简体   繁体   English

跟踪 z3::optimize unsat_core

[英]Tracking z3::optimize unsat_core

How to properly track z3::optimize unsat core?如何正确跟踪z3::optimize unsat core?

The Z3 C++ z3::optimize does not find the expected solution when I add unsat_core tracking (based on these examples ) (gcc 10.1.0).当我添加unsat_core跟踪(基于这些示例)(gcc 10.1.0)时,Z3 C++ z3::optimize没有找到预期的解决方案。

Take the following problem: There are three consecutive points A , B , and C , where A and C are fixed to 0 and 200, respectively.采取以下问题:连续三个点ABC ,其中AC分别固定为 0 和 200。 Determine B 's position such that B - A >= 10 , C - B >= 15 , and our optimization goal is minimize(C - B) .确定B的 position 使得B - A >= 10C - B >= 15 ,我们的优化目标是 minimum minimize(C - B) The solution for this problem should be B = C - 15 = 200 - 15 = 185 .这个问题的解决方案应该是B = C - 15 = 200 - 15 = 185

The untracked code below gives the correct solution.下面未跟踪的代码给出了正确的解决方案。

#include <iostream>
#include <z3++.h>

int main()
{
  z3::context ctx;
  z3::optimize opt(ctx);

  opt.add(ctx.int_const("A") == 0);
  opt.add(ctx.int_const("B") - ctx.int_const("A") >= 10);
  opt.add(ctx.int_const("C") - ctx.int_const("B") >= 15);
  opt.add(ctx.int_const("C") == 200);

  auto h = opt.minimize(ctx.int_const("C") - ctx.int_const("B"));

  if (opt.check() != z3::sat)
    std::cout << "unsat problem!\n" << opt.unsat_core() << std::endl;
  else
    std::cout << "model!\n" << opt.get_model() << std::endl;

  return 0;
}

On the other hand, tracking the unsat_core with void add(expr const& e, expr const& t) return B=10 , which is not the expect solution.另一方面,使用void add(expr const& e, expr const& t)跟踪 unsat_core返回B=10 ,这不是预期的解决方案。 Nonetheless, I am able to track the unsat core if need - eg adding opt.add(ctx.int_const("B") == 200, ctx.bool_const("t4"));尽管如此,如果需要,我可以跟踪未饱和核心 - 例如添加opt.add(ctx.int_const("B") == 200, ctx.bool_const("t4")); creates an unsat.创造一个不饱和。 problem.问题。

#include <iostream>
#include <z3++.h>

int main()
{
  z3::context ctx;
  z3::optimize opt(ctx);

  opt.add(ctx.int_const("A") == 0, ctx.bool_const("t0"));
  opt.add(ctx.int_const("B") - ctx.int_const("A") >= 10, ctx.bool_const("t1"));
  opt.add(ctx.int_const("C") - ctx.int_const("B") >= 15, ctx.bool_const("t2"));
  opt.add(ctx.int_const("C") == 200, ctx.bool_const("t3"));

  auto h = opt.minimize(ctx.int_const("C") - ctx.int_const("B"));

  if (opt.check() != z3::sat)
    std::cout << "unsat problem!\n" << opt.unsat_core() << std::endl;
  else
    std::cout << "model!\n" << opt.get_model() << std::endl;

  return 0;
}

Using z3::implies to track expressions does not work as expected either, but still provides unsat_core tracking capability.使用z3::implies跟踪表达式也不能按预期工作,但仍提供unsat_core跟踪功能。

#include <iostream>
#include <z3++.h>

int main()
{
  z3::context ctx;
  z3::optimize opt(ctx);

  opt.add(z3::implies(ctx.bool_const("t0"), ctx.int_const("A") == 0));
  opt.add(z3::implies(ctx.bool_const("t1"), ctx.int_const("B") - ctx.int_const("A") >= 10));
  opt.add(z3::implies(ctx.bool_const("t2"), ctx.int_const("C") - ctx.int_const("B") >= 15));
  opt.add(z3::implies(ctx.bool_const("t3"), ctx.int_const("C") == 200));

  auto h = opt.minimize(ctx.int_const("C") - ctx.int_const("B"));

  z3::expr_vector asv(ctx);
  asv.push_back(ctx.bool_const("t0"));
  asv.push_back(ctx.bool_const("t1"));
  asv.push_back(ctx.bool_const("t2"));
  asv.push_back(ctx.bool_const("t3"));

  if (opt.check(asv) != z3::sat)
    std::cout << "unsat problem!\n" << opt.unsat_core() << std::endl;
  else
    std::cout << "model!\n" << opt.get_model() << std::endl;

  return 0;
}

Interestingly, adding a weight - ie handle add(expr const& e, unsigned weight) - to the expressions above - eg opt.add(z3::implies(ctx.bool_const("t0"), ctx.int_const("A") == 0), 1);有趣的是,在上面的表达式中添加一个权重- 即handle add(expr const& e, unsigned weight) - 例如opt.add(z3::implies(ctx.bool_const("t0"), ctx.int_const("A") == 0), 1); , "forces" the optimizer to reach the correct solution. , “强制”优化器达到正确的解决方案。

What am I missing here?我在这里想念什么?

EDIT: Curiously, if I add tracking variables t[0-4] to the optimizer - ie opt.add(ctx.bool_const("t0"));编辑:奇怪的是,如果我将跟踪变量t[0-4]添加到优化器 - 即opt.add(ctx.bool_const("t0")); and so on, the optimizer finds the correct solution, but it loses the capability of tracking the unsat core expressions.以此类推,优化器找到了正确的解决方案,但它失去了跟踪 unsat 核心表达式的能力。 That seems to make sense, considering I am changing the expression's purpose.考虑到我正在改变表达式的目的,这似乎是有道理的。

z3 doesn't support unsat-cores in the optimization mode. z3 在优化模式下不支持 unsat-cores。

See this thread for a detailed discussion of this issue: https://github.com/Z3Prover/z3/issues/1577有关此问题的详细讨论,请参阅此线程: https://github.com/Z3Prover/z3/issues/1577

The recommended solution (in pseudo-code) is:推荐的解决方案(伪代码)是:

1.  Assert all constraints except optimization objectives
2.  Issue `check-sat`
        2.1 If `unsat`, get the unsat-core: done
        2.2 If `sat`:
              2.2.1 Assert the optimization objectives
              2.2.2 Issue `check-sat` again
              2.2.3 Get objective values

Admittedly, this isn't ideal;诚然,这并不理想。 but that's the current state of the implementation.但这是当前 state 的实现。 If this feature is important to you, I recommend filing a ticket with z3 as a feature-request, though without a convincing use case it's unlikely to be implemented.如果此功能对您很重要,我建议使用 z3 作为功能请求提交票证,但如果没有令人信服的用例,它不太可能实现。 A better option for you might be to use parallelization capabilities in your host language: Start two threads, one with regular sat call, and one with optimization .一个更好的选择可能是在宿主语言中使用并行化功能:启动两个线程,一个使用常规sat调用,一个使用optimization If you get unsat , kill the second and get the unsat-core from the first.如果你得到unsat ,杀死第二个并从第一个获得 unsat-core。 If you get sat , you can now use the results of your second call.如果您得到sat ,您现在可以使用第二次通话的结果。 If you have multiple cores at your disposal (who doesn't these days?) this should be almost transparent to the end-user.如果您有多个内核可供使用(现在谁没有?)这对最终用户来说应该几乎是透明的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM