Notícias
Jade: Framework Java para sistemas baseados em agentes
TemaTec 231
Vanderson Botêlho da Silva é bacharel em Ciência da Computação pela Universidade Federal de Campina Grande (UFCG) e mestre em Informática Aplicada pela Pontifícia Universidade Católica do Paraná (PUC-PR). Atualmente é doutorando em Informática Aplicada, na linha de pesquisa de Agentes Inteligentes pela PUC-PR e chefe da Divisão de Arquitetura de Software e Tecnologia do Serpro.
A complexidade das aplicações em termos de número de funcionalidades, infraestruturas e alto volume de dados, requer abordagem de desenvolvimento flexível e distribuída, na medida que os sistemas devem ser capazes de adaptarem-se dinamicamente às modificações de estrutura e ambiente. Os sistemas multiagente são fortes candidatos à construção de arquiteturas com esses pré-requisitos.
O Jade (Java Agent Development) é um framework desenvolvido em Java que oferece um conjunto de ferramentas gráficas e APIs para construção de sistemas baseados em agentes de software. O framework provê uma arquitetura distribuída compatível com as especificações da Foundation for Intelligent Physical Agents (FIPA), um conjunto de padrões internacionais mantidos pela IEEE. A figura abaixo ilustra os principais elementos da sua arquitetura.
Instalação
O download da ferramenta pode ser feito no site: http://jade.tilab.com. Para reproduzir os exemplos apresentados neste artigo, deve-se importar a biblioteca jade.jar necessária para o desenvolvimento em qualquer IDE Java.
Criação de Containers
O trecho de código a seguir demonstra como iniciar plataformas a partir de uma simples classe Java.
public class MeuSMA { public static void main(String[] args) { String[] parametros = { "-gui", "-local-host", "127.0.0.1" }; jade.Boot.main(parametros); } }
A classe jade.Boot é responsável por iniciar a plataforma a partir de um conjunto de parâmetros. O resultado dessa chamada é exibido na tela de configuração do Jade.
Os agentes são identificados pela plataforma a partir da regra de formação: <nomedoagente>@<dispositivo>:<porta>/<plataforma>. É possível inicializar vários containers de forma distribuída. A ligação entre os containers é realizada por meio de parâmetros informados na inicialização dos containers secundários, conforme apresentado:
public class MeuSMA { public static void main(String[] args) { String[] parametros = { "-gui", "-local-host", "127.0.0.1"}; jade.Boot.main(parametros); String[] novoContainer = { "-local-host", "127.0.0.1", "-container", "-container-name", "Meu-Container"}; jade.Boot.main(novoContainer); } }
Nesse exemplo, os parâmetros do novoContainer criam um container secundário, identificado pelo nome “Meu-Container”. A figura a seguir apresenta graficamente a nova formação da plataforma Jade após nosso exemplo.
Os agentes especiais do Jade (ams, df e rma) hospedam-se no container principal da plataforma, e não há restrições para que outros agentes criados pelo sistema se hospedem ou se movam livremente entre qualquer container.
Criação de Agentes
Agora trataremos a construção dos agentes nos containers Jade e como inicializá-los. O trecho de código a seguir apresenta dois exemplos de classes de agentes:
public class AgenteComprador extends Agent { } public class AgenteVendedor extends Agent { }
Suas classes de agente devem estender a classe jade.core.Agent. Com poucas linhas de código, é possível iniciar seus agentes. O trecho de código abaixo demonstra como criar um agente “comprador” no container principal e um agente “vendedor” no container secundário:
public class MeuSMA { public static void main(String[] args) { String[] parametros = { "-gui", "-local-host", "127.0.0.1", "comprador:AgenteComprador()",}; jade.Boot.main(parametros); String[] novoContainer = { "-local-host", "127.0.0.1", "-container", "-container-name", "Meu-Container", "vendedor:AgenteVendedor()"}; jade.Boot.main(novoContainer); } }
A figura a seguir apresenta os dois agentes criados em seus respectivos containers.
Comportamentos
O Jade provê um conjunto de classes para composição de comportamentos dos agentes: simples (SimpleBehaviour), paralelos (ParallelBehaviour), cíclicos (CyclicBehaviour), entre outras dezenas de comportamentos. Todo comportamento possui dois métodos: action() para especificar a ação do comportamento e o done() para informar se o comportamento foi concluído. O trecho a seguir exemplifica a criação de um comportamento que será executado dez vezes:
public class MeuAgente extends Agent { protected void setup() { addBehaviour( new SimpleBehaviour() { int count = 1; public boolean done() { return (count == 11); } public void action() { System.out.println(count++); } }); } }
Os comportamentos podem ser incluídos ou removidos dinamicamente a qualquer momento. Isso permite a mutação do agente com ampla flexibilidade de programação.
Comunicação
De acordo com a especificação FIPA, o serviço de transporte de mensagens é um dos mais importantes para uma plataforma de agentes. No Jade, todas as mensagens trocadas pelos agentes seguem a estrutura de mensagem da especificação SC00061G (FIPA, 2014).
(REQUEST :sender ( agent-identifier :name rma@127.0.0.1:1099/JADE :addresses (sequence http://serpro-0000000:7778/acc )) :receiver (set ( agent-identifier :name vendedor@127.0.0.1:1099/JADE ) ) :content "Ola" )
Nesse exemplo, a mensagem representa uma solicitação (REQUEST); as informações sobre o emissor da mensagem estão no atributo sender e as informações do destinatário no atributo receiver, o conteúdo da mensagem é posto pelo atributo content. O Jade oferece a classe ACLMessage para construção de mensagens de forma programática. O trecho de código a seguir demostra como dois agentes podem se comunicar.
public class AgenteComprador extends Agent { public void setup() { System.out.println("Olá, sou o agente " + getLocalName()); addBehaviour(new OneShotBehaviour() { @Override public void action() { ACLMessage msgRx = new ACLMessage(ACLMessage.REQUEST); msgRx.addReceiver(new AID("vendedor", false)); msgRx.setContent("Olá, quero comprar uma TV"); send(msgRx); } }); addBehaviour(new CyclicBehaviour() { public void action() { ACLMessage msgRx = receive(); if (msgRx != null) { System.out.println(msgRx); } else { block(); } } }); } }
O agente comprador possui dois comportamentos: solicitar ao agente vendedor a compra e receber a resposta do vendedor de forma cíclica.
public class AgenteVendedor extends Agent { public void setup() { System.out.println("Olá, sou o agente " + getLocalName()); addBehaviour(new CyclicBehaviour() { public void action() { ACLMessage msgRx = receive(); if (msgRx != null) { System.out.println(msgRx); ACLMessage msgTx = msgRx.createReply(); msgTx.setPerformative(ACLMessage.REFUSE); msgTx.setContent("Não temos seu produto no estoque"); send(msgTx); } else { block(); } } }); } }
O agente vendedor possui um comportamento para receber requisições vindas de agentes compradores. Nesse exemplo, o vendedor recusará o pedido, hipoteticamente, por não possuir o item solicitado. A saída no terminal será:
Olá, sou o agente vendedor Olá, sou o agente comprador (REQUEST :sender ( agent-identifier :name comprador@127.0.0.1:1099/JADE :addresses (sequence http://serpro-1551251:7778/acc )) :receiver (set ( agent-identifier :name vendedor@127.0.0.1:1099/JADE ) ) :content "Olá, quero comprar uma TV" ) (REFUSE :sender ( agent-identifier :name vendedor@127.0.0.1:1099/JADE :addresses (sequence http://serpro-1551251:7778/acc )) :receiver (set ( agent-identifier :name comprador@127.0.0.1:1099/JADE :addresses (sequence http://serpro-1551251:7778/acc )) ) :content "Não temos seu produto no estoque" :reply-with comprador@127.0.0.1:1099/JADE1407613837881 )
Referências
- BELLIFEMINE, Fabio Luigi; CAIRE, Giovanni; GREENWOOD, Dominic. Developing multi-agent systems with JADE. John Wiley & Sons, 2007.
- FIPA, Standard Status Specifications, 2002. Disponível em: <http://www.fipa.org/repository/standardspecs.html>. Acesso em 10 ago. 2014.
Autor:
Vanderson Botêlho da Silva é bacharel em Ciência da Computação pela Universidade Federal de Campina Grande (UFCG) e mestre em Informática Aplicada pela Pontifícia Universidade Católica do Paraná (PUC-PR). Atualmente é doutorando em Informática Aplicada, na linha de pesquisa de Agentes Inteligentes pela PUC-PR e chefe da Divisão de Arquitetura de Software e Tecnologia do Serpro. Possui experiência na área de Engenharia de Software, com ênfase em gestão de projetos, testes de desempenho, desenvolvimento orientado a comportamento e computação distribuída.