基于整数向量执行位排列的有效方法?

Efficient way to perform bit permutations based on a vector of integers?

本文关键字:排列 有效 方法 执行 向量 于整数 整数      更新时间:2023-10-16

我有一组 64 位整数,我需要在其上应用一定数量的"对称操作"。对称运算只是一系列位排列,存储在 int 向量中为 {i0,i1,i2,..},其中 bit[0]->bit[i0]、bit[1]->bit[i1],等等......事实上,我只是使用 N 个前位,其中 N 是在运行时确定的,但原则上可以达到 64。

例如,我正在使用 N=4,输入是整数 3 或 0011,并且我在向量 symmetry_ops 的向量中存储了 4 个对称运算

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;
}

它对整数"状态"执行所有对称操作。我只是在 i 的循环中一个接一个地进行,首先将其存储在 s_i 中,然后为每个对称操作移动它。

知道,这是我的程序中最耗时的部分之一,因为典型的大小是 ~100-200 个对称操作,应用于 ~10^10 个整数,N 约为 40。代码正常工作,但我想知道是否可以优化此功能?

提前谢谢。

首先,如果您在代码中添加注释来解释什么是什么,这将有所帮助。 还要选择描述性变量名称,不要选择"s_i"或"s_moved"作为变量名称,它会使代码不可读。 "symmetry_ops"是一个不错的名称选择,"州"也是如此,其他的则不然。

无论如何,为了加快代码速度:如果你有一个对称运算将位 i 发送到位 x,而下一个对称运算将位 x 发送到位 y,那么将两者结合起来就像在单个操作中将位 i 发送到位 y 相同。

因此,首先单独循环操作。

对于每个对称操作,将其应用于前一个,然后通过循环将该新操作用作前一个。 然后,您可以为整个事物构建一个对称操作。 我正在编写伪代码来明确这一点。

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++代码看起来不错,只需重写即可使用此新算法。