簡體   English   中英

為什么這會導致無限遞歸?

[英]Why is this causing an infinite recursion?

我在序言中有這個程序,在這里我基本上定義了一個人形圖,我需要做一些謂詞,以告訴我哪些人是聯系的,哪些是集團。 這是事實:

graph([person(susan, [reed, jen, andrzej, jessica]),
   person(reed, [tony, jessica]),
   person(jessica, [jen,susan]),
   person(tony, []),
   person(ken, [andrzej]),
   person(jen, [tony, susan, jessica]),
   person(andrzej, [susan, ken])]).

這是我的謂詞clique的定義。 它以圖形G和一個人的列表為參數,並嘗試檢查列表中的人是否確實是一群朋友(這意味着謂詞好朋友對列表中的每一對人都是正確的)

clique(G, [FriendOne, FriendTwo]):-
  goodfriends(G, FriendOne, FriendTwo).
clique(G, [FriendOne | FriendList]):-
  atLeastTwoElements(FriendList),
  clique(G, FriendList),
  goodFriendWith(G, FriendOne, FriendList).

團體的意思是:如果列表僅包含兩個人,則只需檢查這兩個人是否是好朋友。 如果這是真的,那么他們兩個之間就有集團。 如果在人員列表中有兩個以上的人員,則對於該列表的每個頭,即人員,請檢查他是否是好朋友,其余人員在列表的末尾,然后對所有人員列表進行遞歸操作人。 下面定義了使幫派工作的其他輔助謂詞。

goodfriends(G, FriendOne, FriendTwo):-
  getPerson(G, FriendOne, PersonOne),
  getPerson(G, FriendTwo, PersonTwo),
  hasFriend(PersonOne, FriendTwo),
  hasFriend(PersonTwo, FriendOne).

%% checks if this friend is goodfriend with all these friends
goodFriendWith(_, _, []).
goodFriendWith(G, FriendOne, [FriendTwo | FriendList]):-
  goodFriendWith(G, FriendOne, FriendList),
  goodfriends(G, FriendOne, FriendTwo).

%% gets specific person by a name from the graph
getPerson([person(Name, Friends)|_], Name, person(Name, Friends)).
getPerson([_|T], Name, Result):-
  getPerson(T, Name, Result).

%% checks if a person has a certain friend
hasFriend(person(_, Friends), Friend):-
  member_(Friend, Friends).

member_(X, [X|_]).
member_(X, [_|Tail]) :- member_(X, Tail).
atLeastOneElement([_|_]).
atLeastTwoElements([_,_|_]).

當我創建名為runner的謂詞來測試謂詞“ clique”時:

runner(R):-
  graph(G),  
  clique(G, R).

我希望它返回圖中的所有集團,但我的結果是:

?- runner(R).
R = [susan, jessica] ;
R = [susan, jen] ;
R = [susan, andrzej] ;
R = [jessica, susan] ;
R = [jessica, jen] ;
R = [ken, andrzej] ;
R = [jen, susan] ;
R = [jen, jessica] ;
R = [andrzej, susan] ;
R = [andrzej, ken] ;
R = [jen, susan, jessica] ;
R = [jessica, susan, jen] ;
R = [jen, jessica, susan] ;
R = [susan, jessica, jen] ;
R = [jessica, jen, susan] ;
R = [susan, jen, jessica] ;
ERROR: Out of local stack

遞歸有什么問題? 我知道我得到了正確的結果,但是由於某種原因,所有結果都顯示出它不斷遞歸。

先感謝您。

在像您一樣的純單調程序中,有一種簡單的調試技術。 只需在程序中添加false目標即可。 如果生成的程序仍然循環,則必須修復其余可見部分。 (可能會有更多錯誤,但是只要該部分未解決,您就不會解決問題)

這是到目前為止我得到的:

runner(R):-
  graph(G),
  clique(G, R), false.

clique(G, [FriendOne, FriendTwo]):- false,
  goodfriends(G, FriendOne, FriendTwo).
clique(G, [FriendOne | FriendList]):-
  atLeastTwoElements(FriendList),
  goodFriendWith(G, FriendOne, FriendList), false,
  clique(G, FriendList).

因此,一個或一個問題在於goodFriendWith 我發現讓您的定義成功遍歷無限多個列表有點令人惱火:

?- length(L,N),
   maplist(=(jessica),L),
   goodFriendWith(
      [  person(susan,[reed,jen,andrzej,jessica]),
         person(reed,[tony,jessica]),
         person(jessica,[jen,susan]),
         person(tony,[]),
         person(ken,[andrzej]),
         person(jen,[tony,susan,jessica]),
         person(andrzej,[susan,ken])],
      susan,
      L).
L = [],
N = 0 ;
L = [jessica],
N = 1 ;
L = [jessica, jessica],
N = 2 ;
L = [jessica, jessica, jessica],
N = 3 ;
L = [jessica, jessica, jessica, jessica],
N = 4 ;
L = [jessica, jessica, jessica, jessica, jessica],
N = 5 ...

因此對於僅兩個人來說,已經存在無數種不同的解決方案。 那不能終止! 您需要解決此問題。

或者,更准確地說:

?- goodFriendWith([person(susan,[jessica]),person(jessica,[susan])],susan,L).
L = [] ;
L = [jessica] ;
L = [jessica, jessica] ;
L = [jessica, jessica, jessica] ;
L = [jessica, jessica, jessica, jessica] ;
L = [jessica, jessica, jessica, jessica, jessica] 

這個目標必須產生有限的許多解決方案。 但是,有無限多個。

由於您對結果感到驚訝,因此讓我們繼續進行調試。 為了使其更加明顯,我現在將添加額外的目標(=)/2 這些目標也將使該計划專業化:

goodFriendWith(_, _, []) :- false.
goodFriendWith(G, FriendOne, [FriendTwo | FriendList]):-
  FriendOne = susan,
  FriendTwo = jessica,
  goodfriends(G, FriendOne, FriendTwo),
  goodFriendWith(G, FriendOne, FriendList), false.

?- goodFriendWith([person(susan,[jessica]),person(jessica,[susan])],susan,L).

再次,查詢循環! 您現在真的應該看到問題了。

暫無
暫無

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

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