How to use enumerated constants after calling of some tactic in Z3?

狂风中的少年 提交于 2019-11-29 16:13:34

As pointed by Nikolaj, you have a typo. More importantly, you are misusing the C/C++ APIs. It is possible to use both APIs simultaneously. However, when using the C API, we have to increment the reference counters manually, or wrap the Z3_ast values using the C++ wrappers available in the C++ API. Otherwise, the memory will be corrupted. For example, when we invoke

Z3_sort s = Z3_mk_enumeration_sort(z3_cont, enum_nm, 3, enum_names, enum_consts, enum_testers);

We have to increase the reference counter of the Z3_func_decls in enum_names and enum_consts. Otherwise, these objects will be garbage collected by Z3. This happens in your example. That is why you get strange results. If we run a tool such as Valgrind in your example, it will report many memory access violations.

Here is a fixed version of your example:

using namespace z3;
...
context z3_cont;
...

Z3_symbol enum_names[3];
Z3_func_decl enum_consts[3];
Z3_func_decl enum_testers[3];
enum_names[0]=Z3_mk_string_symbol(z3_cont,"a");
enum_names[1]=Z3_mk_string_symbol(z3_cont,"b");
enum_names[2]=Z3_mk_string_symbol(z3_cont,"c");
Z3_symbol enum_nm = Z3_mk_string_symbol(z3_cont,"enumT");
sort s = to_sort(z3_cont, Z3_mk_enumeration_sort(z3_cont, enum_nm, 3, enum_names, enum_consts, enum_testers));
func_decl a_decl = to_func_decl(z3_cont, enum_consts[0]);
func_decl b_decl = to_func_decl(z3_cont, enum_consts[1]);
func_decl c_decl = to_func_decl(z3_cont, enum_consts[2]);
expr a = to_expr(z3_cont, Z3_mk_app(z3_cont, a_decl, 0, 0));
expr b = to_expr(z3_cont, Z3_mk_app(z3_cont, b_decl, 0, 0));
expr x = z3_cont.constant("x", s);
expr test = (x==a) && (x==b);
std::cout << "1: " << test << std::endl;

tactic qe(z3_cont,"ctx-solver-simplify");
goal g(z3_cont);
g.add(test);
expr res(z3_cont);
apply_result result_of_elimination = qe.apply(g);
if ( result_of_elimination.size() == 1){
    goal result_formula = result_of_elimination[0];
    res =  result_formula.operator[](0);
    for (int i = 1; i < result_formula.size(); ++i){
        res = res && result_formula.operator[](i);
    }
}
std::cout << "2: " << res << std::endl;

Note that I'm wrapping the values in enum_consts using func_decl C++ objects. These objects are essentially smart pointers. They automatically manage the reference counters for us.

I also extended the C++ API with a method for simplifying the creation of enumeration sorts. http://z3.codeplex.com/SourceControl/changeset/b2810592e6bb

I also included an example showing how to use this new API. This extension will be available in the next release (Z3 v4.3.2). It is already available in the unstable (working-in-progress) branch, and will be also available tomorrow in the nightly builds.

(declare-fun x () enumT) Here I have expected "c", Why "x"?

Try to change:

enum_names[0]=Z3_mk_string_symbol(z3_cont,"a");
enum_names[1]=Z3_mk_string_symbol(z3_cont,"b");
enum_names[3]=Z3_mk_string_symbol(z3_cont,"c");

to:

enum_names[0]=Z3_mk_string_symbol(z3_cont,"a");
enum_names[1]=Z3_mk_string_symbol(z3_cont,"b");
enum_names[2]=Z3_mk_string_symbol(z3_cont,"c");

and see if that helps

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!