(page created by Ben Goertzel, June 2015)
The basic problem called “execution management” in OpenCog lingo is: dealing with the dynamics, and interaction, of “long-running procedures.”
This page outlines a design that provides the basic needed representations for either simple or complex execution management, and describes how to do simple execution management within this framework.
See also: action orchestration.
Fast and Slow Procedures
Suppose we have a bunch of Atoms which represent “behavior trees” or “finite state machines” or other small procedures for controlling some agent.
Let us assume, for simplicity, that the Scheme or Python code invoked within GroundedSchemaNodes in these procedures is always “lightweight and fast.” That is, let us assume that if there is something expensive to be done, it’s done by having a GSN send a message somewhere else, where the expensive work will be done, and its result then sent back….
As concrete examples, consider the procedures A = Recite the Unabomber Manifesto B = walk forward till you hit a wall C = Answer someone when they say “hello” D = Look at someone when they talk to you
Executing A and B will each take quite a while. They could be broken down into chunks, i.e. into small actions like “say “the” “ or “take one step forward”, but this isn’t always the way things are going to work in practice. Sometimes we will be launching a more extended act, the most common/obvious example being uttering a whole sentence.
This suggests we may wish to consider GSNs as falling into two categories
- effectively instantaneous (i.e. fast enough we’re not going to worry about the possibility of the AI interrupting its action after it’s launched the action)
or, if we want to use a simpler terminology,
Representing and Manipulating the States of Slow Procedures
For a slow GSN, it may be worthwhile for the Atomspace to record information regarding whether the referenced schema is still being executed or not. So we may want something like
EvaluationLink PredicateNode “CurrentlyExecuting” ExecutionLink GroundedSchemaNode “say.py” SentenceNode “I am babbling some words, can you hear them?”
The CurrentlyExecuting predicate would then be removed once a signal was received from the external world indicating that the execution of the procedure was complete. (There is also the matter of handling the error case where the procedure-completed signal is never sent back to the Atomspace. In this case, there could be some process that replaces CurrentlyExecuting predicate with a ProblematicallyExecuted predicate or something, after a certain period of time….)
We will also also have use for
(to use e.g. if the recitation of the Unabomber Manifesto has been paused to say “Hello” to someone), and for
, which would execute its GSN argument, but resuming execution in the middle if execution had previous be paused in the middle.. more on this later…
Managing Simultaneous Execution of Multiple Procedures
Next, we will need a notion of exclusion between GSNs. For instance, you can’t really do A and C at the same time; and only sometimes would be able to do B and D at the same time….
An extreme approach would be to create explicit relationships between each two GSNs, indicating if they can be simultaneously executed: always, never or sometimes (“sometimes” meaning that the situation must be analyzed before choosing to do the two at once)…. But this is pretty inefficient in its quadratic complexity. In practice it seems that we can create groupings of GSNs, wherein we know that executing two GSNs in the same category will be problematic, or that executing one GSN in category X and another GSN in category Y will not be problematic….
For instance, two relevant categories might be
ConceptNode “Vocalization Schema” ConceptNode “Eye Movement Schema” ConceptNode “Mouth Movement Schema” ConceptNode “Locomotion Schema” ConceptNode “Cognitive Schema”
In this case we could have relations like
MemberLink ConceptNode “Vocalization Schema” ConceptNode “Mutually Exclusive Schema Set”
meaning that two vocalization schema, by default, can’t be done at the same time, or
EvaluationLink PredicateNode “Mutually Exclusive Schema Set” ListLink ConceptNode “Vocalization Schema” ConceptNode “Spitting Schema”
indicating that, generically, vocalization and spitting schema interfere with each other (so you can’t do them simultaneously)
We could also have “Mutually Exclusive” or “Non-interfering” predicates between individual schema where useful, though using categories whenever possible will be best…
Operationally, in order to use this sort of information, when considering a GSN S for execution, a control process would then check what other GSNs are currently executing (via the CurrentlyExecuting predicate), and check which of these conflicts with S according to a certain list of predicates (“Mutually Exclusive Schema Set”, etc.)….
If a conflict is found, then what? The right choice won’t always be to avoid doing the new action being considered. We also need the possibility of sending a signal to halt a currently running procedure. This could be done e.g. via
HaltExecutionOutputLink GroundedSchemaNode “blah.py” List args
or, in some cases,
PauseExecutionOutputLink GroundedSchemaNode “blah.py” List args ResumeExecutionOutputLink GroundedSchemaNode “blah.py” List args
Information about which GSNs are haltable and which are pausable will also be needed, e.g. via predicates
PredicateNode “is haltable” PredicateNode “is pausable”
Active Schema Pool
One more concept that we are missing in the current system is what prior OpenCog literature calls the “Active Schema Pool.”
Suppose, for example, that OpenPsi decides that to achieve a certain goal (say pleasing the human interaction-partner), it's valuable to execute the rule
IF the conversation-partner looks at some object X, THEN the OpenCog-controlled agent should look at object X
In the prior (now obsolete) OpenCog Embodiment module, we would have represented this as a Combo program with an internal conditional...
If we want to represent this in the Atomspace, as per the current more Atomspace-centric OpenCog style, then we would say this as something like
BindLink [handle = 123] AndLink InheritanceLink ConceptNode $P ConceptNode "conversation partner" EvaluationLink PredicateNode "look at" ConceptNode $P ConceptNode $X ExecutionOutputLink GroundedSchemaNode "look at" ConceptNode $X
The point is that in this case, what OpenPsi is triggering, as an estimated-OK way of achieving its goals, is an ImplicationLink representing a conditional (rather than directly triggering an ExecutionOutputLink).... This is going to be a general case since we will often see OpenPsi triggering execution of "complex procedures" with internal structure...
In this case, the ImplicationLink needs to be added to a "watch list" so that its precondition will be ongoingly checked. Otherwise its precondition might get fulfilled at some point and the system wouldn't notice.
This “watch list” is what has previously been called the the "ActiveSchemaPool" (ASP), but here it's taking the form of a set of ImplicationLinks (or could they be BindLinks? hmmm...)
Activating the Active Schema Pool
We could represent membership in the ASP via something like
MemberLink  ConceptNode "ActiveSchemaPool"
To actually make the elements of the ASP active, a couple options are possible.
We could have a MindAgent that frequently checks all the Atoms in the ASP to see if any of them is being triggered....
Or, another, alternate approach would be to do something like
BindTriggerLink ConceptNode "conversation partner"  BindTriggerLink PredicateNode "look at" 
In this case it seems the EvaluationTriggerLinks would need to be created and removed when the Atom  was inserted into, and removed from, the ASP.
See TriggerLinks for more details on this aspect...
Monitoring the Active Schema Pool
However, we don’t want membership in the ASP to be permanent.
So, the Atoms in the ASP must be ongoingly reviewed to see how well they fulfill the current goals ...
This monitoring could be expensive in principle, but this shouldn't be a problem issue in practice in the near term, since we're not likely to have a large number of active procedures at the same time.... Mostly what will happen is: As the importances of goals shift, the relevance of each active schema to the "currently important goals" will shift, and schema that are no longer worth pursuing in the context of the current set of goal-importances will get kicked off the watch list....
An alternative to the watch list would be to just boost the STI of the procedures we want to be frequently evaluated.... But I actually don't think this is a great cognitive model (even if ECAN worked really well.). In essence what I'm proposing here is a "procedural working memory" ...
Not much is known about procedural WM in humans, but anyway this is an aspect where OpenCog is fairly different from humans anyway, just due to different infrastructure...