UNKNOWN when using def's - z3

This simple example generates UNKNOWN for me, I suppose there is something that I don't understand about def's.
from z3 import *
s = Solver()
def Min(b, r):
return If(b, r, 1)
a = Real('a')
b = Bool('b')
s.add(a==0.9)
s.add(a<=Min(b,0.9))
s.check()
print "Presenting result "
m = s.model()
print "traversing model..."
for d in m.decls():
print "%s = %s" % (d.name(), m[d])

You did not make any mistake. This is a problem in one of Z3 solvers. Your problem is in a fragment of arithmetic called "difference-logic". A problem in in this fragment, if the arithmetic atoms can be written as x - y <= k, where k is a numeral. When a problem is in this fragment, Z3 will use a specialized solver for it. However, this solver may fail (returns unknown) when the input problem also contains if-then-else terms (the If in your Min).
The bug has been fixed, and will be available in the next release. In the meantime, you can try one of the following workarounds:
Force Z3 to eliminate if-then-else terms before invoking the solver. You just have to replace s = Solver() with s = Then('elim-term-ite', 'smt').solver(). Here is the modified script at rise4fun.
We can add a redundant assertion that is not in the different logic fragment. Example: z + w > 2. Here is the modified script at rise4fun.

Related

In Z3, I cannot understand result of quantifier elimination of Exists y. Forall x. (x>=2) => ((y>1) /\ (y<=x))

In Z3-Py, I am performing quantifier elimination (QE) over the following formulae:
Exists y. Forall x. (x>=2) => ((y>1) /\ (y<=x))
Forall x. Exists y. (x>=2) => ((y>1) /\ (y<=x)),
where both x and y are Integers. I did QE in the following way:
x, y = Ints('x, y')
t = Tactic("qe")
negS0= (x >= 2)
s1 = (y > 1)
s2 = (y <= x)
#EA
ea = Goal()
ea.add(Exists([y],Implies(negS0, (ForAll([x], And(s1,s2))))))
ea_qe = t(ea)
print(ea_qe)
#AE
ae = Goal()
ae.add(ForAll([x],Implies(negS0, (Exists([y], And(s1,s2))))))
ae_qe = t(ae)
print(ae_qe)
Result QE for ae is as expected: [[]] (i.e., True). However, as for ea, QE outputs: [[Not(x, >= 2)]], which is a results that I do not know how to interpret since (1) it has not really performed QE (note the resulting formula still contains x and indeed does not contain y which is the outermost quantified variable) and (2) I do not understand the meaning of the comma in x, >=. I cannot get the model either:
phi = Exists([y],Implies(negS0, (ForAll([x], And(s1,s2)))))
s_def = Solver()
s_def.add(phi)
print(s_def.model())
This results in the error Z3Exception: model is not available.
I think the point is as follows: since (x>=2) is an implication, there are two ways to satisfy the formula; by making the antecedent False or by satisfying the consequent. In the second case, the model would be y=2. But in the first case, the result of QE would be True, thus we cannot get a single model (as it happens with a universal model):
phi = ForAll([x],Implies(negS0, (Exists([y], And(s1,s2)))))
s_def = Solver()
s_def.add(phi)
print(s_def.model())
In any case, I cannot 'philosophically' understand the meaning of a QE of x where x is part of the (quantifier-eliminated) answer.
Any help?
There are two separate issues here, I'll address them separately.
The mysterious comma This is a common gotcha. You declared:
x, y = Ints('x, y')
That is, you gave x the name "x," and y the name "y". Note the comma after the x in the name. This should be
x, y = Ints('x y')
I guess you can see the difference: The name you gave to the variable x is "x," when you do the first; i.e., comma is part of the name. Simply skip the comma on the right hand side, which isn't what you intended anyhow. And the results will start being more meaningful. To be fair, this is a common mistake, and I wish the z3 developers ignored the commas and other punctuation in the string you give; but that's just not the case. They simply break at whitespace.
Quantification
This is another common gotcha. When you write:
ea.add(Exists([y],Implies(negS0, (ForAll([x], And(s1,s2))))))
the x that exists in negS0 is not quantified over by your ForAll, since it's not in the scope. Perhaps you meant:
ea.add(Exists([y],ForAll([x], Implies(negS0, And(s1,s2)))))
It's hard to guess what you were trying to do, but I hope the above makes it clear that the x wasn't quantified. Also, remember that a top-level exist quantifier in a formula is more or less irrelevant. It's equivalent to a top-level declaration for all practical purposes.
Once you make this fix, I think things will become more clear. If not, please ask further clarifying questions. (As a separate question on Stack-overflow; as edits to existing questions only complicate the matters.)

Lambda Functions for Z3Py

