Exemplo simples de Sistema Multiagentes em Java

Olá pessoal,

Neste post irei apresentar um exemplo simples de um Sistema Multiagentes (SMA) implementado em Java utilizando o Eclipse. Um SMA representa um sistema que possui um conjunto de agentes que interagem um ambiente comum. Um agente (inteligente), por sua vez, é uma entidade que pode perceber o ambiente no qual está inserido, reagir e se comunicar com outros agentes.

Um exemplo de SMA é um ambiente de jogos. Além do personagem do jogador, um jogo é composto também de personagens que possuem “vida própria” e objetivos. Cada um desses outros personagens que agem por conta própria podem ser considerados como agentes.

Bom, aqui irei apresentar uma implementação simples de um SMA. Neste exemplo, dois agentes irão ter um pequeno diálogo:

Agente 1: “Olá. Meu nome é Maria.”
Agente 2: “Olá. Meu nome é João”.
Agente 2: “Olá. Como vai você?”
Agente 1: “Bem e você?”
Agente 2: “Eu vou bem também”

Para esta implementação, iremos utilizar o framework JADE e o software Eclipse. JADE (Java Agent Development Framework) é um framework Java que implementa os princípios de um SMA de acordo com as especificações da FIPA (The Foundation of Intelligent Physical Agents). Faça o download do arquivo jadeBin aqui.

Os agentes implementados através do framework JADE possuem um ciclo de vida. Este ciclo é apresentado na figura abaixo:

Na figura do ciclo de vida, cinco métodos são destacados em vermelho: setup(), doDelete(), action(), done() e takedown(). Para a implementação mínima de um agente, estes métodos devem conter alguma lógica definida. Em resumo, o raciocínio pode ser:

setup(): o que acontecerá na inicialização?
doDelete(): o agente deve permanecer vivo?
action(): qual ação (comportamento) o agente irá executar?
done(): tarefa finalizada?
takedown(): encerrar a vida do agente.

Dessa forma, organizando estes métodos em três estados gerais, pode-se dizer que a área (1) representa a inicialização do agente, a área (2) o desenvolvimento da vida do agente (execução de suas ações) e a área (3) o fim da vida do agente.

Vamos então começar a implementação. Crie um novo projeto (Java Project) no Eclipse e adicione o arquivo jade.jar ao projeto. Para tanto, clique com o botão direito do mouse no projeto, selecione Build Path e em seguida Add External Archives. Navegue até a pasta onde você descompactou o arquivo jadeBin e selecione o arquivo jade.jar (localizado na pasta lib).

Feito isso, vamos implementar o primeiro agente: a Maria. Para tanto, crie duas classes Java. Uma se chamará ComportamentoMaria e a outra AgenteMaria. A classe ComportamentoMaria irá implementar as ações que a agente Maria irá executar. A classe AgenteMaria irá implementar a inicialização da agente em si.


import jade.core.Agent;

public class AgenteMaria extends Agent{
  private static final long serialVersionUID = 1L;

  protected void setup(){
    //agente se apresenta
    System.out.println(this.getLocalName() + " diz: Olá. Meu nome é "+ this.getLocalName());
    //definição do comportamento que a agente Maria irá executar
    addBehaviour(new ComportamentoMaria(this));
  }
}


import jade.core.Agent;
import jade.core.behaviours.SimpleBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

public class ComportamentoMaria extends SimpleBehaviour{
  private static final long serialVersionUID = 1L;
  private static final MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.REQUEST);
  ACLMessage msgAgente;
  int contMaria = 0; //conta quantas mensagens já foram enviadas pela agente Maria

  public ComportamentoMaria(Agent agent) {
    super (agent);
  }

  @Override
  public void action() {
    //agente irá verificar se alguma mensagem foi enviada a ela
    msgAgente = myAgent.receive(mt);
    if (msgAgente != null) {
      System.out.println(msgAgente.getContent());
      enviaMsg();
    } else {
      this.block();
    }
  }

  private void enviaMsg(){
    ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
    msg.addReceiver(msgAgente.getSender());
    msg.setContent(myAgent.getLocalName() + " diz: Bem e você?");
    myAgent.send(msg);
  }

  @Override
  public boolean done() {
    if (contMaria == 3)
      myAgent.doDelete();
    else
      contMaria++;

    return false;
  }
}

