I have this following code
(set-logic QF_LIA)
(declare-fun w () Int)
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(assert (> x y))
(assert (> y z))
(push 1)
(assert (> z x))
(check-sat) ; unsat
(get-info :statistics)
(pop 1)
(push 1)
(check-sat (= x w)) ; sat
The code should return unsat on first (check-sat) and sat on second (check-sat), but I get unknown.
Can someone please tell me what's the problem. I am using windows 7, jSMTLIB using cygwin
Thanks
Saif
I don't know which backend in jSMTLIB you used for solving this. However, (check-sat (= x w)) is not even legal in SMT-LIB v2.
When I change that line to:
(assert (= x w))
(check-sat)
I get unsat and sat from Z3 web interface, which is of our expectation.
Note that (get-info :statistics) is also incorrect; the correct option is (get-info :all-statistics). You can read more about SMT-LIB v2 standard in their documentation.
Related
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.
I'm new to Z3 and I'm trying to understand how it works, and what it can and cannot do. I know that Z3 has at least some support for exponentials through the power (^) operator (see Z3py returns unknown for equation using pow() function, How to represent logarithmic formula in z3py, and Use Z3 and SMT-LIB to define sqrt function with a real number). What I'm unclear on is how extensive this support is, and what kind of inferences z3 can make about exponentials.
Here's a simple example involving exponentials which z3 can analyze. We define an exponential function, and then ask it to verify that exp(0) == 1:
(define-fun exp ((x Real)) Real
(^ 2.718281828459045 x))
(declare-fun x1 () Real)
(declare-fun y1 () Real)
(assert (= y1 (exp x1)))
(assert (not (=> (= x1 0.0) (= y1 1.0))))
(check-sat)
(exit)
Z3 returns unsat, as expected. On the other hand, here's a simple example which Z3 can't analyze:
(define-fun exp ((x Real)) Real
(^ 2.718281828459045 x))
(declare-fun x1 () Real)
(declare-fun y1 () Real)
(assert (= y1 (exp x1)))
(assert (not (< y1 0.0)))
(check-sat)
(exit)
This should be satisfiable, since literally any value for x1 would give y1 > 0. However, Z3 returns unknown. Naively I might have expected that Z3 would be able to analyze this, given that it could analyze the first example.
I realize this question is a bit broad, but: can anyone give me any insight into how Z3 handles exponentials, and (more specifically) why it can solve the first example I gave but not the second?
It is hard to say in general, since non-linear solving is challenging, but the case you presented is actually not so mysterious. You wrote:
(assert (= y (exp x)))
(assert (not (=> (= x 0) (= y 1))))
Z3 is going to simplify the second assertion, yielding:
(assert (= y (exp x)))
(assert (= x 0))
(assert (not (= y 1)))
Then it will propagate the first equality, yielding:
(assert (= y (exp 0)))
(assert (not (= y 1)))
Now when exp is expanded, you have a case of constant^constant, which Z3 can handle (for integer exponents, etc).
For the second case, you are asking it a very very basic question about variable exponents, and Z3 immediately barfs. That's not too odd, since so many questions about variable exponents are either known uncomputable or unknown but hard.
I have a simple example in nonlinear integer arithmetic, namely a search for Pythagorean triples. Based on what I read in related questions (see below), I'd expect Z3 to find a solution to this problem, but it returns 'unknown'. Here is the example in SMT-LIB v2:
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(declare-fun xSquared () Int)
(declare-fun ySquared () Int)
(declare-fun zSquared () Int)
(declare-fun xSquaredPlusYSquared () Int)
(assert (= xSquared (* x x)))
(assert (= ySquared (* y y)))
(assert (= zSquared (* z z)))
(assert (= xSquaredPlusYSquared (+ xSquared ySquared)))
(assert (and (> x 0) (> y 0) (> z 0) (= xSquaredPlusYSquared zSquared)))
(check-sat)
(exit)
There are a few related questions, most notably:
How does Z3 handle non-linear integer arithmetic?
Need help understanding the equation
Combining nonlinear Real with linear Int
Z3 support for nonlinear arithmetic
z3 limitations in handling nonlinear real arithmetics
It seems that Z3 won't attempt finding a solution by bit-blasting unless variables have a finite range. Replacing (check-sat) with the following command will find the solution:
(check-sat-using (then (using-params add-bounds :add-bound-lower -100 :add-bound-upper 100) smt))
Alternatively, one can add assert statements forcing each variable to have some finite range.
The following SMT-LIB code runs without problems in Z3, MathSat and CVC4 but it is not running in Alt-Ergo, please let me know what happens, many thanks:
(set-logic QF_LIA)
(set-option :interactive-mode true)
(set-option :incremental true)
(declare-fun w () Int)
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(assert (> x y))
(assert (> y z))
(push 1)
(assert (> z x))
(check-sat)
(pop 1)
(get-info :all-statistics)
(push 1)
(assert (= x w))
(check-sat)
(get-assertions)
(exit)
Run this example online here
In Z3, the message unsupported ; :incremental is generated but this does not alter the computations and the correct answer is obtained.
In mathsat, some messages unsupportedare generated but the correct answer is displayed.
In Cvc4 the code is executed without problems and the correct answer is obtained.
In Alt-Ergo the code is executed without messages but wrong answer unsat is generated ( the correct answer is : unsat, sat).
Regarding Alt-Ergo and SMT-LIB2, please consider reading the answer to one of your previous posts here: How to execute the following SMT-LIB code using Alt-Ergo
I have a file containing:
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(declare-const d Real)
(declare-const e Real)
(assert (> a (+ b 2)))
(assert (= a (+ (* 2 c) 10)))
(assert (<= (+ c b) 1000))
(assert (>= d e))
(check-sat)
(get-model)
and, according to the online tutorial, running z3 on this file should return:
sat
(model
(define-fun c () Int
(- 5))
(define-fun a () Int
0)
(define-fun b () Int
(- 3))
(define-fun d ()
Real 0.0)
(define-fun e ()
Real 0.0)
)
So I know this is legal Z3 input. However, whenever I run "z3 [option] " all I get is error messages no matter what option I choose -- including none. Can someone tell me how to correctly invoke Z3 on the input file?
Regards.
Z3 supports many input formats. It uses the file extension to guess which parser will be used. If the extension is .smt2. It will use the SMT 2.0 parser. You can also specify which parser should be used. The option -smt2 will force Z3 to use the SMT 2.0 parser. Finally, Z3 does not enable model construction by default. So, you should use the option MODEL=true, or add the command (set-option :produce-models true) in the beginning of your script.
If you want to use a very old version of Z3, you will have to use SMT 1.0 format.
This format is described at: http://goedel.cs.uiowa.edu/smtlib/papers/format-v1.2-r06.08.30.pdf
That being said, I strongly encourage you to upgrade. The SMT 1.0 is not very user friendly, and most documentation/tutorials for SMT are in SMT 2.0 format.
Here is your example in this format:
(benchmark file
:extrafuns ((a Int) (b Int) (c Int) (d Real) (e Real))
:assumption (> a (+ b 2))
:assumption (= a (+ (* 2 c) 10))
:assumption (<= (+ c b) 1000)
:assumption (>= d e)
:formula true)