Projet

Général

Profil

Actions

MAY Tutorial V1 » Historique » Révision 5

« Précédent | Révision 5/6 (diff) | Suivant »
Anonyme, 26/07/2010 13:36


Make Agents Yourself Tutorial

% TODO : exemple complet, clair et qui colle au code
% ajouter utilisation objet commun à plusieurs composants (ou remplacé par un compo (Representation))
% retirer code généré !

Introduction

In this tutorial, we are going to see an introduction to MAY.

This tool was made to build application-specific models of agent and to generate dedicated framework providing them.
Such framework would then be usable to program agents compliant with the realised model of agent.

More specifically, a model of agent is realised by an architecture divided in two levels: "container" (the how), hidden to the user of the framework and "application" (the what) expression what the agent does.
These two levels links MuComponents together to form a MuArchitecture realising the model.

Furthermore, such agents have the possibility to self-adapt at runtime: currently, this means that a MuComponent is able to change the implementation of another MuComponent of the MuArchitecture.

In practice, these models are described with the help of the MuADL description language, and from this description, the Java code needed to implement the MuComponents is generated.
The MuArchitecture itself is generated and is directly usable by setting the implementation of its MuComponents.

This tool being experimental, several functionalities described are are subject to change in the future.
If possible, this will be stated in this document.

Requirements

To use MAY, the Eclipse IDE is needed.
It can be found at http://www.eclipse.org/.

Installation

The installation is done from the Software Update in Eclipse by adding the following Update Sites:

http://www.irit.fr/PERSONNEL/SMAC/noel/may/update/
http://oawbranch.pluginbuilder.org/releases/p2-updateSite/

Choose to install Make Agents Yourself.

Upgrades

When upgrades are available, just use the Update feature of Eclipse.

Typical Development Process of an Agent with MAY

As explained before, MAY is a tool usable to description MuArchitectures based on MuComponents to generate a framework that will be distributed to application developers.

Several phases in the development can be distinguished:

  • Description of the MuComponents and MuArchitectures:
    • Create a MAY project
    • Describe the model with MuADL
    • Generate the corresponding Java code
  • Implantation of the MuComponents with Java
  • Implantation of a Factory with Java
  • Generation of the distributable framework in the form of a JAR file

The following sections will describe in detail these development phases.
We will see the tools MAY adds to Eclipse, a description of MuADL and some advice to develop an agent and its MuComponents.

Added Tools to Eclipse

The tools proposed by MAY are the following:

  • Creation of a MAY project
  • Creation of a textual MuADL description file
  • Generation of the corresponding code in Java

A graphical editor is currently being worked on.

Creation of a Project

A MAY project is just a Java Eclipse project with supplementary dependencies, an empty MuADL description file and the required directories already created.

To create a new project, go to File menu, New, Project..., Make Agents Yourself category and choose MAY Project.
Follow the instruction.

Creation of a Textual MuADL Description File

The description of a model of agent is represented by a text file containing the description of MuComponents and MuArchitectures with MuADL (presented Sect.~\ref{muadl}).
The extension of these files is muadlt.
The editor features syntactic colouration, completion and validation of MuArchitectures.

To create a new MuADL file, go to File, New, Others..., Make Agents Yourself category and choose MuADL Text file.
Follow the instructions.

Generation of the corresponding code in Java

This action generates the classes required for the implementation of the MuComponents described in the MuADL file (the QuasiComponent), the class representing the mediator of the MuArchitecture and the class façade representing an agent compliant with the MuArchitecture.

To generate the corresponding code of a MuADL file (a file ending in .muadlt), do a right click on it and in the sub-menu Make Agents Yourself, choose Generate QC and Architecture.

The generated code will be in the src-gen directory.

It is important to notice that the content of this directory must never be modified.

MuADL: Description Language for Agent Architectures

As said before, MAY, using MuADL, make possible to describe:

  • MuComponents that: \todo{MuADL does not permit to specify how they will be implemented (no information of the constructors, the class attributes or private methods)}
    • Provides operations
    • Requires (from the MuArchitecture) operations
    • Requires (from the MuArchitecture) the possibility to change other MuComponents
    • Have a state that must be persisted by the MuArchitecture when their implementation is changed at runtime
  • MuArchitectures containing MuComponents and divided in two levels
  • Datatypes use by MuComponents and corresponding to Java types (classes or interfaces).

