Strange result for arrays and datatypes when using OCaml API - z3

I am using Z3 via Ocaml binding. For the following formula
(set-info :status unknown)
(set-logic ALL)
(declare-datatypes ((Loc 0)) (((|1|) (|2|) (|3|) (|4|) (|5|))))
(declare-fun z () Loc)
(declare-fun y () Loc)
(declare-fun x () Loc)
(declare-fun nil () Loc)
(declare-fun |global fp| () (Array Loc Bool))
(declare-fun heap () (Array Loc Loc))
(declare-fun footprint0 () (Array Loc Bool))
(declare-fun heap0 () (Array Loc Loc))
(declare-fun footprint1 () (Array Loc Bool))
(declare-fun footprint4 () (Array Loc Bool))
(declare-fun footprint3 () (Array Loc Bool))
(declare-fun footprint2 () (Array Loc Bool))
(assert
(let (($x59 (select |global fp| nil)))
(let (($x60 (not $x59)))
(let ((?x61 (select heap nil)))
(let (($x62 (= nil ?x61)))
(let (($x58 (= footprint0 |global fp|)))
(let (($x96 (forall ((l!0 Loc) )(let (($x49 (= (select heap l!0) (select heap0 l!0))))
(or (not (select footprint0 l!0)) $x49)))
))
(let ((?x20 ((as const (Array Loc Bool)) false)))
(let ((?x38 (store ?x20 y true)))
(let (($x39 (= footprint4 ?x38)))
(let (($x28 (= footprint1 footprint3)))
(let (($x27 (= footprint1 footprint2)))
(let (($x32 (or $x27 $x28)))
(let (($x26 (= footprint3 ?x20)))
(let ((?x21 (store ?x20 x true)))
(let (($x22 (= footprint2 ?x21)))
(let ((?x36 (select heap0 y)))
(let (($x37 (= ?x36 z)))
(and
(or $x28 (and (= (select heap0 x) y) $x27))
$x37
(= ((_ map and ) footprint1 ((_ map not ) footprint4)) ?x20)
$x22 $x26 $x32 $x39
(= footprint0 ((_ map and ) footprint4 ((_ map not ) footprint1)))
$x96 $x58 $x62 $x60
(not (= nil |5|)) (not (= x |5|)) (not (= y |5|)) (not (= z |5|))
)))))))))))))))))))
(check-sat)
I got the following model:
(define-fun footprint4 () (Array Loc Bool)
(store ((as const (Array Loc Bool)) true) |2| false))
(define-fun x () Loc
|1|)
(define-fun footprint0 () (Array Loc Bool)
(store (store ((as const (Array Loc Bool)) true) |1| false) |2| false))
(define-fun footprint3 () (Array Loc Bool)
(store (store ((as const (Array Loc Bool)) true) |1| false) |2| false))
(define-fun z () Loc
|1|)
(define-fun nil () Loc
|1|)
(define-fun |global fp| () (Array Loc Bool)
(store (store ((as const (Array Loc Bool)) true) |1| false) |2| false))
(define-fun y () Loc
|1|)
(define-fun heap () (Array Loc Loc)
(store ((as const (Array Loc Loc)) |1|) |2| |2|))
(define-fun footprint1 () (Array Loc Bool)
(store ((as const (Array Loc Bool)) true) |2| false))
(define-fun footprint2 () (Array Loc Bool)
(store ((as const (Array Loc Bool)) true) |2| false))
(define-fun heap0 () (Array Loc Loc)
((as const (Array Loc Loc)) |1|))
I think that the result is incorrect because the formula asserts that array footprint3 is a constant array of false values (expressions ?x20 and $x26). But in the model, for example, footprint3[|3|] is true.
Is the model indeed incorrect, or is there some aspect of combining datatypes with arrays that I am missing?
Also, when storing formula to a file and running Z3 from the command line, I will obtain an expected model. Therefore I was not able to minimize the example.

Related

Why is Z3 unable to prove `unsat` for this query, whereas cvc5 succeeds?

