I am using z3 to write a static checker. I have the following problem:
>>> from z3 import *
>>> s = Solver()
>>> s.add(FreshInt() + FreshInt() > 0)
>>> s.check()
sat
>>> s.model()
[]
As you can see, fresh variables are not shown in the model. I also cannot get their value:
>>> a = FreshInt()
>>> s.add(a > 3)
>>> s.check()
sat
>>> s.model()
[]
>>> s.model()[a]
I've looked in the docs but I cannot find a way to change this behaviour. I could generate unique variables myself, but it would be nice if z3 can take care of that for me. Can someone point me in the right direction? Or is it not possible to change this in z3py?
FreshInt/FreshReal etc. are intended for creating internal variables that are not user-visible. You should instead use Int('name') and Real('name') to create user level variables that will be shown in models.
If you really want to see the value, you can add an observer function and use it like this:
from z3 import *
def observeInt(s, a):
obs = Int('observer')
s.add(obs == a)
# might want to check the following really returns sat!
s.check()
print s.model()[obs]
s = Solver()
a = FreshInt()
s.add(a + FreshInt() > 0)
s.add(a > 12)
print s.check()
observeInt(s, a)
This prints:
sat
13
This is not cheap obviously (as it involves a call to check), but it is safe and so long as it's used in debugging situations to strong-arm z3 as you put it, it should do the trick.
You could circumvent this restriction as follows:
freshIntIdx = 0
def myFreshInt():
global freshIntIdx
freshIntIdx += 1;
return Int('fi' + str(freshIntIdx))
a = myFreshInt()
b = myFreshInt()
s = Solver()
s.add(a + b > 5, a > 0, b > 0, a + b < 10)
print(s.check())
m = s.model()
print("a = %s" % m[a])
print("b = %s" % m[b])
Related
Consider a set of constraints F = [a + b > 10, a*a + b + 10 < 50].
When I run it using:
s = Solver()
s.add(F)
s.check()
I get sat solution.
If I run it with:
s = Solver()
s.check(F)
I get an unknown solution. Can someone explain why this is happening?
Let's see:
from z3 import *
a = Int('a')
b = Int('b')
F = [a + b > 10, a*a + b + 10 < 50]
s = Solver()
s.add(F)
print (s.check())
print (s.model())
This prints:
sat
[b = 15, a = -4]
That looks good to me.
Let's try your second variant:
from z3 import *
a = Int('a')
b = Int('b')
F = [a + b > 10, a*a + b + 10 < 50]
s = Solver()
print (s.check(F))
print (s.model())
This prints:
sat
[b = 7, a = 4]
That looks good to me too.
So, I don't know how you're getting the unknown answer. Maybe you have an old version of z3; or you've some other things in your program you're not telling us about.
The important thing to note, however, is that s.add(F); s.check() AND s.check(F) are different operations:
s.add(F); s.check() means: Assert the constraints in F; check that they are satisfiable.
s.check(F) means: Check that all the other constraints are satisfiable, assuming F is. In particular, it does not assert F. (This is important if you do further asserts/checks later on.)
So, in general these two different ways of using check are used for different purposes; and can yield different answers. But in the presence of no other assertions around, you'll get a solution for both, though of course the models might be different.
Aside One reason you can get unknown is in the presence of non-linear constraints. And your a*a+b+10 < 50 is non-linear, since it does have a multiplication of a variable by itself. You can deal with that either by using a bit-vector instead of an Int (if applicable), or using the nonlinear-solver; which can still give you unknown, but might perform better. But just looking at your question as you asked it, z3 is just fine handling it.
To find out what is going on within s.check(F), you can do the following:
from z3 import *
import inspect
a = Int('a')
b = Int('b')
F = [a + b > 10, a*a + b + 10 < 50]
s = Solver()
print (s.check(F))
print (s.model())
source_check = inspect.getsource(s.check)
print(source_check)
The resulting output:
sat
[b = 10, a = 1]
def check(self, *assumptions):
"""Check whether the assertions in the given solver plus the optional assumptions are consistent or not.
>>> x = Int('x')
>>> s = Solver()
>>> s.check()
sat
>>> s.add(x > 0, x < 2)
>>> s.check()
sat
>>> s.model().eval(x)
1
>>> s.add(x < 1)
>>> s.check()
unsat
>>> s.reset()
>>> s.add(2**x == 4)
>>> s.check()
unknown
"""
s = BoolSort(self.ctx)
assumptions = _get_args(assumptions)
num = len(assumptions)
_assumptions = (Ast * num)()
for i in range(num):
_assumptions[i] = s.cast(assumptions[i]).as_ast()
r = Z3_solver_check_assumptions(self.ctx.ref(), self.solver, num, _assumptions)
return CheckSatResult(r)
The semantics of assumptions vs. assertions are discussed here and here. But if have to admit that they are not really clear to me yet.
F(x1) > a;
F(x2) < b;
∀t, F'(x) >= 0 (derivative) ;
F(x) = ∑ ci*x^i; (i∈[0,n] ; c is a constant)
Your question is quite ambiguous, and stack-overflow works the best if you show what you tried and what problems you ran into.
Nevertheless, here's how one can code your problem for a specific function F = 2x^3 + 3x + 4, using the Python interface to z3:
from z3 import *
# Represent F as a function. Here we have 2x^3 + 3x + 4
def F(x):
return 2*x*x*x + 3*x + 4
# Similarly, derivative of F: 6x^2 + 3
def dF(x):
return 6*x*x + 3
x1, x2, a, b = Ints('x1 x2 a b')
s = Solver()
s.add(F(x1) > a)
s.add(F(x2) < b)
t = Int('t')
s.add(ForAll([t], dF(t) >= 0))
r = s.check()
if r == sat:
print s.model()
else:
print ("Solver said: %s" % r)
Note that I translated your ∀t, F'(x) >= 0 condition as ∀t. F'(t) >= 0. I assume you had a typo there in the bound variable.
When I run this, I get:
[x1 = 0, x2 = 0, b = 5, a = 3]
This method can be generalized to arbitrary polynomials with constant coefficients in the obvious way, but that's mostly about programming and not z3. (Note that doing so in SMTLib is much harder. This is where the facilities of host languages like Python and others come into play.)
Note that this problem is essentially non-linear. (Variables are being multiplied with variables.) So, SMT solvers may not be the best choice here, as they don't deal all that well with non-linear operations. But you can deal with those problems as they arise later on. Hope this gets you started!
I would like to set the initial value for variables in z3py in an efficient way.
x,y = Ints(x,y)
s = Solver()
s.add(x>10)
s.check()
s.model()
I would expect the output value is e.g., x = 11, y = 0, not the result x = 11, y = 7.
One way to do it is:
x,y = Ints(x,y)
s = Optimize()
s.add_soft(x==0)
s.add_soft(y==0)
s.add(x>10)
s.check()
s.model()
But it takes much computation time as my program contains many of variables. Any better way to do it?
The slow-down is because you're forcing the optimizer to run, which is an overkill for this purpose. (The optimizing solver can handle max-sat problems, which does the job here, but it is costly and not needed for this case.)
Instead, simply walk over the model and see if there's an assignment for it:
from z3 import *
def model_with_zeros(s, vs):
m = s.model()
result = []
for v in vs:
val = m.eval(v)
if val.eq(v):
result.append((v, 0))
else:
result.append((v, val))
return result
x, y = Ints('x y')
s = Solver()
s.add(x > 10)
print s.check()
print model_with_zeros(s, [x, y])
This prints:
sat
[(x, 11), (y, 0)]
Note that you have to explicitly pass the solver and the variables you are interested in to the model_with_zeros function; as the trick here is precisely to see which variables the solver left untouched.
If you want a different initial value, then you can modify model_with_zeros to account for that for each variable separately.
I'm experimenting with (and failing at) reducing sets in z3 over operations like addition. The idea is eventually to prove stuff about arbitrary reductions over reasonably-sized fixed-sized sets.
The first of the two examples below seems like it should yield unsat, but it doesn't. The second does work, but I would prefer not to use it as it requires incrementally fiddling with the model.
def test_reduce():
LIM = 5
VARS = 10
poss = [Int('i%d'%x) for x in range(VARS)]
i = Int('i')
s = Solver()
arr = Array('arr', IntSort(), BoolSort())
s.add(arr == Lambda(i, And(i < LIM, i >= 0)))
a = arr
for x in range(len(poss)):
s.add(Implies(a != EmptySet(IntSort()), arr[poss[x]]))
a = SetDel(a, poss[x])
def final_stmt(l):
if len(l) == 0: return 0
return If(Not(arr[l[0]]), 0, l[0] + (0 if len(l) == 1 else final_stmt(l[1:])))
sm = final_stmt(poss)
s.push()
s.add(sm == 1)
assert s.check() == unsat
Interestingly, the example below works much better, but I'm not sure why...
def test_reduce_with_loop_model():
s = Solver()
i = Int('i')
arr = Array('arr', IntSort(), BoolSort())
LIM = 1000
s.add(arr == Lambda(i, And(i < LIM, i >= 0)))
sm = 0
f = Int(str(uuid4()))
while True:
s.push()
s.add(arr[f])
chk = s.check()
if chk == unsat:
s.pop()
break
tmp = s.model()[f]
sm = sm + tmp
s.pop()
s.add(f != tmp)
s.push()
s.add(sm == sum(range(LIM)))
assert s.check() == sat
s.pop()
s.push()
s.add(sm == 11)
assert s.check() == unsat
Note that your call to:
f = Int(str(uuid4()))
Is inside the loop in the first case, and is outside the loop in the second case. So, the second case simply works on one variable, and thus converges quickly. While the first one keeps creating variables and creates a much harder problem for z3. It's not surprising at all that these two behave significantly differently, as they encode entirely different constraints.
As a general note, reducing an array of elements with an operation is just not going to be an easy problem for z3. First, you have to assume an upper bound on the elements. And if that's the case, then why bother with Lambda or Array at all? Simply create a Python list of that many variables, and ignore the array logic completely. That is:
elts = [Int("s%d"%i) for i in range(100)]
And then to access the elements of your 'array', simply use Python accessor notation elts[12].
Note that this only works if all your accesses are with a constant integer; i.e., your index cannot be symbolic. But if you're looking for proving reduction properties, that should suffice; and would be much more efficient.
In Z3 I can call (get-objectives) to have a dump of the resulting weights.
(e.g. here)
It prints something like this:
(objectives
(aaa 1)
(bbb 0)
)
In z3py however Optimize.objectives() prints a dump of the calculation for the objectives, not however the calculated weights, as seen here:
[If(a == 3, 0, 1), If(b == 3, 0, 1)]
Is there a way how I can get the calculated weights? or the weight of a specific objective as in the standard z3?
Here is my example code:
from z3 import *
a, b = Ints('a b')
s = Optimize()
s.add(3 <= a, a <= 10)
s.add(3 <= b, b <= 10)
s.add(a >= 2*b)
s.add_soft(a == 3, weight=1, id="aaa")
s.add_soft(b == 3, weight=1, id="bbb")
print(s.check())
print(s.model())
print(s.objectives())
You can use the model to evaluate the objectives:
m = s.model()
print [m.evaluate(o) for o in s.objectives()]
This yields:
sat
[1, 0]