Closed jendavis closed 5 years ago
The current arithmetic solver is highly incomplete for non-linear integer arithmetic. Only formulas that are purely over the reals are solved using a complete stand-alone solver. Note that non-linear integer arithmetic and by extension non-linear mixed integer/real arithmetic is undecidable. The solver makes a best effort attempt. We hope to avoid missing answers to such simple queries as in this example in newer versions of the solver. Hope this helps
Then perhaps my question is more about how to_real works. I thought that by using to_real, the assertion would be handled the same as it would for reals (in which case Z3 determined the formula was satisfiable). But that's not what happened.
How does to_real work? How is it implemented?
to_real is a built-in function. It coerces an integer to real sort. The value of (to_real b) still has to be integral, that is, it has to be -2, -1, 0, 1, 2, … and cannot be 1/2 or 7/8 or sqrt(2). The front-end of Z3 inserts coercions automatically, so if you write ( a b), where a is declared as Real and b as Int, it is parsed as ( a (to_real b)). The SMT-LIB standard includes a definition of to_real, on http://smtlib.cs.uiowa.edu/theories-Reals_Ints.shtml
OK, that gives me a little more insight at least. And it's good to know that I don't need to even bother with to_real and to_int since they are inserted automatically.
Here is some observed behavior for a simple nonlinear formula, a*b > 0. I'm using the Z3 tutorial version of Z3 (located at https://rise4fun.com/z3/tutorial) to run these examples.
Over the reals, Z3 determines this is SAT -- no problem.
(declare-const a Real) (declare-const b Real) (assert (> (* a b) 0)) (check-sat)
However, if I start with 'a' as an Int and then convert it to a Real, Z3 returns unknown. Why is this?
(declare-const a Int) (declare-const b Real) (assert (> (* (to_real a) b) 0)) (check-sat)
The above information is enough to understand my question and issue. However, I've included a few other related examples, which also may be useful to the reviewer.
Over the integers, Z3 determines the formula is SAT.
(declare-const a Int) (declare-const b Int) (assert (> (* a b) 0)) (check-sat)
If I start with b as a Real and then convert it to an Int, Z3 determines it is sat--great!
(declare-const a Int) (declare-const b Real) (assert (> (* a (to_int b)) 0)) (check-sat)
If I mix Int and Real without conversion, Z3 returns unknown--this is not a surprise.
(declare-const a Int) (declare-const b Real) (assert (> (* a b) 0)) (check-sat)
Thanks for evaluating this!