Computer Science 170
Analysis of Programming Languages

Spring 2003, Clark University
D Joyce


Comments on prolog

Order of operations. When you give prolog a query, it tries to find all the solutions, but one at a time. It will give you one, and if you’re satisfied, press return and give it some other query. If you want more solutions, enter a semicolon and return, and it will keep giving you more solutions until there aren’t any.

More generally, when trying to satisfy a goal (your query or some subquery that follows from it), prolog will try to match it with all the facts and rules it has, one at a time. It takes the first match which can be either a fact or a rule. If it’s a fact, then the goal is satisfied. But if it’s a rule, then there are subgoals which have to be satisfied. If they can be satisfied, that gives a solution to the goal. If the subgoals can’t be satisfied, then it tries the next match, and so forth, until all the matches have been tried. When all the matches have been checked and none satisfy the goal, then the goal is unsatisfiable. As this goal could be a subgoal of the one that generated it, prolog backtracks to the generating goal so it can try alternative matches.

Order of subgoals. If a rule has several parts on its right, then when a goal matches that rule, it will be replaced by several subgoals. Prolog then tries to satisfy all these subgoals, but it procedes from left to right. The first subgoal will be satisfied before the second is considered. If the first subgoal can’t be satisfied, then prolog backtracks to the main goal so it can try matching more rules. If the first subgoal can be satisfied, then the prolog tries to satisfy the second subgoal. If it can’t be satisfied, then it backtracks to the first subgoal to see if it can be satisfied in some other way. If the second goal can be satisfied, then it goes on to the third, and so forth. Eventually, either all the subgoals can be satisfied, and prolog returns to the main goal with a solution, or they can’t all be satisfied, and prolog backtracks to the main goal so it can try other matches.

Because the order of subgoals is important in prolog’s evaluation, it can important in what order you specify them.

Order of rules. As mentioned above, when trying to satisfy a goal, prolog will try to match it will all the facts and rules it has, one at a time. But which one does it try first? The facts and rules were specified to prolog in an order, and that order is used in matching the goal. First prolog tries to match the goal with the first fact or rule it was given, then the second, and so forth.

Because the order that the rules are stated is used by prolog in its evaluation, it can important in what order you specify them.

The search tree. If you place the main goal at the top of a tree, then all the ways it matches facts and rules will be branches from that node (goal). Each subgoal will have branches from it representing all the ways it matches the facts and rules. Since facts have no subgoals, they are leaves and don’t generate branches. But rules do, and this search tree can be infinite. The branches from a node in the tree should be listed in order, based on the order of the rules.

The nodes in a tree don’t have to be single goals. When a rule is applied that has several parts, then the goal is replaced by a list of subgoals. Thus, a each node can be a list of subgoals instead of just a single subgoal.

Cuts. Prolog doesn’t have negation, but something called "cuts" have been added to prolog which have the effect, in part at least, of putting negation into the language of prolog.

Here’s an example. Suppose you want to define nodup(X) to determine if a list has no consecutive duplicates. For instance, the list [3,2,4,4,3] has duplicate 4’s, but the list [3,4,2,3,4] has no duplicates.

One solution would be to look at the first two elements of the list X, and if they’re the same, then nodup(X) should fail. Otherwise, see if the tail of X has no duplicates. If you reach the empty list, then nodup(X) should succeed. Here’s the prolog code for that with some new syntax.

Skip the ‘!’ for the time being. The ‘fail’ in the first line is a goal that is never satisfied. (Think of it as an expression that is false, like 3<2.) So, lists with identical first two elements shouldn’t succeed. The second line says to drop the first A from the list and just look at the tail X. And that rule won’t be considered until the first rule has been looked at and fails. But prolog will try to match all the rules, and a goal like nodup([3,3,4]) does match that rule with A=3 and X=[3,4], and after it’s used a couple times, the empty list be reached, and the goal nodup([3,3,4]) will be satisfied. And that’s no good, since nodup([3,3,4]) shouldn’t be satisfied.

This is where the ‘!’ comes in. It stops the search so that after the first rule fails, then prolog no longer tries to match the goal with any more rules. So if a goal matches

then the goal fails (even if there are more rules down the line that might match it).

Another way of seeing cuts is that the search tree is cut. More specifically, all the branches to the right of the node with the ! are cut from the tree.

By the way, the meaning of "!" is not "not" like it is in Java, it’s more like "the only way" like the "!" that appears in the symbolism of the unique existential quantifier (an upside down E followed by !).


Back to the course page.