max value in set z3 - z3

I'm a new guy to work with the Z3.
Would like to know how I can calculate the maximum value of a set and two different sets.
For example:
[1, 6, 5] - The greater is 6
[1, 6, 5] e [10, 7, 2] - The greater is 6
I use the following code to set:
(declare-sort Set 0)
(declare-fun contains (Set Int) bool)
( declare-const set Set )
( declare-const distinct_set Set )
( declare-const A Int )
( declare-const B Int )
( declare-const C Int )
( assert ( = A 0 ) )
( assert ( = B 1 ) )
( assert ( = C 2 ) )
( assert ( distinct A C) )
( assert ( distinct set distinct_set ) )
(assert
(forall ((x Int))
(= (contains set x) (or (= x A) (= x C)))))
And now would like to know how can I calculate the largest value in the set (set) and the largest value in sets (set and distinct_set).
If it was for all integers was only because it was easy to do:
(define-fun max ((x Int) (y Int)) Int
(ite (< x y) y x))
But I can not leave with sets by their integers, ie, get the values ​​that have set.
Can you help me?
Thanks

Is the following encoding reasonable for your purposes? It is also available online here.
; We Enconde each set S of integers as a function S : Int -> Bool
(declare-fun S1 (Int) Bool)
; To assert that A and C are elements of S1, we just assert (S1 A) and (S1 C)
(declare-const A Int)
(declare-const C Int)
(assert (S1 A))
(assert (S1 C))
; To say that B is not an element of S1, we just assert (not (S1 B))
(declare-const B Int)
(assert (not (S1 B)))
; Now, let max_S1 be the max value in S1
(declare-const max_S1 Int)
; Then, we now that max_S1 is an element of S1, that is
(assert (S1 max_S1))
; All elements in S1 are smaller than or equal to max_S1
(assert (forall ((x Int)) (=> (S1 x) (not (>= x (+ max_S1 1))))))
; Now, let us define a set S2 and S3
(declare-fun S2 (Int) Bool)
(declare-fun S3 (Int) Bool)
; To assert that S3 is equal to the union of S1 and S2, we just assert
(assert (forall ((x Int)) (= (S3 x) (or (S1 x) (S2 x)))))
; To assert that S3 is not equal to S1 we assert
(assert (exists ((x Int)) (not (= (S3 x) (S1 x)))))
(check-sat)
; Now let max_S3 be the maximal value of S3
(declare-const max_S3 Int)
(assert (S3 max_S3))
(assert (forall ((x Int)) (=> (S3 x) (not (>= x (+ max_S3 1))))))
; the set of constraints is still satisfiable
(check-sat)
; Now, let us assert that max_S3 < max_S1.
; It should be unsat, since S3 is a super set of S1
(assert (< max_S3 max_S1))
(check-sat)

Related

Having assertions inside definitions in SMT

I want to capture the assertion inside fac.
int f( x )
{
if( x == 1) return 1;
else{
assert( x > 0 );
return 2;
}
}
int g (x)
{ assert( x > 5 );
return f(x-1) + f(x-2);
}
I want an smt2 code for this.
I can do this by striping the argument and making it global with unique name (also rename inside f), then do this 3 times each with a different name for function. Like below :
( declare-const x1 Int )
(define-fun f1 () Int
( ite ( x1 > 0) 1 2 )
)
(assert (> x1 0))
( declare-const x2 Int )
(define-fun f2 () Int
( ite ( x2 > 0) 1 2 )
)
(assert (> x2 0))
( declare-const x3 Int )
(define-fun g1 () Int
( + f1 f2 )
)
(assert (> x3 5))
I don't want to this. Is there any other way to do this without repeating ?
EDIT
My purpose is to find values violating the asserts.
As far as I know, it is not possible to embed assertions within function definitions.
What I would try to do is to separate the expected behavior, the input assumptions and the output guarantees (if any).
Example:
(define-fun f ((x Int)) Int
(ite (= x 1) 1 2)
)
(define-fun f-helper ((x Int)) Bool
(< 0 x)
)
(define-fun g ((x Int)) Int
(+ (f (- x 1)) (f (- x 2)))
)
(define-fun g-helper ((x Int)) Bool
(and (< 5 x)
(f-helper (- x 1))
(f-helper (- x 2))
)
)
(declare-const x Int)
(declare-const y Int)
(assert (and (= y (g x))
(g-helper x)
))
(check-sat)
(get-model)
In this example we use f to model the behavior of the original function f, and f-helper to model the assumptions of f. The output, using the online Z3 tool, is as follows:
sat
(model
(define-fun x () Int
6)
(define-fun y () Int
4)
)
I would conclude saying that this approach could become tricky as soon as f and g are used inside both positive and negative contexts.. in this case one should pay extra attention that the polarity of the assertions is correct wrt. the expected result.

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 invariant check

