如何使用z3中的arg()函数?

时间:2019-06-05 06:52:53

标签: c++ z3

我最近开始使用带有c ++绑定的z3 API。我的任务是获取 表达式中的单个元素

示例:(x || !z) && (y || !z) && (!x || !y || z)

如何通过使用arg(i)函数索引每个位置来获取单个变量?

在给定示例的情况下,arg(1)应该返回变量“ X”。 z3中还有其他功能可以给我想要的输出吗?

这是我尝试过的代码,但输出不是单个变量:

#include<iostream> 
#include<string>
#include "z3++.h"
using namespace z3;

int main()
{
    context c;
    expr x = c.bool_const("x");
    expr y = c.bool_const("y");
    expr z = c.bool_const("z");
    expr prove = (x || !z) && (y || !z) && (!x || !y || z);
    solver s(c);
    expr argument = prove.arg(1);
    std::cout<<argument;  
}

输出:

(or (not x) (not y) z)(base)

我基本上需要创建一个自动化系统,该系统为表达式中的每个位置建立索引,并检查其是运算符还是操作数,然后插入到数据结构中。因此,我认为我会创建一个循环并在表达式中的每个位置建立索引。但是arg(i)没有给我我想要的输出。

1 个答案:

答案 0 :(得分:1)

您必须遍历AST并挑选节点。 Z3 AST可能比较毛茸茸,因此在不确切知道您的目标是什么的情况下,很难确定这是否是最佳方法。但是,假设您真的想遍历AST,就可以按照以下步骤进行操作:

#include<iostream>
#include<string>
#include "z3++.h"
using namespace z3;
using namespace std;

void walk(int tab, expr e)
{
    string blanks(tab, ' ');

    if(e.is_const())
    {
        cout << blanks << "ARGUMENT: " << e << endl;
    }
    else
    {
        cout << blanks << "APP: " << e.decl().name() << endl;
        for(int i = 0; i < e.num_args(); i++)
        {
            walk(tab + 5, e.arg(i));
        }
    }
}

int main()
{
    context c;
    expr x = c.bool_const("x");
    expr y = c.bool_const("y");
    expr z = c.bool_const("z");
    expr e = (x || !z) && (y || !z) && (!x || !y || z);

    walk(0, e);
}

运行时,此程序将打印:

APP: and
     APP: and
          APP: or
               ARGUMENT: x
               APP: not
                    ARGUMENT: z
          APP: or
               ARGUMENT: y
               APP: not
                    ARGUMENT: z
     APP: or
          APP: or
               APP: not
                    ARGUMENT: x
               APP: not
                    ARGUMENT: y
          ARGUMENT: z

因此,您确切地看到了应用程序(APP)和参数(ARGUMENT)的位置。您可以从这里获取并构建您正在讨论的数据结构。

但是,请注意z3 AST可以具有许多不同种类的对象:量词,数字,位向量,浮点数。因此,如果您想对任意z3表达式进行这项工作,那么在开始编码之前详细研究实际的AST是一个好主意,以了解所有的复杂性。