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])
对每种情况进行查找,看看会发生什么。第一个会找到两个解决方案。第二个会在找到解决方案后进行剪切,并且不提供回溯。因此,找不到任何后续的解决方案。如果将这些谓词编写为输出,例如,出现次数,这一点尤其明显。