Z3では、セットは通常、述語(あなたが行ったように)またはブール値の配列を使用してエンコードされます。Z3_mk_set_sort
Z3 C API には、セット式Z3_mk_empty_set
を作成するための関数がいくつかありますZ3_mk_set_union
。これらは からまでのブール値T
の配列としてのセットを表します。この記事T
で説明されているエンコーディングを使用します。
備考: Z3 では、InSet(C.int_val(2)) == C.bool_val(true)
に相当しInSet(C.int_val(2))
ます。InSet
関数は述語です。std::cout << ite
の代わりに書くことができますstd::cout << Z3_ast_to_string(C, ite)
。
述語に基づくアプローチでは、通常、量指定子を使用する必要があります。あなたの例では、2
and3
がセットの要素であると言っていますが、他に何も要素ではないと言うには、数量詞が必要です。set は set と の和集合にA
等しいなどのプロパティを示す量指定子も必要です。量指定子に基づくアプローチはより柔軟です。たとえば、 と の間のすべての要素を含むセットであると言えます。欠点は、Z3 が処理できる決定可能なフラグメントではない数式を作成するのが非常に簡単であることです。Z3 チュートリアルでは、これらのフラグメントの一部について説明しています。これはチュートリアルの例です。B
C
A
1
n
;; A, B, C and D are sets of Int
(declare-fun A (Int) Bool)
(declare-fun B (Int) Bool)
(declare-fun C (Int) Bool)
(declare-fun D (Int) Bool)
;; A union B is a subset of C
(assert (forall ((x Int)) (=> (or (A x) (B x)) (C x))))
;; B minus A is not empty
;; That is, there exists an integer e that is B but not in A
(declare-const e Int)
(assert (and (B e) (not (A e))))
;; D is equal to C
(assert (forall ((x Int)) (iff (D x) (C x))))
;; 0, 1 and 2 are in B
(assert (B 0))
(assert (B 1))
(assert (B 2))
(check-sat)
(get-model)
(echo "Is e an element of D?")
(eval (D e))
(echo "Now proving that A is a strict subset of D")
;; This is true if the negation is unsatisfiable
(push)
(assert (not (and
;; A is a subset of D
(forall ((x Int)) (=> (A x) (D x)))
;; but, D has an element that is not in A.
(exists ((x Int)) (and (D x) (not (A x)))))))
(check-sat)
(pop)