我試圖定義一個家族樹及其節點之間的關係,它們的定義基於三個謂詞: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