通过C / C ++ API消除Z3中LIA的量化

时间:2012-10-25 15:32:09

标签: z3 quantifiers

我想使用Z3通过C / C ++ API消除线性整数算术公式中的量词。考虑一个简单的例子:Exists(x)(x <= y&amp; y&lt; = 2 * x)。无量词  具有相同模型的公式是y> = 0。

我试着这样做:

   context ctx;
   ctx.set("ELIM_QUANTIFIERS", "true");
   expr x = ctx.int_const("x"); 
   expr y = ctx.int_const("y"); 
   expr sub_expr = (x <= y)  && (y <= 2*x);

   Z3_ast qf = Z3_mk_exists_const(ctx, 0, 1, (Z3_app[]) {x}, 
                                  0, {}, // patterns don't seem to make sense here.
                                  sub_expr); //No C++ API for quantifiers :(
   qf = Z3_simplify(ctx, qf);
   cout << Z3_ast_to_string(ctx, qf);

我得到的是

  

(exists((x Int)(和(&lt; = x y)(&lt; = y(* 2 x))))

虽然我想获得像

这样的东西
  

(&lt; = 0 y)

是否有可能通过Z3获得它? 提前谢谢了。

2 个答案:

答案 0 :(得分:4)

Nikolaj已经指出,战术可用于执行量词消除。在这篇文章中,我想强调如何安全地混合C ++和C API。 Z3 C ++ API使用引用计数来管理内存。 expr本质上是一个“智能指针”,可以自动管理引用计数器。我在以下帖子中讨论了这个问题:Array select and store using the C++ API

因此,当我们调用返回Z3_ast的C API时,我们应该使用函数to_exprto_sortto_func_decl来包装结果。 to_expr的签名是:

inline expr to_expr(context & c, Z3_ast a);

通过使用此函数,我们可以避免内存泄漏和崩溃(访问Z3垃圾收集的对象时)。以下是使用to_expr()的完整示例。您可以通过在Z3发行版的example.cpp文件夹中的c++文件中复制此功能来测试它。

void tst_quantifier() {
    context ctx;
    expr x = ctx.int_const("x"); 
    expr y = ctx.int_const("y"); 
    expr sub_expr = (x <= y) && (y <= 2*x);
    Z3_app vars[] = {(Z3_app) x};

    expr qf = to_expr(ctx, Z3_mk_exists_const(ctx, 0, 1, vars,
                                              0, 0, // patterns don't seem to make sense here.
                                              sub_expr)); //No C++ API for quantifiers :(
    tactic qe(ctx, "qe");
    goal g(ctx);
    g.add(qf);
    std::cout << qe.apply(g);
}

答案 1 :(得分:3)

简化器不再调用量词消除程序。可以通过策略获得量词消除和许多其他特殊用途的简化重写。

C ++包装器z3 ++。h公开了创建战术对象的方法。 你必须为“qe”策略创建一个战术对象。 Z3发行版附带了几个使用z3 ++。h API策略的示例。 例如:

void tactic_example1() {
/*
  Z3 implements a methodology for orchestrating reasoning engines where "big" symbolic
  reasoning steps are represented as functions known as tactics, and tactics are composed
  using combinators known as tacticals. Tactics process sets of formulas called Goals.

  When a tactic is applied to some goal G, four different outcomes are possible. The tactic succeeds
  in showing G to be satisfiable (i.e., feasible); succeeds in showing G to be unsatisfiable (i.e., infeasible); 
  produces a sequence of subgoals; or fails. When reducing a goal G to a sequence of subgoals G1, ..., Gn, 
  we face the problem of model conversion. A model converter construct a model for G using a model for some subgoal Gi.

  In this example, we create a goal g consisting of three formulas, and a tactic t composed of two built-in tactics: 
  simplify and solve-eqs. The tactic simplify apply transformations equivalent to the ones found in the command simplify. 
  The tactic solver-eqs eliminate variables using Gaussian elimination. Actually, solve-eqs is not restricted 
  only to linear arithmetic. It can also eliminate arbitrary variables. 
  Then, sequential composition combinator & applies simplify to the input goal and solve-eqs to each subgoal produced by simplify. 
  In this example, only one subgoal is produced.
*/
std::cout << "tactic example 1\n";
context c;
expr x = c.real_const("x");
expr y = c.real_const("y");
goal g(c);
g.add(x > 0);
g.add(y > 0);
g.add(x == y + 2);
std::cout << g << "\n";
tactic t1(c, "simplify");
tactic t2(c, "solve-eqs");
tactic t = t1 & t2;
apply_result r = t(g);
std::cout << r << "\n";

}

在你的情况下,你会想要的东西:

context ctx;
expr x = ctx.int_const("x"); 
expr y = ctx.int_const("y"); 
expr sub_expr = (x <= y)  && (y <= 2*x);

Z3_ast qf = Z3_mk_exists_const(ctx, 0, 1, (Z3_app[]) {x}, 
                              0, {}, // patterns don't seem to make sense here.
                              sub_expr); //No C++ API for quantifiers :(
tactic qe(ctx, "qe");
goal g(ctx);
g.add(qf);
cout << qe.apply(g);