Nephew of my own father in prolog

Viewed 720

i'm programming a family in prolog and i'm having trouble with the nephew implementation. When I ask if erick is the nephew of Alberto it returns true, when it should return false because Alberto is the father of erick, however, it does works for all the other cases that should be true. If someone could help me I would be very grateful. My code:

man(beto).
man(fransisco).
man(alberto).
man(jaime).
man(manolo).
man(nolo).
man(lito).
man(manuel).
man(erick).
man(jesu).
man(jesus).
woman(emi).
woman(harumi).
woman(haru).
woman(yuneisi).
woman(yasmeli).
woman(mioara).
woman(elia).
woman(iza).
woman(alice).
woman(ofelia).
woman(arlet).
parent(manuel, alberto).
parent(ofelia, alberto).
parent(manuel, jaime).
parent(ofelia, jaime).
parent(manuel, manolo).
parent(ofelia, manolo).
parent(alberto, erick).
parent(alberto, beto).
parent(alberto, fransisco).
parent(emi, erick).
parent(emi, beto).
parent(manolo, nolo).
parent(manolo, arlet).
parent(nolo, lito).
parent(iza, lito).
parent(mioara, yuneisi).
parent(mioara, yasmeli).
parent(jaime, yuneisi).
parent(jaime, yasmeli).
parent(jesus_padre, jesu)
parent(jesus_padre, alice).
parent(jesus_padre, haru).
parent(harumi, haru).
parent(harumi, jesu).
parent(harumi, alice).
father(X,Y) :- parent(X,Y), man(X).
mother(X,Y) :- parent(X,Y), woman(X).
brother(X,Y) :- man(X), parent(F, X), parent(F, Y).
sister(X,Y) :- woman(X), parent(P, X), parent(P, Y).
grandpa(X,Y) :- father(F,Y), father(X,F), man(X).
grandma(X,Y) :- father(F,Y), mother(X,F), woman(X).
son(X,Y) :- father(Y,X), man(X).
nephew(X,Y) :- father(F,X), brother(F,Y).
2 Answers

Besides the missing dot after parent(jesus_padre, jesu) as pointed out by @LuaiGhunim there are a few other issues with your predicates. Your definition of brother/2 is too general. Nobody is his own brother but if you query your predicate you find several such instances:

?- brother(X,X).
X = beto ;
X = beto ;
X = fransisco ;
X = alberto ;
X = alberto ;
X = jaime ;
X = jaime ;
X = manolo ;
X = manolo ;
X = nolo ;
X = lito ;
X = lito ;
X = erick ;
X = erick ;
X = jesu ;
X = jesu ;
false.

You can easily remedy this by adding a goal dif/2:

brother(X,Y) :-
   dif(X,Y),
   man(X),
   parent(F, X),
   parent(F, Y).

Now the query above fails as it should:

?- brother(X,X).
false.

You'll still get a lot of pairs twice:

?- brother(X,Y).
X = beto,               % <- 1st occurrence
Y = erick ;             % <- 1st occurrence
X = beto,
Y = fransisco ;
X = beto,               % <- 2nd occurrence
Y = erick ;             % <- 2nd occurrence
.
.
.

The reason for that is that you can derive it via the mother or the father. In the above example (beto and erick) you'll get there via emi or alberto. These solutions might be redundant but they are correct. The same goes for your predicate sister/2:

?- sister(X,X).
X = haru ;
X = haru ;
X = yuneisi ;
X = yuneisi ;
X = yasmeli ;
X = yasmeli ;
X = alice ;
X = alice ;
X = arlet.

The remedy is the same as above:

sister(X,Y) :-
   dif(X,Y),
   woman(X),
   parent(P, X),
   parent(P, Y).

?- sister(X,X).
false.

?- sister(X,Y).
X = haru,
Y = jesu ;
X = haru,
Y = alice ;
X = haru,
Y = jesu ;
.
.
.

Your definition of grandma/2 and grandpa/2 on the other hand is too specific. To see this let's add the following facts to your code:

man(m1).
man(m2).

woman(w1).
woman(w2).
woman(w3).

parent(m1,w1).
parent(w1,w2).
parent(w2,w3).

Then the following queries should succeed but they fail instead:

?- grandpa(m1,w2).
false.

?- grandma(w1,w3).
false.

The reason for this is that the intermediate parent in your definition of grandpa/2 and grandma/2 is a father/2 where it should be a parent/2. Additionally the last goals (man(X) and woman(X)) are redundant since they are already covered by father/2 and mother/2 respectively. Instead, you could define the two predicates like so:

grandpa(X,Y) :-
   parent(F,Y),
   father(X,F).

grandma(X,Y) :-
   parent(F,Y),
   mother(X,F).

Now the above queries yield the desired result:

?- grandpa(m1,w2).
true.

?- grandma(w1,w3).
true.

Finally, a nephew according to the Cambridge Dictionary is a son of your sister or brother, or a son of the sister or brother of your husband or wife. Since you haven't got predicates for husbands and wives I'll stick with the a son of your sister or brother part. If you add facts for husbands and wives, you can add additional rules to cover the other part of the definition. You can write the first part of the definition in Prolog like so:

nephew(X,Y) :-
   man(X),
   dif(F,Y),
   parent(P,F),
   parent(P,Y),
   parent(F,X).

If you query this predicate there's no erick/alberto solution any more:

?- nephew(erick,X).
X = jaime ;
X = manolo ;
X = jaime ;
X = manolo ;
false.

Prolog it's all about relations. Joins plays a fundamental role. So, often you can think in term of 'yields', or functions over the DB, and design/control the data access plan by means of joins (clauses, i.e. logical formulae) producing records - like SQL does. The procedural execution over the retrieved data is expressed in (almost) the same language: joins, giving us a taste of declarative programming. Anyway, here are the clauses provided by @tas in standard Prolog:

brother(X,Y) :-
   man(X),
   parent(F, X),
   parent(F, Y),
   X\=Y.

sister(X,Y) :-
   woman(X),
   parent(P, X),
   parent(P, Y),
   X\=Y.
Related