我正在试验 Z3,我结合了算术、量词和相等的理论。这似乎不是很有效,事实上,在可能的情况下用所有实例化的地面实例替换量词似乎更有效。考虑以下示例,其中我为一个函数编码了唯一名称公理,该函数f
接受两个 sort 参数Obj
并返回一个解释的 sort S
。这个公理表明每个唯一的参数列表都f
返回一个唯一的对象:
(declare-datatypes () ((Obj o1 o2 o3 o4 o5 o6 o7 o8)))
(declare-sort S 0)
(declare-fun f (Obj Obj) S)
(assert (forall ((o11 Obj) (o12 Obj) (o21 Obj) (o22 Obj))
(=>
(not (and (= o11 o21) (= o12 o22)))
(not (= (f o11 o12) (f o21 o22))))))
尽管这是在逻辑中定义这样一个公理的标准方法,但像这样实现它在计算上是非常昂贵的。它包含 4 个量化变量,每个变量可以有 8 个值。这意味着这会导致8^4 = 4096
平等。这需要 Z3 0.69s 和 2016 量词实例化来证明这一点。当我编写一个生成此公式实例的简单脚本时:
(assert (distinct (f o1 o1) (f o1 o2) .... (f o8 o7) (f o8 o8)))
生成这些公理需要 0.002 秒,在 Z3 中证明它需要 0.01 秒(或更少)。当我们增加域中的对象或函数的参数数量时,f
这种差异会迅速增加,量化的情况很快就会变得不可行。
这让我想知道:当我们有一个有界域时,为什么我们首先要在 Z3 中使用量词?我知道 SMT 使用启发式方法来寻找解决方案,但我觉得它仍然无法与一个简单的特定领域接地器在效率上竞争,后者将接地实例提供给 SMT,这只不过是 SAT 解决方案。我的直觉正确吗?