Z3中的独特集

时间:2013-03-15 19:22:55

标签: z3

我有以下程序:

;;; Sets
(declare-fun lock_0 (Int) Bool)
(declare-fun lock_1 (Int) Bool)
(declare-fun lock_2 (Int) Bool)
(declare-fun lock_3 (Int) Bool)

;;; verify if sets lock_0 and lock_1 haven't elements in common
(assert (exists ((x Int)) (=> (lock_0 x) (not (lock_1 x)))))

;;; verify if sets lock_2 and lock_3 haven't elements in common
(assert (exists ((x Int)) (=> (lock_2 x) (not (lock_3 x)))))

;;; Sets only contain 1 for Lock_0 and lock_1 or 2 for lock_2 or lock_3
(assert (forall ((x Int)) (= (lock_0 x) (= x 2))))
(assert (forall ((x Int)) (= (lock_1 x) (= x 2))))
(assert (forall ((x Int)) (= (lock_2 x)  (= x 1))))
(assert (forall ((x Int)) (= (lock_3 x)  (= x 1))))

;;; set [l1]
(declare-fun SL1 (Int) Bool) 
;;; set only contain 1
(assert (forall ((x Int)) (= (SL1 x) (= x 1))))
;;; SL1 subset lock_2
(assert (forall ((x Int)) (=> (SL1 x) (lock_2 x))))

;; sat
(check-sat)
( get-value (( lock_0 1 )))
( get-value (( lock_0 2 )))
( get-value (( lock_1 1 )))
( get-value (( lock_1 2 )))
( get-value (( lock_2 1 )))
( get-value (( lock_2 2 )))
( get-value (( lock_3 1 )))
( get-value (( lock_3 2 )))
( get-value (( SL1 1 )))
( get-value (( SL1 2 )))

结果:

sat
((( lock_0 1 ) false))
((( lock_0 2 ) true))
((( lock_1 1 ) false))
((( lock_1 2 ) true))
((( lock_2 1 ) true))
((( lock_2 2 ) false))
((( lock_3 1 ) true))
((( lock_3 2 ) false))
((( SL1 1 ) true))
((( SL1 2 ) false))

我需要生成lock_0lock_1以下几组:

[] - Empty set
[2]

要生成lock_2lock_3以下几组:

[] - Empty set
[1]

但是集合lock_0lock_1不能有共同的元素。

但最终我得到了:

( get-value (( lock_0 2 ))) true
( get-value (( lock_1 2 ))) true

结果适用于所有人,在一种情况下应该是假的,例如:

( get-value (( lock_0 2 ))) false
( get-value (( lock_1 2 ))) true

对于集合不能包含相等的元素。

lock_2lock_3相同的问题。

如果我添加:

;;; Set [l2]
(declare-fun SL2 (Int) Bool)

;;; set only contain 2
(assert (forall ((x Int)) (= (SL2 x) (= x 2))))
;;; SL2 is subset lock_0
(assert (forall ((x Int)) (=> (SL2 x) (lock_0 x))))

;; unsat
(check-sat)

我希望结果不尽如人意,但由于集合(lock_0 and lock_1lock_2 and lock_3)相等,我会坐下来。

例如: 如果我获得lock_0 = []lock_1 = [2]以及lock_2 = [1]lock_3 = [],则该计划是正确的。

我该如何解决这个问题?

START EDIT

要添加这段代码: (assert (forall ((x Int)) (or (not (lock_0 x)) (not (lock_1 x)))))

结果不尽如人意。它应该是坐着。

那么如何为同一组,空集或集合{2}生成?或者这是不可能的?

如果这不可能,那么我们可以使元素0为空集吗?但为此,我只能拥有以下几套:

[0] - empty set 
[2]

所以我这样做:(assert (forall ((x Int)) (= (lock_1 x) (or (= x 0) (= x 2)))))

但是如果我想要集合lock_0lock_1也可能有3个元素应该得到:

[0] - empty set
[2]
[3]
[2,3] - may not include zero, since only the zero should be used as the singleton set [0]

