GettingStarted

From Agent Factory

Jump to: navigation, search

On this specific page, you will find all the information you need to understand how to:

  • Install Agent Factory in both flavors Agent Factory Standard Edition (AFSE) and Agent Factory Mobile Edition (AFME)
  • Create your very first examples covering basic use of Agent Factory

Contents

Agent Factory Standard Edition (AFSE)

The preferred mode to use Agent Factory is to run it as an Eclipse plugin.

If you have already installed Eclipse on your machine, directly jump to the section dedicated to Installing Agent Factory Eclipse plugin

Installing Eclipse

First thing first, we need to install Eclipse to run Agent Factory.

Go to Eclipse website:

Then click on Downloads in the menu:

Select the Eclipse IDE for Java Developers and your operating system platform:

Click on a link to start downloading it:

When download is completed, extract the archive file into a directory

You can now run Eclipse and install Agent Factory:

Installing Agent Factory Eclipse plugin

Installing Agent Factory Eclipse plugin is fairly straightforward

Click on Help/Install New Software:

First of all, you need to enter the Agent Factory site

Click on the Add button and fill the dialog with the following data:

Name = Agent Factory

Location = http://www.agentfactory.com/~rem/eclipse

After a while, you should see appearing Agent Factory below:

Tick the Agent Factory box then click on Next

Click on Next

Click on "I accept the terms of the license agreement" and click on Finish

Finally, the installation is on its way:

Click OK on the security warning dialog:

To finish the installation, you should restart Eclipse:

First run

You can check whether Agent Factory is correctly installed by creating a new Agent Factory project

For that, click on File|New|Other, a new dialog opens, the Agent Factory folder should be visible

Expand the Agent Folder and click on New Agent Factory Project

Click on Next

Enter a project name and click on Finish

Examples

In this section, we propose several examples to illustrate most of the concepts present in Agent Factory.

  • Contract Net example that presents how to create agents and how to exchange messages between agents


Contract Net

As first example, we will develop the Contract Net Protocol. A Contract Net protocol concerns two kinds of roles: (1) the manager proposing a task to be performed and monitoring the execution of a task and (2) the contractors is responsible for the execution of a task. There are several phases in the Contract Net protocol:

  • The manager advertises a task to be performed. This advertisement is sent to potential contractors.
  • Contractors can make a proposal
  • The manager selects a contractor based on his/her proposal
  • The awarded contractor performs the task

After creating the Agent Factory project, we need to create the two different roles.

(1) The Manager role

Create a Java class with File|New|Class, enter the name of Manager and change the Superclass for AbstractAgent

For the moment, the role is void:

public class Manager extends AbstractAgent {
}

First of all, fix the imports (with CTRL+SHIFT+O)

Add constructor and unimplemented methods

The Manager class is now:

import java.util.Observable;
import com.agentfactory.platform.impl.AbstractAgent;
public class Manager extends AbstractAgent {
    public Manager(String name) {
        super(name);
	 // TODO Auto-generated constructor stub
    }

    @Override
    public void execute() {
        // TODO Auto-generated method stub
    }

    @Override
    public String getType() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void initialise(String arg0) {
        // TODO Auto-generated method stub
    }

    @Override
    public void update(Observable arg0, Object arg1) {
        // TODO Auto-generated method stub
    }
}

(2) The Contractor role

Do the same for Contractor with a Java class named Contractor.

Now, it is time to change the Main class to request executing the two different roles.

Go on line:

IAgent agent = ams.createAgent("rem", "test.aspeak");

And replace by the following lines:

IAgent manager = ams.createAgent("manager", Manager.class);
IAgent contractor0 = ams.createAgent("contractor0", Contractor.class);
IAgent contractor1 = ams.createAgent("contractor1", Contractor.class);

This creates one manager and two contractors.

Comment the line:

agent.initialise("+event(happy)");

such as:

// agent.initialise("+event(happy)");

It is time to execute your first multiagent system.

Right-click on the Main class, Run as|Java application

If everything goes well, you should see the Agent Factory debugger and your three agents.

You can select the three agents by clicking on them and click on Start. Obviously nothing appears in the command-line of Eclipse since you request nothing from your agents.

It is now time to add behaviour on our agents.

Agent Factory uses a scheduling algorithm to decide in which order to execute the agents. The scheduling algorithm is set in the Main class with the setScheduler() method. When Agent Factory requests an agent to be executed, it invokes the execute() method. The code within the execute() method is executed once then Agent Factory executes next agent based on its scheduling algorithm.

Every agent is represented as a finite state machine.

Add an integer variable named state to specify in which state an agent is:

