Incorrect result with Z3 SMT and Python - z3

I'm trying to replicate the script given by another user from this StackOverflow answer here https://stackoverflow.com/a/14551792
I have what I believe to be most of the pieces to get this to work with the python bindings, however I don't get the correct answer. Here is the python script:
from z3 import *
mask = BitVec('mask', 64)
multiplicand = BitVec('multiplicand', 64)
x = BitVec('x', 64)
y = BitVec('y', 64)
s = SolverFor("BV")
F = [
ForAll(x, (y == (mask & x) * multiplicand)),
And(Extract(63, 63, x) == Extract(63, 63, y),
Extract(55, 55, x) == Extract(62, 62, y),
Extract(47, 47, x) == Extract(61, 61, y),
Extract(39, 39, x) == Extract(60, 60, y),
Extract(31, 31, x) == Extract(59, 59, y),
Extract(23, 23, x) == Extract(58, 58, y),
Extract(15, 15, x) == Extract(57, 57, y),
Extract(7, 7, x) == Extract(56, 56, y))
]
print F[0].sexpr()
print F[1].sexpr()
s.add(F)
if s.check() == sat:
print "ok"
print s.model()
My results give me the following:
(forall ((x (_ BitVec 64))) (= y (bvmul (bvand mask x) multiplicand)))
(and (= ((_ extract 63 63) x) ((_ extract 63 63) y))
(= ((_ extract 55 55) x) ((_ extract 62 62) y))
(= ((_ extract 47 47) x) ((_ extract 61 61) y))
(= ((_ extract 39 39) x) ((_ extract 60 60) y))
(= ((_ extract 31 31) x) ((_ extract 59 59) y))
(= ((_ extract 23 23) x) ((_ extract 58 58) y))
(= ((_ extract 15 15) x) ((_ extract 57 57) y))
(= ((_ extract 7 7) x) ((_ extract 56 56) y)))
[mask = 0, multiplicand = 0, y = 0, x = 0]
This is obviously incorrect. The main difference I'm seeing is that my produced SMT code appears to do an assignment to 'y' whereas in the other StackExchange answer he's got a let-expression. Can somebody point me in the right direction here?

Here's a trick you might enjoy by parsing the SMT2 string via the Python API with parse_smt2_string ( http://research.microsoft.com/en-us/um/redmond/projects/z3/z3.html#-parse_smt2_string ):
from z3 import *
s = SolverFor("BV")
#s.set(':pp.bv_literals', True) # gives error for some reason
mask = BitVec('mask', 64)
multiplicand = BitVec('multiplicand', 64)
x = BitVec('x', 64)
y = BitVec('y', 64)
F = parse_smt2_string(' \
(set-option :pp.bv_literals true) \
(declare-const mask (BV64)) \
(declare-const multiplicand (BV64)) \
(assert (forall ((x (BV64))) \
(let ((y (bvmul (bvand mask x) multiplicand))) \
(and \
(= ((_ extract 63 63) x) ((_ extract 63 63) y)) \
(= ((_ extract 55 55) x) ((_ extract 62 62) y)) \
(= ((_ extract 47 47) x) ((_ extract 61 61) y)) \
(= ((_ extract 39 39) x) ((_ extract 60 60) y)) \
(= ((_ extract 31 31) x) ((_ extract 59 59) y)) \
(= ((_ extract 23 23) x) ((_ extract 58 58) y)) \
(= ((_ extract 15 15) x) ((_ extract 57 57) y)) \
(= ((_ extract 7 7) x) ((_ extract 56 56) y)) \
) \
) \
))', sorts={ 'BV64' : BitVecSort(64) })
print F
s.add(F)
print s.to_smt2()
if s.check() == sat:
print "ok"
print s.model()
m = s.model()
print hex(m[mask].as_long())
print hex(m[multiplicand].as_long())
Output is:
[mask = 9259542123273814144, multiplicand = 567382630219905]
0x8080808080808080L
0x2040810204081L
There was a problem of your encoding of the let expression. You need the universal quantifier over all x for the main assertion, whereas you were trying to use it to define the let expression. The following works for basically your original encoding, just creating a pointer to the appropriate expression y and copying it:
from z3 import *
mask = BitVec('mask', 64)
multiplicand = BitVec('multiplicand', 64)
x = BitVec('x', 64)
y = BitVec('y', 64)
y = ((mask & x) * multiplicand)
s = SolverFor("BV")
F = [
ForAll(x,
And(Extract(63, 63, x) == Extract(63, 63, y),
Extract(55, 55, x) == Extract(62, 62, y),
Extract(47, 47, x) == Extract(61, 61, y),
Extract(39, 39, x) == Extract(60, 60, y),
Extract(31, 31, x) == Extract(59, 59, y),
Extract(23, 23, x) == Extract(58, 58, y),
Extract(15, 15, x) == Extract(57, 57, y),
Extract(7, 7, x) == Extract(56, 56, y)))
]
print F[0].sexpr()
s.add(F)
if s.check() == sat:
print "ok"
print s.model()
m = s.model()
print hex(m[mask].as_long())
print hex(m[multiplicand].as_long())
Output is:
[mask = 9259542123273814144, multiplicand = 567382630219905]
0x8080808080808080L
0x2040810204081L

