eval returns a let statement - z3

I am running the below SMT2 spec in Z3. The goal is to get an answer to the eval at the end -- either true or false -- but instead I get a let statement. Is this a bug, or am I supposed to be interpreting the let in a certain way? Compiling by hand gives me false and it appears to be pretty straightforward, but Z3 seems to confused.
(declare-sort PolymorphicClass 0)
(declare-fun PolymorphicClass!val!6 () PolymorphicClass)
(declare-fun PolymorphicClass!val!13 () PolymorphicClass)
(declare-fun PolymorphicClass!val!2 () PolymorphicClass)
(declare-fun PolymorphicClass!val!12 () PolymorphicClass)
(declare-fun PolymorphicClass!val!14 () PolymorphicClass)
(declare-fun PolymorphicClass!val!10 () PolymorphicClass)
(declare-fun PolymorphicClass!val!8 () PolymorphicClass)
(declare-fun PolymorphicClass!val!9 () PolymorphicClass)
(declare-fun PolymorphicClass!val!15 () PolymorphicClass)
(declare-fun PolymorphicClass!val!0 () PolymorphicClass)
(declare-fun PolymorphicClass!val!1 () PolymorphicClass)
(declare-fun PolymorphicClass!val!11 () PolymorphicClass)
(declare-fun PolymorphicClass!val!3 () PolymorphicClass)
(declare-fun PolymorphicClass!val!5 () PolymorphicClass)
(declare-fun PolymorphicClass!val!4 () PolymorphicClass)
(declare-fun PolymorphicClass!val!7 () PolymorphicClass)
(define-fun k!623 ((x!1 PolymorphicClass)) PolymorphicClass
(ite (= x!1 PolymorphicClass!val!15) PolymorphicClass!val!15
(ite (= x!1 PolymorphicClass!val!2) PolymorphicClass!val!2
(ite (= x!1 PolymorphicClass!val!7) PolymorphicClass!val!7
(ite (= x!1 PolymorphicClass!val!8) PolymorphicClass!val!8
(ite (= x!1 PolymorphicClass!val!10) PolymorphicClass!val!10
(ite (= x!1 PolymorphicClass!val!9) PolymorphicClass!val!9
(ite (= x!1 PolymorphicClass!val!14) PolymorphicClass!val!14
(ite (= x!1 PolymorphicClass!val!0) PolymorphicClass!val!0
(ite (= x!1 PolymorphicClass!val!6) PolymorphicClass!val!6
(ite (= x!1 PolymorphicClass!val!5) PolymorphicClass!val!5
(ite (= x!1 PolymorphicClass!val!1) PolymorphicClass!val!1
(ite (= x!1 PolymorphicClass!val!4) PolymorphicClass!val!4
(ite (= x!1 PolymorphicClass!val!12) PolymorphicClass!val!12
(ite (= x!1 PolymorphicClass!val!11) PolymorphicClass!val!11
PolymorphicClass!val!13)))))))))))))))
(define-fun isBlog!641 ((x!1 PolymorphicClass)) Bool
(ite (= x!1 PolymorphicClass!val!0) true
(ite (= x!1 PolymorphicClass!val!1) true
false)))
(define-fun isBlog ((x!1 PolymorphicClass)) Bool
(isBlog!641 (k!623 x!1)))
(check-sat)
(get-model)
(eval (isBlog PolymorphicClass!val!6))
(exit)
Here is the output I get from Z3:
sat
(model
)
(let ((a!1 (ite (= PolymorphicClass!val!6 PolymorphicClass!val!9)
PolymorphicClass!val!9
(ite (= PolymorphicClass!val!6 PolymorphicClass!val!14)
PolymorphicClass!val!14
(ite (= PolymorphicClass!val!6 PolymorphicClass!val!0)
PolymorphicClass!val!0
PolymorphicClass!val!6)))))
(let ((a!2 (ite (= PolymorphicClass!val!6 PolymorphicClass!val!7)
PolymorphicClass!val!7
(ite (= PolymorphicClass!val!6 PolymorphicClass!val!8)
PolymorphicClass!val!8
(ite (= PolymorphicClass!val!6 PolymorphicClass!val!10)
PolymorphicClass!val!10
a!1)))))
(let ((a!3 (ite (= PolymorphicClass!val!6 PolymorphicClass!val!15)
PolymorphicClass!val!15
(ite (= PolymorphicClass!val!6 PolymorphicClass!val!2)
PolymorphicClass!val!2
a!2))))
(or (= a!3 PolymorphicClass!val!0) (= a!3 PolymorphicClass!val!1)))))

