Understanding quantifier traversing in Z3 - z3

I'm trying to understand traversing quantified formula in z3 (i'm using z3py). Have no idea how to pickup the quantified variables. For example in code shown below i'm trying to print the same formula and getting error.
from z3 import *
def traverse(e):
if is_quantifier(e):
var_list = []
if e.is_forall():
for i in range(e.num_vars()):
var_list.append(e.var_name(i))
return ForAll (var_list, traverse(e.body()))
x, y = Bools('x y')
fml = ForAll(x, ForAll (y, And(x,y)))
same_formula = traverse( fml )
print same_formula
With little search i got to know that z3 uses De Bruijn index and i have to get something like Var(1, BoolSort()). I can think of using var_sort() but how to get the formula to return the variable correctly. Stuck here for some time.

var_list is a list of strings, but ForAll expects a list of constants. Also, traverse should return e when it's not a quantifier. Here's a modified example:
from z3 import *
def traverse(e):
if is_quantifier(e):
var_list = []
if e.is_forall():
for i in range(e.num_vars()):
c = Const(e.var_name(i) + "-traversed", e.var_sort(i))
var_list.append(c)
return ForAll (var_list, traverse(e.body()))
else:
return e
x, y = Bools('x y')
fml = ForAll(x, ForAll (y, And(x,y)))
same_formula = traverse( fml )
print(same_formula)

Related

A model of a simple formula 'Exists([y],ForAll([x],Phi))' should be 'y=2' but Z3 it is returning '[]'

Note the following Z3-Py code:
x, y = Ints('x y')
negS0= (x >= 2)
s1 = (y > 1)
s2 = (y <= x)
s = Solver()
phi = Exists([y],ForAll([x], Implies(negS0, And(s1,s2))))
s.add(phi)
print(s.check())
print(s.model())
This prints:
sat
[]
My question is: why is the model empty? I mean, I think y=2 should be a model...
Note that the same result happens with x and y being Real.
z3 will not include any quantified variable (in your case neither y nor x) in its model. Note that you cannot put x in a model anyhow, because the formula is true for all x: That's the meaning of universal quantification. For the outer-most existentials (like your y), z3 can indeed print the model value for that, but it chooses not to do so since it can be confusing: Imagine you had a phi2, which also had an outer-most existential named y: How would you know which y it would be that it prints in the model?
So, z3 keeps things simple and simply prints the top-level declared variables in the model. And since a top-level declaration is equivalent to an outermost existential, you can simply drop it:
from z3 import *
x, y = Ints('x y')
negS0= (x >= 2)
s1 = (y > 1)
s2 = (y <= x)
s = Solver()
phi = ForAll([x], Implies(negS0, And(s1,s2)))
s.add(phi)
print(s.check())
print(s.model())
This prints:
sat
[y = 2]
like you predicted. Note that this y is unambiguous, since it's declared at the top-level. (Of course, you can redefine it to be something else due to the loosely typed nature of Python bindings and still get yourself confused, but that's a different discussion.)

How to get every clauses of a CNF formula in Z3