所以我这样做:(assert (forall ((x Int)) (= (lock_1 x) (or (= x 0) (and (!= x 0) (or (= x 2) (= x 3)))))))

是吗?

另一个问题:如果我想创建一个像我这样做的集合的函数?对于一个集合是一个功能。 例如:

(define-fun example ((s1 Set) (s2 Set) (x Int)) Int
  (if (and (s1 x) (not (s2 x)))
      (* x x)
      0))

但我不知道该取而代之的是Set(Set s1),可以帮助我。

结束编辑

1 个答案:

答案 0 :(得分:0)

我发现您的编码存在一些问题。

首先是命令

;;; verify if sets lock_0 and lock_1 haven't elements in common
(assert (exists ((x Int)) (=> (lock_0 x) (not (lock_1 x)))))

声称存在元素xxlock_0中的x不在lock_1中。这个断言几乎是空洞的。它只是阻止两个“集合”同时包含所有整数。您的评论表明您实际上是在尝试断言

(assert (forall ((x Int)) (or (not (lock_0 x)) (not (lock_1 x)))))

也就是说,两组的交集都是空的。

其次,你说你期望/需要lock_0lock_2是空集,但你断言

(assert (forall ((x Int)) (= (lock_0 x) (= x 2))))
(assert (forall ((x Int)) (= (lock_2 x)  (= x 1))))

这两个断言实质上是说lock_0是单件集{2},而lock_2是单件集{1}

BTW,如果我们更换

(assert (exists ((x Int)) (=> (lock_0 x) (not (lock_1 x)))))

(assert (forall ((x Int)) (or (not (lock_0 x)) (not (lock_1 x))))),(1)

在我们断言

之后,这个问题变得微不足道了

(assert (forall ((x Int)) (= (lock_0 x) (= x 2))))(2)

(assert (forall ((x Int)) (= (lock_1 x) (= x 2))))(3)

因为,(1)说lock_0lock_1没有共同的元素,而(2)和(3)说它们是单身集合{2}

编辑(有关其他问题)

如果我们想说lock_0是空集,我们可以说它总是假的

(assert (forall ((x Int)) (not (lock_0 x))))

命令

(assert (forall ((x Int)) (= (lock_1 x) (or (= x 0) (= x 2)))))

断言lock_1是集合{0, 2}。 如果我们想说lock_1是空集或集合{2},我们应断言:

(assert (or (forall ((x Int)) (not (lock_1 x))) 
            (forall ((x Int)) (= (lock_1 x) (= x 2)))))

要说lock_1可能只包含值2和3,我们应断言:

(assert (forall ((x Int)) (=> (lock_1 x) (or (= x 2) (= x 3)))))

请注意,我使用了蕴涵(=>)而不是相等。在这种情况下,我们lock_1可能是以下集合之一:{}(空集),{2}{3}{2, 3}。< / p>

命令define-fun不将函数作为参数。 命令define-fun只是定义一个宏。 它不会给Z3增加任何额外的动力。

如果你想要一个更强大的语言与Z3交互,你应该考虑Z3Py,Z3的Python前端。以下是使用Z3Py的示例(也可在线获取here)。

# Declare a function from Int to Bool
lock_1 = Function('lock_1', IntSort(), BoolSort())
x = Int('x')

s = Solver()
# Assert that lock_1 is the empty set
s.add(ForAll(x, Not(lock_1(x))))
print(s.check())

# Declare a function that returns x*x if x is in s1 but not in s2
# Remark: example is a Python function that builds a Z3 expression.
def example(s1, s2, x):
    # Remark: the function If creates a Z3 if expression.
    return If(And(s1(x), Not(s2(x))), x*x, 0)

lock_2 = Function('lock_2', IntSort(), BoolSort())

s = Solver()
a = Int('a')
s.add(a == example(lock_1, lock_2, 3))
s.add(lock_1(3))
s.add(Not(lock_2(3)))
print(s)
print(s.check())
m = s.model()
print(m[a])

结束编辑