此代码如何工作?我很难对C
和X
的第一个可能的值起作用,但不知何故它会循环。
path(A, B, [A, B], X) :-
route(A, B, X).
path(A, B, PathAB, Length) :-
route(A, C, X),
path(C, B, PathCB, LengthCB),
PathAB = [A | PathCB],
Length is X + LengthCB.
routes
定义为route(bahirdar, mota, 32).
。
答案 0 :(得分:1)
举个简单的例子,假设你有以下事实:
foo(1).
foo(2).
然后你查询:
| ?- foo(X).
Prolog将成功X = 1
并提示:
X = 1 ?
?
表示有一个选择点(它为foo
找到了要探索的其他选项),如果按;
并按Enter键,它将回溯< / em>并尝试找到另一种解决方案,并提示:
X = 2 ?
现在,如果按;
并输入,则会失败并停止,因为它无法再继续成功。
让我们尝试使用连词更精细一些。使用事实:
foo(1).
foo(2).
foo(3).
规则:
odd(X) :- X /\ 1 =:= 1. % X is odd if X bit-wise and with 1 is 1
然后执行一个查询,说我希望X
为foo
和我希望X
为odd
:
| ?- foo(X), odd(X).
X = 1 ? ;
X = 3 ? ;
no
| ?-
请注意,我们只得到奇怪的解决方案。此查询中发生的情况如下:
foo(X)
并以X = 1
成功。odd(1)
(因为X
被实例化为1)并且成功X = 1
。odd(1)
,它没有要重新复制的变量,因此Prolog进一步回溯foo(X)
并以X = 2
成功继续前进odd(2)
并失败。失败导致Prolog回溯到foo
电话foo(X)
并以X = 3
成功继续前进odd(3)
并成功并显示解决方案X = 3
&lt; 立即将此应用于您的谓词:
path(A, B, [A, B], X) :-
route(A, B, X).
path(A, B, PathAB, Length) :-
route(A, C, X),
path(C, B, PathCB, LengthCB),
PathAB = [A | PathCB],
Length is X + LengthCB.
如果对path
进行查询,则Prolog首先尝试将查询与第一个子句path(A, B, [A, B], X)
的头部匹配。与此头部的匹配意味着第三个参数必须是由恰好2个元素组成的列表。如果匹配,Prolog将致电route(A, B, X)
。如果route(A, B, X)
成功,Prolog将显示导致成功的A
,B
和X
的值。如果用户提示提供更多解决方案,Prolog将会回溯,如果先前的呼叫中有剩余选择点,则(a)再次呼叫route(A, B, X)
,或者(b)进一步回溯并尝试将原始呼叫与path
到第二个条款path(A, B, PathAB, Length)
。同样,如果对route(A, B, X)
的原始调用失败,Prolog会回溯以尝试匹配第二个子句。
如果执行第二个子句,则您具有如先前简化示例中所示的连接情况。在这里,它是以route(A, C, X)
开头的四个调用的连接序列。 Prolog将按顺序尝试每个这些调用,并且只要先前成功,就会移动到下一个调用。遇到失败时,Prolog将回溯到先前的调用,如果有选择点,则尝试重新实例化参数以使先前的调用再次成功,等等。
也许您可以看到这与循环有何不同。在典型的命令式语言中,您可能有一个由以下语句组成的循环:
while (something) do
A
B
C
end
在满足循环条件之前,将以A B C A B C A B C ...
执行。在Prolog中,你可能有:
A,
B,
C,
可以执行:A(succeeds) B(fails - backtrack) A(succeeds) B(fails - backtrack) A(succeeds) B(succeeds) C(fails - backtrack) B(succeeds) C(succeeds)
然后最终产生结果。
如果这是真正的好答案,我会附上一堆图表来说明这一点。但我希望描述有足够的帮助。 :)