簡體   English   中英

應用遞歸時超出本地堆棧

[英]Out of local stack when applying recursion

上下文,第一。 我試圖用 prolog 建模的是兩個單獨的圖它們都代表一組朋友,所以在它們兩個中我都可以放置friend(X,Y)關系,並且,因為它沒有意義,友誼不是'在這個模型中是相互的,我也把關系放在了friend(Y, X)

所以這意味着兩個圖在它們的元素之間都有雙向關系

例如:

friend(foo1, foo2).
friend(foo2, foo1).

friend(foo3, foo4).
friend(foo4, foo3).

其中foo1foo2相關, foo3foo4 ,但前兩個與另外兩個無關。

因為是一群朋友,所以也沒有感覺,在同一群朋友中,同一群的兩個人不是朋友,所以我使用遞歸來確定一個人是否是另一個人的朋友

definitivefriend(X, Z) :- friend(X, Z). 
definitivefriend(X, Z) :- friend(X, Y), definitivefriend(Y, Z). 

我遇到的問題是,當我嘗試檢查一組中的一個人是否是另一組中的一個人的朋友時。 換句話說,檢查圖的一個元素是否與另一個圖的另一個元素相關

編譯器(在本例中為 SWI-Prolog)並沒有得到 false ,這是預期的結果,而是給了我一個out of local stack錯誤

我想知道如何解決這個問題。

編輯

所以多虧了 CapelliC,我有了解決這個問題的方法。 因為主要目標已經完成,但還有一個次要問題,我將從現在開始描述它。

圖1圖2

這是我正在使用的兩個圖表。 記住我之前說過,兩個圖都是雙向的。

這是我在序言中的程序:

writeit :- write('Frienship').
definitivefriend(X, Z) :- friend(X, Z), friend(Z, X).   
definitivefriend(X, Y) :- friend(X, Z), X @< Z, definitivefriend(Z, Y), Y \= X.
friend(amanda, ryan).       % graph1 %
friend(ryan, amanda).
friend(ryan, lisa).
friend(lisa, ryan).
friend(bryan, ryan).
friend(ryan, bryan).
friend(sara, ryan).
friend(ryan, sara).
friend(sara, simone).
friend(simone, sara).       % graph2 %
friend(sandra, jeff).
friend(jeff, sandra).
friend(betty, jeff).
friend(jeff, betty).
friend(jeff, antonia).
friend(antonia, jeff).
friend(jeff, oskar).
friend(oskar, jeff). 
friend(jeff, leslie).
friend(leslie, jeff). 

這是我得到的一些輸出

?- definitivefriend(amanda, ryan).
true .                         % It's correct, both nodes are neighbours %

?- definitivefriend(amanda, simone).
true .                         % It's correct, both nodes are in the same graph %

?- definitivefriend(ryan, simone).
true .                         % It's correct, same explanation as before %

?- definitivefriend(simone, amanda).
false.                         % It's wrong, expected result is true %

?- definitivefriend(ryan, jeff).
false.                         % It's correct, nodes are in different graphs %

?- definitivefriend(amanda, leslie).
false.                         % It's correct, same explanation as before %

?- definitivefriend(sandra, oskar).
false.                         % It's wrong, expected result is true %

?- definitivefriend(oskar, sandra).
false.                         % It's wrong, expected result is true %

?- definitivefriend(betty, oskar).
true .                         % It's correct, both nodes are in the same graph %

?- definitivefriend(oskar, betty).
false.                         % It's wrong, expected result is true %

正如我在評論中所說的那樣,即使有相同圖形的某些元素(除了相鄰的元素), definitivefriend也會給我錯誤。 並且在某些情況下,當我執行 expiredfriend definitivefriend(X, Y)我會得到正確的結果,但是當我 execite definitivefriend(Y, X)我會得到錯誤的結果。

我覺得你沒有以正確的方式建模,無論如何這似乎有效(濫用 Jean-Bernard 的建議,+1)

definitivefriend(X, Y) :-
    friend(X, Y),
    friend(Y, X).

definitivefriend(X, Y) :-
    friend(X, Z), X @< Z,
    definitivefriend(Z, Y), Y \= X.

編輯:這不適用於您的模型。 除了遵循丹尼爾的建議(+1)之外,我看不到任何其他方式。

對於您的第二個definitivefriend規則,添加 X < Y 的條件。這將避免循環。 然后簡單地添加一個規則:

definitivefriend(X,Y) :- definitivefriend(Y,X)

就像現在一樣,你可以:

definitivefriend(1,2) :- friend(1,3), definitivefriend(3,2)
definitivefriend(3,2) :- friend(2,1), definitivefriend(1,2)

這導致無限遞歸

問題基本上是周期。 您的圖表是非循環的,但您的代碼不是。 這是問題。 假設我給出查詢:- definitivefriend(foo1, foo2). . 是什么阻止 Prolog 像這樣擴展:

definitivefriend(foo1, foo2) 
:- friend(foo1, foo2), definitivefriend(foo2, foo2).                     % by clause 2
:- friend(foo1, foo2), friend(foo2, foo1), definitivefriend(foo1, foo2). % by clause 2

:- friend(foo1, foo2), friend(foo2, foo1), friend(foo1, foo2), 
   definitivefriend(foo2, foo2).                                         % by clause 2

等等。

@Jean-Bernard Pellerin 通過強制完全排序提供了一種防止循環的有用方法。 我不認為這是正確的方法,但我不能完全說明原因。 但是,您可以做的一件事是提供一個訪問過的列表來檢查而不是重新輸入您已經訪問過的節點。 該代碼將如下所示:

definitivefriend(X, Z) :- definitivefriend(X, Z, [X]).

definitivefriend(X, Y, Visited) :- 
    friend(X, Y), \+ memberchk(Y, Visited).
definitivefriend(X, Z, Visited) :- 
    friend(X, Y), \+ memberchk(Y, Visited), 
    definitivefriend(Y, Z, [Y|Visited]).

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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