Recursion SWI-Prolog中的无限递归
我试图根据三个谓词来定义族谱及其节点之间的关系:Recursion SWI-Prolog中的无限递归,recursion,prolog,family-tree,Recursion,Prolog,Family Tree,我试图根据三个谓词来定义族谱及其节点之间的关系:male/1、female/1和parent\u/2 我已经定义了上升、后代、父亲、母亲、儿子、女儿、祖父、祖母、阿姨、叔叔和堂兄弟的概念。任何新的定义都不能基于“兄弟姐妹”的概念,而只能基于以前的定义 代码如下: male(daniel). male(miguelangel). male(mario). male(mahmoud). male(esteban). male(enrique). male(javier). male(miguelin
male/1
、female/1
和parent\u/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))).
我明白了
这些都是有效的结果。但是,当我在右边引入递归定义时,正如第一段(大)代码中所述,表示Y的近亲的后代也是Y的近亲,程序崩溃了:
?- cousin(miguelin, daniel).
ERROR: Out of local stack
我不明白为什么。如果我看这幅图像,递归定义(至少对我来说)是有意义的,而且miguelin
现在应该是daniel
的堂兄弟(因为他是daniel
的另一个堂兄弟的后代,也就是cristina
)。我还“手动”测试了它,得到了正确的结果:
?- cousin(cristina, daniel), descendant(X, cristina).
X = miguelin ;
定义有什么问题?堂兄弟/2谓词的一个问题是,递归发生在解析
后代/2
之前,堂兄弟/2
在此上下文中存在无限递归问题。作为解决这一问题的简单方法,您可以交换它们。此外,还有一个冗余的递归子类。因此,修改后的近亲/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.
?-
哦,我明白了。我忘记了,虽然在逻辑上,两个谓词被一个连词连接的顺序并不重要,但在Prolog中,由于运行它的机器的性质,它们的顺序是重要的。谢谢你的帮助:)@DanielMuñozparsapormoghadam技术上你是对的:从逻辑上讲,谓词应该按原样工作。但是,
近亲
有一个循环逻辑问题,我先考虑了后代
,从而缩小了近亲
的选项范围。它还使谓词尾部递归。通过一些其他重写,可以首先使对cosine
的查询正常工作。但我展示的是最简单的方法。我改写了我的答案以反映这一点。
?- cousin(miguelin, daniel).
true ;
false.
?- cousin(cristina, daniel).
true ;
false.
?-