Your values have not been used in any real constraints (only in definitions).
You can use model completion to ensure that Z3 evaluates values that have not been used in constraints.
So you can call:
(eval (isBlog PolymorphicClass!val!6) :model-completion true)
to get the appropriate evaluation.
See the related question: Z3 4.3: get complete model for additional information.

Related

How to code this in Z3

I'm trying to code in Z3 a very simple problem but I got confuse and I don't know how to solve it properly.
So I have an Array with these elements (Python syntax style code):
array = [0, -1, 1, 8, 43]
And I have an access to this array using an index:
x = array[index]
And finally I want to ask z3 what index I need to use to get the element 8, in my example the solution is index = 3 (starting at 0).
I am trying to code this problem in Z3, I wrote the next lines:
(declare-const x Int)
(declare-const index Int)
(assert (= x
(ite (= index 0)
0
(ite (= index 1)
-1
(ite (= index 2)
1
(ite (= index 3)
8
(ite (= index 4)
43
999999)))))))
(assert (= x 8))
(check-sat)
(get-model)
And it is working, I had this solution:
sat
(model
(define-fun index () Int
3)
(define-fun x () Int
8)
)
But I don't like the last else, the 999999. I needed to use a magic number to know when the value is not found. I tried to see if there is a "it" construction without the else, or a NULL/None/UNSAT or any special value to don't have this problem.
What is the correct way to solve this problem?
Thank you for the help!
I know nothing about the "correct" way to solve this problem, since one should probably define "correct" in the first place.
However, there are many ways in which you can encode it as an smt2 formula.
Example 0.
By simply forcing index to fall within the domain [0, 4], you can get the ite do what you want it to do without the need for any magic number.
(declare-const x Int)
(declare-const index Int)
(assert (= x
(ite (= index 0)
0
(ite (= index 1)
-1
(ite (= index 2)
1
(ite (= index 3)
8
43))))))
(assert (and (<= 0 index) (<= index 4)))
(assert (= x 8))
(check-sat)
(get-model)
which returns you the desired model:
~$ z3 example_00.smt2
sat
(model
(define-fun index () Int
3)
(define-fun x () Int
8)
)
Example 1.
(declare-const x Int)
(declare-const index Int)
(assert (ite (= index 0) (= x 0) true))
(assert (ite (= index 1) (= x (- 1)) true))
(assert (ite (= index 2) (= x 1) true))
(assert (ite (= index 3) (= x 8) true))
(assert (ite (= index 4) (= x 43) true))
(assert (and (<= 0 index) (<= index 4)))
(assert (= x 8))
(check-sat)
(get-model)
which returns you the desired model:
~$ z3 example_01.smt2
sat
(model
(define-fun index () Int
3)
(define-fun x () Int
8)
)
Example 2.
(declare-const x Int)
(declare-const index Int)
(assert (or (not (= index 0)) (= x 0))) ;; (= index 0) -> (= x 0)
(assert (or (not (= index 1)) (= x (- 1))))
(assert (or (not (= index 2)) (= x 1)))
(assert (or (not (= index 3)) (= x 8)))
(assert (or (not (= index 4)) (= x 43)))
(assert (and (<= 0 index) (<= index 4)))
(assert (= x 8))
(check-sat)
(get-model)
which returns you the desired model:
~$ z3 example_02.smt2
sat
(model
(define-fun index () Int
3)
(define-fun x () Int
8)
)
Example 3.
Using the Theory of Arrays
(declare-fun x () Int)
(declare-fun index () Int)
(declare-const ar (Array Int Int))
; array's locations initialization
(assert (= (store ar 0 0) ar))
(assert (= (store ar 1 (- 1)) ar))
(assert (= (store ar 2 1) ar))
(assert (= (store ar 3 8) ar))
(assert (= (store ar 4 43) ar))
; x = ar[index]
(assert (= (select ar index) x))
; bound index to fall within specified locations
(assert (and (<= 0 index) (<= index 4)))
; x = 8
(assert (= x 8))
; check
(check-sat)
(get-model)
which returns you the desired model:
~$ z3 example_03.smt2
sat
(model
(define-fun x () Int
8)
(define-fun ar () (Array Int Int)
(_ as-array k!0))
(define-fun index () Int
3)
(define-fun k!0 ((x!0 Int)) Int
(ite (= x!0 2) 1
(ite (= x!0 3) 8
(ite (= x!0 1) (- 1)
(ite (= x!0 0) 0
(ite (= x!0 4) 43
5))))))
)
Other examples are possible.
Ideally one would pick the encoding for which z3 has the best performance in solving your formula. On this regard I can not help you, since I typically deal with other SMT solvers.
In general, using more complex theories (e.g. Theory of Arrays) results in the run-time executing more expensive routines so one could think that it's best to avoid it. However, I would say that in my experience this is not a general rule of thumb, since even slight variations of the encoding can result in significant performance differences and very poor or naive encodings can perform pretty bad. Therefore, it's always best to perform extensive bench-marking on various candidate encodings.

