JACK——TeamsManual1 Overview

来源:http://aosgrp.com/

 

1 Overview

 

1.1 Background

JACK Teams™ (Teams) is an extension to JACK Intelligent Agents that provides a team-oriented modelling framework. As Teams builds upon the concepts of JACK, this document assumes that the reader is familiar with JACK Intelligent Agents. It also assumes that the user is familiar with the use of JACOB for initialising data.

The most immediate difference between Teams and JACK is the introduction of the team reasoning entity. This entity encapsulates team behaviour in a Teams application in the same way that the Agent entity encapsulates agent behaviour in a JACK application.

Like a JACK agent, a team is also an individual reasoning entity with its own beliefs, desires and intentions (BDI). It includes declarations regarding which roles the team itself may perform for other teams and which roles it offers to other sub-teams to fill. In addition to the normal knowledge-building and practical reasoning in JACK agents, team reasoning is also concerned with the coordination of sub-teams.

As with JACK, behaviour is specified in the form of plans. Teams introduces the teamplan construct for the specification of team-oriented behaviour. Because Teams is an extension of JACK, all the core functionality of JACK is available within a team. In particular, a team can use JACK plans as well as teamplans.

 

1.2 Team-Oriented Programming

The Teams extension provides a team-oriented modelling framework. Team-oriented programming is an intuitive paradigm for engineering group action in multi-agent systems. Team-oriented programming is conceptually powerful, as it allows the software engineer to specify:

  • What a team is capable of doing;
  • Which components are needed to form a particular type of team;
  • Whether a team is willing to take on a particular role within another team;
  • Coordinated behaviour among the team members; and
  • Team knowledge.

In short, the concept of team-oriented programming serves to encapsulate coordination activity. It extends the agent concept by associating tasks with roles. However, the flexibility of multi-agent systems is retained. Although team members act in coordination by being given goals according to the specification, they are individually responsible for determining how to satisfy those goals.

A team's structure can contain teams in any combination and in any number. The hierarchy is not restricted to a two-level design or in fact to a hierarchy. Layers of teams can be encapsulated within other levels, and the structure can be added to or altered at any time during the process. In other words, teams can be created in many layers, where each layer is encapsulated within the next layer, and so on.

Both conceptually and explicitly in a model, teams entities exist independent of their team members. For instance, teams can reason about how they belong as members in enclosing teams, or about which teams they include as sub-teams. The teams concept encapsulates coordination activity, and extends the agent concept by associating tasks with roles.

 

1.3 Team-Oriented Concepts

The Teams extension introduces the new concepts of team, role, teamdata and teamplan. The Teams Model includes all the programming elements of the JACK BDI Agent Model, but with an extended semantics for some elements. Agents compiled under the JACK BDI Agent model and teams compiled under the Teams Model can communicate as peers. However, problems may arise if agents compiled under the JACK BDI Agent Model are used as elements of a team.

1.3.1 Team

In Teams, a team is a distinct reasoning entity which is characterised by the roles it performs and/or the roles it requires others to perform. The formation of a given team is achieved by attaching sub-teams capable of performing the roles required by the team. Note that a sub-team may be attached to more than one role in a containing team and as a sub-team in many teams. As the sub-teams of the given team may require roles to be performed on their behalf, a multi-level hierarchy (or perhaps a more complex structure) may result.

The team is automatically provided with objects to hold the actual role/sub-team selections. These objects are known as role containers.

1.3.2 Role

A role in Teams is a distinct entity which contains a description of the facilities that the participants in a team/sub-team relationship must provide. A role defines a relationship between teams and sub-teams. The role relationship is expressed in terms of the goal and belief exchanges implied by the relationship.

1.3.3 Teamdata

Teamdata is an addition to the JACK data model concept for change propagation declarations. This allows propagation of beliefs from team to sub-team and vice versa. A teamdata element defines how a propagated belief is accepted by the receiving team, and incorporated into its belief structures.

1.3.4 Teamplan

A teamplan specifies how a task is achieved in terms of one or more roles. It typically contains steps determining which of the sub-teams nominated to perform the roles will in fact perform each role (a process known as task team formation). It also dictates the steps directing each sub-team to achieve specific goals.

