How to print out the whole symbolic expression in Z3? - z3

I am using Z3Py for some analysis task, and for many times, I would like to print out the symbolic expression. For example,
a = BitVecVal("test", 32) + 13
print a
However, I find that once the Z3 expression becomes quite large, it just cannot be print out fully. Instead, the "ellipsis" will be used quite often to simplify the expression...
So here is my question, how can I fully print out a Z3 expression? Is there any specific API I could leverage?

The most scalable way is to use the SMT-LIB printer.
For example:
x = Int('x')
for i in range(12):
x = x + x
print x.sexpr()
will print:
(let ((a!1 (+ (+ (+ x x) (+ x x)) (+ (+ x x) (+ x x)))))
(let ((a!2 (+ (+ (+ a!1 a!1) (+ a!1 a!1)) (+ (+ a!1 a!1) (+ a!1 a!1)))))
(let ((a!3 (+ (+ (+ a!2 a!2) (+ a!2 a!2)) (+ (+ a!2 a!2) (+ a!2 a!2)))))
(+ (+ (+ a!3 a!3) (+ a!3 a!3)) (+ (+ a!3 a!3) (+ a!3 a!3))))))
You can control parameters on the formatter used by the pretty printer using the function 'set_pp_option'. You would have to look in the source code of z3printer.py to determine which options would do the trick.

Related

Incremental input and assertion sets in Z3

