Differences between revisions 4 and 5
Deletions are marked like this. Additions are marked like this.
Line 109: Line 109:
Percepts contain the global knowledge that the TR rule set shares with all the rules. The rule set is informed whenever the percepts change, depending upon the options used, this could trigger a new evaluation of the rules and therefore possibly a new rule to be run. The percepts in TrPonder is actually a PonderTalk Hash with some extra commands to enable it to communicate with the rule set.

Teleo Reactive Ponder2

Introduction

A teleo-reactive (T-R) program is a mid-level agent control program that robustly directs an agent toward a goal in a manner that continuously takes into account the agent's changing perceptions of a dynamic environment. T-R programs are written in a production-rule-like language and require a specialized interpreter [ ref ].

T-R programs typically have an ordered set of rules (a Rule Set) each of which contains a condition and one or more actions. The Rule Set then selects the first rule whose condition is true and starts executing the rule's actions. What follows afterwards depends upon the Rule Set's configuration and is described below.

Here is a simple example of a T-R rule set. It is for a robot truck that starts somewhere other than its depot. It's goal is to pick up a bin and put it down at the depot. When it starts off it may or may not be facing the bin (we assume that it is not next to it but that would work too). If it is not facing the bin then rule 6 would be invoked. If it is facing the bin the rule 7 would be invoked and it would move forwards to the bin.

So, if the rule set were continuously evaluated you can see that the truck would start turning to the left, then move forwards, pick up the bin, turn to the left again, go forwards and drop the bin off at the depot. This is bacause the lower numbered rules take precedence over the higher numbered ones. So, if rule 7 was being continuously executed then as soon as the truckwas facing the bin, rule 6 would take over and the truck would move forwards.

Rule

Condition

Action

1

unloaded & at depot

finished

2

loaded & at depot

unload

3

loaded & facing depot

go forwards

4

loaded

turn left

5

next to bin

load bin

6

facing bin

go forwards

7

turn left

Example Notes

  • Rule 7 is executed if the truck is not loaded and it is not at the depot and it is not facing the bin.
  • It would be more efficient if we had another rule with a condition asking if the bin were to the left or the right of the truck and to turn in the appropriate direction.

Rules

Rules have a condition and one or more actions. The rule can be asked if it is available to be run i.e. to evaluate its condition and return the result, true or false. The rule can also be told to execute its actions. A rule can handle two or more parallel sequences of actions, it does this by spawning off separate threads and waiting for them all to finish before indicating that its actions have been completed. Actions are normally blocks but may be Rule Sets or even other rules, more about this later, for the time being we will just use blocks. NB Conditions are likely to be run many times and at any time therefore condition blocks should not have any side effects.

A rule in PonderTalk is used as following:

Operation

Description

condition: aCondition

Creates a rule with the given condition block aCondition

condition: aCondition action: anAction

Creates a rule with the given condition block aCondition and the given action action anAction

condition: aCondition actions: anActionArray

Creates a rule with the given condition block aCondition and the given array of action in anActionArray

Example: Creating a new rule

Here we can see the TR rule factory being imported and then a new rule Managed Object is created with a condition that tests if myValue equals 23. Its action is a block that when activated moves the cart forwards. Notice that both the condition and action are blocks. Blocks are not executed when they are compiled but are activated later when needed; in this case, when the rule is told to evaluate its condition and when the rule is told to run it action(s).

   1 rule := root load: "TrRule".
   2 myrule := rule condition: [ myValue = 23 ] action: [ cart forwards ].

Once the rule has been created, more actions can be added to it, including parallel markers. The operations allowed on a rule are:

Operation

Description

action: anAction

Adds an action to the rule

actions: anActionArray

Adds an array of actions to the rule. The actions are copied from the array, the array is discarded

parallel

Indicates that any following actions are to be run in parallel with the previously given actions. This command may be used many times for multiple parallelism

Example: Adding to a rule

In this example actions are added to the rule. Blocks can be defined and held in domains or variables so these can be to reference them. We show here some blocks being created and then being given to the rule. NB Rules are not (yet) themselves thread safe so any one instance of a rule can only be used at any one time. Do not give the rame rule to different rule sets.

Here we can see that two threads will be started when the rule is run. One thread will move the cart forwards, left, right and then stop it. The other thread will, independently, make the cart go fast, then slow, then fast again.

   1 checkValue := [ myValue = 23 ].
   2 root/actions at: "forwards" put: [ cart forwards ]
   3 myrule := rule condition: checkValue.
   4 myrule actions: #( root/actions/forwards [cart left] [cart right] ).
   5 myrule action: [ cart stop ]; parallel; action: [ cart fast. cart slow. cart fast ].

The following examples are the same. The rule runs blocks b1, b3 and b4 in parallel. b2 is run when b1 finishes. b5 is run when b4 finishes. The rule finishes when all parallel threads have finished.

   1 myrule action: b1; action: b2; parallel; action: b3; parallel; action: b4; action: b5.
   2 // The following is the same as the preceeeding line
   3 myrule actions: #( b1 b2 ); parallel; action: b3; parallel; actions: #( b4 b5 ).
   4 // The following is similar but not identical
   5 myrule action: [ b1 value. b2 value ]; parallel; action: b3; parallel; action: [ b4 value. b5 value ].

