2

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?

Shiloh_C
  • 197
  • 4
  • 13
  • `friend(X, Y) :- friends(X,Ys), member(Y,Ys).` and `visible(X, Y) :- closure(friend, X, Y).` using [this definition](https://stackoverflow.com/q/26946133/772868). – false Dec 05 '17 at 07:38
  • I got this error: ERROR: Undefined procedure: closure/3, Exception: (9) closure(friend, a, b) ? when I query visible(a,b). – Shiloh_C Dec 05 '17 at 08:21
  • You need to use the definition for `closure/3` in the link above! – false Dec 05 '17 at 11:08

1 Answers1

1
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).
damianodamiano
  • 2,528
  • 2
  • 13
  • 21