I have a program that runs Z3 version 4.8.8 - 64 bit, with incremental input: the program starts Z3 once, executes many rounds of input-output to Z3, and then stops Z3. For performance reasons, running Z3 without incremental input is not an option.
Each round, the program inputs some (assert ...) statements to Z3, inputs (check-sat) to Z3, then gets the output of (check-sat) from Z3.
I have two rounds of input-output: the first round of inputs is as in z3.sat:
(declare-fun f () Int)
(declare-fun n () Int)
(assert (< 1 n))
(assert (<= 2 f))
(assert (= (+ (+ 1 f) 1) (+ n n)))
(assert (not false))
(check-sat)
which means: f is an even Int greater or equals to 2.
And the second round of inputs is as in z3.unsat:
(declare-fun f () Int)
(declare-fun n () Int)
(assert (< 1 n))
(assert (<= 2 f))
(assert (= (+ (+ 1 f) 1) (+ n n)))
(assert (not (exists ((alpha Int)) (= (* 2 alpha) f))))
(check-sat)
which means: if f is an even Int greater or equals to 2, then there exists an alpha where alpha=f/2.
I assume that running Z3 with incremental input is similar to concatenating the two rounds of input, z3.sat and z3.unsat, into one input, as in z3.combined:
(declare-fun f () Int)
(declare-fun n () Int)
(assert (< 1 n))
(assert (<= 2 f))
(assert (= (+ (+ 1 f) 1) (+ n n)))
(assert (not false))
(check-sat)
(declare-fun f () Int)
(declare-fun n () Int)
(assert (< 1 n))
(assert (<= 2 f))
(assert (= (+ (+ 1 f) 1) (+ n n)))
(assert (not (exists ((alpha Int)) (= (* 2 alpha) f))))
(check-sat)
Running:
z3 -smt2 z3.sat outputs sat
z3 -smt2 z3.unsat outputs unsat
z3 -smt2 z3.combined outputs errors, because the (assert ...) statements from the first round do not disappear:
sat
(error "line 8 column 21: invalid declaration, constant 'f' (with the given signature) already declared")
(error "line 9 column 21: invalid declaration, constant 'n' (with the given signature) already declared")
unknown
So it seems (push 1) and (pop 1) statements are needed for Z3 to forget previous assertion sets, so I added these statements at the start and end of z3.sat and z3.unsat, and re-concatenated z3.pushpop.sat and z3.pushpop.unsat to get z3.pushpop.combined.
z3.pushpop.sat:
(push 1)
(declare-fun f () Int)
(declare-fun n () Int)
(assert (< 1 n))
(assert (<= 2 f))
(assert (= (+ (+ 1 f) 1) (+ n n)))
(assert (not false))
(check-sat)
(pop 1)
z3.pushpop.unsat:
(push 1)
(declare-fun f () Int)
(declare-fun n () Int)
(assert (< 1 n))
(assert (<= 2 f))
(assert (= (+ (+ 1 f) 1) (+ n n)))
(assert (not (exists ((alpha Int)) (= (* 2 alpha) f))))
(check-sat)
(pop 1)
z3.pushpop.combined:
(push 1)
(declare-fun f () Int)
(declare-fun n () Int)
(assert (< 1 n))
(assert (<= 2 f))
(assert (= (+ (+ 1 f) 1) (+ n n)))
(assert (not false))
(check-sat)
(pop 1)
(push 1)
(declare-fun f () Int)
(declare-fun n () Int)
(assert (< 1 n))
(assert (<= 2 f))
(assert (= (+ (+ 1 f) 1) (+ n n)))
(assert (not (exists ((alpha Int)) (= (* 2 alpha) f))))
(check-sat)
(pop 1)
However, now running:
z3 -smt2 z3.pushpop.sat outputs sat
z3 -smt2 z3.pushpop.unsat outputs unknown
z3 -smt2 z3.pushpop.combined outputs:
sat
unknown
Why does z3 -smt2 z3.pushpop.unsat output unknown?
As Malte mentioned, the presence of pus/pop triggers "weaker" solvers in z3. (There are many technical reasons for this, but I agree from an end-user view-point, the change in behavior is unfortunate and can be rather confusing.)
But there are commands that let you do what you want without resorting to push and pop. Instead of it, simply insert:
(reset)
when you want to "start" a new session, and this will make sure it'll all work. That is, drop the push/pop and when you concatenate, insert a (reset) in between.
A slightly better approach
While the above will work, in general you only want to forget assertions, but not definitions. That is, you want to "remember" that you have an f and an n in the environment. If this is your use case, then put the following at the top of your script:
(set-option :global-declarations true)
and when you want to "switch" to a new problem, issue:
(reset-assertions)
This way, you won't have to "repeat" the declarations each time. That is, your entire interaction should look like:
(set-option :global-declarations true)
(declare-fun f () Int)
(declare-fun n () Int)
(assert (< 1 n))
(assert (<= 2 f))
(assert (= (+ (+ 1 f) 1) (+ n n)))
(assert (not false))
(check-sat)
(reset-assertions)
(assert (< 1 n))
(assert (<= 2 f))
(assert (= (+ (+ 1 f) 1) (+ n n)))
(assert (not (exists ((alpha Int)) (= (* 2 alpha) f))))
(check-sat)
which produces:
sat
unsat
Reference
All of this is documented in the official SMTLib document. See Section 3.9, pg. 44, for the descripton of global-declarations, and Section 4.2.2, pg. 59, for the description of (reset-assertions).
Incremental mode forces Z3 to use different theory subsolvers, as explained by one of the developers in this SO answer. These "incremental mode" subsolvers are often less effective than the "regular" ones, or at least may behave differently. As far as I know, Z3 switches to incremental mode whenever an SMT program contains push-pop scopes or multiple check-sats.
You initially say that not using incremental mode is not an option, but at least your file z3.pushpop.combined looks easily splitable. Another option might be to reset Z3 (I think the SMT command (reset) exists for that purpose) in between, instead of having push-pop blocks. If what I claim above is correct, however, this wouldn't prevent Z3 from staying in non-incremental mode. You could consider asking the developers via a "question issue" on Z3's issue tracker.

unknown when using a integer division in z3 smt2

