Prolog递归做无限循环

时间:2013-04-29 22:35:28

标签: recursion prolog infinite

这是代码

flight(roc,syr,25).
flight(roc,jfk,55).
flight(jfk,bos,65).
flight(bos,syr,40). 
flight(jfk,syr,50). 
flight(bos,roc,50).

layover(roc,25). 
layover(jfk,55).
layover(syr,30).  
layover(bos,40).

route(X,Y,R,D) :-
   flight(X,Y,L),
   D is L,
   R = [X,Y].
route(X,Y,R,D) :-
   flight(X,Z,L),
   route(Z,Y,P,M), 
   R = [X|P],
   layover(Z,T),
   D is M+L+T,
   \+ member(X,P).

这是发生了什么。第二个条款

route(X,Y,R,D) :-
   flight(X,Z,L),
   route(Z,Y,P,M), 
   R = [X|P], 
   layover(Z,T),
   D is M+L+T,
   \+ member(X,P).

进入无限循环。它显示我想要的答案,然后不断找到更多的答案(因为你可以基本上保持循环停止)并进行无限循环直到它停止。该程序应该找到每个可能不会在停靠点周围循环的航线。我知道为什么会这样,但不知道如何更改我的代码来修复它。请帮忙。

这是一个解决方案

?- route(roc, syr, Routing, Duration).
Routing = [roc, syr],
Duration = 25 ;
Routing = [roc, jfk, syr],
Duration = 160 ;
Routing = [roc, jfk, bos, syr],
Duration = 255 ;
false.

2 个答案:

答案 0 :(得分:0)

我的回答有一点需要注意 - 我对你的变量做了一些假设。我假设X是起点,Y是目的地,R是从X到Y(包括)的路径的位置列表,D是行进的距离?或者也许等待时间。无所谓。

看起来你的基本情况有问题。您的基本情况是检查是否存在满足路径的flight(X,Y,L)。你需要检查的是从X到Y(R,如果我没有记错)的位置列表是否已经从X到Y覆盖。也就是说,如果列表R = Y的最后一个元素和R的第一个元素= X,那你完成了。

您可以使用的最后一项功能是:

last([X],X).
last([H|T],R):- last(T,R).

然后你可以有一个基本案例:

route(X,Y,R,D):- last(R,L), L == Y, [H|T] = R, H == X.

或类似的东西,无论如何。自从我使用prolog以来已经有一段时间......

如果有帮助,请告诉我。

答案 1 :(得分:0)

我认为您的问题应该在递归调用之前移动\+member(X,P) 来解决。这是因为Prolog通过深度优先搜索子句来实现逻辑,即自上而下和从左到右选择和匹配。

当然,移动测试需要更改P计算。现在是在访问后建成的。一个简单的方法是使用累加器,在第一次调用时初始化为[],并在目标上统一到完整路径。即。

route(X,Y,Acc, [X,Y|Acc], D) :- flight(X,Y,L), D is L.
...

?- route(roc, syr, [], Routing, Duration).