I'm trying to use Z3 to solve arithmetic equations using bitvector arithmetic. I was wondering if there is a way to handle also Real numbers. For example if I can specify a constant different from #x1 and use real number instead.
(set-option :pp.bv-literals false)
(declare-const x (_ BitVec 4))
(declare-const y (_ BitVec 4))
(assert (= (bvadd x y) #x1))
(check-sat)
(get-model)
Yes, both SMT-Lib (and Z3) fully support real numbers: http://smtlib.cs.uiowa.edu/theories-Reals.shtml
You can simply write your example as follows:
(declare-const x Real)
(declare-const y Real)
(assert (= (+ x y) 1))
(check-sat)
(get-model)
You can also mix/match Int/Real/Bitvector, so long as everything is properly typed. Here's an example showing how to use Ints and Reals together:
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(declare-const d Real)
(declare-const e Real)
(assert (> e (+ (to_real (+ a b)) 2.0)))
(assert (= d (+ (to_real c) 0.5)))
(assert (> a b))
(check-sat)
(get-model)
However, note that conversion from bit-vectors to integers is usually uninterpreted. See here for a discussion: Z3 int2bv operation
Related
I am a beginner user of Z3. Recently, I have been using z3 to verify some problems. Here is one problem I tried: (x < 0 && y < 0) implies x/y >= 0, below are the programs I wrote:
(declare-const x Int)
(declare-const y Int)
(define-fun assumption() Bool
(and (< x 0) (< y 0))
)
(define-fun predicate() Bool
(<= 0 (div x y))
)
(assert (not (=> assumption predicate)))
(check-sat)
When I use 'z3 -smt2 filename' to verify this program, it works and return unsat. However, when I later modify the program to:
(declare-const x Int)
(declare-const y Int)
(define-fun assumption() Bool
(and (< x 0) (< y 0))
)
(define-fun predicate() Bool
(<= 0 (div (* -1 x) (* -1 y)))
)
(assert (not (=> assumption predicate)))
(check-sat)
This cause z3 to timeout when I changed 'x/y' to (-1 * x)/(-1 * y) and somehow I need to add -1 there. I am confused why this happened and why multiplied by a constant makes this problem more complex.
Can somebody help figure out why this happened?
Thank you!
There is very limited support for non-linear arithmetic, such as division where the divisor is a variable.
So Z3 will do a best effort, but in no way be sure to provide decisions on every formula with non-linear arithmetical operations. So for example, you can enter Diophantine equations into Z3, but not expect it to provide sat/unsat answers.
Rather than trying some infinite search, Z3 may prefer to give up and return unknown.
(Note: This is just a comment instead of an answer. I have to do so because I don't have sufficient reputation to add a comment.)
Here is the quote from the Z3 guide about integer division, modulo and reminder operators:
Z3 also has support for division, integer division, modulo and remainder operators. Internally, they are all mapped to multiplication.
(declare-const a Int)
(declare-const r1 Int)
(declare-const r2 Int)
(declare-const r3 Int)
(declare-const r4 Int)
(declare-const r5 Int)
(declare-const r6 Int)
(assert (= a 10))
(assert (= r1 (div a 4))) ; integer division
(assert (= r2 (mod a 4))) ; mod
(assert (= r3 (rem a 4))) ; remainder
(assert (= r4 (div a (- 4)))) ; integer division
(assert (= r5 (mod a (- 4)))) ; mod
(assert (= r6 (rem a (- 4)))) ; remainder
(declare-const b Real)
(declare-const c Real)
(assert (>= b (/ c 3.0)))
(assert (>= c 20.0))
(check-sat)
(get-model)
In Z3, division by zero is allowed, but the result is not specified. Division is not a partial function. Actually, in Z3 all functions are total, although the result may be underspecified in some cases like division by zero.
It is unclear what is the behavior when the arguments are negative. In other words, the mapping to multiplication for these operations is not clear.
The original problem is:
(declare-const a Real)
(declare-const b Bool)
(declare-const c Int)
(assert (distinct a 0.))
(assert (= b (distinct (* a a) 0.)))
(assert (= c (ite b 1 0)))
(assert (not (distinct c 0)))
(check-sat)
The result is unknown.
But the last two constraints, taken together, are equivalent to (assert (= b false)), and after performing this rewrite by hand
(declare-const a Real)
(declare-const b Bool)
(declare-const c Int)
(assert (distinct a 0.))
(assert (= b (distinct (* a a) 0.)))
(assert (= b false))
;(assert (= c (ite b 1 0)))
;(assert (not (distinct c 0)))
(check-sat)
Z3 is now able to solve this instance (it is unsat).
Why can Z3 solve the second instance but not the first one, even though the first instance can be simplified to the second?
edit:
While locating the problem I found something very strange.
Z3 solves the following instance and returns "unsat":
(declare-fun a() Real)
(declare-fun b() Bool)
(declare-fun c() Int)
(assert (distinct a 0.0))
(assert (= b (distinct (* a a) 0.0)))
(assert (= b false))
;(assert (= c 0))
(check-sat)
But if I uncomment (assert (= c 0)), the solver returns "unknown", even though c=0 has nothing to do with the above assertions.
The problem here is that expressions like (* a a) are non-linear and Z3's default solver for non-linear problems gives up because it thinks it's too hard. Z3 does have another solver, but that one has very limited theory combination, i.e., you won't be able to use it for mixed Boolean, bit-vector, array, etc, problems, but only for arithmetic problems. It's easy to test by replacing the (check-sat) command with (check-sat-using qfnra-nlsat).
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.
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 I don't have to insert statement (assert (> x 10)) for every integer constant that I declared.
When you use (assert (forall ((i Int)) (> i 10))), i is a bounded variable and the quantified formula is equivalent to a truth value, which is false in this case.
I think you want to define a macro using quantifiers:
(declare-fun greaterThan10 (Int) Bool)
(assert (forall ((i Int)) (= (greaterThan10 i) (> i 10))))
And you can use them to avoid code repetition:
(declare-const x (Int))
(declare-const y (Int))
(assert (greaterThan10 x))
(assert (greaterThan10 y))
(check-sat)
It is essentially the way to define macros using uninterpreted functions when you're working with Z3 API. Note that you have to set (set-option :macro-finder true) in order that Z3 replaces universal quantifiers with bodies of those functions.
However, if you're working with the textual interface, the macro define-fun in SMT-LIB v2 is an easier way to do what you want:
(define-fun greaterThan10 ((i Int)) Bool
(> i 10))
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)