How can I refractor the display functions? - prolog

I have these display functions:
display_siblings(X,Y):-
setof(X-Y, (siblings(X,Y), ordered(X-Y)), Sibs),
write('The siblings of'),
write(X),
write('are'),nl,
foreach(member(Pair, Sibs),
writeln(Pair)),nl,
write('% end'), nl.
display_sisters(X,Y):-
setof(X-Y, (sisters(X,Y), ordered(X-Y)), Sibs),
write('The sisters of'),
write(X),
write('are'),nl,
foreach(member(Pair, Sibs),
writeln(Pair)),nl,
write('% end'), nl.
As you can see only the second argument of setof is changing.
Could I make one display function of both and if it can how can I do this?
Roelof

One way would be:
display_siblings(X, Y):-
setof(X-Y, (siblings(X, Y), ordered(X-Y)), Sibs),
write('The siblings of'),
write_sibs(X, Sibs).
display_sisters(X, Y) :=
setof(X-Y, (sisters(X, Y), ordered(X-Y)), Sibs),
write('The sisters of'),
write_sibs(X, Sibs).
write_sibs(X, Sibs):-
write(X),
write('are'), nl,
foreach(member(Pair, Sibs),
writeln(Pair)),nl,
write('% end'), nl.
Another way would be:
display_siblings(X, Y) :-
display('siblings', X, Y).
display_sisters(X, Y) :-
display('sisters', X, Y).
display(Type, X, Y) :-
setof(X-Y, (call(Type, X, Y), ordered(X-Y)), Sibs),
write('The '), write(Type), write(' of'),
write(X),
write('are'),nl,
foreach(member(Pair, Sibs),
writeln(Pair)),nl,
write('% end'), nl.

Related

Prolog cousin once removed and half sister/brother rules

