Z3 Output of get-value - z3

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.

Related

Three ways to assgin values to an array in z3

As far as I know, there are three ways to assgin values to an array in z3.
use assert to assgin values to some of the cells:
(declare-const a1 (Array Int Int))
(declare-const a2 (Array Int Int))
(assert (= 1 (select a1 0)))
(assert (= 2 (select a2 0)))
z3 returns unsat when the constraint (assert (= a1 a2)) is added.
use as const to initialize the array first and then assgin values to specific cells:
(declare-const a3 (Array Int Int))
(assert
(=
(store ((as const (Array Int Int)) 64) 0 3)
a3
)
)
(declare-const a4 (Array Int Int))
(assert
(=
(store ((as const (Array Int Int)) 64) 0 4)
a4
)
)
Add (assert (= a3 a4)) and we obtain unsat again.
define the array via a function:
(define-const a5 (Array Int Int)
(lambda ((i Int))
(ite (= i 0) 5 64)))
(define-const a6 (Array Int Int)
(lambda ((i Int))
(ite (= i 0) 6 64)))
But if we add (assert (= a5 a6)), z3 returns sat. Why?
By the way, is there any (better) way to assign values to an array in z3?
It's a bug. Check out this issue.

Z3 converting "small" BitVectors to Ints

I know that both bv2int and int2bv are handled as uninterpreted functions in Z3. Still, I am looking for a best practice in solving the following problem: given a "small" (< 10 bits) bitvector index,
how to efficiently cast it to Int, and use in queries like this one:
(declare-const s String)
(declare-const someInt Int)
(declare-const someBitVec10 (_ BitVec 10))
(assert (= s "74g\x00!!#2#$$"))
;(assert (str.in.re (str.at s someBitVec10) (re.range "a" "z")))
( assert (str.in.re (str.at s someInt ) (re.range "1" "3")))
(check-sat)
(get-value (s someInt))
Output:
sat
((s "74g\x00!!#2#$$")
(someInt 7))
Thanks!

Z3 Solver outputting the satisfying model?

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.

Getting concrete values from a model containing "array-ext"

When I combine arrays and quantifiers, Z3 often produces models containing applications of array-ext. For example, this test case produces the following model:
(define-fun pipeid () (Array Int Int)
(_ as-array k!2))
(define-fun valid () (Array Int Bool)
(_ as-array k!0))
(define-fun ispipe () (Array Int Bool)
(_ as-array k!1))
(define-fun pipeid_ab () Int
2)
(define-fun fd () Int
0)
(define-fun k!3 ((x!1 Int)) Int
(ite (= x!1 0) 0
(array-ext (_ as-array k!0) (_ as-array k!1))))
(define-fun k!0!4 ((x!1 Int)) Bool
(ite (= x!1 3) false
true))
(define-fun k!0 ((x!1 Int)) Bool
(k!0!4 (k!3 x!1)))
(define-fun k!1 ((x!1 Int)) Bool
true)
(define-fun k!2!5 ((x!1 Int)) Int
(ite (= x!1 3) 4
1))
(define-fun k!2 ((x!1 Int)) Int
(k!2!5 (k!3 x!1)))
First, what does the array-ext in k!3 mean? I've pieced together that (array-ext a b) is some index x for which a[x] != b[x], but either what I've pieced together is incorrect or I can't wrap my head around the circular definitions of k!0 and k!3 above.
Second, how can I extract concrete values from such models? I know that it's not in general possible to represent the concrete value of an array directly in the model, but I would like to at least understand what its concrete value is and be able to extract it in some form from the model. Even querying for individual array indices doesn't seem to help:
model.evaluate(pipeid[1]) => If(array-ext(as-array, as-array) = 3, 4, 1)
Thanks.
array-ext is an internal function symbol. It is used to implement array extensionality.
That being said, it should not appear in models. The model-based-quantifier-instantiation (MBQI) module accidentally "leaks" the array-ext into the model. I fixed the problem.
http://z3.codeplex.com/SourceControl/changeset/185f125f7a3d356192df272bfb2339ad36d3cdf9
The fix is already available in the unstable (work-in-progress) branch.
It will also be available in the nightly builds.
Here is the output after the bug fix:
(define-fun pipeid () (Array Int Int)
(_ as-array k!2))
(define-fun valid () (Array Int Bool)
(_ as-array k!0))
(define-fun ispipe () (Array Int Bool)
(_ as-array k!1))
(define-fun pipeid_ab () Int
2)
(define-fun fd () Int
0)
(define-fun k!3 ((x!1 Int)) Int
0)
(define-fun k!0!4 ((x!1 Int)) Bool
(ite (= x!1 3) false
true))
(define-fun k!0 ((x!1 Int)) Bool
(k!0!4 (k!3 x!1)))
(define-fun k!1 ((x!1 Int)) Bool
true)
(define-fun k!2!5 ((x!1 Int)) Int
(ite (= x!1 3) 4
1))
(define-fun k!2 ((x!1 Int)) Int
(k!2!5 (k!3 x!1)))
pipeid[0] => 1
pipeid[1] => 1

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.

Resources