4

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?

Wolff
  • 1,051
  • 3
  • 18
  • 31
  • 1
    Please see the [closely related question](http://stackoverflow.com/questions/19637063/how-to-generate-a-rule-to-tell-that-this-simple-facts-go-both-ways/19637638#19637638). 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 Oct 02 '15 at 14:30
  • 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 Oct 02 '15 at 14:49
  • 1
    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 Oct 02 '15 at 14:53

1 Answers1

7

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).
Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
  • That worked, thanks! I'm not sure if it was the solution which the tutorial was intending for me to find, but I'm happy to go with it. – Wolff Oct 02 '15 at 14:47