2

我正在尝试根据三个谓词来定义家谱及其节点之间的关系male/1female/1parent_of/2

我已经定义了祖先、后代、父亲、母亲、儿子、女儿、祖父、祖母、阿姨、叔叔和堂兄的概念。任何新的定义都不能基于“兄弟/姐妹”的概念,而只能基于以前的概念。

这是代码:

male(daniel).
male(miguelangel).
male(mario).
male(mahmoud).
male(esteban).
male(enrique).
male(javier).
male(miguelin).

female(diana).
female(hengameh).
female(vicenta).
female(mahvash).
female(angeles).
female(mexicana).
female(eloina).
female(esmeralda).
female(cristina).
female(otilia).

parent_of(miguelangel, daniel).
parent_of(miguelangel, diana).
parent_of(hengameh, daniel).
parent_of(hengameh, diana).
parent_of(mario, miguelangel).
parent_of(mario, esteban).
parent_of(mario, eloina).
parent_of(mario, angeles).
parent_of(mario, otilia).
parent_of(vicenta, miguel).
parent_of(vicenta, esteban).
parent_of(vicenta, eloina).
parent_of(vicenta, angeles).
parent_of(vicenta, otilia).
parent_of(mahmoud, hengameh).
parent_of(mahvash, hengameh).
parent_of(enrique, javier).
parent_of(angeles, javier).
parent_of(cristina, miguelin).
parent_of(otilia, cristina).
parent_of(eloina, esmeralda).

% Rules

ancestor(X, Y) :-
    parent_of(X, Y);
    parent_of(X, Z),
    ancestor(Z, Y).

descendant(X, Y) :-
    ancestor(Y, X).

father(X, Y) :- 
    parent_of(X, Y),
    male(X).

mother(X, Y) :-
    parent_of(X, Y),
    female(X).

son(X, Y) :-
    parent_of(Y, X),
    male(X).

daughter(X, Y) :-
    parent_of(Y, X),
    female(X).

grandfather(X, Y) :-
    parent_of(X, Z),
    parent_of(Z, Y),
    male(X).

grandmother(X, Y) :-
    parent_of(X, Z),
    parent_of(Z, Y),
    female(X).

aunt(X, Y) :-
    (grandfather(Z, Y) ; grandmother(Z, Y)),
    (father(Z, X) ; mother(Z, X)),
    not(parent_of(X, Y)),
    female(X).

uncle(X, Y) :-
    (grandfather(Z, Y) ; grandmother(Z, Y)),
    (father(Z, X) ; mother(Z, X)),
    not(parent_of(X, Y)),
    male(X).

cousin(X, Y) :-
    ((uncle(Z, Y), parent_of(Z, X)) ; (cousin(P, Y), descendant(X, P)));    
    ((aunt(Z, Y), parent_of(Z, X)) ; (cousin(P, Y), descendant(X, P))).

为了清楚起见,我通过图像表示了我遇到问题的树部分:

在此处输入图像描述

当我写

cousin(X, Y) :-
    ((uncle(Z, Y), parent_of(Z, X)));   
    ((aunt(Z, Y), parent_of(Z, X))).

代替

cousin(X, Y) :-
    ((uncle(Z, Y), parent_of(Z, X)) ; (cousin(P, Y), descendant(X, P)));    
    ((aunt(Z, Y), parent_of(Z, X)) ; (cousin(P, Y), descendant(X, P))).

我明白了

?- cousin(miguelin, daniel).
false.

?- cousin(cristina, daniel).
true .

这是有效的结果。但是当我介绍右边的递归定义时,如第一个(大)代码中所述,说 Y 的表亲的后代也是 Y 的表亲,程序崩溃:

?- cousin(miguelin, daniel).
ERROR: Out of local stack

我不明白为什么。如果我查看图像,递归定义是有意义的(至少对我而言),并且miguelin现在应该是 的表亲daniel(因为他是 的另一个表亲的后代daniel,即cristina)。我还“手动”测试了它,得到了正确的结果:

?- cousin(cristina, daniel), descendant(X, cristina).
X = miguelin ;

定义有什么问题?

4

1 回答 1

1

谓词的一个问题cousin/2是递归发生在您解决之前descendant/2,并且cousin/2在这种情况下存在无限递归问题。作为解决此问题的一种简单方法,您可以交换它们。此外,您还有一个冗余的递归子条款。所以修改后的cousin/2谓词将是:

cousin(X, Y) :-
    (uncle(Z,Y), parent_of(Z,X)) ;
    (aunt(W,Y), parent_of(W,X)) ;
    (descendant(X,P), cousin(P,Y)).

然后你得到:

?- cousin(miguelin, daniel).
true ;
false.

?- cousin(cristina, daniel).
true ;
false.

?-
于 2014-03-29T23:38:43.350 回答