【问题标题】:Set membership relation in z3在 z3 中设置成员关系
【发布时间】:2013-04-21 22:44:54
【问题描述】:

我想在 Z3 中使用 C++ API 定义成员关系。我想通过以下方式做到这一点:

z3::context C;
z3::sort I = C.int_sort();
z3::sort B = C.bool_sort();
z3::func_decl InSet = C.function("f", I, B);

z3::expr e1 = InSet(C.int_val(2)) == C.bool_val(true);
z3::expr e2 = InSet(C.int_val(3)) == C.bool_val(true);
z3::expr ite  = to_expr(C, Z3_mk_ite(C, e1, C.bool_val(true),
    Z3_mk_ite(C,e2,C.bool_val(true),C.bool_val(false))));
errs() << Z3_ast_to_string(C,ite);

在这个例子中,集合由整数 2 和 3 组成。我确信有更好的方法来定义关系,特别是集合成员关系,但我真的是 Z3 菜鸟。有谁知道最好的吗?

【问题讨论】:

    标签: c++ z3


    【解决方案1】:

    在 Z3 中,集合通常使用谓词(如您所做的那样)或布尔数组进行编码。在 Z3 C API 中,有几个函数用于创建集合表达式:Z3_mk_set_sortZ3_mk_empty_setZ3_mk_set_union、...实际上,这些函数是创建数组表达式。它们将一组T 表示为从T 到布尔值的数组。他们使用this article 中描述的编码。

    备注:在Z3中,InSet(C.int_val(2)) == C.bool_val(true)等价于InSet(C.int_val(2))InSet 函数是一个谓词。我们可以写std::cout &lt;&lt; ite 而不是std::cout &lt;&lt; Z3_ast_to_string(C, ite)

    在基于谓词的方法中,我们通常需要使用量词。 在您的示例中,您说23 是集合的元素,但是要说没有其他元素是元素,我们需要一个量词。我们还需要量词来表示属性,例如:集合A等于集合BC的并集。基于量词的方法更灵活,我们可以说例如A是一个集合包含1n 之间的所有元素。 缺点是很容易创建不在 Z3 可以处理的可判定片段中的公式。 Z3 教程描述了其中一些片段。这是教程中的一个示例。

    ;; 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)
    

    【讨论】:

    • 非常感谢。如何使用 C API 编写断言?如果我想使用 Z3_mk_set_sort,我该如何定义一组元组?例如一对整数值的集合(即 (1,2) ∈ {(1,2),(4,6),(5,1)})?
    • 关于断言,首先你必须创建一个求解器对象Z3_mk_solver,增加它的引用计数器Z3_solver_inc_ref,然后调用Z3_solver_assert。顺便说一句,C++ API 有许多智能指针(例如 z3::expr、z3::solver、...),它们为我们进行所有引用计数。
    • 关于元组集合,首先我们必须使用Z3_mk_tuple_sort创建一个元组排序,然后我们使用新的元组排序作为Z3_mk_set_sort的参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多