陷入无限循环的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应该用来衡量亲属关系。但是:
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=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)这样的问题,我没有得到重复的答案。
你有例子吗