在序言中阅读剪辑!



我现在正在通读学习Prolog!关于削减的章节,同时是布拉特科的人工智能Prolog编程,第5章:控制回溯。起初,剪切似乎是一种模仿其他编程语言中已知的if-else子句的直接方法,例如

# Find the largest number
max(X,Y,Y):- X =< Y,!. 
max(X,Y,X).

但是,正如下面所指出的,即使在我们期望false的情况下,该代码也会失败,即使所有变量都被实例化,例如

?- max(2,3,2).
true.

原因很清楚:第一条规则失败,第二条规则不再有任何与之相关的条件,因此它将成功。我明白这一点,但随后提出了一个解决方案(这是一个嗖嗖声):

max(X,Y,Z):- X =< Y,!, Y = Z. 
max(X,Y,X).

我很困惑我应该如何阅读这篇文章。我想!的意思是:"如果在此!之前的所有内容都是真的,请停止终止,包括具有相同谓词的任何其他规则"。但是,这不可能是正确的,因为这意味着Y = Z的实例化仅在失败的情况下发生,这对于该规则毫无用处。

那么,应该如何以"人"的方式解读切割呢?而且,作为扩展,我应该如何阅读上述max/3的建议解决方案?

另请参阅此答案和此问题。

我应该如何阅读上述 max/3 的建议解决方案?

max(X,Y,Z):- X =< Y, !, Y = Z. 
max(X,Y,X).

您可以按如下方式阅读:

X =< Y时,忘记谓语的第二句,统一YZ

削减会丢弃选择点。选择点是证明树中的标记,告诉Prolog在找到解决方案后在哪里继续搜索更多解决方案。因此,切割切掉了证明树的一部分。上面的第一个链接(再次在这里)详细讨论了削减,但该答案的很大一部分只是引用其他人对其他地方削减的看法。

我想带回家的信息是,一旦你在Prolog程序中进行了削减,你就会强迫自己在操作上而不是声明性地阅读它。为了理解证明树的哪些部分将被切断,你(程序员)必须经历动作,考虑子句的顺序,考虑哪些子目标可以创建选择点,考虑哪些解决方案丢失。你需要构建证明树(而不是让Prolog来做)。

您可以使用许多技术来避免创建您知道不需要的选择点。然而,这是一个有点大的话题。您应该阅读可用的材料并提出具体问题。

代码的问题在于,在评估查询时永远不会达到切口。

尝试使用规则评估目标的第一步是模式匹配。

目标max(2,3,2)与模式max(X,Y,Y)不匹配,因为第二个和第三个参数在模式中是相同的,并且 3 和 2 彼此模式不匹配。 因此,该规则在模式匹配阶段已经失败,因此评估器无法测试X =< Y,更不用说达到!了。

但是你对削减的理解几乎是正确的。 给定此代码

a(X) :- b(X).
a(X) :- c(X).
b(X) :- d(X), !.
b(X) :- e(X).
c(3).
d(4).
d(5).
e(6).

和目标

?- a(X).

解释器将从第一条规则开始,尝试满足b(X)。 在此过程中,它发现d(4)提供了解决方案,因此将值4绑定到X。 然后切入,丢弃b(X)的回溯,因此找不到进一步的b(X)解决方案。 但是,它不会删除a(X)上的回溯,因此,如果您要求Prolog找到另一种解决方案,那么它将通过a(X) :- c(X).规则找到X = 3。 如果将第一个规则更改为a(X) :- b(X), !.则无法找到X = 3

尽管剪切意味着找不到X = 5解决方案,但如果您的查询是

?- a(5).

然后解释器将返回 true。 这是因为a(5)调用b(5)d(5),这被定义为 true。d(4)事实无法进行模式匹配,因此它不会像查询a(X)时那样触发剪切。

这是红色切口的一个例子(请参阅我对user1812457的答案的评论)。 也许避免红色切割的一个很好的理由,除了它们破坏逻辑纯洁性之外,是为了避免这种行为导致的错误。

相关内容

  • 没有找到相关文章

最新更新