Simplifying integer formulas in Z3 - z3

After applying quantifier elimination in Z3 to a linear arithmetic formula h, I'm getting a 30-line or so formula. It turns out this formula is equivalent to h2=And(n>2, i>=0, i<=n-2), which I would much prefer as an output.
I tried ctx-solver-simplify; I'm getting:
And(Not(n <= 2), Or(Not(i >= 1), Not(n + -1*i <= 1)), i >= 0)
Now, Not(n<=2) can be more succinctly expressed as n>=3, Not(n + -1*i <= 1) as n-i>=2, and in this formula i >= 1 is not needed.
Repeat(Then('nnf','ctx-solver-simplify')) does a little better (by getting rid of i>=1).
Is there a better simplification tactic?
Similarly, is there a tactic that would transform Or(x==0, x==1, x==2, x==3) into And(x>=0,x<=3)?

My current best solution is to use Repeat(Then(OrElse('split-clause', 'nnf'), 'propagate-ineqs', 'ctx-solver-simplify')), with the latest unstable version of Z3 (where the bug in ctx-solver-simplify has been corrected).

Related

Does Z3 have troubles with division?

During a project, I encountered a phenomenon I can't explain. It is boiled down in the following minimal example (using Z3Py) which should be unsat but returns a model.
from z3 import *
solver = Solver()
x = Int("x")
# The next proposition is clearly unsatisfiable
solver.add(And(x > 0, (x + 1) * (1 / (x + 1)) != 1))
solver.add(x == 1)
# Still, Z3 provides a "model"
print(solver.check())
print(solver.model())
Is there anything I am missing? Is it forbidden to use division in certain situations?
Z3 version: 4.8.14
Python version: 3.9
Note that when you use / over integers, than the result is an integer itself. That is, we use integer division; which in SMTLib is defined to be the Euclidian one. See https://smtlib.cs.uiowa.edu/theories-Ints.shtml for details.
This means that the expression 1 / (1+1) reduces to 0, since division produces an integer. So you end up with 0 != 1, which is true, and thus your problem is satisfiable.
If you want division to produce reals, then you should either start with a real x (i.e., x = Real("x")) in which case your problem will be unsat; or convert the arguments to be over the reals, via an expression of the form ToReal(x); which again will produce unsat for your problem.
So, in the first case, your modification will be:
x = Real('x')
casting the problem over reals. Or, if you want to keep x an integer, yet the division to be over the reals, you should use:
solver.add(And(x > 0, ToReal(x + 1) * (1 / ToReal(x + 1)) != 1))
which does the conversion.
I should note that mixing integers and reals in this way can lead to hard problems in general, and the solver might end up reporting unknown. But that's besides the point for your particular question here.

Maxima numerical integration syntax

I'm trying to obtain a numerical solution to the following integral:
1
The correct answer is -0.324 + 0.382i but as seen below I am not getting a numerical answer and would appreciate help with the Maxima syntax.
2
Perhaps related to why I am not getting a numerical output are two specific questions:
I read that e and i in Maxima need to be preceded by % in input but should these also appear as %e and %i as seen in the Maxima output?
Why is dy missing at the end of the integral in the Maxima output?
Thank you!
Looks to me like your input is okay, however, the function to compute approximations to integrals is named quad_qags. (There are actually several related functions. See ?? quad_ for more info.) Also, a wrinkle here is that the integrand is a complex-valued function (of a real variable), and quad_qags can only work on real-valued integrands, so we'll have to work around it. Here's how I would arrange it.
myintegrand: exp(%i*(1 + %i*y))/(1 + %i*y + 1/(1 + %i*y));
result_realpart: quad_qags (realpart (myintegrand), y, 0, 6);
result_imagpart: quad_qags (imagpart (myintegrand), y, 0, 6);
result: result_realpart[1] + %i*result_imagpart[1];
I get 0.3243496676292901*%i + 0.3820529930785175 as the final result. That's a little different from what you said; maybe a minus sign went missing? or there's a missing or extra factor of %i?
A quick approximation
0.1 * lsum (x, x, float (rectform (makelist (ev (myintegrand, y = k/10), k, 0, 60))));
seems to show the result from quad_qags is reasonable.

Normal form of formula returned by Z3's qe tactic