Teams provides additional constructs to support both activities (the establish reasoning method and the @teamAchieve statement). The JACK @parallel statement supports non-sequential coordination of sub-team behaviour. As team behaviour embodied in a teamplan is specified in terms of roles, it is decoupled from the actual sub-team behaviour. Thus team behaviour can be specified and understood independently of sub-team behaviour.

 

1.4 The Team Framework

1.4.1 Structure
1.4.1.1 Teams and Roles

A structural relationship between teams is catered for via the role concept. A role defines the means of interacting between a containing team (a role tenderer) and a contained team (a role performer or role filler). The role defines which goals the role tenderer may request the role performer to achieve, and it also defines the counter-goals that the role performer may require from the role tenderer.

The team-role structure is defined by statements specifying which roles a team can perform, and which roles must be performed by sub-teams. These declarations are specified in the team's type definitions, where the containing team requires certain roles to be filled, and the contained team must be able to perform certain roles.

A team can perform roles for a containing team and can also contain sub-teams which perform roles on its behalf. The sub-teams can in turn contain sub-teams which can perform roles on their behalf etc.

The following code segments illustrate how these team and role definitions may look.

    team Company extends Team {
        #performs role CompanyRole;
        // minimum of 3 PlatoonRole fillers required. No upper limit
        #requires role PlatoonRole platoons(3,0);
        // exactly 1 Commander role filler required
        #requires role CommandRole command(1,1);
        // 0 or more ScoutRole fillers required
        #requires role ScoutRole scout(0,0);
           :
           :
    }
 
    role PlatoonRole extends Role {
        #handles event Movement m;
        #posts event Withdraw w;
          :
          :
    }
 

In the above example, role definitions for CompanyRole, CommandRole and ScoutRole would also be required.

The team-role declarations determine which team-team structures can be built at run time.

1.4.1.2 Role Definition

The role definition does not contain implementation – only a description of the facilities that the two participants in the role relationship must provide. A role definition has two parts: first, a downwards interface that declares the events an entity must handle to take on the role, and second, an upwards interface that declares the events the team entity requiring the role needs to handle.

A role definition, such as the PlatoonRole definition shown above, results in two Java classes being generated by the compiler. One is named by the given RoleType type. The second generated class is a specialised 'container' for instances of a RoleType called RoleTypeContainer. The latter is referred to as a role container, as its purpose is to contain RoleType objects. In the case of the PlatoonRole definition shown above, the compiler would automatically generate the two Java classes PlatoonRole and PlatoonRoleContainer.

When the declaration is made that a team requires a given role, the result is a role-defined container to be filled by sub-teams. The #requires role RoleType reference(min,max) statement adds a field to the team class of name reference and type RoleTypeContainer. The #requires role declaration allows the specification of bounds for the container, which results in team formation constraints.

The arguments min and max in the #requires declaration specify the lower and upper bounds for the number of performers in order for the team to be considered formed. A zero upper bound dictates an unlimited upper bound. Note that these bounds are not enforced by the infrastructure in order to allow dynamic attachment/detachment of sub-teams. In practice, a role container can contain an unspecified number of role objects.

In the team definition illustrated above, the declarations state that a Company team requires three sub-teams able to perform the PlatoonRole role, another sub-team able to perform the CommandRole role, and one or more sub-teams able to perform the ScoutRole role. Furthermore, the Company team is declared to be a performer of the CompanyRole role, which would be a role required by some other team type.

It should be noted that the declarations above define how an actual team structure may look, but they do not identify the actual team instances, or what the team types are in the actual team structure.

1.4.1.3 Team Formation

The overall lifetime of a team has two phases. The first phase is for setting up an initial role obligation structure. The second phase constitutes the actual operation of the team.

At run time, teams undergo a team formation phase intended to identify the particular sub-team instances that take on roles in a team. This first phase is initiated via a TeamFormationEvent that is posted by the kernel when each team is constructed. By default, the TeamFormationEvent is handled by a plan that identifies the role fillers according to an initialisation file in JACOB format. The following is an example of an initialisation file:

 <Team :name "company 1"
   :roles (
      <Role :name "hq" :type "Command"
         :fillers (
            <Team :name "cmdgrp 8">
         )
      >
      <Role :name "unit" :type "Subordinate"
         :fillers (
            <Team :name "platoon 1"
               :roles (
                  <Role :name "hq" :type "Command"
                     :fillers (
                        <Team :name "cmdgrp 23">
                     )
                  >
                  <Role :name "unit" :type "Subordinate"
                     :fillers (
                        <Team :name "section 1">
                        <Team :name "section 2">
                        <Team :name "section 3">
                     )
                  >
               )
            >
         )
      >
      ...
   )
 >