Stopping Rules

Rules can be stopped using the stop command. This is normally done by the system not the user. However the user should be aware how the rule manages stop commands. If a stop is received, sends a stop to the currently running action(s) and then waits for them to terminate. Once they have finished the rule returns control to the requester. Blocks are atomic as far as PonderTalk is concerned and cannot be interrupted (and therefore don't receive the stop). This should be taken into account when designing the rule's actions. In the above example, if either of the first two rules are used then a stop could cause the rule to terminate without having either run b2 or b5 or even either. In the third example, since blocks are atomic, if the rule receives a stop command then the rule will wait until all three threads have run to completion i.e. even if b2 hasn't started it will still be run when b1 finishes before the rule returns control.

Rule Sets

Rule Sets are the heart of TR programming. A rule set is given an ordered set of rules which it then manages. The rule set, when started, asks each rule in turn f it can be run, the first rule to respond that it can, gets run. The rule set then proceeds from the top evaluating the rules over and over again. Each time the rules are evaluated, the top-most rule is run. If the top-most rule is the currently running rule (and it is still running) then that rule is simply left alone. If, however, a rule with a higher priority (higher in the ordered list of rules) than the currently running rule is ready to run then the currently running rule is told to stop, when it has stopped, the higher priority rule is run.

The TR program can behave in different ways depending on the way it is configured:

Constant Evaluation

In the strict sense of T-R programs, the Rule Set constantly reevaluates its rules' conditions. If a rule with a higher priority (earlier on in the ordered set) than the currently running rule becomes available to run then the currently running rule is stopped and the new rule is run.

No Interrupts

The Rule Set will not try to stop a currently running rule even if there is a higher priority ready available to run.

Run Once

The Rule Set can to told to run one rule and then terminate. This implies No Interrupts.

Run and Wait

The Rule Set can be told to run one rule and then wait for a new event to occur before re-evaluating all the rules' conditions.

Actions

Actions may be blocks of code, rule sets or even other rules.

Code Blocks

A code block is a non interruptible sequence of operations. If a long running action is to be made interruptible then it should be split into a sequence of actions then after one code block as finished the rule can be terminated before the next action is started. Conversely if there are several actions that should be atomic then they should be grouped into a single code block.

Rule Sets

Other Rules

If another rule is given as an action then it is simply told to execute its actions when the time comes. It's condition is ignored. This is useful if an action is to perform operations in parallel, then it can be described as a rule.

Percepts

Percepts contain the global knowledge that the TR rule set shares with all the rules. The rule set is informed whenever the percepts change, depending upon the options used, this could trigger a new evaluation of the rules and therefore possibly a new rule to be run. The percepts in TrPonder is actually a PonderTalk Hash with some extra commands to enable it to communicate with the rule set.

Examples

PonderTalk blocks can take arguments from a Ponder2 hash managed object. They can also merge the values from a hash into their environment variables before executing the block's code. This allows values in a hash to be used as plain variables without declaring them as arguments. Thia can make a program look more complicated because it is not always clear where values are coming from, however it help in the case of T-R programs because many examples assume the existance of global variables which this construct allows us to do.

   1 percepts at: "size" put: 5.
   2 rule condition: [ size == 5 ] ...
   3 
   4 Otherwise we would need
   5 rule condition: [ :size | size == 5 ] ...
   6 The rule runs this as:
   7 ruleCondition valueVars: percepts

???

Problems

There are a few problems inherent in the way that PonderTalk's blocks work. A block is a closure, that is it contains a copy of its environment at the time the block is created and so it is difficult to keep common information between blocks. This is where the usefulness of the percepts comes in. The copy of the environment is a shallow copy which means that only the values of the top level environment variables are copied not the objects that they refer to. Thus if a variable refers to a domain, then then new copy of the variable will refer to the same domain, in this way shared values can be facilitated.

   1 // Create a new hash
   2 var := #() asHash.
   3 var at: "size" put: 10.
   4 
   5 b1 := [ ... var at: "size" put: 12. ... var := 7. ..].
   6 b2 := [ ... root print: (var at: "size"). ... ].
   7 
   8 b2 value. // prints 10
   9 b1 value.
  10 b2 value. // prints 12
  11 
  12 b1 value. // error number does not understand "at:put:"
  13 b2 value. // prints 12
  14 
  15 var := 4.
  16 b2 value. // prints 12

After the blocks are created, the value of var is copied into each block but they still both refer to the same hash.

Download

The TrPonder zip file can be downloaded here. It should be unzipped inside your Ponder2 installation. It will create some files in src/net/ponder2 and some files in src/resource. To run the example use the build.xml file you already have in the Ponder2 installation:

ant run -boot trmaze.p2

TrPonder (last edited 2010-02-10 16:14:43 by KevinTwidle)