public class Manager extends AbstractAgent {
    private int state = 0;
    public Manager(String name) {
        ...

We add the potential list of contractors the manager will use to send his/her message. Add a List variable of type AgentID as is:

public class Manager extends AbstractAgent {
    private int state = 0;
    private List<AgentID> targets;
    public Manager(String name) {
        super(name);
        targets = new ArrayList<AgentID>();
    }

Now, we need to populate the targets variable.

For this specific example, we populate with the two contractors. In further examples, we will use the AMS and DF services from Agent Factory.

We can initialise an agent with the initialise() method. In the following source code, we add an agent to the list of targets.

public void initialise(String data) {
    targets.add(FIPAHelper.fromFIPASL(FIPAContent.newInstance(data)));
}

We delay data description since this is out of scope at this moment in the tutorial. Data description is provided in the very last lines of this document.

It is time to modify the execute() method for sending and receiving messages.

As mentioned above, agents are represented as a finite state machine. As a consequence, the code within the execute() method is a set of states:

	 public void execute() {
	 	switch(state) {
		case 0 : 
	 		break;
	 	case 1 :
	 		break;
	 	case 2 :
	 		break;
	 	case 3 : 
	                break;
	 	case 4 : 
	 		break;
	 	}
        }

State 0 corresponds to the initial state and sending the call for proposal message.

State 1 corresponds to the state in which the Manager is waiting for proposals. In the current version of this example, we simplify and the Manager is waiting for all the answers.

State 2 corresponds to the state in which the Manager decides which proposal is the best one.

Finally, state 3 is the state where the Manager is waiting for an inform message to announce the task is completed. State 4 is the end of the agent.

Let us begin with state 0 and sending a message for all the potential contractors.

Sending a message

Support for FIPA messages is provided via a combination of the IMessage interface and the StringMessage class, which implements the interface supporting the FIPA String Representation. To create a message, you simply create an instance of the StringMessage class and set relevant properties as is highlighted in the code below, and then invoke the send(...) message, which is provided as part of the underlying agent implementation:

StringMessage message = StringMessage.newInstance();
message.setPerformative(IMessage.CALL_FOR_PROPOSAL);
message.setContent("task0");
message.getReceivers().add(target);
message.setSender(this.getAgentID());
send(message);

As can be seen above, the minimal set of properties required to send a message are:

  • the agent identifier of the sender
  • the agent identifier of the receiver
  • the performative
  • some content

When sending messages, the sender identifier is the agents own identifier (and it is got by calling the getAgentID() method). What is less obvious is how to get the receiver identifier. Basically, any agent that sends a message needs to know the identifier of the agent that will receive the message before it sends the message (this is not strictly true because AF allows regular expressions to be used for the name part of the identifier).

As a consequence, the code for the state 0 is the following:

case 0 : 
       for (AgentID target : targets) {
          StringMessage message = StringMessage.newInstance();
          message.setPerformative(IMessage.CALL_FOR_PROPOSAL);
          message.setContent("task0");
          message.getReceivers().add(target);
          message.setSender(this.getAgentID());
          send(message);
       }
       state = 1;
break;

Sending a message is effective when we call the send() method with the message.

Receiving a message

Receiving a message is almost as simple as sending a message. It involves two basic steps:

  • Loading of new messages into the agents inbox (from its incoming message queue); and
  • Processing any messages you have received.

The first step is required because it gathers any messages that the agent has received and stores them in the agents inbox. Only the messages stored in the inbox should be processed during that iteration of the agents execution cycle. Any messages received after this are then left to the next iteration of the agents execution cycle. The first step is realized when calling the retrieveNewMessages() method.

The second step involves processing of any messages found in the inbox. The expected behaviour is that ALL messages found in the inbox are handled in that execution cycle.

Here is an excerpt of receiving messages in the context of our Contract Net protocol:

for (IMessage message: getInbox()) {
    if (message.getPerformative().equals(IMessage.PROPOSE)) {
        receivedMessages++;
        if (new Integer(message.getContent()).intValue() < bestProposal) {
   	     bestProposal = new Integer(message.getContent()).intValue();
            bestProposalAgent = message.getSender();
        }
        if (receivedMessages == targets.size())
            state = 2;
    }
}

The getInbox() method returns an iteration of all the messages available in the mailbox.

Here, we check whether the message is a PROPOSE message. If it is the case, we increment the number of received messages. We then test whether the proposal is better than the best recorded one.

If the number of messages corresponds to the number of sent messages, the agent can move to next state.

In state 2, the Manager sends a message to the Contractor that has the best offer and jumps to state 3 where he/she waits for an inform message from the awarded contractor.

The complete code of the Manager is given below:

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import com.agentfactory.platform.core.AgentID;
import com.agentfactory.platform.core.IMessage;
import com.agentfactory.platform.impl.AbstractAgent;
import com.agentfactory.platform.impl.StringMessage;
import com.agentfactory.platform.util.FIPAContent;
import com.agentfactory.platform.util.FIPAHelper;
public class Manager extends AbstractAgent {
   //agent is represented as a finite state machine
   private int state = 0;
   //list of potential contractors
   private List<AgentID> targets;
   //used to record the number of received messages
   //in this version, we impose the manager to wait till receiving
   //answers from all the contractors
   private int receivedMessages = 0;
   //record the best proposal
   private int bestProposal = Integer.MAX_VALUE;
   //record the agent responsible for the best proposal
   private AgentID bestProposalAgent = null;
   public Manager(String name) {
      super(name);
      targets = new ArrayList<AgentID>();
   }
   public String getType() {
      return null;
   }
   //invoked on a call to createAgent
   public void initialise(String data) {
      //transform the String agent identifier into something usable on the platform
      targets.add(FIPAHelper.fromFIPASL(FIPAContent.newInstance(data)));
   }
   //invoked every time this is the turn for this agent to be executed
   public void execute() {
      retrieveNewMessages();
      switch(state) {
         case 0 : 
                 for (AgentID target : targets) {
                    StringMessage message = StringMessage.newInstance();
                    message.setPerformative(IMessage.CALL_FOR_PROPOSAL);
                    message.setContent("task0");
                    message.getReceivers().add(target);
                    message.setSender(this.getAgentID());
                    send(message);
                 }
                 state = 1;
                 break;
         case 1 :
                 for (IMessage message: getInbox()) {
                    if (message.getPerformative().equals(IMessage.PROPOSE)) {
                       receivedMessages++;
                       if (new Integer(message.getContent()).intValue() < bestProposal) {
                          bestProposal = new Integer(message.getContent()).intValue();
                          bestProposalAgent = message.getSender();
                       }
	            	if (receivedMessages == targets.size())
                          state = 2;
	             }
	          }
                 break;
         case 2 :
                 StringMessage response = StringMessage.newInstance();
                 response.setPerformative(IMessage.ACCEPT_PROPOSAL);
                 response.setContent(new Integer(bestProposal).toString());
                 response.getReceivers().add(bestProposalAgent);
                 response.setSender(this.getAgentID());
                 send(response);				
                 state = 3;
                 break;
         case 3 : 
                 for (IMessage message: getInbox()) {
                    if (message.getPerformative().equals(IMessage.INFORM)) {
                       state = 4;
                    }
                 }
                 break;
         case 4 : 
                 break;
      }
   }
   public void update(Observable arg0, Object arg1) {
   }
}

We just provide the execute() method for the Contractor since this is only here there is some code. Do not forget to add

private int state = 0;

on top of your Contractor class.

Here is the execute() method:

  retrieveNewMessages();
  switch(state) {
     case 0 :
             for (IMessage message: getInbox()) {
                if (message.getPerformative().equals(IMessage.CALL_FOR_PROPOSAL)) {
                   StringMessage response = StringMessage.newInstance();
                   response.setPerformative(IMessage.PROPOSE);
                   int value = (int)(Math.random()*100);
                   response.setContent(new Integer(value).toString());
                   response.getReceivers().add(message.getSender());
                   response.setSender(this.getAgentID());
                   send(response);
                   state = 1;
                }
             }
             break;
     case 1 : 
             for (IMessage message: getInbox()) {
                if (message.getPerformative().equals(IMessage.ACCEPT_PROPOSAL)) {
                   lastMessage = message;
                   state = 2;
                   break;
                }
                else
                   state = 3;
             }
             break;
     case 2 :
             StringMessage response = StringMessage.newInstance();
             response.setPerformative(IMessage.INFORM);
             response.setContent(lastMessage.getContent());
             response.getReceivers().add(lastMessage.getSender());
             response.setSender(this.getAgentID());
             send(response);
             state = 3;
             break;
     case 3 : 
             break;
  }

It is now time to test these two roles. Add the following lines after the three ones on createAgent:

manager.initialise("(agent-identifier :name contractor0 :addresses (sequence local:test.ucd.ie))");
manager.initialise("(agent-identifier :name contractor1 :addresses (sequence local:test.ucd.ie))");

Then run once again the Main class.

If everything is well, you should see your agents in the Agent Factory debugger:

If you click on Start then on Agent UML, you should see a trace of all the messages exchanged:

Agent Factory Mobile Edition