JACK——AgentManual8 Meta-Level Reasoning

来源:http://aosgrp.com/

 

8 Meta-Level Reasoning

In order for an event to be processed by an agent, the agent must determine which plan (if any) should handle the event.


Note: Each plan is capable of handling only a single event type which is specified by the plan's #handles event declaration. However, it is possible that there is more than one plan capable of handling a particular event type. As will be discussed later, it is also possible for multiple plan instances to be generated from a single plan.


To decide which of the plans are applicable, JACK employs the following steps:

  1. Identify the plans which handle the event type.
  2. Use the relevant() method to eliminate plans on the basis of the data associated with the particular event instance.
  3. Use the context() method to generate plan instances which are consistent with the agent's current beliefs.

The last step results in what is known as the applicable plan set. Elements in the applicable plan set are ordered according to the order in which their corresponding plans were declared – this ordering is called prominence. This ordering can be overridden by a process called precedence, where a ranking is provided for each entry via the getInstanceInfo() method.

Having generated the applicable plan set for an event, one entry must be chosen for subsequent execution. Normally JACK will perform this selection, choosing either the first entry in the set, or choosing one at random. The exact mechanism used is tunable via behaviour attributes associated with the event (this is discussed in detail in the section Customising BDI Behaviour with Behaviour Attributes in the Events chapter). Note that when a choice is being made, only the highest precedence entries are considered. If the event is a BDI event and there is more than one entry in the applicable plan set, a PlanChoice event is posted. If plans are provided to handle this event (referred to as meta-level plans), the applicable set can be interrogated and the entry deemed most appropriate for the current situation selected. Note again that the available choices are restricted to the highest precedence entries – there may be additional entries of lower precedence, but they will be considered only when all entries of higher precedence have been exhausted.

 

8.1 Applicable Set Generation

8.1.1 Handling the Event Type

Most #- declarations are optional in a plan definition, but the #handles event declaration is mandatory. It specifies for which event type the plan type may be relevant. Whenever an instance of this event occurs, the agent will consider this plan as a potential candidate. Unless the plan's relevant() method indicates otherwise, the agent will assume that this plan is relevant to the event.

The #handles event declaration takes the following form:

    #handles event EventType event_ref;

event_ref is available within the plan to reference the event being handled and its data fields.

 

8.1.2 Relevance

To be relevant to a given event instance:

    1. a plan must declare that it handles the event type that has arisen through a #handles event declaration; and
    2. if a relevant() method is present, a value of true must be returned.

If a plan does not have a relevant() method, the plan is relevant for all instances of the event.

In the following example, the relevant() method ensures that the plan is only considered if there is a colour specified in the colour data member of the Paint event.

    public plan PaintSpecifiedCurrentColour extends Plan
    {
        #handles event Paint ev;
 
        static boolean
        relevant{Paint ev}
        {
            return ev.colour != null && ev.colour.length()>0;
        }
 
        // context method, discussed below.
 
        body()
        {
            // As appropriate to the plan
        }
    }
 
8.1.3 Applicability

The context() method provides the next level of 'filtering' after relevant(). If a plan is relevant to a particular event, the context() method determines whether the plan is applicable given the agent's current beliefs.

The context() method does not take any arguments and its body is always a single JACK Agent Language logical expression. Logical expressions are composed of boolean members, logical members and beliefset cursor expressions which can, in general, bind to multiple values. When evaluating the context() method, the agent will consider all possible alternatives. For every possible set of values that satisfy the context() method, a separate entry will be created in the applicable plan set.

In the following example, the context() method ensures that the plan is only applicable if the Paint event requests a specific colour that is the same as the agent's current paintColour.

    public plan PaintSpecifiedCurrentColour extends Plan
    {
        #handles event Paint ev;
 
        static boolean
        relevant(Paint ev)
        {
            // As appropriate to the plan
        }
 
        #uses interface Robot self;
 
        context()
        {
            self.paintColour.equals(ev.colour);
        }
 
        body()
        {
            // As appropriate to the plan
        }
    }

In the following plan, the context() method queries a BOM (Bill of Materials) beliefset using getSubcomponent(). The plan will only be applicable if the getSubcomponent() query can find a tuple with a key of component in the beliefset. Note that it is quite normal for a component to have more than one sub-component – if this is the case, entries corresponding to each sub-component will be added to the applicable plan set.

    public plan FindSubcomponentPlan extends Plan
    {
        #handles event FindSubcomponent fsc;
 
        static boolean
        relevant(FindSubcomponent fsc)
        {
            // As appropriate to the plan
        }
 
        #reads data BOM bom;
 
        context()
        {
            bom.getSubcomponent(fsc.component, sc);
        }
 
        body()
        {
            // As appropriate to the plan
        }
    }

