Is there a maximum value size for variables? - z3

Suppose I have the following (intentionally simple) subsection of constraints:
..... SOME STUFF .....
(declare-const I Int)
(assert (and (>= I 0) (<= I 1)))
(define-fun W () Int
2251799813685248
)
..... MORE STUFF .....
(maximize (* I W))
(check-sat)
(get-model)
Is the size I'm giving to W too big? Or more generally, is there a maximum size value that can be assigned in Z3 (for example if variables are stored as regular ints/floats/longs/etc instead of with variable precision)?

An Int value corresponds to a mathematical integer. It can be of an arbitrary size. There are no maximums.
For sized versions, you should use bit-vectors: (_ BV n) is the type of a bit-vector of size n, which follows machine arithmetic rules.

Related

Strange behaviour of seq.nth in exists-expression

Running z3 on this
(assert (< (seq.nth (seq.unit 0) 0) 0))
(check-sat)
has UNSAT as a result
But running
(assert (exists ((x Int))
(< (seq.nth (seq.unit 0) x) 0)))
(check-sat)
(get-model)
is SAT. Looking at the model
(model
(define-fun seq.nth_u ((x!0 Seq) (x!1 Int)) Int
(- 1))
)
So, doesn't this mean that seq.nth is treated like a variable over a Function?
Shouldn't it be a constant function (returning always the indexed value of seq)?
I would expect the second case also to be UNSAT. In order to achieve that, how can I make seq.nth a non-variable-function?
Help appreciated...
The function seq.nth is underspecified. That is, if you query an element that is out-of-bounds (i.e., either at a negative index or at at an index that is larger than the last), then it is free to return whatever value the solver wants. (And the solver will always pick a value to make your query satisfiable.)
This is typical of SMTLib, where underspecified functions can simply take any value when given arguments that are not in the domain of their arguments. So, z3 is telling you that there is such a model by indexing out-of-bounds using the sequence (seq.unit 0). i.e., we can index it at some negative value, or at some index larger than 0.
Note that the value of seq.nth_u given in the model (note the _u suffix!) is indicative of how the underflow/overflow behavior is modeled. It should not be confused with the value of the function seq.nth.
You can actually get z3 to display the value of the index x if you make it a top-level existential:
(declare-fun x () Int)
(assert (< (seq.nth (seq.unit 0) x) 0))
(check-sat)
(get-value (x))
For this, z3 says:
sat
((x (- 1)))
that is, index at location -1. But do not confuse this with the -1 that you see in the interpretation of seq.nth_u. In fact, if we also add:
(assert (> x 0))
then z3 says:
sat
((x 1))
However, if we add:
(assert (>= x 0))
(assert (< x 1))
then we get unsat as expected. And when working with sequences, you should add these sorts of constraints (if possible!) to avoid out-of-bounds accesses.

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)))))))

Quantifiers in Z3

Basically, I want to ask Z3 to give me an arbitrary integer whose value is greater than 10. So I write the following statements:
(declare-const x (Int))
(assert (forall ((i Int)) (> i 10)))
(check-sat)
(get-value(x))
How can I apply this quantifier to my model? I know you can write (assert (> x 10)) to achieve this, but I mean I want a quantifier in my model so every time I declare an integer constant whose value is guaranteed to be over 10, so that I don't have to insert statement (assert (> x 10)) for every integer constant that I declared. If I have to use macros to prevent repeating code, what is the actual use of quantifiers?
You will need to constrain each int you declare individually. x > 10 is the right way to do that.
You can use macros or any other codegen technique. In the SMT solver all of that expands to regular constraints. It has no runtime impact.
forall ((i Int)) (> i 10)) means "Are all ints bigger than 10?" which is false.
Quantifiers do not quantify over all variables that you have declared. They quantify only over the bound variables, here i.

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)

Difference between macro and quantifier in Z3

I would like to know what is the difference between following 2 statements -
Statement 1
(define-fun max_integ ((x Int) (y Int)) Int
(ite (< x y) y x))
Statement 2
(declare-fun max_integ ((Int)(Int)) Int)
(assert (forall ((x Int) (y Int)) (= (max_integ x y) (if (< x y) y x))))
I observed that when I use Statement1, my z3 constraints give me a result in 0.03 seconds. Whereas when I used Statement2, it does not finish in 2 minutes and I terminate the solver.
I would like also to know how achieve it using C-API.
Thanks !
Statement 1 is a macro. Z3 will replace every occurrence of max_integ with the ite expression. It does that during parsing time. In the second statement, by default, Z3 will not eliminate max_integ, and to be able to return sat it has to build an interpretation for the uninterpreted symbol max_integ that will satisfy the quantifier for all x and y.
Z3 has an option called :macro-finder, it will detect quantifiers that are essentially encoding macros, and will eliminate them. Here is an example (also available online here):
(set-option :macro-finder true)
(declare-fun max_integ ((Int)(Int)) Int)
(assert (forall ((x Int) (y Int)) (= (max_integ x y) (if (< x y) y x))))
(check-sat)
(get-model)
That being said, we can easily simulate macros in a programmatic API by writing a function that given Z3 expressions return a new Z3 expression. Here in an example using the Python API (also available online here):
def max(a, b):
# The function If builds a Z3 if-then-else expression
return If(a >= b, a, b)
x, y = Ints('x y')
solve(x == max(x, y), y == max(x, y), x > 0)
Yet another option is to use the C API: Z3_substitute_vars. The idea is to an expression containing free variables. Free variables are created using the API Z3_mk_bound. Each variable represents an argument. Then, we use Z3_substitute_vars to replace the variables with other expressions.

Resources