1
我正在使用swipl 5.10.2。今天我開始學習我的AI課程的Prolog。 我已經開始與一個非常簡單的例子:這是Prolog中的左遞歸嗎?
father(giovanni,maria).
brother(paolo,pietro).
grandpa(X,Y) :-
father(X,Z),
father(Z,Y).
grandpa(X,Y) :-
father(X,Z),
mother(Z,Y).
mother(maria,paolo).
mother(I,J) :-
mother(I,K),
brother(K,J).
不是什麼大不了的,如果我嘗試這個目標grandpa(giovanni,pietro)
,它的工作,這讓我真正。然後我想辣迎接挑戰,我修改這樣的代碼:
father(giovanni,maria).
brother(paolo,pietro).
grandpa(X,Y,Z) :-
father(X,Z),
father(Z,Y).
grandpa(X,Y,Z) :-
father(X,Z),
mother(Z,Y).
mother(maria,paolo).
mother(I,J) :-
mother(I,K),
brother(K,J).
,因爲我想知道中間人但是當我運行它這裏發生了什麼:
?- grandpa(giovanni,pietro,M).
M = maria ;
ERROR: Out of local stack
這是因爲,imho,母親有一個左遞歸,樹不斷髮展而沒有發現關閉。
然後我寫了這個:
father(giovanni,maria).
brother(paolo,pietro).
mother(maria,paolo).
grandpa(X,Y,Z) :-
father(X,Z),
father(Z,Y).
grandpa(X,Y,Z) :-
father(X,Z),
mother(Z,Y).
mother(I,J) :-
brother(K,J),
mother(I,K).
這是輸出:
?- grandpa(giovanni,pietro,M).
M = maria ;
false.
這是正確的。那麼這只是一個左遞歸問題,還是我錯過了一些關於swipl行爲的東西?當我有一個「錯誤:超出本地堆棧」,它總是一個遞歸問題?
+1我想補充一點,最大遞歸深度根據處理的項的數量和大小而變化很大(如果涉及到列表,很容易按100倍),而* tail遞歸*是解決方案可以很大程度上避免過度使用堆棧。如果編譯器支持* tail遞歸*,則編譯器支持 – 2011-02-25 21:49:12
。就像你可以用Java那樣做,但JVM不支持它,對吧? – dierre 2011-02-27 13:53:05
雖然這段代碼沒有這個問題;它是一個無限遞歸,與是否使用尾調用無關(在這種情況下,對'mother'的規則中的目標進行重新排序可以解決問題)。 – 2011-02-27 21:58:40