[英]Out of local stack error in Prolog route planner
我正在嘗試編寫城鎮之間的Prolog路線規划器。 這是我的代碼:
road(meath,dublin,5).
road(dublin,kildare,9).
road(kildare,wicklow,7).
road(wicklow,wexford,10).
/*Rules:*/
route(X,Y,[H|_ ],N) :-
road(H,Y,_),
routen(X,Y,N1),
N is N1.
route(X,Y,[H|T],N) :-
road(X,H,_ ),
routen(X,Y,N1),
N is N1,
route(H,Y,T,_),
!.
route(X,Y,[],N) :-
road(X,Y,N1),
N is N1.
routen(X,Y,N) :-
road(X,Y,N).
routen(X,Y,N) :-
road(X,Z,N1),
road(Z,Y,N2),
N is N1+N2.
routen(X,Y,N) :-
routen(X,Z,N1),
routen(Z,Y,N2),
N is N1+N2,
!.
謂語road
具有兩個城鎮及其之間的距離。 該規則route
發現與城鎮的名單X
和Y
和routen
發現兩個鎮之間的總距離。
當我運行route
,它有時可以工作,而有時我會收到ERROR: Out of local stack
。
例:
?- route(meath,wexford,[dublin,kildare,wicklow],31).
true.
?- route(meath,wexford,[dublin,kildare,wicklow],30).
false.
?- route(meath,kerry,[dublin,kildare,wicklow],31).
ERROR: Out of local stack
最后一個應該返回false
,因為在meath
和kerry
之間的路由不存在。 有人知道我為什么會出錯嗎?
Prolog中的規則為左遞歸。 在上一條規則中,您執行了以下操作:
routen(X,Y,N) :- routen(X,Z,N1),routen(Z,Y,N2),N is N1+N2,!.
它使您的程序無限次嘗試規則routen(X,Z,N1) 。 這意味着堆棧將一度充滿。
這里發生了什么:
找到一條從米斯到凱里的路線。
它在城市之間不存在直接道路:嘗試尋找另一個中間城市。 它找到了都士都柏林。
然后,嘗試都柏林凱利。 但是,同樣,它在城市之間不存在直接道路:嘗試尋找另一個中間城市。 它找到都柏林基爾代爾。 等等。
最后到達米克洛-韋克斯福德。 因此,到目前為止找到的路線是:Meath-dublin-kildare-wicklow-wexford。
現在,它首先嘗試為韋克斯福德-凱里
route(X,Y,[H|_ ],N) :- road(H,Y,_),routen(X,Y,N1), N is N1.
它滿足第一個
road(H,Y,_)
然后減少
routen(X,Y,N1), N is N1.
5.1嘗試第一個規則
routen(wexford,kerry,N) :- road(wexford,kerry,N).
失敗了,因為它們之間不存在直接的道路。 因此它調用:
routen(wexford,kerry,N) :- road(wexford,Z,N1),road(Z,kerry,N2),N is N1+N2.
失敗導致無法滿足
road(wexford,Z,N1).
最后,它嘗試使用最后一條規則
routen(wexford,kerry,N) :- routen(wexford,Z,N1),routen(Z,kerry,N2),N is N1+N2,!.
所以它減少了
routen(wexford,Z,N1),routen(Z,kerry,N2),N is N1+N2,!.
它試圖滿足第一個
routen(wexford,Z,N1).
與
routen(X,Y,N) :- road(X,Y,N). routen(X,Y,N) :- road(X,Z,N1),road(Z,Y,N2),N is N1+N2. routen(X,Y,N) :- routen(X,Z,N1),routen(Z,Y,N2),N is N1+N2,!.
分別與
X=wexford Z=DG51_ % or something like that. That is, an not instantiated variable
並重復步驟5.1
如您所見,它將永遠找不到城市“克里”,並且陷入無限循環。
這里是新代碼:
road(meath,dublin,5).
road(dublin,kildare,9).
road(kildare,wicklow,7).
road(wicklow,wexford,10).
/*Rules:*/
route(X,Y,[H|_ ],N) :- routen(X,Y,N),!.
%route(X,Y,[H|T],N) :- road(X,H,_ ),routen(X,Y,N1), N is N1, route(H,Y,T,_).
route(X,Y,[],N) :- road(X,Y,N1), N is N1.
routen(X,Y,N) :- road(X,Y,N).
%routen(X,Y,N) :- road(X,Z,N1),road(Z,Y,N2),N is N1+N2.
routen(X,Y,N) :- road(X,Z,N1),routen(Z,Y,N2),N is N1+N2.
請注意,我在最后一條規則中
road(X,Z,N1)
之前
routen(Z,Y,N2)
因此,如果該正文的第一個子句失敗,您將永遠不會陷入與第二個子句的循環中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.