12 Prolog Intro
12 Prolog Intro
edu/classes/cs245/fall04/
Heres how it works (very roughly!). Assume the following database: parent(amy,bob). parent(bob,cathy). parent(bob,doug). grandparent(X,Z) :- parent(X,Y) , parent(Y,Z). ancestor(X,Y) :- parent(X,Y). ancestor(X,Y) :- parent(Z,Y) , ancestor(X,Z). The query parent(amy,bob). will return true because Prolog can see that it is dened in the database as a fact. ancestor(bob,doug). is also true; bob is a parent of doug, and the rst ancestor rule says that if youre a parent, then youre an ancestor, too. What about ancestor(amy,cathy). ? This is true if Prolog can nd a constant to replace Z such that parent(Z,cathy) is true AND such that ancestor(amy,Z) is also true. In this example, it will nd that replacing Z with bob will make both subgoals true, and so the answer to the query is true. Prolog can do more. Consider this query: parent(bob,X). With that form of query, we arent interested in just a true/false answer; we want to know which constants exist in the database that can replace X to make the query true. By searching the facts, Prolog will nd that X can be cathy or X can be doug. If you let it, Prolog will tell you both (or you can stop after seeing just the rst response). Prolog can do a LOT more than this example can show. But, this is sucient for our purposes. Using gprolog: The rst step is to create the database. Traditionally, the database le has a .pl le extension, and gprolog follows this tradition. Using an editor (a really easy one to use from a terminal window under UNIX is pico; you can nd a short command list on my web page), create a le with that extension and type in your facts and rules. For example, you might create a le named family.pl and type in the following: parent(hank,ben). parent(hank,denise). parent(irene,ben). parent(irene,denise). parent(alice,carl). parent(ben,carl). parent(denise,frank). parent(denise,gary). parent(earl,frank). parent(earl,gary). grandparent(X,Z) :- parent(X,Y) , parent(Y,Z). ancestor(X,Y) :- parent(X,Y). ancestor(X,Y) :- parent(Z,Y) , ancestor(X,Z). Dont forget the period at the end of each line! Blank lines are OK. You can even put in comments; in Prolog, they start with a percent sign and stop at the end of the line. With the le created, you can start gprolog. At the shell prompt, type: gprolog and press Enter. Youll see something like this: GNU Prolog 1.2.16 By Daniel Diaz Copyright (C) 1999-2002 Daniel Diaz | ?-
The last line is the Prolog prompt; its ready for you to type a command. To load your family database into Prolog, use this command at that prompt: [family]. This will load the database from the family.pl le into Prolog. If Prolog nds that everything is in order, it will say something like this: compiling /***/***/family.pl for byte code... /***/***/family.pl compiled, 14 lines read - 1204 bytes written, 109 ms yes | ?If its not happy, it will give an error message that probably wont make much sense. Dont panic! It will report the line in the le on which it found the error. Go back to your le, nd that line, x the error, and try again. With the database loaded, you can type in queries. Here are a few to show you what will happen: | ?- parent(hank,denise). yes | ?- parent(denise,hank). no | ?- grandparent(irene,frank). true ? ; no | ?- parent(hank,X). X = ben ? ; X = denise yes | ?- grandparent(hank,X). X = carl ? ; X = frank ? ; X = gary yes | ?When Prolog prints a response and follows it with a question mark, it is asking if you want it to keep searching for more answers. Typically, you do. If so, just press the semicolon, which tells Prolog to keep going. When youre done and want to leave gprolog, just enter CtrlD (that is, hold down the Ctrl key on the keyboard, and press D). Youll be back at the shell prompt.
Tracing Frequently, your database will cause Prolog to produce answers that you know arent correct. This means that your facts or rules are incorrect, but nding out which ones are wrong can be dicult. To help, Prolog provides a tracing command that allows you to watch Prologs reasoning as it happens. Its hard to follow until you see it a few times, but its very helpful, not only for debugging, but also for learning about how Prolog works. To turn on tracing, the command is trace. While tracing is on, you can issue any query, and Prolog will step you through its logical process. Heres what a trace of the grandparent(hank,X). query looks like: | ?- trace. The debugger will first creep -- showing everything (trace) yes {trace} | ?- grandparent(hank,X). 1 1 Call: grandparent(hank,_16) ? 2 2 Call: parent(hank,_85) ? 2 2 Exit: parent(hank,ben) ? 3 2 Call: parent(ben,_16) ? 3 2 Exit: parent(ben,carl) ? 1 1 Exit: grandparent(hank,carl) ? X = carl ? ; 1 1 2 2 2 2 3 2 3 2 1 1 X = frank ? ; 1 1 3 2 3 2 1 1 X = gary yes {trace} | ?Note that you press Return at the question marks after the trace output, but semicolons after the normal results output (as shown). Starting at the top of the trace, note that Prolog uses its own internal labels to represent the variables. Prolog needs to nd a constant that has hank as its parent; it nds ben. That takes care of the rst subgoal of the grandparent rule. To satisfy the second subgoal it needs to nd a constant that has ben as its parent. It nds carl, and reports him to us. We typed a semicolon, which asked Prolog to look for more grandchildren. It nds that ben doesnt have any other children, but it nds that denise is another child of hank, and denise has a child named frank. Continuing, it nds another child of denise (gary), and thats all. To turn tracing o, the command is notrace.
Connecting Prolog to Predicate Logic You no doubt remember that in logic, we like to represent predicates with capital letters (e.g., E(x, y) represents x eats y). Consider this implication: (P (x, y) P (y, z)) G(x, z). This says: If P (x, y) is true and P (x, z) is also true, then G(x, z) is true. This is exactly what our grandparent rule says in Prolog! The Prolog syntax is just backwards. Think of the :- symbol in Prolog as representing the word if, and the connection becomes clear. Internally, Prolog represents rules in a form known as a Horn clause. A Horn clause is a disjunction of predicates in which at most one of the predicates is not negated. Sounds odd, but it matches well with Prologs needs. Consider the grandparent clause again: grandparent(X,Z) :- parent(X,Y) , parent(Y,Z). Rewritten as in our logical notation, including quantication: x y z ((P (x, y) P (y, z)) G(x, z)) We know that p q is logically equivalent to p q, and so the above is equivalent to: x y z ((P (x, y) P (y, z)) G(x, z)) And De Morgans Laws tell us that we can replace the AND with an OR as the negation is pulled through, producing a Horn clause: x y z (P (x, y) P (y, z) G(x, z)) Heres why having a Horn clause is important: Prolog has facts in its database about parents. By employing a simplied version of the resolution rule of inference, Prolog can use a fact to remove a predicate from the Horn clause and get closer to an answer. For example, for the query grandparent(hank,X), the resulting Horn clause would be not parent(hank,A) or not parent(A,B) or grandparent(hank,B). The database tells Prolog that parent(hank,ben) is a fact, and Prolog can resolve that fact with the Horn clause if A = ben. That assignment is called unication, and the result is the Horn clause not parent(ben,B) or grandparent(hank,B). Finding that ben is the parent of carl lets Prolog use resolution and unication once more to conclude that grandparent(hank,carl) is true. Yes, Virginia; there are good reasons to learn about logic if you want to be a computer scientist!
Hopelessly Stuck in Gatesville? For those of you who are not quite ready to brave the world of UNIX, gprolog is available for Windows in the GS228 lab. I believe that theres an icon for it on the desktop, but if not, check the Start menu for GNU Prolog. One important dierence from the UNIX version: When you load your database into the Windows version, the command syntax is dierent. For example, if family.pl is on the D: drive, your syntax would be [d:family.pl]. instead of just [family]. . Otherwise, for what you need to worry about, I think everythings the same.
Want to Learn More? There are lots of good texts on Prolog, and plenty of web pages with tutorials. Resolution and unication are often covered in articial intelligence texts.