Am working on a prolog genealogy project and cannot figure out how to make the rules for cousin once removed and half sister/brother rules. Below is what I have and cannot get it to work. Any help or suggestions would be appreciated. I have placed in bold what I have tried. I'm sure its something simple in the way I'm trying to code it.I just cannot figure it out.
person(marc,male).
person(faith,female).
person(alan,male).
person(kim,female).
person(missy,female).
person(eric,male).
person(charles,male).
person(eleanor,female).
person(roland,male).
person(corey,male).
person(amy,female).
person(tyler,male).
person(matty,male).
person(kaydi,female).
person(jenna,female).
person(allison,female).
person(emma,female).
person(hayley,female).
person(jaylin,female).
person(lukus,male).
person(brendon,male).
person(bradley,male).
person(tylerh,male).
person(dayna,female).
person(victor,male).
person(jacoby,male).
person(javi,male).
person(jordan,male).
person(jaxson,male).
person(kenzie,female).
person(richard,male).
person(reggie,male).
person(reggiejr,male).
person(beverly,female).
person(floyd,male).
person(marjorie,female).
person(kevin,male).
parent(marc,alan).
parent(faith,alan).
parent(charles,marc).
parent(charles,kim).
parent(charles,missy).
parent(charles,eric).
parent(eleanor,marc).
parent(eleanor,kim).
parent(eleanor,missy).
parent(eleanor,eric).
parent(eric,matty).
parent(eric,tyler).
parent(eric,kaydi).
parent(amy,matty).
parent(amy,tyler).
parent(amy,kaydi).
parent(missy,jordan).
parent(missy,jaxson).
parent(missy,kenzie).
parent(richard,jordan).
parent(corey,kenzie).
parent(corey,jaxson).
parent(kim,allison).
parent(kim,jenna).
parent(kim,emma).
parent(kim,jaylin).
parent(kim,hayley).
parent(kim,dayna).
parent(roland,allison).
parent(roland,jenna).
parent(roland,emma).
parent(roland,jaylin).
parent(roland,hayley).
parent(roland,dayna).
parent(dayna,javi).
parent(dayna,jacoby).
parent(victor,javi).
parent(victor,jacoby).
parent(jenna,bradley).
parent(brendon,bradley).
parent(tylerh,lukus).
parent(allison,lukus).
parent(reggie,reggiejr).
parent(beverly,reggiejr).
parent(floyd,beverly).
parent(marjorie,beverly).
parent(reggiejr,kevin).
parent(floyd,eleanor).
parent(marjorie,eleanor).
married(marc,faith).
married(charles,eleanor).
married(kim,roland).
married(eric,amy).
married(missy,corey).
married(dayna,victor).
married(allison,tylerh).
married(marjorie,floyd).
married(beverly,reggie).
father(X, Y) :- parent(X, Y), person(X,male).
mother(X, Y) :- parent(X, Y), person(female,Y).
son(X, Y) :- parent(Y,X), person(X,male).
daughter(X, Y) :- parent(X,Y), person(Y,female).
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
grandfather(X, Z) :- grandparent(X, Z), person(X,male).
grandmother(X, Z) :- grandparent(X, Z), person(female,Y).
grandson(X, Z) :- grandchild(X, Z), person(X,male).
granddaughter(Y, Z) :- grandchild(Y, Z), person(Y,female).
grandchild(X, Z) :- grandparent(Z, X).
sibling(X,Y) :- parent(Z,X), parent(Z,Y).
brother(Y, X) :- sibling(Y,X), person(X,male), not(X=Y).
sister(X, Y) :- sibling(X, Y), person(Y,female).
auntoruncle(X, W) :- sibling(X, Y), parent(Y, W).
auntoruncle(X, Z) :- married(X,Y), sibling(Y,W), parent(W,Z).
uncle(X, W) :- auntoruncle(X, W), person(X,male).
aunt(X, W) :- auntoruncle(X, W), person(female,Y).
cousin(X, Y) :- parent(Z, X), auntoruncle(Z, Y), Y\=X.
nieceornephew(X, Y) :- parent(Z, X), sibling(Z, Y).
nephew(X, Y) :- nieceornephew(X, Y), person(X,male).
niece(X, Y) :- nieceornephew(Y, X), person(Y,female).
greatgrandparent(X, Z) :- parent(X, Y), grandparent(Y, Z).
greatgrandfather(X, Z) :- greatgrandparent(X, Z), person(X,male).
greatgrandmother(X, Z) :- greatgrandparent(X, Z), person(female,Y).
greatgrandchild(X, Z) :- child(X, Y), grandchild(X, Z).
greatgrandson(X, Z) :- greatgrandchild(X, Z), person(X,male).
greatgranddaughter(X, Z) :- greatgrandchild(X, Z), person(female,Y).
married_to(X,Y) :- married(X,Y), not divorced(X,Y).
whatgender(X,Y) :- person(X,Y).
**child(X, Y) :- parent(Y, X).
cousinonceremoved(X, Y) :- cousin(Z, Y), child(X, Z).
halfsibling(X,Y) :- parent(Z,X), parent(Z,Y), parent(P,X), \+parent(P,Y).
halfbrother(X,Y) :- halfsibling(X,Y), male(X).
halfsister(X,Y) :- halfsibling(X,Y), female(X).**
strong text

How to find if somebody is somebodies second cousin once removed in prolog?

I am writing a program to return true if a person is another persons second cousin once removed. The only information that is known is who is the parent of who else. I am using the family tree from here http://en.wikipedia.org/wiki/Cousin#Second_cousins_once_removed. Overall I got everything working but i cant make it find the second cousin once removed. The first cousin and the once removed ones work, just looking to get some help on how to find a second cousin that is also once removed.
parent(adam, betty).
parent(agatha, betty).
parent(adam, charles).
parent(agatha, charles).
parent(bill, david).
parent(betty, david).
parent(charles, emma).
parent(corinda, emma).
parent(dawn, frank).
parent(david, frank).
parent(emma, gwen).
parent(eric, gwen).
parent(frank, harry).
parent(felicity, harry).
child(X, Y) :-
parent(Y, X).
grandparent(X, Y) :-
parent(X, Z),
parent(Z, Y).
greatgrandparent(X, Y) :-
parent(P, Y),
grandparent(X, P).
cousin(X, Y) :-
grandparent(Z, X),
grandparent(Z, Y),
\+sibling(X, Y),
X \= Y.
sibling(X, Y) :-
parent(Z, X),
parent(Z, Y),
X \= Y.
cousinonceremoved(X, Y) :-
cousin(Z, Y),
child(X, Z).
secondcousin(X, Y) :-
greatgrandparent(Z, X),
greatgrandparent(Z, Y),
\+sibling(X, Y),
\+cousin(X, Y),
X \= Y.
Just as stated in the article: "The child of one's second cousin".
secondCousinOnceRemoved(H, G) :- child(H, F), secondcousin(F, G).

