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

前端 未结 2 1141
误落风尘
误落风尘 2020-12-21 11:34

Here are the source code of my testing program of enumerated types:

    Z3_symbol enum_names[3];
    Z3_func_decl enum_consts[3];
    Z3_func_decl enum_teste         


        
相关标签:
2条回答
  • 2020-12-21 11:49

    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.

    0 讨论(0)
  • 2020-12-21 12:03

    (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

    0 讨论(0)
提交回复
热议问题