简体   繁体   English

SWI-Prolog中的无限递归

[英]Infinite recursion in SWI-Prolog

I am trying to define a family tree and the relationships between its nodes basing their definitions on three predicates: male/1 , female/1 and parent_of/2 . 我试图基于三个谓词定义一个家谱及其节点之间的关系: male/1female/1parent_of/2

I have defined the notions of ascendant, descendant, father, mother, son, daughter, grandfather, grandmother, aunt, uncle and cousin. 我定义了上升,后代,父亲,母亲,儿子,女儿,祖父,祖母,阿姨,叔叔和表弟的概念。 Any new definition can't be based on the notion of "brother/sister of", but only on the previous ones. 任何新定义都不能基于“兄弟/姊妹”的概念,而只能基于先前的定义。

This is the code: 这是代码:

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

For the sake of clarity I have represented through an image the part of the tree where I'm having issues: 为了清楚起见,我通过图像表示了我遇到问题的那部分树:

在此处输入图片说明

When I write 当我写

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

instead of 代替

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

I get 我懂了

?- cousin(miguelin, daniel).
false.

?- cousin(cristina, daniel).
true .

which are valid results. 这是有效的结果。 But when I introduce the recursive definitions on the right, as stated on the first (big) code, for saying that the descendants of the cousins of Y are also the cousins of Y, the program crashes: 但是,当我在第一个(大)代码中介绍了右边的递归定义时,为了说Y的表亲的后代也是Y的表亲,程序崩溃了:

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

I don't understand why. 我不明白为什么。 If I look at the image, it makes sense (at least to me) that recursive definition, and miguelin should be now the cousin of daniel (since he is a descendant of another cousin of daniel , which is cristina ). 如果我查看图像,那么递归定义(至少对我而言)是有意义的,并且miguelin现在应该是daniel的表亲(因为他是daniel的另一个表亲cristina的后代)。 I also tested it "manually" and I got the right result: 我还“手动”对其进行了测试,并且得到了正确的结果:

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

What's wrong with the definition? 定义有什么问题?

One problem with the cousin/2 predicate is that the recursion is occurring before you resolve the descendant/2 , and cousin/2 is having an infinite recursion issue in this context. cousin/2谓词的一个问题是递归是在解析descendant/2之前发生的,而cousin/2在这种情况下存在无限递归的问题。 As a simple way to fix that, you can swap them around. 作为解决此问题的简单方法,您可以交换它们。 Also, you have one redundant recursive subclause. 另外,您有一个冗余的递归子句。 So the modified cousin/2 predicate would be: 因此,修改的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)).

And then you get: 然后您得到:

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

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

?-

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM