Truncate Integers Like C in SMT-LIB 2 - z3

I'm passing the symbolic output of a symbolic execution engine to Z3 in SMT-LIB 2 format. I need it to truncate integers like they would be in C. So that (assert (= 1 (/ 3 2))) would be SAT.
These formulas might also have floats, so not all divisions should truncate. Just division of ints.
How does one do this?

Integer division is simply called div:
(assert (= 1 (div 3 2)))
(check-sat)
This produces:
sat

Related

What is `root-object` in z3 with Real theory?

I tried QF_NRA in z3 and it gave me an abstract value about root-obj.
(set-logic QF_NRA)
(declare-const x Real)
(assert (= 2 (* x x)))
(check-sat)
sat
(get-model)
(
(define-fun x () Real
(root-obj (+ (^ x 2) (- 2)) 1))
)
I don’t quite understand its meaning.
In addition, the x seems defined in recursion but not by define-fun-rec.
Thanks.
Algebraic reals
Z3's Real theory supports what's known as algebraic reals. That is, it can express solutions in terms of the roots of polynomials with rational (equivalently, integer) valued coefficients. Note that such a polynomial can have complex roots. Z3 only supports those roots that are real, i.e., those with an imaginary part of 0. An algebraic real is essentially the real-root of a univariate polynomial with integer coefficients.
Dealing with root-obj's
In the example you posted, you're asking z3 to find a satisfying model for x*x == 2. And it's telling you that the solution is "a" zero-of-the polynomial (+ (^ x 2) (- 2)), or written in more familiar notation P(x) = x^2 -2. The index you get is 1 (the second argument to the root-obj), which says it's the "first" real-root of this polynomial. If you ask z3 to give you another solution, it'll give you the next one:
(set-logic QF_NRA)
(declare-const x Real)
(assert (= 2 (* x x)))
(assert (distinct x (root-obj (+ (^ x 2) (- 2)) 1)))
(check-sat)
(get-model)
This prints:
sat
(
(define-fun x () Real
(root-obj (+ (^ x 2) (- 2)) 2))
)
As you see, the "next" solution is the second root. What if we assert we want yet another solution?
(set-logic QF_NRA)
(declare-const x Real)
(assert (= 2 (* x x)))
(assert (distinct x (root-obj (+ (^ x 2) (- 2)) 1)))
(assert (distinct x (root-obj (+ (^ x 2) (- 2)) 2)))
(check-sat)
This prints:
unsat
as expected.
Note that algebraic reals do not include numbers such as pi, e, etc., i.e., they do not include transcendentals. Only those real numbers that can be expressed as the root of polynomials with integer coefficients. Leonardo's paper from 2012 explains this in great detail.
Getting approximations
z3 also allows you to get an approximation for such a root-obj solution, with as arbitrary a precision as you like. To do so, use the incantation:
(set-option :pp.decimal true)
(set-option :pp.decimal_precision 20)
where 20 in the second line is how many digits of precision you'd like, and you can change it as you see fit. If you add these two lines to your original script, z3 will respond:
sat
(
(define-fun x () Real
(- 1.4142135623730950?))
)
Note the ? at the end of the number. This is z3's way of telling you that the number it printed is an "approximation" to the value, i.e., it isn't the precise result.
A note on "recursion"
Your question suggests maybe x is defined recursively. This isn't the case. It just happens that you picked the variable name to be x and z3 always uses the letter x for the polynomial as well. If you picked y as the variable, you'd still get the exact same answer; the parameter to the polynomial has nothing to the with the variables in your program.

Multi-element subtraction in Z3

I'm using Z3 to solve a problem that needs subtraction and I've run into the fact that subtraction in Z3 allows multiple arguments.
This seems odd to me as subtraction is not an associative operation.
This can be seen from the following script.
(declare-fun a () Int)
(declare-fun b () Int)
(declare-fun c () Int)
(assert (= a (- 1 2 3)))
(assert (= b (- 1 (- 2 3))))
(assert (= c (- (- 1 2) 3)))
which is satisfied by a=c=-4 and b=2
So this means that subtraction in Z3 is defined by applying the binary operation from left to right?
This is actually a feature of SMT-Lib, z3 is simply implementing that. See here: http://smtlib.cs.uiowa.edu/theories-Ints.shtml
And yes, if you have multiple elements, it simply associates to the left. That is:
(- 1 2 3 4)
means exactly the same thing as:
(- (- (- 1 2) 3) 4)
This is indeed confusing as we only want to do for associative operators where parenthesization doesn't matter (like + and *), but SMTLib is liberal in this sense. This does not mean subtraction is associative in SMT-Lib, it just means if you have multiple arguments it's parsed as described above. Hope that helps!

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

