假设我有两个约束(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()方法对于大型约束非常昂贵。
两个问题:
如何在Z3(Java版本)中检查两个约束在语法上是否完全相同?
如果我们没有1的好解决方案,我正在考虑为 Expr 对象编写一个包装器并使用工厂方法来避免生成重复(语法)对象来自Z3。然后我必须设计自己的equal()和hashCode()函数。但到目前为止,我仍然无法找到一种有效的方法。
答案 0 :(得分:4)
Expr类派生自AST,为此目的,它具有equals
,compareTo
和hashCode
函数。由于Z3使用散列值,这非常有效,基本上只是指针的比较(在Java中,是一个强制转换)。
答案 1 :(得分:1)
不是一个真正的答案,但是评论的时间太长了。
在Expr中调用toString()方法对于大型约束非常昂贵。
我建议查看toString
实施。有一个可能的原因是它很慢:dumb String连接而不是StringBuilder
。如果是这样,那么您可能希望提供更快的实现。但是,无论如何,解决打印时间过长的CSP是徒劳的。
如何在Z3
中检查两个约束在语法上是否完全相同
我敢打赌,使用toString
不是a && b
和b && a
相同的方式,但他们的字符串表示不是。
您可能需要使用交换性,关联性以及其他规则来规范化表达式。为此,您需要在条款上有一些任意但equals
- 一致的排序。
你肯定不想检查所有对的约束是否相等。在这里,根据哈希码将约束放入桶中有助于。不知道,如果提供的hashCode
可用于此目的。
然后我必须设计自己的equal()和hashCode()函数。但到目前为止,我仍然无法找到一种有效的方法。
标准化后应该相当简单。如果您因此进行规范化并将每个表达式映射到规范表示(就像String#intern
那样),那么您可以使用equals
的引用相等性。对于hashCode
,您需要为每个树节点组合公式,例如,您可以将a && b
的哈希码计算为f(111 * ha + hb)
,其中ha
和hb
是分别为a
和b
以及f(x) = x ^ (x>>15)
或类似的哈希码。