As usual, only one plan instance will be attempted, and a second one is only tried if the first one fails.

 

8.1.4 Prominence

In the absence of precedence, the order in which plans appear in an agent or capability (the order of the #uses plan declarations) determines the order in which the corresponding entries appear in the applicable plan set.

For example, the agent below uses two plans. Prominence dictates that entries arising from PaintSpecifiedCurrentColour will appear in the applicable plan set before entries arising from PaintAnyColour.

    public agent Robot extends Agent
    {
            ...
 
        #handles event Paint;
 
        #uses plan PaintSpecifiedCurrentColour;
        #uses plan PaintAnyColour;
            ...
    }

Note that inner capabilities are more prominent than plans.

 

8.1.5 Precedence

Precedence is the second means of ordering entries in the applicable plan set. If a getInstanceInfo() method is provided in a plan when the entry for the applicable plan set is being generated, the getInstanceInfo() method will be called. getInstanceInfo() returns a PlanInstanceInfo object. The PlanInstanceInfo class has the following members and methods:

Name

Description

public static final PlanInstanceInfo def[]

An array of PlanInstanceInfo objects pre-constructed for ranks 0 – 9.

public PlanInstanceInfo(int)

For constructing an object with a given rank.

public int rank

The rank.

public int getRank()

Returns the rank.

Table 8-1: PlanInstanceInfo class members and methods

Note that a data member is available for holding a rank – the entries in the applicable plan set are ordered according to rank. In order to simplify the ranking process, an array of predefined PlanInstanceInfo objects (def[]) is provided. The array index corresponds to the rank – 0 is the lowest rank and 9 is the highest rank. For example, the following plan will have a rank of 4:

    public plan PaintSpecifiedCurrentColour extends Plan
    {
        #handles event Paint ev;
            ...
 
        public PlanInstanceInfo getInstanceInfo()
        {
            return PlanInstanceInfo.def[4];
        }
            ...
    }

If a second plan is now introduced:

    public plan PaintAnyColour extends Plan
    {
        #handles event Paint ev;
            ...
 
        public PlanInstanceInfo getInstanceInfo()
        {
            return PlanInstanceInfo.def[5];
        }
            ...
    }

then entries arising from the PaintAnyColour plan will always precede those arising from the PaintSpecifiedCurrentColour plan regardless of their prominence.

Note that getInstanceInfo() is executed after each binding of the context() method. Thus the current binding is available to getInstanceInfo() and can be used in determining the rank to be returned, as shown in the following example:

    public plan DoSomething extends Plan
    {
 
        #handles event SomeEvent ev;
        #reads data Order order;
        // BeliefSet "Order order(tag,precedence)" has tuples
        // of the form:
        //
        //   <"important",8>, <"normal",5>, <"background", 3>
        // and the incoming event includes a tag to match.
 
        logical int precedence;
 
        context()
        {
            order.get( ev.tag, precedence );
        }
 
        public PlanInstanceInfo getInstanceInfo()
        {
            try
            {
                return PlanInstanceInfo.def[ precedence.as_int() ];
            }
            catch (LogicException ex)
            {
                return PlanInstanceInfo.def[ 5 ];
            }
        }
            ...
    }

When context() results in multiple bindings (as could occur in the earlier BOM example), getInstanceInfo() is executed after each binding. Thus, each entry added to the applicable plan set could be assigned a different ranking.

 

8.2 The Applicable Plan Set

The applicable plan set is used to determine which plan instance of those applicable to the event under current consideration should be executed. A plan instance is defined by:

  • the plan type instance which is handling the event instance in question, and
  • a binding of logical variables arising from execution of the context() method.

Note that multiple plan instances may arise from a single plan type instance.

In order to facilitate reasoning about plan instances JACK provides the Signature class. It provides a representation which enables plan instances to be uniquely identified and efficiently compared for logical equivalence. Note that a signature does not contain a reference to the actual plan type instance – rather, it keeps all the information needed for re-establishing the plan instance.

The Signature class provides the following methods for use by the programmer:

Name

Description

public Event getEvent()

Returns the originating event.

public PlanInstanceInfo getInfo()

Returns the PlanInstanceInfo object associated with this signature.

public Plan getPlan()

Returns a 'plan factory' which can be used to determine the type of the plan concerned, and to access the logical plan variables associated with the plan.

Table 8-2: Signature class methods

One can gain access to the PlanInstanceInfo object that was returned by the plan's getInstanceInfo() method via the getInfo() method.

The ApplicableSet class extends the SignatureList class and one can therefore access the applicable plan set using the following methods:

Name

Description

public Signature first()

Returns the first signature in the list.

public Signature last()

Returns the last signature in the list.

public Signature next(Signature)

Returns the signature in the list after the one given, or null if the one given is the last signature.

public Signature prev(Signature)

Returns the signature in the list before the one given, or null if that given is the first signature.

public int size()

Returns the number of signatures in the list.

Table 8-3: Methods to access the applicable plan set

Thus, given a reference to the applicable plan set for an event, one can iterate through the Signature objects, inspect their corresponding PlanInstanceInfo objects and decide which signature is most appropriate for the current situation. Note that the applicable set only contains the highest precedence signatures – lower precedence signatures become 'visible' only after all higher precedence signatures have been used and failed.

If one is going to explicitly select a signature, additional information regarding the plan instances will invariably be required. This can be provided by extending the PlanInstanceInfo base class and then creating a suitable PlanInstanceInfo instance in the getInstanceInfo() method.

 

8.3 Choosing a Plan Instance

With normal events, the agent selects an entry from the applicable plan set for a given event and executes only the plan instance associated with that entry. As noted earlier, the mechanism used for selection (pick the first entry in the list or a pick an entry at random) is tunable via behaviour attributes associated with the event.

With BDI events, if the applicable plan set contains more than one entry, a PlanChoice event is posted. PlanChoice events are described in detail elsewhere; for the purposes of this discussion note that the PlanChoice class allows access to the following data members:

Name

Description

public Event event

Holds the object level event instance that caused the plan choice event.

public ApplicableSet applicable

Holds information about the current set of applicable plan instances.

public FailureSet failure

Holds information about the current set of failed plan instances.

public Signature chosen

Assigned by the plan choice handling plan.

Table 8-4: PlanChoice class data members

If the user has provided meta-level plans to handle the PlanChoice event, one uses the PlanChoice data members to reason about the applicable plan set and to determine which is the most appropriate plan instance in the current situation. This process is called meta-level reasoning.

A meta-level plan is defined to #handle the PlanChoice event. It may further include one or more #chooses for statements to constrain to which object-level events the plan is relevant. This is discussed in more detail in the section on Plan Declarations in the Plans chapter. The plan will also access the data members of the particular PlanChoice event instance.

These features are illustrated in the following simple example which prints "Hello World" in different languages. Each language is identified by a number (1 for English, 2 for Swedish ...) and each plan #handles an event of type TransEvent. This event has a single data member which contains the requested language number. The code for TransEvent is not listed but note that it must extend BDIGoalEvent. Meta-level reasoning is used to select the appropriate plan instance. Note that this example is for pedagogical purposes only – there are much simpler ways to achieve the same result.

     public class LanguageType extends PlanInstanceInfo
     {
         public int language;
 
         public LanguageType(int i)
         {
             super(5);          // 5 is the default precedence
             language = i;
         }
     }
 
     plan Trans1Plan extends Plan
     {
         #handles event TransEvent ev;
 
         public PlanInstanceInfo getInstanceInfo()
         {
             return new LanguageType(1);
         }
 
         body()
         {
             System.out.println("Hello World");
         }
     }
 
     plan Trans2Plan extends Plan
     {
         #handles event TransEvent ev;
 
         public PlanInstanceInfo getInstanceInfo()
         {
             return new LanguageType(2);
         }
 
         body()
         {
             System.out.println("Tjena Moss");
         }
     }
 
     plan ChooseLanguage extends Plan 
     {
         #handles event PlanChoice ev;
         #chooses for event TransEvent;
         body()
         {
             TransEvent te = (TransEvent) ev.event;
 
             for ( Signature s = ev.applicable.first();
                   s != null ;
                   s = ev.applicable.next( s )
                 )
             {
                 if ( s.getInfo() instanceof LanguageType )
                 {
                     LanguageType p = (LanguageType) s.getInfo();
                     if ( p.language == te.n )
                     {
                         ev.chosen = s;
                         return true;
                     }
                 }
             }
         }
     }
 

你可能感兴趣的:(agent)