CIS 554 Prolog 1: Notes on the It's-a-Tie puzzle
Fall 2013, David Matuszek

Here are some comments about the program, negation and lists 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.

The 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 ! operator. It also uses lists, but the syntax is simple (brackets and commas).

    Triples = [ [crow, CrowTie, CrowRelative],
                [evans, EvansTie, EvansRelative],
                [hurley, HurleyTie, HurleyRelative],
                [speigler, SpeiglerTie, SpeiglerRelative] ]
Each list in the triple is [mr, SomeTie, SomeRelative]. 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 leprechauns and daughter. The underscore, _, is a variable that could unify with anything, and you don't care what. Later tests are similar.

Negation isn't difficult, but it's tricky. 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.