We detail here how to describe these elements.

DataTypes

To refer to Java types, we give them a name in the MuADL file.

The syntax is as following:

DataType AliasLocal : package.NomClass
DataType AliasLocal : package.NomClass<Generique>
DataType AliasLocal : package.NomClass<package.Generique>

// examples
DataType String : String
DataType Int : int
DataType Msg : my.package.Msg
DataType ListString : java.util.List<String>
DataType MailBox : java.util.List<my.package.Msg>

\todo{Currently, no verification is done on the existence of these classes}

It is important to understand that DataTypes are just aliases, they can't be used inside generics parameters.

MuComponents

Elements of a MuComponent :

  • A name
  • Provided operations (provided)
  • Required operations (required)
  • Attributes that must be persisted between runtime replacement of implementations (persistent)
  • A set of MuComponents whose implementation could be changed at runtime \todo{This point is likely to change in the future} (change)

The MuComponents operations are similar to Java methods: they have a name, ordered typed parameters and a return type.
To refer to a method, it is only needed to know its name, its ordered parameter types and its return type.

An example of MuComponent :

MuComponent Message {
  package a.test.package
  provided send(mess : String)
  provided receive() : String
  persistent mailbox : MailBox
  required do(String) : Int
  change LifeCycle
}

MuArchitectures

A MuArchitecture have:

  • A name
  • A set of MuComponents in the container level (container)
  • A set of MuComponents in the application level (application)
  • A set of visibility modifiers on th MuComponents operations (visibility)

The MuComponents can be specified as changeable (with changeable) by other MuComponents.
MuComponents can only change MuComponents of the same level.

By default, a MuComponent operation of the application level is visible by every MuComponents of the MuArchitecture, and a MuComponent operation of the container level is only visible by the MuComponents of the container level.
This fact can be changed by specifying (with application visibility) that an operation of the container level is visible in the application level.

An operation of the MuArchitecture can be specified as being available from outside of the agent (with external \todo{This is susceptible to change in the future}).

An example of MuArchitecture :

MuArchitecture MyAgent {
  package another.test.package
  container {
    changeable LifeCycle
    Message
  }
  application {
    Behavior
  }
  visibility {
    external Message.send(String)
    application Message.receive() : String
  }
}

Notice that :

  • If a MuComponent A requires an operation 0, then a MuComponent providing 0 must be present in the MuArchitecture.
  • Requirements are only validated in the MuArchitecture.
  • Two MuComponents can't provide the same operation.

Complementary Informations

MuADL allows for comments :

  // a comment
  /*
  a multi-line
  comment
  */

Implantation of MuComponents, use of MuArchitectures and Framework Distribution

After the Java code from a MuADL file was generated (see \ref{generation}), MuComponents implementation and MuArchitectures instantiation is possible.

The generation result in a set of Java classes situated in the src-gen directory.
To implement MuComponents, we will write Java classes (typically in the src directory) that extends some of these generated classes.

MuComponents Implementations

For each MuComponent X defined in the MuADL file, MAY generates a class QuasiComponentX and a class AdapterX.
The first must be extended to implement X.

For example, there is the two generated classes for a component LifeCyle:

public abstract class QuasiComponentLifeCycle
    extends QuasiComponent<AdapterLifeCycle>  {
  abstract public void suicide();
}
public interface AdapterLifeCycle extends Adapter {
  public void cycle(java.lang.String arg0);
  public java.lang.String receive();
}

Thus, by extending QuasiComponentLifeCycle, one can use the required methods of the MuComponent by using the architecture through the method this.architecture().

There is an example of this MuComponent :

public class LifeCycle extends QuasiComponentLifeCycle {
  private boolean alive = true;

  @Override
  public void start() {
    Runnable me = new Runnable() {
      public void run() {
        while (alive) {
          String msg = architecture().receive();
          architecture().cycle(msg);
        }
      }
    };
    new Thread(me).start();
  }

  public void suicide() {
    alive = false;
  }
}

The important points to notice are:

  • A method void start() is present to execute instructions at the start of the agent
  • this.architecture() gives access to required methods through the MuArchitecture

There is an example of a generated MuComponent with a persistent state:

