Running the RAP System


1. The Task Agenda

The RAP task agenda is a simple structure bound to main-agenda*. You give the RAP system tasks to perform by installing them in the agenda. You can mess with the task agenda using the following commands:

(install-goal index priority deadline)
Add a task to the agenda corresponding to a RAP with the given index, with the given priority and deadline. Priorities and deadlines are positive integers.
(process-goal-agenda)
After any number of tasks are added to the agenda, this function will put the RAP interpreter running in a loop until no goals remain to be achieved.
(execute-goal index priority deadline)
Add a task to the agenda and then run. This is just a short form for (install-goal index priority nil) followed by (process-goal-agenda).
(dump-agenda)
Prints a list of everything waiting to run on the agenda.
(reset-agenda)
Removes all pending tasks from the agenda.

The usual way to run things is with execute-goal. A common way to get confused is to forget to do a (reset-agenda ...) after some RAP breaks or you interrupt LISP. In such a situation, tasks will be left on the agenda and the interpreter will try to run them next time you do an execute-goal. Be careful of this problem, it happens all the time.

2. The Memory

The RAP memory keeps track of a lot of stuff and it is updated automatically during primitive action execution. The standard assertion types that live in the memory are outlined below. Occassionally, the assertions in memory get out of sync with the world due to errors in RAP execution. You can start the memory fresh with the command:

(reset-memory)
You shouldn't have to do this on a regular basis but watch out when you start Truckworld up repeatedly. (Remember that restarting Truckworld requires doing a (initialize-raps) call or else the map data will be incorrect).

The RAP memory structure is bound to main-memory*. You can look at the contents of memory using:

(dump-memory (&key :assertion :expset))
With no keywords this function prints everything in memory. That can get a bit huge so adding the keyword :ASSERTION TYPE will print out all of the assertions starting with TYPE or the keyword :EXPSET LOC will print out the expectation sets that exist for location LOC.

A simple way to look at a particular fact in memory is to use the function:

(memory-ask query)
This function assumes that you are talking about main-memory* and prints the truth of the query along with variables bindings.

Stuff in memory is cross indexed under items as well. You can print out everything the system knows about an object using:

(dump-item item-name)

3. Show Level

While you are writing and debugging RAPs, all sorts of horrible things can happen. Here are some interpreter commands that you can use to help figure out what is happening.

(set-show-level :high)  [or :low :medium :extreme :hyper :memory :off]
By default, the interpreter prints out messages as it goes along so that you can see what it is doing. The default show-level for these messages is :low. The different sorts of messages you get at different levels are:
  :off     - No messages
  :low     - Top level goal selection
  :medium  - Primitive action calls
  :high    - Each task considered on the agenda
  :extreme - Every facet of each tasks consideration
  :hyper   - Detailed method selection and task agenda shuffling
  :memory  - All memory assert, erase, query calls
Play around with this.

4. Debugging: Goals, RAPs, and Breakpoints

You can always look at the current definition of a RAP with:

(dump-rap rap-index)
Within the system, RAPs are just used as little programs. The actual tasks driving the system are represented in structures called GOALs. The SHOW traces print out goals as #{Goal num}. You can look at a goal in detail with:
(dump-goal num)
Many times, when you want to see a goal, it has already succeeded or failed and been recycled. To help zero in on problems, there are two facilities: tracing and breaking. Tracing a RAP changes the SHOW-LEVEL every time a GOAL using that RAP comes up for execution. For example:
(trace-rap 'eye-scan-p)  - Increases the show-level to :hyper for eye-scan-p
To control printing more carefully, couple the RAP indices with the show-level you want:
(trace-rap '(eye-scan-p :high) '(arm-grasp-p :extreme) ...)
While these function help generate a lot of information, if you want to look at a goal, or the state of the task agenda, or something, you have to stop execution for a while. You can do this with:
(break-rap 'eye-scan-p)  - Stops execution when eye-scan-p is selected to run
You can control when the system will break (a standard, continuable LISP break), using the keywords: :run, :fail, :succeed. The default is :run but you can do:
(break-rap '(eye-scan-p :fail) '(arm-grasp-p :succeed) ...)
The :succeed and :fail keys cause a break only after a GOAL using the specified RAP runs and then succeeds or fails. The break will occur before the GOAL is recycled.

5. More Information

See the following documents for further information:
CS Home AI Home AI Projects RAPs Firby
Running the RAP System / R. James Firby / firby@cs.uchicago.edu
March, 1995