I have some issues in my family tree. As required, I need to create predicates on father, mother, son, daughter, grandfather, sibling, aunt, uncle, cousin, spouse, parent_of based on the facts of Male, Female, parent_of.
male(jerry).
male(stuart).
male(warren).
male(peter).
female(kather).
female(maryalice).
female(ann).
brother(jerry,stuart).
brother(jerry,kather).
brother(peter, warren).
sister(ann, maryalice).
sister(kather,jerry).
parent_of(warren,jerry).
parent_of(maryalice,jerry).
father(X,Y) :- male(X), parent_of(X,Y).
mother(X,Y) :- female(X), parent_of(X,Y).
son(X,Y) :- male(X), parent_of(Y,X).
daughter(X,Y) :- female(X), parent_of(Y,X).
grandfather(X,Y) :- father(X,P), parent_of(P,Y).
sibling(X,Y):- parent_of(P,X), parent_of(P,Y), X\=Y.
aunt(X,Y) :- sister(X,P), parent_of(P,Y).
uncle(X,Y) :- brother(X,P), parent_of(P,Y).
cousin(X,Y):- sibling(P,Q), parent_of(P,X), parent_of(Q,Y).
spouse(X,Y) :- parent_of(X,P), parent_of(Y,P).
parent_of(X,Y) :- male(X), father(X,Y); female(X), mother(X,Y).
The parent_of predicate gives me an error. Clasues of parent_of/2 are not together in the source file. When I ignore the error and run a query ?- sibling(jerry, stuart), it gives me an error out of local stack. Anyone know how to solve this problem. Your help will be appreicated. Thanks.
Problem 1
The parent_of predicate gives me an error. Clasues of parent_of/2 are not together in the source file.
Simply place definitions of the predicate right next to eachother
Change
parent_of(warren,jerry).
parent_of(maryalice,jerry).
...
spouse(X,Y) :- parent_of(X,P), parent_of(Y,P).
parent_of(X,Y) :- male(X), father(X,Y); female(X), mother(X,Y).
to
parent_of(warren,jerry).
parent_of(maryalice,jerry).
parent_of(X,Y) :- male(X), father(X,Y); female(X), mother(X,Y).
...
spouse(X,Y) :- parent_of(X,P), parent_of(Y,P).
Problem 2
?- sibling(jerry, stuart), it gives me an error out of local stack.
You have a circular logic error. You define parent_of\2 in terms of father\2 and father\2 in terms of parent_of\2. This will cause each to circle off into Prolog never-never-land.
Related
I have the following code in prolog.
male(X).
female(X).
child(X,Y).
mother(X,Y) :- female(X), child(Y,X).
this code outputs yes even when I test it as
male(X), mother(X,Y).
I don't how should I code male(X) is not equal to female(X) in this?
I have tried mother(X,Y) :- female(X), !, +male(X), child(Y,X). But this doesn't work.
When I try to see who is brother to who and same for sister it gives me the sons and daughter, I cannot find the mistake...
father(pedro-i,fernando-i).
father(pedro-i,beatriz(1347)).
father(pedro-i,joão(1349)).
father(pedro-i,dinis(1354)).
father(pedro-i,joão_grão_mestre_da_ordem_de_avis).
mother(constança(1320),luis).
mother(constança(1320),maria(1342)).
mother(constança(1320),fernando-i).
mother(inês_de_castro,beatriz(1347)).
Any other opinion I appreciate that
ancestor(X,Y) :- mother(X,Y).
ancestor(X,Y) :- father(X,Y).
if_then_else(X,Y,male) :- father(X,Y).
if_then_else(X,Y,female) :- mother(X,Y).
son(X,Y) :- father(X,Y).
sister(X,Y) :- ancestor(Z,Y),X\==Y,if_then_else(X,Y,female).
brother(X,Y) :- ancestor(Z,Y),X\==Y,if_then_else(X,Y,male).
descendent (X,Y) :- filho(X,Y).
descendent (X,Y) :- filho(X,Z),descendent (Z,Y).
grandfather(X,Y) :- ancestor(X,Z),ancestor(Z,Y).
grandmother(X,Y) :- ancestor(X,Z),ancestor(Z,Y).
grandchildren(X,Y) :- ancestor(Z,X),ancestor(Y,Z).
uncle(X,Y) :- brother(X,Z),ancestor(Z,Y).
Your clause brother(X,Y) :- ancestor(Z,Y),X\==Y,if_then_else(X,Y,male). requires Y to have an ancestor, but X also needs to have an ancestor -- the same ancestor:
brother(X,Y) :- ancestor(Z,Y),ancestor(Z,X), X\==Y,if_then_else(X,Y,male).
You also need to eliminate the requirement at the end that X be the father of Y.
brother(X,Y) :- ancestor(Z,Y),ancestor(Z,X), X\==Y,male(X).
male needs to depend simply on the individual (you don't need to be a father to be a male.) male (fernando-i)., etc.
Using recursion i need to find all blood relatives of any person in the family tree.
My attempt so far has failed.
Here is my code, with my attempt at the bottom
female(helen).
female(debbie).
female(louise).
female(yvonne).
female(belinda).
female(heather).
male(john).
male(andrew).
male(barry).
male(daniel).
male(charles).
parent(helen, debbie).
parent(helen, barry).
parent(helen, louise).
parent(john, debbie).
parent(john, barry).
parent(andrew, louise).
parent(debbie, yvonne).
parent(debbie, daniel).
parent(barry, charles).
parent(barry, belinda).
parent(louise, heather).
mother(X, Y) :-
female(X),
parent(X, Y).
father(X, Y) :-
male(X),
parent(X,Y).
child(X, Y) :-
parent(Y, X).
daughter(X, Y) :-
parent(Y, X),
female(X).
son(X, Y) :-
parent(Y,X),
male(X).
sister(X, Y) :-
female(X),
parent(Q,X),
parent(Q,Y).
brother(X, Y) :-
male(X),
parent(Q,X),
parent(Q,Y).
sibling(X, Y) :-
parent(Q,X),
parent(Q,Y),
X\=Y.
uncle(X, Y) :-
parent(P,Y),
brother(X,P).
aunt(X, Y) :-
parent(P,Y),
sister(X,P).
cousin(C, Cousin):-
parent(Parent,C),
sibling(Parent,AU),
child(Cousin,AU).
%Here is Relative
relative(An, Re):-
An\=Re,
parent(An, Re);
sibling(An, Re).
relative(An, Rela):-
parent(An, Child);
sibling(An, Rela),
relative(Child, Rela),
An\=Rela, C\=Rela.
Sort of works, but gets stuck in an infinite loop at the end.
Thanks.
not sure about 'relatives' (any person bound reachable in a parent/child relation ?), but your definition seems more complex than needed ( do you know what ; does ?).
I tried
relative(An, Re):-
parent(An, Re).
relative(An, Rela):-
parent(An, C),
relative(C, Rela).
that yields
16 ?- forall(relative(X,Y),writeln(X:Y)).
helen:debbie
helen:barry
helen:louise
john:debbie
john:barry
andrew:louise
debbie:yvonne
debbie:daniel
barry:charles
barry:belinda
louise:heather
helen:yvonne
helen:daniel
helen:charles
helen:belinda
helen:heather
john:yvonne
john:daniel
john:charles
john:belinda
andrew:heather
true.
edit I tried another relation, using a generalized parent/2, but still too permissive.
relative(Pers, Re):-
ancestor(Re, Pers) ; sibling(Pers, Re) ; cousin(Pers, Re) ; uncle(Re, Pers) ; aunt(Re, Pers).
ancestor(Anc, Pers) :- parent(Anc, Pers).
ancestor(Anc, Pers) :- parent(Anc, P), ancestor(P, Pers).
Maybe cousin/2 is too permissive also. Here is the graph
I guess that heather should have only luise,helen,andrew as relatives. It's this true ?
edit given latest comment, seems that the definition could be right. I get
24 ?- setln(X,relative(heather,X)).
andrew
barry
belinda
charles
daniel
debbie
helen
louise
yvonne
true.
that is everyone is related to heather apart john.
Here's one way that works, but it will sometimes produce duplicates. Using setof will give the unique collection. I avoided the miscellaneous relations and stuck with descendent or parent.
descendent(A, B) :-
parent(B, A).
descendent(A, B) :-
parent(C, A),
descendent(C, B).
relative(A, B) :-
descendent(B, A).
relative(A, B) :-
descendent(A, B).
relative(A, B) :-
descendent(A, C),
descendent(B, C),
A \= B.
setof(A, relative(heather, A), Relatives).
Relatives = [andrew,barry,belinda,charles,daniel,debbie,helen,louise,yvonne]
If you don't have setof, you can use the findall/3 and sort/2 ISO predicates:
findall(A, relative(heather, A), R), sort(R, Relatives).
Note that the solutions presented so far assume that all of the relatives have unique names. A general case of dealing with relatives with the same first name (and possibly the same last name) you would need to track and compare lineages for differences.
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).
A (very) strange story:
I married a widow(W) who has a daughter(D). My father(F) married my stepdaughter (D). My wife gave birth to a son(s1). The wife of my father (the stepdaughter) also had a son (s2).
The goal of this project is to input:
grandfather(i,i).
and return yes in prolog.
Here is what I have so far:
%facts
father(f,i).
husband(i,w).
husband(f,d).
mother(w,d).
mother(w,s1).
father(i,s1).
mother(d,s2).
father(f,s2).
%rules
father(X,Y) :- f_in_law(X,Y).
father(X,Y) :- husband(X,Z),mother(Z,Y).
f_in_law(X,Y) :- husband(Z,Y),father(X,Z).
b_in_law(X,Y) :- husband(Z,Y),brother(X,Z).
%brother(X,Y) :- b_in_law(X,Y).
uncle(X,Y) :- father(Z,Y),brother(X,Z).
grandfather(X,Y) :- father(Z,Y),father(X,Z).
I traced through it to see what went wrong. father(f,i) is true so that's good! But father(i,f) is thought of as false. Any suggestions/ideas on how to correct this? I appreciate any input as I am rather new to prolog.
Should the predicate be
f_in_law(X,Y) :- husband(Y,Z),father(X,Z).
instead of
f_in_law(X,Y) :- husband(Z,Y),father(X,Z).
I have reformulated the riddle
father(i, s1).
father(f, i).
father(f, s2).
fatlaw(X, Y) :- husband(X, Z), mother(Z, Y).
mother(w, d).
mother(w, s1).
mother(d, s2).
motlaw(X, Y) :- husband(Z, X), father(Z, Y).
husband(i, w).
husband(f, d).
grandfather(X, Y) :-
( father(X, Z) ; fatlaw(X, Z) )
, ( father(Z, Y) ; fatlaw(Z, Y) ; mother(Z, Y) ; motlaw(Z, Y) )
.
the point seems to be that grandfather must accept fake biological offsprings (I hope this is reasonable English).
with that
?- grandfather(X,X).
X = i ;
false.