How do I get the maximum of a formula using smt-lib2?
I want something like this:
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(assert (= x 2))
(assert (= y 4))
(assert (= z (max x y))
(check-sat)
(get-model)
(exit)
Of course, 'max' is unknown to smtlibv2.
So, how can this be done?
In Z3, you can easily define a macro max and use it for getting maximum of two values:
(define-fun max ((x Int) (y Int)) Int
(ite (< x y) y x))
There is another trick to model max using uninterpreted functions, which will be helpful to use with Z3 API:
(declare-fun max (Int Int) Int)
(assert (forall ((x Int) (y Int))
(= (max x y) (ite (< x y) y x))))
Note that you have to set (set-option :macro-finder true), so Z3 is able to replace universal quantifiers with body of the function when checking satisfiability.
You've got abs, and per basic math max(a,b) = (a+b+abs(a-b))/2
Related
I list some assert about Quadratic function:
(declare-fun H () Int)
(assert (>= H 8000))
(assert (<= H 12000))
(minimize (- (^ H 2) H))
(check-sat)
but the answer is "unknown" and the reason for unknown is (incomplete (theory arithmetic)); I can't understand which is the lost one
In general z3 cannot deal with non-linear terms. (A term is non-linear if you multiply two variables together. In your case, that'd be (^ H 2).
This is especially true of the optimization engine: Nonlinear constraints over integers is most likely going to be beyond reach. But you're in luck: Your formula is rather simple so it can handle it fine. Rewrite it using multiplication:
(declare-fun H () Int)
(assert (>= H 8000))
(assert (<= H 12000))
(minimize (- (* H H) H))
(check-sat)
(get-model)
This prints:
sat
(model
(define-fun H () Int
8000)
)
I'm trying to get z3 to work (most of the time) for very simple non-linear integer arithmetic problems. Unfortunately, I've hit a bit of a wall with exponentiation. I want to be able handle problems like x^{a+b+2} = (x * x * x^{a} * x{b}). I only need to handle non-negative exponents.
I tried redefining exponentiation as a recursive function (so that it's just allowed to return 1 for any non-positive exponent) and using a pattern to facilitate z3 inferring that x^{a+b} = x^{a} * x^{b}, but it doesn't seem to work - I'm still timing out.
(define-fun-rec pow ((x!1 Int) (x!2 Int)) Int
(if (<= x!2 0) 1 (* x!1 (pow x!1 (- x!2 1)))))
; split +
(assert (forall ((a Int) (b Int) (c Int))
(! (=>
(and (>= b 0) (>= c 0))
(= (pow a (+ b c)) (* (pow a c) (pow a b))))
:pattern ((pow a (+ b c))))))
; small cases
(assert (forall ((a Int)) (= 1 (pow a 0))))
(assert (forall ((a Int)) (= a (pow a 1))))
(assert (forall ((a Int)) (= (* a a) (pow a 2))))
(assert (forall ((a Int)) (= (* a a a) (pow a 3))))
; Our problem
(declare-const x Int)
(declare-const i Int)
(assert (>= i 0))
; This should be provably unsat, by splitting and the small case for 2
(assert (not (= (* (* x x) (pow x i)) (pow x (+ i 2)))))
(check-sat) ;times out
Am I using patterns incorrectly, is there a way to give stronger hints to the proof search, or an easier way to do achieve what I want?
Pattern (also called triggers) may only contain uninterpreted functions. Since + is an interpreted function, you essentially provide an invalid pattern, in which case virtually anything can happen.
As a first step, I disabled Z3's auto-configuration feature and also MBQI-based quantifier instantiation:
(set-option :auto_config false)
(set-option :smt.mbqi false)
Next, I introduced an uninterpreted plus function and replaced each application of + by plus. That sufficed to make your assertion verify (i.e. yield unsat). You can of course also axiomatise plus in terms of +, i.e.
(declare-fun plus (Int Int) Int)
(assert (forall ((a Int) (b Int))
(! (= (plus a b) (+ a b))
:pattern ((plus a b)))))
but your assertion already verifies without the definitional axioms for plus.
In Z3, if the input script is written in SMTLib format, is it possible to output the model (value assignments satisfying the model)? The get-model returns an interpretation satisfying the constraints. Is there any way to extract the concrete values from these interpretations. I am aware that we can use the python/C++ API to get model values.
You probably want to use get-value, here's a minimal example (rise4fun link: http://rise4fun.com/Z3/wR81 ):
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(assert (>= (* 2 x) (+ y z)))
(declare-fun f (Int) Int)
(declare-fun g (Int Int) Int)
(assert (< (f x) (g x x)))
(assert (> (f y) (g x x)))
(check-sat) ; sat
(get-model) ; returns:
; (model
; (define-fun z () Int
; 0)
; (define-fun y () Int
; (- 38))
; (define-fun x () Int
; 0)
; (define-fun g ((x!1 Int) (x!2 Int)) Int
; (ite (and (= x!1 0) (= x!2 0)) 0
; 0))
; (define-fun f ((x!1 Int)) Int
; (ite (= x!1 0) (- 1)
; (ite (= x!1 (- 38)) 1
; (- 1))))
;)
(get-value (x)) ; returns ((x 0))
(get-value ((f x))) ; returns (((f x) (- 1)))
You'd potentially then have to parse this depending on what you're trying to do, etc.
For more details, check out the SMT-LIB standard:
http://smtlib.cs.uiowa.edu/language.shtml
The latest version is: http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.0-r12.09.09.pdf
You can see some examples of get-value on page 39 / figure 3.5.
I have a problem required to solve a set of nonlinear polynomial constraints. Can z3 always give a result (sat or unsat) when handling nonlinear real arithmetic.
Is the result also sound?
Yes, it is complete assuming (1) availability of resources, and (2) you only use real constraints so that the nlsat tactic is used, as the last I checked, it wasn't full integrated with the other solvers, see the below questions/answers for more details. Here's a simple example illustrating this (at least by default, rise4fun link: http://rise4fun.com/Z3/SRZ8 ):
(declare-fun x () Real)
(declare-fun y () Real)
(declare-fun z () Real)
(assert (>= (* 2 (^ x 2)) (* y z)))
(assert (> x 100))
(assert (< y 0))
(assert (< z 0))
(assert (> (^ y 2) 1234))
(assert (< (^ z 3) -25))
(check-sat) ; sat
(get-model)
(declare-fun b () Int)
(assert (> b x))
(check-sat) ; unknown
Z3 Theorem Prover: Pythagorean Theorem (Non-Linear Artithmetic)
mixing reals and bit-vectors
z3 produces unknown for assertions without quantifiers
z3 existential theory of the reals
Combining nonlinear Real with linear Int
Z3 support for nonlinear arithmetic
Encoding returns "unknown"
For the incremental question, it may be possible to use nlsat with incremental solving, but in this simple example applying a standard method (rise4fun link: http://rise4fun.com/Z3/Ce1F and see: Soft/Hard constraints in Z3 ) there is an unknown, although a model assignment is made, so it may be useful for your purposes. If not, you can try push/pop: Incremental solving in Z3 using push command
(set-option :produce-unsat-cores true)
(set-option :produce-models true)
(declare-const p1 Bool)
(declare-const p2 Bool)
(declare-const p3 Bool)
(declare-const p4 Bool)
(declare-const p5 Bool)
(declare-const p6 Bool)
(declare-const p7 Bool)
(declare-fun x () Real)
(declare-fun y () Real)
(declare-fun z () Real)
(assert (=> p1 (>= (* 2 (^ x 2)) (* y z))))
(assert (=> p2 (> x 100)))
(assert (=> p3 (< y 0)))
(assert (=> p4 (< z 0)))
(assert (=> p5 (> (^ y 2) 1234)))
(assert (=> p6 (< (^ z 3) -25)))
(assert (=> p7 (< x 50)))
(check-sat p1 p2 p3 p4 p5 p6 p7) ; unsat
(get-unsat-core) ; (p2 p7)
(check-sat p1 p2 p3 p4 p5 p6) ; unknown, removed one of the unsat core clauses
(get-model)
(declare-fun b () Int)
(assert (> b x))
(check-sat) ; unknown
I have some confusion of using universal quantifier and declare-const without using forall
(set-option :mbqi true)
(declare-fun f (Int Int) Int)
(declare-const a Int)
(declare-const b Int)
(assert (forall ((x Int)) (>= (f x x) (+ x a))))
I can write like this:
(declare-const x Int)
(assert (>= (f x x) (+ x a))))
with Z3 will explore all the possible values of type Int in this two cases. So what's the difference?
Can I really use the declare-const to eliminate the forall quantifier?
No, the statements are different. Constants in Z3 are nullary (0 arity) functions, so (declare-const a Int) is just syntactic sugar for (declare-fun a () Int), so these two statements are identical. Your second statement (assert (>= (f x x) (+ x a)))) implicitly asserts existence of x, instead of for all x as in your first statement (assert (forall ((x Int)) (>= (f x x) (+ x a)))). To be clear, note that in your second statement, only a single assignment for x needs to satisfy the assertion, not all possible assignments (also note the difference in the function f, and see this Z3#rise script: http://rise4fun.com/Z3/4cif ).
Here's the text of that script:
(set-option :mbqi true)
(declare-fun f (Int Int) Int)
(declare-const a Int)
(declare-fun af () Int)
(declare-const b Int)
(declare-fun bf () Int)
(push)
(declare-const x Int)
(assert (>= (f x x) (+ x a)))
(check-sat) ; note the explicit model value for x: this only checks a single value of x, not all of them
(get-model)
(pop)
(push)
(assert (forall ((x Int)) (>= (f x x) (+ x a))))
(check-sat)
(get-model) ; no model for x since any model must satisfy assertion
(pop)
Also, here's an example from the Z3 SMT guide ( http://rise4fun.com/z3/tutorial/guide from under the section "Uninterpreted functions and constants"):
(declare-fun f (Int) Int)
(declare-fun a () Int) ; a is a constant
(declare-const b Int) ; syntax sugar for (declare-fun b () Int)
(assert (> a 20))
(assert (> b a))
(assert (= (f 10) 1))
(check-sat)
(get-model)
You can eliminate a top-level exists with a declare-const. Maybe this is the source of your confusion? The following two are equivalent:
(assert (exists ((x Int)) (> x 0)))
(check-sat)
and
(declare-fun x () Int)
(assert (> x 0))
(check-sat)
Note that this only applies to top-level existential quantifiers. If you have nested quantification of both universals (forall) and existentials (exists), then you can do skolemization to float the existentials to the top level. This process is more involved but rather straightforward from a logical point of view.
There is no general way of floating universal quantifiers to the top-level in this way, at least not in classical logic as embodied by SMT-Lib.