Why does Z3 return unknown for this nonlinear integer arithmetic example? - z3

I have a simple example in nonlinear integer arithmetic, namely a search for Pythagorean triples. Based on what I read in related questions (see below), I'd expect Z3 to find a solution to this problem, but it returns 'unknown'. Here is the example in SMT-LIB v2:
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(declare-fun xSquared () Int)
(declare-fun ySquared () Int)
(declare-fun zSquared () Int)
(declare-fun xSquaredPlusYSquared () Int)
(assert (= xSquared (* x x)))
(assert (= ySquared (* y y)))
(assert (= zSquared (* z z)))
(assert (= xSquaredPlusYSquared (+ xSquared ySquared)))
(assert (and (> x 0) (> y 0) (> z 0) (= xSquaredPlusYSquared zSquared)))
(check-sat)
(exit)
There are a few related questions, most notably:
How does Z3 handle non-linear integer arithmetic?
Need help understanding the equation
Combining nonlinear Real with linear Int
Z3 support for nonlinear arithmetic
z3 limitations in handling nonlinear real arithmetics

It seems that Z3 won't attempt finding a solution by bit-blasting unless variables have a finite range. Replacing (check-sat) with the following command will find the solution:
(check-sat-using (then (using-params add-bounds :add-bound-lower -100 :add-bound-upper 100) smt))
Alternatively, one can add assert statements forcing each variable to have some finite range.

Related

Are equations with products of uninterpreted functions unsolvable in Z3

The following code
(declare-fun f (Int) Real)
(declare-fun g (Int) Real)
(declare-const x Int)
(declare-const y Int)
(assert (= (* (f x) (g y)) 1.0))
(check-sat)
(get-model)
returns "unknown", even though there is an obvious solution. Eliminating arguments to f and g (effectively making them constants?) results in "sat" with expected assignments. I guess, my question is: what is special about arithmetic with uninterpreted functions?
BTW, replacing * with + also results in "sat", so the issue is not about uninterpreted functions, per se, but about how they are combined.
Additional thoughts
Making the domain (very) finite does not help, e.g.,
(declare-fun f (Bool) Real)
(declare-fun g (Bool) Real)
(declare-const x Bool)
(declare-const y Bool)
(assert (= (* (f x) (g y)) 1.0))
(check-sat)
(get-model)
returns "unknown". This is odd given that f:Bool->Real is essentially just two variables f(False) and f(True) (of course, the solver has to recognize this).
Inability to handle non-linear arithmetic over real-valued uninterpreted functions is a very severe limitation because arrays are implemented as uninterpreted functions. So, for example,
(declare-const a (Array Int Real))
(assert (= (* (select a 1) (select a 1)) 1))
(check-sat)
(get-model)
returns "unknown". In other words, any non-linear algebraic expression on real array elements involving multiplication is unsolvable:'(
It's the non-liearity introduced by the multiplication that makes the problem hard to solve, not the uninterpreted functions. In fact, you can ask the solvers why by using the get-info command:
(set-logic QF_UFNIRA)
(declare-fun f (Int) Real)
(declare-fun g (Int) Real)
(declare-const x Int)
(declare-const y Int)
(assert (= (* (f x) (g y)) 1.0))
(check-sat)
(get-info :reason-unknown)
Here're some responses I got from various solvers:
Z3:
(:reason-unknown smt tactic failed to show goal to be sat/unsat (incomplete (theory arithmetic)))
CVC4:
(:reason-unknown incomplete)
MathSAT:
(error "sat, but with non-linear terms")
So, as the solvers themselves improve and start handling more nonliear arithmetic, you might get models eventually. But, in general, nonlinear problems will always be problematic as they are undecidable when integers are involved. (Since you can code Diophantine equations using non-linear terms.)
See also How does Z3 handle non-linear integer arithmetic? for a relevant discussion from 2012.
Removing uninterpreted functions
Even if you get rid of the uninterpreted functions, you'd still be in the unknown land, so long as you mix Int and Real types and non-linear terms:
(set-logic QF_NIRA)
(declare-const f Real)
(declare-const g Real)
(declare-const x Int)
(declare-const y Int)
(assert (= (+ (* f g) (to_real (+ x y))) 1.0))
(check-sat)
(get-info :reason-unknown)
Z3 says:
(:reason-unknown "smt tactic failed to show goal to be sat/unsat (incomplete (theory arithmetic))")
So, the issue would arise with mixed types and non-linear terms.

Z3 should be able to verify this program?

