Well, after telling everyone to avoid negation, I see I have used it in my its-a-tie.pl example. So here are some comments about the program, negation and other stuff.
solve :- tie(CrowTie), tie(EvansTie), tie(HurleyTie), tie(SpeiglerTie), all_different([CrowTie, EvansTie, HurleyTie, SpeiglerTie]),
Choose some ties. This will choose the same tie for everybody, then repeatedly backtrack, choosing different ties, until the
all_different predicate is satisfied. We do the same thing for relatives.
all_different predicate takes a list and succeeds if the list contains no duplicate values. You can use this predicate without completely understanding it. That's fortunate, because it uses the metalogical
Triples = [ [crow, CrowTie, CrowRelative], [evans, EvansTie, EvansRelative], [hurley, HurleyTie, HurleyRelative], [speigler, SpeiglerTie, SpeiglerRelative] ]Each list in the triple is
]. Notice that the person owning the tie is specified. We could instead have specfied all the ties, or all the relatives. The important thing is that we cover all three dimensions.
% 1. The tie with the grinning leprechauns wasn't a present from a daughter. \+ member([_, leprechauns, daughter], Triples),
Uh, oh, negation. That's the
\+ operator. All this says is that you cannot find, in the
list of triples, a triple containing both
daughter. The underscore,
_, is a variable that could unify
with anything, and you don't care what. Later tests are similar.
I said negation was difficult. The above doesn't look difficult, and it isn't. Here's what you need to remember about negation: Whether negation succeeds or fails, it cannot ever unify (instantiate) anything. You can use negation to prevent certain unifications, as above, but you cannot use it to find out anything.