怎么写prolog规则?

时间:2014-01-11 19:59:07

标签: prolog

我正在尝试创建一个prolog规则,它将使用S个分离度生成社交网络中的所有人。

这是我制定的规则,但它只打印空列表。有人可以帮助我帮助我理解为什么会这样,以及我在哪里出错?:

socialN(_,N):- N<1,!.
socialN(_,N,_,_):- N<1,!.
socialN(P1,Separation,S1,S):-
    (message(P1,P2,_); message(P2,P1,_)),
    D is Separation-1,
    \+(member(P2,S1)),
    append(P2,S1,S2),socialN(P1,D,S2,S),!.
socialN(P2,Separation,S,S).

这些是事实:

message(allan, steve, 2013-09-03).
message(nayna, jane, 2013-09-03).
message(steve, jane, 2013-09-04).
message(steve, allan, 2013-09-04).
message(mark, martin, 2013-09-04).
message(martin, steve, 2013-09-04).
message(allan, martin, 2013-09-05).

E.g。马克的网络仅包括马丁的1度分离;它包括马丁,史蒂夫和艾伦的2度分离;马丁,史蒂夫,艾伦和简3岁。

1 个答案:

答案 0 :(得分:1)

我发现您正在使用appendmember,所以我想您正在尝试建立一个人员列表。你没有使用findall,我有点惊讶。像这样:

allDirectLinks(P1, L) :- findall(P2, directlyLinked(P1, P2), L).

directlyLinked(P1, P1).
directlyLinked(P1, P2) :- message(P1, P2, _).
directlyLinked(P1, P2) :- message(P2, P1, _).

从那里,您可以编写递归函数来查找间接链接:

socialN(0, P, [P]) :- !.
socialN(N, P1, L3) :-
    N>0, !,
    N1 is N-1,
    socialN(N1, P1, L1)
    maplist(allDirectLinks, L1, L2),
    append(L2, L3).

例如,这会在Y中产生一个与Mark分开2步或更少的人员列表:

socialN(2, mark, X), list_to_set(X, Y).

请注意,Mark自己包含在结果列表中(是'0级'链接);我认为事后过滤它不会太难。

我希望这是有道理的;我有点生疏,25年没有做任何Prolog。

编辑:对我定义的规则的解释:

  • 直接链接:如果两个人之间有消息(无论消息的方向如何),则为true。
  • allDirectLinks :累积到列表中 L 直接链接到指定人员的所有人 P1 ;只需阅读有关 findall
  • 的手册
  • socialN :建立一个与给定人( P )相关的人员列表,其距离小于或等于给定距离( N < / em>的)
    • socialN(0,...):距离0,每个人都与自己联系
    • socialN(N,...):进行递归调用以获取距离 N-1 的连接列表,然后使用 maplist allDirectLinks 应用于找到的每个连接,最后使用追加将结果连接在一起。