为什么此代码返回Unsat(使用ForAll& Implies的公式)?

时间:2013-06-25 09:25:50

标签: z3 z3py

给出2个等式c == a + 4t == c + b,如果a == -4,则为t == b。我试图做相反的事情,意思是给出上述2个等式,t == b,我试图找到a 的值。

我有以下代码来执行此操作 ForAll 隐含

from z3 import *

a, b, c, t = BitVecs('a b c t', 32)

g = True
g = And(g, c == (a + 4))
g = And(g, t == (c + b))

s = Solver()
s.add(ForAll([c, t, b], Implies(g, t == b)))

if s.check() == sat:
    print s.model()[a]
else:
    print 'Unsat'

但是,运行上面的代码会返回 Unsat 。我希望这会返回-4(或0xfffffffc),所以很困惑。

知道我哪里错了吗?

谢谢!

1 个答案:

答案 0 :(得分:3)

您编写的公式与您问题的文字说明不符。特别是,您使用的含义并不能确保t == b必须为真,才能使公式满意。

根据您问题的文字说明,如果t == b为真,那么这意味着t == c + b成立的唯一方法是c == 0。自c == 0开始,c == a + 4成立的唯一方法是a == -4,如果需要的话。 tb的分配是任意的。

以下是两种编码方式。在第一种情况下,z3将0分配给tb两者,因为它们是隐式存在量化的。在第二种情况下,我使用了bt上的通用量词来突出显示赋值是任意的。基于刚才所述的讨论(因为c必须为真),任意选择c == 0的公式不能令人满意,所以c不应该被普遍量化。以下说明了这一点(http://rise4fun.com/Z3Py/uGEV):

a, b, c, t = BitVecs('a b c t', 32)

g = True
g = And(g, c == (a + 4))
g = And(g, t == (c + b))
g = And(g, t == b)

s = Solver()
s.add(g)
s.check()
print s.model()
ma = s.model()[a]
s = Solver()
s.add(Not(ma == 0xfffffffc))
print s.check() # unsat, proves ma is -4

solve(g) # alternatively, just solve the equations

# illustrate that the assignments to t and b are arbitrary
s = Solver()
g = True
g = And(g, c == (a + 4))
g = And(g, t == (c + b))
g = ForAll([t, b], Implies(t == b, g))
s.add(g)
s.check()
print s.model()
ma = s.model()[a]

<强>更新 根据以下评论,我希望此示例有助于了解您需要Implies(t == b, g)代替Implies(g, t == b)的原因(使用z3py链接:http://rise4fun.com/Z3Py/pl80I):

p1, p2 = BitVecs('p1 p2', 4)

solve(Implies(p1 == 1, p2 == 2)) # gives p1 = 14, p2 = 13

solve(And(p1 == 0, Implies(p1 == 1, p2 == 2))) # gives p1 = 0, p2 unassigned

solve(And(p1 == 0, p1 == 1)) # no solution to illustrate that p1 can only be 0 or 1 in previous, but would be unsat is trying to assign both

solve(ForAll([p1], Implies(p1 == 1, p2 == 2))) # gives p2 == 2

solve(ForAll([p1], Implies(p2 == 2, p1 == 1))) # gives p2 = 0 and does not ensure p1 == 1 is true since the formula is satisfiable by picking p2 != 2