我有一组64位整数,我需要在其上应用一定数量的“对称操作”。对称操作只是一组位置换,存储在int的向量中为{i0,i1,i2,..},其中位[0] - >位[i0],位[1] - >位[i1]等......事实上,我只是使用N个第一位,其中N是在运行时确定的,但原则上可以达到64位。
例如,我正在使用N = 4,输入是整数3或0011,我有4个对称运算存储在向量symmetry_ops的向量中
symmetry_ops[0] = {0,1,2,3};
symmetry_ops[1] = {1,2,3,0};
symmetry_ops[2] = {2,3,0,1};
symmetry_ops[4] = {3,0,1,2};
我想要一个函数,它返回通过将这些操作应用到3获得的4个整数,即0011,0110,1100和1001.这个例子很简单,但实际上,排列可能比移动到左
我写了以下简单(天真?)的代码:
std::vector<unsigned long> apply_symmetries(const std::vector<std::vector<unsigned> > &symmetry_ops, unsigned long state)
{
unsigned N = symmetry_ops[0].size();
std::vector<unsigned long> s_moved(symmetry_ops.size(),0);
for (unsigned i = 0; i < N; i++) {
unsigned long s_i = (state&(1UL<<i))>>i; // extracts bit i in state
for (unsigned op = 0; op != symmetry_ops.size(); op++)
s_moved[op] = s_moved[op]|(s_i<<symmetry_ops[op][i]);
}
return s_moved;
}
对整数“state”执行所有对称操作。我只是在i循环中一个接一个地读取,首先将其存储在s_i中,然后为每个对称操作移动它。
正确地知道,这是我的程序中最耗时的部分之一,因为典型的大小是~100-200对称操作适用于~10 ^ 10整数,N大约40.代码正常工作,但我我想知道这个功能是否可以优化?
提前致谢。
答案 0 :(得分:0)
首先,如果您在代码中添加注释来解释什么是有用的,那将会有所帮助。同时选择描述性变量名,不要为变量名选择's_i'或's_moved',这会使代码不可读。 'symmetry_ops'对于一个名字来说是一个很好的选择,所以'state'也是如此,其他的并不是那么多。
无论如何,为了加速你的代码:如果你有一个对称操作,它将位i发送到位x,而下一个对称操作将位x发送到位y,那么组合这两个就像将位i发送到位y in一个操作。
首先,单独循环操作。
对于每个对称op,将其应用于前一个,然后通过循环使用新的那个作为前一个。然后你可以为整个事物构建一个单一的对称操作。我正在编写伪代码以明确这一点。
identity_op = {0, 1, 2, 3, 4, 5, 6, 7} //vector of int, maps each bit to same bit
previous_op = identity_op
for each op { //op is vector of ints, op[i] maps bit i to op[i]
//combine op with prev_op to make a new prev_op
for each i in op {
prev_op[i] = op[prev_op[i]] //bit i is mapped by prev_op and then mapped again by op, giving new value for prev_op
}
}
combined_op = previous_op
apply combined_op to the bits, this is only place you need to to bit shifting
您的C ++代码看起来很好,只需重写即可使用这种新算法。