How to produce the model for partial orders? - z3

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

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.

Z3 Interpolants in presence of quantifiers

I am experimenting with iZ3 to see if I can derive quantified invariants making use of iZ3's get-interpolant functionality. Here is my example:
(set-option :auto-config false)
(set-option :smt.mbqi true)
(set-option :smt.macro-finder true)
(set-option :produce-interpolants true)
(declare-sort T0)
(declare-const l1 T0)
(declare-const l2 T0)
(declare-const v T0)
(declare-sort T1)
(declare-const z1 T1)
(declare-const z2 T1)
(declare-const z3 T1)
(declare-fun Rmem (T0 T1) Bool)
(declare-const phi1 Bool)
(declare-const phi2 Bool)
(declare-const assn1 Bool)
(declare-const assn2 Bool)
;; A fact: \forall x. (Rmem(l1) = {x}) => (Rmem(v) = {x} \union Rmem(l2))
(assert (! (= phi1 (forall ((x T1))
(=> (forall ((bv0 T1)) (= (Rmem l1 bv0) (= bv0 x)))
(forall ((bv0 T1)) (= (Rmem v bv0)
(or (Rmem l2 bv0) (= bv0 x))))))) :named f1))
;; An observation: When (Rmem(l1) = {z1}) and (Rmem(l2)= {z2,z3}), then
;; Rmem(v) was observed to be {z1,z2,z3}
(assert (! (= phi2 (! (=> (and (forall ((bv0 T1))
(= (Rmem l1 bv0) (= bv0 z1)))
(forall ((bv0 T1))
(= (Rmem l2 bv0) (or (= bv0 z2) (= bv0 z3)))))
(forall ((bv0 T1))
(= (Rmem v bv0) (or (= bv0 z1) (= bv0 z2)
(= bv0 z3))))))) :named f2))
(assert (= assn2 (and phi1 (not phi2))))
(assert assn2)
(check-sat)
;; Can Z3 derive the following invariant: Rmem(v) = Rmem(l1) \union Rmem(l2)?
(get-interpolant f1 f2)
For the above example, Z3 prints Unsat (as expected), but nothing else.
Does this mean that Z3 was unable to derive interpolants from the proof of unsatisfiability?
I understand that iZ3 has limited support for quantifiers. Notwithstanding, I expected interpolation to succeed because my example is in decidable (EPR) logic. Is the failure due to inherent limitations of Z3? If not, are there any alternative ways constructing my query?
I get this result for your file:
unsat
(forall ((%0 T1))
(! (let ((a!1 (exists ((%1 T1)) (! (= (not (Rmem l1 %1)) (= %1 %0)) :qid itp)))
(a!2 (forall ((bv0 T1))
(! (= (Rmem v bv0) (or (Rmem l2 bv0) (= bv0 %0)))
:pattern ((Rmem v bv0))
:pattern ((Rmem l2 bv0))))))
(or a!1 a!2))
:qid itp))
Can you say what version/architecture you're using?

Defining injective functions in Z3

My goal is to define an injective function f: Int -> Term, where Term is some new sort. Having referred to the definition of the injective function, I wrote the following:
(declare-sort Term)
(declare-fun f (Int) Term)
(assert (forall ((x Int) (y Int))
(=> (= (f x) (f y)) (= x y))))
(check-sat)
This causes a timeout. I suspect that this is because the solver tries to validate the assertion for all values in the Int domain, which is infinite.
I also checked that the model described above works for some custom sort instead of Int:
(declare-sort Term)
(declare-sort A)
(declare-fun f (A) Term)
(assert (forall ((x A) (y A))
(=> (= (f x) (f y)) (= x y))))
(declare-const x A)
(declare-const y A)
(assert (and (not (= x y)) (= (f x) (f y))))
(check-sat)
(get-model)
The first question is how to implement the same model for Int sort instead of A. Can solver do this?
I also found the injective function example in the tutorial in multi-patterns section. I don't quite get why :pattern annotation is helpful. So the second question is why :pattern is used and what does it brings to this example particularly.
I am trying this
(declare-sort Term)
(declare-const x Int)
(declare-const y Int)
(declare-fun f (Int) Term)
(define-fun biyect () Bool
(=> (= (f x) (f y)) (= x y)))
(assert (not biyect))
(check-sat)
(get-model)
and I am obtaining this
sat
(model
;; universe for Term:
;; Term!val!0
;; -----------
;; definitions for universe elements:
(declare-fun Term!val!0 () Term)
;; cardinality constraint:
(forall ((x Term)) (= x Term!val !0))
;; -----------
(define-fun y () Int
1)
(define-fun x () Int
0)
(define-fun f ((x!1 Int)) Term
(ite (= x!1 0) Term!val!0
(ite (= x!1 1) Term!val!0
Term!val!0)))
)
What do you think about this
(declare-sort Term)
(declare-fun f (Int) Term)
(define-fun biyect () Bool
(forall ((x Int) (y Int))
(=> (= (f x) (f y)) (= x y))))
(assert (not biyect))
(check-sat)
(get-model)
and the output is
sat
(model
;; universe for Term:
;; Term!val!0
;; -----------
;; definitions for universe elements:
(declare-fun Term!val!0 () Term)
;; cardinality constraint:
(forall ((x Term)) (= x Term!val!0))
;; -----------
(define-fun x!1 () Int 0)
(define-fun y!0 () Int 1)
(define-fun f ((x!1 Int)) Term
(ite (= x!1 0) Term!val!0
(ite (= x!1 1) Term!val!0
Term!val!0)))
)

Can options change `sat` into `unsat`?

Another question from a Z3 newbie. Can options change the behavior of Z3? I might expect them to affect termination, or change sat or unsat into unknown but not sat into unsat or vice versa.
This example:
(set-option :smt.macro-finder true)
(declare-datatypes () ((Option (none) (some (Data Int)))))
(define-sort Set () (Array Option Option))
(declare-fun filter1 (Option) Option)
(declare-fun filter2 (Option) Option)
(declare-var s1 Set)
(declare-var s2 Set)
(declare-var x1 Option)
(declare-var x2 Option)
(declare-var x3 Option)
(declare-var x4 Option)
(assert (not (= x1 none)))
(assert (not (= x2 none)))
(assert (not (= x3 none)))
(assert (not (= x4 none)))
(assert (= (select s1 x1) x2))
(assert (= (select s2 x3) x4))
(assert (forall ((x Option)) (= (filter1 x) (ite (or (= none x) (= (Data x) 1)) x none))))
(assert (forall ((x Option)) (= (filter2 x) (ite (or (= none x) (= (Data x) 2)) x none))))
(assert (= ((_ map filter1) s1) s2))
(assert (= ((_ map filter2) s1) s2))
(check-sat)
(get-model)
returns sat with the first line and unsat without it.
Is this a bug or am I missing something fundamental?
This is a bug. The two quantifiers are essentially providing "definitions" for filter1 and filter2.
The option smt.macro-finder is used to eliminate functions symbols by expanding these definitions. It is essentially performing "macro expansion". However, there is a bug in the macro expander. It does not expand the occurrences of filter1 and filter2 in the map constructs: (_ map filter1) and (_ map filter2).
This bug will be fixed.
In the meantime, we should not use the map construct and smt.macro-finder option simultaneously.

eval returns a let statement

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.

Resources