簡體   English   中英

Prolog路由計划器中的本地堆棧錯誤

[英]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發現與城鎮的名單XYrouten發現兩個鎮之間的總距離。

當我運行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 ,因為在meathkerry之間的路由不存在。 有人知道我為什么會出錯嗎?

Prolog中的規則為左遞歸。 在上一條規則中,您執行了以下操作:

routen(X,Y,N) :- routen(X,Z,N1),routen(Z,Y,N2),N is N1+N2,!.

它使您的程序無限次嘗試規則routen(X,Z,N1) 這意味着堆棧將一度充滿。

這里發生了什么:

  1. 找到一條從米斯到凱里的路線。

  2. 它在城市之間不存在直接道路:嘗試尋找另一個中間城市。 它找到了都士都柏林。

  3. 然后,嘗試都柏林凱利。 但是,同樣,它在城市之間不存在直接道路:嘗試尋找另一個中間城市。 它找到都柏林基爾代爾。 等等。

  4. 最后到達米克洛-韋克斯福德。 因此,到目前為止找到的路線是:Meath-dublin-kildare-wicklow-wexford。

  5. 現在,它首先嘗試為韋克斯福德-凱里

     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,!. 
  6. 它試圖滿足第一個

     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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM