We will be running Sicstus Prolog 3.7 on the graduate server paul. The interpreter executable is located at /usr/local/bin/prolog. If you PATH variable includes /usr/local/bin/, then you should be able to launch the Prolog interpreter by typing prolog on the command line. WARNING: there are several Prolog interpreters on different machines in the department. Make sure that the first two lines printed after you launch Prolog are:
SICStus 3.7: Tue Sep 08 19:55:50 MET DST 1998 Licensed to cs.rutgers.edu | ?-to show that you are using Sicstus Prolog. Note that the interpreter is now ready for you to either type a query or to read in a Prolog program (i.e., some rules). At this point commonly, you load a file containing Prolog rules. This is accomplished as follows: [filename]. -- consults (or reads) the file named filename for input to the data base of Prolog rules. The system assumes that the file extension is .pl. For example, the Prolog program
memberof(A,[A|B]). memberof(A,[B|C]) :- memberof(A,C).in file mem.pl can be input as follows:
24 paul!programs> prolog SICStus 3.7: Tue Sep 08 19:55:50 MET DST 1998 Licensed to cs.rutgers.edu | ?- [mem]. {consulting /grad/users/ryder/prolog/programs/mem.pl...} {Warning: [B] - singleton variables in memberof/2 in lines 1-2} {Warning: [B] - singleton variables in memberof/2 in lines 2-3} {/grad/users/ryder/prolog/programs/mem.pl consulted, 0 msec 808 bytes} yes
The final yes indicates that a Prolog program has been input. The warnings are because the program could optimized by using a don't care variable for the B since it never appears on the righthandside of a rule.
Now if you want to see all the rules in the current database you use the listing command.
| ?- listing. file_search_path(library, A) :- library_directory(A). mem(A, [A|_]). mem(A, [_|B]) :- mem(A, B). library_directory('/igor/sicstus37/lib/sicstus37/library'). memberof(A, [A|_]). memberof(A, [_|B]) :- memberof(A, B). yes
Example Prolog programs that you can run can be found on paul in /grad/users/ryder/prolog/programs/*. Execution traces that correspond to these programs can be found in /grad/users/ryder/prolog/newtraces/*. The expected Prolog source file extension is .pl. All rules and facts with the same lefthandside predicate must be defined on the same file. Because the listing command needs filenames relative to your working directory, you first should connect to the subdirectory containing your Prolog programs before launching the Prolog interpreter.
The following commands are typed in at the Prolog prompt. listing. --creates a listing of the current data base of Prolog facts and rules.
[filename]. --``consults'' (reads) the file named filename for input to the data base; assumes that the file extension is .pl. Other files can be consulted by surrounding their full filename (with extension) in quotes.
When running Prolog, Control-c interrupts execution and results in the Prolog prompt for help. If you reply to the prompt h thus asking for help, the following choices are open to you:
Prolog interrupt options:
a abort - cause abort
b break - cause break
c continue - do nothing
e exit - cause exit
d debug - start leaping
z zip - start zipping
t trace - start creeping
h help - get this list
t will turn on a step-by-step trace of your execution (see below).
d turns on a ``skipping'' trace.
e allows you to exit from Prolog gracefully.
To trace a running Prolog program there are many options. You can trace the step-by-step execution of the program. You can trace the program, but skip some of the intermediate steps. You can watch just one predicate as the rules defining it are executed; this means execution procedes as normal until that predicate is hit and then step-by-step tracing begins and continues as long as a rule for that predicate is executing.
trace. --starts the step-by-step execution; end by the interrupt (Control-c Control-c) followed by e; if you specify notrace the trace is turned off.
spy(
Options: Return - single step trace
l - leap trace (allows you to skip over subgoals)
? - help
g - shows the ancestor list of current goals not yet satisfied
debug --starts the debugging. Normally this goes in steps larger size than the tracing steps. if you have set spypoints the output will show execution of those predicates. The manual calls this "leaping". The command nodebug turns off debugging.
The following informal discussion is to help you understand the meaning of the labels on the traces you are generating. It makes the most sense using the procedural semantics of Prolog.
Think of each Prolog function as a box containing all the rules with the same head. Each corner of the box is labelled with an arrow coming into the box (on the left) or leaving the box (on the right). The labels on the arrows are the same as the labels you see in the trace of a Prolog function.
If the Prolog function is recursive, then there is one box for each recursive invocation of the function (like copies of a recursive Pascal procedure). They are all labelled with the four arrows given above. If you trace a recursive computation, you can watch execution travel in/out of these boxes along these arrows. On the trace, the levels are numbered.
The following exerpt of a program was run on paul and traced as shown below. The annotations which follow the % on the right, were inserted after the run of the program.
{\bf Program Used:} SICStus 3.7: Tue Sep 08 19:55:50 MET DST 1998 Licensed to cs.rutgers.edu | ?- ['mem']. {consulting /grad/users/weileiz/Courses/cs515_2003f/prolog/programs/mem.pl...} {Warning: [B] - singleton variables in memberof/2 in lines 1-2} {Warning: [B] - singleton variables in memberof/2 in lines 2-3} {/grad/users/weileiz/Courses/cs515_2003f/prolog/programs/mem.pl consulted, 10 msec 808 bytes} yes | ?- listing. file_search_path(library, A) :- library_directory(A). %these clauses test the first arg for mem(A, [A|_]). %membership in the second arg; mem(A, [_|B]) :- %these use the ``don't care'' variable. mem(A, B). library_directory('/igor/sicstus37/lib/sicstus37/library'). memberof(A, [A|_]). memberof(A, [_|B]) :- memberof(A, B). yes | ?-trace. trace. {The debugger will first creep -- showing everything (trace)} yes {trace} | ?- | ?- mem(Z,[a,b]). 1 1 Call: mem(_246,[a,b]) ?%initial call of recursive clause. ? 1 1 Exit: mem(a,[a,b]) ? Z = a ? ; %successful return with A bound to a 1 1 Redo: mem(a,[a,b]) ? %forced re-execution by ; 2 2 Call: mem(_246,[b])? ? 2 2 Exit: mem(b,[b]) ? ? 1 1 Exit: mem(b,[a,b]) ? %successful return with A bound to b Z = b ? ; 1 1 Redo: mem(b,[a,b]) ? 2 2 Redo: mem(b,[b]) ? 3 3 Call: mem(_246,[]) ? 3 3 Fail: mem(_246,[]) ? %can't unify with [] 2 2 Fail: mem(_246,[b]) ? 1 1 Fail: mem(_246,[a,b]) ? no %report failure to user. {trace} | ?- Prolog interruption (h for help)? a {Execution aborted} | ?- Prolog interruption (h for help)? e %e was typed to exit. Process prolog finished Process prolog finished
[] the empty list
[1,2,3] list of 3 elements, namely, 1 2 and 3
[X|L] list whose first element is the variable X and whose rest_of_list is the list L
\+(P) :- call(P),!, fail. \+(P).where the call causes the predicate P to be evaluated. This is referred to as negation by failure in Prolog language descriptions.
var(X) succeeds when X is an uninstantiated variable
atom(X) succeeds when X is instantiated to a constant or a number
integer(X) succeeds when X is instantiated to an integer
number(X) succeeds when X is instantiated to a number
nonvar(X) succeeds when X is not an uninstantiated variable
length(L,N) if L is instantiated to a list, N gets the value of the number of elements in L; if N is a length, and L is uninstantiated, this creates a list L with the correct number of variable elements.
call(X) if X is instantiated to an atom or compound term, then that goal executes as if it appeared here. (i.e., this lets us create goals while running the Prolog program)
true a predicate that always succeeds
fail a predicate that always fails
Last edited by BGR at 4pm on September 19, 2005.