假设我使用API读取SMTLIB公式:
context ctx;
...
expr F = to_expr(ctx, Z3_parse_smtlib2_file(ctx,argv[1],0,0,0,0,0,0));
表达式F
是形式断言的结合:
(and (< (+ x y) 3)
(> (- x1 x2) 0)
(< (- x1 x2) 4)
(not (= (- x1 x2) 1))
(not (= (- x1 x2) 2))
(not (= (- x1 x2) 3)))
我想使用帖子中的以下代码片段从此连接中提取每个单独的断言:How to use z3 split clauses of unsat cores & try to find out unsat core again
F = F.simplify();
for (unsigned i = 0; i < F.num_args(); i++) {
expr Ai = F.arg(i);
// ... Do something with Ai, just printing in this example.
std::cout << Ai << "\n";
}
使用F.arg(i)
后,原始条款(< (+ x y) 3)
已更改为(not (<= 3 (+ x y)))
。这是我的
a)问题:如何将条款(not (<= 3 (+ x y)))
放到(< (+ x y) 3)
?
b)问题:我认为符号<=
意味着暗示在这种情况下,并不意味着小于。我是对的吗?
c)问题:因为条款(not (<= 3 (+ x y)))
模型是真还是假,我怎样才能获得x = 1, y = -1
等算术值?
非常感谢任何建议。 非常感谢你。
答案 0 :(得分:2)
当(< (+ x y) 3)
时,表达式(not (<= 3 (+ x y)))
会转换为F = F.simplify()
。
在您使用的代码片段中,方法simplify()
用于“展平”嵌套的“和”。也就是说,公式(and (and A B) (and C (and D E)))
被展平为(and A B C D E)
。然后,可以使用for循环轻松遍历所有合取。但是,simplify()
还将在输入公式中执行其他转换。请记住,所有转换都保持等价。也就是说,输入和输出公式在逻辑上是等价的。如果simplify()
应用的转换不合适,我建议您避免使用此方法。如果您仍想遍历嵌套的“和”,则可以使用辅助todo
向量。这是一个例子:
expr_vector todo(c);
todo.push_back(F);
while (!todo.empty()) {
expr current = todo.back();
todo.pop_back();
if (current.decl().decl_kind() == Z3_OP_AND) {
// it is an AND, then put children into the todo list
for (unsigned i = 0; i < current.num_args(); i++) {
todo.push_back(current.arg(i));
}
}
else {
// do something with current
std::cout << current << "\n";
}
}