I'm using Z3's quantifier elimination tactic via Z3py and have tried the following examples.
from z3 import *
x,y,xp,yp = Ints('x y xp yp')
t = Tactic('qe')
t(Exists((xp, yp), And(xp==x+1, yp==y+2, xp<=8, xp >=1, yp<=12, yp>=2)))
#returns: [[y <= 10, y >= 0, x <= 7, x >= 0]]
t(Exists((xp, yp), Implies(x<10 , And(xp==x+1, yp==y+2, xp<=8, xp >=1, yp<=12, yp>=2))))
#returns: [[Or(10 <= x, And(y <= 10, y >= 0, And(x <= 7, x >= 0)))]]
I think that the resultant formulas are in quantifier-free DNF(which is what I need), but I could not find anything in the API documentation that guarantees it. Does anyone know if qe always returns formulas in DNF?
Where can I(if at all) find such details regarding tactics without having to dig through the original source code?
EDIT: All formulas are restricted to linear integer arithmetic.
By design, tactics make "best effort." That is, while qe is designed to eliminate quantifiers, it may end up failing to do so, returning the goal stack unchanged.
Note that quantifier elimination is not just one tactic, but it is a whole collection of them, depending on what other theories are involved in your benchmark. See the directory: https://github.com/Z3Prover/z3/tree/master/src/qe

Signed division not working in z3py

I was trying to work with z3py. I came across a strange problem. I read that the operation / is treated as signed division for bit vectors in z3py. I was trying to give the following commands:
a = z3.BitVec('a',2)
b = z3.BitVec('b',2)
solver = z3.Solver()
solver.add((a + b)/2 == 3)
solver.check()
The result z3 gives is unsat
In my views this is not correct because it has a solution a = 2, b = 0, a = 2 in 2's complement means a = -2, so (a+b)/2 must be equal to -1 i.e. 3 by signed representation.
Can anyone please help me what is wrong here?
I finally found the solution myself!
The problem is in expression (a+b)/2. Here a and b are Bit Vectors of size 2. So the denominator 2 of the expression is also treated as a 2-bit Bit Vector by z3. So the 2 in denominator is actually -2. Thus the constraint I was trying to solve was (a+b)/(-2) == -1 This is actually unsat.

Minimum and maximum values of integer variable

Let's assume a very simple constraint: solve(x > 0 && x < 5).
Can Z3 (or any other SMT solver, or any other automatic technique)
compute the minimum and maximum values of (integer) variable x that satisfies the given constraints?
In our case, the minimum is 1 and the maximum is 4.
Z3 has not support for optimizing (maximizing/minimizing) objective functions or variables.
We plan to add this kind of capability, but it will not happen this year.
In the current version, we can "optimize" an objective function by solving several problems where in each iteration we add additional constraints. We know we found the optimal when the problem becomes unsatisfiable. Here is a small Python script that illustrates the idea. The script maximizes the value of a variable X. For minimization, we just have to replace s.add(X > last_model[X]) with s.add(X < last_model[X]). This script is very naive, it performs a "linear search". It can be improved in many ways, but it demonstrates the basic idea.
You can also try the script online at: http://rise4fun.com/Z3Py/KI1
See the following related question: Determine upper/lower bound for variables in an arbitrary propositional formula
from z3 import *
# Given formula F, find the model the maximizes the value of X
# using at-most M iterations.
def max(F, X, M):
s = Solver()
s.add(F)
last_model = None
i = 0
while True:
r = s.check()
if r == unsat:
if last_model != None:
return last_model
else:
return unsat
if r == unknown:
raise Z3Exception("failed")
last_model = s.model()
s.add(X > last_model[X])
i = i + 1
if (i > M):
raise Z3Exception("maximum not found, maximum number of iterations was reached")
x, y = Ints('x y')
F = [x > 0, x < 10, x == 2*y]
print max(F, x, 10000)
As Leonardo pointed out, this was discussed in detail before: Determine upper/lower bound for variables in an arbitrary propositional formula. Also see: How to optimize a piece of code in Z3? (PI_NON_NESTED_ARITH_WEIGHT related).
To summarize, one can either use a quantified formula, or go iteratively. Unfortunately, these techniques are not equivalent:
Quantified approach needs no iteration, and can find global min/max in a single call to the solver; at least in theory. However, it does give rise to harder formulas. So, the backend solver can time-out, or simply return "unknown".
Iterative approach creates simple formulas for the backend solver to deal with, but it can loop forever if there's no optimal value; simplest example being trying to find the largest Int value. Quantified version can solve this problem nicely by quickly telling you that there is no such value, while the iterative version would go on indefinitely. This can be a problem if you don't know ahead of time that your constraints do have an optimal solution. (Needless to say, the "sufficient" iteration count is typically hard to guess, and might depend on random factors, like the seed used by the solver.)
Also keep in mind that if there is a custom optimization algorithm for the problem domain at hand, it's unlikely that a general purpose SMT solver can outperform it.
z3 now supports optimization.
from z3 import *
o = Optimize()
x = Int( 'x' )
o.add(And(x > 0, x < 5))
o.maximize(x)
print(o.check()) # prints sat
print(o.model()) # prints [x = 4]
This particular problem is an integer program.

Resources