1

Given the following code:

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)

I would assume that z3 implicitly existential quantifies a, b and c, in this example. Why aren't the two formulas equal, what is the difference?

n4ph1
  • 11
  • 1

1 Answers1

1

The way you formulated your query doesn't really check whether f1 equals f2. Your query is essentially asking the solver to find a, b, c such that the following fails to hold:

      Exists([a, b, c], And(a + b == c, a < b, c == 1337))
              =          
      And(a + b == c, a < b, c == 1337))

And indeed, you can instantiate the outer a, b, and c such that the right hand-side is false; but the left hand side is an existential which is true; thus failing the equivalence you asked for.

It might be easier to see this with a simpler example; with just one boolean variable. You're essentially asking:

     x == (Exists [x], x)

You see that those xs are actually different, so we can rename the inner one to (say) y; we get:

      x == (Exist [y]. y)

Now, the right-hand-side is clearly true since there is a y that makes (Exist [y]. y) true. So, you are essentially asking the prover to establish that no matter what x you pick, it is true. Which is definitely not the case when you pick x to be false.

Indeed, you can ask Z3 to give you the formula it's trying to prove, and this is what it returns for your original query:

(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)

Which is clearly satisfiable, by the above reasoning.

(See Z3: convert Z3py expression to SMT-LIB2 from Solver object for the code that converts a z3-python query to smt-lib.)

Community
  • 1
  • 1
alias
  • 28,120
  • 2
  • 23
  • 40