Next: Exercises: Up: Recursion Previous: Recursion

Tracing Prolog Execution

At this point you should probably try using Prolog's trace facilities, and see if you can follow what's happening for examples like the one above. Trace facilities may vary slightly from implementation to implementation, but are all based on the same basic control flow model, known as the box model. Basically, for any prolog procedure (say, ancestor) we can get Prolog to tell us when it calls that procedure, when it exits (successfully) that procedure, when it retries that procedure (because of bactracking - sometimes indicated by back) and when it finally fails that procedure. You can specify the procedure of interest by setting spy points, but for now we will just look at the simplest kind of trace, where it tells you about every procedure. In a typical Prolog we might have, for example:


| ?- trace.

yes
| ?- ancestor(alison, Anc).
   (1)  1 call: ancestor(alison,_0) ? 
   (2)  2 call: parent(alison,_0) ? 
   (2)  2 exit: parent(alison,david)
   (1)  1 exit: ancestor(alison,david)

X = david ;
   (1)  1 redo: ancestor(alison,_0) ?
   (2)  2 redo: parent(alison,_0) ? 
   (2)  2 exit: parent(alison,kathleen)
   (1)  1 exit: ancestor(alison,kathleen)

X = kathleen ;
   (1)  1 redo: ancestor(alison,_0) ?
   (2)  2 redo: parent(alison,_0) ? 
   (2)  2 fail: parent(alison,_0)
   (3)  2 call: parent(alison,L103) ? 
   (3)  2 exit: parent(alison,david)
   (4)  2 call: ancestor(david,_0) ? 
   (5)  3 call: parent(david,_0) ? 
   (5)  3 exit: parent(david,harold)
   (4)  2 exit: ancestor(david,harold)
   (1)  1 exit: ancestor(alison,harold)

X = harold ;

Prolog first calls ancestor(alison, _0) (where \_0 is Prolog's internal variable name), and calls the subgoal, parent(alison, _0). This succeeds, so exits which results in ancestor(alison, _0) exiting with ancestor(alison, david). When bactracking is forced, Prolog retries ancestor(alison, _0), and starts by redoing parent(alison, _0), which exits with parent(alison, kathleen). ancestor(alison, _0) therefore also exits. Forcing backtracking again, Prolog retries (again) ancestor(alison, _0). Retrying parent(alison, _0) fails - there are no more facts matching this. So using the second ancestor rule it calls parent(alison, L103) (where L103 is an internal Prolog variable). This succeeds, so using the second subgoal of rule 2 it calls ancestor(david, _0). This succeeds (exits) with parent(david, harold), so the second call to ancestor exits, and so does the first.

Prolog trace facilities, while all looking something like the above, vary a fair amount between implementations. Eventually you will have to get to know the foibles and peculiarities of your favourite Prolog's trace facilities. For now, just try tracing a few simple predicates and see if you can follow what's going on.




Next: Exercises: Up: Recursion Previous: Recursion


alison@
Fri Aug 19 10:42:17 BST 1994