How can I write a long smt-lib expression with an existential quantifier?

I have the following expression
(declare-fun x00 () Real)
(declare-fun x01 () Real)
(declare-fun x10 () Real)
(declare-fun x11 () Real)
(declare-fun t0init () Real)
(declare-fun z0init0 () Real)
(declare-fun z0init1 () Real)
(assert (>= t0init 0))
(assert (= (+ x00 z0init0) x10))
(assert (= (+ x01 z0init1) x11))
(assert (< (+ (* 1 x00)(* 0 x01)) 0.0))
(assert (= (+ (* 0 x00)(* 1 x01)) 0.0))
(assert (< (+ (* 1 x10)(* 0 x11)) 0.0))
(assert (= (+ (* 0 x10)(* 1 x11)) 0.0))
...
(assert (< (+ (* 1 x40)(* 0 x41)) 0.0))
(assert (= (+ (* 0 x40)(* 1 x41)) 0.0))
(assert (= (+ (* 1 z4end0)(* 0 z4end1)) (* t4end 1)))
(assert (= (+ (* 0 z4end0)(* 1 z4end1)) (* t4end -2)))
and I would like to express as a simple formula in order to express the following:
(assert exists (x00 x01) ("the above expression"))
and then perform a quantifier elimination.
Is there anyone who knows how to proceed?
I know how to do it with z3py but I need some faster solution.
Thank you very much for any hint.
One possible solution is as follows
(declare-fun x00 () Real)
(declare-fun x01 () Real)
(declare-fun x10 () Real)
(declare-fun x11 () Real)
(declare-fun t0init () Real)
(declare-fun z0init0 () Real)
(declare-fun z0init1 () Real)
(define-fun conjecture () Bool
(and (>= t0init 0) (= (+ x00 z0init0) x10) (= (+ x01 z0init1) x11)))
(assert (exists ((x00 Real) (x01 Real)) conjecture))
(check-sat)
and the corresponding output is
sat
I am not sure if the quantifier elimination that you need will work with Z3. Maybe for your problem "Redlog" of "Reduce" is the better option. All the best.

How to produce the model for partial orders?