I am trying to find a solution for the function penta(n) = (n * (3n -1)) / 2 and where penta (z) = penta (a) + penta(b) for all number positives. That works until the integer division (div) is part ofthe definition, but when it is added in the definition I either got a timeout or an unknown.
I would expect to get 8 , 7 , 4. Any idea on what I did wrongly?
(declare-const a Int)
(declare-const b Int)
(declare-const z Int)
(define-fun penta ((n Int)) Int (div (* (- (* 3 n ) 1) n) 2) )
(assert (= (penta z) (+ (penta a) (penta b)) ))
(assert (> a 1))
(assert (> b 1))
(assert (> z 1))
(check-sat)
(get-model)
I am using the version on the http://rise4fun.com/Z3 website and the version 4.1 (x64).
The main issue is that the problem uses integer multiplication between two non-numeric arguments. There are no decision procedures for general Diophantine problems so Z3 does a best effort, which does not favor model enumeration.
When you don't use integer division, Z3 will try a partial heuristic based on
converting the problem into finite domain bit-vectors to find models. It invokes
this heuristic by performing a syntactic check on the formulas. THe syntactic check fails when you use the operator (div .. 2).
You can encode (div x 2) so the heuristic picks up the problem
by introducing fresh variables and bounding them:
(declare-const penta_z Int)
(declare-const penta_a Int)
(declare-const penta_b Int)
(assert (or (= (* 2 penta_z) (penta z)) (= (+ 1 (* 2 penta_z)) (penta z))))
(assert (or (= (* 2 penta_a) (penta a)) (= (+ 1 (* 2 penta_a)) (penta a))))
(assert (or (= (* 2 penta_b) (penta b)) (= (+ 1 (* 2 penta_b)) (penta b))))
(assert (= penta_z (+ penta_a penta_b) ))
(assert (> a 1))
(assert (> b 1))
(assert (> z 1))
(assert (>= penta_z 0))
(assert (<= penta_z 100))
You can also directly encode your problem using bit-vectors although this starts getting error prone because you have to deal with how to handle overflows.

z3: What might be the reason for timeout (rise4fun)

The problem is: timeout when I try it in rise4fun:
I already tried not to use "forall", but it doesn't work too.
(declare-const x Real)
(declare-const y Real)
(declare-const t Real)
(declare-const u Real)
(declare-const v Real)
(declare-const w Real)
(declare-fun f (Real) Real)
(assert (forall ((x Real) (y Real)) (<= (+ (f x) (f y)) (* 2 (f (/ (+ x y) 2))))))
(assert (<= (+ 2 (f (* 2 (+ t u))) (f (* 2 (+ v w))) (f (+ t u v w))) (+ 2 (* 3 (f (+ t u v w))))))
(check-sat)
(get-model)
Can anybody help?
The example uses both non-linear arithmetic, functions and quantifiers.
Z3 does not handle this combination in any particular way.
The latest version of Z3 does terminate quickly in default mode without the quantifier, but mainly by being lucky as opposed to using a
decision procedure, in this case. With the quantifier, however, tZ3 enters
a search space where it is unable to solve for the function f.

Should Z3 prove monotonicity of <= (with respect to multiplication)?

