我正在尝试使用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的错误赋值是逻辑上正确的赋值,但我不知道如何以这样的方式陈述事情以便排除这些案例。
也许我没有正确地思考这个问题。
非常感谢任何建议。 :)
答案 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
y
是distinct_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
包含两个值的情况:A
和C
,它们都具有相同的值。以下脚本还会询问以下问题:是否存在模型
distinct_set
不包含A
distinct_set
不包含A
也不包含C
distinct_set
包含A
和C
脚本:
( 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 )