How can I simplify the following expression using Z3 Solver?
(declare-const c0 Int)
(declare-const c1 Int)
(declare-const c2 Int)
(assert (let ((a!1 (to_real (+ (* (* 2 c0) c2)
(* (* 2 c0) c1)
(* 2 c1 c2)
(* c0 (- c0 1))
(* c1 (- c1 1))))))
(let ((a!2 (/ (to_real (* (* 2 c0) c2)) a!1)))
(and (or (and (<= c2 1) (>= c2 1) (<= c0 2) (>= c0 2) (<= c1 3) (>= c1 3))
(and (<= c2 1) (>= c2 1) (<= c0 3) (>= c0 3) (<= c1 2) (>= c1 2)))
(= (/ 2.0 15.0) a!2))))
)
(apply (then qe propagate-values (repeat (then ctx-solver-simplify propagate-ineqs) 10)))
Link : http://rise4fun.com/Z3/u7F7
I tried all the possible tactics that I know about and yet ended up causing time out by the solver. Is there a way that I can avoid time out? Is it suppose to return false as a result in Java API?
It's hard to tell what's going on just by looking at that code. But I'd think that to_real might be the problematic part, as conversion between domains tend to generate non-linear constraints that can cause complexity problems.
I'd give it a try using purely Reals (i.e., declare c0, c1.. as Reals; and remove calls to to_real.)
If you do need integers/reals mixed; make sure that mixing is done at the leaves (i.e., at constants); or at the very-top, as much as you can push the conversions around; instead of at intermediate values.
But I'd guess that sticking to Reals would be the way to go here if your problem space allows for that.
The example uses non-linear integer arithmetic. Unfortunately, it is easy to produce examples in this domain where Z3 does not terminate. The ctx-solver-simplify routine calls the SMT solver multiple times and in each invocation has to check satisfiability of some combination of the non-linear constraints.
Related
I'm trying to proof the following proposition with Z3 Theorem Prover:
|CA|^2 = |AB|^2 + |BC|^2,
|AB| = cos(alpha),
|BC| = sin(alpha)
=>
|CA| = 1
What exactly I do:
(declare-const AB Real)
(declare-const BC Real)
(declare-const CA Real)
(declare-const alpha Real)
(assert (and (>= AB 0) (>= BC 0) (>= CA 0)) )
(assert (= (^ CA 2) (+ (^ AB 2) (^ BC 2))) )
(assert (= AB (cos alpha)) )
(assert (= BC (sin alpha)) )
(assert (not (= CA 1) ))
(check-sat)
I expect unsat but got unknown. Also I know that problem is concentrated in the part with functions sin and cos.
What am I doing wrong? Is it possible to do something at all?
Thanks for help!
z3 has a rather limited understanding of sin and cos, and I wouldn't expect it to be able to decide all such problems. For a detailed discussion on this, see https://github.com/Z3Prover/z3/issues/680. For complicated queries, it's normal for you to get unknown as an answer.
Having said that, you're in luck! Z3 can actually correctly answer your particular query; but you have to use the correct incantation. Instead of:
(check-sat)
Use
(check-sat-using qfnra-nlsat)
and z3 correctly deduces unsat for this problem. This form of check-sat tells z3 to use the internal nl-sat engine for nonlinear real arithmetic.
I am trying to find a solution for the function penta(n) = (n * (3n -1)) / 2 and where penta (z) = penta (a) + penta(b) for all number positives. That works until the integer division (div) is part ofthe definition, but when it is added in the definition I either got a timeout or an unknown.
I would expect to get 8 , 7 , 4. Any idea on what I did wrongly?
(declare-const a Int)
(declare-const b Int)
(declare-const z Int)
(define-fun penta ((n Int)) Int (div (* (- (* 3 n ) 1) n) 2) )
(assert (= (penta z) (+ (penta a) (penta b)) ))
(assert (> a 1))
(assert (> b 1))
(assert (> z 1))
(check-sat)
(get-model)
I am using the version on the http://rise4fun.com/Z3 website and the version 4.1 (x64).
The main issue is that the problem uses integer multiplication between two non-numeric arguments. There are no decision procedures for general Diophantine problems so Z3 does a best effort, which does not favor model enumeration.
When you don't use integer division, Z3 will try a partial heuristic based on
converting the problem into finite domain bit-vectors to find models. It invokes
this heuristic by performing a syntactic check on the formulas. THe syntactic check fails when you use the operator (div .. 2).
You can encode (div x 2) so the heuristic picks up the problem
by introducing fresh variables and bounding them:
(declare-const penta_z Int)
(declare-const penta_a Int)
(declare-const penta_b Int)
(assert (or (= (* 2 penta_z) (penta z)) (= (+ 1 (* 2 penta_z)) (penta z))))
(assert (or (= (* 2 penta_a) (penta a)) (= (+ 1 (* 2 penta_a)) (penta a))))
(assert (or (= (* 2 penta_b) (penta b)) (= (+ 1 (* 2 penta_b)) (penta b))))
(assert (= penta_z (+ penta_a penta_b) ))
(assert (> a 1))
(assert (> b 1))
(assert (> z 1))
(assert (>= penta_z 0))
(assert (<= penta_z 100))
You can also directly encode your problem using bit-vectors although this starts getting error prone because you have to deal with how to handle overflows.
Executing the following query with the Z3 solver:
(declare-const c0 Int)
(declare-const c1 Int)
(declare-const c2 Int)
(assert (exists ((c0_s Int) (c1_s Int) (c2_s Int))
(and
(= (+ c0 c1 c2) 5) (>= c0 0) (>= c1 1) (>= c2 1)
(= c0_s c0) (= c1_s (- c1 1)) (= c2_s (+ c2 1))
(= c2_s 3) (= (+ c0_s c1_s) 2)
))
)
(apply (then qe ctx-solver-simplify propagate-ineqs))
produces the following output:
(goals
(goal
(>= c0 0)
(<= c0 2)
(>= c1 1)
(<= c1 3)
(<= (+ (* (- 1) c0) (* (- 1) c1)) (- 3))
(<= (+ c1 c0) 3)
(= c2 2)
:precision precise :depth 3)
)
where I was expecting a result from the Z3 solver like this:
(goals
(goal
(>= c0 0)
(<= c0 2)
(>= c1 1)
(<= c1 3)
(= (+ c1 c0) 3)
(= c2 2)
:precision precise :depth 3)
)
Can anyone explain why Z3 is producing such a complex result instead of what I expected? Is there a way to get Z3 to simplify this output?
You may get a more detailed answer from a member of the core Z3 team, but from my experience working with Z3's integer solver at a low level, I can give a bit of intuition as to why this is happening.
Briefly, in order to solve integer equations, Z3's integer theory solver expects all of its constraints to appear in a very particular and restricted form. Expressions that do not follow this form must be rewritten before they are presented to the solver. Normally this happens internally by a theory rewriter, and any expression can be used in the input constraint set without issue.
The restrictions that apply here (that I am aware of), which help explain why you are seeing this strange-looking output, are as follows:
The integer solver can represent an equality constraint (= a b) as two separate inequality constraints (<= a b) and (>= a b). This is why you're seeing two separate constraints over your variables in the model instead of just one equality.
The integer solver rewrites subtractions, or negated terms, as multiplication by -1. This is why you are seeing these negations in your first constraint, and why the operator is addition instead of subtraction.
Arithmetic expressions are rewritten so that the second argument to a comparison operator is always a constant value.
In short, what you're seeing is likely an artifact of how the arithmetic theory solver represents constraints internally.
Since the output of your instance is a goal and not a model or proof, these expressions may not have been fully simplified yet, as I believe that intermediate goals are not always simplified (but I don't have experience with this part of the solver).
I am just starting to use Z3 (v4.4.0), and I wanted to try one of the tutorial examples :
(declare-const a Int)
(assert (> (* a a) 3))
(check-sat)
(get-model)
(echo "Z3 will fail in the next example...")
(declare-const b Real)
(declare-const c Real)
(assert (= (+ (* b b b) (* b c)) 3.0))
(check-sat)
As said, the second example fails with "unknown", and by increasing the verbose level (to 3) I think I understand why : some problem with the simplifying process, then the tactic fails.
In order to have a better idea of the problem (and a shorter output), I decided to remove the first part of the code to test only the failed part :
(echo "Z3 will fail in the next example...")
(declare-const b Real)
(declare-const c Real)
(assert (= (+ (* b b b) (* b c)) 3.0))
(check-sat)
But magically, now I get "sat". I am not sure about how Z3 chooses its tactic when it is about non linear arithmetic, but can the problem be from Z3 choosing a tactic for the first formula that is useless for the second one ?
Thanks in advance
The second encoding is not equivalent to the first, hence the different behavior. The second encoding does not include the constraint (assert (> (* a a) 3)), so Z3 can find it is satisfiable that b^3 + b*c = 3 for some choice of reals b and c. However, when it has the constraint that a^2 > 3 for some integer a, it fails to find it's satisfiable, even though the two assertions are independent from one another.
For this problem, it's essentially that Z3 by default will not use the nonlinear real arithmetic solver (which is complete) when it encounters reals mixed with integers. Here's an example of how to force it using qfnra-nlsat (rise4fun link: http://rise4fun.com/Z3/KDRP ):
(declare-const a Int)
;(assert (> (* a a) 3))
;(check-sat)
;(get-model)
(echo "Z3 will fail in the next example...")
(declare-const b Real)
(declare-const c Real)
(push)
(assert (and (> (* a a) 3) (= (+ (* b b b) (* b c)) 3.0)))
(check-sat)
(check-sat-using qfnra-nlsat) ; force using nonlinear solver for nonlinear real arithimetic (coerce integers to reals)
(get-model)
(pop)
(assert (= (+ (* b b b) (* b c)) 3.0))
(check-sat)
(get-model)
Likewise, if you just change (declare-const a Int) to (declare-const a Real), it will by default pick the correct solver that can handle this. So yes, in essence this has to do with what solver is getting picked, which is determined in part by the sorts of the underlying terms.
Related Q/A: Combining nonlinear Real with linear Int
This is the reduction of a more interesting problem, in which the missing property was (for positive k,M and N), that ((k % M) * N) < M*N. Below is an encoding of the simpler problem that a <= b ==> (a*c) <= (b*c). Such a query succeeds (we get unsat), but if the expression b is replaced by b+1 (as in the second query below) then we get unknown, which seems surprising. Is this the expected behaviour? Are there options to improve the handling of such inequalities? I tried with and without configuration options, and various versions of Z3, including the current unstable branch. Any tips would be much appreciated!
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(assert (> a 0))
(assert (> b 0))
(assert (> c 0))
(assert (<= a b))
(assert (not (<= (* a c) (* b c))))
(check-sat)
(assert (<= a (+ b 1)))
(assert (not (<= (* a c) (* (+ b 1) c))))
(check-sat)
This falls into nonlinear integer arithmetic (which has an undecidable decision problem, see, e.g., How does Z3 handle non-linear integer arithmetic? ), so it's actually not too surprising Z3 returns unknown for some examples, although I guess a bit surprising that it toggled between unsat and unknown for quite similar examples.
If it works for your application, you can try a type coercion: encode the constants as Real instead of Int. This will allow you to use Z3's complete solver for nonlinear real arithmetic and returns unsat with check-sat.
Alternatively, you can force Z3 to use the nonlinear solver even for the integer encoding with (check-sat-using qfnra-nlsat) as in the following based on your example (rise4fun link: http://rise4fun.com/Z3/87GW ):
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(assert (> a 0))
(assert (> b 0))
(assert (> c 0))
(assert (<= a b))
(assert (not (<= (* a c) (* b c))))
;(check-sat)
(check-sat-using qfnra-nlsat) ; unsat
(assert (<= a (+ b 1)))
(assert (not (<= (* a c) (* (+ b 1) c))))
; (check-sat)
(check-sat-using qfnra-nlsat) ; unsat
Some more questions and answers on similar subjects:
Combining nonlinear Real with linear Int
z3 fails with this system of equations
Using Z3Py online to prove that n^5 <= 5 ^n for n >= 5
Can z3 always give result when handling nonlinear real arithmetic
Z3 Theorem Prover: Pythagorean Theorem (Non-Linear Artithmetic)