An easier way to generate SMTLib from the solver is to simply print s.sexpr()
:
from z3 import *
s = Solver()
x, y = BitVecs("x y",7)
d = BitVecVal(6, 7)
s.add(x & 6 != 6) #1'th or 2'th bit unset using Integer #....(1)
check = s.check()
print(s.sexpr())
if check == sat:
print(s.model())
This prints:
declare-fun k!0 () (_ BitVec 2))
(declare-fun x () (_ BitVec 7))
(declare-fun k!1 () Bool)
(declare-fun k!2 () Bool)
(assert (distinct (bvand x #b0000110) #b0000110))
(model-del k!0)
(model-add x () (_ BitVec 7) (concat #x0 k!0 #b0))
(model-del k!1)
(model-add k!0 () (_ BitVec 2) (ite k!1 #b11 (bvnot #b11)))
(model-del k!2)
(model-add k!1 () Bool (not k!2))
[x = 0]
Two things to notice here:
s.sexpr()
can be used to print the "internal" form of any solver state at any time.
- You never actually used an integer in the first form of your constraint: Since you were comparing it to a bit-vector, z3 automatically coerced it into a bit vector. In fact, comparing a bit-vector to an integer value would not be valid, i.e., it would be a type-error. You can see this as follows:
s.add(x & 6 != IntVal(6))
And for this, z3 would throw a sort-mismatch error:
z3.z3types.Z3Exception: sort mismatch
In short, SMTLib is a logic with simple-types, and a bit-vector can only be compared to another bit-vector. It just happens that the Python API inserts implicit coercions from literal values that are appearing in your program. While this can be convenient for programming, it can lead to misunderstandings as to if you were comparing it to an integer; which is not allowed in the first place. Hope that clears it up!