I am a beginner user of Z3. Recently, I have been using z3 to verify some problems. Here is one problem I tried: (x < 0 && y < 0) implies x/y >= 0, below are the programs I wrote:
(declare-const x Int)
(declare-const y Int)
(define-fun assumption() Bool
(and (< x 0) (< y 0))
)
(define-fun predicate() Bool
(<= 0 (div x y))
)
(assert (not (=> assumption predicate)))
(check-sat)
When I use 'z3 -smt2 filename' to verify this program, it works and return unsat. However, when I later modify the program to:
(declare-const x Int)
(declare-const y Int)
(define-fun assumption() Bool
(and (< x 0) (< y 0))
)
(define-fun predicate() Bool
(<= 0 (div (* -1 x) (* -1 y)))
)
(assert (not (=> assumption predicate)))
(check-sat)
This cause z3 to timeout when I changed 'x/y' to (-1 * x)/(-1 * y) and somehow I need to add -1 there. I am confused why this happened and why multiplied by a constant makes this problem more complex.
Can somebody help figure out why this happened?
Thank you!
There is very limited support for non-linear arithmetic, such as division where the divisor is a variable.
So Z3 will do a best effort, but in no way be sure to provide decisions on every formula with non-linear arithmetical operations. So for example, you can enter Diophantine equations into Z3, but not expect it to provide sat/unsat answers.
Rather than trying some infinite search, Z3 may prefer to give up and return unknown.
(Note: This is just a comment instead of an answer. I have to do so because I don't have sufficient reputation to add a comment.)
Here is the quote from the Z3 guide about integer division, modulo and reminder operators:
Z3 also has support for division, integer division, modulo and remainder operators. Internally, they are all mapped to multiplication.
(declare-const a Int)
(declare-const r1 Int)
(declare-const r2 Int)
(declare-const r3 Int)
(declare-const r4 Int)
(declare-const r5 Int)
(declare-const r6 Int)
(assert (= a 10))
(assert (= r1 (div a 4))) ; integer division
(assert (= r2 (mod a 4))) ; mod
(assert (= r3 (rem a 4))) ; remainder
(assert (= r4 (div a (- 4)))) ; integer division
(assert (= r5 (mod a (- 4)))) ; mod
(assert (= r6 (rem a (- 4)))) ; remainder
(declare-const b Real)
(declare-const c Real)
(assert (>= b (/ c 3.0)))
(assert (>= c 20.0))
(check-sat)
(get-model)
In Z3, division by zero is allowed, but the result is not specified. Division is not a partial function. Actually, in Z3 all functions are total, although the result may be underspecified in some cases like division by zero.
It is unclear what is the behavior when the arguments are negative. In other words, the mapping to multiplication for these operations is not clear.

Why operators '/' and 'div' in Z3 give different results?

I was trying to represent a real number with two integer numbers as using them as the numerator and the denominator of the real number. I wrote the following program:
(declare-const a Int)
(declare-const b Int)
(declare-const f Real)
(assert (= f (/ a b)))
(assert (= f 0.5))
(assert (> b 2))
(assert (> b a))
(check-sat)
(get-model)
The program returned SAT result as follows:
sat
(model
(define-fun f () Real
(/ 1.0 2.0))
(define-fun b () Int
4)
(define-fun a () Int
2)
)
However, if I write '(assert (= f (div a b)))' instead of '(assert (= f (/ a b)))', then the result is UNSAT. Why does not div return the same result?
Moreover, and the main concern for me, I did not find a way to use operator '/' in z3 .Net API. I can see only function MkDiv, which actually for operator 'div'. Is there a way so that I can apply operator '/' in the case of z3 .Net API? Thank you in advance.
Strictly speaking neither of these formulas is SMT-LIB2 compliant, because / is a function that takes two Real inputs and produces a Real output, whereas div is a function that takes two Int inputs and produces an Int (see SMT-LIB Theories). Z3 is more relaxed and automatically converts those objects. If we enable the option smtlib2_compliant=true then it will indeed report an error in both cases.
The reason for the div version being unsatisfiable is that there is indeed no solution where f is an integer according to (= f (/ a b)), but there is indeed no integer that satisfies (= f 0.5)

Smtlib trouble with the code

I have this following code
(set-logic QF_LIA)
(declare-fun w () Int)
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(assert (> x y))
(assert (> y z))
(push 1)
(assert (> z x))
(check-sat) ; unsat
(get-info :statistics)
(pop 1)
(push 1)
(check-sat (= x w)) ; sat
The code should return unsat on first (check-sat) and sat on second (check-sat), but I get unknown.
Can someone please tell me what's the problem. I am using windows 7, jSMTLIB using cygwin
Thanks
Saif
I don't know which backend in jSMTLIB you used for solving this. However, (check-sat (= x w)) is not even legal in SMT-LIB v2.
When I change that line to:
(assert (= x w))
(check-sat)
I get unsat and sat from Z3 web interface, which is of our expectation.
Note that (get-info :statistics) is also incorrect; the correct option is (get-info :all-statistics). You can read more about SMT-LIB v2 standard in their documentation.

Sort Mismatch in Model

I have analyzed a formula in QF_AUFLIA with z3. The result was sat. The model returned by (get-model) contained the following lines:
(define-fun PCsc5_ () Int
(ite (= 2 false) 23 33)
According to my understanding of the SMTLIBv2 language, this statement is malformed. = should only be applied to arguments of the same sort. However, 2 has sort Int and false has sort Bool.
When I feed back just these two lines to z3, it agrees with me by saying:
invalid function application, sort mismatch on argument at position 2
Is this a bug?
If not, how am I supposed to interpret (= 2 false)?
The problem was due to a type error in the input. Z3 3.2 misses some type errors in macro applications. This problem was fixed. The next release will correctly report the type error (aka sort mismatch). Here is a minimal example that exposes the problem:
(set-option :produce-models true)
(declare-fun q (Int) Bool)
;; p1 is a macro
(define-fun p1 ((z Int) (y Int)) Bool
(ite (q y) (= z 0) (= z 1)))
(declare-const a Int)
(declare-const b Bool)
(assert (p1 a b)) ;; << TYPE ERROR: b must be an Int
(check-sat)
(get-model)

Resources