Performance 为什么z3的增量性能如此糟糕?

Performance 为什么z3的增量性能如此糟糕?,performance,z3,smt,z3py,sat,Performance,Z3,Smt,Z3py,Sat,我有以下python代码: from z3 import * import time s = Solver() p = Array("p", BitVecSort(11), BitVecSort(8)) for m in range(200): start_time = time.time() for i in range(20): s.add(Or([p[m*20 + i] % 72 == BitVecVal(x, 8) for x in [k * 6

我有以下python代码:

from z3 import *
import time

s = Solver()
p = Array("p", BitVecSort(11), BitVecSort(8))


for m in range(200):
    start_time = time.time()

    for i in range(20):
        s.add(Or([p[m*20 + i] % 72 == BitVecVal(x, 8) for x in [k * 6 for k in [0,2,4,5,7,9,11]]]))

    s.check()
    model = s.model()
    pre_push = time.time()
    s.push()
    push_time = time.time() - pre_push

    if m % 5 == 0:
        print((m, (time.time() - start_time - push_time)))
从代码中可以看出,在每个周期m中,我对数组的值m*20到m*20+19施加约束。因此,不存在任何附加约束,该约束涉及来自先前m估值的变量。然而,即使不考虑执行“s.push”所需的时间,z3在大多数回合中仍然会大大降低速度:

Output:
(0, 0.23836421966552734)
(5, 1.3699274063110352)
(10, 4.132023096084595)
(15, 3.884359836578369)
(20, 4.81259298324585)
(25, 7.442332029342651)
(30, 12.25448989868164)
(35, 15.96577787399292)
(40, 16.90854024887085)
(45, 22.725850105285645)
(50, 29.525628328323364)
(55, 23.494187355041504)
(60, 31.887953996658325)

我的直觉是,推送将保存以前模型的值,并且每个模型都有相同数量的约束添加到以前的无约束变量中,因此除了推送所需的时间外,每个循环的时间应该相对相似。为什么我会变得如此缓慢?

即使你添加了你所说的“不相关”约束,解算器仍然需要建立这种独立性。而且这个过程在约束的数量上很容易是二次的。话虽如此,也许这指向了一个可能的优化,解算器可以投入其中,以更快地检测这些情况。在z3github站点上报告这一点可能是一个好主意,这样开发者就可以发表意见。请把你发现的情况报告给我!我在那里没有看到任何
s.pop()
,因此约束的数量会增加,求解时间也会增加,这是正常的。另外,
push()
仅创建回溯点,不保存任何模型值。您是否尝试过不使用
s.push()
?考虑到您向我们展示的代码片段,这似乎没有必要。也值得记住:并非所有Z3的理论子解算器都可以在增量模式下使用,因此Z3可能不得不求助于性能较差(或不太完整)的子解算器。是的,在这种情况下,push()没有帮助。我假设通过保存当前状态,push()将保存令人满意的变量-这不是真的吗?@lightning不,push()不是为了这个。我建议略读一遍,即使您添加了您所说的“不相关”约束,解算器仍然需要建立这种独立性。而且这个过程在约束的数量上很容易是二次的。话虽如此,也许这指向了一个可能的优化,解算器可以投入其中,以更快地检测这些情况。在z3github站点上报告这一点可能是一个好主意,这样开发者就可以发表意见。请把你发现的情况报告给我!我在那里没有看到任何
s.pop()
,因此约束的数量会增加,求解时间也会增加,这是正常的。另外,
push()
仅创建回溯点,不保存任何模型值。您是否尝试过不使用
s.push()
?考虑到您向我们展示的代码片段,这似乎没有必要。也值得记住:并非所有Z3的理论子解算器都可以在增量模式下使用,因此Z3可能不得不求助于性能较差(或不太完整)的子解算器。是的,在这种情况下,push()没有帮助。我假设通过保存当前状态,push()将保存令人满意的变量-这不是真的吗?@lightning不,push()不是为了这个。我建议你略读一下