Acessing elements of a sort w/ multiple fields - z3

I'm having some trouble using sorts in the SMTlib2 format. For example, I define an Interval as:
(declare-sort Pair 2)
(define-sort Interval () (Pair Int Int))
Now how can I return a new Interval from a function? e.g.:
(define-fun getInterval ((a Int) (b Int)) Interval
(Interval a b))
This doesn't work.
My question is: how can I construct and instantiate objects of a given sort, and how can I access their fields?
Right now I'm using 2 UFs that I created as field getters, but I still don't know how to have a constructor:
(declare-fun L (Interval) Int)
(declare-fun H (Interval) Int)
Thanks,
Nuno

You should look into Record subsection, Datatypes section in Z3 SMT guide. Basically, you can create a record type with a constructor mk-pair and two selectors first and second for accessing its fields.
Here is an examplerise4fun link:
(set-option :macro-finder true)
(declare-datatypes (T1 T2) ((Pair (mk-pair (first T1) (second T2)))))
(define-sort Interval () (Pair Int Int))
(define-fun getInterval ((a Int) (b Int)) Interval
(mk-pair a b))
(declare-const p1 Interval)
(declare-const p2 Interval)
;construct objects of a give sort
(assert (= p1 (getInterval 2 2)))
;accessing their fields
(assert (= (first p1) (second p2)))
(check-sat)
(get-model)

Related

Converting Z3 QBF formula directly to pcnf

I'm using Z3 theorem prover (using Z3Py: the Z3 API in Python) to create QBF (Quantified Boolean formula).
Is there any way in Z3 to directly convert your qbf formula into Prenex normal form ?
I don't think there's a tactic to convert to Prenex, but you can surely apply the quantifier-elimination tactic and further process your formulas. Note that the transformed formulas will not really look like the originals, as they are mechanically generated.
Here's an example:
from z3 import *
f = Function('f', IntSort(), IntSort(), IntSort())
x, y = Ints('x y')
p = ForAll(x, Or(x == 2, Exists(y, f (x, y) == 0)))
print Tactic('qe')(p)
Here qe is the quantifier elimination tactic. This produces:
[[Not(Exists(x!0,
Not(Or(x!0 == 2,
Exists(x!1,
And(f(x!0, x!1) <= 0,
f(x!0, x!1) >= 0))))))]]
For a nice tutorial on tactics, see here: http://ericpony.github.io/z3py-tutorial/strategies-examples.htm
You could use the skolemize tactic (snf) which will by definition be in prenex form. However it will also eliminate existential quantifiers which is not what you want. Here's an example.
(declare-fun a (Int) Bool)
(declare-fun b (Int) Bool)
(declare-fun c (Int) Bool)
(assert
(forall ((x Int))
(or
(exists ((y Int))
(a y)
)
(exists ((z Int))
(=>
(b z)
(c x)
)
)
)
)
)
(apply
(and-then
; mode (symbol) NNF translation mode: skolem (skolem normal form), quantifiers (skolem normal form + quantifiers in NNF), full (default: skolem)
(using-params snf :mode skolem)
)
:print_benchmark true
:print false
)
When Z3 is given the above it will responds with something like
(declare-fun c (Int) Bool)
(declare-fun b (Int) Bool)
(declare-fun a (Int) Bool)
(assert (forall ((x Int))
(or (exists ((y Int)) (a y)) (exists ((z Int)) (=> (b z) (c x))))))
(check-sat)
You can see the available tactics by running
echo "(help-tactic)" | ./z3 -in | less
from a bash shell.
Unfortunately I can't see one that states it does conversion to prenex.

Z3 Output of get-value

I have a problem with the generation of model values through get-value.
If I try to get the value of an array, I will get a value
containing internal z3 constants which are not printed. I know that
get-model would print those constants but I would like to stick
to using get-value.
Here is an example (I tried it on rise4fun):
(declare-const b (Array Int Int))
(declare-const a (Array Int Int))
(assert (= (store a 1 2) b))
(check-sat)
(get-value (b a))
returns:
sat ((b (_ as-array k!1)) (a (_ as-array k!0)))
The output with get-model is the following:
sat (model (define-fun b () (Array Int Int) (_ as-array k!1)) (define-fun a () (Array Int Int) (_ as-array k!0)) (define-fun k!0 ((x!1 Int)) Int 0) (define-fun k!1 ((x!1 Int)) Int (ite (= x!1 1) 2 0)) )
It contains the value of k!0 and k!1. Is it possible to substitute these in the values for a and b ?
This is a limitation with Z3's modeling of arrays.
get-value isn't guaranteed to give meaningful results for arrays.

Equivalent of "store" operator for Records in z3

I am wondering if there is an operator for Records in z3 similar to the "store" operator for arrays. That is, given a record, is there any way to return a new record in which we've changed one element and all other elements retain their values? For instance:
(declare-datatypes (T1 T2) ((Pair (mk-pair (first T1) (second T2)))))
(declare-const p1 (Pair Int Int))
(declare-const p2 (Pair Int Int))
(assert (= p1 (mk-pair 1 2)))
(assert (= p2 (store p1 second 3)))
The last line above is an example of what I would like to do. Is there any way to do this? Or is the user-defined constructor the only means to construct a new record? Thank you.
You could try your luck with:
(declare-datatypes (T1 T2) ((Pair (mk-pair (first T1) (second T2)))))
(declare-const p1 (Pair Int Int))
(declare-const p2 (Pair Int Int))
(assert (= p1 (mk-pair 1 2)))
(assert (= p2 ((_ update-field second) p1 3)))
Alternatively, you just create a new record that has the same fields as the old one, except for the specified field.

Can I use declare-const to eliminate the forall universal quantifier?

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.

Use Z3 and SMT-LIB to get a maximum of two values

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

Resources