How to make quantifier elimination using Z3-Py? - z3

I am trying to obtain a quantifier-free formula using the following code:
S, E, I, R = Reals('S E I R')
b, n, s, g, m = Reals('b n s g m')
SS = Then('qe', 'smt').solver()
SS.add(Exists([S,E,I,R], And(m+g*R-m*S-b*I*S == 0,
b*I*S-(m+s)*E==0, s*E-(n+m)*I==0, n*I-(m+g)*R==0,
S > 0, I > 0, E > 0, R >0)))
SS.add(b > 0, n > 0, s >0 , g >0, m>0)
print SS
print SS.check()
but I am obtaining the output:
unknown
Please can you tell me what happens with my code? Many thanks.

Quantifier elimination works just for additive arithmetic. It does not eliminate quantifiers from formulas where variables are multiplied with other variables. This is why quantifier elimination does not produce a reduced formula for your problem.
Notice, however, that a formula Exists x . phi[x] is equi-satisfiable to a formula of the form
phi[x], so it should not be required to put an existential quantifier on your formula.
The nlsat strategy handles quantifier-free formulas over the reals with multiplication.

Related

Power and logarithm in Z3

I'm trying to learn Z3 and the following example baffles me:
from z3 import *
a = Int("a")
b = Int("b")
print(solve(2**a <= b))
print(solve(a > 0, b > 0, 2**a <= b))
I would expect it returns "[a = 1, b = 2]" but it instead returns "failed to solve".
Why cannot it be solved?
Is it possible to compute with powers and logarithms in Z3 at all? How do I find, say, the length of binary string representation of a number (log base 2)?
Long story short, z3 (or SMT solvers in general) cannot deal with non-linear constraints like this. Exponentiation/Logs etc are difficult to deal with, and there are no decision procedures for them over the integers. Even over reals they are difficult to handle. That is, the solver will apply some heuristics, which may or may not work. But for these sorts of constraints, SMT solvers are just not the right tool.
For an earlier answer on non-linear arithmetic in z3, see this answer: https://stackoverflow.com/a/13898524/936310
Here're some more details if you are interested. First, there is no power-operator for integers in SMTLib or z3. If you look at the generated program, you'll see that it's actually over real values:
from z3 import *
a = Int("a")
b = Int("b")
s = Solver()
s.add(2**a <= b)
print(s.sexpr())
print(s.check())
This prints:
(declare-fun b () Int)
(declare-fun a () Int)
(assert (<= (^ 2 a) (to_real b)))
unknown
Note the conversion to to_real. The ^ operator automatically creates a real. The way this would be solved is if the solver can come up with a solution over reals, and then checks to see if the result is an integer. Let's see what happens if we try with Reals:
from z3 import *
a = Real("a")
b = Real("b")
s = Solver()
s.add(2**a <= b)
print(s.check())
print(s.model())
This prints:
sat
[b = 1, a = 0]
Great! But you also wanted a > 0, b > 0; so let's add that:
from z3 import *
a = Real("a")
b = Real("b")
s = Solver()
s.add(2**a <= b)
s.add(a > 0)
s.add(b > 0)
print(s.check())
This prints:
unknown
So, the solver can't handle this case either. You can play around with tactics (qfnra-nlsat), but it's unlikely to handle problems of this sort in general. Again, refer to https://stackoverflow.com/a/13898524/936310 for details.

How to declare/use Arrays and Quantifiers in Z3Py?