The question is really about the Z3 Python bindings. But it's an interesting one. Without starting any language wars, I just wanted to put here the Haskell solution to the same for reference purposes, again using Z3 as the underlying solver:
import Data.SBV
main :: IO ()
main = print =<< satWith z3{printBase=16} find
where find = do mask <- exists "mask"
mult <- exists "mult"
inp <- forall "inp"
let res = (mask .&. inp) * (mult :: SWord64)
x `grab` is = map (sbvTestBit x) is
solve [inp `grab` [7, 15 .. 63] .== res `grab` [56 .. 63]]
We get:
*Main> main
Satisfiable. Model:
mask = 0x8080808080808080 :: Word64
mult = 0x0002040810204081 :: Word64

Related

array element in z3 counterexample

counterexample output of an aaary element of z3 tool
I try the following python code, and get an counterexample
from z3 import Solver, parse_smt2_string
s = Solver()
#str1="(declare-const x Int) (declare-const y Int) (declare-const z Int) (declare-const a1 (Array Int Int)) (declare-const a2 (Array Int Int)) (declare-const a3 (Array Int Int)) (assert (= (select a1 x) x)) (assert (= (store a1 x y) a1))"
str1="(define-sort A () (Array Int Int Int)) (define-fun bag-union ((x A) (y A)) A ((_ map (+ (Int Int) Int)) x y)) (declare-const s1 A) (declare-const s2 A) (declare-const s3 A) (assert (= s3 (bag-union s1 s2))) (assert (= (select s1 0 0) 5)) (assert (= (select s2 0 0) 3)) (assert (= (select s2 1 2) 4))"
s.add(parse_smt2_string(str1))
s.check()
m = s.model()
for d in m:
print(d,m[d])
if str(s.check())=="sat":
print(s.model())
m = s.model()
for d in m:
print(d,m[d])
(s2, [(1, 2) -> 4, (0, 0) -> 3, else -> 7719])
(s3, [(1, 2) -> 8859, (0, 0) -> 8, else -> 8955])
(s1, [(1, 2) -> 8855, (0, 0) -> 5, else -> 1236])
(k!1, [(1, 2) -> 4, (0, 0) -> 3, else -> 7719])
(k!2, [(1, 2) -> 8859, (0, 0) -> 8, else -> 8955])
(k!0, [(1, 2) -> 8855, (0, 0) -> 5, else -> 1236])
....
The lines such as (k!1, [(1, 2) -> 4, (0, 0) -> 3, else -> 7719]) confuse me?
They seem duplicate lines (s2, [(1, 2) -> 4, (0, 0) -> 3, else -> 7719.
Can I add an option not to show these lines?
You're mixing SMTLib and Python inputs into one; there's really no good reason to do this. Either program in Python, or in SMTLib. When you use z3 this way, you have no access to the variables you have defined. If you directly program in z3py, then you can simply query the values of the variables you have defined with ease. Other than that, your best bet is to simply check if the name is of the form k!n and skip it inside your for loop.
Also note that what will be printed in the output for these "auxiliary" model variables is quite z3 version dependent. When I run your program with the latest version of z3 from github sources, it prints:
(s2, Store(K(Int, 4), 0, 0, 3))
(s1, K(Int, 5))
(s3, Store(K(Int, 9), 0, 0, 8))
[s2 = Store(K(Int, 4), 0, 0, 3),
s1 = K(Int, 5),
s3 = Store(K(Int, 9), 0, 0, 8)]
(s2, Store(K(Int, 4), 0, 0, 3))
(s1, K(Int, 5))
(s3, Store(K(Int, 9), 0, 0, 8))
which has no mention of k!n variables. Mixing the two input languages this way is merely asking for a lot of confusion.

An efficient way to nest store operations

In Most efficient way to represent memory buffers in Z3 the question on how make nested store operations more efficient is answered that one can replace the (nested) store operations with selects as in: (assert (= (select A i1) v1)). However, I need the store operation because previous constraints have to be replaced with the new constraints.
For example: the following constraints simulate the following assembly program:
mov qword ptr [rax], rbx
mov rcx, qword ptr [rax]
I like to proof that rbx and rcx are equal, I assert (= RBX!2 RCX!2) and expect that the model can be satisfied. This works perfectly. I assert (not (= RBX!2 RCX!2)) and expect that the model cannot be satisfied. When I feed the following constraints to Z3 (eg here) it gives an almost instant answer: UNSAT. However, if I proof the same problem in a C# program (see below) it cannot deduce UNSAT (in reasonable time).
Question: What can I try to make the C# program as quick as the SMT2.0 program?
(declare-fun RAX!0 () (_ BitVec 64))
(declare-fun RAX!1 () (_ BitVec 64))
(declare-fun RAX!2 () (_ BitVec 64))
(declare-fun RBX!0 () (_ BitVec 64))
(declare-fun RBX!1 () (_ BitVec 64))
(declare-fun RBX!2 () (_ BitVec 64))
(declare-fun RCX!0 () (_ BitVec 64))
(declare-fun RCX!1 () (_ BitVec 64))
(declare-fun RCX!2 () (_ BitVec 64))
(declare-fun MEM!0 () (Array (_ BitVec 64) (_ BitVec 8)))
(declare-fun MEM!1 () (Array (_ BitVec 64) (_ BitVec 8)))
(declare-fun MEM!2 () (Array (_ BitVec 64) (_ BitVec 8)))
(assert (= RAX!1 RAX!0))
(assert (= RBX!1 RBX!0))
(assert (= RCX!1 RCX!0))
(assert (let ((a!1 (store (store (store MEM!0 RAX!0 ((_ extract 7 0) RBX!0))
(bvadd #x0000000000000001 RAX!0)
((_ extract 15 8) RBX!0))
(bvadd #x0000000000000002 RAX!0)
((_ extract 23 16) RBX!0))))
(let ((a!2 (store (store (store a!1
(bvadd #x0000000000000003 RAX!0)
((_ extract 31 24) RBX!0))
(bvadd #x0000000000000004 RAX!0)
((_ extract 39 32) RBX!0))
(bvadd #x0000000000000005 RAX!0)
((_ extract 47 40) RBX!0))))
(= MEM!1
(store (store a!2
(bvadd #x0000000000000006 RAX!0)
((_ extract 55 48) RBX!0))
(bvadd #x0000000000000007 RAX!0)
((_ extract 63 56) RBX!0))))))
(assert (= RAX!2 RAX!1))
(assert (= RBX!2 RBX!1))
(assert (= RCX!2
(concat (select MEM!1 (bvadd #x0000000000000007 RAX!1))
(select MEM!1 (bvadd #x0000000000000006 RAX!1))
(select MEM!1 (bvadd #x0000000000000005 RAX!1))
(select MEM!1 (bvadd #x0000000000000004 RAX!1))
(select MEM!1 (bvadd #x0000000000000003 RAX!1))
(select MEM!1 (bvadd #x0000000000000002 RAX!1))
(select MEM!1 (bvadd #x0000000000000001 RAX!1))
(select MEM!1 RAX!1))))
(assert (= MEM!2 MEM!1))
(assert (not (= RBX!2 RCX!2)))
C# code:
Dictionary<string, string> settings = new Dictionary<string, string>
{
{ "unsat-core", "false" }, // enable generation of unsat cores
{ "model", "false" }, // enable model generation
{ "proof", "false" }, // enable proof generation
{ "timeout", "60000" } // 60000=1min
};
Context ctx = new Context(settings);
Solver solver = ctx.MkSolver(ctx.MkTactic("qfbv"));
BitVecExpr rax0 = ctx.MkBVConst("RAX!0", 64);
BitVecExpr rax1 = ctx.MkBVConst("RAX!1", 64);
BitVecExpr rax2 = ctx.MkBVConst("RAX!2", 64);
BitVecExpr rbx0 = ctx.MkBVConst("RBX!0", 64);
BitVecExpr rbx1 = ctx.MkBVConst("RBX!1", 64);
BitVecExpr rbx2 = ctx.MkBVConst("RBX!2", 64);
BitVecExpr rcx0 = ctx.MkBVConst("RCX!0", 64);
BitVecExpr rcx1 = ctx.MkBVConst("RCX!1", 64);
BitVecExpr rcx2 = ctx.MkBVConst("RCX!2", 64);
ArrayExpr mem0 = ctx.MkArrayConst("MEM!0", ctx.MkBitVecSort(64), ctx.MkBitVecSort(8));
ArrayExpr mem1 = ctx.MkArrayConst("MEM!1", ctx.MkBitVecSort(64), ctx.MkBitVecSort(8));
ArrayExpr mem2 = ctx.MkArrayConst("MEM!2", ctx.MkBitVecSort(64), ctx.MkBitVecSort(8));
solver.Assert(ctx.MkEq(rax1, rax0));
solver.Assert(ctx.MkEq(rbx1, rbx0));
solver.Assert(ctx.MkEq(rcx1, rcx0));
ArrayExpr memX0 = ctx.MkStore(mem0, ctx.MkBVAdd(ctx.MkBV(0, 64), rax0), ctx.MkExtract((1 * 8) - 1, 0 * 8, rbx0));
ArrayExpr memX1 = ctx.MkStore(memX0, ctx.MkBVAdd(ctx.MkBV(1, 64), rax0), ctx.MkExtract((2 * 8) - 1, 1 * 8, rbx0));
ArrayExpr memX2 = ctx.MkStore(memX1, ctx.MkBVAdd(ctx.MkBV(2, 64), rax0), ctx.MkExtract((3 * 8) - 1, 2 * 8, rbx0));
ArrayExpr memX3 = ctx.MkStore(memX2, ctx.MkBVAdd(ctx.MkBV(3, 64), rax0), ctx.MkExtract((4 * 8) - 1, 3 * 8, rbx0));
ArrayExpr memX4 = ctx.MkStore(memX3, ctx.MkBVAdd(ctx.MkBV(4, 64), rax0), ctx.MkExtract((5 * 8) - 1, 4 * 8, rbx0));
ArrayExpr memX5 = ctx.MkStore(memX4, ctx.MkBVAdd(ctx.MkBV(5, 64), rax0), ctx.MkExtract((6 * 8) - 1, 5 * 8, rbx0));
ArrayExpr memX6 = ctx.MkStore(memX5, ctx.MkBVAdd(ctx.MkBV(6, 64), rax0), ctx.MkExtract((7 * 8) - 1, 6 * 8, rbx0));
memX7 = ctx.MkStore(memX6, ctx.MkBVAdd(ctx.MkBV(7, 64), rax0), ctx.MkExtract((8 * 8) - 1, 7 * 8, rbx0));
solver.Assert(ctx.MkEq(mem1, memX7).Simplify() as BoolExpr);
solver.Assert(ctx.MkEq(rax2, rax1));
solver.Assert(ctx.MkEq(rbx2, rbx1));
BitVecExpr y0 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(0, 64), rax1)) as BitVecExpr;
BitVecExpr y1 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(1, 64), rax1)) as BitVecExpr;
BitVecExpr y2 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(2, 64), rax1)) as BitVecExpr;
BitVecExpr y3 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(3, 64), rax1)) as BitVecExpr;
BitVecExpr y4 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(4, 64), rax1)) as BitVecExpr;
BitVecExpr y5 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(5, 64), rax1)) as BitVecExpr;
BitVecExpr y6 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(6, 64), rax1)) as BitVecExpr;
BitVecExpr y7 = ctx.MkSelect(mem1, ctx.MkBVAdd(ctx.MkBV(7, 64), rax1)) as BitVecExpr;
BitVecExpr y = ctx.MkConcat(y7, ctx.MkConcat(y6, ctx.MkConcat(y5, ctx.MkConcat(y4, ctx.MkConcat(y3, ctx.MkConcat(y2, ctx.MkConcat(y1, y0)))))));
solver.Assert(ctx.MkEq(rcx2, y).Simplify() as BoolExpr);
solver.Assert(ctx.MkEq(mem2, mem1));
Status status_Neg = solver.Check(ctx.MkNot(ctx.MkEq(rbx2, rcx2)));
Console.WriteLine("Status Neg = "+status_Neg); // Go on holiday...
I don't have a way to run the C# program to play with it, unfortunately. But I noticed that you had calls to Simplify:
solver.Assert(ctx.MkEq(mem1, memX7).Simplify() as BoolExpr);
I'm curious why you needed that call? Perhaps that's the culprit?
The other thing to try would be to use uninterpreted functions for representing memory, instead of Arrays. UF's are typically much easier to deal with, and they provide roughly the same abstraction in my personal experience.
It might be a good idea to look at what the C# interface generated as SMT-Lib, to see if the translation is significantly different than what you thought it would be. I guess you could do that using the following function: https://github.com/Z3Prover/z3/blob/master/src/api/dotnet/AST.cs#L195

Getting the domain of an Int with z3

Is there any way of get the specific domain of an Integer variable with z3 (assuming the variable belong to a finite domain)?
I have the following set of constraints:
1 <= X <= 5
2 <= Y <= 8
X + Y == T
and I would like to obtain:
3 <= T <= 13
Or even a simpler case:
1 <= X <= 10
5 <= X <= 15
I want to get:
5 <= X <= 10
This seems to be pretty trivial, but I didn't find a way to obtain such an answer with z3.
You can use Z3's optimization routines to solve these sorts of constraints. Your first problem can be coded as:
(declare-const X Int)
(declare-const Y Int)
(declare-const T Int)
(assert (<= 1 X 5))
(assert (<= 2 Y 8))
(assert (= (+ X Y) T))
(push)
(minimize T)
(check-sat)
(pop)
(maximize T)
(check-sat)
To which z3 responds:
sat
(objectives
(T 3)
)
sat
(objectives
(T 13)
)
Which, if you squint right, is saying 3 <= T <= 13; as you were trying to find out.
You can also use the Python interface to do the same. Your second example can be coded in z3py as follows:
from z3 import *
X = Int('X')
s = Optimize()
s.add(1 <= X); s.add(X <= 10)
s.add(5 <= X); s.add(X <= 15)
s.push()
s.minimize(X)
s.check()
print s.model()
s.pop()
s.maximize(X)
s.check()
print s.model()
which produces:
[X = 5]
[X = 10]
indicating 5 <= X <= 10.
Getting min/max with one call
If you want to avoid two calls to the solver, then you can use the box parameter to optimization, which optimizes the objectives independently:
(declare-const X Int)
(declare-const Y Int)
(declare-const T Int)
(assert (<= 1 X 5))
(assert (<= 2 Y 8))
(assert (= (+ X Y) T))
(minimize T)
(maximize T)
(set-option:opt.priority box)
(check-sat)
Now, z3 responds:
sat
(objectives
(T 3)
(T 13)
)
which contains the results in the order given, i.e, 3 for minimize and 13 for maximize.

Z3 to show that if a^3=x*y*z then 3a <= x+y+z

I'm a total newbie with Z3 (started today). So far liking it a lot. Great tool. Unfortunately the syntax confuses me a bit.
I want to prove that if:
a^3 = xyz = m ( with a, x, y, z, m (0..1) )
then:
3a <= (x+y+z)
I do so by trying to find a model satisfying that:
3a > (x+y+z)
Here is the Z3 code:
(declare-const a Real)
(declare-const x Real)
(declare-const y Real)
(declare-const z Real)
(declare-const m Real)
(assert (> a 0))
(assert (< a 1))
(assert (> x 0))
(assert (< x 1))
(assert (> y 0))
(assert (< y 1))
(assert (> z 0))
(assert (< z 1))
(assert (> m 0))
(assert (< m 1))
(assert (= (* (* a a) a) m))
(assert (= (* (* x y) z) m))
(assert (> (* 3.0 a) (+ (+ z y) x) ))
(check-sat)
The model is unsatisfied.
Have I successfully proved what I wanted? As I said, the syntax confuses me since I'm a total newbie.
Your solution is correct.
Explanation: What you wrote is equivalent to:
0 < x < 1
0 < y < 1
0 < z < 1
0 < m < 1
a * a * a = m
x * y * z = m
3 * a > x + y + z
Z3 says this is unsatisfiable. Thus, if
a^3 = xyz = m ( with a, x, y, z, m (0..1) )
then it cannot be the case that:
3a > (x+y+z)
because, if this did occur, then the SMT problem you posed would be satisfiable, which would be a contradiction with the claim by Z3 that the SMT problem is unsatisfiable. If it cannot be the case that 3a > (x+y+z), then it must be the case that 3a <= (x+y+z), which is the statement you originally wanted to prove.
I think that your solution is correct. Let me explain a bit about using Z3 to prove validity of a statement A. The key idea is that, in the classical logic, e.g., propositional logic and predicate logic:
A is Valid iff negation(A) is Unsatisfiable.
This is a pretty well-known result. You can find it in many textbooks and materials, for example, in page 4 of this slide. So, validity of P -> Q can be proved via checking for unsatisfiability of its negation: P /\ negation(Q).
In particular, for your example,
(a^3 = x*y*z = m) -> (3a <= x+y+z) is Valid,
iff
(a^3 = m) /\ (x*y*z = m) /\ (3a > x+y+z) is Unsatifiable.

Distinct in z3 SMT and python

My question is that Does "Distinct" works in z3 python?. I've compared the following code and it seem not giving the same results:
(declare-const x Int)
(declare-const y Int)
(assert (distinct x y))
(check-sat)
(get-model)
The result was:
sat
(model
(define-fun y () Int
0)
(define-fun x () Int
1)
)
I've added negative assertion just to test and the result was unsat which is correct:
(assert (= x y))
unsat
Z3(6, 10): ERROR: model is not available
But when I use z3 in python it give me always sat as follows:
x = Int('x')
y = Int('y')
Distinct(x, y)
s = Solver
s = Solver()
s.check()
when I add the following assertion It should give me unsat but It returns sat:
s.add(x == y)
[y = 0, x = 0]
Is this means that I used wrong syntax ?
The `Distinct' function only creates a term, it doesn't add itself to the solver. Here's an example that works for me:
x = Int('x')
y = Int('y')
d = Distinct(x, y)
s = Solver()
s.add(d) # SAT without this one, UNSAT with
s.add(x == y)
print s
print s.check()

Resources