z3py: Symbolic expressions cannot be cast to concrete Boolean values? - python

from z3 import *
x = Real('x')
s = Solver()
s.add(x > 1 or x < -1)
print(s.check())
if s.check() == sat:
print(s.model())
I want to solve a or expressions , how can i do it?
when z3 told me "Symbolic expressions cannot be cast to concrete Boolean values"

Python's or is not symbolic aware. Instead, use z3py's Or:
from z3 import *
x = Real('x')
s = Solver()
s.add(Or(x > 1, x < -1))
r = s.check()
print(r)
if r == sat:
print(s.model())
This prints:
sat
[x = -2]
Note that I'd also avoid two separate calls to check, by storing the result in a variable first. (Which I called r above.) In general, the second call to check will be cheap since you haven't added any constraints after the first, but this makes the intention clearer.

Related

Modulo operation on Real values (Z3Py)

I want to implement the modulo operation using Z3Py. I've found this discussion on the Z3 github page where one of the creators has the following solution. However, I'm not sure I fully understand it.
from z3 import *
mod = z3.Function('mod', z3.RealSort(), z3.RealSort(), z3.RealSort())
quot = z3.Function('quot', z3.RealSort(), z3.RealSort(), z3.IntSort())
s = z3.Solver()
def mk_mod_axioms(X, k):
s.add(Implies(k != 0, 0 <= mod(X, k)),
Implies(k > 0, mod(X, k) < k),
Implies(k < 0, mod(X, k) < -k),
Implies(k != 0, k * quot(X, k) + mod(X, k) == X))
x, y = z3.Reals('x y')
mk_mod_axioms(x, 3)
mk_mod_axioms(y, 5)
print(s)
If you set no additional constraints the model evaluates to 0, the first solution. If you set additional constraints that x and y should be less than 0, it produces correct solutions. However, if you set the constraint that x and y should be above 0 it produces incorrect results.
s.add(x > 0)
s.add(y > 0)
The model evaluates to 1/2 for x and 7/2 for y.
Here's the model z3 prints:
sat
[y = 7/2,
x = 1/2,
mod = [(7/2, 5) -> 7/2, else -> 1/2],
quot = [else -> 0]]
So, what it's telling you is that it "picked" mod and quot to be functions that are:
def mod (x, y):
if x == 3.5 and y == 5:
return 3.5
else:
return 0.5
def quot (x, y):
return 0
Now go over the axioms you put in: You'll see that the model does satisfy them just fine; so there's nothing really wrong with this.
What the answer you linked to is saying is about what sort of properties you can state to get a "reasonable" model. Not that it's the unique such model. In particular, you want quot to be the maximum such value, but there's nothing in the axioms that require that.
Long story short, the answer you're getting is correct; but it's perhaps not useful. Axiomatizing will take more work, in particular you'll need quantification and SMT solvers don't deal with such specifications that well. But it all depends on what you're trying to achieve: For specific problems you can get away with a simpler model. Without knowing your actual application, the only thing we can say is that this axiomatization is too weak for your use case.

Declaring a finite sort in z3

Let us assume I have a finite set {e1, e2, e3}. I want to be able to distinguish transitive constraints so I can handle this behavior:
from z3 import *
solver = Solver()
A = DeclareSort('A')
x = Const('x', A)
y = Const('y', A)
z = Const('z', A)
solver.add(x!=y)
solver.add(y!=z)
solver.add(x==z)
assert solver.check() != z3.sat
The only way I found to solve it is changing the last constraint with this one:
solver.add(ForAll([x,z],x==z))
Is this the way to model it? Is there any finite sort available? Should I need to add all the constraints declaring the elements different from each other?
Some clarification: Maybe is not a variable what I need, because {x == y, y == z, x == z } is clearly sat, but the behavior I want to model is more like this {x == 1, 2 == z, x == z } that is obviously unsat (assuming some finite sort like {1,2,3,4}).
What I was looking for was the EnumSort:
from z3 import *
solver = Solver()
S, (a, b, c) = EnumSort('round', ['a','b','c'])
x = Const("x", S)
z = Const("z", S)
solver.add(x==a)
solver.add(z==b)
solver.add(x==z)
assert solver.check() != z3.sat

Is there a way to use solver.unsat_core, without using solver.assert_and_track?