I'm new to Z3py and I found an exercise where it would ask to check if some verification conditions were true. Up to this moment, the exercises I've done were basically to transform simple propositional formulas into z3py clauses, something like:
Propositional Formula would be:
(n>=4) -> (x = y +2)
Which would become in Z3Py:
n, x, y = Ints('n x y')
s.add(Implies(n>=5, x == y+3))
The conditions I'm presented now, introduce Arrays and Quantifiers and after spending hours trying to figure it out on the documentation around, I'm still not able to get it properly done.
For example, how would I do the same process above but with the following conditions:
n ≥ 1 ∧ i = 1 ∧ m = A[0]
i <= n ∧ ∀j. 0 ≤ j < i → m ≥ A[j]
A little snippet of what I think that is correctly done:
i, n = Ints('i n')
s.add(And(n>=1, i == 1, ???)
s.add(And(i<=n,Implies(???))
How should I replace the ??? so that the conditions would be correctly transformed into Z3Py?
Solution:
- The constraint
n ≥ 1 ∧ i = 1 ∧ m = A[0]
would become in Z3Py:
A = Array('A', IntSort(), IntSort()) //Array declaration
i, n, m, j = Ints('i n m j') //Ints declaration for both constraints
And(n>=1, i==1, m==A[0])
- The constraint
i <= n ∧ ∀j. 0 ≤ j < i → m ≥ A[j]
would become:
And(i<=n,ForAll(j,Implies(And(j>=0,j<i),m>=A[j])))
Your questions is quite ambiguous. Note that you've the constraints:
n ≥ 1 ∧ i = 1
and then
i <= n
but that consequent is already implied by the first, and hence is redundant. Meaning, if you add them both to the solver like you did with your s.add lines, then it won't really mean much of anything at all.
I'm guessing these two lines actually arise in different "subparts" of the problem, i.e., they aren't used together for the same verification goal. And, making an educated guess, you're trying to say something about the maximum element of an array; where i is some sort of a loop-counter. The first line is what happens before the loop starts, and the second is the invariant the loop-body ensures. If this is the case, you should be explicit about that.
Assuming this is the case, then these sorts of problems are usually modeled on the "body" of that loop, i.e., you need to show us exactly what sort of a "program" you're dealing with. That is, these constraints will only make sense in the presence of some sort of a transformation of your program variables.

Derivatives using indexed variables

As an example I want to try to find the partial derivatives of
f(x) = \sum_{i=1}^n x_i^2
in Maxima. (The expected output would be \frac{\partial f}{\partial x_k} = 2x_k) I have tried following, but it seems the indexed variables are not handled as I expected, can anyone explain what I am doing wrong?
The same command works if you replace n and k with actual numbers, but not in this form:
f(x) := 1/2 * sum( x[i]^2, i, 1, n);
print(diff(f(x),x[k]));
Try it online!
Maxima can't handle derivative with respect to a indexed variable by default. I wrote a couple of small packages to handle these problems. Perhaps this is useful to you.
See: https://pastebin.com/MmYJRqCq (sum_kron_delta, summation of Kronecker delta)
and: https://pastebin.com/UGCPgvAn (diff_sum, derivative of summation wrt indexed variable)
Here's an example applied to your problem. I'll assume you have downloaded the code above to your computer.
(%i1) load ("sum_kron_delta.mac");
(%o1) sum_kron_delta.mac
(%i2) load ("diff_sum.mac");
(%o2) diff_sum.mac
(%i3) 'diff ('sum (x[i]^2, i, 1, n), x[j]);
n
====
\
(%o3) 2 > x kron_delta(i, j)
/ i
====
i = 1
Note that you have to write 'diff('sum(... that is, with the quote mark ' to indicate that diff and sum are nouns (formal expressions) instead of verbs (functions which are called). This is necessary in the implementation of diff_sum and sum_kron_delta because they work with simplification rules. (It's a long story, which I can explain if there's interest.)
I see we got the kron_delta summation, but we need to cause the simplification rules to be applied. We could also write expand(%, 0, 0) here instead of ''%.
(%i4) ''%;
(%o4) 2 (if (1 <= j) and (j <= n) and %elementp(j, integers) then x else 0)
j
At this point we have the final result, which we can simplify further with additional data.
(%i5) assume (j >= 1, j <= n);
(%o5) [j >= 1, n >= j]
(%i6) ''%o4;
(%o6) 2 (if %elementp(j, integers) then x else 0)
j
(%i7) declare (j, integer);
(%o7) done
(%i8) ''%o6;
(%o8) 2 x
j
If this seems fruitful to you, I'll be happy to go into details.

Z3Py is not able to make certain proof?

I am trying to prove that
4*n^3*m+4*n*m^3 <= n^4+6*n^2*m^2+m^4
for all n, m reals; using Z3Py online.
I am using the code:
n, m = Reals('n m')
s = Solver()
s.add(ForAll([n, m], n**4+6*n**2*m**2+m**4 >= 4*n**3*m+4*n*m**3))
print s.check()
and the output is : unknown.
Please can you tell why Z3 does not obtain "sat".
Note that Z3 checks for "satisfiability" and not "validity".
A formula is valid if and only if the negation is not satisfiable (unsat).
So to prove validity of your inequality, you can add the negation of it to Z3 and see if it is able to reason about it.
n, m = Reals('n m')
s = Solver()
s.add(Not(n**4+6*n**2*m**2+m**4 >= 4*n**3*m+4*n*m**3))
print s.check()
It turns out that Z3 does establish that the inequality is unsat using the default Solver.

Using quantifer elimination with Z3 Python

I try to find the values for A,B,C,D satisfiying the formula g = And(ForAll([i, j, k], Implies(And(k <= 0, A * i + B * j + C * k + D <= 0), k + i - j <= 0)),Not(And(A==0,B==0,C==0))) using solve(g) . This has many possible solutions, one is A=1,B=-1,C=D=0 but Z3 can't seem to do this (solve(g) does not terminate).
Can Z3 do this kind of nonlinear (but simple) formula ? Perhaps I can specify some QE strategies or something for this ?
Z3 has a quantifier elimination tactic. We can enable it by creating a solver using:
s = Then('qe', 'smt').solver()
This command will create a solver that first applies quantifier elimination and then invokes a SMT solver. However, Z3 has very limited support for quantifier elimination of nonlinear formulas. Your examples is nonlinear because it contains: A * i + B * j + C * k + D <= 0.
So, the qe tactic will not be able to eliminate the quantifier.
It would be great if you could implement better QE support for nonlinear arithmetic.

Resources