Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Query the relation between two people in a Prolog Family Tree

Suppose I have the below code in my familyTree.pl file:

male(tom).
male(bob).

female(lisa).
female(emily).

parent(tom, bob).
parent(lisa, bob).

morethanfriends(emily, bob).

father(X,Y) :- male(X), parent(X,Y).
mother(X,Y) :- female(X), parent(X,Y).
girlfriend(X,Y) :- female(X), (morethanfriends(X,Y); morethanfriends(Y,X)).
boyfriend(X,Y) :- male(X), (morethanfriends(X,Y); morethanfriends(Y,X)).

Now, I want to get the answer to the questions like:

What is the relationship between Tom and Bob ?

What is the relationship between Lisa and Emily ?

How can I ask the above questions to prolog?

The only solution I could come up with was to iterate over the known relation types giving (Tom, Bob) or (Lisa, Emily) as paremeter and check which one returns true. But; this solution seems to be a waste of time, when the number of known relation types are more than a few and/or there is a chain relation between the given two people (i.e.: Lisa and Emily: Lisa is Emily's boyfriend's mother).

like image 489
Cihan Keser Avatar asked Oct 13 '22 19:10

Cihan Keser


1 Answers

I have come up with this solution (not checked thoroughly but it seems to be ok):

relations(What, Name1, Name2):-
  relation_facts(Facts, Name1, _),
  relations1(Facts, [], Name2, What1),
  atomic_list_concat(What1, What).

relations1(Facts, Forbidden, Name2, What):-
  member(Relation, Facts),
  call(Relation),
  relations2(Relation, Forbidden, Name2, What).

relations2(Relation, Forbidden, Right, [Left, ' ', is, ' ', Right, '''s ', Name]):-
  Relation =.. [Name, Left, Right],
  Forbidden \= Right.
relations2(Relation, Forbidden, Name2, [Left, ' ', is, ' '| What]):-
  Relation =.. [Name, Left, Right],
  relation_facts(Facts, Right, _),
  Forbidden\=Right,
  relations1(Facts, Left, Name2, [_,_,_,_, NRight|What1]),
  append([NRight|What1], ['''s ', Name], What).

% Here goes the relations you want to check for:
relation_facts([father(X,Y), mother(X,Y), girlfriend(X,Y), boyfriend(X,Y)], X, Y).

Test cases:

?- relations(Relation,lisa,emily).
Relation = 'lisa is emily\'s boyfriend\'s mother' ;

?- relations(Relation,lisa,bob).
Relation = 'lisa is bob\'s mother' ;

?- relations(Relation,_,_).
Relation = 'tom is bob\'s father' ;
Relation = 'tom is emily\'s boyfriend\'s father' ;
Relation = 'lisa is bob\'s mother' ;
Relation = 'lisa is emily\'s boyfriend\'s mother' ;
Relation = 'emily is bob\'s girlfriend' ;
Relation = 'bob is emily\'s boyfriend' ;
like image 60
gusbro Avatar answered Oct 18 '22 02:10

gusbro