I want a way to, given an invariant and one or more operation's effects, check if, after the operation's execution, the invariant still holds.
Any ideas on how to accomplish this?
Using Z3 I was thinking of doing something similar to
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(declare-const d Int)
(define-fun invariant () Bool
(= a b c d 2)
)
(assert invariant)
(assert (= a 1)) ;operation1
(assert (= b 2)) ;operation2
(assert (not invariant))
(check-sat)
If (check-sat) returns unsat then I conclude that the system's state is valid after the operations.
I obviously can't do the above since
(assert invariant)
(assert (not invariant))
always make the theorem unsat.
But I need to assert that the initial state is valid so that the parts of the system that aren't changed by the operations are valid when I run (assert (not invariant)).
I assume that your operations mutate some kind of state (local variables, a program heap, ...), and your invariant should therefore be a function of the state.
As a small example, consider this hypothetical imperative program with local variables:
var start: Int := 0
var end: Int := 0
var arr: Array[Int] := new Array(10) // Array of ints, size 10
fill(arr, 0) // Fill the array with zeros
def invariant() =
(0 < start <= end)
&& forall i in [start, end - 1) :: arr(i) < arr(i + 1) // Sorted
assert invariant() // holds
end := end + 1
assert invariant() // holds
end := end + 1
assert invariant() // fails
arr(start + 1) := arr(start + 1) + 1
assert invariant() // holds
It could be encoded as follows, where the mutated local variables are represented in static single assignment form:
(define-fun invariant ((start Int) (end Int) (arr (Array Int Int))) Bool
(and
(<= 0 start)
(<= start end)
(forall ((i Int))
(implies
(and (<= start i) (< i (- end 1)))
(< (select arr i) (select arr (+ i 1)))))))
(declare-const start0 Int)
(declare-const end0 Int)
(declare-const arr0 (Array Int Int))
(assert (= start0 0))
(assert (= end0 0))
(assert (= arr0 ((as const (Array Int Int)) 0)))
(push)
(assert (not (invariant start0 end0 arr0)))
(check-sat) ;; UNSAT --> Invariant holds
(pop)
;; Operation: end := end + 1
(declare-const end1 Int)
(assert (= end1 (+ end0 1)))
(push)
(assert (not (invariant start0 end1 arr0)))
(check-sat) ; UNSAT --> Invariant still holds
(pop)
;; Operation: end := end + 1
(declare-const end2 Int)
(assert (= end2 (+ end1 1)))
(push)
(assert (not (invariant start0 end2 arr0)))
(check-sat) ; SAT --> Invariant has been broken!
(pop)
;; Operation: arr[start + 1] := arr[start + 1] + 1
(declare-const arr1 (Array Int Int))
(assert (= arr1 (store arr0 (+ start0 1) (+ (select arr0 (+ start0 1)) 1))))
(push)
(assert (not (invariant start0 end2 arr1)))
(check-sat) ; UNSAT --> Invariant has been restored
(pop)

z3 times out in case of a formula with quantifiers