like in the code below, Is there any function in Z3 to get all the clauses of a formula(as a CNF)?
x = Boolean('x')
y = Boolean('y')
f = And(x, Or(x,y),And(x,Not(x,y))
# can I get all the clauses of formula f stored in a list
You can do something like the following:
from z3 import *
x = Bool('x') # Note: Bool() rather than Boolean()
y = Bool('y')
z = Bool('z')
f = And(x, Or(x,y), And(x, z == Not(y)))
# from https://stackoverflow.com/a/18003288/1911064
g = Goal()
g.add(f)
# use describe_tactics() to get to know the tactics available
t = Tactic('tseitin-cnf')
clauses = t(g)
for clause in clauses[0]:
print(clause)
Output is a list of disjunctive clauses:
x
Or(x, y)
Or(y, z)
Or(Not(y), Not(z))
Your original expression is not satisfiable.
What is Not(x, y) supposed to do?
As simpler way to convert (nested) Boolean expressions to CNF is provided by bc2cnf.

z3python: no XOR operator?

I have this code in Z3 python:
x = Bool('x')
y = Bool('y')
z = Bool('z')
z == (x xor y)
s = Solver()
s.add(z == True)
print s.check()
But this code reports below error when running:
c.py(4): error: invalid syntax
If I replace xor with and, there is no problem. So this means XOR is not supported?
You should use Xor(a, b). Moreover, to create the Z3 expression that represents the formula a and b, we must use And(a, b). In Python, we can't overload the operators and and or.
Here is an example with the Xor (available online at rise4fun).
x = Bool('x')
y = Bool('y')
z = Xor(x, y)
s = Solver()
s.add(z)
print s.check()
print s.model()

Needless Var() returned by Solver.model()

Solver.model() sometimes returns an assignment with a seemingly-needless Var(), whereas I was (perhaps naively) expecting Solver.model() to always return a concrete value for each variable. For example:
#!/usr/bin/python
import z3
x, y = z3.Ints('x y')
a = z3.Array('a', z3.IntSort(), z3.IntSort())
e = z3.Not(z3.Exists([x], z3.And(x != y, a[x] == a[y])))
solver = z3.Solver()
solver.add(e)
print solver.check()
print solver.model()
produces
sat
[k!1 = 0,
a = [else -> k!5!7(k!6(Var(0)))],
y = 1,
k!5 = [else -> k!5!7(k!6(Var(0)))],
k!5!7 = [1 -> 3, else -> 2],
k!6 = [1 -> 1, else -> 0]]
What's going on here? Is Var(0) in a's "else" referring to the 0th argument to the a array, meaning a[i] = k!5!7[k!6[i]]? Is it possible to get a concrete satisfying assignment for a out of Z3, such as a = [1 -> 1, else -> 0]?
This is the intended output. The interpretation for functions and arrays should be viewed as function definitions. Keep in mind that the assertion
z3.Not(z3.Exists([x], z3.And(x != y, a[x] == a[y])))
is essentially a universal quantifier. For quantifier free problems, Z3 does generate the "concrete assignments" suggested in your post. However, this kind of representation is not expressive enough. In the end of the message, I attached an example that cannot be encoded using "concrete assignments".
The following post has additional information about how models are encoded in Z3.
understanding the z3 model
You can find more details regarding the encoding used by Z3 at http://rise4fun.com/Z3/tutorial/guide
Here is an example that produces a model that can't be encoded using "concrete" assignments (available online at http://rise4fun.com/Z3Py/eggh):
a = Array('a', IntSort(), IntSort())
i, j = Ints('i j')
solver = Solver()
x, y = Ints('x y')
solver.add(ForAll([x, y], Implies(x <= y, a[x] <= a[y])))
solver.add(a[i] != a[j])
print solver.check()
print solver.model()

Z3 array: why Select() does not return value saved by Store()?

I have simple Z3 python code like below. I expect the "print" line will return me "y" which was stored in the line above it. Instead, I got back "A[x]" as result.
I = IntSort()
A = Array('A', I, I)
x = Int('x')
y = Int('y')
Store(A, x, y)
print Select(A,x)
Why does not Select() return the value stored by Store()?
Thanks.
There are two things to note:
First:
When you write
Store(A, x, y)
You create a term with three arguments , A, x, and y.
There is no side-effect to A.
You can create a name for this term by writing
B = Store(A,x,y)
Second:
Z3 does not simplify terms unless you want it to.
The python API exposes a simplification function called simplify.
You can obtain the reduced term by calling the simplifier.
The example is:
I = IntSort()
A = Array('A', I, I)
x = Int('x')
y = Int('y')
B = Store(A, x, y)
print Select(B,x)
print simplify (Select(B,x))

Resources