在z3中有效地找到BitVec权重(也就是访问位向量的位)

时间:2013-02-06 14:06:49

标签: python z3

我目前正在使用python api for z3来计算bitvectors的权重。

在搜索python API以获得更直接的方法之后,我正在以下列方式为bitvector st1实现权重函数:

Sum([( (st1 & (2**(i)))/(2**(i)) ) for i in range(bits)])

我的问题相对简单,是否有更容易/更有效的方式?

我遇到的问题包含1500多个这些重量限制,并希望确保我尽可能高效地做事。

编辑:我将添加以下说明,我试图计算的是一个名字(它是汉明重量),我知道在命令式语言中实现功能的超高效方法,但< strong>最终我正在寻找的是,如果有任何基础方法可以访问z3位向量的各个位。

2 个答案:

答案 0 :(得分:1)

我在你在问题中发布的例子中玩了一点:

我认为不满意的实例很难解决,因为问题似乎有许多对称性。 如果是这种情况,我们可以通过包含“对称破坏约束”来提高性能。 对于这种问题,Z3不能自动打破对称性。

这是一个次要的编码改进。表达式((st1 & (2**(i)))/(2**(i))实质上是提取第i位。我们可以使用Extract(i, i, st1)来提取第i位。结果是一个大小为1的位向量。然后,我们必须“扩展”它以避免溢出。问题中的位向量最多为28位。因此,5位足以避免溢出。因此,我们可以使用ZeroExt(4, Extract(i, i, st1))。也就是说,我们替换

Sum([( (st1 & (2**(i)))/(2**(i)) ) for i in range(bits)])

Sum([ ZeroExt(4, Extract(i,i,st1)) for i in range(bits) ])

我得到了适度的2倍加速。所以,Z3仍然无法解决6位不饱和实例:(

答案 1 :(得分:-1)

你应该尝试使用递归方法,也许你可以看看这个Dynamic programming