c++ - 跟踪z3::优化unsat_core

标签 c++ z3

如何正确跟踪z3::optimize unsat核心?
当我添加unsat_core跟踪(基于这些examples)(gcc 10.1.0)时,Z3 C++ z3::optimize找不到所需的解决方案。
解决以下问题:存在三个连续的点ABC,其中AC分别固定为0和200。确定B的位置,使B - A >= 10C - B >= 15和我们的优化目标为minimize(C - B)。这个问题的解决方案应该是B = C - 15 = 200 - 15 = 185
下面的未跟踪代码提供了正确的解决方案。

#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;
}
另一方面,使用 void add(expr const& e, expr const& t)跟踪unsat_core返回B=10,这不是期望的解决方案。尽管如此,如果需要,我仍然可以跟踪unsat核心-例如添加opt.add(ctx.int_const("B") == 200, ctx.bool_const("t4"));会创建一个unsat。问题。
#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;
}
使用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;
}
有趣的是,在上面的表达式中增加一个权重-即handle add(expr const& e, unsigned weight)-例如opt.add(z3::implies(ctx.bool_const("t0"), ctx.int_const("A") == 0), 1);,“强制”优化器获得正确的解决方案。
我在这里想念什么?
编辑:奇怪的是,如果我向优化器添加跟踪变量t[0-4]-即opt.add(ctx.bool_const("t0"));等,则优化器会找到正确的解决方案,但会失去跟踪unsat核心表达式的功能。考虑到我正在更改表达式的目的,这似乎很有意义。

最佳答案

z3在优化模式下不支持unsat-cores。
有关此问题的详细讨论,请参见此线程:https://github.com/Z3Prover/z3/issues/1577
推荐的解决方案(使用伪代码)是:

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
诚然,这并不理想。但这是实现的当前状态。如果此功能对您很重要,我建议将z3的故障单作为功能请求,尽管没有令人信服的用例,但不太可能实现。对于您来说,更好的选择可能是在您的宿主语言中使用并行化功能:启动两个线程,一个线程进行常规sat调用,一个线程进行optimization。如果获得unsat,请杀死第二个,并从第一个获得unsat-core。如果您获得sat,现在可以使用第二个调用的结果。如果您有多个内核可供使用(这些天不是谁?),这对最终用户几乎是透明的。

关于c++ - 跟踪z3::优化unsat_core,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63419012/

相关文章:

c++ - 累积 double vs 整数

c++ - C++11中列表初始化的优点

c++ - 将绝对地址转换为指针变量的现代 C++ 方法是什么?

c++ - 如何在 C++ 中以正确的方式定义树的插入函数?

Z3py:如何从公式中获取变量列表?

Z3:表达线性代数属性

java - 如何解决我的错误LNK2019

z3 - 是否有可能在 Z3 中或在传递到 Z3 之前检测到不一致的方程?

java - 如何在 Travis-CI 机器上设置 Z3 解算器

java - Z3 Java : simplify a distributive expression