I am trying to use Z3 to produce a model for a set of SAT assertions describing a partial order theory. I tried the subtype example in Z3 guide but it seems I cannot get a concrete model. Is there a way that Z3 can produce a model that describes the orders among elements and satisfies all assertions I made?
For example, following are the constraints for "subtype". Is it possible that Z3 may produce a model like "int-type *<* real-type *<* complex-type *<* obj-type *<* root-type" and "string-type *<* obj-type *<* root-type" (if I use "*<*" to denote subtype relation)?
(set-option :produce-models true)
(declare-sort Type)
(declare-fun subtype (Type Type) Bool)
(assert (forall ((x Type)) (subtype x x)))
(assert (forall ((x Type) (y Type))
(=> (and (subtype x y) (subtype y x))
(= x y))))
(assert (forall ((x Type) (y Type) (z Type))
(=> (and (subtype x y) (subtype y z))
(subtype x z))))
(assert (forall ((x Type) (y Type) (z Type))
(=> (and (subtype x y) (subtype x z))
(or (subtype y z) (subtype z y)))))
(declare-const obj-type Type)
(declare-const int-type Type)
(declare-const real-type Type)
(declare-const complex-type Type)
(declare-const string-type Type)
(assert (forall ((x Type)) (subtype x obj-type)))
(assert (subtype int-type real-type))
(assert (subtype real-type complex-type))
(assert (not (subtype string-type real-type)))
(declare-const root-type Type)
(assert (subtype obj-type root-type))
(check-sat)
(get-model)
Currently, I got
sat
(model
;; universe for Type:
;; Type!val!0 Type!val!3 Type!val!2 Type!val!4 Type!val!1
;; -----------
;; definitions for universe elements:
(declare-fun Type!val!0 () Type)
(declare-fun Type!val!3 () Type)
(declare-fun Type!val!2 () Type)
(declare-fun Type!val!4 () Type)
(declare-fun Type!val!1 () Type)
;; cardinality constraint:
(forall ((x Type))
(or (= x Type!val!0)
(= x Type!val!3)
(= x Type!val!2)
(= x Type!val!4)
(= x Type!val!1)))
;; -----------
(define-fun complex-type () Type
Type!val!2)
(define-fun real-type () Type
Type!val!1)
(define-fun obj-type () Type
Type!val!4)
(define-fun root-type () Type
Type!val!4)
(define-fun string-type () Type
Type!val!3)
(define-fun int-type () Type
Type!val!0)
(define-fun subtype!73 ((x!1 Type) (x!2 Type)) Bool
(ite (and (= x!1 Type!val!3) (= x!2 Type!val!1)) false
(ite (and (= x!1 Type!val!2) (= x!2 Type!val!3)) false
(ite (and (= x!1 Type!val!4) (= x!2 Type!val!1)) false
(ite (and (= x!1 Type!val!4) (= x!2 Type!val!3)) false
(ite (and (= x!1 Type!val!2) (= x!2 Type!val!1)) false
(ite (and (= x!1 Type!val!1) (= x!2 Type!val!3)) false
(ite (and (= x!1 Type!val!4) (= x!2 Type!val!0)) false
(ite (and (= x!1 Type!val!4) (= x!2 Type!val!2)) false
(ite (and (= x!1 Type!val!0) (= x!2 Type!val!3)) false
(ite (and (= x!1 Type!val!2) (= x!2 Type!val!0)) false
(ite (and (= x!1 Type!val!1) (= x!2 Type!val!0)) false
(ite (and (= x!1 Type!val!3) (= x!2 Type!val!0)) false
true)))))))))))))
(define-fun k!72 ((x!1 Type)) Type
(ite (= x!1 Type!val!1) Type!val!1
(ite (= x!1 Type!val!4) Type!val!4
(ite (= x!1 Type!val!3) Type!val!3
(ite (= x!1 Type!val!0) Type!val!0
Type!val!2)))))
(define-fun subtype ((x!1 Type) (x!2 Type)) Bool
(subtype!73 (k!72 x!1) (k!72 x!2)))
)
Thank you in advance for any help you could give.
I think that your line
(assert (forall ((x Type)) (subtype x obj-type)))
is wrong.
The correct is
(assert (forall ((x Type)) (subtype x root-type)))
The possible correct model is obtained here

