2

Currently I'm exercising the Prolog chapter of seven languages in seven weeks. I tried to change the coloring example, in order to not write down every valid color combination.

different(red, green).
different(green, red).
different(red, blue).
different(blue, red).
different(blue, green).
different(green, blue).

coloring(A, M, G, T, F) :-
    different(M, T),
    different(M, A),
    different(A, T),
    different(A, M),
    different(A, G),
    different(A, F),
    different(G, F),
    different(G, T).

I changed the file to make different a functionpredicate:

color(red).
color(blue).
color(green).

different(X, Y) :- color(X), color(Y), \+(X=Y).
different_fail(X, Y) :- \+(X=Y), color(X), color(Y).

coloring(A, M, G, T, F) :-
    different(M, T),
    different(M, A),
    different(A, T),
    different(A, M),
    different(A, G),
    different(A, F),
    different(G, F),
    different(G, T).

What I don't get is that different gives me all combinations of different colors, but different_fail does only check if they are really different.

GNU Prolog 1.4.5 (32 bits)
Compiled Feb 23 2015, 08:36:31 with gcc
By Daniel Diaz
Copyright (C) 1999-2015 Daniel Diaz
| ?- ['color'].             
compiling /home/rudi/7langs/prolog/color.pl for byte code...
/home/rudi/7langs/prolog/color.pl compiled, 17 lines read - 2206 bytes written, 7 ms
| ?- different(red, red).   

no
| ?- different(red, blue).

yes
| ?- different_fail(red, red). 

no
| ?- different_fail(red, blue).

Up to here everything works as expected.

yes
| ?- different(red, A).        

A = blue ? ;

A = green

yes
| ?- different_fail(red, A).

no

But here I would expect that different_fail yields the exact results as different.

What is the difference in these functions, which cause my different_fail to fail?

Rudi
  • 19,366
  • 3
  • 55
  • 77
  • Just to point out, like CapelliC has said (but Mat has not!) that `=` does **not** mean equality-comparison. A bit closer to what you need is `==` (see the documentation of your Prolog). For `\+ A == B` you can also write `A \== B`. –  Feb 26 '15 at 09:17
  • 4
    Just to point out (which nobody else has yet said!): Instead of "functions", you should write "predicates". – mat Feb 26 '15 at 09:45
  • See [this answer](http://stackoverflow.com/a/8523825/772868) – false Feb 26 '15 at 14:36

2 Answers2

2

To declaratively express that two terms be different, use the dif/2 constraint, which is available in SICStus Prolog, SWI-Prolog, YAP and several others.

If you write different_colors/2 like this:

different_colors(X, Y) :- dif(X,Y), color(X), color(Y).

then everything will work exactly as you expect it, no matter in which order you place the goals.

The reason it currently fails is that \+/1 only means not provable at this time. It is not true negation in the declarative sense. Therefore, we have:

?- \+ X = Y, X = a, Y = b.
false.

but if we simply exchange the goals by commutativity of conjunction:

?- X = a, Y = b, \+ X = Y.
X = a,
Y = b.

In contrast, dif/2 works correctly in both cases, and I highly recommend you use it instead:

?- dif(X, Y), X = a, Y = b.
X = a,
Y = b.

?- X = a, Y = b, dif(X, Y).
X = a,
Y = b.
mat
  • 40,498
  • 3
  • 51
  • 78
  • You are missing something important in your answer, namely, that `=` means unification, which is arguably not what OP is calling "equality-comparison". –  Feb 26 '15 at 09:19
  • 3
    There are several additional things wrong with OP's description (for example the use of "function" instead of "predicate", "combination" instead of "permutation" etc.). However, the *core problems* are missing knowledge of `dif/2` to express syntactic disequality, and misunderstanding the meaning of `\+/1`. – mat Feb 26 '15 at 09:37
  • 2
    I was just trying to say that knowing what `=` does might help explain the cause of the mistake. `dif/2` is about how to avoid the mistake. –  Feb 26 '15 at 10:42
1

The (=)/2 means unification, not equality, and a variable can unify with anything, by definition.

Then, when you pass an unbound variable to different_fail/2, its first goal will fail, since the unification is actually performed, and then immediately undone by the negation...

I don't agree fully with the answer by mat... I think that in Prolog you cannot avoid to understand the operational semantic...

CapelliC
  • 59,646
  • 5
  • 47
  • 90