My goal is to find a construct within Z3Py which allows me to:
(1) Write propositions as a function of a variable. For eg theoretically, if I define P(x) = x < 3, then the code should allow me to access P(u) for some other variable u.
(2) And Z3 should be able to solve and find a model for such a construct.
I thought Z3's 'Lambda' function theoretically made sense. However with this construct neither can I do (1) or (2). As a concrete eg, suppose I have the following code:
u, x = Ints('u x')
P = Lambda( [x], x < 5 )
I = Lambda ([x], x < 3)
C1 = Not(Implies(P.body(), I.body() ))
s = Solver()
s.add(C1)
r = s.check()
print(r.__repr__())
s.add( Implies(P(u), u == 2) )
Run this code to get the output:
unknown
Traceback (most recent call last):
File "testfile.py", line 20, in <module>
s.add( Implies(P(u), u == 2) )
TypeError: 'QuantifierRef' object is not callable
There are two issues to fix here:
(1) Why does r._ repr_() have 'unknown' stored and not 'sat' i.e. Why isn't Z3 solving this system?
(2) In the final line, how can I get the predicate u < 5 from P i.e. in lambda calculus terminology, how do I do application of a function to a variable in Z3Py? Clearly P(u) does not work.
For this sort of modeling, you should simply use a regular python function:
from z3 import *
def P(x):
return x < 5
def I(x):
return x < 3
Then, to do the proof Q(x) => P(x), you'd use a quantifier:
dummy = Int('dummy')
C1 = ForAll([dummy], Implies(I(dummy), P(dummy)))
prove(C1)
This prints:
proved
Regarding your specific questions:
(1) Adding Implies(P.body(), Q.body()) means something completely different. If you run:
from z3 import *
x = Int('x')
P = Lambda( [x], x < 5 )
I = Lambda( [x], x < 3 )
s = Solver()
s.add(Implies(P.body(), I.body()))
print(s.sexpr())
You'll see it prints:
(assert (=> (< (:var 0) 5) (< (:var 0) 3)))
where :var is an internal free-variable generating function. This isn't an object you should be passing back and forth to z3; in fact, I think you're becoming a victim of the loosely typed nature of z3; this isn't a construct that really make much sense at all. Long story short, you should never look at P.body() or I.body() in your own code. I'd ignore the unknown result in this context; the input is more or less meaningless, and z3 spits out a nonsensical answer. A better system should've checked and complained about this; but this is not a strong point for z3's Python API.
(2) If you use a regular function, this isn't really a problem at all; because you're just doing regular application at the Python level. You can apply a lambda-bound value by directly calling it as well, though you need the notation P[u]. (Lambda's are similar to arrays in z3.) So, something like:
from z3 import *
u, x = Ints('u x')
P = Lambda([x], x < 5)
I = Lambda([x], x < 3)
s = Solver()
s.add(Implies(P[u], u == 2))
print(s.check())
print(s.model())
will print:
sat
[u = 2]
which is what you were looking for I think.
Multiple arguments
If you want to model a lambda with multiple arguments, the easiest way is to think of it as a nested construct. That is, you store a new lambda at each index. Here's an example:
from z3 import *
dummy1 = FreshInt()
dummy2 = FreshInt()
P = Lambda([dummy1], Lambda([dummy2], dummy1 < dummy2))
s = Solver()
x, y = Ints('x y')
s = Solver()
s.add(P[x][y])
print(s.check())
print(s.model())
This prints:
sat
[y = 1, x = 0]
Note that the above also demonstrates the use of the FreshInt function, which avoids name-clashes by providing a unique name each time it is called.

Power and logarithm in Z3

I'm trying to learn Z3 and the following example baffles me:
from z3 import *
a = Int("a")
b = Int("b")
print(solve(2**a <= b))
print(solve(a > 0, b > 0, 2**a <= b))
I would expect it returns "[a = 1, b = 2]" but it instead returns "failed to solve".
Why cannot it be solved?
Is it possible to compute with powers and logarithms in Z3 at all? How do I find, say, the length of binary string representation of a number (log base 2)?
Long story short, z3 (or SMT solvers in general) cannot deal with non-linear constraints like this. Exponentiation/Logs etc are difficult to deal with, and there are no decision procedures for them over the integers. Even over reals they are difficult to handle. That is, the solver will apply some heuristics, which may or may not work. But for these sorts of constraints, SMT solvers are just not the right tool.
For an earlier answer on non-linear arithmetic in z3, see this answer: https://stackoverflow.com/a/13898524/936310
Here're some more details if you are interested. First, there is no power-operator for integers in SMTLib or z3. If you look at the generated program, you'll see that it's actually over real values:
from z3 import *
a = Int("a")
b = Int("b")
s = Solver()
s.add(2**a <= b)
print(s.sexpr())
print(s.check())
This prints:
(declare-fun b () Int)
(declare-fun a () Int)
(assert (<= (^ 2 a) (to_real b)))
unknown
Note the conversion to to_real. The ^ operator automatically creates a real. The way this would be solved is if the solver can come up with a solution over reals, and then checks to see if the result is an integer. Let's see what happens if we try with Reals:
from z3 import *
a = Real("a")
b = Real("b")
s = Solver()
s.add(2**a <= b)
print(s.check())
print(s.model())
This prints:
sat
[b = 1, a = 0]
Great! But you also wanted a > 0, b > 0; so let's add that:
from z3 import *
a = Real("a")
b = Real("b")
s = Solver()
s.add(2**a <= b)
s.add(a > 0)
s.add(b > 0)
print(s.check())
This prints:
unknown
So, the solver can't handle this case either. You can play around with tactics (qfnra-nlsat), but it's unlikely to handle problems of this sort in general. Again, refer to https://stackoverflow.com/a/13898524/936310 for details.

Using sets and SetHasSize on intersections in z3

I've been trying to enumerate solutions to the following problem. I've started with simple approach first.
Below I have two sets of size k, intersection between them is of size 1 and I want to see how sets A and B look:
Els, elems = EnumSort('Els',['a1', 'a2', 'a3'])
A, B = Consts('A B', SetSort(Els))
k, c = Ints('k c')
s = Solver()
s.add(SetHasSize(A, k))
s.add(SetHasSize(B, k))
s.add(k == 2, c == 1)
s.add(SetHasSize(SetIntersect(A, B), c))
s.check()
s.model()
Here, the solution should be A == ['a1', 'a2'] and B == ['a2', 'a3'] but satisfiability was not reached.
Even a simple task like one below results in never ending execution:
V, _ = EnumSort('Els',['a1', 'a2', 'a3'])
A = Const('A', SetSort(V))
k = Int('k')
s = SimpleSolver()
s.add(SetHasSize(A, k))
s.add(k == IntVal(2))
s.check()
s.model()
Changing k == IntVal(2) to k <= IntVal(2) makes the problem satisfiable and returns [A = ∃k!0 : k!0 = a1 ∨ k!0 = a2, k = 2] as a model of the set. I'm not sure if there is a faster approach.
If I run your program, I get:
WARNING: correct handling of finite domains is TBD
WARNING: correct handling of finite domains is TBD
WARNING: correct handling of finite domains is TBD
before it starts looping. This is a known issue in the implementation: Z3 cannot really deal with sets that have a finite domain.
Alas, replacing it with an infinite domain doesn't help either. Making this change:
A, B = Consts('A B', SetSort(IntSort()))
You get:
unsat
which is clearly bogus. I strongly suspect this is related to the following issue: https://github.com/Z3Prover/z3/issues/3854 (In short, the SMTLib frontend does not support set-has-size. For whatever reason, they left it in the Python and C/C++ interfaces, but clearly it's not really functional.)
So, strictly speaking, this is a bug. But more realistic answer is that set-has-size is no longer supported by z3. You should file an issue at https://github.com/Z3Prover/z3/issues so the authors are aware of this problem and perhaps remove it from the API completely if it won't ever be supported.
UPDATE:
As of this commit, z3 no longer accepts the set-has-size predicate; it is no longer supported.

Is there way to give input as normal expression to Z3 Solver?

The Z3 input format is an extension of the one defined by SMT-LIB 2.0 standard. The input expressions need to write in prefix form. As for example rise4fun,
x + (y * 2) = 20 needs to be given input in the form of " (= (+ x (* 2 y)) 20)) ".
Z3 supports JAVA API. As for example, let us consider the below code which evaluates and checks satisfiability expressions: x+y = 500 and x + (y * 2) = 20.
final Context ctx = new Context();
final Solver solver = ctx.mkSimpleSolver();
IntExpr x = ctx.mkIntConst("x");
IntExpr y = ctx.mkIntConst("y");
IntExpr th = ctx.mkInt(500);
IntExpr th1 = ctx.mkInt(2);
IntExpr th2 = ctx.mkInt(20);
BoolExpr t1 = ctx.mkEq(ctx.mkAdd(x,y), th);
BoolExpr t2 = ctx.mkEq(ctx.mkAdd(x,ctx.mkMul(th1, y)), th2);
solver.add(t1);
solver.add(t2);
solver.check()
The problem is if an external user wants to give input to the solver, he cannot give it in the form of the general formula as " x+y = 500, x + (y * 2) = 20 ".
The input needs to be parsed and then should be written manually using JAVA API in prefix form (Note BoolExpr t2 in above code) to give the final expressions to Solver.
Is there any parser/library/API (Preferably JAVA or in any other language) which parses the general expressions with arithmetic operators(+, -, <, >, =), propositional logic connectors (And, OR), Quantifiers(ForAll, Exists) and then gives input to the Z3 Solvers ?
Please suggest and help.
This is precisely why people build high-level interfaces to SMT solvers. There are many choices here for z3:
Official Python interface to z3: https://ericpony.github.io/z3py-tutorial/guide-examples.htm This is supported by Microsoft directly, and is probably the easiest to use.
PySMT, which aims to cover as many SMT solvers as they can: https://github.com/pysmt/pysmt
Scala bindings: https://github.com/epfl-lara/ScalaZ3
Haskell SBV: http://hackage.haskell.org/package/sbv
Many others at various maturity levels for Racket, Go, Lisp.. You name it. You can find many of them on github.
The goal of these "wrappers" is to precisely save the end-user from all the details of intricate bindings, and provide something much easier and less-error prone to use. On the flip side, they require you to learn yet another library. In my experience, if the host language of your choice has such an implementation, it'd pay off nicely to use it. If not, you should build one!

Resources