陷入无限循环的Prolog

陷入无限循环的Prolog,prolog,Prolog,我有两个问题困扰了我好几个小时connected/2用来判断两个人是否有关联距离/3应该用来衡量亲属关系。但是: 对于连接(x,y)的查询,我不断得到trues 对于距离(x,y,N)查询,我得到了无限增加的N。有什么建议吗 以下是我的事实: male(ted). male(barney). male(ranjit). male(marshall). male(tony). male(swarley). male(steve). male(chuck). male(john). male(dev

我有两个问题困扰了我好几个小时
connected/2
用来判断两个人是否有关联<代码>距离/3应该用来衡量亲属关系。但是:

  • 对于连接(x,y)的查询,我不断得到
    true
    s
  • 对于
    距离(x,y,N)
    查询,我得到了无限增加的
    N
    。有什么建议吗
  • 以下是我的事实:

    male(ted).
    male(barney).
    male(ranjit).
    male(marshall).
    male(tony).
    male(swarley).
    male(steve).
    male(chuck).
    male(john).
    male(devon).
    male(morgan).
    
    female(robin).
    female(lily).
    female(wendy).
    female(stellar).
    female(abby).
    female(victoria).
    female(carina).
    female(sarah).
    female(ellie).
    
    married(ted,      robin).
    married(marshall, lily).
    married(ranjit,   wendy).
    married(stellar,  tony).
    married(steve,    carina).
    married(sarah,    chuck).
    married(ellie,    devon).
    
    father(ted,      barney).
    father(ted,      ranjit).
    father(marshall, wendy).
    father(ranjit,   stellar).
    father(tony,     abby).
    father(tony,     swarley).
    father(tony,     victoria).
    father(steve,    chuck).
    father(steve,    ellie).
    father(chuck,    john).
    father(devon,    morgan).
    
    mother(robin,    barney).
    mother(robin,    ranjit).
    mother(lily,     wendy).
    mother(wendy,    stellar).
    mother(stellar,  abby).
    mother(stellar,  swarley).
    mother(stellar,  victoria).
    mother(carina,   chuck).
    mother(carina,   ellie).
    mother(sarah,    john).
    mother(ellie,    morgan).
    
    现在,我的谓词:

    parent(X,Y) :- father(X,Y).
    parent(X,Y) :- mother(X,Y).
    
    son(X,Y) :-
        male(X),
        parent(Y,X).
    
    daughter(X,Y) :-
        female(X),
        parent(Y,X).
    
    sibling(X,Y) :-
        parent(Z,X),
        parent(Z,Y).
    
    cousin(X,Y) :-
        parent(Z,X),
        parent(W,Y),
        parent(G,Z),
        parent(G,W).
    
    ancestor(X,Y) :-
        parent(X,Z),
        ancestor(Z,Y).
    ancestor(X,Y) :- parent(X,Y).
    
    notmember(X,[]).
    notmember(X,[H|T]) :- 
        X \= H,
        notmember(X,T).
    
    connected(X,Y,_) :- X == Y.
    connected(X,Y,Visited) :- 
        ancestor(X,Z),
        notmember(Z,Visited),
        connected(Z,Y,[Z|Visited]).
    connected(X,Y,Visited) :- 
        ancestor(Z,X),
        notmember(Z,Visited),
        connected(Z,Y,[Z|Visited]).
    connected(X,Y,Visited) :- 
        sibling(X,Z),
        notmember(Z,Visited),
        connected(Z,Y,[Z|Visited]).
    connected(X,Y,Visited) :- 
        married(X,Z),
        notmember(Z,Visited),
        connected(Z,Y,[Z|Visited]).
    connected(X,Y) :- connected(X,Y,[X]).
    
    minimum(X,[X]).
    minimum(X,[M,H|T]) :- 
        M =< H,
        minimum(X,[M|T]).
    minimum(X,[M,H|T]) :-
        M > H,
        minimum(X,[H|T]).
    
    distance(X,X,_,0).
    distance(X,Y,Visited,N) :- 
        parent(X,Z),
        notmember(Z,Visited),
        distance(Z,Y,[Z|Visited],N1),
        N is N1+1.
    distance(X,Y,Visited,N) :- 
        parent(Z,X),
        notmember(Z,Visited),
        distance(Z,Y,[Z|Visited],N1),
        N is N1+1.
    distance(X,Y,N) :- distance(X,Y,[],N).
    
    父(X,Y):-父(X,Y)。 父母(X,Y):-母亲(X,Y)。 儿子(X,Y):- 男(X),, 父(Y,X)。 女儿(X,Y):- 女(X),, 父(Y,X)。 兄弟姐妹(X,Y):- 父(Z,X), 父(Z,Y)。 表亲(X,Y):- 父(Z,X), 父母(W,Y), 父(G,Z), 父代(G,W)。 祖先(X,Y):- 父(X,Z), 祖先(Z,Y)。 祖先(X,Y):-父(X,Y)。 notmember(X,[])。 非成员(X[H|T]):- X\=H, notmember(X,T)。 连接的(X,Y,u):-X==Y。 已连接(X、Y、已访问):- 祖先(X,Z), 非成员(Z,已访问), 连接(Z,Y,[Z |访问])。 已连接(X、Y、已访问):- 祖先(Z,X), 非成员(Z,已访问), 连接(Z,Y,[Z |访问])。 已连接(X、Y、已访问):- 兄弟姐妹(X,Z), 非成员(Z,已访问), 连接(Z,Y,[Z |访问])。 已连接(X、Y、已访问):- 已婚(X,Z), 非成员(Z,已访问), 连接(Z,Y,[Z |访问])。 连通的(X,Y):-连通的(X,Y,[X])。 最小值(X,[X])。 最小值(X[M,H | T]):- M=H, 最小值(X[H | T])。 距离(X,X,0)。 距离(X,Y,N):- 父(X,Z), 非成员(Z,已访问), 距离(Z,Y,[Z |到访],N1), N是N1+1。 距离(X,Y,N):- 父(Z,X), 非成员(Z,已访问), 距离(Z,Y,[Z |到访],N1), N是N1+1。 距离(X,Y,N):-距离(X,Y,[],N)。 编辑: 谢谢,我想我已经解决了一半的问题了。 根据@twinterer的建议,我已经修复了如下谓词

    connected(X,Y,_) :- X == Y.
    connected(X,Y,V) :-
        married(X,Z),
        notmember(Z,V),
        connected(Z,Y,[Z|V]),!.
    connected(X,Y,V) :-
        sibling(X,Z),
        notmember(Z,V),
        connected(Z,Y,[Z|V]),!.
    connected(X,Y,V) :-
        parent(X,Z),
        notmember(Z,V),
        connected(Z,Y,[Z|V]),!.
    connected(X,Y,V) :-
        parent(Z,X),
        notmember(Z,V),
        connected(Z,Y,[Z|V]),!.
    connected(X,Y) :- connected(X,Y,[X]).
    
    minimum(X,[X]).
    minimum(X,[M,H|T]) :- 
        M =< H,
        minimum(X,[M|T]).
    minimum(X,[M,H|T]) :-
        M > H,
        minimum(X,[H|T]).
    
    count(X,[],0).
    count(X,[X|T],N) :-
        count(X,T,N1),
        N is N1+1.
    count(X,[H|T],N) :-
        X \== H,
        count(X,T,N1),
        N is N1.
    
    distance(X,X,Visited,0) :-
        count(X,Visited,N),
        N =< 1, !.
    distance(X,Y,Visited,N) :- 
        parent(X,Z),
        (notmember(Z,Visited)->
            distance(Z,Y,[Z|Visited],N1),
            N is N1+1
        ;
            fail
        ),!.
    distance(X,Y,Visited,N) :- 
        parent(Z,X),
        (notmember(Z,Visited)->
            distance(Z,Y,[Z|Visited],N1),
            N is N1+1
        ;
            fail
        ),!.
    distance(X,Y,N) :- 
        findall(N1,distance(X,Y,[X],N1),L),!,
        minimum(N,L),!.
    
    已连接(X,Y,u):-X==Y。
    已连接(X、Y、V):-
    已婚(X,Z),
    非成员(Z,V),
    连通的(Z,Y,[Z | V]),!。
    已连接(X、Y、V):-
    兄弟姐妹(X,Z),
    非成员(Z,V),
    连通的(Z,Y,[Z | V]),!。
    已连接(X、Y、V):-
    父(X,Z),
    非成员(Z,V),
    连通的(Z,Y,[Z | V]),!。
    已连接(X、Y、V):-
    父级(Z,X),
    非成员(Z,V),
    连通的(Z,Y,[Z | V]),!。
    连通的(X,Y):-连通的(X,Y,[X])。
    最小值(X,[X])。
    最小值(X[M,H | T]):-
    M=H,
    最小值(X[H | T])。
    计数(X,[],0)。
    计数(X[X | T],N):-
    计数(X,T,N1),
    N是N1+1。
    计数(X[H | T],N):-
    X\==H,
    计数(X,T,N1),
    N是N1。
    距离(X,X,0):-
    计数(X,N),
    N=<1!。
    距离(X,Y,N):-
    父(X,Z),
    (非成员(Z,已访问)->
    距离(Z,Y,[Z |到访],N1),
    N是N1+1
    ;
    失败
    ),!.
    距离(X,Y,N):-
    父(Z,X),
    (非成员(Z,已访问)->
    距离(Z,Y,[Z |到访],N1),
    N是N1+1
    ;
    失败
    ),!.
    距离(X,Y,N):-
    findall(N1,距离(X,Y,[X],N1),L),!,
    最小值(N,L),!。
    
    但现在出现了一系列新的问题

  • 它不能接受像
    距离(X,y,n)
  • connected(X,y)
    这样的查询返回重复的结果
  • 我认为使用
    findall/3
    谓词可以消除重复结果, 但我不知道如何真正实现它。

    1)我不认为你以无限循环结束,但你让你的程序探索两个人连接的所有方式,这将是一个非常大的数字。由于您可能只对他们是否连接感兴趣,您应该在
    connected/3
    子句的末尾添加剪切,一旦您成功确定两个人连接,这些剪切将防止回溯,例如:

    connected(X,Y,_) :- X == Y,!.
    connected(X,Y,Visited) :- 
        ancestor(X,Z),
        notmember(Z,Visited),
        connected(Z,Y,[Z|Visited]),!.
    ...
    
    2) 当我测试代码时,我没有得到N的无限递增值,但是
    距离/3
    谓词将决定两个人如何连接的不同路径。根据不同的人群,最小距离不会是第一个被计算的距离。我会将
    distance/3
    的定义更改为如下内容:

    distance(X,Y,N) :- 
        findall(N0, distance(X,Y,[],N0), Ns), !,
        minimum(N, Ns).
    
    这是重复使用
    最小值/2
    谓词。请注意,您应该在该谓词的前两个子句中添加剪切,以避免虚假的选择点

    关于你的其他问题:

    3) 您必须区分寻找最小的N和寻找匹配度N的人:

    distance(X,Y,N) :-
      nonground(N),!,
      findall(N0, distance(X,Y,[],N0), Ns), !,
      minimum(N, Ns).
    distance(X,Y,N) :-
      distance(X,Y,[X],N).
    
    此外,还需要删除添加到
    distance/4
    的切口。这与添加到
    connected/3
    的切割不同

    也许有一种更好的方法可以避免区分这两种模式,但目前我所能想到的就是使用某种广度优先搜索(以确保最小程度)

    4) 对于像
    ?-connected(X,victoria)这样的问题,我没有得到重复的答案。
    你有例子吗