How to check the theorem that involves some trigonometry with Z3 prover? - z3

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.

Related

Best Z3 tactics for elementary algebra of fields

I want to use Z3 to proof validity of statements like this:
∀ a b: ℤ, ~ b = 0 -> (a / b) ^ 2. = (a * a) / (b * b)
Or in SMT-LIB format:
(declare-fun b () Int)
(declare-fun a () Int)
(assert (=> (= b 0) false))
(assert (let ((a!1 (= (^ (/ (to_real a) (to_real b)) 2.0)
(/ (to_real (* a a)) (to_real (* b b))))))
(not a!1)))
(check-sat)
But I get timeout with the default tactic. I guess Z3 is wasting its time trying to instantiate numbers in order to find a solution. But I'm only interested in unsat output since the problem is generalized and a sat output doesn't mean anything. What combination of tactics I should use to find validity of simple algebraic statements like this?
When I run your script, I get unsat pretty quickly:
$ time z3 a.smt2
unsat
z3 a.smt2 0.17s user 0.01s system 97% cpu 0.191 total
Perhaps your z3 is too old? Here's the version I have:
$ z3 --version
Z3 version 4.12.0 - 64 bit
Try upgrading, I think the latest released version is 4.12.1.
If the issue persists and you have the latest z3, you should report this as a regression at https://github.com/Z3Prover/z3/issues

How to express set membership in SMTLIB format in Z3?

I'm trying to use the SMTLIB format to express set membership in Z3:
(declare-const a (Set Int))
;; the next two lines parse correctly in CVC4, but not Z3:
(assert (= a (as emptyset (Set Int))))
(assert (member 12 a))
;; these work in both solvers
(assert (= a (union a a)))
(assert (subset a a))
(assert (= a (intersection a a)))
(check-sat)
The functions emptyset and member seem to parse as expected in CVC4, but not in Z3.
From checking the API (e.g., here: https://z3prover.github.io/api/html/group__capi.html), Z3 does support empty sets and membership programatically, but how does one express these in SMTLIB syntax?
It's indeed annoying z3 and CVC4 use slightly different notations for sets. In z3, a set is essentially an array with the range of bool. Based on this analogy, your program is coded as:
(declare-const a (Set Int))
(assert (= a ((as const (Set Int)) false)))
(assert (select a 12))
(assert (= a (union a a)))
(assert (subset a a))
(assert (= a (intersection a a)))
(check-sat)
which z3 accepts as is and produces unsat. But you'll find that CVC4 doesn't like this program now.
It would be great if the SMTLib movement standardized the theory of sets (http://smtlib.cs.uiowa.edu/) and there has indeed been a proposal along these lines (https://www.kroening.com/smt-lib-lsm.pdf) but I don't think it has been adopted by solvers nor sanctioned by the SMTLib committee yet.

Z3 support for exponentials

I'm new to Z3 and I'm trying to understand how it works, and what it can and cannot do. I know that Z3 has at least some support for exponentials through the power (^) operator (see Z3py returns unknown for equation using pow() function, How to represent logarithmic formula in z3py, and Use Z3 and SMT-LIB to define sqrt function with a real number). What I'm unclear on is how extensive this support is, and what kind of inferences z3 can make about exponentials.
Here's a simple example involving exponentials which z3 can analyze. We define an exponential function, and then ask it to verify that exp(0) == 1:
(define-fun exp ((x Real)) Real
(^ 2.718281828459045 x))
(declare-fun x1 () Real)
(declare-fun y1 () Real)
(assert (= y1 (exp x1)))
(assert (not (=> (= x1 0.0) (= y1 1.0))))
(check-sat)
(exit)
Z3 returns unsat, as expected. On the other hand, here's a simple example which Z3 can't analyze:
(define-fun exp ((x Real)) Real
(^ 2.718281828459045 x))
(declare-fun x1 () Real)
(declare-fun y1 () Real)
(assert (= y1 (exp x1)))
(assert (not (< y1 0.0)))
(check-sat)
(exit)
This should be satisfiable, since literally any value for x1 would give y1 > 0. However, Z3 returns unknown. Naively I might have expected that Z3 would be able to analyze this, given that it could analyze the first example.
I realize this question is a bit broad, but: can anyone give me any insight into how Z3 handles exponentials, and (more specifically) why it can solve the first example I gave but not the second?
It is hard to say in general, since non-linear solving is challenging, but the case you presented is actually not so mysterious. You wrote:
(assert (= y (exp x)))
(assert (not (=> (= x 0) (= y 1))))
Z3 is going to simplify the second assertion, yielding:
(assert (= y (exp x)))
(assert (= x 0))
(assert (not (= y 1)))
Then it will propagate the first equality, yielding:
(assert (= y (exp 0)))
(assert (not (= y 1)))
Now when exp is expanded, you have a case of constant^constant, which Z3 can handle (for integer exponents, etc).
For the second case, you are asking it a very very basic question about variable exponents, and Z3 immediately barfs. That's not too odd, since so many questions about variable exponents are either known uncomputable or unknown but hard.

Z3 : strange behavior with non linear arithmetic

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

Does z3 support rational arithmetic for its input constraints?

In fact, does the SMT-LIB standard have a rational (not just real) sort? Going by its website, it does not.
If x is a rational and we have a constraint x^2 = 2, then we should get back ``unsatisfiable''. The closest I could get to encoding that constraint is the following:
;;(set-logic QF_NRA) ;; intentionally commented out
(declare-const x Real)
(assert (= (* x x) 2.0))
(check-sat)
(get-model)
for which z3 returns a solution, as there is a solution (irrational) in the reals. I do understand that z3 has its own rational library, which it uses, for instance, when solving QF_LRA constraints using an adaptation of the Simplex algorithm. On a related note, is there an SMT solver that supports rationals at the input level?
I'm sure it's possible to define a Rational sort using two integers as suggested by Nikolaj -- I would be interested to see that. It might be easier to just use the Real sort, and any time you want a rational, assert that it's equal to the ratio of two Ints. For example:
(set-option :pp.decimal true)
(declare-const x Real)
(declare-const p Int)
(declare-const q Int)
(assert (> q 0))
(assert (= x (/ p q)))
(assert (= x 0.5))
(check-sat)
(get-value (x p q))
This quickly comes back with
sat
((x 0.5)
(p 1)
(q 2))

Resources