I am getting timeout on the following example.
http://rise4fun.com/Z3/zbOcW
Is there any trick to make this work (eg.by reformulating the problem or using triggers)?
For this example, the macro finder will be useful (I think often with forall quantifiers with implications), you can enable it with:
(set-option :macro-finder true)
Here's your updated example that gets sat quickly (rise4fun link: http://rise4fun.com/Z3/Ux7gN ):
(set-option :macro-finder true)
(declare-const a (Array Int Bool))
(declare-const sz Int)
(declare-const n Int)
(declare-const d Int)
(declare-const r Bool)
(declare-const x Int)
(declare-const y Int)
;;ttff
(declare-fun ttff (Int Int Int) Bool)
(assert
(forall ((x1 Int) (y1 Int) (n1 Int))
(= (ttff x1 y1 n1)
(and
(forall ((i Int))
(=> (and (<= x1 i) (< i y1))
(= (select a i) true)))
(forall ((i Int))
(=> (and (<= y1 i) (< i n1))
(= (select a i) false)))))))
;; A1
(assert (and (<= 0 n) (<= n sz)))
;; A2
(assert (< 0 d))
;; A3
(assert (and (and (<= 0 x) (<= x y)) (<= y n)))
;; A4
(assert (ttff x y n))
;; A6
(assert
(=> (< 0 y)
(= (select a (- y 1)) true)))
;; A7
(assert
(=> (< 0 x)
(= (select a (- x 1)) false)))
;;G
(assert
(not
(iff
(and (<= (* 2 d) (+ n 1)) (ttff (- (+ n 1) (* 2 d)) (- (+ n 1) d) (+ n 1)))
(and (= (- (+ n 1) y) d) (<= d (- y x))))))
(check-sat)
(get-model)

contains for two sets in Z3

If I want to check if a set has elements of another set is also possible?
For example (contains Set1 Set2):
contains [1,2] [3,5] -> is false
contains [1] [2,3, 1] -> is true
The sets are finite. And the maximum value of the sets is five and the minimum is 0, the sets may not have values greater than 5 neither smaller than 0.
For example:
[1,5,3] -> valid set
[1,8,2] -> invalid set
If it were only for a set and check whether a value exist in the set was easy. It was in the following way:
( declare-sort Set 0 )
( declare-fun contains (Set Int) bool )
( declare-const set Set )
( declare-const A Int )
( assert ( contains set A ))
( assert ( not (contains set 0 )))
( check-sat )
But for two sets I do not see how it's done.
Thank you for your attention.
The operation (contains S1 S2) that you describe in your message is the subset relation. If we encode sets of integers as functions from Int to Boolean (like in: max value in set z3), then S1 and S2 are declared as:
(declare-fun S1 (Int) Bool)
(declare-fun S2 (Int) Bool)
Then, we can say that S1 is a subset of S2 by asserting
(assert (forall ((x Int)) (=> (S1 x) (S2 x))))
We just saying that any element in S1 is also an element of S2.
EDIT
We can use the expression (exists ((x Int)) (and (S1 x) (S2 x))) to check whether the sets S1 and S2 have an element in common or not
END EDIT
The minimal element of a set can be encoded as we did in max value in set z3.
For example, suppose the minimal element of S1 is min_S1.
; Now, let min_S1 be the min value in S1
(declare-const min_S1 Int)
; Then, we now that min_S1 is an element of S1, that is
(assert (S1 min_S1))
; All elements in S1 are bigger than or equal to min_S1
(assert (forall ((x Int)) (=> (S1 x) (not (<= x (- min_S1 1))))))
If the minimal values of the sets you are encoding are known at "encoding time" (and are small). We can use yet another encoding based on Bit-vectors.
In this encoding, a set is a Bit-vector. If the sets only contain values between 0 and 5, then we can use a Bit-vector of size 6. The idea is: if bit i is true iff i is an element of the set.
Here is an example with the main operation:
(declare-const S1 (_ BitVec 6))
(declare-const S2 (_ BitVec 6))
(declare-const S3 (_ BitVec 6))
; set equality is just bit-vector equality
(assert (= S1 S2))
; set intersection, union, and complement are encoded using bit-wise operations
; S3 is S1 union S2
(assert (= S3 (bvor S1 S2)))
; S3 is S1 intersection of S2
(assert (= S3 (bvand S1 S2)))
; S3 is the complement of S1
(assert (= S3 (bvnot S1)))
; S1 is a subset of S2 if S1 = (S1 intersection S2), that is
(assert (= S1 (bvand S1 S2)))
; S1 is the empty set if it is the 0 bit-vector
(assert (= S1 #b000000))
; To build a set that contains only i we can use the left shift
; Here, we assume that i is also a bit-vector
(declare-const i (_ BitVec 6))
; S1 is the set that contains only i
; We are also assuming that i is a value in [0, 5]
(assert (= S1 (bvshl #b000001 i)))

Resources