Prolog 为什么这会导致无限递归?

Prolog 为什么这会导致无限递归?,prolog,failure-slice,non-termination,Prolog,Failure Slice,Non Termination,我在prolog中有一个程序,我基本上定义了一个人的图表,我需要做一些谓词,告诉我哪些人是有联系的,哪些是集团。事实如下: graph([person(susan, [reed, jen, andrzej, jessica]), person(reed, [tony, jessica]), person(jessica, [jen,susan]), person(tony, []), person(ken, [andrzej]), person(jen, [tony

我在prolog中有一个程序,我基本上定义了一个人的图表,我需要做一些谓词,告诉我哪些人是有联系的,哪些是集团。事实如下:

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和一个人员列表作为参数,并尝试检查列表中的人员是否确实是朋友团(这意味着谓词goodfriends对于列表中的每对人员都是true)

派克所做的是:如果名单上只有两个人,那么就检查这两个人是否是好朋友。如果这是真的,那么他们之间就有一个派系。如果名单中有两个以上的人,那么对于名单中的每个人,即每个人,检查他是否与名单尾部的其他人是好朋友,并递归地对所有人进行检查。 下面定义了其余的帮助器谓词,以便该组工作

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).
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([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). goodFriendWith(,,[]):-false。 goodFriendWith(G,FriendOne,[FriendTwo | FriendList]):- FriendOne=susan, FriendTwo=杰西卡, 好朋友(G,FriendOne,FriendTwo), goodFriendWith(G,FriendOne,FriendList),false。 -好朋友([个人(苏珊,[杰西卡]),个人(杰西卡,[苏珊]),苏珊,L)。
同样,查询循环!您现在真的应该看到问题了。

请添加您对
至少两个元素的定义。如果你能简单地说明
member
,为什么要说
member
?你在回答中添加的集团没有递归调用。列表中的所有人不应该都有递归吗?你在答案中添加的小团体没有递归调用。还有,你认为好朋友有什么问题?我不明白怎么会有无限的解。我的意思是它在有限的列表中“迭代”。@sokras:它产生无限多的解!如果你期望它终止,那就大错特错了。这怎么能产生无穷多个解呢。我不明白:/goodfriends的代码简单明了。遍历列表,如果列表为空则结束,如果不为空,则检查列表的下一个元素,因此我仍然不明白为什么会进行无限次迭代。:/我知道它确实以我的方式进行无限迭代,我可以看到我一次又一次地得到相同的结果,但我不明白为什么它会这样继续下去。我是说不应该,是吗?
?- 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] 
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).