Prolog Family Relation, unexpected failure

Could anyone tell me why my aunt relation isn't working? It just returns false whenever I try to call it.
The Uncle relation I wrote under it seems to work perfectly. I can't figure out what the difference is. I tried (not(mother(X,Y)). at the end also but that doesn't change anything.
/* FACTS */
parents(david, george, noreen).
parents(jennifer, george, noreen).
parents(georgejr, george, noreen).
parents(scott, george, noreen).
parents(joanne, george, noreen).
parents(jessica, david, edel).
parents(clara, david, edel).
parents(michael, david, edel).
parents(laura, georgejr, susan).
parents(anna, scott, siobhan).
/* Relationships */
father(X, Y) :- parents(Y, X, _).
male(X) :- father(X, _).
mother(X, Y) :- parents(Y, _, X).
female(X) :- mother(X, _).
grandfather(X, Y) :- father(X, Z), father(Z, Y).
grandfather(X, Y) :- father(X, Z), mother(Z, Y).
grandmother(X, Y) :- mother(X, Z), mother(Z, Y).
grandmother(X, Y) :- mother(X, Z), father(Z, Y).
brother(X, Y) :- male(X), father(Z, X), father(Z, Y).
sister(X, Y) :- female(X), father(Z, X), father(Z, Y).
aunt(X,Y) :- sister(X,Z), parents(Y, Z, _).
aunt(X,Y) :- sister(X,Z), parents(Y, _, Z).
uncle(X, Y) :- brother(X, Z), parents(Y, Z, _), not(father(X,Y)).
uncle(X, Y) :- brother(X, Z), parents(Y, _, Z), not(father(X,Y)).
The short answer is that an uncle is working (sort of) and the aunt does not because your definition of male and female is deficient: it does not recognize people a male or a female unless they have kids. In your set of facts there is no female (judging by name) who would have kids and have a sibling who has kids. It is for the same reason that scott should not be showing up among the list of uncles.
Fixing this is simple: you could either
drop the rules that infer gender and state the gender instead, or
replace the parents facts with son/daughter facts + parents rule, and infer the gender from the fact that someone is a daughter of someone.
You are asking why aunt(A,P) does not have any solution. In other words
There are no aunts.
Here is a systematic way to localize the problem using program slicing. Since the program relevant for aunt/2 is a pure monotonic program, we can localize the problem in a very systematic manner.
Your problem is this: you have a goal aunt(A,P) that is too specialized. We will now try to generalize it. But only as long as the goal still fails. In this manner we will obtain a maximal generalization that still fails. Therefore, the problem must be somewhere in the remaining part.
To begin with, let me introduce the following definition in your program:
:- op(950,fx, *).
*_.
This permits to "comment out" a goal with prefix *. In this manner we will generalize your program. Let us try this out with the definition of aunt. That is, insert * in front of a goal, reload the example and see if it still fails. The following is its maximal generalization:
aunt(X,Y) :- sister(X,Z), * parents(Y, Z, _).
aunt(X,Y) :- sister(X,Z), * parents(Y, _, Z).
Even that generalization fails! So, in other words, also sister/2 is always failing.
There are no sisters.
sister(X, Y) :- female(X), father(Z, X), * father(Z, Y).
And even above fails!
There are no females with a father.
You might stick to this, or continue, by replacing the goals by their definitions.
sister(X, Y) :- mother(X,_), parents(X, Z, _), * father(Z, Y).
one more:
sister(X, Y) :- parents(_,_,X), parents(X, Z, _), * father(Z, Y).
So only mothers may be sisters which certainly is a bit too much of a restriction.
You are introducing a lot of redundancy and at least strange checking mechanisms.
The father and mother relationship imply that you specify the parents/3 relationship as parents(child,father,morther). I don't see why you define two queries.
What goes wrong is that the brother and sister relationship will succeed on brother(X,X). One can avoid this with X \= X, this is basically what you resolve in the aunt clause.
Furthermore you will need to provide additional information. The male and female relationship are only resolved when the person (X) has children. It is however possible to be an aunt or uncle when you have no children on your own.
This should work:
/* FACTS */
parents(david, george, noreen).
parents(jennifer, george, noreen).
parents(georgejr, george, noreen).
parents(scott, george, noreen).
parents(joanne, george, noreen).
parents(jessica, david, edel).
parents(clara, david, edel).
parents(michael, david, edel).
parents(laura, georgejr, susan).
parents(anna, scott, siobhan).
/* Relationships */
parent(X,Y) :- parents(Y,X,_).
parent(X,Y) :- parents(Y,_,X).
father(X, Y) :- parents(Y, X, _).
male(michael).
male(X) :- father(X, _).
mother(X, Y) :- parents(Y, _, X).
female(joanne).
female(jessica).
female(jennifer).
female(clara).
female(laura).
female(anna).
female(X) :- mother(X, _).
grandfather(X, Y) :- father(X, Z), father(Z, Y).
grandfather(X, Y) :- father(X, Z), mother(Z, Y).
grandmother(X, Y) :- mother(X, Z), mother(Z, Y).
grandmother(X, Y) :- mother(X, Z), father(Z, Y).
brother(X, Y) :- male(X), father(Z, X), father(Z, Y), X \= Y.
sister(X, Y) :- female(X), father(Z, X), father(Z, Y), X \= Y.
aunt(X,Y) :- sister(X,Z), parent(Z,Y).
uncle(X, Y) :- brother(X, Z), parent(Z,Y).

