首页 文章

SWI-Prolog中的无限递归

提问于
浏览
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))).

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

enter image description here

当我写作

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 ) . 我也测试了它"manually",我得到了正确的结果:

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

定义有什么问题?

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.
    
    ?-
    

相关问题