自动定理证明的重要部分是通过弄清一个子句何时包含另一个子句来减少冗余。
从直觉上讲,一个子句(CNF中的一阶逻辑公式)C至少包含一个子句D时,通常包含另一个子句D。具体定义是必须将变量替换为将C变成D的子多重集的项。(不是子集;这将使子句包含其自身的因子,这将破坏某些最佳饱和度计算的完整性。例如叠加。)
有一些索引技术可以极大地减少必须进行的包含尝试的次数,但是即使这样,包含也可以消耗大量的CPU时间,因此对其进行优化很重要。显然,在一般情况下它是NP难解的,但要使大多数特定情况下快速运行仍然是可能而且必要的。
以下伪代码正确但无效。 (在实践中,负数和正数文字必须分别处理,然后出现像尝试双向求解方程式这样的问题,但是在这里,我仅考虑匹配两袋文字的核心算法。)
def match_clauses(c, d, map):
if c == {}:
return true
for ci in c:
for di in d:
if match_terms(ci, di, map):
if match_clauses(c - ci, d - di, map):
return true
return false
为什么效率低下?考虑两个子句p(x) | q(y) | r(42)
和p(x) | q(y) | r(54)
。上面的算法将首先成功匹配p(x)
,然后成功匹配q(y)
,然后注意r(42)
不匹配r(54)
。好的,但是它将以另一种方式尝试:首先成功匹配q(y)
,然后成功匹配p(x)
,然后再次注意r(42)
与r(54)
不匹配。如果有N个文字确实匹配,那么浪费的工作将是N个阶乘,在某些实际情况下会严重降低效率。
毫无疑问,我有足够的时间想出一种更好的算法,但是其他人必须在我之前完成此操作,因此似乎值得一问:什么是最知名的算法?