更好地理解序言

我试图了解 Prolog 以及它如何使用解析算法。我有这个例子,我发现:

hates(1, 2).
hates(2, 3).
hates(3, 4).
jealous(A, B) :- jealous(A, C), jealous(C,B).
jealous(A,B) :- hates(A,B).

但是当我试图说jealous(1,4)然后它不断溢出并且永远不会产生真时,这很奇怪,好像1讨厌2,2讨厌3,3讨厌4,那么1也应该讨厌4。

但是我尝试改变它,所以它是这样的:

hates(1, 2).
hates(2, 3).
hates(3, 4).
jealous(A,B) :- hates(A,B).
jealous(A, B) :- jealous(A, C), jealous(C,B).

然后当我说jealous(1,4).

回答

然后当我说的时候它就起作用了 jealous(1,4)

不,它没有。或者,嗯,有点。只需键入SPACE以查看它是否再次循环。又是怎么回事jealous(4,1)这立即循环?

要理解这一点,只需查看程序的一小部分就足够了,即:

嫉妒(A,B): -错误,讨厌(A,B)。
嫉妒(A,B): - 嫉妒(A,C),假, 嫉妒(C,B)

注意B在可见部分从未使用过的变量。所以它不会对终止产生任何影响。并注意A哪个刚刚交给第一个目标。所以这两个参数在这个程序中都没有影响。因此这个程序永远不会终止。它可能会在这里和那里找到解决方案,但是当被要求找到所有解决方案时,它永远不会终止。

这个小片段称为失败切片,如果它没有终止,那么你的整个程序也会终止!也就是说,没有必要读你的定义,hates/2在所有1

如果您想掌握 Prolog 的执行,您需要掌握失败切片的概念。因为,有经验的程序员或多或少是凭直觉做到这一点的。因此,他们不会阅读整个程序,他们只是扫描相关部分。Prolog 中的好处是这样的切片和整个程序之间存在真正的因果关系。

要解决此问题,您需要更改故障切片突出显示的部分中的某些内容。这是一种可能的变化:

jealous(A,B) :- false, hates(A,B).
jealous(A, B) :- jealous(A, C), false, jealous(C,B).

但是一旦你有了循环hates/2,这将不再有效。然后,考虑closure/3

jealous(A,B) :- hates(A,B).
jealous(A, B) :- hates(A, C), jealous(C,B).

另一种方法是使用表格。但请注意,制表解决了这一问题,但在约束环境中将不再起作用(您迟早会遇到这种情况)。


1) 前提是你有一个纯单调的程序。


以上是更好地理解序言的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>