我需要使用Z3_parse_smtlib2_string
使用C ++ API将一些SMTLIB字符串解析为Z3,并使用Z3 C ++ API来查找不完整的核心。
我知道还有其他方法可以找到here和here所描述的不饱和内核更容易且不那么繁琐,但我真的希望能够仅使用解析的数据结构来做到这一点从字符串到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似乎并不知道我已经宣布它。
任何想法我做错了什么?
答案 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
。