I have a list of user facts defined as:
user(@michael).
user(@ana).
user(@bob).
user(@george).
user(@john).
and so on. Furthermore, I have a set of facts as:
follows(@michael,@ana).
follows(@ana,@bob).
follows(@bob,@michael).
I am trying to write a relation indirect(user1,user1) which will tell me if user1 indirectly follows user2. However, I am not able to do away with cyclic relations.
Like in the given example, michael -> ana -> bob -> michael will cause a cycle.
What is the best way to eliminate these cycles from the result of indirect(user1,user2)?
You can make a rule that passes an extra list of users that you have "seen" so far, and ignore follows originating from these users:
follows(A, B, Seen)
.To do that, define a "follow transitive" rule that wraps the actual rule, like this:
Now you can define
follows/3
rule this way:The base clause says that if there is a fact about
A
followingB
, we consider the predicate proven as long as we have not seenB
before.Otherwise, we find someone who follows
A
, check that we have not seen that user yet by checkingnot_member/2
, and finally see if that user followsB
, directly or indirectly.Finally, here is how you can define
not_member
:Demo.
See for a definition of
closure/3
.