如何在prolog中找到血缘关系

时间:2013-11-08 10:44:14

标签: prolog

使用递归我需要找到家谱中任何人的所有血缘亲属。 到目前为止,我的尝试失败了。 这是我的代码,我在底部尝试

female(helen).
female(debbie).
female(louise).
female(yvonne).
female(belinda).
female(heather).
male(john).
male(andrew).
male(barry).
male(daniel).
male(charles).
parent(helen, debbie).
parent(helen, barry).
parent(helen, louise).
parent(john, debbie).
parent(john, barry).
parent(andrew, louise).
parent(debbie, yvonne).
parent(debbie, daniel).
parent(barry, charles).
parent(barry, belinda).
parent(louise, heather).

mother(X, Y) :-
        female(X),
        parent(X, Y).
father(X, Y) :-
        male(X),
        parent(X,Y).
child(X, Y) :-
        parent(Y, X).
daughter(X, Y) :-
        parent(Y, X),
        female(X).
son(X, Y) :-
        parent(Y,X),
        male(X).
sister(X, Y) :-
        female(X),
        parent(Q,X),
        parent(Q,Y).
brother(X, Y) :-
        male(X),
        parent(Q,X),
        parent(Q,Y).
sibling(X, Y) :-
        parent(Q,X),
        parent(Q,Y),
        X\=Y.
uncle(X, Y) :-
        parent(P,Y),
        brother(X,P).
aunt(X, Y) :-
        parent(P,Y),
        sister(X,P).

cousin(C, Cousin):-
        parent(Parent,C),
        sibling(Parent,AU),
        child(Cousin,AU).

        %Here is Relative

relative(An, Re):-
        An\=Re,
        parent(An, Re);
        sibling(An, Re).

relative(An, Rela):-
        parent(An, Child);
        sibling(An, Rela),      
        relative(Child, Rela),
        An\=Rela, C\=Rela.

工作类型,但最后陷入无限循环。 感谢。

2 个答案:

答案 0 :(得分:2)

不确定'亲戚'(父母/子女关系中任何人可以约束?),但你的定义似乎比需要的更复杂(你知道;做了什么吗?)。

我试过

relative(An, Re):-
        parent(An, Re).
relative(An, Rela):-
        parent(An, C),
        relative(C, Rela).

产生

16 ?- forall(relative(X,Y),writeln(X:Y)).
helen:debbie
helen:barry
helen:louise
john:debbie
john:barry
andrew:louise
debbie:yvonne
debbie:daniel
barry:charles
barry:belinda
louise:heather
helen:yvonne
helen:daniel
helen:charles
helen:belinda
helen:heather
john:yvonne
john:daniel
john:charles
john:belinda
andrew:heather
true.

编辑我尝试了另一种关系,使用广义的父/ 2,但仍然过于宽容。

relative(Pers, Re):-
        ancestor(Re, Pers) ; sibling(Pers, Re) ; cousin(Pers, Re) ; uncle(Re, Pers) ; aunt(Re, Pers).

ancestor(Anc, Pers) :- parent(Anc, Pers).
ancestor(Anc, Pers) :- parent(Anc, P), ancestor(P, Pers).

也许堂兄/ 2也太宽容了。这是图表

enter image description here

我想希瑟应该只有luise,helen和andrew作为亲戚。这是真的吗?

给出最新评论

编辑,似乎定义可能是正确的。我得到了

24 ?- setln(X,relative(heather,X)).
andrew
barry
belinda
charles
daniel
debbie
helen
louise
yvonne
true.

这是每个人都与石南花分开约翰。

答案 1 :(得分:0)

这是一种有效的方法,但它有时会产生重复。使用setof将提供唯一的集合。我避免了杂项关系并坚持使用descendentparent

descendent(A, B) :-
    parent(B, A).
descendent(A, B) :-
    parent(C, A),
    descendent(C, B).

relative(A, B) :-
    descendent(B, A).
relative(A, B) :-
    descendent(A, B).
relative(A, B) :-
    descendent(A, C),
    descendent(B, C),
    A \= B.

setof(A, relative(heather, A), Relatives).

Relatives = [andrew,barry,belinda,charles,daniel,debbie,helen,louise,yvonne]

如果您没有setof,则可以使用findall/3sort/2 ISO谓词:

findall(A, relative(heather, A), R), sort(R, Relatives).

请注意,到目前为止提供的解决方案假设所有亲属都有唯一的名称。处理具有相同名字(可能是相同的姓氏)的亲属的一般情况,您需要跟踪和比较不同的血统。