如何有效地提取Z3中的子公式(谓词,术语)?

时间:2014-09-11 01:26:00

标签: java performance z3

假设我想从具有BoolExpr类型的给定约束中提取所有子公式(谓词,术语),这里有两个例子:

(f(x)=2 and f(y)=3) or (f(z)=1 and f(y)=3)
The output should be f(x)=2, f(y)=3 and f(z)=1.

(p and q) or (p or r) and (p and (q or r))
The output should be p, q and r.

一种天真的方式是遍历整个AST并记录所有独特的子公式。当AST中存在大量冗余节点并且我们必须经常执行这样的提取时,这是令人不愉快的。 我想知道是否存在一种干净有效的方法来做到这一点。

我正在使用Java API for Z3。

1 个答案:

答案 0 :(得分:1)

您可以利用表达式是唯一的这一事实。 您可以将它们插入到有序字典或散列表中,并使用字典/散列表 检测您是否已经遍历了相同的子表达式。

您还可以利用每个子表达式都具有唯一标识符的事实。 标识符是唯一的,只要表达式仍然是" live",也就是说,它没有被垃圾收集。你当然可以" pinn" (通过维护您跟踪的表达式列表,确保表达式不是垃圾回收)表达式。 使用方法" getId"访问唯一标识符。它在AST.java中定义 (和.NET的Ast.cs,C的z3_api.h和C ++的z ++。)。

  /**
   * A unique identifier for the AST (unique among all ASTs).
   **/
  public int getId() throws Z3Exception
  {
      return Native.getAstId(getContext().nCtx(), getNativeObject());
  }

一个好的遍历算法然后维护一个缓存(从整数标识符到子公式的字典)。在遍历子表达式之前,如果已经看到此标识符,它将检查缓存。

标识符用于" compareTo"对使用的AST对象的方法 表达式(函数应用程序,量化,绑定变量),排序和函数。 因此,您也可以选择将缓存维护为一组先前看到的表达式,而无需访问较低级别的整数标识符。 有关更多详细信息,请参阅AST.java。