How to execute the following SMT-LIB code using Alt-Ergo

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_UF)
(set-option :incremental true)
(set-option :produce-models true)
(declare-fun m () Bool)
(declare-fun p () Bool)
(declare-fun b () Bool)
(declare-fun c () Bool)
(declare-fun r () Bool)
(declare-fun al () Bool)
(declare-fun all () Bool)
(declare-fun la () Bool)
(declare-fun lal () Bool)
(declare-fun g () Bool)
(declare-fun a () Bool)
(define-fun conjecture () Bool
(and (= (and (not r) c) m) (= p m) (= b m) (= c (not g))
(= (and (not al) (not all)) r) (= (and la b) al)
(= (or al la lal) all) (= (and (not g) p a) la)
(= (and (not g) (or la a)) lal)))
(push 1)
(assert (and conjecture (= a false) (= g false)))
(check-sat)
(get-model)
(pop 1)
(push 1)
(assert (and conjecture (= a false) (= g true)))
(check-sat)
(get-model)
(pop 1)
(push 1)
(assert (and conjecture (= a true) (= g true)))
(check-sat)
(get-model)
(pop 1)
(push 1)
(assert (and conjecture (= a true) (= g false)))
(check-sat)
(get-model)
For now, Alt-Ergo does not provide a full support for the SMT-2 format. In particular, the command get-model is not recognized.
Moreover, the commands push and pop are ignored. This is why Alt-Ergo says sat, unsat, ..., unsat on the given code (when get-model is removed).

soundness issue with integer/bv mixed benchmarks?

I've the following SMT-Lib2 script:
(set-option :produce-models true)
(declare-fun s0 () Int)
(declare-fun table0 (Int) (_ BitVec 8))
(assert (= (table0 0) #x00))
(assert
(let ((s3 (ite (or (< s0 0) (<= 1 s0)) #x01 (table0 s0))))
(let ((s5 (ite (bvuge s3 #x02) #b1 #b0)))
(= s5 #b1))))
(check-sat)
(get-model)
With Z3 v3.2 running on the Mac, I get:
sat
(model
;; universe for (_ BitVec 8):
;; bv!val!2 bv!val!3 bv!val!0 bv!val!1
;; -----------
;; definitions for universe elements:
(declare-fun bv!val!2 () (_ BitVec 8))
(declare-fun bv!val!3 () (_ BitVec 8))
(declare-fun bv!val!0 () (_ BitVec 8))
(declare-fun bv!val!1 () (_ BitVec 8))
;; cardinality constraint:
(forall ((x (_ BitVec 8)))
(and (= x bv!val!2) (= x bv!val!3) (= x bv!val!0) (= x bv!val!1)))
;; -----------
(define-fun s0 () Int
(- 1))
(define-fun table0 ((x!1 Int)) (_ BitVec 8)
(ite (= x!1 0) bv!val!0
(ite (= x!1 (- 1)) bv!val!3
bv!val!0)))
)
Which states that s0 = -1 is a model. However, with s0 = -1, we have s3 = 1 and s5 = #b0, which makes the assertion false. In fact, I'm quite sure the benchmark as stated is unsatisfiable.
One thing I noticed in the Z3 output is the quantified formula it gives for the cardinality constraint. It says:
;; cardinality constraint:
(forall ((x (_ BitVec 8)))
(and (= x bv!val!2) (= x bv!val!3) (= x bv!val!0) (= x bv!val!1)))
The assertion is a conjunction, which sounds rather weird; shouldn't that be a disjunction? I'm not sure if this is the root-cause of the problem, but it sure sounds fishy.
There are two problems in Z3.
First, you are correct, there is a typo in the model printer. It should be a "or" instead of an "and". The second problem is that Z3 did not install the bit-vector theory and treated (_ BitVec 8) as a uninterpreted sort. This was a bug in the preprocessor that is used to decide in which logic the problem is in. You can workaround this bug by adding the following command in the beginning of the file:
(set-option :auto-config false)
These bugs have been fixed, and the fix will be available in the next release.

Resources