This is the reduction of a more interesting problem, in which the missing property was (for positive k,M and N), that ((k % M) * N) < M*N. Below is an encoding of the simpler problem that a <= b ==> (a*c) <= (b*c). Such a query succeeds (we get unsat), but if the expression b is replaced by b+1 (as in the second query below) then we get unknown, which seems surprising. Is this the expected behaviour? Are there options to improve the handling of such inequalities? I tried with and without configuration options, and various versions of Z3, including the current unstable branch. Any tips would be much appreciated!
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(assert (> a 0))
(assert (> b 0))
(assert (> c 0))
(assert (<= a b))
(assert (not (<= (* a c) (* b c))))
(check-sat)
(assert (<= a (+ b 1)))
(assert (not (<= (* a c) (* (+ b 1) c))))
(check-sat)
This falls into nonlinear integer arithmetic (which has an undecidable decision problem, see, e.g., How does Z3 handle non-linear integer arithmetic? ), so it's actually not too surprising Z3 returns unknown for some examples, although I guess a bit surprising that it toggled between unsat and unknown for quite similar examples.
If it works for your application, you can try a type coercion: encode the constants as Real instead of Int. This will allow you to use Z3's complete solver for nonlinear real arithmetic and returns unsat with check-sat.
Alternatively, you can force Z3 to use the nonlinear solver even for the integer encoding with (check-sat-using qfnra-nlsat) as in the following based on your example (rise4fun link: http://rise4fun.com/Z3/87GW ):
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(assert (> a 0))
(assert (> b 0))
(assert (> c 0))
(assert (<= a b))
(assert (not (<= (* a c) (* b c))))
;(check-sat)
(check-sat-using qfnra-nlsat) ; unsat
(assert (<= a (+ b 1)))
(assert (not (<= (* a c) (* (+ b 1) c))))
; (check-sat)
(check-sat-using qfnra-nlsat) ; unsat
Some more questions and answers on similar subjects:
Combining nonlinear Real with linear Int
z3 fails with this system of equations
Using Z3Py online to prove that n^5 <= 5 ^n for n >= 5
Can z3 always give result when handling nonlinear real arithmetic
Z3 Theorem Prover: Pythagorean Theorem (Non-Linear Artithmetic)

Incorrect calculations in Z3 for sub comma values of Real numbers

I recently started using Z3 and currently have issues with incorrect calculations for Real numbers with sub comma values. I use SMT2 to define the problem in a text file and feed it to Z3 (version 4.3).
I use non-linear arithmetic for solving a scheduling problem which solves well if the task execution time, period, etc. are in natural numbers e.g., 1.0, 2.0. While for instance 0.3 or 0.2 would not return a correct result. It seems as if there would be a conversion error. The problem can be reproduced for different sub comma values. Current work around is to multiply the constants by 10^x to eliminate all sub comma values and then the problem solves fine.
I could produce the error for the following code: (It returns an incorrect value for w_t1_t2)
(set-option :produce-models true)
(declare-const s_t2 Real)
(declare-const s_t1 Real)
(declare-const w_t1_t2 Real)
(declare-const t_f1 Real)
(assert (<= 0 s_t2 5.0))
(assert (<= 0 s_t1 5.0))
(assert (xor (<= (+ (+ 0.0 s_t2) 0.3) (+ 0.0 s_t1)) (<= (+ (+ 0.0 s_t1) 0.2) (+ 0.0 s_t2))))
(assert (xor (<= (+ (+ 0.0 s_t2) 0.3) (+ 5.0 s_t1)) (<= (+ (+ 5.0 s_t1) 0.2) (+ 0.0 s_t2))))
(assert (xor (<= (+ (+ 5.0 s_t2) 0.3) (+ 0.0 s_t1)) (<= (+ (+ 0.0 s_t1) 0.2) (+ 5.0 s_t2))))
(assert (xor (<= (+ (+ 5.0 s_t2) 0.3) (+ 5.0 s_t1)) (<= (+ (+ 5.0 s_t1) 0.2) (+ 5.0 s_t2))))
(assert (<= 0 w_t1_t2 5.0))
(assert (xor (= w_t1_t2 (- s_t2 (mod (+ s_t1 0.2) 5.0))) (= w_t1_t2 (- (+ s_t2 5.0) (mod (+ s_t1 0.2) 5.0)))))
(assert (<= (+ 0.3 0.2) t_f1 6.0))
(assert (>= t_f1 (+ (+ 0.3 0.2) (+ w_t1_t2))))
(check-sat)
(get-value ( s_t2 s_t1 w_t1_t2 t_f1))
(exit)
The code calculates feasible start times for two periodic tasks t1 and t2 communicating with each other. Constrained by a defined deadline and preventing that both tasks intersect. s_t1 and s_t2 stand for the start times of t1 and t2 respectively, w_t1_t2 is the waiting time and t_f1 stands for the deadline from the start of t1 till the completion of t2. With a period of 5.0, a deadline of 6.0 and execution time of 0.2 and 0.3 for t1 and t2 respectively, the result obtained here is:
s_t1=0.3, s_t2=0 (equalling a 5.0 as its periodically executed) and w_t1_t2=5.0.
However, calculating w_t1_t2 by hand leads to: w_t1_t2= s_t2 + period -(s_t2 + execution_time_t1)=0.0 +5.0 -(0.3+0.2)=4.5
If in contrast 0.2 and 0.3 would be replaced by 0.1 and 2.0 the result is correct.
Am I missing something? Do you have any suggestions on how to solve this problem?
Thank you and best regards,
Florian
The equation:
(= w_t1_t2 (- (+ s_t2 5.0) (mod (+ s_t1 0.2) 5.0)))
is satisfied. You are using the operator "mod", which is defined for integers.
Z3 inserts coercions from Reals to integers such that (+ s_t1 0.2) is the floor.

Resources