public abstract class QuasiComponentMessage
    extends QuasiComponent<AdapterMessage>
    implements WithPersistentState<PersistentStateMessage> {

  abstract public void send(java.lang.String message);
  abstract public java.lang.String receive();
}
public interface AdapterMessage extends Adapter {}

When implementing it, one has access to the methods needed for the handling of the persistent state (automatically called by the architecture if the MuComponent implementation is changed at runtime).

There is an example of implementation for this MuComponent:

public class Message extends QuasiComponentMessage {

  private ArrayBlockingQueue<String> messageBox =
    new ArrayBlockingQueue<String>(100);

  public void send(String message) {
    try {
      messageBox.put(message);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

  public PersistentStateMessage getPersistentState() {
    return new PersistentStateMessage(
                new ArrayList<String>(messageBox)
           );
  }

  public void setPersistentState(PersistentStateMessage state) {
    messageBox =
      new ArrayBlockingQueue<String>(10, false, state.messageBox);
    System.out.println("Message Component started with "+
                        messageBox.size()+ " messages");
  }

  public String receive() {
    try {
      return messageBox.take();
    } catch (InterruptedException e) {
      e.printStackTrace();
      return "";
    }
  }
}

Notice that we use an object of type PersistentStateMessage to store and read the persistent state.

There is an example of a generated MuComponent changing another MuComponent implementation:

public abstract class QuasiComponentAdaptation
    extends QuasiComponent<AdapterAdaptation>  {
  abstract public void adapt();
}
public interface AdapterAdaptation extends Adapter {
  public void change(QuasiComponentMessage _comp);
}

Notice that a void change(QuasiComponentMessage _comp) method is present to give access to the replacement functionalities of the MuArchitecture.

There is an example of implementation of this MuComponent:

public class Adaptation extends QuasiComponentAdaptation {
  public void adapt() {
    architecture().change(new Message());
  }
}

We can also see here for the first time the instantiation of a MuComponent.

When calling change(...), the MuArchitecture will get the current state of Message and will inject it in the new implementation with the methods we defined previously in Message.

MuArchitecture Use

To use a MuArchitecture is to create an agent complying to this MuArchitecture by instantiating each of its MuComponents.

For this, the generated code of a MuArchitecture X consists into 2 classes: XMediator and X.
The first one is the implementation of the MuArchitecture itself, and the second one is a façade providing the external methods of the agent \todo{This will change in the future.}.

Thus, to create an agent compliant with a MuArchitecture SimpleAgent with 4 MuComponents Adaptation, Message, LifeCycle and Behavior is done like this:

  SimpleAgent agent1 = new SimpleAgent(
                          new Message(),
                          new LifeCycle(),
                          new Adaptation(),
                          new Behavior());
  agent1.start();

Notice the call to start() that starts each of the MuComponents and thus the agent.

Factory

One of the objectives of MAY being to reduce the development effort by distributing models of agents ready to use, it is necessary to be able to provide partially instantiated MuArchitecture where some of the MuComponents implementation are already fixed.
These will then be directly usable by users by choosing the remaining MuComponent implementations.

This is done by using a Factory, which currently must be built by hand.

A factory is only a class providing one (or several) static methods instantiating some MuComponents and an agent.
For example:

public class MySimpleAgent {
  public static SimpleAgent create(QuasiComponentBehavior behavior) {
    SimpleAgent agent = new SimpleAgent(new Message(),
                                        new LifeCycle(),
                                        new Adaptation(),
                                        behavior);
    agent.start();
    return agent;
  }
}

Thus, to create an agent, one just need to know MySimpleAgent.create(...).

For example:

public class Main {
  public static void main(String[] args) {
    SimpleAgent agent1 = create(new Behavior2("agent1"));
    SimpleAgent agent2 = create(new Behavior("agent2", agent1));

    agent2.send("hello");
  }
}

Framework Distribution

The created classes in the previous sections form a framework usable by a user of the model of agent to create agents.

Delivering them to such an user is to export the Eclipse project as a JAR using its export facilities:
right-click on the project, choose Export..., in the Java category, choose JAR File and follow the instructions.

The resulting JAR file will only need the fr.irit.smac.muadl.impl_X.X.X.jar file available of the MAY website.
For example they can both be added to a classic Eclipse Java project as dependencies.

Mis à jour par Anonyme il y a presque 16 ans · 6 révisions