|
Nikolaj Bjørner
Microsoft Research
nbjorner@microsoft.com |
Check satisfiability of
(declare-fun RangeLU (Int) Bool)
(declare-fun A (Int) Bool)
(declare-const lo Int)
(declare-const hi Int)
(declare-const x Int)
(declare-const y Int)
(assert (< lo x y hi))
; express that RangeLU = [lo..hi]
(define-fun below_lo ((i Int)) Bool (=> (<= i (- lo 1)) (not (RangeLU i))))
(define-fun in_range ((i Int)) Bool (=> (>= i (+ hi 1)) (not (RangeLU i))))
(define-fun above_hi ((i Int)) Bool (=> (and (<= lo i) (<= i hi)) (RangeLU i)))
(assert (forall ((i Int)) (below_lo i)))
(assert (forall ((i Int)) (in_range i)))
(assert (forall ((i Int)) (above_hi i)))
; express that [l..u] \ { x, y } \subseteq A \subseteq [l..u] \ { x }
(define-fun below-A ((i Int)) Bool (=> (and (RangeLU i) (not (= i x)) (not (= i y))) (A i)))
(define-fun above-A ((i Int)) Bool (=> (A i) (and (RangeLU i) (not (= i x)))))
(assert (forall ((i Int)) (below-A i)))
(assert (forall ((i Int)) (above-A i)))
(check-sat)
(get-model)
(reset)
; read set of free variables:
; R := { x, y }
; read set for bound variables:
; B := { lo - 1, hi + 1, lo, hi }
;
(declare-fun RangeLU (Int) Bool)
(declare-fun A (Int) Bool)
(declare-const lo Int)
(declare-const hi Int)
(declare-const x Int)
(declare-const y Int)
(assert (< lo x y hi))
(assert (< (+ lo 10) hi))
(define-const r1 Int x)
(define-const r2 Int y)
(define-const b1 Int (- lo 1))
(define-const b2 Int (+ hi 1))
(define-const b3 Int lo)
(define-const b4 Int hi)
(define-fun below-lo ((i Int)) Bool (=> (<= i (- lo 1)) (not (RangeLU i))))
(define-fun in-range ((i Int)) Bool (=> (>= i (+ hi 1)) (not (RangeLU i))))
(define-fun above-hi ((i Int)) Bool (=> (and (<= lo i) (<= i hi)) (RangeLU i)))
(assert (below-lo r1))
(assert (below-lo r2))
(assert (below-lo b1))
(assert (below-lo b2))
(assert (below-lo b3))
(assert (below-lo b4))
(assert (in-range r1))
(assert (in-range r2))
(assert (in-range b1))
(assert (in-range b2))
(assert (in-range b3))
(assert (in-range b4))
(assert (above-hi r1))
(assert (above-hi r2))
(assert (above-hi b1))
(assert (above-hi b2))
(assert (above-hi b3))
(assert (above-hi b4))
; express that [l..u] \ { x, y} \subseteq A \subseteq [l..u] \ { x }
(define-fun below-A ((i Int)) Bool (=> (and (RangeLU i) (not (= i x)) (not (= i y))) (A i)))
(define-fun above-A ((i Int)) Bool (=> (A i) (and (RangeLU i) (not (= i x)))))
(assert (above-A r1))
(assert (above-A r2))
(assert (above-A b1))
(assert (above-A b2))
(assert (above-A b3))
(assert (above-A b4))
(assert (below-A r1))
(assert (below-A r2))
(assert (below-A b1))
(assert (below-A b2))
(assert (below-A b3))
(assert (below-A b4))
(check-sat)
(get-model)Run z3 with model.compact=false We get a model, corresponding to assigned atoms:
(define-fun RangeLU ((x!0 Int)) Bool
(ite (= x!0 1) true
(ite (= x!0 2) true
(ite (= x!0 (- 1)) false
(ite (= x!0 11) true
(ite (= x!0 12) false
(ite (= x!0 0) true
true)))))))
(define-fun A ((x!0 Int)) Bool
(ite (= x!0 1) false
(ite (= x!0 2) false
(ite (= x!0 (- 1)) false
(ite (= x!0 12) false
(ite (= x!0 0) true
(ite (= x!0 11) true
false)))))))
The ite guards are based on assigned atoms. We can ignore the default case. Here it is arbitrary.
For RangeLU we should have the interpretation .
The set should be equal to except two elements, these are . So the expected interpretation of is .
Let us recall the correctness proof for the array property fragment. We will consider the special case for a single bound variable to keep it simple.
Define projection function project such that
For example project(-3) = project(-2) = projec(-1) = -1.
We would like to build an interpretation over finite sets from the above interpretation using project. Define:
for every integer z.
Then
Given
Suppose we have a model for for every in the instantation set .
Let us show that for every z:
Then it follows from transitivity of that .
Recall that can be assumed to be a conjunction , . Then as project(z) is the a term in inst that maps to the nearest value close to z. Then, the truth value of , or is the same. This proves (1)
is a disjunction of ground formulas or (negated) membership constraints . Assume . Then one of the disjunctions in is true. Suppose it is project(z) in A. Now, we constructed . Therefore .
If we construct a model from our instantiation set we don't get a well-formed model. What is going on?
The problem is that our quantified formula wasn't in the right format.
(define-fun below-A ((i Int)) Bool (=> (and (RangeLU i) (not (= i x)) (not (= i y))) (A i)))
is not in the format of . Guards cannot be atoms .
Instead we have to create multiple guards to capture the property in the array fragment:
(define-fun below-A-1 ((i Int)) Bool (=> (and (RangeLU i) (< i x) (< i y)) (A i)))
(define-fun below-A-1 ((i Int)) Bool (=> (and (RangeLU i) (< x i) (< i y)) (A i)))
(define-fun below-A-1 ((i Int)) Bool (=> (and (RangeLU i) (< y i) (< i x)) (A i)))
(define-fun below-A-1 ((i Int)) Bool (=> (and (RangeLU i) (> i x) (> i y)) (A i)))
Thus, the index set now includes .
We can now turn our attention to the following question: how do we best automatically detect instantation sets from finite set formulas?
In a nutshell we want to ensure that we have enough membership constraints for ranges to force composite constraints to evaluate correctly if we use the nearest neighbor projection function.
For example if the atomic formula exists then we should also evaluate it on .
Range local terms: For every range expression define the range local terms as initially .
Saturating range local terms: Whenever occurs and is assigned to true and x is not a range local term, then add to range local terms and add atoms for .
If we can't assume complete assignments for ground formulas, this saturation rule is insufficient.
For example, we could have () holds for because and and and we don't need the truth value of to evaluate this formula (to false) for .
The way we got from finite set constraints to the array property fragment was to encode every connective with universal axioms. For example,
It suffices to retrace range-local terms from axioms.
Claim: The following extension will do the trick: Whenever occurs, and x is not a range local term, then add range local terms .
A set expression is a value if:
Assume isvalue can be evaluated over the base sort of .
Task: Given two sets that satisfy isvalue, develop a good algorithm and implementation to check if they are equal.