Prolog中的cut有什么用途?
这两个步骤的轨迹有什么不同 (一) (二)Prolog中的cut有什么用途?,prolog,Prolog,这两个步骤的轨迹有什么不同 (一) (二) 当Prolog执行一个查询时,它会寻找使查询成功的所有解决方案(true)。在一个非常简单的情况下,如果我有: foo(a). foo(b). 然后我进入: | ?- foo(X). X = a ? ; X = b yes 您可以看到Prolog找到两个解决方案,然后停止。这里发生的是,在Prolog找到解决方案X=a并按下,您要求Prolog找到更多解决方案。Prolog然后返回到最近遇到的“选择点”(在查询执行过程中,它有一个关于如何选择
当Prolog执行一个查询时,它会寻找使查询成功的所有解决方案(true)。在一个非常简单的情况下,如果我有:
foo(a).
foo(b).
然后我进入:
| ?- foo(X).
X = a ? ;
X = b
yes
您可以看到Prolog找到两个解决方案,然后停止。这里发生的是,在Prolog找到解决方案X=a
并按下代码>,您要求Prolog找到更多解决方案。Prolog然后返回到最近遇到的“选择点”(在查询执行过程中,它有一个关于如何选择有效的替代选择的决定),并尝试另一个选择。在本例中,它查找foo(b)
并匹配foo(X)
,因此您也可以得到X=b
。Prolog在找到X=b
后没有更多的选择点,因此它在提示X=b
后没有选择,只说yes
(最后一次成功)
序言切割(!
)用于消除选择点。或者说另一种方式,它告诉Prolog,在这一点之前不要回溯
现在让我们在我们的简单案例中引入一个切入点:
foo(a) :- !.
foo(b).
然后查询变成:
| ?- foo(X).
X = a
yes
Prolog找到解决方案X=a
后,cut消除了回溯
在使用find/2
的给定示例中,如果我们执行查询,find(b[a,b,c])。
对于非剪切版本,我们得到:
| ?- find(b, [a,b,c]).
true ? ;
no
| ?- find(b, [a,b,c]).
yes
如果我们对剪切版本执行相同的操作,我们会得到:
| ?- find(b, [a,b,c]).
true ? ;
no
| ?- find(b, [a,b,c]).
yes
嗯。他们都成功地找到了b
,但结果看起来有点不同。在第一种情况下,Prolog在最后遇到子句时在[a,b,c]
中找到b
,find(X,[X | |)]。
但是没有切割,所以这里有一个选择点,因为仍然有下面的子句,find(X,[u124; Tail):-…
.Prolog说,true?
并询问您是否希望回溯以找到更多的解决方案(返回到选择点)。由于它无法从该选择点找到另一个解决方案,它最后说,“否”
在第二种情况下,Prolog通过子句find(X,[X |]):-!
找到第一个解决方案(success)。
但是切割消除了选择点,并告诉Prolog,如果你到了这里,就不要麻烦从这一点开始回溯到任何其他解决方案。因此,你只要得到“是”就成功了,Prolog就不再寻找更多的解决方案
当只有一个解决方案时,剪切只是删除不必要的回溯,以找到更多不存在的解决方案。但是如果有多个解决方案可用,剪切将阻止Prolog回溯并找到其中一些解决方案
下面是另一个简单的例子,说明了剪切可以做的“修剪解决方案”:
a(1). a(2).
b(1). b(2).
foo(X, Y) :- a(X), b(Y).
然后查询:
| ?- foo(X, Y).
X = 1
Y = 1 ? a
X = 1
Y = 2
X = 2
Y = 1
X = 2
Y = 2
yes
| ?-
| ?- foo(X, Y).
X = 1
Y = 1 ? a
X = 1
Y = 2
yes
| ?-
引入削减:
foo(X, Y) :- a(X), !, b(Y).
然后查询:
| ?- foo(X, Y).
X = 1
Y = 1 ? a
X = 1
Y = 2
X = 2
Y = 1
X = 2
Y = 2
yes
| ?-
| ?- foo(X, Y).
X = 1
Y = 1 ? a
X = 1
Y = 2
yes
| ?-
这种情况下发生的情况是,切割阻止了回溯,以在子句中找到a(X)
的附加选项。但在为b(Y)
找到解决方案时,仍然有一个选择点,我们没有切割这些选项。如果我们将切割放在b(Y)
之后,如下所示,那么这些选项也将被切割:
foo(X, Y) :- a(X), b(Y), !.
那么它只能找到一个解决方案:
| ?- foo(X, Y).
X = 1
Y = 1
yes
| ?-
许多Prolog书籍都有一些关于剪切的讨论。一本很好的书是Clocksin&Mellish在Prolog中编程。它有图表等,显示了剪切点和选择点是如何工作的。可能重复它有点不同,因为据我所知,在这种情况下,输出不会因为!而改变。输出将根据您的查询内容而改变。请尝试
find(b[a,b,c,b,d])
对每种情况进行查找,看看会发生什么。第一个会找到两个解决方案。第二个会在找到解决方案后进行剪切,并且不提供回溯。因此,找不到任何后续的解决方案。如果将这些谓词编写为输出,例如,出现次数,这一点尤其明显。