The Teams framework is flexible at this point, but it includes the notion of a fully formed team as a team for which all necessary role performers have been identified.

The framework will allow a team instance to complete its team formation phase without necessarily satisfying all the role filling constraints. However, the team will only be considered formed when its role containment constraints are all filled. This is a state that a program may query.

At this stage the initial role obligation structure has been constructed. It is possible to dynamically modify this structure during program execution. This is discussed in the chapter on Team Formation.

1.4.1.4 Task Teams

Task teams are dynamically formed sub-groups within a team, created to perform a team task. When chosen to handle an event, the initial step of a teamplan is to establish the task team, by selecting which role performers to use from within the team for the various roles needed within the task/plan.

Task teams are not defined separately, but are contained within the teamplans defining the team tasks. A teamplan uses #requires and/or #uses declarations to declare the roles needed for the task team. The teamplan may also include an establish() reasoning method that defines how the task team is to be established for the task. This is illustrated in the code segment below:

    teamplan CompanyFormationMove extends TeamPlan {
        #requires role PlatoonRole platoons as left;
        #requires role PlatoonRole platoons as right;
        #requires role PlatoonRole platoons as depth;
        #requires role CommandRole command as hq;
 
        #reasoning method
        establish()
        {
            // code to establish the task team for the task
        }
 
        body()
        {
           // body of the plan to perform the task
        }
    }

The establish step of a teamplan is a proper plan step, and may involve any amount of reasoning by the team entity, as well as negotiations with the candidate sub-teams. The outcome is either a complete assignment of sub-teams to the roles required by the teamplan, or a plan failure allowing the team to choose an alternative plan for handling the same event. If there is a fail() reasoning method associated with the plan, it does not get executed if the establish() method fails.

There is a default establish() method which fills the required roles uniquely at random, if possible. However, the default establish method only assigns the #requires roles and not the #uses roles.

1.4.2 Behaviour

The concepts of teams requiring roles and teams performing roles provide a framework where group behaviours and individual behaviours can be clearly separated. Group behaviour is specified in terms of the roles that are required to achieve the desired behaviour. This behaviour is specified independently of the actual teams performing the roles. However, the team has access to its sub-teams through the role container, so it is able to perform reasoning based on the actual team membership when necessary.

The team is a separate entity and has its own teamplans for the specification of team behaviour. Within these teamplans, the @teamAchieve statement can be used to help coordinate the behaviour of the sub-teams.

@teamAchieve

The @teamAchieve statement is used to activate a sub-team by sending an event to the sub-team. The team that sent the @teamAchieve then waits until the event has been processed by the sub-team.

In combination with the JACK @parallel statement, a wide range of team behaviours can be implemented.

1.4.3 Belief Propagation

In addition to communicating via the normal message/event passing in agent-oriented programming, Teams also provides a capability for the propagation of team beliefs. This propagation can be both from team to sub-team and from sub-team to team. In the latter case, the capability is provided within Teams to combine the propagated sub-team beliefs within the team. The use of Team beliefs in conjunction with the Team coordination statements enables sophisticated team behaviours to be implemented.

 

1.5 Example: Martian Visitors

This is a simple example to illustrate the basic steps in building a team containing several sub-teams. In this example, a team of Martians are coming to visit Earth.

The team will be contained within a spacecraft which will travel to Earth. Each spacecraft contains at least 3 sub-teams (Martians) capable of performing the role required to pilot the spacecraft. It also contains 3 Martians capable of carrying out the duties performed by a basic crew member, and 3 capable of performing the task of spokesperson when the craft arrives at its destination.

In reality, only one Martian allocated to each of these roles is required when the spacecraft performs the task of visiting Earth. However, 3 Martians are specified per role to ensure that there are backup teams, in case any Martian becomes unavailable.

