z3 numerical constraints: which is better? - z3

Which of the following two ways of writing (equivalent) constraints is preferable (performance-wise) when solving integer-real constraints using z3?
(assert (=> (and (<= 0.0009765625 value) (< value 0.001953125)) (= new-value 0.0009765625)))
OR
(assert (=> (and (<= (/ 1.0 1024.0) value) (< value (/ 1.0 512.0))) (= new-value (/ 1.0 1024.0))))
Note that we have reciprocals of powers of two here (and there are many such constraints of this type involving both smaller and larger numbers).

Internally, Z3 converts all numerals in decimal notation into fractions. This transformation is performed when parsing the formula. Anyway, we do not expect to see any big difference in performance between these two encodings. The parsing time is usually insignificant in Z3 (when compared with solving time).

Related

How to obtain parametric models using Z3?

Given this formula,
(p & (x < 0)) | (~p & (x > 0)).
How could I get these 2 "parametric" models in Z3:
{p=true, x<0}
{p=false, x>0}
When I submit this SMTLIB program to Z3,
(declare-const p Bool)
(declare-const x Int)
(assert (or (and p (< x 0)) (and (not p) (> x 0))))
(check-sat)
(get-model)
(assert (or (not p) (not (= x -1))))
(check-sat)
(get-model)
(exit)
it gives me concrete models instead (e.g. {p=true, x=-1}, {p=true, x=-2}, ...).
You can't.
SMT solvers do not produce non-concrete models; it's just not how they work. What you want is essentially some form of "simplification" in steroids, and while you can use an SMT solver to help you in simplifying expressions, you'll have to build a tool on top that understands the kind of simplifications you'd like to see. Bottom line: What you'd consider "simple" as a person, and what an automated SMT-solver sees as "simple" are usually quite different from each other; and given lack of normal forms over arbitrary theories, you cannot expect them to do a good job.
If these sorts of simplifications is what you're after, you might want to look at symbolic math packages, such as sympy, Mathematica, etc.

Is it possible to detect inconsistent equations in Z3, or before passing to Z3?

I was working with z3 with the following example.
f=Function('f',IntSort(),IntSort())
n=Int('n')
c=Int('c')
s=Solver()
s.add(c>=0)
s.add(f(0)==0)
s.add(ForAll([n],Implies(n>=0, f(n+1)==f(n)+10/(n-c))))
The last equation is inconsistent (since n=c would make it indeterminate). But, Z3 cannot detect this kind of inconsistencies. Is there any way in which Z3 can be made to detect it, or any other tool that can detect it?
As far as I can tell, your assertion that the last equation is inconsistent does not match the documentation of the SMT-LIB standard. The page Theories: Reals says:
Since in SMT-LIB logic all function symbols are interpreted
as total functions, terms of the form (/ t 0) are meaningful in
every instance of Reals. However, the declaration imposes no
constraints on their value. This means in particular that
for every instance theory T and
for every value v (as defined in the :values attribute) and
closed term t of sort Real,
there is a model of T that satisfies (= v (/ t 0)).
Similarly, the page Theories: Ints says:
See note in the Reals theory declaration about terms of the form
(/ t 0).
The same observation applies here to terms of the form (div t 0) and
(mod t 0).
Therefore, it stands to reason to believe that no SMT-LIB compliant tool would ever print unsat for the given formula.
Z3 does not check for division by zero because, as Patrick Trentin mentioned, the semantics of division by zero according to SMT-LIB are that it returns an unknown value.
You can manually ask Z3 to check for division by zero, to ensure that you never depend division by zero. (This is important, for example, if you are modeling a language where division by zero has a different semantics from SMT-LIB.)
For your example, this would look as follows:
(declare-fun f (Int) Int)
(declare-const c Int)
(assert (>= c 0))
(assert (= (f 0) 0))
; check for division by zero
(push)
(declare-const n Int)
(assert (>= n 0))
(assert (= (- n c) 0))
(check-sat) ; reports sat, meaning division by zero is possible
(get-model) ; an example model where division by zero would occur
(pop)
;; Supposing the check had passed (returned unsat) instead, we could
;; continue, safely knowing that division by zero could not happen in
;; the following.
(assert (forall ((n Int))
(=> (>= n 0)
(= (f (+ n 1))
(+ (f n) (/ 10 (- n c)))))))

