Reputation: 358
I am trying to use the z3 to eliminate the expression
not ((not x) add y)
which equals to
x sub y
by this 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)))
I want to get the result like:
sat
(bvsub x y)
However, the result is:
sat
(bvnot (bvadd (bvnot x) y))
Would some one help me out?
Upvotes: 3
Views: 755
Reputation: 21475
We can prove that (bvnot (bvadd (bvnot x) y))
is equivalent to (bvsub x y)
using the following script.
(declare-const x (_ BitVec 32))
(declare-const y (_ BitVec 32))
(assert (not (= (bvnot (bvadd (bvnot x) y)) (bvsub x y))))
(check-sat)
In this script, we used Z3 to show that (not (= (bvnot (bvadd (bvnot x) y)) (bvsub x y)))
is unsatisfiable. That is, it is not possible to find values for x
and y
such that the value of (bvnot (bvadd (bvnot x) y))
is different from the value of (bvsub x y)
.
In Z3, the simplify
command just applies rewriting rules, and it ignores the set of asserted expressions. The simplify
command is much faster than checking satisfiability using check-sat
. Moreover, given two equivalent expressions F
and G
, there is not guarantee that the result of (simplify F)
will be equal to (simplify G)
. For example, in Z3 v4.3.1, the simplify command produces different results for (= (bvnot (bvadd (bvnot x) y)
and (bvsub x y)
, although they are equivalent expressions. On the other hand, it produces the same result for (= (bvneg (bvadd (bvneg x) y)
and (bvsub x y)
.
(simplify (bvnot (bvadd (bvnot x) y)))
(simplify (bvneg (bvadd (bvneg x) y)))
(simplify (bvsub x y))
Here is the full script for the examples above.
BTW, these examples are much more readable if we use the 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))
Finally, Z3 has more complex simplification procedures. They are available as Tactics. The tutorials in Python and SMT 2.0 format provide additional information.
Another possibility is to modify the Z3 simplier/rewriter. As you pointed out, not x
is equivalent to -x -1
. We can easily add this rewrite rule: not x --> -x - 1
to the Z3 rewriter.
As an example, in this commit, I added a new option called "bvnot2arith" that enables this rule.
The actual implementation is very small (5 lines of code).
Upvotes: 3