DCS 440 -- Undergraduate Introduction to AI

Getting Started With Prolog on Romulus/Remus


Contents
Setup
Writing Programs
Running Them
Stepping Through Them
Emacsing Them
Resources

Setup

In order to have the most congenial prolog environment to work with, there are a couple of changes that you need to make to some initialization files in your accounts.

First, you need to configure emacs to link up prolog files that you edit and the fancy operations we have for running and debugging prolog in emacs. If you don't have a file in your home directory called

.emacs
you must create one. (Remember to use the unix command
ls -a
to get a listing of files in your directory that includes the ones whose names begin with a dot.)

Add the lines

(setq load-path (cons "/igor/sicstus37/" load-path))
(setq prolog-use-sicstus-sd t)
to your .emacs file and save it.

Second, you need to let emacs know where prolog is on the romulus/remus system. If you don't have a file in your home directory called

.login
you must create one. Add the line
setenv EPROLOG prolog
to your .login file and save it.

Now emacs and prolog will be set up correctly the next time you log in. To get working in prolog immediately, exit emacs. In a shell, do the command

source ~/.login
Then run emacs from the shell - by
emacs &
Everything should now be cool.


Defining Prolog Programs

In prolog, data structures are specified by terms. Terms include constants for integers, like:

-53
constants for floats, like:
3.1415
and constant atomic symbols - strings beginning with a lower case letter, like:
broadway

Terms can also be variables, which are written as any sequence of alphanumeric characters (including _) starting with a capital letter or _.

Finally, terms can be compound. These have a function symbol (a string beginning with a lower case letter) and a number of arguments, such as

intersection(broadway,X)

There is a special notation for list terms. Expressions like

[t1 | t2]
are short for corresponding ones like
.(t1,t2)
and expressions like
[a,b]
are short for corresponding ones like
.(a,.(b,[]))

Prolog programs are made up of clauses. Clauses make statements about the objects named by terms. One kind of clause is a fact:

predicate(arguments).
A fact says that the relation corresponding to predicate generally holds of the objects named by the terms arguments.

The other kind of clause is a rule. A rule takes the form

head :-
b1,
b2,
...
bn.
head and each of the body expressions bi can have the same form as a fact - a predicate and some number of argument terms. This means that in general whenever all of the relationships specified in the body hold then also the relationship specified by the head holds.

In addition, as bodies, it is possible to use a number of builtin relationships whose intended meaning is part of the specification of the prolog language and where the prolog interpreter handles the goals specially. For example,

t1 = t2
requires two terms to be identical.
Var is expr
is true if expr is a mathematical expression (that is instantiated at the time prolog considers the goal) and the value of Var is (or can be set to) the value of the mathematical expression.
n1 > n2
tests whether n1 as a specific number exceeds the specific number n2 (again n1 and n2 must be instantiated at the time prolog considers this goal).


Running Prolog Programs

To run prolog in a shell, type

prolog
Prolog will start, and show you the interpreter prompt
| ? -
To load in the program at this point type
[filename].
For filename, you may type the name of the file itself if the name doesn't have any punctuation in it. Otherwise, you should enclose the name of the file in single quotes, to give a line like
['mydirectory/myfile.prolog'].
You need a period at the end - you may find yourself forgetting it, but you can always type it on a subsequent line of input. Prolog will print out where there are any syntax errors or will report that it consulted your file successfully.

Your program will describe a model of the world in terms of simple relationships that hold in a single case in that world and generalizations that hold across multiple cases. Now you can pose queries to the interpreter that ask about other relationships that might hold in the world that your program describes. For example, suppose your program includes a predicate mightDo (with one argument) so that mightDo(a) is true exactly when a refers to an action that your agent might consider performing given its task and the current state of the environment. Then you could use a query:

mightDo(X).
to look for all of the values of X that give actions that your program says the agent might do. (Don't forget the period again.)

When it finds an answer, prolog will give something like:

X = turnLeft ?
This indicates that your program has allowed prolog to prove that your agent might do the action associated with the symbol turnLeft. If you want to see what other instances of the query prolog can prove using your program, type a semicolon (;) at this point. To stop the query, just hit return.

If there are no (more) answers, prolog will come back with the response

no
Meanwhile, when you ask a query that doesn't contain any variables or when prolog finishes something successfully, it will come back with the response
yes

To stop prolog, type

halt.

Stepping Through Prolog Programs

Prolog comes with a debugging facility that allows you to inspect the search process for a query.

The most common thing to do is to trace through the search process, which you do by typing into the interpreter:

trace.
This allows you to step through each place where prolog considers each proof goal that arises as part of your program. There's the point where the goal is first raised - the call stage. Then there may be a point where the goal succeeds - the exit stage. There may be a point where prolog reconsiders the goal during backtracking - the redo stage. That may lead to other successful proofs and then prolog will revisit the exit stage. Eventually there are no more proofs available and this is the fail stage. At each point, for each goal, prolog prints out the goal so that you can see the instantiations that have been made to relevant variables and gives you a prompt so that you can consider alternative actions. Typing
notrace.
into the interpreter turns tracing off.

If you want to skip large chunks of the search space, it's often convenient to set spy points. These narrow prolog's attention to just a single predicate. It will zip ahead until a goal with this predicate is reached. Then there are commands that allow you to continue until the same goal is treated again or until another goal with this predicate is considered. You can get a listing of these options by typing h in the debugging prompt. To check out a particular predicate, type

spy predicate.
into the interpreter. To turn off a spy point, type
nospy predicate.
To temporarily turn off debugging (leaving the spypoints for later) type:
nodebug.
To turn debugging back on, type
debug.


Prolog in Emacs

All the things you can do in a shell, you can still do when you run prolog in emacs. But there are some shortcuts now.

If you type control-C control-f in the buffer with the file with your program in it, emacs will automatically start up a prolog interpreter if there isn't already one running. Then emacs will automatically give the prolog interpreter a command to load in the contents of that file.

You can use menu commands to do frequent tasks like starting debugging, interrupting the interpreter, loading in new definitions, etc.

When running prolog in emacs, it's easy to adapt and repeat queries. Just go back up to a previous line with a query in it and edit the line there. When you hit return, the revised query will be copied down to the last prompt that the interpreter spit out, and the revised query will automatically be fed to the interpreter there.

Once you have some interesting clause definitions loaded into a running prolog interpreter, turn on tracing. As always, the prolog interpreter will step you through the search process for your query. However, now emacs will bring up a new prolog source window. In that window, the clause definition from your program which the prolog search has currently reached will be highlighted. Plus, the line will be annotated so that you can see what stage of search prolog is working on.

  • When a line of code gives rise to a goal for the first time, the line is noted by
    >>>
  • When a line of code gives rise to a goal that's just been satisfied by being proved, the line is noted by
    +++ or ?++
    The question mark means that there are further alternatives for search for this goal, so this goal might be reconsidered later.
  • When a line of code gives rise to a goal that is being returned to after backtracking, the line is noted by
    <<<
  • Finally, when a line of code fails for the last time, the line is noted by
    ---

For More Information

The following books are good references for prolog programming if you get stuck - which I don't expect - or if you want to learn more about prolog than what the class requires - which may be more likely.

The full documentation for the prolog system on romulus/remus can be pulled up

Let me know what you consult this documentation for - so that I can update this page (both for this year and for future years) to make it more useful and comprehensive.