使用C ++定义Z3集合理论

时间:2016-09-21 05:52:46

标签: c++ z3

我需要使用C ++实现使用Z3的集合理论,系统应该像这样工作: 1.使用C ++构建支持公共集合操作的约束系统;

  1. 在smtlib2格式中添加其他约束,我在这里使用 C中的这个API将字符串转换为expr:Z3_parse_smtlib2_string
  2. 对于Set理论,我在这篇文章中从Leonardo的原始答案开始: Defining a Theory of Sets with Z3/SMT-LIB2

    我在http://rise4fun.com/Z3/DWYC中尝试了编码,并且在rise4fun中一切正常。但是,在将编码转换为C ++代码时遇到了一些麻烦,我无法在Z3中为C ++找到任何设置API。 有什么例子吗?

    然后我发现z3_api.h包含c的set API。所以我写了一个非常简单的代码片段,它似乎有效:

    //https://github.com/Z3Prover/z3/blob/master/examples/c/test_capi.c#L105
    Z3_context c = mk_context();
    Z3_solver s = mk_solver(c);
    Z3_sort ty = Z3_mk_int_sort(c);
    Z3_ast emp = Z3_mk_empty_set(c, ty);
    Z3_ast s1 = Z3_mk_empty_set(c, ty);
    Z3_ast s2 = Z3_mk_empty_set(c, ty);
    Z3_ast one = Z3_mk_int(c, 1, ty);
    Z3_ast two = Z3_mk_int(c, 2, ty);
    Z3_ast three = Z3_mk_int(c, 3, ty);
    
    s1 = Z3_mk_set_add(c, s1, one);
    s1 = Z3_mk_set_add(c, s1, two);
    s2 = Z3_mk_set_add(c, s2, three);
    
    Z3_ast intersect_array[2];
    intersect_array[0] = s1;
    intersect_array[1] = s2;
    Z3_ast s3 = Z3_mk_set_intersect(c, 2, intersect_array);
    Z3_ast assert1 = Z3_mk_eq(c, s3, emp);
    Z3_solver_assert(c, s,assert1);
    check(c, s, Z3_L_TRUE);
    

    如果我使用z3 :: context初始化Z3_context对象,代码将引发一个"分段错误"调用" Z3_mk_set_intersect"。

    时出错
    context ctx;
    Z3_context c = ctx.operator _Z3_context *(); 
    

    我想对字符串元素执行一些set操作,而且我不知道如何将它集成到我的C ++代码中,因为我还在C ++中创建了自己的z3:context。如何在C ++中直接执行set操作?

    谢谢,

1 个答案:

答案 0 :(得分:1)

很抱歉没有公开C ++ API的设置操作。 问题是表达式需要正确引用计数。 使用Z3 _...方法时,调用者负责处理此问题。 C ++包装器自动处理引用计数。 现在,您可以创建C ++ API的临时扩展,通过创建自己的方法来包含集合交集:

inline expr set_intersect(expr const& a, expr const& b) {
    check_context(a, b); 
    Z3_ast es[2] = { a, b };
    Z3_ast r = Z3_mk_set_intersect(a.ctx(), 2, es);
    a.check_error();                    
    return expr(a.ctx(), r);
}

“expr”类的构造函数对'r'进行引用计数。这确保只要表达式在范围内,指向'r'的指针就会保持有效。

我将为C ++ API添加set操作以方便其他用途。 在它们被整合之前,这基本上就是它们的样子:

#define MK_EXPR1(_fn, _arg)                     \
  Z3_ast r = _fn(_arg.ctx(), _arg);           \
  _arg.check_error();                         \
  return expr(_arg.ctx(), r);

#define MK_EXPR2(_fn, _arg1, _arg2)             \
  check_context(_arg1, _arg2);                \
  Z3_ast r = _fn(_arg1.ctx(), _arg1, _arg2);  \
  _arg1.check_error();                        \
  return expr(_arg1.ctx(), r);

inline expr empty_set(sort const& s) {
    MK_EXPR1(Z3_mk_empty_set, s);
}

inline expr full_set(sort const& s) {
    MK_EXPR1(Z3_mk_full_set, s);
}

inline expr set_add(expr const& s, expr const& e) {
    MK_EXPR2(Z3_mk_set_add, s, e);
}

inline expr set_del(expr const& s, expr const& e) {
    MK_EXPR2(Z3_mk_set_del, s, e);
}    

inline expr set_union(expr const& a, expr const& b) {
    check_context(a, b); 
    Z3_ast es[2] = { a, b };
    Z3_ast r = Z3_mk_set_union(a.ctx(), 2, es);
    a.check_error();                    
    return expr(a.ctx(), r);
}

inline expr set_intersect(expr const& a, expr const& b) {
    check_context(a, b); 
    Z3_ast es[2] = { a, b };
    Z3_ast r = Z3_mk_set_intersect(a.ctx(), 2, es);
    a.check_error();                    
    return expr(a.ctx(), r);
}

inline expr set_difference(expr const& a, expr const& b) {
    MK_EXPR2(Z3_mk_set_difference, a, b);
}

inline expr set_complement(expr const& a) {
    MK_EXPR1(Z3_mk_set_complement, a);
}

inline expr set_member(expr const& s, expr const& e) {
    MK_EXPR2(Z3_mk_set_member, s, e);
}

inline expr set_subset(expr const& a, expr const& b) {
    MK_EXPR2(Z3_mk_set_subset, a, b);
}

#define MK_EXPR1(_fn, _arg) \ Z3_ast r = _fn(_arg.ctx(), _arg); \ _arg.check_error(); \ return expr(_arg.ctx(), r); #define MK_EXPR2(_fn, _arg1, _arg2) \ check_context(_arg1, _arg2); \ Z3_ast r = _fn(_arg1.ctx(), _arg1, _arg2); \ _arg1.check_error(); \ return expr(_arg1.ctx(), r); inline expr empty_set(sort const& s) { MK_EXPR1(Z3_mk_empty_set, s); } inline expr full_set(sort const& s) { MK_EXPR1(Z3_mk_full_set, s); } inline expr set_add(expr const& s, expr const& e) { MK_EXPR2(Z3_mk_set_add, s, e); } inline expr set_del(expr const& s, expr const& e) { MK_EXPR2(Z3_mk_set_del, s, e); } inline expr set_union(expr const& a, expr const& b) { check_context(a, b); Z3_ast es[2] = { a, b }; Z3_ast r = Z3_mk_set_union(a.ctx(), 2, es); a.check_error(); return expr(a.ctx(), r); } inline expr set_intersect(expr const& a, expr const& b) { check_context(a, b); Z3_ast es[2] = { a, b }; Z3_ast r = Z3_mk_set_intersect(a.ctx(), 2, es); a.check_error(); return expr(a.ctx(), r); } inline expr set_difference(expr const& a, expr const& b) { MK_EXPR2(Z3_mk_set_difference, a, b); } inline expr set_complement(expr const& a) { MK_EXPR1(Z3_mk_set_complement, a); } inline expr set_member(expr const& s, expr const& e) { MK_EXPR2(Z3_mk_set_member, s, e); } inline expr set_subset(expr const& a, expr const& b) { MK_EXPR2(Z3_mk_set_subset, a, b); }