Get fractional part of real in QF_UFNRA

Using smtlib I would like to make something like modulo using QF_UFNRA. This disables me from using mod, to_int, to_real an such things.
In the end I want to get the fractional part of z in the following code:
(set-logic QF_UFNRA)
(declare-fun z () Real)
(declare-fun z1 () Real)
(define-fun zval_1 ((x Real)) Real
x
)
(declare-fun zval (Real) Real)
(assert (= z 1.5));
(assert (=> (and (<= 0.0 z) (< z 1.0)) (= (zval z) (zval_1 z))))
(assert (=> (>= z 1.0) (= (zval z) (zval (- z 1.0)))))
(assert (= z1 (zval z)))
Of course, as I am asking this question here, implies, that it didn't work out.
Has anybody got an idea how to get the fractional part of z into z1 using logic QF_UFNRA?
This is a great question. Unfortunately, what you want to do is not possible in general if you restrict yourself to QF_UFNRA.
If you could encode such functionality, then you can decide arbitrary Diophantine equations. You would simply cast a given Diophantine equation over reals, compute the "fraction" of the real solution with this alleged method, and assert that the fraction is 0. Since reals are decidable, this would give you a decision procedure for Diophantine equations, accomplishing the impossible. (This is known as Hilbert's 10th problem.)
So, as innocent as the task looks, it is actually not doable. But that doesn't mean you cannot encode this with some extensions, and possibly have the solver successfully decide instances of it.
If you allow quantifiers and recursive functions
If you allow yourself quantifiers and recursive-functions, then you can write:
(set-logic UFNRA)
(define-fun-rec frac ((x Real)) Real (ite (< x 1) x (frac (- x 1))))
(declare-fun res () Real)
(assert (= (frac 1.5) res))
(check-sat)
(get-value (res))
To which z3 responds:
sat
((res (/ 1.0 2.0)))
Note that we used the UFNRA logic allowing quantification, which is required here implicitly due to the use of the define-fun-rec construct. (See the SMTLib manual for details.) This is essentially what you tried to encode in your question, but instead using the recursive-function-definition facilities instead of implicit encoding. There are several caveats in using recursive functions in SMTLib however: In particular, you can write functions that render your system inconsistent rather easily. See Section 4.2.3 of http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.5-draft.pdf for details.
If you can use QF_UFNIRA
If you move to QF_UFNIRA, i.e., allow mixing reals and integers, the encoding is easy:
(set-logic QF_UFNIRA)
(declare-fun z () Real)
(declare-fun zF () Real)
(declare-fun zI () Int)
(assert (= z (+ zF zI)))
(assert (<= 0 zF))
(assert (< zF 1))
(assert (= z 1.5))
(check-sat)
(get-value (zF zI))
z3 responds:
sat
((zF (/ 1.0 2.0))
(zI 1))
(You might have to be careful about the computation of zI when z < 0, but the idea is the same.)
Note that just because the encoding is easy doesn't mean z3 will always be able to answer the query successfully. Due to mixing of Real's and Integer's, the problem remains undecidable as discussed before. If you have other constraints on z, z3 might very well respond unknown to this encoding. In this particular case, it happens to be simple enough so z3 is able to find a model.
If you have sin and pi:
This is more of a thought experiment than a real alternative. If SMTLib allowed for sin and pi, then you can check whether sin (zI * pi) is 0, for a suitably constrained zI. Any satisfying model to this query would ensure that zI is integer. You can then use this value to extract the fractional part by subtracting zI from z.
But this is futile as SMTLib neither allows for sin nor pi. And for good reason: Decidability would be lost. Having said that, maybe some brave soul can design a logic that supported sin, pi, etc., and successfully answered your query correctly, while returning unknown when the problem becomes too hard for the solver. This is already the case for nonlinear arithmetic and the QF_UFNIRA fragment: The solver may give up in general, but the heuristics it employs might solve problems of practical interest.
Restriction to Rationals
As a theoretical aside, it turns out that if you restrict yourself to rationals only (instead of actual reals) then you can indeed write a first-order formula to recognize integers. The encoding is not for the faint of heart, however: http://math.mit.edu/~poonen/papers/ae.pdf. Furthermore, since the encoding involves quantifiers, it's probably quite unlikely that SMT solvers will do well with a formulation based on this idea.
[Incidentally, I should extend thanks to my work colleagues; this question made for a great lunch-time conversation!]

Does Z3 support Real-to-Int conversions?

In Z3 you have to_real to obtain the Real equivalent of an Int. Is there some support to the inverse conversions, i.e., to truncation, rounding or like? In the negative case, what could be the most Z3-friendly way of defining them, if any? Many thanks to everyone will answer.
Yes, Z3 has a to_int function that converts a Real into an integer. The semantics of to_int is defined in the SMT 2.0 standard. Here is an example: http://rise4fun.com/Z3/uJ3J
(declare-fun x () Real)
(assert (= (to_int x) 2))
(assert (not (= x 2.0)))
(check-sat)
(get-model)

Quantifier Vs Non-Quantifier

I have a question about Quantifiers.
Suppose that I have an array and I want to calculate array index 0, 1 and 2 for this array -
(declare-const cpuA (Array Int Int))
(assert (or (= (select cpuA 0) 0) (= (select cpuA 0) 1)))
(assert (or (= (select cpuA 1) 0) (= (select cpuA 1) 1)))
(assert (or (= (select cpuA 2) 0) (= (select cpuA 2) 1)))
Or otherwise I can specify the same using forall construct as -
(assert (forall ((x Int)) (=> (and (>= x 0) (<= x 2)) (or (= (select cpuA x) 0) (= (select cpuA x) 1)))))
Now I would like to understand the difference between two of them.
The first method executes quickly and gives a simple and readable model.
In contrast the code size with second option is very less, but the program takes time to execute. And also the solution is complex.
I would like to use the second method as my code will become smaller.
However, I want to find a readable simple model.
Quantifier reasoning is usually very expensive. In your example, the quantified formula is equivalent to the three assertions you provided.
However, that is not how Z3 decides/solves your formula. Z3 solves your formula using a technique called Model-Based Quantifier Instantiation (MBQI).
This technique can decide many fragments (see http://rise4fun.com/Z3/tutorial/guide). It is mainly effective on the fragments described in this guide.
It supports uninterpreted functions, arithmetic and bit-vector theories. It also has limited support for arrays and datatypes.
This is sufficient for solving your example. The model produced by Z3 seems more complicated because the same engine is used to decide more complicated fragments.
The model should be seem as a small functional program. You can find more information on how this approach works in the following articles:
Complete instantiation for quantified SMT formulas
Efficiently Solving Quantified Bit-Vector Formula
Note that, array theory is mainly useful for representing/modeling unbounded or big arrays. That is, the actual size of the array is not known or is too big. By big, I mean the number of array accesses (i.e., selects) in your formula is much smaller than the actual size of the array. We should ask ourselves : "do we really need arrays for modeling/solving problem X?". You may consider the following alternatives:
(Uninterpreted) functions instead of arrays. Your example can be encoded also as:
(declare-fun cpuA (Int) Int)
(assert (or (= (cpuA 0) 0) (= (cpuA 0) 1)))
(assert (or (= (cpuA 1) 0) (= (cpuA 1) 1)))
(assert (or (= (cpuA 2) 0) (= (cpuA 2) 1)))
Programmatic API. We've seen many examples where arrays (and functions) are used to provide a compact encoding. A compact and elegant encoding is not necessarily easier to solve. Actually, it is usually the other way around. You can achieve the best of both worlds (performance and compactness) using a programmatic API for Z3. In the following link, I encoded your example using one "variable" for each position of the "array". Macros/functions are used to encode constraints such as: an expression is a 0 or 1.
http://rise4fun.com/Z3Py/JF

Resources