如何消除Z3中的bitvector算法

时间:2012-12-27 07:58:02

标签: z3 bitvector

我正在尝试使用z3来消除表达式

not ((not x) add y)

等于

x sub y

由此code

(declare-const x (_ BitVec 32))
(declare-const y (_ BitVec 32))
(assert (= (bvnot (bvadd (bvnot x) y)) (bvsub x y)))
(check-sat)
(simplify (bvnot (bvadd (bvnot x) y)))

我希望得到如下结果:

sat
(bvsub x y) 

然而,结果是:

sat
(bvnot (bvadd (bvnot x) y))

有人会帮助我吗?

1 个答案:

答案 0 :(得分:3)

我们可以使用以下脚本证明(bvnot (bvadd (bvnot x) y))等同于(bvsub x y)

(declare-const x (_ BitVec 32))
(declare-const y (_ BitVec 32))
(assert (not (= (bvnot (bvadd (bvnot x) y)) (bvsub x y))))
(check-sat)

在此脚本中,我们使用Z3来显示(not (= (bvnot (bvadd (bvnot x) y)) (bvsub x y)))不可满足。也就是说,无法找到xy的值,以使(bvnot (bvadd (bvnot x) y))的值与(bvsub x y)的值不同。

在Z3中,simplify命令只应用重写规则,它忽略了一组断言的表达式。 simplify命令比使用check-sat检查可满足性要快得多。此外,给定两个等效表达式FG,不能保证(simplify F)的结果等于(simplify G)。例如,在Z3 v4.3.1中,simplify命令为(= (bvnot (bvadd (bvnot x) y)(bvsub x y)生成不同的结果,尽管它们是等效的表达式。另一方面,它为(= (bvneg (bvadd (bvneg x) y)(bvsub x y)生成相同的结果。

(simplify (bvnot (bvadd (bvnot x) y)))
(simplify (bvneg (bvadd (bvneg x) y)))
(simplify (bvsub x y))

Here是上述示例的完整脚本。

顺便说一句,如果我们使用Z3 Python interface,这些示例会更具可读性。

x, y = BitVecs('x y', 32)
prove(~(~x + y) == x - y)
print simplify(x - y)
print simplify(~(~x + y))
print simplify(-(-x + y))

最后,Z3有更复杂的简化程序。它们以 Tactics 的形式提供。 PythonSMT 2.0格式的教程提供了更多信息。

另一种可能性是修改Z3简化/重写器。正如您所指出的,not x相当于-x -1。我们可以轻松地将此重写规则not x --> -x - 1添加到Z3重写器。 作为一个例子,in this commit,我添加了一个名为“bvnot2arith”的新选项来启用此规则。 实际实现非常小(5行代码)。