使用C ++和Z3_parse_smtlib2_string在Z3中获取Unsat Core

时间:2015-03-11 06:55:19

标签: c++ parsing z3 smt

我需要使用Z3_parse_smtlib2_string使用C ++ API将一些SMTLIB字符串解析为Z3,并使用Z3 C ++ API来查找不完整的核心。

我知道还有其他方法可以找到herehere所描述的不饱和内核更容易且不那么繁琐,但我真的希望能够仅使用解析的数据结构来做到这一点从字符串到Z3。原因是我试图使用Z3自动化某些东西。

很明显,如果我将这个SMTLIB程序传递给Z3,那就是UNSAT。

(declare-const p0 Bool)
(assert(= p0 true)) (assert(= p0 false))
(assert (exists ((x Int)) (= 3 x)))

我想要做的是能够使用Z3以编程方式获得不满核心。我所做的是分别将这些行分别读入Z3,并使用solver.add(expr, name)使用下面的程序为它们命名。

void my_test() {
    context c1;
    solver s(c1);

    std::string declare = "(declare-const p0 Bool)";
    std::string testing = "(assert(= p0 true)) (assert(= p0 false))";
    std::string obvious = "(assert (exists ((x Int)) (= 3 x)))";

    Z3_ast parsed1 = Z3_parse_smtlib2_string(c1, declare.c_str(), 0,0,0,0,0,0);
    expr e1(c1, parsed1);

    Z3_ast parsed2 = Z3_parse_smtlib2_string(c1, testing.c_str(), 0,0,0,0,0,0);
    expr e2(c1, parsed2);
    std::cout << "what: " << e2 << std::endl;

    Z3_ast parsed3 = Z3_parse_smtlib2_string(c1, obvious.c_str(), 0,0,0,0,0,0);
    expr e3(c1, parsed3);

    s.add(e1, "declare");
    s.add(e2, "testing");
    s.add(e3, "obvious");

    if (s.check() == z3::sat) {
        std::cout << "SAT!\n";
        model m = s.get_model();
        std::cout << m << std::endl;
    } else {
        std::cout << "UNSAT!\n";
        expr_vector core = s.unsat_core();
        std::cout << core << "\n";
        std::cout << "size: " << core.size() << "\n";
        for (unsigned i = 0; i < core.size(); i++) {
            std::cout << core[i] << "\n";
        }
    }
}

我希望将不满核心变为declare,因为这显然是错误的,而其他表达式显然是有效的。但是,Z3给了我这样的答复:

(error "line 1 column 11: unknown constant p0")
(error "line 1 column 31: unknown constant p0")
what: true
SAT!
(define-fun testing () Bool
  true)
(define-fun declare () Bool
  true)
(define-fun obvious () Bool
  true)

这显然是错误的,因为引用declare的{​​{1}}是SAT!显然这应该是UNSAT。另外,我确实声明(assert(= p0 true)) (assert(= p0 false)),但Z3似乎并不知道我已经宣布它。

任何想法我做错了什么?

1 个答案:

答案 0 :(得分:1)

Z3_parse_smtlib2_string的第二次调用不知道第一次调用中的声明:

Z3_ast parsed2 = Z3_parse_smtlib2_string(c1, testing.c_str(), 0,0,0,0,0,0);

最后一堆零意味着&#34;不假设任何其他内容&#34;,所以它不知道p0存在。有关详细信息,请参阅Z3_parse_smtlib2_string in the API documentation;在您的情况下,您想要传递非空decls