A classe AgenteMaria irá implementar o método setup(), ou seja, irá definir as regras de inicialização da agente. Neste exemplo, a agente irá se apresentar e irá determinar a classe que irá definir suas ações.

A classe ComportamentoMaria irá implementar os métodos action(), done(), doDelete() e herdar a classe SimpleBehaviour. Comportamentos do tipo SimpleBehaviour são utilizados quando o agente irá executar uma única tarefa que não poderá ser interrompida [1].

A comunicação entre os agente acontecerá via ACLMessage (Agente Comunication Language), uma implementação que segue a FIPA ACL Message Structure Specification [2].

Agora crie mais duas classes: ComportamentoJoao e AgenteJoao. A primeira irá implementar as ações do agente João e a segunda será o agente João em si. Os códigos utilizados para o agente João são semelhantes aos utilizados para a agente Maria.


import jade.core.Agent;

public class AgenteJoao extends Agent {
  private static final long serialVersionUID = 1L;

  protected void setup(){
    //linha de apresentação
    System.out.println(this.getLocalName() + " diz: Olá. Meu nome é "+ this.getLocalName());
    addBehaviour(new ComportamentoJoao(this));
  }
}


import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.SimpleBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

public class ComportamentoLucia extends SimpleBehaviour{
  private static final long serialVersionUID = 1L;
  private static final MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.REQUEST);
  ACLMessage msgAgente;
  int contJoao = 0; //conta quantas mensagens já foram enviadas pelo agente João

  public ComportamentoLucia(Agent agent) {
    super (agent);
  }

  @Override
  public void action() {
    if (contJoao == 0){ //para a primeira mensagem da conversa entre os agentes
      enviaPrimeiraMsg();
    } else {
      msgAgente = myAgent.receive(mt);
      if (msgAgente!= null) {
        System.out.println(msgAgente.getContent());
        enviaMsg();
      } else {
        this.block();
      }
    }
  }

  private void enviaPrimeiraMsg(){
    //definição do agente que irá conversar com o João
    AID agenteRecebedor = new AID ("maria", AID.ISLOCALNAME);
    ACLMessage priMsgAgente = new ACLMessage(ACLMessage.REQUEST);
    priMsgAgente.addReceiver(agenteRecebedor);
    priMsgAgente.setContent(myAgent.getLocalName() + " diz: Olá! Como vai você?");
    myAgent.send(priMsgAgente);
  }

  private void enviaMsg(){
    ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
    msg.addReceiver(msgAgente.getSender());
    msg.setContent(myAgent.getLocalName() +" diz: Eu vou bem também!");
    myAgent.send(msg);
  }

  @Override
  public boolean done() {
    if (contJoao == 1)
      myAgent.doDelete();
    else
      contJoao++;

    return false;
  }
}

Vocês devem ter observado que o método takeDown() não foi implementado em nenhuma das classes. Isto acontece, pois este método já é chamado pelo framework no momento em que é encerrada a vida do agente [3].

Com o código todo implementado, vamos ao passo final antes da execução. Precisamos alterar as configurações de execução. Para tanto, clique com o botão direito do mouse no projeto, selecione Run As e em seguida Run Configurations. Aplique as seguintes configurações:

Na aba Main, no campo Main class , preencha com jade.Boot . Na aba Arguments , no campo Program arguments , preencha com -agents maria:.AgenteMaria;joao:.AgenteJoao .

Aplique as alterações e execute o projeto. Você irá ver na sua tela do console esta saída:

É isso pessoal. Espero que este exemplo tenha sido útil para vocês.

Até mais!

Referências:

[1] http://jade.tilab.com/doc/api/jade/core/behaviours/SimpleBehaviour.html
[2] http://jade.tilab.com/doc/api/jade/lang/acl/ACLMessage.html
[3] http://jade.tilab.com/doc/programmersguide.pdf

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s