在Z3中有效地检验两个约束的句法等价

时间:2014-08-11 20:33:45

标签: java performance z3

假设我有两个约束(c1,c2),我想检查它们是否语法相同:

c1: f(x)>1 && g(y)=2
c2: f(x)>1 && g(y)=2

选项1: 我们可以把这变成一个像这篇文章这样的可满足性问题: Whether two boolexpr are equal

选项2: 我们也可以把它们变成字符串并比较相等:

if(c1.toString().equals(c2.toString()))
    ///do somthing

但是随着约束的大小增加,这两个选项都有很大的开销。例如在 Expr 中调用toString()方法对于大型约束非常昂贵。

两个问题:

  1. 如何在Z3(Java版本)中检查两个约束在语法上是否完全相同?

  2. 如果我们没有1的好解决方案,我正在考虑为 Expr 对象编写一个包装器并使用工厂方法来避免生成重复(语法)对象来自Z3。然后我必须设计自己的equal()和hashCode()函数。但到目前为止,我仍然无法找到一种有效的方法。

2 个答案:

答案 0 :(得分:4)

Expr类派生自AST,为此目的,它具有equalscompareTohashCode函数。由于Z3使用散列值,这非常有效,基本上只是指针的比较(在Java中,是一个强制转换)。

答案 1 :(得分:1)

不是一个真正的答案,但是评论的时间太长了。

  

在Expr中调用toString()方法对于大型约束非常昂贵。

我建议查看toString实施。有一个可能的原因是它很慢:dumb String连接而不是StringBuilder。如果是这样,那么您可能希望提供更快的实现。但是,无论如何,解决打印时间过长的CSP是徒劳的。

  

如何在Z3

中检查两个约束在语法上是否完全相同

我敢打赌,使用toString不是a && bb && a相同的方式,但他们的字符串表示不是。

您可能需要使用交换性,关联性以及其他规则来规范化表达式。为此,您需要在条款上有一些任意但equals - 一致的排序。

你肯定不想检查所有对的约束是否相等。在这里,根据哈希码将约束放入桶中有助于。不知道,如果提供的hashCode可用于此目的。

  

然后我必须设计自己的equal()和hashCode()函数。但到目前为止,我仍然无法找到一种有效的方法。

标准化后应该相当简单。如果您因此进行规范化并将每个表达式映射到规范表示(就像String#intern那样),那么您可以使用equals的引用相等性。对于hashCode,您需要为每个树节点组合公式,例如,您可以将a && b的哈希码计算为f(111 * ha + hb),其中hahb是分别为ab以及f(x) = x ^ (x>>15)或类似的哈希码。