为什么Z3在很小的搜索空间中速度慢?

里奥·阿德伯格

我正在尝试制作一个Z3程序(在Python中),该程序会生成执行某些任务(例如,添加两个n位数字)的布尔电路,但是性能太差了,以至于蛮力搜索整个解决方案空间会快一点 这是我第一次使用Z3,所以我可能会做一些会影响性能的事情,但是我的代码似乎还不错。

以下是从我的代码中复制过来的

from z3 import *

BITLEN = 1 # Number of bits in input
STEPS = 1 # How many steps to take (e.g. time)
WIDTH = 2 # How many operations/values can be stored in parallel, has to be at least BITLEN * #inputs

# Input variables
x = BitVec('x', BITLEN)
y = BitVec('y', BITLEN)

# Define operations used
op_list = [BitVecRef.__and__, BitVecRef.__or__, BitVecRef.__xor__, BitVecRef.__xor__]
unary_op_list = [BitVecRef.__invert__]
for uop in unary_op_list:
    op_list.append(lambda x, y : uop(x))

# Chooses a function to use by setting all others to 0
def chooseFunc(i, x, y):
    res = 0
    for ind, op in enumerate(op_list):
        res = res + (ind == i) * op(x, y)
    return res

s = Solver()
steps = []

# First step is just the bits of the input padded with constants
firststep = Array("firststep", IntSort(), BitVecSort(1))
for i in range(BITLEN):
    firststep = Store(firststep, i * 2, Extract(i, i, x))
    firststep = Store(firststep, i * 2 + 1, Extract(i, i, y))
for i in range(BITLEN * 2, WIDTH):
    firststep = Store(firststep, i, BitVec("const_0_%d" % i, 1))
steps.append(firststep)

# Generate remaining steps
for i in range(1, STEPS + 1):
    this_step = Array("step_%d" % i, IntSort(), BitVecSort(1))
    last_step = steps[-1]

    for j in range(WIDTH):
        func_ind = Int("func_%d_%d" % (i,j))
        s.add(func_ind >= 0, func_ind < len(op_list))

        x_ind = Int("x_%d_%d" % (i,j))
        s.add(x_ind >= 0, x_ind < WIDTH)

        y_ind = Int("y_%d_%d" % (i,j))
        s.add(y_ind >= 0, y_ind < WIDTH)

        node = chooseFunc(func_ind, Select(last_step, x_ind), Select(last_step, y_ind))
        this_step = Store(this_step, j, node)

    steps.append(this_step)

# Set the result to the first BITLEN bits of the last step
if BITLEN == 1:
    result = Select(steps[-1], 0)
else:
    result = Concat(*[Select(steps[-1], i) for i in range(BITLEN)])

# Set goal
goal = x | y
s.add(ForAll([x, y], goal == result))

print(s)
print(s.check())
print(s.model())

该代码基本上将输入布置为单独的位,然后在每个“步骤”中,五个布尔函数之一都可以对上一步中的值进行操作,其中最后一步表示最终结果。

在此示例中,我生成了一个电路来计算两个1位输入的布尔“或”,并且该电路中有一个“或”功能,因此解决方案很简单。

我的解决方案空间只有5 * 5 * 2 * 2 * 2 * 2 = 400:

  • 5个可能的功能(两个功能节点)
  • 每个功能有2个输入,每个输入都有两个可能的值

这段代码需要花费几秒钟的时间来运行并提供正确的答案,但是我认为它应该立即运行,因为只有400种可能的解决方案,其中有很多是有效的。如果我将输入增加到两位长,则解决方案空间的大小为(5 ^ 4)*(4 ^ 8)= 40,960,000,并且永远不会在我的计算机上完成,尽管我觉得Z3应该可以轻松实现。

我也有效地尝试了相同的代码,但用Arrays / Store / Select代替了Python列表,并使用与selectFunc()中相同的技巧“选择”了变量。代码在这里,它的运行时间与原始代码大致相同,因此不会加速。

我在做会大大减慢求解器速度的事情吗?谢谢!

别名

您的副本__xor__有一个op_list但这并不是真正的主要问题。随着位大小的增加,速度的降低是不可避免的,但乍一看,您可以(并且应该)避免在此处将整数推理与布尔值混合在一起。我将为您编写chooseFunc以下代码

def chooseFunc(i, x, y):
    res = False;
    for ind, op in enumerate(op_list):
        res = If(ind == i, op (x, y), res)
    return res

看看是否以任何有意义的方式改善了运行时间。如果没有,那么下一步是尽可能多地删除数组。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么启动速度慢?

为什么Python枚举速度慢?

为什么LiveData速度慢

为什么Matlab Coder速度慢?

为什么我的查询速度慢?

为什么我的Ubuntu速度慢

为什么我的电脑速度慢?

为什么这个简单的Z3证明这么慢?

为什么Android上的okhttp3比台式计算机执行请求的速度慢?

为什么我的无线速度慢?

为什么大数组Java速度慢

为什么我的LDAP登录速度慢?

为什么数组元素的平均打印速度比C ++中单个对象的打印速度慢?

Python | 为什么访问实例属性的速度比本地速度慢?

为什么在 PgAdmin 中 Java 应用程序查询速度慢但速度快?

为什么我的Python脚本运行速度比HeapSort实现上的速度慢?

为什么内联Math.max给出的速度慢200倍以上?

为什么对小型数据多次调用numpy.linalg.norm速度慢?

为什么有些float <整数比较的速度慢四倍?

基于其他查询结果的SQL查询-为什么速度慢?

为什么numpy.power比内联速度慢60倍?

为什么使用Hibernate进行查询缓存会使查询速度慢十倍?

与C相比,为什么Go中写入字节的速度慢

为什么Electron.js应用对用户输入的响应速度慢?

为什么在程序上绘制圆比从纹理读取速度慢?

查询执行速度慢:执行时间长=>非常奇怪为什么?

为什么Exiftool速度慢,从stdin中读取内存占用;快速,小磁盘读取

为什么Windows 8.1笔记本电脑上的Nmap速度慢?

Windows 10存储空间速度慢