z3 - 使用 Z3_solver_get_unsat_core 获取 unsat 核心

标签 z3

假设这是非线性实数算术的约束集,例如

pred1 = (> (- (* (- v2_x v0_x) (- v1_y v0_y)) (* (- v2_y v0_y) (- v1_x v0_x))) 0)
pred2 = (> (- (* (- v1_x v0_x) (- v2_y v0_y)) (* (- v1_y v0_y) (- v2_x v0_x))) 0)

事实上,如果我们这样做

Z3_solver_assert(ctx,solver,pred1);
Z3_solver_assert(ctx,solver,pred2);
b = Z3_solver_check(ctx, solver);

b 会不饱和。我想获得 unsat 核心(对于这个例子来说是微不足道的)。因此,我为每个谓词定义了一个谓词变量。假设它们是 p1p2

Z3_ast p1 = mk_bool_var(ctx, "P1");
assumptions[i] = Z3_mk_not(ctx, p1);
Z3_ast g[2] = { pred1, p1 };
Z3_solver_assert(ctx,solver,Z3_mk_or(ctx, 2, g));
Z3_ast p2 = mk_bool_var(ctx, "P2");
assumptions[i] = Z3_mk_not(ctx, p2);
Z3_ast g[2] = { pred2, p2 };
Z3_solver_assert(ctx,solver,Z3_mk_or(ctx, 2, g));

然后我调用 Z3_solver_check_asclusions(ctx,solver, 2 ,假设);

但这会返回Z3_L_UNDEF,原因是(不完整(理论算术))

我想知道我在哪里犯了错误以及如何解决这个问题。

以下是初始化的方式:

  ctx = Z3_mk_context(cfg);
  Z3_symbol logic_symbol = Z3_mk_string_symbol(ctx, "QF_UFNRA");
  solver = Z3_mk_solver_for_logic((Z3_context)ctx, logic_symbol);
  Z3_solver_inc_ref(ctx, solver);
  Z3_params params = Z3_mk_params(ctx);
  Z3_symbol param_symbol = Z3_mk_string_symbol(ctx, "unsat_core");
  Z3_params_set_bool(ctx , params, param_symbol, Z3_L_TRUE);
  Z3_solver_set_params(ctx, solver, params); 

谢谢

最佳答案

Z3 包含许多求解器。对于非线性算术问题,它使用nlsat。该求解器的实现位于目录src/nlsat中,算法解释here 。但是,当前的 nlsat 实现不支持 unsat 核心提取或证明生成。当用户请求unsat核心提取时,Z3切换到对于非线性算术来说不完整的通用求解器。也就是说,对于非线性算术问题,它可能会返回unknown。通用求解器支持许多理论、量词、unsat 核心提取和证明生成。它对于线性算术来说是完整的,但正如我所说,对于非线性片段来说它是不完整的。计划中,Z3将会有一个新版本的nlsat,与其他理论相结合,支持unsat核心提取,但这是 future 的工作。

关于z3 - 使用 Z3_solver_get_unsat_core 获取 unsat 核心,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13590129/

相关文章:

java - 缺少通过 Java-Wrapper 将表达式添加到 Z3 的批量模式

z3 - 关于 Z3 中 Uninterpreted Function 的表示

z3 - 我们可以在Z3中定义关系吗?

java - 在 z3 中表示推理规则

c - Z3使用目标和战术

arrays - Z3 中的 SMTLIB 阵列理论奇怪

z3 - 浮点文字

c++ - 将 z3 C++ API ast(或求解器)对象转换为 SMTLIB 字符串

c - Z3 (Haskell) 中的段错误

z3 - 证明 Z3 中的归纳事实