CVC3 is used to get value assignments satisfying constraints. I have been trying to check the feasibility of replacing the use of CVC3 with Z3. For example, if there are department records like department record = [NAME, SALARY] and following constraints:
1. SALARY > 100 and SALARY < 1000
2. NAME can be one of {abc, def, ghi}
The primary aim is to generate records satisfying some constraints for relations in database.
How can these constraints be specified using Z3 to get possible value assignments to the department records? Is the SMT lib format input file sufficient or should I be looking at the programmatic APIs exposed by Z3?
A possible solution is as follows
(declare-sort S)
(declare-fun abc () S)
(declare-fun def () S)
(declare-fun ghi () S)
(declare-fun NAME () S)
(declare-fun SALARY () Int)
(assert (and (> SALARY 100) (< SALARY 1000)))
(assert (or (= NAME abc) (= NAME def) (= NAME ghi)))
(check-sat)
(get-model)
The corresponding output is
sat
Please run this example online here
I think I found a way to do it.
(declare-datatypes () ((S abc def ghi)))
(declare-fun NAME () S)
(declare-fun SALARY () Int)
(assert (and (> SALARY 100) (< SALARY 1000)))
(assert (or (not (= NAME abc)) (= NAME def) (= NAME ghi)))
(check-sat)
(get-value (NAME))
(get-value (SALARY))
Now the above model will return:
sat
((NAME ghi))
((SALARY 101))
Related
For the following formula
(declare-fun i () Int)
(declare-fun #I () Int)
(declare-fun r2 () (Array Int Int))
(assert (= i 4))
(assert (forall ((#I Int))
(! (=> (and (>= #I 0) (< #I i)) (= (select r2 #I) 0))
:weight 10
:skolemid test
:qid test)))
(check-sat)
(get-model)
The Java API returns:
SATISFIABLE
(define-fun i () Int 4)
(define-fun #I () Int (- 1))
Why it generate specific value for quantifier variable "#I"?
Note that #I is declared twice:
(declare-fun #I () Int)
...
(assert (forall ((#I Int)) ...
Thus, it is indeed both, existential and universal. I've taken the liberty of copying this over into our issue tracker. As discussed there, this is not a bug: "Within the term namespace, bound variables can shadow one another as well as function symbol names ..." is what the SMT2 standard says (Remark 2, Sec. 3.3).
I was trying to represent a real number with two integer numbers as using them as the numerator and the denominator of the real number. I wrote the following program:
(declare-const a Int)
(declare-const b Int)
(declare-const f Real)
(assert (= f (/ a b)))
(assert (= f 0.5))
(assert (> b 2))
(assert (> b a))
(check-sat)
(get-model)
The program returned SAT result as follows:
sat
(model
(define-fun f () Real
(/ 1.0 2.0))
(define-fun b () Int
4)
(define-fun a () Int
2)
)
However, if I write '(assert (= f (div a b)))' instead of '(assert (= f (/ a b)))', then the result is UNSAT. Why does not div return the same result?
Moreover, and the main concern for me, I did not find a way to use operator '/' in z3 .Net API. I can see only function MkDiv, which actually for operator 'div'. Is there a way so that I can apply operator '/' in the case of z3 .Net API? Thank you in advance.
Strictly speaking neither of these formulas is SMT-LIB2 compliant, because / is a function that takes two Real inputs and produces a Real output, whereas div is a function that takes two Int inputs and produces an Int (see SMT-LIB Theories). Z3 is more relaxed and automatically converts those objects. If we enable the option smtlib2_compliant=true then it will indeed report an error in both cases.
The reason for the div version being unsatisfiable is that there is indeed no solution where f is an integer according to (= f (/ a b)), but there is indeed no integer that satisfies (= f 0.5)
I wanted to ask a question about assigning distinct values in Z3.
suppose that I have 6 variables A,B,C,D,E,F.
Now, I would like to assign distinct values to some of them and some of them will be zero. How many variables will be distinct and how many variables are zero is unknown before-hand. It depends on certain other conditions.
generally for all the variables I shall write
(assert (distinct A B C D E F))
However is it possible to write constraint such as A, B, D are zero and others are distinct? Again remember that A,B, D are just example variables. They can change dynamically depending on the constraints.
Thanks !
As far as I understand, you have a set V of variables v1, ..., vn, where each variable vi is either zero or different from all other variables vj, j ≠ i.
As an example, let V = {a, b, c, d}.
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(declare-const d Int)
You could encode your constraints as
(assert (or (= a 0) (not (or (= a b) (= a c) (= a d)))))
(assert (or (= b 0) (not (or (= b a) (= b c) (= b d)))))
(assert (or (= c 0) (not (or (= c a) (= c b) (= c d)))))
(assert (or (= d 0) (not (or (= d a) (= d b) (= d c)))))
Adding two constraints and querying Z3 for a model
(assert (= a 0))
(assert (not (= b 0)))
(check-sat)
(get-model)
then yields
sat
(model
(define-fun b () Int
(- 2))
(define-fun c () Int
(- 1))
(define-fun d () Int
0)
(define-fun a () Int
0)
)
Since generating the "zero or distinct" constraints is a tedious task you'd probably want to work with a Z3 front-end such as PyZ3 or Scala^Z3.
I'm using the latest Z3 version 3.2. I get an unexpected response from the "get-value" command. Here is the little script that I run in SMT-LIB2 compliant mode:
(set-option :produce-models true)
(declare-datatypes () ((Object o0 null)))
(declare-fun IF (Object) Int)
(declare-fun i2 () Int)
(assert (= (IF o0) i2))
(assert (= (IF null) 0))
(check-sat)
(get-value (i2))
The response is:
((i2 (IF o0)))
I expect to get just "0" back. Is there any way to ask Z3 to evaluate the returned term to a universe constant?
Here is the full model:
(model
;; universe for Object:
;; Object!val!0
;; -----------
;; definitions for universe elements:
(declare-fun Object!val!0 () Object)
;; cardinality constraint:
(forall ((x Object)) (= x Object!val!0))
;; -----------
(define-fun i2 () Int
(IF o0))
(define-fun IF ((x!1 Object)) Int
(ite (= x!1 Object!val!0) 0
0))
)
I'm also puzzled why o0 is not defined in the model.
This has been fixed in Z3 4.0.
Z3 4.0 will be released soon. In the meantime, you can use it online: http://rise4fun.com/Z3/75y
This link can be used to execute your example. Z3 4.0 produces the expected result.
Regarding the bug, the main problem is that Z3 is treating Object as an uninterpreted sort.
In Z3 3.2, you can workaround this bug by including
(set-option :auto-config false)
in the beginning of your script.
how can I make a datatype that contains a set of another objects. Basically, I am doing the following code:
(define-sort Set(T) (Array Int T))
(declare-datatypes () ((A f1 (cons (value Int) (b (Set B))))
(B f2 (cons (id Int) (a (Set A))))
))
But Z3 tells me unknown sort for A and B. If I remove "Set" it works just as the guide states.
I was trying to use List instead but it does not work. Anyone knows how to make it work?
You are addressing a question that comes up on a regular basis:
how can I mix data-types and arrays (as sets, multi-sets or
data-types in the range)?
As stated above Z3 does not support mixing data-types
and arrays in a single declaration.
A solution is to develop a custom solver for the
mixed datatype + array theory. Z3 contains programmatic
APIs for developing custom solvers.
It is still useful to develop this example
to illustrate the capabilities and limitations
of encoding theories with quantifiers and triggers.
Let me simplify your example by just using A.
As a work-around you can define an auxiliary sort.
The workaround is not ideal, though. It illustrates some
axiom 'hacking'. It relies on the operational semantics
of how quantifiers are instantiated during search.
(set-option :model true) ; We are going to display models.
(set-option :auto-config false)
(set-option :mbqi false) ; Model-based quantifier instantiation is too powerful here
(declare-sort SetA) ; Declare a custom fresh sort SetA
(declare-datatypes () ((A f1 (cons (value Int) (a SetA)))))
(define-sort Set (T) (Array T Bool))
Then define bijections between (Set A), SetA.
(declare-fun injSA ((Set A)) SetA)
(declare-fun projSA (SetA) (Set A))
(assert (forall ((x SetA)) (= (injSA (projSA x)) x)))
(assert (forall ((x (Set A))) (= (projSA (injSA x)) x)))
This is almost what the data-type declaration states.
To enforce well-foundedness you can associate an ordinal with members of A
and enforce that members of SetA are smaller in the well-founded ordering:
(declare-const v Int)
(declare-const s1 SetA)
(declare-const a1 A)
(declare-const sa1 (Set A))
(declare-const s2 SetA)
(declare-const a2 A)
(declare-const sa2 (Set A))
With the axioms so far, a1 can be a member of itself.
(push)
(assert (select sa1 a1))
(assert (= s1 (injSA sa1)))
(assert (= a1 (cons v s1)))
(check-sat)
(get-model)
(pop)
We now associate an ordinal number with the members of A.
(declare-fun ord (A) Int)
(assert (forall ((x SetA) (v Int) (a A))
(=> (select (projSA x) a)
(> (ord (cons v x)) (ord a)))))
(assert (forall ((x A)) (> (ord x) 0)))
By default quantifier instantiation in Z3 is pattern-based.
The first quantified assert above will not be instantiated on all
relevant instances. One can instead assert:
(assert (forall ((x1 SetA) (x2 (Set A)) (v Int) (a A))
(! (=> (and (= (projSA x1) x2) (select x2 a))
(> (ord (cons v x1)) (ord a)))
:pattern ((select x2 a) (cons v x1)))))
Axioms like these, that use two patterns (called a multi-pattern)
are quite expensive. They produce instantiations for every pair
of (select x2 a) and (cons v x1)
The membership constraint from before is now unsatisfiable.
(push)
(assert (select sa1 a1))
(assert (= s1 (injSA sa1)))
(assert (= a1 (cons v s1)))
(check-sat)
(pop)
but models are not necessarily well formed yet.
the default value of the set is 'true', which
would mean that the model implies there is a membership cycle
when there isn't one.
(push)
(assert (not (= (cons v s1) a1)))
(assert (= (projSA s1) sa1))
(assert (select sa1 a1))
(check-sat)
(get-model)
(pop)
We can approximate more faithful models by using
the following approach to enforce that sets that are
used in data-types are finite.
For example, whenever there is a membership check on a set x2,
we enforce that the 'default' value of the set is 'false'.
(assert (forall ((x2 (Set A)) (a A))
(! (not (default x2))
:pattern ((select x2 a)))))
Alternatively, whenever a set occurs in a data-type constructor
it is finite
(assert (forall ((v Int) (x1 SetA))
(! (not (default (projSA x1)))
:pattern ((cons v x1)))))
(push)
(assert (not (= (cons v s1) a1)))
(assert (= (projSA s1) sa1))
(assert (select sa1 a1))
(check-sat)
(get-model)
(pop)
Throughout the inclusion of additional axioms,
Z3 produces the answer 'unknown' and furthermore
the model that is produced indicates that the domain SetA
is finite (a singleton). So while we could patch the defaults
this model still does not satisfy the axioms. It satisfies
the axioms modulo instantiation only.
This is not supported in Z3. You can use arrays in datatype declarations, but they can't contain "references" to the datatypes you are declaring. For example, it is ok to use (Set Int).