In this example, the spacecraft contains 3 Martian sub-teams. Each of the Martian sub-teams is capable of performing each of the 3 roles in spacecraft team's role obligation structure. This means that in practice a Martian sub-team could be responsible for more than one role in a task team. However, in this example, the establish method ensures that each Martian sub-team is only allocated to one role in the task team.

The steps involved in building this application are as follows:

Step 1: Create the two team types

    Spacecraft.team
 
    public team Spacecraft extends Team {
 
        #requires role Spokesperson sp(3,3);
        #requires role Pilot pi(3,3);
        #requires role Crew cr(3,3);
 
        #uses plan Visit;
 
        #handles event PerformVisit;
 
        public Spacecraft(String name)
        {
          super(name);
        }
 
        #posts event PerformVisit pfv;
        public void visit(String planet)
        {
          postWhenFormed(pfv.visitPlanet(planet));
        }
    }
 
    Martian.team
 
    public team Martian extends Team {
 
        #performs role Spokesperson;
        #performs role Pilot;
        #performs role Crew;
 
        #uses plan SpeakGreeting;
        #uses plan Travel;
        #uses plan WatchMonitor;
 
        public Martian(String name)
        {
          super(name);
        }
    }

The team definitions are very similar to the definitions for a JACK agent, except that the keyword team is used, and the Team class is extended. Most of the declarations contained in these team definitions should already be familiar from previous JACK agent programming.

The new declarations illustrated here are #performs role and #requires role. As previously discussed, this specifies that a spacecraft must contain 3 sub-teams capable of performing the role of Spokesperson, 3 sub-teams capable of performing the role of Pilot, and 3 sub-teams capable of performing the role of Crew. These could be 3 entirely different sub-teams for each of the roles or there could be overlap. In this example, there are only 3 Martians within the spacecraft team and each is capable of performing all 3 roles.

The Spacecraft team definition also includes a visit method which posts a PerformVisit event using the postWhenFormed method. The postWhenFormed method puts the event in a special queue so that it gets posted asynchronously when the team has completed its team formation phase and built the initial role obligation structure.

The Martian team contains #performs role declarations to indicate that teams of this type are capable of performing the roles Spokesperson, Pilot and Crew.

Step 2: Create the main Java program and the initialisation file

Step 2.1: Create the main Java program

The main Java program must construct instances of the spacecraft and Martian teams. These will be the instances attached to the specific roles in the initialisation file. In the main program, the sub-teams must be constructed before the containing team, so that they already exist when the containing team attempts to build its role obligation structure.

 
public class AlienProgram {
 
    public static void main(String [] args)
    {
        new Martian("Dennis");
        new Martian("Ralph");
        new Martian("Jacquie");
        Spacecraft spacecraft = new Spacecraft("Enterprise");
        spacecraft.visit("Earth");
    }
}

Step 2.2: Create the initialisation file

In this example, it is assumed that this initialisation file is called scenario.def. It contains the following:

 
    <Team :name "Enterprise"
        :roles (
           <Role :type "Spokesperson" :name "sp"
                 :fillers (
                    <Team :name "Dennis@%portal" >
                    <Team :name "Ralph@%portal" >
                    <Team :name "Jacquie@%portal" >
                )
           >
           <Role :type "Pilot" :name "pi"
                 :fillers (
                    <Team :name "Dennis@%portal" >
                    <Team :name "Ralph@%portal" >
                    <Team :name "Jacquie@%portal" >
                 )
            >
            <Role :type "Crew" :name "cr"
                  :fillers (
                     <Team :name "Dennis@%portal" >
                     <Team :name "Ralph@%portal" >
                     <Team :name "Jacquie@%portal" >
                )
            >
        )
    >

Note the relationship between the names of instances and roles in the main program and in the team definitions in the initialisation file. Also note that the team names are in the form name@%portal and that if your application is organised into packages, then the package details must be included in the type specifications.

Step 3: Create the role definitions files

There are 3 role definition files required in this example. They are:

 
    Crew.role
 
    public role Crew extends Role
    {
      #handles event DoWatch wm;
    }
 
    Spokesperson.role
 
    public role Spokesperson extends Role
    {
      #handles event DoGreeting dg;
    }
 
    Pilot.role
 
    public role Pilot extends Role
    {
      #handles event PilotCraft st;
    }