Prolog and ancestor relationship

I have to write a small prolog program which checks if a given person is a ancestor of a second one.
These are the facts and rules:
mother(tim, anna).
mother(anna, fanny).
mother(daniel, fanny).
mother(celine, gertrude).
father(tim, bernd).
father(anna, ephraim).
father(daniel, ephraim).
father(celine, daniel).
parent(X,Y) :- mother(X,Y).
parent(X,Y) :- father(X,Y).
The test if a person is an ancestor of another person is easy:
ancestor(X, Y) :- parent(X, Y).
ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
But now I have to write a method ancestor(X,Y,Z) which also prints out the relationship between two persons. It should look like this
?- ancestor(ephraim, tim, X).
false.
?- ancestor(tim, ephraim, X).
X = father(mother(tim)).
And that is the problem: I have no clue how do to this.
You can use an accumulator to adapt #Scott Hunter's solution :
mother(anna, fanny).
mother(daniel, fanny).
mother(celine, gertrude).
father(tim, bernd).
father(anna, ephraim).
father(daniel, ephraim).
father(celine, daniel).
ancestor(X, Y, Z) :- ancestor(X, Y, X, Z).
ancestor(X, Y, Acc, father(Acc)) :- father(X, Y).
ancestor(X, Y, Acc, mother(Acc)) :- mother(X, Y).
ancestor(X, Y, Acc, Result) :-
father(X, Z),
ancestor(Z, Y, father(Acc), Result).
ancestor(X, Y, Acc, Result) :-
mother(X, Z),
ancestor(Z, Y, mother(Acc), Result).
edit : as Scott Hunter showed in his edit, there's no need for an explicit accumulator here, since we can left the inner part of the term unbound easily at each iteration. His solution is therefore better !
A term manipulation alternative to the accumulator tecnique by #Mog:
parent(X, Y, mother(X)) :- mother(X, Y).
parent(X, Y, father(X)) :- father(X, Y).
ancestor(X, Y, R) :-
parent(X, Y, R).
ancestor(X, Y, R) :-
parent(X, Z, P),
ancestor(Z, Y, A),
eldest(A, P, R).
eldest(A, P, R) :-
A =.. [Af, Aa],
( atom(Aa)
-> T = P
; eldest(Aa, P, T)
),
R =.. [Af, T].
To test, I made tim a father: father(ugo, tim).
?- ancestor(tim, ephraim, X).
X = father(mother(tim)) .
?- ancestor(ugo, ephraim, X).
X = father(mother(father(ugo))) .
Simply add a term which tracts what kind of parent is used at each step (edited to get result in proper order):
ancestor(X,Y,father(X)) :- father(X,Y).
ancestor(X,Y,mother(X)) :- mother(X,Y).
ancestor(X,Y,father(Z2)) :- father(Z,Y), ancestor(X,Z,Z2).
ancestor(X,Y,mother(Z2)) :- mother(Z,Y), ancestor(X,Z,Z2).

