我试图定义一个家族树及其节点之间的关系,它们的定义基于三个谓词:male/1
,female/1
和parent_of/2
。SWI-Prolog中的无限递归
我已经定义尊亲属,后裔,父亲,母亲,儿子,女儿,爷爷,奶奶,姑姑,叔叔和表哥的概念。任何新的定义都不能基于“兄弟/姐妹”的概念,而只能基于以前的定义。
这是代码:
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 ;
定义有什么问题?
哦,我明白了。我忘记了,尽管在逻辑中由一个连接词连接的两个谓词的顺序并不重要,但在Prolog中,由于它所运行的机器的性质,这很重要。感谢您帮助我:) –
@DanielMuñozParsapoormoghadam从技术上说,您是正确的:逻辑上,谓词应该按原样工作。然而,“堂兄”有一个循环逻辑问题,我首先考虑了“后代”,从而缩小了“堂兄”的选项。它也使谓词尾递归。通过一些其他重写,可以使查询“正式”第一次正常工作。但是我展示的是最简单的方法。我重新回答了我的答案以反映这一点。 – lurker