我最近开始使用带有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)没有给我我想要的输出。
答案 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是一个好主意,以了解所有的复杂性。