4
\$\begingroup\$

I tried to write a program in Prolog and describe a family tree:

parents(uranus, gaia, rhea).
parents(uranus, gaia, cronus).
parents(cronus, rhea, zeus).
parents(cronus, rhea, hera).
parents(cronus, rhea, demeter).
parents(zeus, leto, artemis).
parents(zeus, leto, apollo).
parents(zeus, demeter, persephone).

man(uranus).
man(cronus).
man(zeus).
man(apollo).
man(artemis).

woman(gaia).
woman(rhea).
woman(leto).
woman(demeter).
woman(persephone).
woman(hera).

father(X,Y) :- parents(X,_,Y).
mother(X,Y) :- parents(_,X,Y).

parent(X,Y) :- father(X,Y); mother(X,Y).

son(S,P) :- man(S), father(P,S).
daughter(D,P) :- woman(D), mother(P, D).

siblings(A,B) :- (parents(P,_,A), parents(P,_,B), A\=B) ; (parents(_,P,A), parents(_,P,B), A\=B).

sister(X, Y) :- woman(X), ((parents(F,_,X)), (parents(F,_,Y)); ((parents(_,M,X)), (parents(_,M,Y)).

uncle(U,N) :- man(U), (siblings(U,M); siblings(U,F)), parents(M, F, N). 
aunt(U,N) :- woman(U), (siblings(U,M); siblings(U,F)), parents(M, F, N).

grandparent(G,N) :- (parents(G,_,X), parents(X,_,N)); (parents(_,G,X), parents(_,X,N)).

grandpa(G,N) :- (parents(G,_,X), parents(X,_,N)); (parents(_,G,X), parents(_,X,N)), man(G).
grandma(G,N) :- (parents(G,_,X), parents(X,_,N)); (parents(_,G,X), parents(_,X,N)), woman(G).

The question is, I don't know if I did it right - especially the siblings, uncle, aunt, grandpa and grandma relations. Could somebody say if it's good or not? Thank you.

\$\endgroup\$
4
+25
\$\begingroup\$

I think you can simplify your code quite a bit if you drop the implicit restrictions you have on parent.

Consider the following:

parents(X,Y,Z) :- (father(X,Z), mother(Y,Z)); (father(Y,Z), mother(X,Z)).

father(X,Y) :- parent(X,Y), man(X).
mother(X,Y) :- parent(X,Y), woman(X).

This gets rid of the implicit genders in your definitions (see your parents declarations). It means you'll need a few more lines, but it allows you to define parentship as data.

It also makes the definition for siblings a tad easier:

siblings(A,B) :- father(F,A), father(F,B), mother(M,A), mother(M,B) A\=B.

this can will make half-siblings (and step-parentship) a lot cleaner, especially considering Zeus' significant number of illegitimate offspring in case you want to extend the family tree... Greek Gods have quite the messy family if you look closer.

It also makes uncle and aunt slightly easier to follow:

uncle(U,N) :- man(U), ((siblings(U,M), mother(M,N)) ; (siblings(U,F), father(F,N))).

it can be even easier if you go for a definition with parent:

uncle(U,N) :- man(U), siblings(U,P), parent(P,N).

making the rest of the family relationships cleaner and easier to follow from here should be rather obvious. It especially eases up the grandparent definitions...

On that note: grandparent has a "small" bug. Since you implicity gendered parents, your grandparent relationship only includes the father's father and the mother's mother. A similar bug has shown itself in son and daughter... The gender of the parent doesn't influence whether the child is a son or a daughter ... father and mother respectively should be replaced by parent in that definition.

As a closing note: You should strive to build your data in a "simplistic" way of atomic units with as little "implicit relation" as possible. This might seem more effort, it will drastically reduce the chance of such bugs to happen though.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.