排除和包含在Z3中

时间:2012-03-15 04:08:16

标签: set z3 quantifiers

我正在尝试使用Z3模拟包含和排除集合中的元素。特别是包含具有不同值的元素,并排除尚未存在于目标集中的元素。所以基本上我想要一个集合U并让Z3找到一个集合U_d,它只包含具有不同值的U元素。

我当前的方法使用量词,但是我无法理解如何声明如果它们出现在U中我想要总是包含U_d中的元素。

( set-option :produce-models true)

;;; Two simple sorts.
;;; Sets and Zs.

( declare-sort Z   0 )
( declare-sort Set 0 )

;;; A set can contain a Z or not.
;;; Zs can have a value.

( declare-fun contains (Set Z) bool )
( declare-fun value (Z) Int )

;;; Two sets and two Z instances for use in the example.

( declare-const set Set )
( declare-const distinct_set Set )

( declare-const A Z )
( declare-const B Z )

;;; The elements and sets are distinct.     

( assert ( distinct A B ) )
( assert ( distinct set distinct_set ) )

;;; Set 'set' contains A but not B

( assert ( = ( contains set A ) true ) )
( assert ( = ( contains set B ) false ) )

;;; Assert that all elements contained by distinct_set have different values unless they're the same variable.
( assert
  ( forall ( (x Z) (y Z) )
    ( =>
        ( and 
            ( contains distinct_set x )
            ( contains distinct_set y )
            ( = ( value x ) ( value y ) ) )
        ( = x y ) )))

;;; distinct_set can contain only elements that appear in set.
;;; In other words, distinct_set is a proper set.
( assert
( forall ( ( x Z ) )
    ( =>
        ( contains distinct_set x )
        ( contains set x ))))

;;; Give elements some values.
( assert ( = (value A) 0 ) )
( assert ( = (value B) 1 ) )

( push )
( check-sat )
( get-value (( contains distinct_set A )))
( get-value (( contains distinct_set B )))
( pop )

它产生的任务是:

sat
((( contains distinct_set A ) false))
((( contains distinct_set B ) false))

我想要的任务是:

sat
((( contains distinct_set A ) true))
((( contains distinct_set B ) false))

据我所知,对A和B的错误赋值是逻辑上正确的赋值,但我不知道如何以这样的方式陈述事情以便排除这些案例。

也许我没有正确地思考这个问题。

非常感谢任何建议。 :)

1 个答案:

答案 0 :(得分:1)

您如何看待以下断言?

(assert
(forall ((x Z))
        (=> (contains set x)
            (exists ((y Z))
                    (and (= (value x) (value y))
                         (contains set y)
                         (contains distinct_set y))))))

它表示对于x的每个元素set(即U),都有一个y s.t。

  • y的值等于x
  • 的值
  • y也是set
  • 的元素
  • ydistinct_set的元素(即U_d)

此断言确保如果set中有两个元素具有相同的值,则其中只有一个元素是distinct_set的元素。这就是你想要的吗?

请注意,如果我们只是添加这个断言,Z3仍然会产生一个模型

((( contains distinct_set A ) false))
((( contains distinct_set B ) false))

如果我们使用(get-model)检查Z3生成的模型,我们会注意到set包含与A不同的另一个元素。因此,要强制set仅包含元素A,我们必须断言

(assert
 (forall ((x Z))
         (= (contains set x) (= x A))))

添加此断言后,以下两个断言变得多余:

( assert ( = ( contains set A ) true ) )
( assert ( = ( contains set B ) false ) )

现在,让我们考虑set包含两个值的情况:AC,它们都具有相同的值。以下脚本还会询问以下问题:是否存在模型

  • distinct_set不包含A

  • distinct_set不包含A也不包含C

  • distinct_set包含AC

脚本:

( set-option :produce-models true)

;;; Two simple sorts.
;;; Sets and Zs.

( declare-sort Z   0 )
( declare-sort Set 0 )

;;; A set can contain a Z or not.
;;; Zs can have a value.

( declare-fun contains (Set Z) bool )
( declare-fun value (Z) Int )

;;; Two sets and two Z instances for use in the example.

( declare-const set Set )
( declare-const distinct_set Set )

( declare-const A Z )
( declare-const B Z )
( declare-const C Z )

;;; The elements and sets are distinct.     

( assert ( distinct A B C) )
( assert ( distinct set distinct_set ) )

;;; set contains only A and C
 (assert
 (forall ((x Z))
         (= (contains set x) (or (= x A) (= x C)))))

;;; Assert that all elements contained by distinct_set have different values unless they're the same variable.
( assert
  ( forall ( (x Z) (y Z) )
    ( =>
        ( and 
            ( contains distinct_set x )
            ( contains distinct_set y )
            ( = ( value x ) ( value y ) ) )
        ( = x y ) )))

;;; distinct_set can contain only elements that appear in set.
;;; In other words, distinct_set is a proper set.
( assert
( forall ( ( x Z ) )
   ( =>
       ( contains distinct_set x )
       ( contains set x ))))

;;; Give elements some values.
( assert ( = (value A) 0 ) )
( assert ( = (value B) 1 ) )
( assert ( = (value C) 0 ) )

(assert
(forall ((x Z))
        (=> (contains set x)
            (exists ((y Z))
                    (and (= (value x) (value y))
                         (contains set y)
                         (contains distinct_set y))))))

( push )
( check-sat )
( get-model )
( get-value (( contains distinct_set A )))
( get-value (( contains distinct_set B )))
( get-value (( contains distinct_set C )))
( echo "Is there another model where A is not in distinct_set")
( assert (not ( contains distinct_set A )))
(check-sat)
( get-value (( contains distinct_set A )))
( get-value (( contains distinct_set B )))
( get-value (( contains distinct_set C )))
( echo "Is there another model where A and C are not in distinct_set")
( assert (not ( contains distinct_set C )))
(check-sat)
( pop ) ;; retracting the last two assertions
( push )
( echo "Is there a model where A and C are in distinct_set")
( assert ( contains distinct_set A ))
( assert ( contains distinct_set C ))
( check-sat )