I would like to define a piece-wise (linear) function in Z3py, for example, the function f(x) has the form
f(x) = a*x + b when 0 <= x <= 1
f(x) = exp(c*x) when 1 < x <= 2
f(x) = 1/(1+10^x) when 2 < x <= 3
etc.
where a, b and c are constants.
I guess the z3.If() function will be relevant, but as the number of pieces grows, the expression gets convoluted.
My questions is, does Z3pyprovides the if-else statement, or is there an elegant way to define piece-wise function in Z3py?
Yes, Z3 supports if-then-elses and in Python they can be constructed using the If function. An example from the documentation of If:
>>> x = Int('x')
>>> y = Int('y')
>>> max = If(x > y, x, y)
max = If(x > y, x, y)
Related
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.)
I was checking the sort for some operations in z3py and ran into the following:
x = Int('x')
y = Int('y')
print((1 + (2 + (x*(y**2)))).sort())
which outputs
Real
Why does the type of the expression result in a Real?
It's because the ** (exponentiation) operator always returns a Real in z3, even if the arguments are integers. Note that if the second argument is negative, then the result will not be an integer.
Compare:
>>> from z3 import *
>>> x, y, z = Ints('x y z')
>>> s = Solver()
>>> s.add(And(x == 2, y == -1, z == x ** y))
>>> print(s.check())
unsat
to:
>>> from z3 import *
>>> x, y = Ints('x y')
>>> z = Real('z')
>>> s = Solver()
>>> s.add(And(x == 2, y == -1, z == x ** y))
>>> print(s.check())
sat
>>> print(s.model())
[z = 1/2, y = -1, x = 2]
If you want an integer-only producing version of exponentiation, you can code it yourself by enforcing all results to be equal to some existential Int.
Note that the power operator is usually difficult to deal with in SMT solvers due to non-linearity, and undecidable in general due to the undecidability of Diophantine equations. So unless the constraints are easy enough you'll most likely get unknown as an answer at best, or the solver will loop forever.
I want to find a maximal interval in which an expression e is true for all x. A way to write such a formula should be: Exists d : ForAll x in (-d,d) . e and ForAll x not in (-d,d) . !e.
To get such a d, the formula f in Z3 (looking at the one above) could be the following:
from __future__ import division
from z3 import *
x = Real('x')
delta = Real('d')
s = Solver()
e = And(1/10000*x**2 > 0, 1/5000*x**3 + -1/5000*x**2 < 0)
f = ForAll(x,
And(Implies(And(delta > 0,
-delta < x, x < delta,
x != 0),
e),
Implies(And(delta > 0,
Or(x > delta, x < -delta),
x != 0),
Not(e))
)
)
s.add(Not(f))
s.check()
print s.model()
Which outputs [d = 1/4].
To check it, I set delta = RealVal('1/4'), drop the ForAll quantifier from f and I get x = 1/2. I replace delta with 1/2 and get 3/4, then 7/8 and so on. The bound should be 1. Can I get Z3 to output that immediately?
If you do the math yourself, you can see that the solution is x != 0, x < 1. Or you can simply ask Wolfram Alpha to do it for you. So, there's no such delta.
The issue you're having is that you're asserting:
s.add(Not(f))
This turns the universal quantification on x into an existential; asking z3 to find a delta such that there is some x that fits the bill. (That is, you're negating your whole formula.) Instead, you should do:
s.add(delta > 0, f)
which also makes sure that delta is positive. With that change, z3 will correctly respond:
unsat
(And then you'll get an error for the call to s.model(), you should only call s.model() if the previous call to s.check() returns sat.)
This script
from z3 import *
solver = z3.Solver()
x = Int('x')
def f(y):
return y+y
solver.add(x >= 0, x < 10, Exists(x, f(x) == 4) )
print solver.check()
print solver.model()
gives me
sat
[x = 0]
as an answer. This is not what I want or expect. As an answer I would like to see
sat
[x = 2]
I found two other posts going in a similar direction((Z3Py) declaring function and Quantifier in Z3), but something doesn't work out.
How do you use the existantial quantifier in this case to get an adequate answer?
The existential binds a different x whose scope is limited to the body of the formula. Hence, your constraints are effectively (0 ≤ x < 10) ∧ (∃ x' . f(x') == 4). Both conjuncts are satisfied by a model in which x = 0; in particular, the second conjunct is satisfied in this model because x' could be 2.
It seems that you want to constrain x further, not only by the inequality. Try the following (not tested)
solver.add(x >= 0, x < 10, f(x) == 4)
and then print the model.
I was trying to translate the following MATLAB code to tensorflow:
WW = sum(W.^2, 1); % ( 1 x D^(l)= sum( (D^(l-1) x D^(l)), 1 )
XX = sum(A.^2, 2); % (M x 1) = sum( (M x D^(l-1)), 2 )
bsxfun(#plus, WW, XX) ; % (M x D^(l)) - (M x D^(l)) = (M x D^(l-1)) * (D^(l-1) x D^(l)) - (M x D^(l))
which is very simple MATLAB code and was wondering if there was an equivalent code in TensorFlow. Ideally, W and/or X should be tf.Variable(init) variables because I'd like to compute the derivatives with respect to each variable.
Tensorflow, like NumPy, does broadcasting.
You can do
WW + XX
and it'll figure out the sizes itself
See the documentation here