Page Numbers: Yes First Page: 1
Heading:
April 28, 1979 12:11 PM [IVY]<KRL>document>proc-pat-event
An Introduction to System events and responses
The description of the interpreter process so far has not included any place for the procedural parameterization provided by signals in KRL-0, or for the procedural attachment provided by traps and triggers. In KRL-1, these are thought of as specialized versions of a more general notion of responses to system events. At the most abstract level, we can imagine there being a global pool of productions (in the Newell and Simon sense). The pattern of each production is matched against each member of a running sequence of descriptions of the events going on in the interpreter. The action for each production specifies one or more operations to be added to the agenda whenever the pattern matches. Because the control structure is based on agendas, there is no restriction on the number of productions which can be activated by a single event. They all propose new agenda items, and it is up to the scheduler for the current agenda to decide where to add them and when to execute them.
Of course, in order to make the system run efficiently (or for that matter, at all), this cannot be implemented by actually producing all such descriptions and performing the matches. There would be an immediate infinite regress. However with the notions of indexing and compiling described below, we can produce a runnable system whose actions correspond to those which would be taken in the theoretical abstract case. In most of of this section, we will ignore these issues, and describe the system as if the production system were implemented literally. In parts 2 and 3 of this paper <chapter??>, we will deal with the specific syntax for specifying responses and the mechanisms used for implementing them.
The basic classes of event descriptions
In theory, a single production could specify any description whatever in its pattern. In actual use, it is useful to distinguish the information in the patterns into three major classes with several distinct subclasses corresponding to the mechanisms of KRL-0:
* Specifying only prototype descriptions for situations: This subclass corresponds loosely to signals in KRL-0. Patterns would be things like "Creating a new unit" or even "Parsing a syntactic form and running out without finding a matching right bracket". In KRL-1, these are thought of as descriptions of a situation, rather than as atomic signal names.
* Specifying details about the current process: The association of signal paths with individual processes (calls) in KRL-0 provided a means to have different actions for a single signal. In the production system metaphor, this would be done by having the pattern include a description of the process which is running as well as a description of what event is happening.
* Including specific process identity: The simplest case is one where the description says "the current process is X" where X is a specific instance of a process. This would correspond to having a signal table for each call.
* Including prototype descriptions for processes: Rather than specifying a specifc process, the pattern can say something like "The current process is a Match process with resource limitation, and its resources are now zero". This provides a generalization capability which is somewhat different from the scoping of signal tables into a path, and which seems to provide better structuring for having different processes share parts of the response set, while differing in other parts. The structuring is better because it is associated with explicit classifications of processes (using information which appears in their description) rather than the implicit scoping of the signal path.
* Specifying details about the operands: Many of the signals used in the KRL-0 Match and Describe functions were associated with specific patterns of arguments. In KRL-1 this case has been generalized to include traps and triggers as well.
* Including only prototype descriptions for descriptors: In some cases, the specific arguments involved are not considered in deciding whether to invoke a resonse, but a more general description of them is used. For example, there is a general event of "Adding a descriptor to a description", but we might want a specialized response to "Adding a descriptor which is a unit coreference to a description which already contains one".
* Including specific descriptor identity: If the pattern includes the specific identity of a descriptor, then the production corresponds to a trap in KRL-0. For example, a production might be looking for the event of "Any descriptor being added to description X", or "A unit-coreference being added to descripton X" where X is some specific description form in the knowledge base.
* Including identity of prototypes and slots involved in mappings: If the pattern includes the specific identity of a unit or slots used as prototypes in one of the descriptors involved in the system event, then the production corresponds to a trigger in KRL-0. For example, a production might be looking for the event of "Any mapping with X as the prototype being added to a primary description not already containing a mapping with that prototype", or "Any descriptor being added to a filler-pair with slot X in a perspective with prototype Y which appears at the top level of a primary description".
No overriding along the signal path
The descriptive information relating an entity to the result of a process can be used by any program (system or user-provided) at any time. The procedural demons are associated only with a small set of system events built into the interpreter. User-provided demons have to be set off by one of these events. <There is a mechanism for combining prouction-like rules into a discrimination net associated with an arbitrary pattern. This can be used for doing demon-like triggering on arbitrary event descriptions designed by the user. It might also be used for the implementation of the mechanisms described here>. The events represent
The set of responses is pre-compiled, using a general discrimination network mechanism.
Events:
* Modifying description
* Adding new descriptor
* Removing descriptor
* Changing current value
* Modifying primary description
* Adding new mapping
* Adding description to filler (including self)
* Adding coreference
* Adding pointer
* Adding other descriptor
* Augmenting set or sequence
* Changing current value
* Setting goals
* Find primary description
* Establish mapping
* Establish coreference
.
servants as demons in a search framework -- specialized interpretation in compiled cases
B.2. Description as a hook onto system events
KRL-1 is fundamentally a description system. Considered from a level 2 point of view (and level 2 is the point of view from which we want to think about most of the operations of the interpreter), the only things that exist in KRL-1 are descriptions and the anchors to which they are attached. A program in KRL-1 consists of some number of active processes which go around creating anchors and attaching descriptions. As a consequence of either creating certain anchors or attaching certain descriptions to certain anchors, these processes decide to create more anchors or to attach other descriptions to other anchors. And so on forever. In some sense there is nothing else that could happen; the acts of creation and description are the fundamental acts in the KRL-1 model of computation.
As a consequence of this, there are really only two kinds of system events in KRL-1. One event is the creation of an anchor, and the other is the attaching of a description to an anchor. Any action whatsoever that happens in the interpreter can be described in these terms. Hence we can define every trigger that we provide (or indeed that could possibly be provided) in terms of an anchor being created, or (which is in fact much more common) in terms of a description being attached to an anchor.
An analogy can be made to the PDP-10, where one could say that the fundamental act is changing a register (such as a memory location, the PC, an I/O status register, etc.). If somehow you could provide an arbitrary description of a register change in a PDP-10, including being able to say anything you wanted to about what register got changed, what it was changed to and from, and what the state of the rest of the machine was, and furthermore you were told that the machine would halt if it was ever going to change a register in the way you described, then you could catch anything that happened in that PDP-10. Nothing could slip by, because nothing else can happen in such a machine.
In a similar way, if you can catch any act of creation or description, you can catch anything that happens in KRL-1. This fact underlies the KRL-1 mechanism for procedural attachment. The idea is that if you want to specify a computational process to be run, what you do is to specify the act (or class of acts) of creation or description that you are interested in, and then also specify a procedure to be run at that point. The mechanism which allows you to do this is called a trigger. More precisely, when you specify a KRL-1 trigger you give the following two things:
1. A description of a system event, which includes a description of its type (which can be either an AnchorCreation or a DescriptionAttachment) and also a description of the process which is causing the event.
2. A description of a procedure to be run at that point.
In general, when you specify a description of the system event that should set off your trigger, you don’t want to catch just one single event, but rather any event which matches your description. For example you might want to define a trigger to be activated every time an entity is described with the perspective "A Dog". Hence in describing the class of system events that you want your trigger to respond to, there is an implicit universal of the form: "any time there is a system event which matches this description, do such and such ... ".
It would be nice if we could build the interpreter to run fast and to respond to any defineable trigger. However, since this is impossible, we are providing a set of standard triggers which the interpreter will know about, which are defined and explained below. Until further notice we make no guarantee that a trigger which describes some other type of system event will be set off at the appropriate times.
Whether a trigger is simple or complex, there is an issue regarding how to tell the interpreter that you want it to set off this trigger. In designing the language we have specified a convention which says that any trigger must be attached, in a footnote, to some anchor. This anchor is called the cataloguing anchor of the trigger. In general it will be one of the ones which figures in the description of the type of event being caught. For example there is a standard trigger that you can attach to a prototype unit (such as Friend) which will catch any occurence of someone being described as an instance of this prototype (i.e. with the persepctive "a Friend").
Different types of description are appropriate for describing acts of creation and acts of describing, but in specifying a trigger for either of them you technically have to give a process description, which must match the description of the process performing the described act. Normally, however, you want to catch the event no matter which process is performing it, and therefore the standard trigger functionals described below provide a process description which will match any process whatsoever. If you want to restrict the setting off of a trigger to a specific process you should use an expanded descriptor (i.e. not a functional) using the standard units described in Appendix D.
It might seem that specifying triggers to catch these two types of system events would provide the appropriate handles for triggers reminiscent of KRL-0’s WhenIdentified and WhenFilled, but that they wouldn’t be appropriate for cases dealing with matching and seeking (like ToFill or WhenMatched), or for catching acts of scheduling. However, because we are designing the KRL-1 intepreter primarily in KRL-1, the Match and Seek processes are themselves defined in terms of prototypical units for SeekGoals, MatchHypotheses, etc. When the interpreter tries to match two descriptions, it (effectively) creates an instance of a MatchHypothesis which has various fillerpairs filled in with the specifics of the case at hand. Therefore a trigger like WhenMatched can be defined to fire when, in a match process, an entity is described as an instance of a MatchHypothesis. The details of the standard triggers dealing with the Match and Seek processes have yet to be worked out, but they will all be formulated in these terms. Even if some of them are not implemented in this way, a description in this framework can uniquely specify what they should do, and will be the final arbiter in specifying their behaviour.
There is one final issue regarding triggers which is common to triggers of all sorts. When the procedure associated with a trigger is run, the LISP code often will want to know specific details about the particular event which has just happened, such as exactly what desciption is getting added to what anchor, etc. There is therefore a standard convention, honoured by the interpreter, that a distinguished standard unit called CurrentSystemEvent will always be defined when a trigger is run, which completely describes the circumstances of the current system event. For example, suppose in a given case the description form "a Dog with kind = Beagle" were being added to the self slot of a unit called Fido. Then the CurrentSystemEvent unit would have the following form, if this event caused a trigger to fire:
# CurrentSystemEvent
self: a SystemEvent with
type = a DescriptionAttachment with
anchor = SelfSlot(’Fido)
descriptionForm = \a Dog with kind = Beagle
process = ... some appropriate process description ...
Section B.3 describes particular standard triggers, and defines the appropriate general forms for defining triggers dealing with anchor creation and description attachment.
The descriptive information relating an entity to the result of a process can be used by any program (system or user-provided) at any time. The procedural demons are associated only with a small set of system events built into the interpreter. User-provided demons have to be set off by one of these events. <There is a mechanism for combining prouction-like rules into a discrimination net associated with an arbitrary pattern. This can be used for doing demon-like triggering on arbitrary event descriptions designed by the user. It might also be used for the implementation of the mechanisms described here>. The events represent
The set of responses is pre-compiled, using a general discrimination network mechanism.
Events:
* Modifying description
* Adding new descriptor
* Removing descriptor
* Changing current value
* Modifying primary description
* Adding new mapping
* Adding description to filler (including self)
* Adding coreference
* Adding pointer
* Adding other descriptor
* Augmenting set or sequence
* Changing current value
* Setting goals
* Find primary description
* Establish mapping
* Establish coreference
.
servants as demons in a search framework -- specialized interpretation in compiled cases
---from 2matchspecs---
System events and responses
The description of the interpreter process so far has not included any place for the procedural parameterization provided by signals in KRL-0, or for the procedural attachment provided by traps and triggers. In KRL-1, these are thought of as specialized versions of a more general notion of responses to system events. At the most abstract level, we can imagine there being a global pool of productions (in the Newell and Simon sense). The pattern of each production is matched against each member of a running sequence of descriptions of the events going on in the interpreter. The action for each production specifies one or more operations to be added to the agenda whenever the pattern matches. Because the control structure is based on agendas, there is no restriction on the number of productions which can be activated by a single event. They all propose new agenda items, and it is up to the scheduler for the current agenda to decide where to add them and when to execute them.
Of course, in order to make the system run efficiently (or for that matter, at all), this cannot be implemented by actually producing all such descriptions and performing the matches. There would be an immediate infinite regress. However with the notions of indexing and compiling described below, we can produce a runnable system whose actions correspond to those which would be taken in the theoretical abstract case. In most of of this section, we will ignore these issues, and describe the system as if the production system were implemented literally. In parts 2 and 3 of this paper <chapter??>, we will deal with the specific syntax for specifying responses and the mechanisms used for implementing them.
The basic classes of event descriptions
In theory, a single production could specify any description whatever in its pattern. In actual use, it is useful to distinguish the information in the patterns into three major classes with several distinct subclasses corresponding to the mechanisms of KRL-0:
* Specifying only prototype descriptions for situations: This subclass corresponds loosely to signals in KRL-0. Patterns would be things like "Creating a new unit" or even "Parsing a syntactic form and running out without finding a matching right bracket". In KRL-1, these are thought of as descriptions of a situation, rather than as atomic signal names.
* Specifying details about the current process: The association of signal paths with individual processes (calls) in KRL-0 provided a means to have different actions for a single signal. In the production system metaphor, this would be done by having the pattern include a description of the process which is running as well as a description of what event is happening.
* Including specific process identity: The simplest case is one where the description says "the current process is X" where X is a specific instance of a process. This would correspond to having a signal table for each call.
* Including prototype descriptions for processes: Rather than specifying a specifc process, the pattern can say something like "The current process is a Match process with resource limitation, and its resources are now zero". This provides a generalization capability which is somewhat different from the scoping of signal tables into a path, and which seems to provide better structuring for having different processes share parts of the response set, while differing in other parts. The structuring is better because it is associated with explicit classifications of processes (using information which appears in their description) rather than the implicit scoping of the signal path.
* Specifying details about the operands: Many of the signals used in the KRL-0 Match and Describe functions were associated with specific patterns of arguments. In KRL-1 this case has been generalized to include traps and triggers as well.
* Including only prototype descriptions for descriptors: In some cases, the specific arguments involved are not considered in deciding whether to invoke a resonse, but a more general description of them is used. For example, there is a general event of "Adding a descriptor to a description", but we might want a specialized response to "Adding a descriptor which is a unit coreference to a description which already contains one".
* Including specific descriptor identity: If the pattern includes the specific identity of a descriptor, then the production corresponds to a trap in KRL-0. For example, a production might be looking for the event of "Any descriptor being added to description X", or "A unit-coreference being added to descripton X" where X is some specific description form in the knowledge base.
* Including identity of prototypes and slots involved in mappings: If the pattern includes the specific identity of a unit or slots used as prototypes in one of the descriptors involved in the system event, then the production corresponds to a trigger in KRL-0. For example, a production might be looking for the event of "Any mapping with X as the prototype being added to a primary description not already containing a mapping with that prototype", or "Any descriptor being added to a filler-pair with slot X in a perspective with prototype Y which appears at the top level of a primary description".
The invocation of demons and servants
Although there was no syntactic means to specify the distinction, the signal actions, triggers and traps of KRL-0 were clearly divisible into two classes -- demons and servants. Demons were used for data-directed process invocation. They specified a particular condition (for example, adding a new description to a filler in a perspective), and when that condition occurred, the process (A LISP expression) associated with the demon was executed.
Servants were of two somewhat different types (with a fuzzy area in-between), value producers and action producers. Value producers were associated with specific situations in which a LISP value was needed from a computation. When that situation was recognized, the system would execute the body of the servant (a LISP expression) and its value would be used. For example, a commonly used trigger was ToFill, which was associated with a slot and whose value was a unit which in KRL-1 would be described as the result of a Seek with the initial description a slot perspective with that slot as its focus. Another frequent use of servants was in the signals associated with match routines. A signal was invoked, and the corresponding action was expected to return a value of Match, NoMatch, or Unknown.
Servants could also be invoked to perform an action (like a PRINT) without returning any value. The signals referred to as "notifications" fell into this category, as did some triggers. There was no systematic notion of how the value returned by a servant was related to the context in which it appeared. It was handled on a case by case basis, both for system- defined and user-defined servants. This in fact was one of the weakest points of the documentation. In order to find out what kind of result was expected from a servant, and what would be done with it, it was often necessary to find the place in the code where a signal was generated or a trigger or trap was probed.
In KRL-1, we have attempted to fit demons and servants into a more general framework, both syntactically and semantically. The "uniformization" can be described in several steps:
Statements of how LISP values are related to enities can be separated from procedural attachment for causing their use: Servants in KRL-0 really conveyed two kinds of information. One part was procedural: "When you have the goal X to achieve, do Y". The other part was really declarative, e.g.: "The thing which fills this slot is the value of the LISP expression Z". The merging of these two aspects led to a good deal of confusion about just what servants were, and how they related to other descriptions. If a user had a procedure, for example, which would produce an English summary of a description, he or she could choose between inventing a trigger ToSummarize, or a functional SummarizedBy whose argument was a LISP expression In the first case, a summary could be produced by probing the trigger, and in the second by evaluating the argument of the functional. Both would work, but there were subtle differences in how they were inherited. If the functional form was used, then the information was inherited normally like any other description. If the trigger form was used, then the information was inherited only if a further-specification hierarchy was established. System-probed servants could only be inherited by using further specification (this was in fact one of the major motivations for including the further specification mechanism).
In KRL-1, we have separated out the two kinds of information. The declarative part appears as part of the normal description structure (in the slot descriptions and self description of a unit, embedded at any level of nesting). The procedural part is expressed in footnotes. Traps are associated with pieces of the description structure (footnotes on descriptions) and triggers with unit structure (footnotes on units and slots -- see the point on indexing, below).
Servants are just demons triggered by the setting of goals: The framework of section 2.3 makes it possible to define servants and demons in terms of goals and operations in the interpreter. A demon can be viewed as saying: "If a situtation (an event happening in the interpreter) matching the pattern X is activated, then add to the agenda an operation Y". Some examples of situations which correspond to demons in KRL-0 are: the adding of a new descriptor to a description, the adding of a new perspective to a self-description, etc. Servants can be seen as a specialized case of this. Each servant can be viewed as saying: "If a goal matching the pattern X is added to the set of active goals in the interpreter’s data structures, then add to the agenda an operation Y".
In KRL-0, it was unclear what should happen if more than one trigger or trap were associated with a situation in which a servant was needed. Since servants were expected to return values, there was a clear one-need, one-provider situation. In the KRL-1 view, any demon can provide any number of operations to be added to the agenda. In the case of servants, it is expected that the operations suggested will help towards achieving the goal which invokes them. One of the standard things which can be suggested is "Take the action X on the description form Y" where the description form is one of the declarative forms relating a result to a LISP process which will produce it (like the ToSummarize example above). However, an operation suggested by a servant does not need to be related to the goal in a simple one-one value-producing way. It is quite reasonable for a KRL knowledge base to contain a number of servants for the same goal, some of which suggest operations likely (perhaps only in a loose heuristic sense) to lead towards progress, others suggesting operations which may affect scheduling priorities, etc. etc.
Triggers, traps, and signal actions are all just different ways of cataloguing the set of responses to system events: The opening of this section proposed the idea of a global "pool" of productions. The pattern on each production specified the details of the events for which it would respond. There are reasons to provide more structure to this pool, both for the implementer and the user. The implementer does not want to have to test any more patterns than absolutely necessary for each event. The user wants to organize his or her set of productions in a way which clarifies the conceptual structure of the knowledge base. Some of them are best thought of as generally associated with a specific system event, others as "belonging" to a particular procedure, others as belonging to a specific unit, or description.
The mechanisms of KRL-0 were primarily means of cataloguing responses in appropriate places. Signals were catalogued in a two level structure, first by association with an individual process, and within that by event prototype (signal name) <more discussion later on the notion of signal path>. Triggers were catalogued by unit and slot, and within that by event prototype (the name of the individual trigger, like WhenFilled). Traps were catalogued by the description on which they were to act, and within that by event prototype.
There were problems, however, raised by the confusion between this notion of cataloging, and the content which related the LISP values resulting from actions to the structures in which the responses appeared. One example was the difficulty of having a response to a condition of several slots in a unit being filled, or any one of a set of slots. In KRL-1 terms, the pattern wanted to specify a unit and a description of its state, where that description involved not one slot, but a set of slots. Another similar example (which Paul wrestled with extensively in the cryptarithemetic program) was a situation where the pattern specifies both a specific description (in trap style) and a specific unit and slot (in trigger style). Since KRL-0 insisted on one or the other, he ended up adding traps to triggers, and triggers to traps, then removing them once they had fired, etc., etc.
From this vantage point, we can view a "simple" trigger appearing in a slot (such as (ToFill (DoStuff.....))) as expressing four separate messages:
* Cataloguing: Don’t even think about this or waste time looking at it unless you are currently setting up a goal to find a filler for an instance of this particular slot in this particular unit.
* Pattern: Do the response in every case where you are currently setting up a goal to find a filler for an instance of this particular slot in this particular unit. In KRL-0 it was impossible for the pattern to contain anything other than the information used in cataloguing. This led to the problems mentioned in the previous paragraph.
* Action: The piece of LISP code
* Use of results: Implicit in the use of name ToFill is the information that the LISP value returned by running the code will be a pointer to a unit, and a coreference descriptor to that unit is the desired form to be added to the filler.
Signal tables also combined these four in a similar way. We want to maintain the ability to combine them when that will make the knowledge base smaller and clearer, but we have added the ability to specify them separately when that is appropriate. Section 2.?? describes the ways in which responses can be associated with units, slots, and descriptions using footnotes. Section 2.??? describes the association of responses with processes, and globally with event prototypes. This includes the ability to catalog user-generated events, as well as the built-in system events. Section 3.?? discusses the implementation of all of these, using discrimination networks.