为什么z3.check()前面紧跟着z3.push()时会变慢?

为什么z3.check()前面紧跟着z3.push()时会变慢?,z3,z3py,Z3,Z3py,下面的Python代码片段演示了Z3的strage性能行为。如果没有push()调用,z3将在0.1s内检查公式。使用push()(并且没有额外的断言),z3需要0.8秒。即使在交换s.append(f)和s.push()之后,也会出现类似的结果 你知道为什么会出现这种减速吗?如何解决这个问题 我使用的是z3-4.3.2.bb56885147e4-x64-osx-10.9.2。您的示例在第二个实例化中使用了“push”。 这是一个巨大的不同。 Z3的位向量解算器(尚未)适合通过API进行增量使用

下面的Python代码片段演示了Z3的strage性能行为。如果没有
push()
调用,z3将在0.1s内检查公式。使用
push()
(并且没有额外的断言),z3需要0.8秒。即使在交换
s.append(f)
s.push()
之后,也会出现类似的结果

你知道为什么会出现这种减速吗?如何解决这个问题

我使用的是z3-4.3.2.bb56885147e4-x64-osx-10.9.2。

您的示例在第二个实例化中使用了“push”。 这是一个巨大的不同。 Z3的位向量解算器(尚未)适合通过API进行增量使用。 它只适用于备用断言,不与作用域(push/pop)进行互操作。 第一次调用使用位向量SAT解算器。没有“推送/弹出”正在进行。
第二个调用在调用“push”之后。Z3然后确定,为了跟踪作用域依赖关系,它必须使用增量SMT核心,而增量SMT核心不能从更高效的位向量解算器中获益。

谢谢,这是一个很好的重新编程。Z3对第二个实例使用增量解算器。用例中不清楚为什么会出现这种情况,所以它指向了一个可用性缺陷。在内部,Z3使用工厂模式创建解算器。我正在研究这是否是原因所在,还是之前的解算器覆盖状态的副作用。@NikolajBjorner即使代码段在不同的Python进程中执行,行为也是相同的。因此,您是否建议累积Z3外部的断言并使用解算器的非作用域实例?
import time
import z3
f = z3.parse_smt2_file("smt-lib/QF_BV/RWS/Example_1.txt.smt2")
s = z3.Solver()
s.append(f)
t1 = time.time()
s.check()  # 0.10693597793579102 seconds
print(time.time() - t1)

s = z3.Solver()
t1 = time.time()
s.append(f)
s.push()
s.check()  # 0.830916166305542 seconds
print(time.time() - t1)