在递归中使用Prolog列表

时间:2012-11-02 13:39:24

标签: list recursion path prolog

所以我试图使用递归方法来找到两个人之间的路径。这是快速背景: 我定义了一些事实in(X,Y)。那表明谁是相关的,即。 in(person1,project1)in(person2,project1)等等。现在任何两个人都是相关的,如果他们在彼此的同一个项目中,或者他们之间有人的链接路径。例如,p1工作于A p2工作于A和B,p3工作于B,因此存在从p1到p3到p2的路径。这些路径可以是任意长度。

我试图递归地解决这个问题(不要看其他任何方式),但是有一个恼人的问题:

related(A,B) :-
        in(A,X),
        in(B,X),
        not(A=B).

chain(A,B) :-
        related(A,B).
chain(A,B) :-
        related(A,Y),       
        chain(Y,B).

问题是路径可以重复。它可以从p1到p2回到p1无尽的时间。一个人不应该超过1次。

我尝试使用我添加的列表修复此问题。如果一个人已经在列表中,则无法再次添加:

related(A,B,L) :-
        in(A,X),
        in(B,X),not(A=B).

chain(A,B,L) :-
        related(A,B,L).
chain(A,B,L) :-
        related(A,Y,L),
        not(member(Y,L)),
        append(L,[Y],Q),
        chain(Y,B,Q).

它有点奏效,但造成了大量的随机错误,多次重复一些人,有些只重复一次,然后失败。这种方法看起来不错吗?我是否完全使用了错误列表?

谢谢。

3 个答案:

答案 0 :(得分:0)

第一次改进。您是在寻找所有关系链还是想检查是否存在一个关系链?在第一种情况下添加一个剪切。

chain(A,B) :-
        related(A,B), !.
chain(A,B) :-
        related(A,Y),       
        chain(Y,B).

在第二种情况下,Prolog完全按照要求去做,就是找到所有可能的链。

请发布导致问题的查询,以便我们可以一起推理并改进解决方案。

答案 1 :(得分:0)

这是一种替代方法,可能效率较低,但相当一般,基于固定点计算。

connected(Found, Connected) :-
    collect(Found, [], Ext),
    (   Ext == Found
    ->  Connected = Found
    ;   connected(Ext, Connected)
    ).

collect([], Set, Set).
collect([E|Es], Set, Fix) :-
    extend(E, Set, Ext),
    collect(Es, Ext, Fix).

extend(E, Set, Ext) :-
    directly(E, DirectConn),
    ord_union(DirectConn, Set, Ext).

directly(A, DirectConn) :-
    setof(B, P^(in(A, P), in(B, P)), DirectConn).

我们必须使用已排序的列表调用connected(Found,Connected),然后循环直到无法扩展该set。例如,使用此测试数据

in(anna,  project1).
in(bob,   project1).
in(bob,   project2).
in(chris, project2).
in(dan,   project3).

?- connected([bob],L).
L = [anna, bob, chris].

?- connected([dan],L).
L = [dan].

我允许直接/ 2获得身份,即

?- directly(X,Y).
X = anna,
Y = [anna, bob] ;
...
X = dan,
Y = [dan].

答案 2 :(得分:0)

我觉得我从来都不是很清楚,但我最终解决了这个问题。我把代码放在下面。

真正重要的是一个有效的notchain谓词,然后确保我正确地做了追加。我还创建了一个notsame谓词来替换not(A = B)。代码如下。大多数答案是确保在列表附加的内容周围有[]。

附近没有正确附加的正确[]
  

notchain(X,L): -

     

构件(X,L),!,失败。

     

notchain(X,L)。

然后:

  

链(A,B,L): -

     

相关(A,B),        附加(L,[A],Q),        追加(Q,[B],Z),        写(最终),writeln(Z)。

     链(A,B,L): -         notchain(A,L),         附加(L,[A],Q),         相关(A,Y),           链(Y,B,Q)。

这用于相关:

  

notsame(A,B): -
    (A = B),!,失败。

     

notsame(A,B)。