Z3中bitvector的成员

时间:2013-03-21 01:06:34

标签: z3 bitvector

我需要知道如何在z3中执行以下操作:

L4中的forall x。 x< L2

L0中的forall x和L1中的forall y。 x< ÿ

(declare-const L4 (_ BitVec 6))
(declare-const L1 (_ BitVec 6))
(declare-const L0 (_ BitVec 6))
(declare-const l2 Int)
(declare-const l1 Int)

断言L0和L1使得x <1。 ÿ

(check-sat)

结果是星期六

断言L0和L1使y <0。 X

(check-sat)

结果是UnSat

1 个答案:

答案 0 :(得分:2)

我假设您正在使用位向量来编码有限集。 所以,这是一个可能的编码(它也可以在线here):

;; You use bit-vectors of size 6. That is, we are encoding sets that are subsets of {0, 1, 2, ... 5}
(declare-const L4 (_ BitVec 6))
(declare-const L1 (_ BitVec 6))
(declare-const L0 (_ BitVec 6))
;; I will also encode l1 and l2 as Bit-Vectors.
;; Thus, I don't need to convert them into Bit-vectors to be able to use them in Bit-vector operations.
(declare-const l1 (_ BitVec 6))
(declare-const l2 (_ BitVec 6))
;; To make the problems more interesting let us assume that l1 and l2 are <= 5
(assert (bvsle l1 (_ bv5 6)))
(assert (bvsle l2 (_ bv5 6)))

;; All is encoding the set that contains {0, 1, 2, 3, 4, 5}
(define-const All (_ BitVec 6) #b111111) 
;; Empty is encoding the empty set
(define-const Empty (_ BitVec 6) #b000000) 

(define-fun LT_l ((S (_ BitVec 6)) (l (_ BitVec 6))) Bool
    ;; True if for all x in S x < l
    ;; Note that: All << l is the set of values greater than l
    ;; In SMT-LIB, bvshl is the left shift operator <<  
    (= (bvand (bvshl All l) S) Empty))

;; We can use shifting to encode the set that contains all values in {0, 1, 2, 3, 4, 5} that greater than or equal to l2
(define-const GE_l2 (_ BitVec 6) (bvshl All l2))
;; To assert that forall x in L4. x < l2, we assert that the intersection of L4 and GE_l2 is empty 
(assert (= (bvand GE_l2 L4) Empty))

(check-sat)
(get-model) 

(define-fun is_in ((e (_ BitVec 6)) (S (_ BitVec 6))) Bool
   ;; True if e is an element of the "set" S.
   ;; That is, it checks whether the (1 << e) && S is 0
   (not (= (bvand (bvshl (_ bv1 6) e) S) Empty))) 

(echo "is_in tests")
;; Test: is 2 in the set {0,3}
(simplify (is_in (_ bv2 6) #b001001))
;; Test: is 0 in the set {0, 3}
(simplify (is_in (_ bv0 6) #b001001))
;; Test: is 3 in the set {0, 3}
(simplify (is_in (_ bv3 6) #b001001))
;; Test: is 4 in the set {0, 3}
(simplify (is_in (_ bv4 6) #b001001))
(echo "end is_in tests")

(define-fun is_minimal ((e (_ BitVec 6)) (S (_ BitVec 6))) Bool
    ;; True if e is the minimal element of S
    (and (is_in e S) ;; S contains e
         ;; (1 << e) - 1 represents the set of elements that are smaller than e
         (= (bvand (bvsub (bvshl (_ bv1 6) e) (_ bv1 6)) S) Empty))) 

(echo "is_minimal tests")
;; is 2 the minimal element in {5, 3}
(simplify (is_minimal (_ bv2 6) #b101000))
;; is 3 the minimal element in {5, 3}
(simplify (is_minimal (_ bv3 6) #b101000))
;; is 4 the minimal element in {5, 3}
(simplify (is_minimal (_ bv4 6) #b101000))
;; is 0 the minimal element in {4, 0}
(simplify (is_minimal (_ bv0 6) #b010001))
;; is 4 the minimal element in {4, 0}
(simplify (is_minimal (_ bv4 6) #b010001))
(echo "end is_minimal tests")

;; To encode that forall x in L0 and forall y in L1. x < y
(define-fun LT ((L0 (_ BitVec 6)) (L1 (_ BitVec 6))) Bool
    ; True if forall x in L0 and forall y in L1, x < y
    ; We encode that by saying that 
    ;    - L0 is empty OR
    ;    - L1 is empty OR
    ;    - Or Let min be the minimal value of L1 and Forall x in L0, x < min
    (or (= L0 Empty)
        (= L1 Empty)
        (exists ((min (_ BitVec 6))) (and (is_minimal min L1) (LT_l L0 min)))))

;; To make the problem non-trivial, let us assume that L0 and L1 are not empty
(assert (not (= L0 Empty)))
(assert (not (= L1 Empty)))
(assert (LT L0 L1))
(check-sat)
(get-model)
(assert (LT L1 L0))
(check-sat)