Reputation: 197
I'm new to Prolog. I'm trying to write a query to check if a person is the friend or friend of friend of another person.
I have some facts like this:
friends(joe, [john, ann, pete, ellen,
maria, jose, bruno, ali, jing, yang]).
friends(john, [rick]).
friends(ellen, [mia, xing, jun, maria]).
friends(maria, [pete, ellen, zhang, jose, serena]).
friends(serena, [ali, rick, zhang, mia]).
friends(jose, [maria, jose, bruno, ali, jing]).
My target is to write a query like this:
visible(joe, ann).
true
I have made something like this:
visible(X,Y) :- friends(X,[Y|T]); member(Y,T).
visible(X,Y) :- visible(X,Z), visible(Z,Y).
member(X,[X|T]).
member(X,[H|T]) :- member(X,T).
But it becomes an infinite loop. I don't know how to write the base case.
The relationship is a graph with loop. Is there anyway to recursively find the friend of friend, transitively?
Upvotes: 2
Views: 1147
Reputation: 2662
visible(X,Y):- friends(X,YS), member(Y,YS).
visible(X,Y):- friends(X,XF), friends(Y,YF), member(Z,XF), member(Z,YF).
The first line checks if two people are directly friends (Y
is in the list of friends of X
). The second line checks if two peolpe are friend of friends (an element Z
is both in the list of friends of X
and Y
. If you also want to know wich is the friend in common you could add write(Z)
). In this case, for instance, joe
is friend of john
but no viceversa. If you want also this property you should add
visible(X,Y):- friends(Y,XS), member(X,XS).
Queries:
?-visible(john,serena).
true.
?-visible(joe,john).
true.
?-visible(john,joe).
true. (only if you add the third line of code).
Upvotes: 1