使用 C++ 使用 Z3 定义集合论
Defining a Theory of Sets with Z3 using C++
我需要使用 C++ 通过 Z3 实现集合理论,系统应该像这样工作:
1. 使用C++搭建支持普通集合操作的约束系统;
- 以 smtlib2 格式添加额外的约束,我在这里使用
C 中的 API 将字符串转换为 expr:Z3_parse_smtlib2_string
对于集合论,我从 Leonardo 在这个 post 中的原始答案开始:
Defining a Theory of Sets with Z3/SMT-LIB2
我尝试了 http://rise4fun.com/Z3/DWYC 中的编码,在 rise4fun 中一切正常。但是,我 运行 在将编码转换为 C++ 代码时遇到了一些麻烦,我在 Z3 for C++ 中找不到任何集合 API 。
有没有例子?
然后我发现z3_api.h包含c的集合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".
时引发 "Segmentation fault" 错误
context ctx;
Z3_context c = ctx.operator _Z3_context *();
我想对字符串元素执行一些集合操作,但我不知道如何将其集成到我的 C++ 代码中,因为我也在 C++ 中创建了自己的 z3:context。如何在C++中直接执行集合操作?
谢谢,
很抱歉没有公开 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" class 的构造函数对 'r' 进行引用计数。这确保只要表达式在范围内,指向 'r' 的指针就保持有效。
我会在 C++ 中添加集合操作 API 以方便其他用途。
在将它们集成之前,它们基本上是这样的:
</p>
<pre><code>#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);
}
我需要使用 C++ 通过 Z3 实现集合理论,系统应该像这样工作: 1. 使用C++搭建支持普通集合操作的约束系统;
- 以 smtlib2 格式添加额外的约束,我在这里使用 C 中的 API 将字符串转换为 expr:Z3_parse_smtlib2_string
对于集合论,我从 Leonardo 在这个 post 中的原始答案开始: Defining a Theory of Sets with Z3/SMT-LIB2
我尝试了 http://rise4fun.com/Z3/DWYC 中的编码,在 rise4fun 中一切正常。但是,我 运行 在将编码转换为 C++ 代码时遇到了一些麻烦,我在 Z3 for C++ 中找不到任何集合 API 。 有没有例子?
然后我发现z3_api.h包含c的集合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".
时引发 "Segmentation fault" 错误context ctx;
Z3_context c = ctx.operator _Z3_context *();
我想对字符串元素执行一些集合操作,但我不知道如何将其集成到我的 C++ 代码中,因为我也在 C++ 中创建了自己的 z3:context。如何在C++中直接执行集合操作?
谢谢,
很抱歉没有公开 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" class 的构造函数对 'r' 进行引用计数。这确保只要表达式在范围内,指向 'r' 的指针就保持有效。
我会在 C++ 中添加集合操作 API 以方便其他用途。 在将它们集成之前,它们基本上是这样的:
</p>
<pre><code>#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);
}