In all three cases, these roles indicate the downward interface between a team that can perform that role and a team that requires a sub-team to perform that role. This indicates the events that will be posted from the containing Spacecraft team to the Martian sub-team capable of performing the role. This means that the Martian sub-team must have at least one plan capable of handling each specified event.

Role definitions can also include additional declarations which will be discussed in the chapter on Roles.

Step 4: Create the events

 
    DoGreeting.event
    event DoGreeting extends MessageEvent
    {
        String planet;
        #posted as
        speakGreeting(String p)
        {
          planet = p;
        }
    }
 
    DoWatch.event 
    event DoWatch extends MessageEvent
    {
        #posted as
        watch()
        {
        }
    }
 
    PerformVisit.event
    event PerformVisit extends MessageEvent
    {
        String planet;
        #posted as
        visitPlanet(String p)
        {
           planet = p;
        }
    }
 
    PilotCraft.event
    event PilotCraft extends MessageEvent
    {
        String planet;
        #posted as
        start(String p)
        {
           planet = p;
        }
    }

Step 5: Create the plans used by the Martian sub-teams

 
    WatchMonitor.plan
    plan WatchMonitor extends Plan
    {
        #handles event DoWatch dw;
        body()
        {
          System.out.println(getAgent().name()+" on watch");
        }
    }
 
    SpeakGreeting.plan
    plan SpeakGreeting extends Plan
    {
        #handles event DoGreeting dg;
        body()
        {
          System.out.println("Hello "+dg.planet);
          System.out.println("I am "+getAgent().name());
        }
    }
 
    Travel.plan
    plan Travel extends Plan
    {
        #handles event PilotCraft pc; 
        body()
        {
          System.out.println(getAgent().name()+" flying craft to "+
                             pc.planet);
          @waitFor(elapsed(10.0));
          System.out.println(getAgent().name()+
                             " arriving at "+pc.planet);
        }
    }

The 3 plans required are implemented as agent plans. This is because there are no sub-teams within the Martian teams, so there is no requirement to establish a task team to perform the task or for the new plan statements which enable coordinated activity between the sub-teams. Teamplans are only required when the plan requires sub-teams to perform roles on its behalf.

Step 6: Create the plan used by the spacecraft team

    import java.util.Enumeration;
    import java util.Vector;
 
    teamplan Visit extends TeamPlan
    {
        #handles event PerformVisit pfv;
        #uses role Spokesperson sp as speaker;
        #uses role Pilot pi as pilot;
        #uses role Crew cr as crew;
        #uses interface Team team;
 
        /**
         * establish the task team.
         */
        #reasoning method
        establish()
        {
            Vector busy = new Vector();
            crew = (Crew) pickRole(busy,cr);
            crew != null;
            pilot = (Pilot) pickRole(busy,pi);
            pilot != null;
            speaker = (Spokesperson) pickRole(busy,sp);
            speaker != null;
        }
 
        Role pickRole(Vector busy, RoleContainer rc)
        {
            for (Enumeration e = rc.tags(); e.hasMoreElements(); )
            {
                Role r = rc.find((String) e.nextElement());
                if (r.state == Role.ACTIVE &&
                               !busy.contains(r.actor))
                {
                     busy.add(r.actor);
                     return r;
                }
            }
            return null;
        }
 
        body()
        {
            System.out.println("Team established for craft: "
                               +team.name());
            System.out.println("  crew          = " + crew.actor);
            System.out.println("  pilot         = " + pilot.actor);
            System.out.println("  spokesperson  = " +
                                                     speaker.actor);
 
            @parallel(ParallelFSM.ALL,false,null)
            {
               @teamAchieve(crew, crew.wm.watch());
               @teamAchieve(pilot, pilot.st.start(pfv.planet));
            };
            @teamAchieve(speaker,
                               speaker.dg.speakGreeting(pfv.planet));
        }
    }

The spacecraft team has RoleContainer members (one per role that it has declared that it requires). In the teamplan the first task is to iterate through the appropriate role containers to select the particular role object to perform the required roles for a particular instantiation of the plan. This forms the task team for the plan. The role object selected will allow access to both the containing team and sub-team involved in the relationship.

