0

在learnprolognow上做练习 10.4 ,有人可以向我解释或帮助我想象为什么?- p(X),p(Y)我们得到:
X=1,Y=1; X=1,Y=2; X=2, Y=1; X=2, Y=1. 而且不仅仅是 X=1, Y=1; X=1, Y=2.

我想我误解了切割是如何发生的,当它在规则集中而不是在查询中时 - 因为我认为我可以将它可视?- p(X),!,p(Y).化为 ,它实际上的行为就像我认为的最后一个......

编辑:来自网站

% database
p(1).
p(2):-!.
p(3).

% Queries
p(X). % returns: X=1; X=2.
p(X),p(Y). % returns: X=1,Y=1; X=1, Y=1; X=2, Y=2. (?)
p(X),!,p(Y). % returns X=1, Y=1; X=1, Y=2.
4

1 回答 1

1

要理解这个问题,您可以想象一棵树,其中Xin 作为第一级和Y第二级(prolog 使用可以用树很好地描述的 sld 分辨率)。考虑这个问题:

p(1).
p(2):-!.
p(3).

sol(X,Y):-
    p(X),
    p(Y).

我添加了谓词solve/2以使其更清晰。运行查询:

?- solve(X,Y).

首先,您必须选择 的值X。Prolog 使用从上到下,从左到右的深度优先搜索。所以它评估p(x)p(1)成功(因为是第一个子句,如果你p(2)在上面写p(1)p(2)将成功)等等X = 1。然后评估p(Y)p(1)成功,所以你有第一个解决方案:

X = Y, Y = 1.

如果单击 more,则 prolog 会进行回溯(您可以将其想象为树上的一个步骤)并尝试为p(Y). 在这种情况下p(2)成功,谓词为真,你得到:

X = 1, Y = 2.

现在,如果您单击更多,由于在(prolog 中的一般规则具有形式)!的主体中有一个切口(),prolog 不会更深入并被忽略。所以没有更多的解决方案。所以还有另一个回溯,这一次, for ,成功 和,成功,你得到:p(2)head :- bodyp(3)p(Y)p(X)p(2)X = 2p(Y)p(1)

X = 2, Y = 1.

如果您点击更多,您将获得:

X = Y, Y = 2.

现在,由于在 之后有一个删减p(2),因此没有更多的解决方案适用于XY!删减下面的所有内容p(2))。

如果您删除切口,您将获得所有可能的解决方案:

X = Y, Y = 1
X = 1,
Y = 2
X = 1,
Y = 3
X = 2,
Y = 1
X = Y, Y = 2
X = 2,
Y = 3
X = 3,
Y = 1
X = 3,
Y = 2
X = Y, Y = 3

请记住,子句的顺序很重要。如果你写

p(2).
p(1):-!.
p(3).

你得到

X = Y, Y = 2
X = 2,
Y = 1
X = 1,
Y = 2
X = Y, Y = 1

您可以使用跟踪器检查此行为。在 SWI 或 SWISH 你可以写?- trace, solve(X,Y).

如果你有这样的情况:

p(1).
p(2).
p(3).

sol(X,Y):-
    p(X),
    !,
    p(Y).

prolog 将测试所有可能的值,Y并且只有一个值,X因为切割停止了对树的探索(理想情况下,(1,2,3) 有 3 个分支,X(1,2,3)有 3 个分支Y!切割 2 和3 从X) 你得到:

X = Y, Y = 1
X = 1,
Y = 2
X = 1,
Y = 3

对不起,很长的帖子,希望清楚。

于 2018-01-05T16:57:42.103 回答