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
outputssat
z3 -smt2 z3.unsat
outputsunsat
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
outputssat
z3 -smt2 z3.pushpop.unsat
outputsunknown
z3 -smt2 z3.pushpop.combined
outputs:sat unknown
Why does z3 -smt2 z3.pushpop.unsat
output unknown
?