Prolog: X is the grandfather of Y

Assume that the following facts are already entered into the Prolog database:
father(X, Y) // X is the father of Y
mother(X, Y) // X is the mother of Y
male(X) // X is a male
female(X) // X is a female
parent(X, Y) // X is a parent of Y
diff(X, Y) // X and Y are different
(1) Now add a Prolog rule for grandpa_of(X, Y) where "X is the grandfather of Y"
(2) Add another rule for sibling(X, Y) where "X is the sibling of Y"
My thoughts:
Question 1:
I am confused on how I can find the parents of the parents, all I have so far is
grandpa_of(X,Y) :- male(X), ...
Question 2:
sibling(X, Y) :- parent(P, X), parent(P, Y), diff(X, Y)
I think Jason means grandpa_of(X,Y) :- father(X,P), parent(P,Y).
It has been a long time... The first one is something like this:
grandpa_of(X, Y) :- father(X, P), father(P, Y).
Been too long... :-P
Hamad is the parent of Bilal, Laiba, and Marium.
Ali and Mona are Hamad's parents.
Musarat is also the parent of Bilal, Laiba, and Marium.
Kamran and Javeria are her parents.
Kamran and Javeria are also the parents of Salma, and Umar.
Parents are ancestors as are ancestors of parents.
Siblings share a parent.
mother
brother
grandfather
uncle
aunt
male(hamad).
male(bilal).
male(ali).
male(kamran).
male(umar).
female(laiba).
female(marium).
female(mona).
female(musarat).
female(javeria).
female(salma).
parents(ali, hamad).
parents(mona, hamad).
parents(kamran, musarat).
parents(javeria, musarat).
parents(kamran, salma).
parents(kamran, umar).
parents(javeria, salma).
parents(javeria, umar).
parents(hamad, bilal).
parents(hamad, laiba).
parents(hamad, marium).
parents(musarat, bilal).
parents(musarat, laiba).
parents(musarat, marium).
mother(X, Y) :-
parents(X, Y),
female(X),
write(X),
write(' is a mother of '),
write(Y),
nl.
brother(X, Y) :-
male(X),
x \= y,
parents(Z, X),
parents(Z, Y),
write(X),
write(' is a brother of '),
write(Y),
nl.
sister(X, Y) :-
female(X),
x \= y,
parents(Z, X),
parents(Z, Y),
write(X),
write(' is a sister of '),
write(Y),
nl.
grandfather(X, Y) :-
parents(X, P),
parents(P, Y),
male(X),
write(X),
write(' is grandfather of '),
write(Y),
nl.
uncle(X, Z) :-
brother(X, P),
parents(P, Z),
male(X),
write(X),
write(' is an uncle of '),
write(Z),
nl.
aunt(X, Z) :-
sister(X, P),
parents(P, Z),
female(X),
write(X),
write(' is an aunt of '),
write(Z),
nl.
%Sample program of X is a Grandfather of Y
%knowledgebase or database
female(amrita).
female(aroti).
female(manusi).
female(parboti).
male(susanta).
male(prasanta).
male(haran).
male(ratan).
male(srijit).
%clause
parent(manusi,susanta).
parent(ratan,amrita).
parent(aroti,amrita).
parent(haran,prasanta).
parent(haran,susanta).
parent(manusi,prasanta).
parent(susanta,srijit).
%rules
mother(X,Y):-parent(X,Y),female(X).
father(X,Y):-parent(X,Y),male(X).
sister(X,Y):-female(X),x==y,parent(Z,X),parent(Z,Y).
brother(X,Y):-male(X),x==y,parent(Z,X),parent(Z,Y).
grandparent(X,Y):-parent(X,Y),parent(Y,Z).
grandmother(X,Y):-mother(X,Y),parent(Y,Z).
grandfather(X,Y):-father(X,Y),parent(Y,Z).

Resources