4

I've seen a few questions on this topic, however none of them really answers my question properly. I'll write a small example, here are some facts:

football(john).
football(sam).

tennis(john).
tennis(pete).

netball(sandy).

I want to create a rule that states pete likes anyone that plays football or tennis.

likes(pete, X) :- (football(X) ; tennis(X)), X \= pete.

But obviously when I query it in Prolog, john will come up twice as john plays both football and tennis. I want it to come up with john only once. How can I amend my code to do that?

Thanks in advance - Dan

repeat
  • 18,496
  • 4
  • 54
  • 166
  • 4
    The only real way to do it is with `setof/3`. This is because Prolog doesn't keep state between solutions, so it literally doesn't know that it has already given you john once before—unless you make it keep track using a second-order predicate like `setof/3`. – Daniel Lyons Aug 02 '18 at 03:45

3 Answers3

3

One clean solution is to use your Prolog system's tabling mechanism.

For example, in SWI-Prolog, you can do this by adding the following directive at the top :

:- table likes/2.

With this directive, you get:

?- likes(pete, X).
X = john ;
X = sam.

Whereas without it, you get:

?- likes(pete, X).
X = john ;
X = sam ;
X = john.

Tabling is also known as SLG resolution.

repeat
  • 18,496
  • 4
  • 54
  • 166
mat
  • 40,498
  • 3
  • 51
  • 78
  • The code in the question had a trivial, but hard-to-find error (`x` vs `X`) which was clearly unintentional and obfuscated the question. I took the liberty to adapt your code, ok? – repeat Jan 29 '19 at 19:35
2

Here's the approach mentioned by @DanielLyons in his comment to your question.

It is based on , so it is portable across different Prolog systems.

Using SICStus Prolog 4.5.0:

| ?- setof(t, likes(pete,X), _).
X = john ? ;
X = sam ? ;
no
repeat
  • 18,496
  • 4
  • 54
  • 166
1

SWI-Prolog offers library(solution_sequences)

likes(pete, X) :- distinct( ((football(X) ; tennis(X)), X \= pete) ).

?- likes(pete, X).
X = john ;
X = sam ;
false.

It's built on the infrastructure that make tabling available, tough, so it has similar requirements on memory storage.

CapelliC
  • 59,646
  • 5
  • 47
  • 90