Three ways to assgin values to an array in z3 - 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.

Related

Z3 Checking whether all values in array are unique

So I'm trying to check whether all values in an array is unique with the following Z3 code.
(declare-const A (Array Int Int))
(declare-const n Int)
(assert (forall ((i Int) (j Int)) (and (and (and (>= i 0) (< i n)) (and (>= j 0) (< j n)))
(implies (= (select A i) (select A j)) (= i j)))))
(check-sat)
I'm quite new to Z3 so I don't quite understand the grammar and stuff, but can anyone tell me whether this code is right, and if not, where's the problem?
The problem as you wrote is unsat, because it says whenever 0 <= i < n and 0 <= j < n, if A[i] = A[j], then i = j. There is no array and a particular n you can pick to satisfy this constraint.
What you really want to write is the following instead:
(declare-const A (Array Int Int))
(declare-const n Int)
(assert (forall ((i Int) (j Int)) (implies (and (>= i 0) (< i n)
(>= j 0) (< j n)
(= (select A i) (select A j)))
(= i j))))
(check-sat)
(get-model)
The above says If it's the case that i and j are within bounds, and array elements are the same, then i must equal j. And this variant would be satisifiable for any n; and indeed here's what z3 reports:
sat
(
(define-fun n () Int
0)
(define-fun A () (Array Int Int)
((as const (Array Int Int)) 0))
)
But note that z3 simply picked n = 0, which made it easy to satisfy the formula. Let's make sure we get a more interesting model, by adding:
(assert (> n 2))
Now we get:
sat
(
(define-fun n () Int
3)
(define-fun A () (Array Int Int)
(lambda ((x!1 Int))
(let ((a!1 (ite (and (<= 1 x!1) (not (<= 2 x!1))) 7 8)))
(ite (<= 1 x!1) (ite (and (<= 1 x!1) (<= 2 x!1)) 6 a!1) 5))))
)
and we see that z3 picked the array to have 3 elements with distinct values at positions we care about.
Note that this sort of reasoning with quantifiers is a soft-spot for SMT solvers; while z3 is able to find models for these cases, if you keep adding quantified axioms you'll likely get unknown as the answer, or z3 (or any other SMT solver for that matter) will take longer and longer time to respond.

Quantifier patterns in Z3

I am having trouble attempting to prove this fairly simple Z3 query.
(set-option :smt.auto-config false) ; disable automatic self configuration
(set-option :smt.mbqi false) ; disable model-based quantifier instantiation
(declare-fun sum (Int) Int)
(declare-fun list () (Array Int Int))
(declare-fun i0 () Int)
(declare-fun s0 () Int)
(declare-fun i1 () Int)
(declare-fun s1 () Int)
(assert (forall ((n Int))
(! (or (not (<= n 0)) (= (sum n) 0))
:pattern ((sum n)))))
(assert (forall ((n Int))
(! (let ((a1 (= (sum n)
(+ (select list (- n 1))
(sum (- n 1))))))
(or (<= n 0) a1))
:pattern ((sum n)))))
(assert (>= i0 0))
(assert (= s0 (sum i0)))
(assert (= i1 (+ 1 i0)))
(assert (= s1 (+ 1 s0 (select list i0))))
(assert (not (= s1 (sum i1))))
(check-sat)
Seems to me that the final assertion should instantiate the second quantified statement for i1 while the assert involving s0 should instantiate the quantifiers for i0. These two should should easily lead to UNSAT.
However, Z3 returns unknown. What am I missing?
Never mind, there was an silly error in my query.
This code:
(assert (= s1 (+ 1 s0 (select list i0))))
should have been:
(assert (= s1 (+ s0 (select list i0))))

Z3 set default value of array to zero

I am trying to solve models for array expressions, where default values for array is equal to 0.
For example, I am trying to solve this example, but I get unknown results all the time
(declare-const arr (Array Int Int))
(declare-const arr2 (Array Int Int))
(declare-const a Int)
(declare-const b Int)
(assert (forall ((x Int)) (= (select arr x) 0)))
(assert (> a 0))
(assert (<= a 10))
(assert (= arr2 (store arr a 1337)))
(assert (> b 0))
(assert (<= b 10))
(assert (= (select arr2 b) 0))
(check-sat)
(get-model)
Patrick's advice on not using quantifiers is spot on! They'll make your life harder. However, you're in luck, because z3 supports constant-arrays for your use case, which is quite common. The syntax is:
(assert (= arr ((as const (Array Int Int)) 0)))
This makes sure arr will have all its entries as 0; no quantification needed and z3 handles it internally just fine.
So, your benchmark will be:
(declare-const arr (Array Int Int))
(declare-const arr2 (Array Int Int))
(declare-const a Int)
(declare-const b Int)
(assert (= arr ((as const (Array Int Int)) 0)))
(assert (> a 0))
(assert (<= a 10))
(assert (= arr2 (store arr a 1337)))
(assert (> b 0))
(assert (<= b 10))
(assert (= (select arr2 b) 0))
(check-sat)
(get-model)
which is solved in no time. This way, you can have the entire array start with 0, and modify the range you're interested in; which can depend on variables as usual and is not required to be known ahead of time.

Function with ordered arguments

It seems that uninterpret functions treat arguments as unordered.
For example,
(declare-fun Lturn (Int Int Int) Bool)
(assert (forall ((x Int) (y Int) (z Int))
(not (= (Lturn x y z) (Lturn x z y)))))
(check-sat)
The result is UNSAT.
The above code is available here: http://rise4fun.com/Z3/hkpwO
To overcome this situation, I tried using array:
(declare-fun Lturn ((Array Int Int)) Bool)
(assert (forall ((A1 (Array Int Int)) (A2 (Array Int Int)))
(=> (and (= (select A1 1) (select A2 1))
(= (select A1 2) (select A2 3))
(= (select A1 3) (select A2 2)))
(not (= (Lturn A1) (Lturn A2))))))
(check-sat)
The result is "unknown."
The above code is available here: http://rise4fun.com/Z3/bdTL
Is there any method to let the Array version be SAT?
Function arguments are not unordered. Can you give a function Lturn that would make your assertion SAT? Here's a simpler case with just two arguments: http://rise4fun.com/Z3/Zsjs
For x == 0 && y == 0 && z == 0 there is no function such that f(x, y, z) != f(x, z, y) because f(0, 0, 0) != f(0, 0, 0) is always false.

Modeling array assignment in Z3

I'm working on a project for program verification. I have the following statement to be modeled in Z3:
temp = a[i];
a[i] = a[j];
a[j] = temp;
All the variables are of integer type. Would someone give me some hints on how to build constraints to model the above statements?
Here is a general "recipe".
We represent array updates using (store a i v). The result is a new array equal to a, but at position i contains the value v.
An array access a[i] should be encoded as (select a i).
Assignments such as i = i + 1 are usually encoded by creating Z3 variables that represent the value of i before and after the assignment. That is, we would encode it as (= i1 (+ i0 1)).
Keep in mind that the formula (= i (+ i 1)) is equivalent to false.
Here is the example above encode in SMT 2.0 format.
http://www.rise4fun.com/Z3/G5Zk
Here is the script found in the link above.
(declare-const a0 (Array Int Int))
(declare-const a1 (Array Int Int))
(declare-const a2 (Array Int Int))
(declare-const temp0 Int)
(declare-const temp1 Int)
(declare-const i0 Int)
(declare-const j0 Int)
(assert (= temp0 (select a0 i0)))
(assert (= a1 (store a0 i0 (select a0 j0))))
(assert (= a2 (store a1 j0 temp0)))
(check-sat)
(get-model)

Resources