The #uses role declarations indicate that within this plan three sub-teams are required – one to fill the role of Spokesperson, one to fill the role of Pilot, and one to fill the role of Crew. In this example, iteration to make a selection occurs through the respective role containers.

As this plan requires that each sub-team only be responsible for one particular role, a "busy" vector is used to keep track of which sub-teams are already allocated to roles. Each instance of a role has details about the containing team and the sub-team. The role's actor member contains the name of the instance of the sub-team that is capable of performing the role. The selection of sub-teams to perform specific roles for this task occurs in the teamplan's establish() method.

The RoleContainer base class contains a method (tags()) which returns its current role object tags as a java.util.Enumeration object. The role object tags relate to the role fillers or role performers and can be passed into the role container's find() method to return the Role object that corresponds to the tag.

In this example, the establish() reasoning method makes use of a method called pickRole(). The method begins by iterating through the required role container and then performing a find() to return the actual role object related to the tag. When selecting a suitable sub-team, it is a case of selecting the first role object which has a value of Role.ACTIVE, and which does not relate to a sub-team that has already been allocated (i.e. not already in the busy vector).

The test for Role.ACTIVE is not strictly necessary in this application as we do not have any dynamic attachment/detachment of teams in the role obligation structure. In this application, the formation of the role obligation structure will have been completed before the event is posted to activate the plan.

During the attachment/detachment of sub-teams to the role obligation structure, the role object can be in different states. The role object exists and is added to the container before the attachment handshaking between team and sub-team has completed; however, the sub-team may still refuse the attachment. Similarly, the role object exists, but is not active when the team has initiated a detachment process, because the sub-team may still be performing tasks in the role. The detachment cannot go ahead until the sub-team has finished all of the tasks in the role. The role object is marked as active when the role attachment procedure has completed, and before the role detachment procedure has started. If dynamic attachment/detachment is occurring in an application, it is not sufficient only to look at the presence of a role object to know whether or not the team it refers to is performing in that role, one should also test whether or not the role object is ACTIVE.

If the task team is successfully established, the plan body will be executed. This plan body illustrates how the @teamAchieve statement can be used in combination with the @parallel statement to coordinate the behaviour of the sub-teams. The @parallel statement operates like a control structure in which the body statements are executed as parallel tasks, while the @parallel statement itself is postponed until its termination condition holds. In this example, the arguments used in the @parallel statement are as follows:

mode: ParallelFSM.ALL
This means the @parallel statement will succeed after all the branches have succeeded, but fail immediately if any branch fails. All ongoing sub-statements will be notified on failure.
termination condition: false
This means that the abort mechanism is turned off and not used (i.e. there is no termination condition). This is discussed in more detail in the Agent Manual.
notification: null
This argument is for a user-defined Java exception object. If it is not null, the exception is thrown to active branches that are executing in parallel if they are required to terminate (i.e. if the termination condition is encountered). If there is no termination condition, as in this example, this can be null.

The @teamAchieve declaration is used to activate a sub-team (role filler) by posting an event to the sub-team. The team that posted the event using @teamAchieve waits until the event has been processed.

In the Martian Visit example, the first argument is the RoleType instance obtained from the RoleTypeContainer instance. The second argument is an event instance being sent to the sub-team. In the example, the events are constructed using posting methods from event factories accessed via the sub-team RoleType instances.

Step 7: Compile and run the program

Step 7.1: Compile the program

To compile the example:

    java aos.main.JackBuild -r -map=team

Step 7.2: Run the program

To run the program:

The team structure can be specified by using a Java property to specify an initialisation file that contains details of the teams. The most straightforward way of doing this is by associating a file to be read in with the Team.Structure property via the -D flag. In this example, the initialisation file was shown earlier. Assuming that the file is called scenario.def, the program runs as follows:

    java -DTeam.Structure=scenario.def AlienProgram

The output from the example is:

    Team established for craft: Enterprise@%portal
      crew          = Ralph@%portal
      pilot         = Dennis@%portal
      spokesperson  = Jacquie@%portal
    Ralph@%portal on watch
    Dennis@%portal flying craft to Earth
    Dennis@%portal arriving at Earth
    Hello Earth. I am Jacquie@%portal

你可能感兴趣的:(view)