4
votes

I'm following a Prolog tutorial that asks to define a symmetric relation.

Say for instance you have the following fact in the knowledge base:

colleague(john,bob).

You also want colleague(bob,john) to be true, and likewise for all colleague facts.

The tutorial says to use the following rule...

colleague(X,Y) :- colleague(Y,X).

But there are issues when I do this when using the following query...

| ? - colleague(john,X).
X = bob ? ;
X = bob ? ;
X = bob ? ;
X = bob ? ;
...

| ? - colleague(bob,X).
X = john ? ;
X = john ? ;
X = john ? ;
X = john ? ;
...

I think I understand why this is happening - the rule is infinitely recursive? But I'm having issues fixing it. This is what I want...

| ? - colleague(john,X).
X = bob ? ;
no

| ? - colleague(bob,X).
X = john ? ;
no

I've had a look at other answers to very similar questions on here, but haven't been able to sort it. I've tried putting using a cut at the end of the rule, which seems to perform better but still repeats itself once for the fact that is included in the knowledge base:

colleague(X,Y) :- colleague(Y,X), !.

_

| ? - colleague(john,X).
X = bob ? ;
X = bob ? ;
no

| ? - colleague(bob,X).
X = john ? ;
no

Any ideas what I'm doing wrong?

1
Please see the closely related question. Adding !/0 only breaks the relation completely, so I strongly recommend to avoid that. As a simple check, always also try the most general query (in your case: ?- colleague(X, Y).) and see if it still means the same thing you originally meant. You will find that using !/0 thoroughly ensures that it doesn't. - mat
I've not quite got my head round understanding use of cuts as we've only just touched upon it in class this week, so I was a little unsure of it's usage. Thanks for pointing that out though! - Wolff
Using !/0 has a simple rule attached: In short, don't. Chances are high you will completely destroy your program semantics when using them. As a beginner, you have really nothing to gain by using !/0, and can only lose big time. - mat

1 Answers

6
votes

I think you'll have to make the rule distinct from the facts. For example:

known_colleague(bob,john).
colleague(X,Y) :- known_colleague(X,Y);known_colleague(Y,X).