z3py: restricting solution to a set of values - z3

I am new to Z3-solver python. I am trying to define a list and confine all my outputs to that list for a simple operation like xor.
My code:
b=Solver()
ls=[1,2,3,4,5] #my list
s1=BitVec('s1',32)
s2=BitVec('s2',32)
x=b.check(s1^s2==1, s1 in ls, s2 in ls) #s1 and s2 belongs to the list, however, this is not the correct way
if x==sat: print(b.model().eval)
The check function doesn't work like that.
Can anyone please help me in figuring how to do this in a different way?
Ans: s1=2,s2=3; since 2xor3 = 1 and s2,s3 belongs to ls=[1,2,3,4,5]

The easiest way to do this would be to define a function that checks if a given argument is in a list provided. Something like:
from z3 import *
def oneOf(x, lst):
return Or([x == i for i in lst])
s1 = BitVec('s1', 32)
s2 = BitVec('s2', 32)
s = Solver()
ls = [1, 2, 3, 4, 5]
s.add(oneOf(s1, ls))
s.add(oneOf(s2, ls))
s.add(s1 ^ s2 == 1)
print (s.check())
print (s.model())
When I run this, I get:
sat
[s2 = 2, s1 = 3]
which I believe is what you're after.

Related

Z3 - how to count matches?

I have a finite set of pairs of type (int a, int b). The exact values of the pairs are explicitly present in the knowledge base. For example it could be represented by a function (int a, int b) -> (bool exists) which is fully defined on a finite domain.
I would like to write a function f with signature (int b) -> (int count), representing the number of pairs containing the specified b value as its second member. I would like to do this in z3 python, though it would also be useful to know how to do this in the z3 language
For example, my pairs could be:
(0, 0)
(0, 1)
(1, 1)
(1, 2)
(2, 1)
then f(0) = 1, f(1) = 3, f(2) = 1
This is a bit of an odd thing to do in z3: If the exact values of the pairs are in your knowledge base, then why do you need an SMT solver? You can just search and count using your regular programming techniques, whichever language you are in.
But perhaps you have some other constraints that come into play, and want a generic answer. Here's how one would code this problem in z3py:
from z3 import *
pairs = [(0, 0), (0, 1), (1, 1), (1, 2), (2, 1)]
def count(snd):
return sum([If(snd == p[1], 1, 0) for p in pairs])
s = Solver()
searchFor = Int('searchFor')
result = Int('result')
s.add(Or(*[searchFor == d[0] for d in pairs]))
s.add(result == count(searchFor))
while s.check() == sat:
m = s.model()
print("f(" + str(m[searchFor]) + ") = " + str(m[result]))
s.add(searchFor != m[searchFor])
When run, this prints:
f(0) = 1
f(1) = 3
f(2) = 1
as you predicted.
Again; if your pairs are exactly known (i.e., they are concrete numbers), don't use z3 for this problem: Simply write a program to count as needed. If the database values, however, are not necessarily concrete but have other constraints, then above would be the way to go.
To find out how this is coded in SMTLib (the native language z3 speaks), you can insert print(s.sexpr()) in the program before the while loop starts. That's one way. Of course, if you were writing this by hand, you might want to code it differently in SMTLib; but I'd strongly recommend sticking to higher-level languages instead of SMTLib as it tends to be hard to read/write for anyone except machines.

Incorrect behaviour of .check() in z3py

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.

Z3py how to solve a problem with many possible path (k out of n potential actions, order matters) efficiently

I am trying to solve a problem that consists of n actions (n >= 8). A path consists k (k == 4 for now) actions. I would like to check if there exists any path, which satisfies the set of constraints I defined.
I have made two attempts to solve this problem:
Attempt 1: Brute force, try all permutations
Attempt 2: Code a path selection matrix M [k x n], such that each row contains one and only one element greater than 0, and all other elements equal to 0.
For instance if k == 2, n == 2, M = [[0.9, 0], [0, 0.7]] represents perform action 1 first, then action 2.
Then my state transition was coded as:
S1 = a2(a1(S0, M[1][1]), M[1][2]) = a2(a1(S0, 0.9), 0)
S2 = a2(a1(S1, M[2][1]), M[2][2]) = a2(a1(S1, 0), 0.7)
Note: I made sure that S == a(S,0), so that in each step only one action is executed.
Then constraints were checked on S2
I was hoping this to be faster than the permutation way of doing it. Unfortunately, this turns out to be slower. Just wondering if there is any better way to solve this problem?
Code:
_path = [[Real(f'step_{_i}_action_{_j}') for _j in range(len(actions))] for _i in range(number_of_steps)]
_states: List[State] = [self.s0]
for _i in range(number_of_steps):
_new_state = copy.deepcopy(_states[-1])
for _a, _p in zip(actions, _path[_i]):
self.solver.add(_a.constraints(_states[-1], _p))
_new_state = _a.execute(_new_state, _p)
_states.append(_new_state)

z3py: Retrieve branching conditions from z3 formula

Let's say I have a z3py program like this one:
import z3
a = z3.Int("a")
input_0 = z3.Int("input_0")
output = z3.Int("output")
some_formula = z3.If(a < input_0, 1, z3.If(a > 1, 4, 2))
s = z3.Solver()
s.add(output == some_formula)
s.check()
m = s.model()
print(m)
Is there an elegant way for me to retrieve the branching conditions from some_formula?
So get a list like [a < input_0, a > 1]. It should work for arbitrarily deep nesting of if expressions.
I know there is some way to use cubes, but I am not able to retrieve more than two cube expressions. I am not sure how to configure the solver.
My ultimate goal is to force the solver to give me different outputs based on the constraints I push and pop. The constraints are the set of conditions I have inferred from this formula.
You can print the cubes using:
for cube in s.cube():
print cube
But this isn't going to really help you. For your example, it prints:
[If(a + -1*input_0 >= 0, If(a <= 1, 2, 4), 1) == 1]
[Not(If(a + -1*input_0 >= 0, If(a <= 1, 2, 4), 1) == 1)]
which isn't quite what you were looking for.
The easiest way to go about your problem would be to directly walk down the AST of the formula yourself, and grab the conditions as you walk along the expressions. Of course, Z3 AST is quite a hairy object (pun intended!), so this will require quite a bit of programming. But reading through the constructors (If, Var etc.) in this file can get you started: https://z3prover.github.io/api/html/z3py_8py_source.html
Alright,thanks #alias! I came up with a custom version, which gets the job done. If someone knows a more elegant way to do this, please let me know.
import z3
a = z3.Int("a")
input_0 = z3.Int("input_0")
output = z3.Int("output")
some_formula = z3.If(a < input_0, 1, z3.If(a > 1, 4, 2))
nested_formula = z3.If(some_formula == 1, 20, 10)
s = z3.Solver()
s.add(output == some_formula)
s.check()
m = s.model()
print(m)
def get_branch_conditions(z3_formula):
conditions = []
if z3.is_app_of(z3_formula, z3.Z3_OP_ITE):
# the first child is usually the condition
cond = z3_formula.children()[0]
conditions.append(cond)
for child in z3_formula.children():
conditions.extend(get_branch_conditions(child))
return conditions
conds = get_branch_conditions(some_formula)
print(conds)
conds = get_branch_conditions(nested_formula)
print(conds)

Initial value for variables

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.

Resources