Prolog - 家谱

时间:2015-12-11 08:48:17

标签: prolog family-tree

我正致力于在prolog中创建一个家谱。我遇到麻烦的地方是我打电话给姐姐或兄弟。我得到的结果是正确的,朱莉是迈克的妹妹,朱莉是阿曼达的妹妹,阿曼达是迈克的妹妹,阿曼达是朱莉的妹妹。但是,如果我继续打击' n'键它将再次循环返回结果。为什么会这样?

parent(pete,mike).
parent(pete,julie).
parent(pete,amanda).
parent(mary,mike).
parent(mary,julie).
parent(mary,amanda).
female(mary).
female(julie).
female(amanda).
male(mike).
male(pete).



mother(X,Y):-
    parent(X,Y),
    female(X).

father(X,Y):-
    parent(X,Y),
    male(X).

sibling(X,Y):-
    parent(Z,X),
    parent(Z,Y),
    X\=Y.

sister(X,Y):-
    sibling(X,Y),
    female(X).

brother(X,Y):-
    sibling(X,Y),
    male(X).

2 个答案:

答案 0 :(得分:1)

每对兄弟姐妹都会有同一个父亲同一个母亲(至少在保守的社会中,在你的计划中)。这是您从中获得双重答案的地方。您可以说兄弟姐妹总是分享两个父母?

答案 1 :(得分:1)

如上所述,你得到双重答案,因为你正在检查他们是否有同一个父母,他们有两个。此外,您将获得更多解决方案,例如迈克是阿曼达的兄弟姐妹,但阿曼达也是迈克的兄弟姐妹,而且你没有做任何事情来阻止两种解决方案的出现。 所以而不是:

sibling(X, Y):-
    parent(Z, X),
    parent(Z, Y),
    X\=Y.

要解决两个父母的问题,你可以说他们总是和父母分享:

sibling(X, Y):-
    mother(Z, X),
    mother(Z, Y),
    father(W, X),
    father(W, Y),
    X\=Y.

你可以通过引入@<:

来阻止第二个问题(X =迈克,Y =阿曼达; X =阿曼达,Y =迈克)
sibling(X, Y):-
    mother(Z, X),
    mother(Z, Y),
    father(W, X),
    father(W, Y),
    X@<Y.

这样一来,只出现了一套解决方案,但是你必须要小心,因为它可能不会让你想要你想要的,这取决于你想要达到的目标(X = julie,Y = amanda不会在这种情况下是真实的。)

根据需要,也许更优雅和一般的解决方案(不要求父母双方都一样)将使用setof(http://www.swi-prolog.org/pldoc/doc_for?object=setof/3)与你的原始兄弟条款,但你会重写你的兄弟/姐妹条款,例如:

sibling(X, Y):-
    parent(Z, X),
    parent(Z, Y),
    X\=Y.

sister(X,Y,L):-
    female(X),
    setof([X, Y], (sibling(X, Y)), L).

brother(X,Y,L):-
    male(X),
    setof([X, Y], (sibling(X, Y)), L).

这将为您提供列表L中唯一对的列表,例如对于妹妹(X,Y,L),你得到:

X = julie
L = [[julie, amanda], [julie, mike]]

X = amanda
L = [[amanda, julie], [amanda, mike]]

稍微玩一下,准确得到你需要的东西。