给出以下代码:
from z3 import *
a,b,c = BitVecs('a b c', 32)
f1 = Exists([a, b, c], And(a + b == c, a < b, c == 1337))
f2 = And(a + b == c, a < b, c == 1337)
prove(f1 == f2)
在本例中,我假设z3隐式存在量化a
,b
和c
。为什么两个公式不相等,有什么区别?
答案 0 :(得分:1)
您制定查询的方式并未真正检查f1
是否等于f2
。您的查询实际上是要求求解程序找到a, b, c
,以便以下内容无法保留:
Exists([a, b, c], And(a + b == c, a < b, c == 1337))
=
And(a + b == c, a < b, c == 1337))
实际上,您可以实例化外部a
,b
和c
,以便右侧是假的;但左手边是一个真实的存在主义;因此,你所要求的等同性失败了。
通过一个更简单的例子可能更容易看到这一点;只有一个布尔变量。你基本上是在问:
x == (Exists [x], x)
您看到那些x
实际上是不同的,因此我们可以将内部重命名为(例如)y
;我们得到:
x == (Exist [y]. y)
现在,右侧显然是正确的,因为y
使(Exist [y]. y)
成立。所以,你基本上要求证明者确定无论你选择什么x
,都是如此。当你选择x
为假时,绝对不是这种情况。
事实上,您可以要求Z3为您提供它试图证明的公式,这就是它为您的原始查询返回的内容:
(set-info :status unknown)
(declare-fun c () (_ BitVec 32))
(declare-fun b () (_ BitVec 32))
(declare-fun a () (_ BitVec 32))
(assert
(let (($x24 (exists ((a (_ BitVec 32))
(b (_ BitVec 32))
(c (_ BitVec 32)) )
(and (= (bvadd a b) c) (bvslt a b) (= c (_ bv1337 32))))))
(let (($x57 (= $x24 (and (= (bvadd a b) c) (bvslt a b) (= c (_ bv1337 32))))))
(and $x57))))
(check-sat)
通过上述推理,这显然是可以满足的。
(有关将z3-python查询转换为smt-lib的代码,请参阅Z3: convert Z3py expression to SMT-LIB2 from Solver object。)