Prolog - 获取朋友的朋友列表

时间:2018-05-09 11:56:43

标签: recursion prolog prolog-findall

我努力获得不错的结果,

我有一些朋友,

friend(a,b).
friend(a,b2).
friend(a,b3).
friend(b,c).
friend(c,d).
friend(d,e).  
friend(e,f).

使用findall(X,friend(a,X),List)我得到a

的所有直接朋友
List=[b,b2,b3].

例如,我想获得a的3级朋友列表,例如,我想要a的直接朋友,a朋友的朋友(这意味着) bb2b3)的朋友和c的朋友。获取清单:

List=[b,b2,b3,c,d].

我正在尝试一切。我只能得到直接的朋友或所有朋友的朋友。

帮助!!

2 个答案:

答案 0 :(得分:3)

对于找到距离给定距离的朋友的谓词,正如您在评论中所要求的那样,您需要三个参数,即两个朋友和距离。让我们给它一个很好的关系名称,比如if float(computer_deck[0].weight) > float(user_deck[0].weight): print("Computer wins.") computer_deck.append(user_deck.pop(0)) else: print("You win.") user_deck.append(computer_deck.pop(0)) 。现在让我们尝试描述这种关系:

friend_of_maxdist/3

这个谓词一个接一个地传递给定距离的所有朋友:

friend_of_maxdist(F1,F2,D) :-
   D > 0,                        % if the distance is greater than 0
   friend(F1,F2).                % F2 is a friend in range
friend_of_maxdist(F1,F2,D) :-
   D > 1,                        % if the distance is greater than 1
   D0 is D-1,                    
   friend(F1,X),                 % X is an intermediary friend
   friend_of_maxdist(X,F2,D0).   % of distance minus 1

现在您可以在列表中收集所有解决方案。我将使用bagof/3显示示例查询,请参阅下文,了解原因:

?- friend_of_maxdist(a,F2,1).
F2 = b ;
F2 = b2 ;
F2 = b3 ;
false.

?- friend_of_maxdist(a,F2,2).
F2 = b ;
F2 = b2 ;
F2 = b3 ;
F2 = c ;
false.

?- friend_of_maxdist(a,F2,3).
F2 = b ;
F2 = b2 ;
F2 = b3 ;
F2 = c ;
F2 = d ;
false.

但是,由于使用?- bagof(F2,friend_of_maxdist(a,F2,1),L). L = [b, b2, b3]. ?- bagof(F2,friend_of_maxdist(a,F2,2),L). L = [b, b2, b3, c]. ?- bagof(F2,friend_of_maxdist(a,F2,3),L). L = [b, b2, b3, c, d]. >/2is/2如果第三个参数不是基数,则会产生错误,例如对于查询:

friend_of_maxdist/3

如果您不打算以这种方式使用谓词,那么您已经完成了。否则你可能想看看CLP(FD)。对上面的代码进行以下更改:

?- friend_of_maxdist(a,F2,N).
ERROR: >/2: Arguments are not sufficiently instantiated

如果您现在尝试有问题​​的查询,则会得到答案而不是错误。但是,您会在答案中获得剩余目标(有关详细信息,请参阅documentation):

:- use_module(library(clpfd)).   % <- new

friend_of_maxdist(F1,F2,D) :-
   D #> 0,                       % <- change
   friend(F1,F2).
friend_of_maxdist(F1,F2,D) :-
   D #> 1,                       % <- change
   D0 #= D-1,                    % <- change
   friend(F1,X),
   friend_of_maxdist(X,F2,D0).

要获取实际数字而不是?- friend_of_maxdist(a,F2,N). F2 = b, N in 1..sup ; F2 = b2, N in 1..sup ; F2 = b3, N in 1..sup ; F2 = c, N in 2..sup, _G778+1#=N, _G778 in 1..sup ; F2 = d, N in 3..sup, _G1264+1#=N, _G1264 in 2..sup, _G1288+1#=_G1264, _G1288 in 1..sup ; F2 = e, N in 4..sup, _G1855+1#=N, _G1855 in 3..sup, _G1879+1#=_G1855, _G1879 in 2..sup, _G1903+1#=_G1879, _G1903 in 1..sup ; F2 = f, N in 4..sup, _G2446+1#=N, _G2446 in 4..sup, _G2470+1#=_G2446, _G2470 in 3..sup, _G2494+1#=_G2470, _G2494 in 2..sup, _G2518+1#=_G2494, _G2518 in 1..sup ; false. 的范围,请限制其范围并标记它:

N

现在您可以收集上述解决方案:

?- N in 0..3, friend_of_maxdist(a,F2,N), label([N]).
N = 1,
F2 = b ;
N = 2,
F2 = b ;
N = 3,
F2 = b ;
N = 1,
F2 = b2 ;
N = 2,
F2 = b2 ;
N = 3,
F2 = b2 ;
N = 1,
F2 = b3 ;
N = 2,
F2 = b3 ;
N = 3,
F2 = b3 ;
N = 2,
F2 = c ;
N = 3,
F2 = c ;
N = 3,
F2 = d ;
false.

在上面的查询中,您可以看到我建议?- bagof(F2,(N in 0..3, friend_of_maxdist(a,F2,N), label([N])),L). N = 1, L = [b, b2, b3] ; N = 2, L = [b, b2, b3, c] ; N = 3, L = [b, b2, b3, c, d]. 收集解决方案的原因:bagof/3绑定到一个值,然后您获得与该值相关的所有解决方案。如果您使用N尝试相同的操作,则可以在一个列表中获得三个列表中的所有元素:

findall/3

要使用?- findall(F2,(N in 0..3, friend_of_maxdist(a,F2,N), label([N])),L). L = [b, b, b, b2, b2, b2, b3, b3, b3|...]. 获得相同的解决方案,您必须明确告诉bagof/3不要在目标中绑定bagof/3

N

请注意,谓词的CLP(FD) - 版本现在类似于真实关系,正如其关系名称所示。

答案 1 :(得分:0)

以下代表三级友谊。正如评论中所说,如果你想要更多,你可能想要寻找递归。

% my friend is my friend
friend_of_friend(X,Y):-
    friend(X,Y).
% the friend of my friend is my friend
friend_of_friend(X,Y):-
    friend(X,Z),
    friend(Z,Y).
% the friend of the friend of my friend is my friend
friend_of_friend(X,Y):-
    friend(X,A),
    friend(A,B),
    friend(B,Y).

然后

findall(X, friend_of_friend(a,X), List).

给出:

List = [b, b2, b3, c, d]

这代表无限的递归友谊:

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

并给予:

List = [b, b2, b3, c, d, e, f]