Is there any way to make the following code work, and print out a valid unsat core?
from z3 import *
a = Int('a')
b = Int('b')
s = Solver()
s.add(a == 1)
s.add(a == 2)
s.add(b == 3)
s.check()
# This prints [], and I would like it to print [a == 1, a == 2]
print(s.unsat_core())
I know I could do this instead:
from z3 import *
a = Int('a')
b = Int('b')
s = Solver()
s.assert_and_track(a == 1, 'p1')
s.assert_and_track(a == 2, 'p2')
s.assert_and_track(b == 3, 'p3')
s.check()
# This prints [p1, p2]
print(s.unsat_core())
But for the real project I'm working on, it would be painful to go through and give names to every constraint (due to their volume, as well as how they're generated.)
Not unless you implement it yourself. Unsat core extraction requires labeling the constraints, see top of page 67 of this document: http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf
Having said that, you can build a "database" of your assertions by defining your own version of add that first makes up a name and inserts it, and then do the reverse lookup in a function my_unsat_core that you would similarly define. If you were to implement this in a generic way, Z3 folks might be interested in incorporating it into their API as well. Would be a nice addition.

Use z3 to Prove Identity of Boolean/Arithmetic Formula

I'm trying to use z3 to prove the following identity:
x+y == x^y + 2*(x&y)
That is, we can replace any addition with a mixture of boolean and arithmetic instructions (example taken from Chapter 2.2, Hacker's Delight).
I'm using the following z3 python snippet:
from z3 import *
x = BitVec("x", 32)
y = BitVec("y", 32)
lhs = x ^ y + (2*(x&y))
rhs = x + y
s = Solver()
s.add(lhs != rhs)
print s.check()
print s.model()
However, z3 gives me this:
sat
[y = 1509949440, x = 1040187384]
So I suppose I'm somehow using the API incorrectly. Any idea what my error is?
Apparently it is an issue with the precedence of the ^ operator. Using
lhs = (x ^ y) + (2*(x&y))
makes the example work for me.

Writing a function for x * sin(3/x) in python

I have to write a function, s(x) = x * sin(3/x) in python that is capable of taking single values or vectors/arrays, but I'm having a little trouble handling the cases when x is zero (or has an element that's zero). This is what I have so far:
def s(x):
result = zeros(size(x))
for a in range(0,size(x)):
if (x[a] == 0):
result[a] = 0
else:
result[a] = float(x[a] * sin(3.0/x[a]))
return result
Which...doesn't work for x = 0. And it's kinda messy. Even worse, I'm unable to use sympy's integrate function on it, or use it in my own simpson/trapezoidal rule code. Any ideas?
When I use integrate() on this function, I get the following error message: "Symbol" object does not support indexing.
This takes about 30 seconds per integrate call:
import sympy as sp
x = sp.Symbol('x')
int2 = sp.integrate(x*sp.sin(3./x),(x,0.000001,2)).evalf(8)
print int2
int1 = sp.integrate(x*sp.sin(3./x),(x,0,2)).evalf(8)
print int1
The results are:
1.0996940
-4.5*Si(zoo) + 8.1682775
Clearly you want to start the integration from a small positive number to avoid the problem at x = 0.
You can also assign x*sin(3./x) to a variable, e.g.:
s = x*sin(3./x)
int1 = sp.integrate(s, (x, 0.00001, 2))
My original answer using scipy to compute the integral:
import scipy.integrate
import math
def s(x):
if abs(x) < 0.00001:
return 0
else:
return x*math.sin(3.0/x)
s_exact = scipy.integrate.quad(s, 0, 2)
print s_exact
See the scipy docs for more integration options.
If you want to use SymPy's integrate, you need a symbolic function. A wrong value at a point doesn't really matter for integration (at least mathematically), so you shouldn't worry about it.
It seems there is a bug in SymPy that gives an answer in terms of zoo at 0, because it isn't using limit correctly. You'll need to compute the limits manually. For example, the integral from 0 to 1:
In [14]: res = integrate(x*sin(3/x), x)
In [15]: ans = limit(res, x, 1) - limit(res, x, 0)
In [16]: ans
Out[16]:
9⋅π 3⋅cos(3) sin(3) 9⋅Si(3)
- ─── + ──────── + ────── + ───────
4 2 2 2
In [17]: ans.evalf()
Out[17]: -0.164075835450162

Categories

Resources