I have a (relatively) simple query attached below
(set-logic AUFLIRA)
(set-option :produce-models true)
(declare-sort Loc 0)
(declare-sort HeapChunk 0)
(declare-sort HeapIndex 0)
(declare-fun makeHeapChunk (Loc Real) HeapChunk)
(declare-fun valid ((Array HeapIndex HeapChunk)) Bool)
(declare-const empty (Array HeapIndex HeapChunk))
(assert (
forall (
(heap (Array HeapIndex HeapChunk))
(i1 HeapIndex)
(i2 HeapIndex)
(l1 Loc)
(l2 Loc)
(own_val1 Real)
(own_val2 Real)
)
(=>
(and
(valid heap)
(= (select heap i1) (makeHeapChunk l1 own_val1))
(= (select heap i2) (makeHeapChunk l2 own_val2))
(> (+ own_val1 own_val2) 1)
(not (= i1 i2))
)
(not (= l1 l2))
)
))
(declare-const index0 HeapIndex)
(declare-const index1 HeapIndex)
(assert (not (= index0 index1)))
(declare-const l1 Loc)
(declare-const heap0 (Array HeapIndex HeapChunk))
(assert (valid heap0))
(assert (= heap0 (store empty index0 (makeHeapChunk l1 0.6))))
(declare-const heap1 (Array HeapIndex HeapChunk))
(assert (valid heap1))
(assert (= heap1 (store heap0 index1 (makeHeapChunk l1 0.5))))
(check-sat)
(get-model)
(exit)
It should return unsat because heap1 contains two elements which violate the constraints in the big assertion (essentially because 0.6 + 0.5 > 1 and valid(heap1)). Giving this example to cvc5 returns unsat which is the expected outcome, but z3 returns unknown. I want to understand why, and what I can do to help z3 figure this out.
Thanks in advance.

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.

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

Defining Set in z3

To create a Sets of 3 elements (1,2,3) in Z3, I am using the follows code:
(define-sort Set () ( Array Int Bool ) )
(declare-const s Set )
( assert ( and ( = ( select s 1 ) true ) ( = ( select s 2 ) true )
( = ( select s 3 ) true ) ) )
The Model I am getting is as follows :
(model
(define-fun s () (Array Int Bool)
(_ as-array k!0))
(define-fun k!0 ((x!1 Int)) Bool
(ite (= x!1 2) true
(ite (= x!1 3) true
(ite (= x!1 1) true
true))))
)
But instead how can I get a model of the form :
(model (define-fun s () (Array Int Bool)
(_ as-array k!0)) (define-fun k!0 ((x!1 Int)) Bool
(ite (= x!1 2) true
(ite (= x!1 3) true
(ite (= x!1 1) true
false)))) )
So that elements other than the set members are not included in the set.
You can achieve this by starting from the empty set, i.e. the array that is defined to be false everywhere.
Here is an example:
(declare-const s1 (Array Int Bool))
(assert (= s1
(store
(store
(store
((as const (Array Int Bool)) false)
1 true)
2 true)
3 true)
))
(check-sat)
(get-model)

Simplifying uninterpreted functions in Z3

Is there any way to apply simplifications to uninterpreted functions defined in z3, rather than the goals and subgoals ?
I have the following z3 code :
(declare-fun f (Bool Bool) Bool)
(assert (forall ((b1 Bool) (b2 Bool))
(implies b2 (f b1 b2))))
(assert (exists ((b1 Bool) (b2 Bool))
(not (f b1 b2))))
(check-sat)
(get-model)
And I get the following output:
sat
(model
(define-fun b1!1 () Bool
false)
(define-fun b2!0 () Bool
false)
(define-fun k!7 ((x!1 Bool)) Bool
false)
(define-fun f!8 ((x!1 Bool) (x!2 Bool)) Bool
(ite (and (= x!1 false) (= x!2 true)) true
false))
(define-fun k!6 ((x!1 Bool)) Bool
(ite (= x!1 false) false
true))
(define-fun f ((x!1 Bool) (x!2 Bool)) Bool
(f!8 (k!7 x!1) (k!6 x!2)))
)
It turns out that by applying rewrite rules to the definition of f, we can get that
f is equal to the second argument (x!2) by the following derivation:
(f!8 (k!7 x!1) (k!6 x!2))
= (f!8 false (k!6 x!2))
= (f!8 false x!2)
=(x!2)
Is there any way to get z3 to produce the following definition automatically ?
(define-fun f ((x!1 Bool) (x!2 Bool)) Bool
(x!2))
Thanks for your help.
Regards,
Oswaldo.
One option is to ask Z3 to evaluate the expression (f x y) where x and y are fresh Boolean constants. The eval command will evaluated (f x y) in the current model, and will produce y in your example. Here is the complete example (also available online here):
(declare-fun f (Bool Bool) Bool)
; x and y are free Boolean constants that will be used to create the expression (f x y)
(declare-const x Bool)
(declare-const y Bool)
(assert (forall ((b1 Bool) (b2 Bool))
(implies b2 (f b1 b2))))
(assert (exists ((b1 Bool) (b2 Bool))
(not (f b1 b2))))
(check-sat)
(eval (f x y))

Resources