Simplfying Expression : Z3 SMT Solver

Executing the following query with the Z3 solver:
(declare-const c0 Int)
(declare-const c1 Int)
(declare-const c2 Int)
(assert (exists ((c0_s Int) (c1_s Int) (c2_s Int))
(and
(= (+ c0 c1 c2) 5) (>= c0 0) (>= c1 1) (>= c2 1)
(= c0_s c0) (= c1_s (- c1 1)) (= c2_s (+ c2 1))
(= c2_s 3) (= (+ c0_s c1_s) 2)
))
)
(apply (then qe ctx-solver-simplify propagate-ineqs))
produces the following output:
(goals
(goal
(>= c0 0)
(<= c0 2)
(>= c1 1)
(<= c1 3)
(<= (+ (* (- 1) c0) (* (- 1) c1)) (- 3))
(<= (+ c1 c0) 3)
(= c2 2)
:precision precise :depth 3)
)
where I was expecting a result from the Z3 solver like this:
(goals
(goal
(>= c0 0)
(<= c0 2)
(>= c1 1)
(<= c1 3)
(= (+ c1 c0) 3)
(= c2 2)
:precision precise :depth 3)
)
Can anyone explain why Z3 is producing such a complex result instead of what I expected? Is there a way to get Z3 to simplify this output?
You may get a more detailed answer from a member of the core Z3 team, but from my experience working with Z3's integer solver at a low level, I can give a bit of intuition as to why this is happening.
Briefly, in order to solve integer equations, Z3's integer theory solver expects all of its constraints to appear in a very particular and restricted form. Expressions that do not follow this form must be rewritten before they are presented to the solver. Normally this happens internally by a theory rewriter, and any expression can be used in the input constraint set without issue.
The restrictions that apply here (that I am aware of), which help explain why you are seeing this strange-looking output, are as follows:
The integer solver can represent an equality constraint (= a b) as two separate inequality constraints (<= a b) and (>= a b). This is why you're seeing two separate constraints over your variables in the model instead of just one equality.
The integer solver rewrites subtractions, or negated terms, as multiplication by -1. This is why you are seeing these negations in your first constraint, and why the operator is addition instead of subtraction.
Arithmetic expressions are rewritten so that the second argument to a comparison operator is always a constant value.
In short, what you're seeing is likely an artifact of how the arithmetic theory solver represents constraints internally.
Since the output of your instance is a goal and not a model or proof, these expressions may not have been fully simplified yet, as I believe that intermediate goals are not always simplified (but I don't have experience with this part of the solver).

Simplifying an expression leads to time out

How can I simplify the following expression using Z3 Solver?
(declare-const c0 Int)
(declare-const c1 Int)
(declare-const c2 Int)
(assert (let ((a!1 (to_real (+ (* (* 2 c0) c2)
(* (* 2 c0) c1)
(* 2 c1 c2)
(* c0 (- c0 1))
(* c1 (- c1 1))))))
(let ((a!2 (/ (to_real (* (* 2 c0) c2)) a!1)))
(and (or (and (<= c2 1) (>= c2 1) (<= c0 2) (>= c0 2) (<= c1 3) (>= c1 3))
(and (<= c2 1) (>= c2 1) (<= c0 3) (>= c0 3) (<= c1 2) (>= c1 2)))
(= (/ 2.0 15.0) a!2))))
)
(apply (then qe propagate-values (repeat (then ctx-solver-simplify propagate-ineqs) 10)))
Link : http://rise4fun.com/Z3/u7F7
I tried all the possible tactics that I know about and yet ended up causing time out by the solver. Is there a way that I can avoid time out? Is it suppose to return false as a result in Java API?
It's hard to tell what's going on just by looking at that code. But I'd think that to_real might be the problematic part, as conversion between domains tend to generate non-linear constraints that can cause complexity problems.
I'd give it a try using purely Reals (i.e., declare c0, c1.. as Reals; and remove calls to to_real.)
If you do need integers/reals mixed; make sure that mixing is done at the leaves (i.e., at constants); or at the very-top, as much as you can push the conversions around; instead of at intermediate values.
But I'd guess that sticking to Reals would be the way to go here if your problem space allows for that.
The example uses non-linear integer arithmetic. Unfortunately, it is easy to produce examples in this domain where Z3 does not terminate. The ctx-solver-simplify routine calls the SMT solver multiple times and in each invocation has to check satisfiability of some combination of the non-linear constraints.

Resources