理解模型的所有常量的索引

时间:2015-05-11 22:15:49

标签: z3

我想我的问题与Read func interp of a z3 array from the z3 model有关,但我仍然无法理解如何修复它。

编辑:我认为它也与de bruijn指数挂钩:Understanding the indexing of bound variables in Z3

这是我为解释问题而建立的一个小例子:

#include <iostream>
#include <sstream>
#include <cassert>
#include "z3++.h"

using namespace z3;

int main(void)
{
    context ctx;
    params p(ctx);
    p.set("MACRO_FINDER",true);

    expr_vector v(ctx);
    sort_vector sv(ctx);
    for(int i = 0; i < 3; i++)
    {
        std::ostringstream o;
        o << "c[" << i << "]";
        expr c = ctx.bv_const(o.str().c_str(),1);
        v.push_back(c);
        sv.push_back(ctx.bv_sort(1));
    }

    expr x = ctx.bv_const("x",8);

    v.push_back(x);
    sv.push_back(ctx.bv_sort(8));

    expr one_bit = ctx.bv_val(1,1);
    expr two = ctx.bv_val(2,8);
    expr one = ctx.bv_val(1,8);
    expr zero = ctx.bv_val(0,8);
    expr fcore = x + ite(v[1] == one_bit , one, zero) + ite(v[2] == one_bit, two, zero); 

    func_decl f = ctx.function("f",sv,ctx.bv_sort(8));

    solver s(ctx);
    s.set(p);
    s.add(forall(v,f(v) == fcore));

    expr_vector t1(ctx);
    expr_vector t2(ctx);
    t1.push_back(v[0]); t1.push_back(v[1]); t1.push_back(v[2]); t1.push_back(ctx.bv_val(0,8));
    t2.push_back(v[0]); t2.push_back(v[1]); t2.push_back(v[2]); t2.push_back(ctx.bv_val(1,8));
    expr constraints = (f(t1) == ctx.bv_val(1,8)) && (f(t2) == ctx.bv_val(2,8));

    s.add(exists(v[0],v[1],v[2],constraints));

    std::cout << "Solver: " << s << "\n\n";
    if(s.check()==sat)
    {
        model m = s.get_model();
        std::cout << "Model: " << m << "\n\n";
        std::cout << "Number of constants: " << m.num_consts() << "\n";

        expr F = m.eval(f(v),true);

        for(size_t i = 0; i < m.num_consts(); ++i)
            std::cout << "\t constant " << i << ": " << "(" << m.get_const_decl(i).name() << ") " << m.get_const_interp(m.get_const_decl(i)) << "\n";

        std::cout << "Number of functions: " << m.num_funcs() << "\n";
        std::cout << "\t" << F << "\n";
    }
    else
        std::cout << "unsat\n";
    return 0;
}

通过运行此程序,我得到以下输出:

Solver: (solver
  (forall ((|c[0]| (_ BitVec 1))
           (|c[1]| (_ BitVec 1))
           (|c[2]| (_ BitVec 1))
           (x (_ BitVec 8)))
    (= (f |c[0]| |c[1]| |c[2]| x)
       (bvadd x (ite (= |c[1]| #b1) #x01 #x00) (ite (= |c[2]| #b1) #x02 #x00))))
  (exists ((|c[0]| (_ BitVec 1)) (|c[1]| (_ BitVec 1)) (|c[2]| (_ BitVec 1)))
    (and (= (f |c[0]| |c[1]| |c[2]| #x00) #x01)
         (= (f |c[0]| |c[1]| |c[2]| #x01) #x02))))

Model: (define-fun |c[2]!0| () (_ BitVec 1)
  #b0)
(define-fun |c[1]!1| () (_ BitVec 1)
  #b1)
(define-fun f ((x!1 (_ BitVec 1))
 (x!2 (_ BitVec 1))
 (x!3 (_ BitVec 1))
 (x!4 (_ BitVec 8))) (_ BitVec 8)
  (bvadd x!4 (ite (= #b1 x!3) #x02 #x00) (ite (= #b1 x!2) #x01 #x00)))

Number of constants: 2
         constant 0: (c[2]!0) #b0
         constant 1: (c[1]!1) #b1
         constant 2: (c[0]) #b0
         constant 3: (c[1]) #b0
         constant 4: (c[2]) #b0
         constant 5: (x) #x00
Number of functions: 1
        #x00

我没有得到:

  • 为什么它枚举6个常数而不是3?
  • 如何检索向量“v”的第n个常量的值而不解析它们的名称,这不是模型“m”的第n个常量?
  • 为什么c [1]的评估结果为0而我希望它评估为1?
  • 什么“!x”在常数c [2]!0和c [1]的名称中表示!1?

我想将c [0],c [1]和c [2]的评估重新注入函数f(),以简化其表达式(我希望得到x + 1)

注意:c [0]不是故意使用的......

1 个答案:

答案 0 :(得分:1)

感谢Tushar回答这个帖子。你是对的,其他变量来自存在量词。 Z3将对这些变量进行分析,并且目前看来,Z3返回的模型包括来自skolemized存在量词的常量。 这显然令人困惑,我们可能在将来过滤 这些变量(和函数)远离模型构造。另一方面,用于存在变量的命名约定保留了量词的名称,因此至少可以手动跟踪这些额外变量的来源。