IC Andre Manual Jade Portuguese

ManualJadePortuguese

ManualJadePortuguese

ManualJadePortuguese

ManualJadePortuguese

ManualJadePortuguese

User Manual: Pdf

Open the PDF directly: View PDF PDF.
Page Count: 86

Universidade Federal do ABC
ufabc
Andr´e Filipe de Moraes Batista
andre.batista@ufabc.edu.br
Manual Complementar do Projeto de Pesquisa:
Sistemas Multiagentes na Constru¸ao de um
Middleware para Suporte a Ambientes
Computacionais
Orienta¸ao:
ProfaDraMaria das Gra¸cas Bruno Marietto
Santo Andr´e, Agosto de 2008
Pref´acio
“Atingimos a perfei¸ao n˜ao quando nada pode
acrescentar-se a um projeto, mas quando nada pode
retirar-se”
—–Saint-Exup´ery
A id´eia de escrever este manual teve in´ıcio nos meus estudos de inicia¸ao cient´ıfica
na Universidade Federal do ABC, sob a orienta¸ao da professora Grca Marietto. ´
E neste
esp´ırito de aprendizado que este manual foi escrito. Desde o primeiro momento que des-
cobri que iria trabalhar programando em Java, e que esta programa¸ao seria para sistemas
multiagentes, a alegria e ansiedade foram estonteantes. ´
E este o meu objetivo: ser o mais
did´atico poss´ıvel e fazer com que voe sinta um pouco das emo¸oes que senti durante
as longas horas diante do computador, programando e ao mesmo tempo descobrindo a
plataforma JADE e suas fa¸canhas.
A programa¸ao de sistemas multiagentes ´e uma t´ecnica de desenvolvimento de sistemas
distribu´ıdos, e neste contexto encontramos quest˜oes tais como: “como distribuir?”, “como
fazer a comunicao entre as partes do sistema?”, “como administrar o sistema?”, entre
outras. Essas e outras perguntas foram respondidas ao longo do estudo desta plataforma.
Aem de abstrair muitos recursos do programador, as facilidades de implementa¸ao fazem
com que esta seja uma das mais utilizadas plataformas de desenvolvimento de aplicoes
distribu´ıdas.
Este manual n˜ao est´a finalizado e nunca estar´a. Ele contar´a sempre com um toque
especial seu. Sim, voe!... Vocˆe dever´a ao longo de sua leitura criar cen´arios para suas
aplicoes, buscar solu¸oes para as d´uvidas que surgir˜ao, enfim, nunca se contentar apenas
com o que est´a escrito, tente sempre tirar suas pr´oprias conclus˜oes. Fazendo isto vocˆe
aprender´a cada vez mais.
Andr´e Filipe de Moraes Batista
ii
Aos meus pais.
Lista de Figuras
2.1 Ciclo de Execu¸ao de um Agente. . . . . . . . . . . . . . . . . . . . . . . . 13
2.2 Exemplo de aquina de Estado Finito. . . . . . . . . . . . . . . . . . . . . 28
3.1 Situa¸ao Problema - Incˆendio. . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.2 Cen´ario - Loja de M´usica. . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.3 Estrutura de uma Entrada no DF. . . . . . . . . . . . . . . . . . . . . . . . 48
3.4 Cen´ario - Solicitando Ajuda. . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.5 Interface Gr´afica da Plataforma JADE. . . . . . . . . . . . . . . . . . . . . 59
3.6 AgenteSnier. ................................. 60
3.7 Agente Pedinte na Plataforma. . . . . . . . . . . . . . . . . . . . . . . . . 61
3.8 Execu¸ao do Agente Sniffer. . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.9 Troca de Mensagens entre os Agentes. . . . . . . . . . . . . . . . . . . . . . 62
3.10 P´aginas Amarelas - Notifica¸ao. . . . . . . . . . . . . . . . . . . . . . . . . 66
3.11 Estrutura dos Protocolos Baseados no fipa-request............. 69
3.12 Protocolo fipa-request. ........................... 71
3.13 Plataforma Distribu´ıda JADE. . . . . . . . . . . . . . . . . . . . . . . . . . 77
iv
Lista de Tabelas
3.1 Valores Inteiros das Performatives. ...................... 33
v
Sum´ario
Lista de Figuras iv
Lista de Tabelas v
1 Instala¸ao 1
1.1 RequisitosB´asicos ............................... 1
1.2 Software de Instala¸ao da Plataforma JADE . . . . . . . . . . . . . . . . . 1
1.3 Execu¸c˜aodoAmbiente............................. 2
1.4 Integra¸ao com a IDE NetBeans . . . . . . . . . . . . . . . . . . . . . . . . 3
2 Primeiros Programas 5
2.1 Hello World ................................... 5
2.2 Identificadores de Agentes . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Passando Informa¸oes a um Agente . . . . . . . . . . . . . . . . . . . . . . 8
2.4 Comportamentos ................................ 10
2.4.1 Execu¸ao dos Comportamentos . . . . . . . . . . . . . . . . . . . . 12
2.4.2 Bloqueando Comportamentos . . . . . . . . . . . . . . . . . . . . . 12
2.5 Comportamentos Pr´e-Definidos . . . . . . . . . . . . . . . . . . . . . . . . 17
2.5.1 Comportamentos One-shot ....................... 18
2.5.2 Comportamentos C´ıclicos . . . . . . . . . . . . . . . . . . . . . . . 19
2.5.3 Comportamentos Temporais . . . . . . . . . . . . . . . . . . . . . . 19
2.5.4 Comportamentos Compostos . . . . . . . . . . . . . . . . . . . . . . 21
2.5.4.1 SequencialBehaviour ..................... 21
2.5.4.2 ParallelBehaviour ...................... 23
2.5.4.3 FSMBehaviour ........................ 27
3 Comunica¸ao entre Agentes 32
3.1 Envio e Recebimento de Mensagens . . . . . . . . . . . . . . . . . . . . . . 32
3.1.1 Classe ACLMessage ........................... 32
3.1.2 Enviar uma Mensagem . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.1.3 Receber uma Mensagem . . . . . . . . . . . . . . . . . . . . . . . . 34
vi
SUM´
ARIO vii
3.1.4 Exemplo de Troca de Mensagens . . . . . . . . . . . . . . . . . . . 35
3.2 EnviodeObjetos ................................ 40
3.3 Sele¸c˜aodeMensagens.............................. 45
3.4 P´aginasAmarelas................................ 48
3.4.1 Registro ................................. 50
3.4.2 Busca .................................. 51
3.4.3 SolicitandoAjuda............................ 52
3.4.4 Notica¸c˜ao ............................... 62
3.5 P´aginasBrancas ................................ 67
3.6 Protocolos de Intera¸ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
3.6.1 Classe AchieveREInitiator . . . . . . . . . . . . . . . . . . . . . . . 70
3.6.2 Classe AchieveREResponder . . . . . . . . . . . . . . . . . . . . . . 70
3.6.3 Exemplo de Implementa¸ao do Protocolo FIPA-Request . . . . . . 70
Referˆencias Bibliogr´aficas 79
Cap´ıtulo 1
Instala¸ao
Neste cap´ıtulo ser´a demonstrado o processo de instala¸ao da plataforma JADE.
1.1 Requisitos B´asicos
Por ser desenvolvida em Java, o requisito m´ınimo para executar a plataforma JADE ´e o
run-time do Java. No caso Java Run-Time Environment (JRE) vers˜ao 1.4 ou superior.
1.2 Software de Instala¸ao da Plataforma JADE
Todos os software JADE, inclusive add-ons e novas vers˜oes, est˜ao distribu´ıdos sob as
limita¸oes da LGPL1e dispon´ıveis para download no web site http://jade.cselt.it ou
http://jade.tilab.com.
A vers˜ao atual da plataforma JADE utilizada neste trabalho ´e a 3.5. Para esta vers˜ao,
cinco arquivos s˜ao disponibilizados:
1. jadeSrc.zip (1.8 MB) – c´odigo fonte do software JADE;
2. jadeExamples.zip (270 KB) – c´odigo fonte dos exemplos de programas feitos em
JADE;
3. jadeDoc.zip (4.7 MB) – toda a documenta¸ao, incluindo o javadoc da API da
plataforma e manuais de referˆencia;
4. jadeBin.zip (2.0 MB) – o software JADE bin´ario, pronto para uso;
1A licen¸ca LGPL fornece alguns direitos e tamb´em deveres. Dentre os direitos est˜ao o acesso ao
odigo fonte do software, a permiss˜ao de fazer e distribuir c´opias, permiss˜ao para fazer melhorias e
funcionalidades etc. a alguns dos deveres s˜ao: ao fazer modifica¸oes privadas e secretas, n˜ao alterar a
licen¸ca do software e suas modifica¸oes, dentre outros.
1
1.3. Execu¸ao do Ambiente 2
5. jadeAll.zip (5.8 MB) – todos os arquivos anteriormente citados.
Recomenda-se o download do arquivo jadeAll.zip. Ap´os o download descompacta-se
o arquivo interno jade-Bin-3.5.zip em um diret´orio, por exemplo o diret´orio raiz (C:).
Uma pasta denominada jade ´e criada. Deve-se incluir as seguintes linhas na vari´avel de
ambiente classpath:
.;c:\jade\lib\jade.jar; c:\jade\lib\jadeTools.jar; c:\jade\lib\iiop.jar
Com isto a plataforma JADE est´a instalada e configurada para rodar no ambiente
Windows.
1.3 Execu¸ao do Ambiente
Ap´os os passos citados anteriormente, ´e poss´ıvel a execu¸ao da plataforma JADE pelo
prompt de comando. A linha de execu¸ao da plataforma JADE ´e a seguinte:
java jade.Boot [op¸c~oes] [agentes]
Esta linha de execu¸ao ser´a abordada nas pr´oximas se¸oes com mais detalhes. Neste
momento, para verificar se a instala¸ao e a configura¸ao da plataforma foram feitas cor-
retamente, digite no prompt o seguinte comando:
java jade.Boot
Com este comando a plataforma JADE ´e executada. Se tudo foi configurado correta-
mente, a seguinte mensagem ser´a exibida:
INFO: ----------------------------------
This is JADE 3.5 - revision 5988 of 2007/06/21 11:02:30
downloaded in Open Source, under LGPL restrictions,
at http://jade.tilab.com/
----------------------------------------
11/11/2007 12:22:50 jade.core.BaseService init
INFO: Service jade.core.management.AgentManagement initialized
11/11/2007 12:22:50 jade.core.BaseService init
INFO: Service jade.core.messaging.Messaging initialized
11/11/2007 12:22:50 jade.core.BaseService init
INFO: Service jade.core.mobility.AgentMobility initialized
11/11/2007 12:22:50 jade.core.BaseService init
INFO: Service jade.core.event.Notification initialized
1.4. Integra¸ao com a IDE NetBeans 3
11/11/2007 12:22:50 jade.core.messaging.MessagingService clearCachedSlice
INFO: Clearing cache
11/11/2007 12:22:50 jade.mtp.http.HTTPServer <init>
INFO: HTTP-MTP Using XML parser com.sun.org.apache.xerces.internal
.parsers.SAXParser
11/11/2007 12:22:50 jade.core.messaging.MessagingService boot
INFO: MTP addresses:
http://lap:7778/acc
11/11/2007 12:22:50 jade.core.AgentContainerImpl joinPlatform
INFO: --------------------------------------
Agent container Main-Container@lap is ready.
--------------------------------------------
A exibi¸ao da mensagem Agent container Main-Container@lap is ready indica
que a plataforma est´a em execu¸ao. Para finalizar a execu¸ao pressione as teclas CTRL+C.
Existe um bug na vers˜ao 3.5 da JADE, onde um erro ligado aos sockets ´e exibido
pois a m´aquina que est´a executando a plataforma pode n˜ao estar em rede. Esta falha
o apareceu na vers˜ao 3.5 e sua corre¸ao ainda est´a em desenvolvimento. Recomenda-se
que quando uma m´aquina estiver fora da rede deve-se incluir o parˆametro -detect-main
false na linha de execu¸ao da plataforma, da seguinte maneira:
java jade.Boot -detect-main false
1.4 Integra¸ao com a IDE NetBeans
Vamos integrar as bibliotecas da plataforma JADE com a IDE Netbeans2, para que seja
poss´ıvel o desenvolvimento de agentes contando com as ferramentas de uma IDE. No
NetBeans abra o menu Ferramentas (Tools) e clique na op¸ao Gerenciador de Biblioteca
(Library Manager). Uma janela ser´a aberta.
Na janela Gerenciador de Bibliotecas clique no bot˜ao Nova Biblioteca (new library).
Uma janela de di´alogo ser´a aberta. No campo Nome da Biblioteca digite jade e deixe
marcado o campo Tipo de Biblioteca como Bibliotecas da Classe. E clique em ok. A
janela de Gerenciador de Bibliotecas agora apresentar´a a nova biblioteca adicionada.
Nesta mesma janela, na guia Classpath clique no bot˜ao Adicionar JAR/Pasta e adi-
cione os arquivos (localizados em C:/jade/lib/): http.jar, iiop.jar, jade.jar e
jadeTools.jar. Na guia Javadoc adicione a pasta C:/jade/doc. Clique em ok e as
bibliotecas JADE estar˜ao integradas ao Netbeans.
Quando estiver desenvolvendo um projeto no NetBeans, v´a na guia Projetos e sele-
cione o item Bibliotecas. Com o bot˜ao direito do mouse selecione a op¸ao Adicionar
2A vers˜ao utilizada foi a 6.0, dispon´ıvel em http://www.netbeans.org
1.4. Integra¸ao com a IDE NetBeans 4
Biblioteca. Ser´a aberta a janela Adicionar Biblioteca. Nesta, selecione a biblioteca
JADE e clique em OK. Com isto, o NetBeans passar´a a reconhecer os m´etodos e atribu-
tos fornecidos pela plataforma.
A execu¸ao de um agente n˜ao ser´a pela IDE3. Vocˆe dever´a executar os agentes a partir
de um prompt de comando.
3Existem formas de se executar um agente pela IDE, mas estas n˜ao ser˜ao abordadas neste manual.
Cap´ıtulo 2
Primeiros Programas
Neste cap´ıtulo ser´a apresentada a estrutura b´asica de uma implementa¸ao na plataforma
JADE, com o uso de exemplos de implementa¸ao.
2.1 Hello World
Vamos come¸car com um programa cl´assico: um agente JADE que imprime na tela a frase
Hello World. Agentes JADE s˜ao definidos como subclasses da classe Agent e seu c´odigo
inicial (o que o agente far´a ao ser executado) deve ser colocado dentro do m´etodo setup().
O c´odigo do Hello World ´e mostrado na Caixa de C´odigo 2.1.
Herdando a classe jade.core.Agent os agentes j´a possuem as opera¸oes b´asicas dentro
da plataforma, como registro e configura¸ao e outro conjunto de m´etodos para implemen-
ta¸ao de comportamentos pr´e-definidos, como m´etodos de troca de mensagens.
odigo 2.1: HelloAgent.java
import ja de . co r e . Agent ;
3public c l a s s H elloAgent extends Agent{
protected void se tu p ( )
6{
System . out . p r i n t l n ( "Hello World . " ) ;
System . out . p r i n t l n ( "Meu nome ´e " + getLocalName ( ) ) ;
9}
}
 
Devemos estar dentro do diret´orio dos arquivos .java para que este agente seja execu-
tado. Uma vez no diret´orio, deve-se executar as seguintes linhas de comando no prompt:
javac HelloAgent.java
java jade.Boot Andre:HelloAgent
5
2.2. Identificadores de Agentes 6
A primeira linha trata da compila¸ao da classe HelloAgent.java, gerando o arquivo
HelloAgent.class. A segunda linha de comando requer um pouco mais de explica¸ao.
Basicamente, agentes s˜ao como Java Applets na medida em que ambos n˜ao podem ser exe-
cutados diretamente: eles s˜ao executados dentro de outro programa que proe os recursos
necess´arios para sua execu¸ao. No caso dos applets, um browser ou um Applet Viewer ´e
necess´ario; para agentes JADE o ambiente de execu¸ao ´e fornecido pela classe jade.Boot.
O parˆametro Andre:HelloAgent indica a classe do agente (HelloAgent), e provˆe um nome
´unico ao agente (Andre). A classe Agent conem o m´etodo getLocalName(), que retorna
o nome do agente em seu container.
Com a execu¸ao das linhas de comando tem-se o seguinte resultado:
INFO: ----------------------------------
This is JADE 3.5 - revision 5988 of 2007/06/21 11:02:30
downloaded in Open Source, under LGPL restrictions,
at http://jade.tilab.com/
----------------------------------------
.
.
.
INFO: --------------------------------------
Agent container Main-Container@lap is ready.
--------------------------------------------
Hello World.
Meu nome ´e Andre
´
E importante lembrar que este agente ainda est´a em execu¸ao. Para finaliza¸ao do
agente e da plataforma pressione as teclas CTRL+C.
2.2 Identificadores de Agentes
De acordo com o padr˜ao FIPA cada instˆancia de agente ´e identificada por um agent
identifier. Na plataforma JADE um agent identifier ´e representado como uma instˆancia
da classe jade.core.AID. O m´etodo getAID() permite obter a identifica¸ao completa
(global, nome na plataforma, endere¸co, etc) do agente, armazenando estas informa¸oes
em uma lista. Um ID global ´e aquele que representa o identificador do agente em toda a
plataforma. Um ID local refere-se ao conjunto de informa¸oes que representam o agente
em seu container.
O nome global do agente ´e ´unico na plataforma, e possui a seguinte estrutura:
2.2. Identificadores de Agentes 7
<nome_local>@<nome-plataforma>
Por exemplo o agente Pedro, localizado na plataforma Escola, ter´a seu nome global
definido por Pedro@Escola.
A classe AID disponibiliza m´etodos para obter o nome local (getLocalName()1), o
nome global (getName()) e os endere¸cos de um agente (getAllAddresses()). Para visu-
aliza¸ao destas funcionalidades, considere o c´odigo exibido na Caixa de C´odigo 2.2.
odigo 2.2: InfoAgentes.java
import ja de . co r e . Agent ;
import ja de . co r e . AID ;
3import jav a . u t i l . I t e r a t o r ;
public c l a s s InfoAgentes extends Agent{
6protected void se tu p ( ) {
System . out . p r i n t l n ( "Hello World . Eu sou um agente!" ) ;
System . out . p r i n t l n ( "Todas as minhas informa¸c~oes: \n" + getAID ( ) ) ;
9System . out . p r i n t l n ( "Meu nome local ´e "+ getAID ( ) . getLocalName ( ) ) ;
System . out . p r i n t l n ( "Meu nome global (GUID) ´e"+ getAID ( ) . getName ( ) ) ;
System . out . p r i n t l n ( "Meus endere¸cos s~ao:" ) ;
12 I t e r a t o r i t = getAID ( ) . g e t A l l A d d r e s s e s ( ) ;
while ( i t . hasNext ( ) ) {
System . out . p r i n t l n ( "- "+i t . next ( ) ) ;
15 }
}
18 }
 
Com a execu¸ao da seguinte linha de comando:
java jade.Boot Ivan:InfoAgentes
Temos o seguinte resultado:
Hello World. Eu sou um agente!
Todas as minhas informa¸c~oes:
( agent-identifier :name Ivan@lap:1099/JADE
:addresses (sequence http://lap:7778/acc ))
Meu nome local ´e Ivan
Meu nome global (GUID) ´e Ivan@lap:1099/JADE
Meus endere¸cos s~ao:
- http://lap:7778/acc
1A classe Agent tamem disponibiliza este m´etodo.
2.3. Passando Informa¸oes a um Agente 8
O nome local do agente ´e Ivan, conforme especificado na linha de comando. Uma vez
que n˜ao especificamos o nome da plataforma, JADE automaticamente atribui um nome
a esta, usando as informa¸oes do host e da porta do container principal (no caso, o host
´e denominado lap e a porta do container principal ´e 1099). Com isso, o nome global
(GUID - Globally Unique Name) do agente ´e Ivan@lap:1099/JADE.
Embora pare¸ca um endere¸co, o GUID n˜ao ´e o endere¸co do agente. No caso, vemos
que o endere¸co do agente Ivan ´e http://lap:7778/acc(Agent Communication Channel).
Os endere¸cos inclu´ıdos em uma AID s˜ao referentes ao MTP (Message Transport Proto-
col). Por padr˜ao, a plataforma JADE atribui um MTP HTTP ao main-container. Estes
endere¸cos s˜ao usados na comunica¸ao entre agentes que est˜ao em plataformas diferentes.
Pode-se incluir endere¸cos FTP, IIOP dentre outros.
Para designarmos um nome para a plataforma, devemos passar este nome como parˆa-
metro na execu¸ao da seguinte forma:
java jade.Boot -name plataforma-de-teste Ivan:InfoAgentes
Neste caso demos o nome de plataforma-de-teste `a nossa plataforma e, com isso,
na execu¸ao do agente tem-se o seguinte resultado:
Hello World. Eu sou um agente!
Todas as minhas informa¸c~oes:
( agent-identifier :name Ivan@plataforma-de-teste:1099/JADE
:addresses (sequence http://plataforma-de-teste:7778/acc ))
Meu nome local ´e Ivan
Meu nome global (GUID) ´e Ivan@plataforma-de-teste
Meus endere¸cos s~ao:
- http://lap:7778/acc
2.3 Passando Informa¸oes a um Agente
Considere um agente comprador de livros, que deve saber quais livros ir´a comprar. Vamos
criar um agente em que ser´a poss´ıvel indicar qual livro este agente ir´a comprar. Seu c´odigo
est´a apresentado na Caixa de C´odigo 2.3.
odigo 2.3: CompradorDeLivros.java
import ja de . co r e . Agent ;
import ja de . co r e . AID ;
3
public c l a s s CompradorDeLivros extends Agent{
6private S t r i n g l iv ro sC om pr ar ;
2.3. Passando Informa¸oes a um Agente 9
protected void se tu p ( )
9{
// imprime mensagem de BemVindo
System . out . p r i n t l n ( "Ol´a !!! Eu sou o Agente Comprador "+ getLocalName ()
+" e estou pronto para comprar !" ) ;
12
// ca pt ura o t´ı t u l o do l i v r o que comprar´a , que f o i passado como
argumento de i n i c i a l i z a ¸c ˜a o
Ob ject [ ] a rg s = getArguments ( ) ;
15 i f ( ar gs != null && ar g s . len gth >0)
{
l iv ro sC om pr ar = ( S t r i n g ) a r g s [ 0 ] ;
18 System . out . p r i n t l n ( " Pretendo comprar o livro: "+ l ivro sComp rar ) ;
}e l s e
{
21 // f i n a l i z a o a ge nte
System . out . p r i n t l n ( "Nao tenho livros para comprar!" ) ;
doDelete () ; // i n vo c a a e xe cu ¸c ˜a o do etodo takeDown ( )
24 }
}
27 protected void takeDown () {
System . out . p r i n t l n ( "Agente Comprador " + getAID ( ) . getName ( ) + "
est´a finalizado " ) ;
}
30
}
 
Para executar o C´odigo 2.3 digitamos no prompt:
javac CompradorDeLivros.java
java jade.Boot Jose:CompradorDeLivros("O-Pequeno-Principe")
Com a execu¸ao destas linhas tem-se o seguinte resultado:
Ol´a!!! Eu sou o Agente Comprador Jose e estou pronto para comprar!
Pretendo comprar o livro: O-Pequeno-Principe
Caso n˜ao seja passado nenhum parˆametro na execu¸ao do agente, este imprimir´a a
mensagem:
Ol´a !!! Eu sou o Agente Comprador Jose e estou pronto para comprar!
Nao tenho livros para comprar!
Agente Comprador Jose@lap:1099/JADE est´a finalizado
2.4. Comportamentos 10
Observe que a frase Agente Comprador Jose@lap:1099/JADE est´a finalizado uti-
liza no c´odigo o m´etodo getAID().getName(), que retorna o nome global do agente. Por
padr˜ao JADE adiciona o n´umero da porta de comunica¸ao da plataforma (padr˜ao ´e 1099)
e tamem adiciona a string /JADE ao final, para indicar que trata-se de um agente JADE.
Para finalizar a execu¸ao da plataforma pressione as teclas CTRL+C.
2.4 Comportamentos
Cada a¸ao que um agente pode realizar ´e representada como um comportamento deste
agente. O c´odigo que implementa esta funcionalidade deve estar em uma nova classe, que
deve herdar as funcionalidades da classe jade.core.behaviours.Behaviour.
Uma vez implementado o c´odigo referente ao comportamento, para que este seja exe-
cutado ´e necess´aria a invoca¸ao, no corpo de a¸ao do agente, do m´etodo addBehaviour
pertencente `a classe Agent. Como exemplo considere a classe MeuAgente, cujo c´odigo est´a
ilustrado na Caixa de C´odigo 2.4.
odigo 2.4: MeuAgente.java
import ja de . co r e . Agent ;
import ja de . co r e . be ha vi ou rs . Behaviour ;
3public c l a s s MeuAgente extends Agent{
protected void se tu p ( ) {
6System . out . p r i n t l n ( "Ol´a , eu sou um agente." ) ;
System . out . p r i n t l n ( "Estou disparando meu comportamento ..." ) ;
addBehaviour (new MeuComportamento ( this) ) ;
9}
}
 
Quando um agente da classe MeuAgente ´e inicializado seu m´etodo setup() ´e exe-
cutado. A linha de c´odigo addBehaviour(new MeuComportamento(this)) indica a ini-
cializa¸ao de um comportamento que est´a especificado na classe MeuComportamento. O
parˆametro this indica que o agente que executar´a este comportamento ´e o pr´oprio agente
que est´a invocando o comportamento.
Toda classe que especifica o comportamento de um agente deve possuir os seguintes
m´etodos:
action() - neste m´etodo inclu´ımos o c´odigo referente ao comportamento a ser exe-
cutado pelo agente;
done() - este m´etodo devolve um valor booleano, indicando se o comportamento foi
finalizado ou n˜ao.
A classe MeuComportamento est´a contida na Caixa de C´odigo 2.5.
2.4. Comportamentos 11
odigo 2.5: MeuComportamento.java
import ja de . co r e . Agent ;
import ja de . co r e . be ha vi ou rs . Behaviour ;
3
public c l a s s MeuComportamento extends Behaviour{
int i =0;
6
public MeuComportamento ( Agent a ) {
super ( a ) ;
9}
public void a c t i o n ( ) {
System . out . p r i n t l n ( "* Ol´a Mundo! ... Meu nome ´e " + myAgent .
getLocalName ( ) ) ;
12 i=i +1;
}
15 public boolean done ( ) {
// ca so e s t e etodo r et o rn e TRUE o comportamento se r´a f i n a l i z a d o
return i>3;
18 }
}
 
O comportamento indicado nesta classe far´a com que sejam impressas quatro mensa-
gens de texto. Neste c´odigo, quando a vari´avel iassume um valor maior que 3, o m´etodo
done() retorna true e a execu¸ao do comportamento ´e finalizada.
´
E importante notar a utiliza¸ao da vari´avel myAgent. Trata-se de uma vari´avel nativa
de uma classe que herda jade.core.behaviours.Behaviour. Como um comportamento
tem que ser codificado em outra classe, esta vari´avel oferece a capacidade de acessar todos
os m´etodos e atributos do agente que est´a executando o comportamento. Isto justifica
a utiliza¸ao do m´etodo super(a) no m´etodo construtor da classe MeuComportamento.
Atrav´es da invoca¸ao do super(a) ´e que indicamos o agente que ser´a representado pela
vari´avel myAgent.
Observe tamem que a classe MeuComportamento.java ´e filha da classe Behaviour
(fazemos isto atrav´es do comando extends Behaviour). A mesma funcionalidade po-
deria ser alcan¸cada se esta fosse filha da classe SimpleBehaviour (e conseq¨
uentemente
ter´ıamos extends SimpleBehaviour). Logo, Behaviour possui a mesma funcionalidade
de SimpleBehaviour, pois SimpleBehaviour ´e uma classe-filha de Behaviour.
Ap´os compilar ambas as classes, podemos executar um agente:
java jade.Boot Agent1:MeuAgente
O resultado desta execu¸ao ´e o seguinte:
Ol´a, eu sou um agente.
2.4. Comportamentos 12
Estou disparando meu comportamento ...
* Ol´a Mundo! ... Meu nome ´e Agent1
* Ol´a Mundo! ... Meu nome ´e Agent1
* Ol´a Mundo! ... Meu nome ´e Agent1
* Ol´a Mundo! ... Meu nome ´e Agent1
2.4.1 Execu¸ao dos Comportamentos
Um agente pode executar v´arios comportamentos concorrentemente com o uso de um
escalonador. Um comportamento ´e executado at´e que seu m´etodo action() chegue ao
fim de sua execu¸ao. O escalonador controla a execu¸ao dos comportamentos de um
agente com as seguintes estruturas de dados:
Uma fila de comportamentos ativos;
Uma fila de comportamentos bloqueados.
A Figura 2.1, adaptada de [Bellifemine, Caire e Greenwood 2007], ilustra a intera¸ao
de um agente com estas filas com o uso de uma an´alise no ciclo de execu¸ao de um agente.
A execu¸ao de um agente na plataforma JADE ´e constitu´ıda por trˆes n´ıveis b´asicos.
ao eles:
1. Inicializa¸ao - Consiste na execu¸ao do m´etodo setup();
2. Realiza¸ao da tarefa - Representa o n´ıvel de execu¸ao dos comportamentos do agente.
O escalonador seleciona o primeiro comportamento da fila e executa seu m´etodo
action(). Ap´os a execu¸ao deste m´etodo, verifica-se a finaliza¸ao do comporta-
mento no m´etodo done(). Caso este comportamento ainda n˜ao esteja finalizado, o
escalonador captura o pr´oximo comportamento da lista de comportamentos ativos,
colocando este comportamento ainda n˜ao finalizado no final da fila, para ser poste-
riormente executado, ou seja, este comportamento ´e bloqueado at´e que chegue sua
vez de ser executado. Quando um comportamento ´e finalizado, ´e removido da lista
de comportamentos ativos e enviado para a lista de comportamentos bloqueados;
3. Limpeza e finaliza¸ao - Consiste na execu¸ao de m´etodos espec´ıficos para finaliza¸ao
do agente (e.g takeDown()).
2.4.2 Bloqueando Comportamentos
Com o uso do m´etodo block() ´e poss´ıvel bloquear um comportamento de um agente.
Com a execu¸ao deste m´etodo, o comportamento em execu¸ao ´e movido para a lista
2.4. Comportamentos 13
Figura 2.1: Ciclo de Execu¸ao de um Agente.
de comportamentos bloqueados at´e que um evento ocorra. Este m´etodo pode ser ´util
na recep¸ao de mensagens, por exemplo. No caso deste exemplo, um comportamento
espec´ıfico para recep¸ao de mensagens fica aguardando ser ativado quando uma nova
mensagem chegar ao agente.
Um objeto da classe Behaviour tamem pode se bloquear durante uma certa quan-
tidade de tempo, definida na execu¸ao do m´etodo block().´
E importante enfatizar que
este m´etodo n˜ao ´e igual ao sleep() de uma thread. O m´etodo block() ao p´ara a exe-
cu¸ao de um comportamento no momento em que ´e invocado. Ele aguarda a finaliza¸ao
do m´etodo action(). Caso este comportamento ainda n˜ao esteja finalizado (done() re-
torna false), este ´e colocado na fila de comportamentos bloqueados. Como j´a foi dito,
a permanˆencia deste comportamento na fila de comportamentos bloqueados pode ser por
um determinado tempo, ou at´e que um evento ocorra.
Como exemplo de utiliza¸ao do block() considere um agente que imprime na tela seu
nome local por 10 vezes, sendo que ele possui um intervalo entre as impress˜oes na tela de
2.4. Comportamentos 14
5 segundos. O c´odigo deste agente est´a contido nas Caixas de C´odigo 2.6 e 2.7.
odigo 2.6: AgenteImpressor.java
import ja de . co r e . Agent ;
public c l a s s AgenteImpressor extends Agent {
3
protected void se tu p ( ) {
6System . out . p r i n t l n ( "Ol´a! Eu sou um agente impressor!" ) ;
System . out . p r i n t l n ( "# Vou executar meu comportamento " ) ;
addBehaviour (new ImprimeFrase ( this , 5000) ) ;
9
}
}
 
odigo 2.7: ImprimeFrase.java
import ja de . co r e . Agent ;
import ja de . co r e . be ha vi ou rs . Behaviour ;
3
public c l a s s ImprimeFrase extends Behaviour{
int numExecu¸c˜ao=1;
6long de lay ;
long t e m p o I n i c i a l = System . c u r r e n t T i m e M i l l i s ( ) ;
9public ImprimeFrase ( Agent a , long d ela y ) {
super ( a ) ;
this . de la y = d ela y ;
12 }
public void a c t i o n ( ) {
15 bl oc k ( del ay ) ;
System . out . p r i n t l n ( "# Tempo " + ( System . c u r r e n t T i m e M i l l i s ( )
tempoInicial) + ": Meu nome ´e " + myAgent . getLocalName ( ) ) ;
numExecu¸c˜ao = numExecu¸c˜ao+1;
18 }
public boolean done ( ) {
21 return numExecu¸ao >10;
}
24
public in t onEnd ( ) {
27 System . out . p r i n t l n ( myAgent . getLocalName ( ) + ": Meu comportamento foi
fina lizado ! At´e mais ... " ) ;
2.4. Comportamentos 15
return 0 ;
}}
 
Na classe AgenteImpressor temos um agente que executa seu comportamento que
est´a implementado na classe ImprimeFrase.
A linha de c´odigo addBehaviour(new ImprimeFrase(this,5000)) passa os parˆame-
tros necess´arios para execu¸ao do comportamento. O m´etodo block recebe valores do
tipo long, representados em milisegundos. Isto justifica a utiliza¸ao do valor 5000, para
indicar que o tempo entre cada frase impressa ser´a de 5 segundos.
Observe que o comando block() est´a no in´ıcio do bloco de comandos do m´etodo
action() da classe ImprimeFrase. Isto n˜ao indica que o block() ser´a executado primeiro.
Este ser´a executado ao fim do bloco de comandos do m´etodo action().
A classe ImprimeFrase tamb´em nos revela um novo m´etodo: trata-se do m´etodo
onEnd(). Este m´etodo retorna um valor inteiro que representa um valor de finaliza¸ao
para o comportamento. Este m´etodo ´e invocado ap´os o comportamento estar conclu´ıdo e
ap´os este ser movido para a lista de comportamentos bloqueados, pois ´e poss´ıvel reiniciar
este comportamento com a utiliza¸ao do m´etodo reset().´
E poss´ıvel, tamem, utilizar o
m´etodo onStart() que ´e acionado no in´ıcio da execu¸ao do comportamento.
Com a execu¸ao do agente teste temos a seguinte sa´ıda:
java jade.Boot teste:AgenteImpressor
...
Ol´a! Eu sou um agente impressor!
# Vou executar meu comportamento
# Tempo 0: Meu nome ´e teste
# Tempo 5015: Meu nome ´e teste
# Tempo 10031: Meu nome ´e teste
# Tempo 15046: Meu nome ´e teste
# Tempo 20062: Meu nome ´e teste
# Tempo 25078: Meu nome ´e teste
# Tempo 30093: Meu nome ´e teste
# Tempo 35109: Meu nome ´e teste
# Tempo 40125: Meu nome ´e teste
# Tempo 45140: Meu nome ´e teste
teste: Meu comportamento foi finalizado! At´e mais...
Vamos aproveitar este momento para abordar o conceito de concorrˆencia entre agen-
tes. Cada agente JADE ´e uma thread. Isto significa que a execu¸ao destes agentes ser´a
escalonada. Vamos testar a seguinte aplica¸ao, iniciando trˆes agentes ao mesmo tempo na
2.4. Comportamentos 16
plataforma. Cada agente passar´a como argumento seu tempo de impress˜ao de mensagem
na tela. O c´odigo referente `a classe de agente que vamos utilizar est´a na Caixa de C´odigo
2.8. O comportamento dos agentes ser´a o mesmo descrito na Caixa de C´odigo 2.7.
odigo 2.8: AgenteImpressorArgs.java
import ja de . c o re . Agent ;
import j a de . c o r e . ;
3
public c l a s s AgenteImpressorArgs extends Agent {
6protected void s etu p ( ) {
Ob ject [ ] a rg s = getArguments ( ) ;
9i f ( a rg s != n u l l && a rg s . l ength >0)
{
long v a l o r = Long . p ars eLon g ( ( S t r i n g ) a r g s [ 0 ] ) ;
12 System . out . p r i n t l n ( "Ol´a! Eu sou um agente impressor !" ) ;
System . out . p r i n t l n ( "# Vou executar meu comportamento " ) ;
addBehaviour (new ImprimeFrase ( this , v a l o r ) ) ;
15 }e l s e
System . out . p r i n t l n ( "Voc^e n~ao passou argumentos " ) ;
18
}
21 }
 
A linha de execu¸ao no prompt ser´a a seguinte:
java jade.Boot Andre:AgenteImpressorArgs(200)
Maria:AgenteImpressorArgs(400) Paulo:AgenteImpressorArgs(600)
Isto implica que o agente Andre executar´a seu comportamento a cada 0.2 seg., o agente
Maria a cada 0,4 seg. e o agente Paulo a cada 0.6 seg. O resultado obtido ´e o seguinte:
Ol´a! Eu sou um agente impressor!
# Vou executar meu comportamento
# Tempo 0: Meu nome ´e Andre
Ol´a! Eu sou um agente impressor!
# Vou executar meu comportamento
# Tempo 0: Meu nome ´e Maria
Ol´a! Eu sou um agente impressor!
# Vou executar meu comportamento
# Tempo 0: Meu nome ´e Paulo
# Tempo 203: Meu nome ´e Andre
2.5. Comportamentos Pr´e-Definidos 17
# Tempo 406: Meu nome ´e Maria
# Tempo 406: Meu nome ´e Andre
# Tempo 610: Meu nome ´e Paulo
# Tempo 610: Meu nome ´e Andre
# Tempo 813: Meu nome ´e Maria
# Tempo 813: Meu nome ´e Andre
# Tempo 1016: Meu nome ´e Andre
# Tempo 1219: Meu nome ´e Paulo
# Tempo 1219: Meu nome ´e Maria
# Tempo 1219: Meu nome ´e Andre
# Tempo 1422: Meu nome ´e Andre
# Tempo 1625: Meu nome ´e Maria
# Tempo 1625: Meu nome ´e Andre
# Tempo 1828: Meu nome ´e Paulo
# Tempo 1828: Meu nome ´e Andre
Andre: Meu comportamento foi finalizado! At´e mais...
# Tempo 2031: Meu nome ´e Maria
# Tempo 2438: Meu nome ´e Paulo
# Tempo 2438: Meu nome ´e Maria
# Tempo 2844: Meu nome ´e Maria
# Tempo 3047: Meu nome ´e Paulo
# Tempo 3250: Meu nome ´e Maria
# Tempo 3657: Meu nome ´e Paulo
# Tempo 3656: Meu nome ´e Maria
Maria: Meu comportamento foi finalizado! At´e mais...
# Tempo 4266: Meu nome ´e Paulo
# Tempo 4875: Meu nome ´e Paulo
# Tempo 5485: Meu nome ´e Paulo
Paulo: Meu comportamento foi finalizado! At´e mais...
2.5 Comportamentos Pr´e-Definidos
JADE conta com uma s´erie de comportamentos pr´e-definidos que auxiliam o desenvolvedor
na constru¸ao de sistemas multiagentes. Pode-se agrupar os comportamentos oferecidos
por JADE em quatro grupos:
1. Comportamentos one-shot: tipos de comportamentos que se executam de maneira
quase instananea, e apenas uma vez;
2. Comportamentos c´ıclicos: ao aqueles comportamentos que nunca finalizam. O
2.5. Comportamentos Pr´e-Definidos 18
m´etodo action() deste comportamento ´e sempre executado pois done() sempre
retorna false;
3. Comportamentos temporais: ao comportamentos que incluem uma rela¸ao tempo-
ral em sua execu¸ao;
4. Comportamentos compostos: ao comportamentos que modelam situa¸oes espec´ıfi-
cas, tais como comportamentos seq¨
uenciais, paralelos, etc.
A seguir tem-se uma breve introdu¸ao aos tipos de comportamentos pr´e-definidos. Os
exemplos mais completos destes comportamentos s˜ao mostrados no decorrer deste manual,
juntamente com o avan¸co das funcionalidades dos agentes e dos servi¸cos oferecidos pela
plataforma.
2.5.1 Comportamentos One-shot
Neste comportamento o m´etodo done() sempre retorna o valor true, fazendo com que
seja executado apenas uma vez. Para utiliza¸ao deste comportamento deve-se importar a
classe jade.core.behaviours.OneShotBehaviour. A estrutura da implementa¸ao deste
comportamento d´a-se conforme ilustrado na Caixa de C´odigo 2.9. Em seguida, na Figura
2.10, ilustra-se o c´odigo de agente invocando este comportamento.
odigo 2.9: Exemplo OneShot Behaviour
import ja de . c o re . b eh av io ur s . OneShotBehaviour ;
public c l a s s ComportamentoOneShot extends OneShotBehaviour {
3public void a c t i o n ( ) {
// c ´o d i g o a s e r e xe c ut a d o
}
6}
 
odigo 2.10: AgenteComportamentoOneShot.java
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . ;
3
public c l a s s AgenteComportamentoOneShot extends Agent{
protected void s etu p ( ) {
6addBehaviour (new ComportamentoOneShot( this ) ) ;
}
}
 
2.5. Comportamentos Pr´e-Definidos 19
2.5.2 Comportamentos C´ıclicos
Neste comportamento o m´etodo done() sempre devolve false. Este comportamento se
manem ativo enquanto o agente estiver ativo na plataforma. Para utiliza¸ao deste com-
portamento deve-se importar a classe jade.core.behaviours.CyclicBehaviour. Sua
estrutura de implementa¸ao est´a ilustrada na Caixa de C´odigo 2.11. Em seguida, na
Figura 2.12, ilustra-se o c´odigo de agente invocando este comportamento.
odigo 2.11: Exemplo Cyclic Behaviour
import j a de . c o r e . b e h a vi o u r s . C y c li c B e h av i o u r ;
public c l a s s ComportamentoCiclico extends CyclicBehaviour {
3public void a c t i o n ( ) {
// c ´o d i g o a s e r e xe c ut a d o
}
6}
 
odigo 2.12: AgenteComportamentoCiclico.java
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . ;
3
public c l a s s AgenteComportamentoCiclico extends Agent{
protected void s etu p ( ) {
6addBehaviour (new ComportamentoCiclico(this , 300) ) ;
}
}
 
2.5.3 Comportamentos Temporais
Neste tipo de comportamentos encontram-se os comportamentos WakerBehaviour eTic-
kerBehaviour. Ambos possuem uma estreita rela¸ao com o tempo durante sua execu¸ao.
Aos serem invocados, ambos aguardam at´e que se tenha cumprido um tempo definido
(time-out) para serem executados. A diferen¸ca ´e que o WakerBehaviour executa apenas
uma ´unica vez, enquanto que o TickerBehaviour realiza um comportamento c´ıclico.
Como exemplo de um comportamento WakerBehaviour, considere um agente que exe-
cuta seu comportamento ap´os 1 minuto da invoca¸ao do mesmo e depois n˜ao ´e mais
executado, conforme consta na Caixa de C´odigo 2.13. Para utiliza¸ao deste comporta-
mento deve-se importar a classe jade.core.behaviours.WakerBehaviour. O m´etodo
que executa a a¸ao do agente do tipo WakerBehaviour ´e o m´etodo onWake()2. Este
m´etodo ´e executado logo ap´os o time-out.
2Pode-se tamb´em utilizar o m´etodo void handleElapsedTimeout(), cuja funcionalidade ´e a mesma
do onWake().
2.5. Comportamentos Pr´e-Definidos 20
odigo 2.13: Exemplo Waker Behaviour
import ja de . c o re . Agent ;
import ja de . c o re . b eh av io ur s . WakerBehaviour ;
3public c l a s s Waker extends Agent {
protected void s etu p ( ) {
System . out . p r i n t l n ( " Adicionando waker behaviour" ) ;
6
addBehaviour (new WakerBehaviour ( this , 10000) {
protected void onWake ( ) {
9// r e a l i z a opera¸c˜a o X
}
}) ;
12 }
}
 
OTickerBehaviour possui seus m´etodos action() edone() pr´e-implementados, bas-
tando para o desenvolvedor implementar o m´etodo onTick(). Um comportamento ticker
nunca termina ao menos que seja removido pelos m´etodos removeBehaviour() ou stop().
A Caixa de C´odigo 2.14 ilustra um agente que executa um TickerBehaviour, exibindo
a cada segundo o n´umero de seu ciclo (tick). Para utiliza¸ao deste comportamento deve-se
importar a classe jade.core.behaviours.TickerBehaviour.´
E poss´ıvel obter o n´umero
de ciclos atrav´es do m´etodo getTickCount(), que retorna um valor inteiro que representa
o ciclo do agente. Observe que ap´os 5 ciclos o comportamento ´e interrompido com o
m´etodo stop(). Este tamb´em pode ser reiniciado com o o m´etodo reset(), fazendo
com que o comportamento fosse novamente iniciado e o n´umero de ciclos executados seja
zerado.
odigo 2.14: Exemplo Ticker Behaviour
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . T ic k er Be h av i ou r ;
3public c l a s s Ticker extends Agent {
protected void s etu p ( ) {
System . out . p r i n t l n ( " Adicionando TickerBehaviour" ) ;
6
addBehaviour (new Tick erBe ha viou r ( this , 1 0 0 0 ) {
protected void onTick ( ) {
9i f ( getTickCount ( ) >5){
st op ( ) ;
}e l s e
12 // g et Ti ck C ou nt ( ) r e to r n a o n´umero de e x e c u¸c ˜o e s
// do comportamento .
System . out . p r i n t l n ( "Estou realizando meu " +
getTickCount () + " tick" ) ;
15 }
}) ;
2.5. Comportamentos Pr´e-Definidos 21
}
18 }
 
Tem-se como resultado da execu¸ao deste agente:
Adicionando TickerBehaviour
Estou realizando meu 1 tick
Estou realizando meu 2 tick
Estou realizando meu 3 tick
Estou realizando meu 4 tick
Estou realizando meu 5 tick
2.5.4 Comportamentos Compostos
Comportamentos compostos s˜ao aqueles formados por sub-comportamentos. A pol´ıtica de
sele¸ao de comportamentos filhos est´a implementada em trˆes subclasses: SequencialBeha-
viour,ParallelBehaviour eFSMBehaviour. Os trˆes tipos de comportamentos compostos
ser˜ao apresentados nas pr´oximas se¸oes.
2.5.4.1 SequencialBehaviour
Este comportamento executa seus sub-comportamentos de maneira seq¨
uencial e termina
quando todos seus sub-comportamentos estiverem conclu´ıdos. A pol´ıtica de escalona-
mento dos sub-comportamentos est´a descrita a seguir. O comportamento inicia execu-
tando seu primeiro sub-comportamento. Quando este sub-comportamento ´e finalizado
(isto ´e, seu m´etodo done() retorna true), o segundo sub-comportamento ´e executado e
assim por diante. Quando o ´ultimo sub-comportamento ´e finalizado, o comportamento
composto seq¨
uencial ´e finalizado.
Os sub-comportamentos s˜ao adicionados ao comportamento composto com o m´etodo
addSubBehaviour(). A ordem em que estes sub-comportamentos s˜ao adicionados indica
a ordem de execu¸ao dos mesmos. Na Caixa de C´odigo 2.15 tem-se um exemplo de um
agente que executa seq¨
uencialmente trˆes comportamentos.
odigo 2.15: AgenteSequencial.java
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . ; ;
3
public c l a s s AgenteSequencial extends Agent{
6protected void s etu p ( ) {
2.5. Comportamentos Pr´e-Definidos 22
//mensagem de i n i c i a l i z a ¸c ˜a o do a gen te
System . out . p r i n t l n ( "Ol´a! Meu nome ´e " + getLocalName ( ) ) ;
9System . out . p r i n t l n ( "Vou executar tr^es comportamentos :" ) ;
// cr iamo s um o b j e t o da c l a s s e S e q u e n t i a l B e h a v i o u r
12 Se qu e nt ia lB eh a vi ou r comportamento = new Se qu e nt ia lB eh av i ou r ( this){
public in t onEnd ( ) {
15 myAgent . d oD el ete ( ) ;
return 0 ;
}
18
};
// adicionamos seu p ri me ir o comportamento
21 comportamento . addSubBehaviour (new WakerBehaviour ( this , 500 ) {
long t0 = System . c u r r e n t T i m e M i l l i s ( ) ;
protected void onWake ( ) {
24 System . o ut . p r i n t l n ( ( System . c u r r e n t T i m e M i l l i s ( ) t0 ) +":
Executei meu primeiro comportamento ap´os meio segundo !" )
;
}
}) ;
27
// adicionamos seu segundo comportamento
comportamento . addSubBehaviour (new OneShotBehaviour( this ){
30
public void a c t i o n ( ) {
System . out . p r i n t l n ( " Executei meu segundo comportamento " ) ;
33 }
}) ;
36 // adicionamos seu t e r c e i r o comportamento
comportamento . addSubBehaviour (new Tic kerB eh avio ur ( this , 700) {
int exec =0;
39 long t1 = System . c u r r e n t T i m e M i l l i s ( ) ;
protected void onTick ( ) {
i f ( e xe c==3) st op ( ) ;
42 e l s e {
System . o ut . p r i n t l n ( ( System . c u r r e n t T i m e M i l l i s ( )t1 )+
": Estou executando meu terceiro comportamento " ) ;
exec++;
45 }
}
}) ;
48
// acionamos sua ex ec u¸c˜ao ;
addBehaviour ( comportamento ) ;
2.5. Comportamentos Pr´e-Definidos 23
51
}
54
protected void takeDown () {
System . out . p r i n t l n ( "Fui finalizado com sucesso" ) ;
57
}
}
 
Este agente adiciona trˆes sub-comportamentos para seu comportamento composto.
Podemos ter estes trˆes comportamentos em classes separadas e apenas adicion´a-las ao
comportamento composto.
Executando no prompt a linha java jade.Boot Nick:AgenteSequencial, tem-se a
seguinte execu¸ao:
Ol´a! Meu nome ´e Nick
Vou executar tr^es comportamentos:
515: Executei meu primeiro comportamento ap´os meio segundo!
Executei meu segundo comportamento
1218: Estou executando meu terceiro comportamento
1921: Estou executando meu terceiro comportamento
2625: Estou executando meu terceiro comportamento
Fui finalizado com sucesso
2.5.4.2 ParallelBehaviour
OParallelBehaviours implementa um comportamento composto que escalona seus sub-
comportamentos em paralelo. Toda vez que o m´etodo action() do comportamento pa-
ralelo ´e executado, o m´etodo action() de seus sub-comportamentos ´e executado.
Um comportamento paralelo pode ser instru´ıdo para ser finalizado quando todos os
comportamentos paralelos estiverem completos, ou quando algum deles ´e finalizado. Al´em
disto, ´e poss´ıvel definir a finaliza¸ao do comportamento composto para quando um certo
n´umero nde sub-comportamentos estiverem finalizados. Essas condi¸oes s˜ao definidas
no construtor da classe, passando como parˆametro as constantes when all, quando for
todos, when any, quando for algum, ou um valor inteiro que especifica o n´umero de
sub-comportamentos que s˜ao necess´arios para finalizar o ParallelBehaviour.
A seguir tem-se um exemplo de um agente com comportamento paralelo. O c´odigo
deste agente est´a na Caixa de C´odigo 2.16.
odigo 2.16: AgenteCompParalelo.java
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . ;
2.5. Comportamentos Pr´e-Definidos 24
3
public c l a s s AgenteCompParalelo extends Agent{
6
protected void setup () {
System . out . p r i n t l n ( "Ol´a! Eu sou o agente " + getLocalName ( ) ) ;
9System . out . p r i n t l n ( "Vou executar tr^es comportamentos concorrentemente" ) ;
P a r a l l e l B e h a v i o u r s = new P a r a l l e l B e h a v i o u r ( this ,WHEN ALL) {
12
public in t onEnd ( ) {
System . out . p r i n t l n ( " Comportamento Composto Finalizado com
Sucesso!" ) ;
15 return 0 ;
}
18 };
addBehaviour ( s ) ;
s . addSubBehaviour (new SimpleBehaviour ( this ){
21 int qtd =1;
public void a c t i o n ( ) {
24 System . out . p r i n t l n ( " Comportamento 1: Executando pela "
+ qtd + " vez" ) ;
qtd = qtd +1;
27 }
30 public boolean done ( ) {
i f ( qtd==4) {
System . out . p r i n t l n ( " Comportamento 1 - Finalizado" ) ;
33 return true ;
}e l s e
return f a l s e ;
36 }
}) ;
39 s . addSubBehaviour (new SimpleBehaviour ( this ){
int qtd =1;
42 public void a c t i o n ( ) {
System . out . p r i n t l n ( " Comportamento 2: Executando pela "
+ qtd + " vez" ) ;
qtd = qtd +1;
45
}
2.5. Comportamentos Pr´e-Definidos 25
48
public boolean done ( ) {
i f ( qtd==8) {
51 System . out . p r i n t l n ( " Comportamento 2 - Finalizado" ) ;
return true ;
}e l s e
54 return f a l s e ;
}
}) ;
57
s . addSubBehaviour (new SimpleBehaviour ( this ){
int qtd =1;
60
public void a c t i o n ( ) {
System . out . p r i n t l n ( " Comportamento 3: Executando pela "
+ qtd + " vez" ) ;
63 qtd = qtd +1;
}
66
public boolean done ( ) {
69 i f ( qtd==10) {
System . out . p r i n t l n ( " Comportamento 3 - Finalizado" ) ;
return true ;
72 }e l s e
return f a l s e ;
}
75 }) ;
}
78 }
 
Executando a linha de comando java jade.Boot Azul:AgenteCompParalelo tem-se
o seguinte resultado:
Ol´a! Eu sou o agente Azul
Vou executar tr^es comportamentos concorrentemente
Comportamento 1: Executando pela 1 vez
Comportamento 2: Executando pela 1 vez
Comportamento 3: Executando pela 1 vez
Comportamento 1: Executando pela 2 vez
Comportamento 2: Executando pela 2 vez
Comportamento 3: Executando pela 2 vez
Comportamento 1: Executando pela 3 vez
2.5. Comportamentos Pr´e-Definidos 26
Comportamento 1 - Finalizado
Comportamento 3: Executando pela 3 vez
Comportamento 2: Executando pela 3 vez
Comportamento 3: Executando pela 4 vez
Comportamento 2: Executando pela 4 vez
Comportamento 3: Executando pela 5 vez
Comportamento 2: Executando pela 5 vez
Comportamento 3: Executando pela 6 vez
Comportamento 2: Executando pela 6 vez
Comportamento 3: Executando pela 7 vez
Comportamento 2: Executando pela 7 vez
Comportamento 2 - Finalizado
Comportamento 3: Executando pela 8 vez
Comportamento 3: Executando pela 9 vez
Comportamento 3 - Finalizado
Comportamento Composto Finalizado com Sucesso!
Observe na linha 11 que o comando ParallelBehaviour s = new ParallelBehaviour
(this, ParallelBehaviour.WHEN_ALL) constr´oi o objeto sda classe ParallelBehaviour.
Em seu construtor passamos o parˆametro inteiro ParallelBehaviour.WHEN_ALL. Este
parˆametro indica que ap´os todos os sub-comportamentos estarem conclu´ıdos, o compor-
tamento composto ser´a finalizado, ativando seu m´etodo onEnd().
Vamos mudar este parˆametro para ParallelBehaviour.WHEN_ANY. Isto indica que
quando qualquer um dos sub-comportamentos for finalizado, o comportamento composto
´e finalizado. Executando novamente o agente obtemos o seguinte resultado:
Ol´a! Eu sou o agente Azul
Vou executar tr^es comportamentos concorrentemente
Comportamento 1: Executando pela 1 vez
Comportamento 2: Executando pela 1 vez
Comportamento 3: Executando pela 1 vez
Comportamento 1: Executando pela 2 vez
Comportamento 2: Executando pela 2 vez
Comportamento 3: Executando pela 2 vez
Comportamento 1: Executando pela 3 vez
Comportamento 1 - Finalizado
Comportamento Composto Finalizado com Sucesso!
Como prev´ıamos, o comportamento composto foi finalizado ap´os a finaliza¸ao de um
dos sub-comportamentos. Podemos tamb´em definir que o comportamento composto fi-
nalize ap´os um certo n´umero de finaliza¸oes de seus sub-comportamentos. Podemos
2.5. Comportamentos Pr´e-Definidos 27
utilizar como parˆametro um valor inteiro, por exemplo: ParallelBehaviour s = new
ParallelBehaviour(this, 2), onde 2 indica que ap´os dois sub-comportamentos serem
finalizados o comportamento composto ser´a finalizado. O resultado da execu¸ao do agente
com esse novo parˆametro de comportamento ´e exibido a seguir:
Ol´a! Eu sou o agente Azul
Vou executar tr^es comportamentos concorrentemente
Comportamento 1: Executando pela 1 vez
Comportamento 2: Executando pela 1 vez
Comportamento 3: Executando pela 1 vez
Comportamento 1: Executando pela 2 vez
Comportamento 2: Executando pela 2 vez
Comportamento 3: Executando pela 2 vez
Comportamento 1: Executando pela 3 vez
Comportamento 1 - Finalizado
Comportamento 3: Executando pela 3 vez
Comportamento 2: Executando pela 3 vez
Comportamento 3: Executando pela 4 vez
Comportamento 2: Executando pela 4 vez
Comportamento 3: Executando pela 5 vez
Comportamento 2: Executando pela 5 vez
Comportamento 3: Executando pela 6 vez
Comportamento 2: Executando pela 6 vez
Comportamento 3: Executando pela 7 vez
Comportamento 2: Executando pela 7 vez
Comportamento 2 - Finalizado
Comportamento Composto Finalizado com Sucesso!
2.5.4.3 FSMBehaviour
Este comportamento ´e baseado no escalonamento por uma m´aquina finita de estados
(Finite State Machine). O FSMBehaviour executa cada sub-comportamento de acordo
com uma m´aquina de estados finitos definido pelo usu´ario. Mais especificamente, cada
sub-comportamento representa um estado definido na m´aquina de estados finitos. Ela
fornece m´etodos para registrar estados (sub-comportamentos) e transi¸oes que definem
como dar-se-´a o escalonamento dos sub-comportamentos. Os passos b´asicos para se definir
um FSMBehaviour ao:
1. Registrar um comportamento ´unico como estado inicial, passando como parˆametros
o comportamento e uma String que nomeia este estado. Para isto utiliza-se o m´etodo
2.5. Comportamentos Pr´e-Definidos 28
registerFirstState();
2. Registrar um ou mais comportamentos como estados finais, utilizando o m´etodo
registerLastState();
3. Registrar um ou mais comportamentos como estados intermedi´arios utilizando o
m´etodo registerState();
4. Para cada estado, registrar as transi¸oes deste com os outros estados utilizando o
m´etodo registerTransition(). Por exemplo, suponha que vocˆe tenha um estado
definido como Xe outro estado definido como Ye voe deseja informar que a transi¸ao
ser´a feita do estado Xpara o Y, quando o estado Xretornar o valor 1. O m´etodo
seria definido como registerTransition(X,Y,1).
Considere um agente que realiza um determinado comportamento x. Ao final deste
comportamento ´e verificada se sua opera¸ao foi conclu´ıda. Caso esta opera¸ao n˜ao seja
conclu´ıda, um comportamento z´e efetuado. Ao t´ermino do comportamento z, o compor-
tamento x´e executado novamente e toda a verifica¸ao ocorre novamente. Na execu¸ao
em que o comportamento xestiver conclu´ıdo, ser´a invocado o ´ultimo comportamento do
agente, o comportamento y. Este algoritmo est´a ilustrado na Figura 2.2 e o c´odigo deste
agente encontra-se Caixa de C´odigo 2.17.
Figura 2.2: Exemplo de M´aquina de Estado Finito.
2.5. Comportamentos Pr´e-Definidos 29
odigo 2.17: AgenteFSM.java
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . ;
3public c l a s s AgenteFSM extends Agent{
protected void s etu p ( ) {
6
FSMBehaviour compFSM = new FSMBehaviour( this ){
9public in t onEnd ( ) {
System . out . p r i n t l n ( " Comportamento FSM finalizado com
sucesso!" ) ;
return 0 ;
12 }
};
15 // r e g i s t r a m o s o p r im e ir o comportamento X
compFSM. r e g i s t e r F i r s t S t a t e (new OneShotBehaviour( this ){
18 int c =0;
public void a c t i o n ( ) {
System . out . p r i n t l n ( " Executando Comportamento X" ) ;
21 c++;
}
24
public in t onEnd ( ) {
return ( c>4? 1 : 0 ) ;
27 }
},"X") ;
30 // r e g i s t r a m o s o ut r o e s t a d o Z
compFSM. r e g i s t e r S t a t e (new OneShotBehaviour( this){
33
public void a c t i o n ( ) {
System . out . p r i n t l n ( " Executando Comportamento Z" ) ;
36 }
public in t onEnd ( ) {
return 2 ;
39 }
},"Z") ;
42
// r e g i s t r a m o s o ´u l t i m o e s t a d o Y
compFSM. r e g i s t e r L a s t S t a t e (new OneShotBehaviour ( this){
45
2.5. Comportamentos Pr´e-Definidos 30
public void a c t i o n ( ) {
System . out . p r i n t l n ( " Executando meu ´ultimo comportamento." ) ;
48 }
},"Y") ;
51 // d ef in im os as t r a n s i ¸c ˜o e s
compFSM. r e g i s t e r T r a n s i t i o n ( "X" ,"Z" , 0) ; //X >Z , ca so onEnd ( )
do X r e t o r n e 0
compFSM. r e g i s t e r T r a n s i t i o n ( "X" ,"Y" , 1) ; //X >Y, c as o onEnd ( )
do X r e t o r n e 1
54
// d e fi ni m os uma t r a n s i ¸c ˜a o padr˜ao ( n˜ao importa t i p o de r et o rn o )
//como a m´aquina ´e f i n i t a , temos que z er ar os e st ad o s X e Z >new
S t r i n g [ ] {”X” , ”Z}
57 compFSM. r e g i s t e r D e f a u l t T r a n s i t i o n ( "Z" ,"X" ,new S t r i n g [ ] {"X" ,"Z"}) ;
// Podemos tamem r e g i s t r a r uma t r a n s i ¸c ˜a o quando o e s t a d o Z r e t o r n a r
2
//compFSM. r e g i s t e r T r a n s i t i o n ( ”Z” , X, 2) ;
60
// acionamos o comportamento
addBehaviour (compFSM) ;
63
}
}
 
Ao executarmos java jade.Boot Caio:AgenteFSM obtemos o seguinte resultado:
Executando Comportamento X
Executando Comportamento Z
Executando Comportamento X
Executando Comportamento Z
Executando Comportamento X
Executando Comportamento Z
Executando Comportamento X
Executando Comportamento Z
Executando Comportamento X
Executando meu ´ultimo comportamento.
Comportamento FSM finalizado com sucesso!
Observe que o comportamento X foi executado 5 vezes e ao final de cada execu¸ao o
comportamento Z era invocado. Quando c>4, a execu¸ao de X estava completa e com isto,
o ´ultimo comportamento foi invocado. Observe no c´odigo deste agente que definimos um
estado com o m´etodo registerState(Comportamento, Nome do Comportamento). As
transi¸oes definimos com registerTransition(Origem, Destino, Retorno da Origem).
O m´etodo registerDefaultTransition() define uma transi¸ao padr˜ao, ou seja, uma
2.5. Comportamentos Pr´e-Definidos 31
transi¸ao que ocorre sempre de um estado para o outro independente do retorno obtido
na execu¸ao do estado de origem.
´
E importante enfatizar que a linha de c´odigo compFSM.registerDefaultTransition("Z",
"X", new String[]{"X", "Z"}) registra uma transi¸ao padr˜ao entre Z e X, mas como
ambos estados j´a foram executados e como s˜ao comportamentos one-shot o poderiam
executar uma vez. Por isto, temos o argumento new String[]{"X", "Z"} zerando as
informa¸oes sobre estes estados, possibilitando que possam ser novamente executados.
Cap´ıtulo 3
Comunica¸ao entre Agentes
A comunica¸ao entre agentes ´e fundamental para a execu¸ao de sistemas multiagentes.
Ela determina o comportamento em uma sociedade, permitindo que um agente n˜ao seja
apenas um programa que executa seus comportamentos, mas tamb´em um programa que
recebe e envia pedidos aos demais agentes.
3.1 Envio e Recebimento de Mensagens
A troca de mensagens na plataforma JADE realiza-se mediante mensagens FIPA-ACL.
JADE disponibiliza um mecanismo ass´ıncrono de mensagens: cada agente possui uma
fila de mensagens (caixa de entrada), onde este agente decide o momento de ler estas
mensagens. No momento desejado pelo agente este pode ler apenas a primeira mensagem,
ou ler as mensagens que satisfazem algum crit´erio.
As mensagens trocadas s˜ao instanciadas da classe jade.lang.acl.ACLMessage. A
seguir apresenta-se como os agentes podem enviar e receber estas mensagens.
3.1.1 Classe ACLMessage
A classe ACLMessage disponibiliza uma s´erie de m´etodos para manipula¸ao das mensagens.
Dentre os m´etodos mais utilizados cita-se:
setPerformative(int): recebe como parˆametro uma constante que representa o
ato comunicativo da mensagem. Por exemplo, uma mensagem msg que tenha o ato
agree ser´a escrita como: msg.setPerformative(ACLMessage.AGREE). Os c´odigos
das performatives est˜ao contidos na Tabela 3.1;
getPerformative(): devolve um inteiro equivalente `a constante que representa o
ato comunicativo da mensagem;
32
3.1. Envio e Recebimento de Mensagens 33
Tabela 3.1: Valores Inteiros das Performatives.
createReply(): cria uma mensagem de resposta para uma mensagem recebida, cap-
turando automaticamente alguns campos tais como: receiver, conversation-id,
etc;
addReceiver(AID): recebe como parˆametro um objeto AID (Agent Identifier) e o
adiciona `a lista de receptores;
getAllReceiver(): devolve um objeto iterator contendo a lista de receptores;
setContent(String): recebe como parˆametro uma String e a coloca como conte´udo
da mensagem;
getContent(): devolve o conte´udo da mensagem;
setContentObject(Serializable s): recebe como parˆametro um objeto de uma
classe que implementa serializa¸ao. Por meio deste m´etodo ´e poss´ıvel transmitir
objetos como conte´udos das mensagens;
getContentObject(): devolve o objeto que est´a no conte´udo da mensagem.
3.1.2 Enviar uma Mensagem
Existem alguns passos a serem seguidos para envio de mensagens. ao eles:
1. Crie um objeto ACLMessage;
2. Use os m´etodos dispon´ıveis para preencher os campos necess´arios (conte´udo, onto-
logia, receptor, etc);
3.1. Envio e Recebimento de Mensagens 34
3. Invoque o m´etodo send() da classe Agent. Este m´etodo recebe como parˆametro
um objeto ACLMessage e adiciona automaticamente o campo do remetente com a
identifica¸ao do agente, e envia a mensagem aos destinat´arios.
Por exemplo, considere que desejamos enviar a seguinte mensagem:
(QUERY-IF
:receiver (set (agent-identifier :name pcseller) )
:content "(pc-offer (mb 256) (processor celeron) (price ?p))"
:language Jess
:ontology PC-ontology
)
Esta mensagem de exemplo representa um pedido de um agente para o outro, onde o
solicitante deseja obter o pre¸co (que ser´a armazenado na vari´avel p) de um computador
com processador Celeron e 256 MB de mem´oria. Para o envio desta mensagem escreva o
odigo contido na Caixa de C´odigo 3.1.
odigo 3.1: Envio de Mensagem
ACLMessage msg = new ACLMessage ( ACLMessage . QUERY IF) ;
msg . se tO nto lo gy ( "PC -ontology" ) ;
3msg . setLanguage ( "Jess" ) ;
msg . addR ec eiver (new AID( " pcseller " , AID .ISLOCALNAME) ;
msg . s etC on ten t ( "(pc -offer (mb 256) ( processor celeron) (price ?p))" ) ;
6send (msg ) ;
 
Observe que utilizamos o m´etodo addReceiver() pois podemos adicionar v´arios re-
ceptores. Quando sabemos o nome de um agente e queremos que ele seja o receptor
da mensagem devemos criar um objeto da classe AID. Um objeto da classe AID ´e cri-
ado passando as seguintes informa¸oes: AID agente1 = new AID("Nome do Agente",
AID.ISLOCALNAME), onde o segundo parˆametro indica que o nome que estamos passando
ao se trata do nome global do agente, mas sim de seu nome local.
3.1.3 Receber uma Mensagem
Para receber uma mensagem deve-se utilizar o m´etodo receive() da classe Agent. Este
m´etodo captura a primeira mensagem da fila de mensagens (se n˜ao houver mensagens, o
m´etodo retorna null). Na Caixa de C´odigo 3.2 tem-se um agente que imprime todas as
mensagens que recebe.
3.1. Envio e Recebimento de Mensagens 35
odigo 3.2: Receiver.java
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . C y c li c B e h av i o u r ;
3import ja de . la ng . a c l . ACLMessage ;
6public c l a s s Receiver extends Agent{
protected void s etu p ( ) {
9addBehaviour (new Cy cli cB eha vi our ( this){
public void a c t i o n ( ) {
ACLMessage msg = r e c e i v e ( ) ;
12 i f ( msg!= nu l l )
System . out . p r i n t l n ( " - " + myAgent . getLocalName ( ) + "
<- " + msg . getConte nt ( ) ) ;
// i nt e r ro m pe e s t e comportamento a t ´e qu e c he gu e uma nova mensagem
15 b lo ck ( ) ;
}
}) ;
18 }
}
 
Observe o uso do comando block() sem um argumento de time-out. Este m´etodo
coloca o comportamento na lista de comportamentos bloqueados at´e que uma nova men-
sagem chegue ao agente. Se n˜ao invocamos este m´etodo, o comportamento ficar´a em um
looping e usar´a muito a CPU.
3.1.4 Exemplo de Troca de Mensagens
Considere a situa¸ao representada na Figura 3.1. Nela, o agente Alarmado nota que est´a
acontecendo um incˆendio e avisa ao agente Bombeiro para que este tome as providˆencias
necess´arias.
Vamos desenvolver esta situa¸ao problema criando duas classes: a classe AgenteAlarmado
e a classe AgenteBombeiro. O agente Alarmado envia uma mensagem informando ao
agente Bombeiro que est´a acontecendo um inendio. Ao receber a mensagem, o agente
Bombeiro ativa os procedimentos para combate do incˆendio. Os c´odigos est˜ao nas Caixas
de C´odigo 3.3 e 3.4.
odigo 3.3: AgenteAlarmado.java
import ja de . c o re . Agent ;
import ja de . c o re . b eh av io ur s . OneShotBehaviour ;
3import ja de . la ng . a c l . ACLMessage ;
import ja de . c o re . AID ;
public c l a s s AgenteAlarmado extends Agent{
3.1. Envio e Recebimento de Mensagens 36
Figura 3.1: Situa¸ao Problema - Incˆendio.
6protected void s etu p ( ) {
addBehaviour (new OneShotBehaviour( this){
9public void a c t i o n ( ) {
ACLMessage msg = new ACLMessage(ACLMessage .INFORM) ;
msg . addR ec eiver (new AID( "Bombeiro" ,AID .ISLOCALNAME) ) ;
12 msg . setLanguage ( "Portugu^es" ) ;
msg . se tO nto lo gy ( "Emerg^encia") ;
msg . s etC on ten t ( "Fogo" ) ;
15 myAgent . send (msg) ;
}
18 }) ;
}
}
 
odigo 3.4: AgenteBombeiro.java
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . C y c li c B e h av i o u r ;
3import ja de . la ng . a c l . ACLMessage ;
public c l a s s AgenteBombeiro extends Agent{
6
protected void s etu p ( ) {
addBehaviour (new Cy cli cB eha vi our ( this){
9
public void a c t i o n ( ) {
ACLMessage msg = myAgent . r e c e i v e ( ) ;
12 i f ( msg != n u ll ){
3.1. Envio e Recebimento de Mensagens 37
S t r i n g c o nt en t = msg . ge tCon tent ( ) ;
//com e qu al sIg no re C as e fazemos uma compara¸c˜ao
15 // n˜ao cases e n s i t i v e .
i f ( c on te nt . e qu al sI g no re Ca se ( " Fogo" ) ) {
System . out . p r i n t l n ( "O agente " + msg . g et Sen der ( ) .
getName ( ) +
18 " avisou de um inc^endio " ) ;
System . out . p r i n t l n ( "Vou ativar os procedimentos de
combate ao inc^endio!" ) ;
}
21 }e l s e
b lo ck ( ) ;
}// fim do a c t i o n ( )
24 }) ; // f im do a dd Beha vi ou r ( )
}
}
 
Observe na classe AgenteAlarmado que escolhemos o receptor da mensagem com a li-
nha de comando: msg.addReceiver(new AID("Bombeiro",AID.ISLOCALNAME)). Quando
conhecemos o nome de um agente, no caso Bombeiro, adicionamos este nome em um ob-
jeto AID e informamos com o parˆametro AID.ISLOCALNAME que trata-se do nome local
do agente.
Execute no prompt a linha:
java jade.Boot Bombeiro:AgenteBombeiro A1:AgenteAlarmado
Obter´a o seguinte resultado:
O agente A1@lap:1099/JADE avisou de um inc^endio
Vou ativar os procedimentos de combate ao inc^endio!
Vamos agora incrementar nossos agentes. O agente Alarmado envia uma mensagem
para o agente Bombeiro. O agente Bombeiro recebe e processa esta mensagem. Agora, o
agente Bombeiro ir´a responder ao agente Alarmado.
Os c´odigos desta nova funcionalidade est˜ao nas Caixas de C´odigo 3.5 e 3.6, respecti-
vamente.
odigo 3.5: AgenteAlarmado2.java
import ja de . c o re . Agent ;
import ja de . c o re . b eh av io ur s . OneShotBehaviour ;
3import j a de . c o r e . b e h a vi o u r s . C y c li c B e h av i o u r ;
import ja de . la ng . a c l . ACLMessage ;
import ja de . c o re . AID ;
6public c l a s s AgenteAlarmado2 extends Agent{
3.1. Envio e Recebimento de Mensagens 38
protected void s etu p ( ) {
9
addBehaviour (new OneShotBehaviour( this){
12 public void a c t i o n ( ) {
ACLMessage msg = new ACLMessage(ACLMessage .INFORM) ;
msg . addR ec eiver (new AID( "Bombeiro" ,AID .ISLOCALNAME) ) ;
15 msg . setLanguage ( "Portugu^es" ) ;
msg . se tO nto lo gy ( "Emerg^encia") ;
msg . s etC on ten t ( "Fogo" ) ;
18 myAgent . send (msg) ;
}
21 }) ;
addBehaviour (new Cy cli cB eha vi our ( this){
24
public void a c t i o n ( ) {
ACLMessage msg = myAgent . r e c e i v e ( ) ;
27 i f ( msg != n u ll ){
S t r i n g c o nt en t = msg . ge tCon tent ( ) ;
System . out . p r i n t l n ( "--> " + msg . g et Se nde r ( ) . getName ( ) + ":
"+ c ont en t ) ;
30 }e l s e
//Com o b l o c k ( ) bloqueam os o comportamento a t´e que uma nova
//mensagem chegue ao a ge nt e e assim evi tam os consumir c i c l o s
33 // da CPU.
b lo ck ( ) ;
36 }
}) ;
39
42
}
}
 
odigo 3.6: AgenteBombeiro2.java
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . C y c li c B e h av i o u r ;
3import ja de . la ng . a c l . ACLMessage ;
public c l a s s AgenteBombeiro2 extends Agent{
6
3.1. Envio e Recebimento de Mensagens 39
protected void s etu p ( ) {
addBehaviour (new Cy cli cB eha vi our ( this){
9
public void a c t i o n ( ) {
ACLMessage msg = myAgent . r e c e i v e ( ) ;
12
i f ( msg != n u ll ){
ACLMessage r e p l y = msg . c r e at eR e pl y ( ) ;
15 S t r i n g c o nt en t = msg . ge tCon tent ( ) ;
i f ( c on te nt . e qu al sI g no re Ca se ( " Fogo" ) ) {
r e p l y . s e t P e r f o r m a t i v e ( ACLMessage .INFORM) ;
18 r e p l y . s et Co nt e nt ( " Recebi seu aviso ! Obrigado por
auxiliar meu servi¸co" ) ;
myAgent . send ( r e p l y ) ;
System . out . p r i n t l n ( "O agente "+ msg . g et Sen der ( ) .
getName ( ) +" avisou de um inc^endio " ) ;
21 System . out . p r i n t l n ( "Vou ativar os procedimentos de
combate ao inc^endio!" ) ;
}
}e l s e
24 b lo ck ( ) ;
}
}) ;
27 }
}
 
Observe o uso do m´etodo createReply() na classe AgenteBombeiro2. Este m´etodo
auxilia na resposta de mensagens recebidas, encapsulando automaticamente no objeto
reply o endere¸co do destinat´ario da resposta.
Vamos executar estes agentes de um modo diferente do que estamos fazendo at´e agora:
vamos executar os agentes a partir de prompts diferentes. Para que um agente JADE
possa ser criado este deve estar em um container. Este container deve ser criado no
mesmo instante em que o agente ´e criado. Quando execut´avamos a linha java jade.Boot
agente:ClassedoAgente agente2:ClassedoAgente est´avamos criando agentes em um
container nativo, o Main Container. Neste caso, vamos iniciar o agente Bombeiro no main
container e criar o agente Alarmado em outro container. Criamos o agente Bombeiro com
a seguinte linha:
java jade.Boot Bombeiro:AgenteBombeiro2
Ae agora nada mudou na nossa maneira de iniciar um agente. Como vamos iniciar
outro agente, poder´ıamos pensar em executar novamente a ´ultima linha de comando. No
entanto, agora precisamos passar o parˆametro -container para que o agente Alarmado
seja criado. Assim:
3.2. Envio de Objetos 40
java jade.Boot -container A1:AgenteAlarmado2
Executando esses agentes, obtemos os seguintes resultados:
No prompt do Agente Bombeiro:
O agente A1@lap:1099/JADE avisou de um inc^endio
Vou ativar os procedimentos de combate ao inc^endio!
No prompt do Agente Alarmado A1:
--> Bombeiro@lap:1099/JADE: Recebi seu aviso!
Obrigado por auxiliar meu servi¸co
Observe que durante o desenvolvimento de nosso agente utilizamos o m´etodo block()
para evitar o consumo da CPU. Existe uma peculiaridade da plataforma JADE que deve
ser observada durante o desenvolvimento de um agente. Quando uma mensagem chega
a um determinado agente, todos os seus comportamentos que est˜ao bloqueados s˜ao des-
bloqueados. Logo, se um agente possui um comportamento ou mais comportamentos
bloqueados, todos ser˜ao desbloqueados com a chegada de uma mensagem. Pode-se usar
como corre¸ao desta peculiaridade condi¸oes (if-elses) da linguagem JAVA para que um
comportamento n˜ao seja executado e volte a se bloquear novamente. ´
E importante lembrar
que os comportamentos CyclicBehaviour,TickerBehaviour eWakerBehaviour a foram
implementados com estas funcionalidades.
3.2 Envio de Objetos
Em muitas situa¸oes costuma-se transferir uma grande quantidade de informa¸oes. Passar
essas informa¸oes como strings requer um pouco mais de tempo de execu¸ao da aplica¸ao,
e a implementa¸ao pode perder eficiˆencia na transmiss˜ao das informa¸oes.
A linguagem JAVA possui um recurso que permite o envio de objetos pela stream de
dados. Este processo ´e denominado de serializa¸ao. Tecnicamente falando, serializar ´e
transformar um objeto em uma seq¨
uˆencia de bytes, que poder´a ser armazenado em algum
local (arquivo de dados, por exemplo) e futuramente ser deserializado para seu estado
original.
A plataforma JADE disponibiliza m´etodos que permitem a transmiss˜ao de objetos
como conte´udo de mensagens. Estes m´etodos s˜ao setContentObject(Serializable s)
egetContentObject(). Para exemplo de utiliza¸ao destas funcionalidades considere a
3.2. Envio de Objetos 41
seguinte situa¸ao problema. Em uma loja de m´usica temos dois funcion´arios: o agente
Estoque e o agente Contador. O agente Estoque deve informar ao agente Contador os
m´usicos contidos no estoque da loja. Para isto, devem ser informados o nome do m´usico,
sua idade e a banda que este comp˜oe, caso participe de uma. Este cen´ario est´a ilustrado
na Figura 3.2. Nela, o agente Estoque envia as informa¸oes para o agente Contador que
lista as informa¸oes recebidas.
Figura 3.2: Cen´ario - Loja de M´usica.
Vamos desenvolver este cen´ario aplicando as utilidades da serializa¸ao de objetos,
para que estes objetos possam ser o conte´udo das mensagens. Para informa¸oes sobre os
m´usicos temos a classe Musicos, cujo c´odigo est´a descrito na Caixa de C´odigo 3.7.
O agente Estoque criar´a cinco objetos da classe Musicos contendo as informa¸oes so-
bre os m´usicos, e esses objetos ser˜ao enviados para o agente Contador. As funcionalidades
do agente Estoque est˜ao na Caixa de C´odigo 3.8.
odigo 3.7: Musicos.java
import ja de . u t i l . l ea p . S e r i a l i z a b l e ;
/Uma c l a s s e que t e r´a se us o b j e t o s
3s e r i a l i z a d o s deve implementar a i n t e r f a c e S e r i a l i z a b l e /
public c l a s s Musicos implements Serializable {
6S t r i n g nome ;
int idade ;
S t r i n g banda ;
9
3.2. Envio de Objetos 42
public Mus icos ( S t r i n g nome , int id ade , S t r i n g banda ) {
this . nome = nome ;
12 this . idade = idade ;
this . banda = banda ;
}
15
public void Imprimir ( ) {
System . out . p r i n t l n ( "----------------------------") ;
18 System . out . p r i n t l n ( " Nome ...: " + nome ) ;
System . out . p r i n t l n ( " Idade ...: " + id ade ) ;
System . out . p r i n t l n ( " Banda ...: " + banda ) ;
21 System . out . p r i n t l n ( "----------------------------\n") ;
}
}
 
odigo 3.8: AgenteEstoque.java
import ja de . c o re . Agent ;
import ja de . c o re . b eh av io ur s . SimpleBehaviour ;
3import ja de . la ng . a c l . ACLMessage ;
import ja de . c o re . AID ;
import jav a . i o . IOException ;
6
public c l a s s AgenteEstoque extends Agent {
9Musicos [ ] mus = new Musicos [ 5 ] ;
protected void s etu p ( ) {
12
mus [ 0 ] = new Musicos ( "Cl´audia Leite" , 30 , "Babado Novo" ) ;
mus [ 1 ] = new Musicos ( "Paula Toller" , 4 5 , "Kid Abelha" ) ;
15 mus [ 2 ] = new Musicos ( "Rog´erio Flausino " , 37 , "Jota Quest " ) ;
mus [ 3 ] = new Musicos ( "Laura Pausini " , 33 , null ) ;
mus [ 4 ] = new Musicos ( "Bono Vox" , 47 , "U2" ) ;
18
addBehaviour (new SimpleBehaviour ( this ){// i n´ı c i o do comportamento
21 int cont = 0 ;
public void a c t i o n ( ) {
24 try {
ACLMessage msg = new ACLMessage(ACLMessage .INFORM) ;
msg . addR ec eiver (new AID( "Contador" , AID .ISLOCALNAME) ) ;
27 msg . s etC ont ent Obj ect (mus [ co nt ] ) ;
myAgent . send (msg) ; // en via a mensagem
cont = cont + 1 ;
30 // b l o c k ( 10 0) ;
}catch ( IOException ex ) {
3.2. Envio de Objetos 43
System . out . p r i n t l n ( "Erro no envio da mensagem" ) ;
33 }
}
36 public boolean done ( ) {
i f (cont >4) {
39 myAgent . d oD el ete ( ) ; // f i n a l i z a o ag en te
return true ;
}e l s e {
42 return f a l s e ;
}
}
45 }) ; // fim do comportamento
}// fim do m´etodo s e t u p ( ) do a g e nt e
48 //A i nv o ca ¸c ˜a o do m´etodo d oD e le t e ( ) a ci o na o m´etodo takeDown ( )
protected void takeDown () {
System . out . p r i n t l n ( "Todas as informa¸c~oes foram enviadas " ) ;
51 }
}
 
O agente Contador receber´a as mensagens enviadas pelo agente Estoque e os obje-
tos recebidos ter˜ao suas informa¸oes impressas na tela. As funcionalidades do agente
Contador est˜ao na Caixa de C´odigo 3.9.
odigo 3.9: AgenteContador.java
import ja de . c o re . Agent ;
3import j a de . c o r e . b e h a vi o u r s . C y c li c B e h av i o u r ;
import ja de . la ng . a c l . ACLMessage ;
6public c l a s s AgenteContador extends Agent {
protected void s etu p ( ) {
9System . out . p r i n t l n ( " Agente Contador inicializado .\ n " +
" Aguardando informa¸c~oes ... " ) ;
12 addBehaviour (new Cy cli cB eha vi our ( this){// i n´ı c i o do comportamento
Musicos [ ] musicos = new Musicos [ 5 ] ; // v e t o r da c l a s s e Musicos
15 int cont = 0 ;
public void a c t i o n ( ) {
18
ACLMessage msg = r e c e i v e ( ) ; // ca ptu ra nova mensagem
3.2. Envio de Objetos 44
21 i f ( msg != n u ll ){// se e x i s t e mensagem
try {// e x t r a i o o b j e t o
musicos [ co nt ] = ( Musicos ) msg . g etCont en tO bj ec t ( ) ;
24 // imprime as i nf or ma ¸c˜o es do o b j e t o
musicos [ c ont ] . Impri mir ( ) ;
cont = cont + 1 ;
27 }catch ( Exception e ) {
}
}e l s e
30 b lo ck ( ) ; // aguarda nova mensagem
}
}) ; // t´ermino do comportamento
33 }// fim do m´etodo s e t u p ( ) do a g e nt e
}
 
Executando o agente Contador com a seguinte linha:
java jade.Boot Contador:AgenteContador
Obtemos o seguinte resultado:
Agente Contador inicializado.
Aguardando informa¸c~oes...
Vamos executar agora o agente Estoque, com a seguinte linha:
java jade.Boot -container Estoque:AgenteEstoque
Quando o agente Estoque ´e iniciado, este envia as mensagens para o agente Contador
e ap´os o t´ermino do envio obtemos o seguinte resultado:
Todas as informa¸c~oes foram enviadas.
E no prompt do agente Contador obtemos o seguinte resultado:
----------------------------
Nome...: Cl´audia Leite
Idade...: 30
Banda...: Babado Novo
----------------------------
----------------------------
Nome...: Paula Toller
3.3. Sele¸ao de Mensagens 45
Idade...: 45
Banda...: Kid Abelha
----------------------------
----------------------------
Nome...: Rog´erio Flausino
Idade...: 37
Banda...: Jota Quest
----------------------------
----------------------------
Nome...: Laura Pausini
Idade...: 33
Banda...: null
----------------------------
----------------------------
Nome...: Bono Vox
Idade...: 47
Banda...: U2
----------------------------
3.3 Sele¸ao de Mensagens
Para selecionar as mensagens que um agente deseja receber podemos utilizar a classe
jade.lang.acl.MessageTemplate. Esta classe permite definir filtros para cada atributo
da mensagem ACLMessage e estes filtros podem ser utilizados como parˆametros do m´etodo
receive().
Nesta classe se define um conjunto de m´etodos est´aticos que retornam como resultado
um objeto do tipo MessageTemplate. As op¸oes para filtragem das mensagens s˜ao:
MatchPerformative(performative ): permite selecionar os tipos de atos comuni-
cativos das mensagens que ser˜ao aceitos;
MatchSender(AID): permite selecionar um ou um grupo de agentes cujas mensagens
enviadas por estes ser˜ao lidas;
MatchConversationID(String): permite que apenas mensagens de um determi-
nado t´opico sejam lidas. Um t´opico nada mais ´e do que uma String definido por um
3.3. Sele¸ao de Mensagens 46
agente. Todas as mensagens relacionadas a este t´opico contˆem essa string, e ser˜ao
lidas baseadas neste filtro;
and(MessageTemplate1, MessageTemplate2): realiza um “E” ogico entre dois fil-
tros;
or(MessageTemplate1, MessageTemplate2): realiza um “OU” ogico entre dois
filtros;
not(MessageTemplate): inverte o filtro;
MatchOntology(String): permite que mensagens com uma determinada ontologia
sejam lidas;
MatchProtocol(String): permite que mensagens envolvidas em um protocolo se-
jam lidas;
MatchLanguage(String): permite que mensagens em uma certa linguagem sejam
lidas;
MatchContent(String): permite que mensagens com um determinado conte´udo
sejam lidas;
MatchReplyWith(String): permite que um filtro seja realizado de acordo com o
campo replywith.
Existe tamb´em o m´etodo match(ACLMessage) que retorna um valor booleano verda-
deiro caso a mensagem que est´a em seu parˆametro respeite os filtros definidos pelo objeto
MessageTemplate.
O nosso agente Bombeiro, citado na Se¸ao 3.1.4 (p´agina 35), poderia estar interessado
em receber apenas mensagens do tipo inform e cuja linguagem seja o Portugu^es. Seu
odigo ficaria como mostrado na Caixa de C´odigo 3.10.
odigo 3.10: AgenteBombeiroFiltro.java
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . C y c li c B e h av i o u r ;
3import ja de . la ng . a c l . ACLMessage ;
import ja de . la ng . a c l . MessageTemplate ;
6public c l a s s Agen te Bo mb eiroFi lt ro extends Agent {
protected void s etu p ( ) {
9addBehaviour (new Cy cli cB eha vi our ( this){// I n´ı c i o do Comportamento
public void a c t i o n ( ) {
3.3. Sele¸ao de Mensagens 47
12
// de fi n im os o p rimei ro f i l t r o
MessageTemplate MT1 = MessageTemplate . MatchPerformative (
ACLMessage .INFORM) ;
15 // de fi n im os o segundo f i l t r o
MessageTemplate MT2 = MessageTemplate . MatchLanguage ( "
Portugu^es " ) ;
// Realizamos um E l ´o g i c o e nt r e os d o i s f i l t r o s
18 MessageTemplate MT3 = MessageTemplate . and (MT1, MT2) ;
// Recebe a mensagem de acordo com o f i l t r o
ACLMessage msg = myAgent . r e c e i v e (MT3) ;
21
i f ( msg != n u ll ){
S t r i n g c o nt en t = msg . ge tCon tent ( ) ;
24 i f ( c on te nt . e qu al sI g no re Ca se ( " Fogo" ) ) {
System . out . p r i n t l n ( "O agente " + msg . g et Se nd er ( ) .
getName ( ) + "avisou de um inc^endio" ) ;
}
27
}
}
30 }) ; //Fim do Comportamento
}
}
 
3.4. P´aginas Amarelas 48
3.4 aginas Amarelas
a vimos como ocorre a comunica¸ao entre agentes. Agora temos um
novo dilema: como um agente pode localizar outros agentes que oferecem
um determinado servi¸co, e obter seus identificadores para que possam se
comunicar?
Para que isto possa ser feito, a plataforma JADE implementa o servi¸co de p´aginas
amarelas em um agente: o agente Directory Facilitator (DF), seguindo as especifica¸oes
do padr˜ao FIPA. Agentes que desejam divulgar seus servi¸cos registram-se no DF, e os
demais podem ent˜ao buscar por agentes que proem algum servi¸co desejado.
O DF nada mais ´e do que um registro centralizado cuja entradas associam a ID do
agente aos seus servi¸cos. Para cria¸ao e manipula¸ao (busca) dessas entradas utilizamos
um objeto DFAgentDescription. Para registrar o servi¸co de um agente devemos fornecer
uma descri¸ao deste servi¸co e a AID do agente. Para uma busca, basta fornecer a descri¸ao
do servi¸co. Essa busca retornar´a um array com ID’s dos agentes que oferecem o servi¸co
buscado.
Figura 3.3: Estrutura de uma Entrada no DF.
Na Figura 3.3 tem-se a estrutura de uma entrada no registro do DF. Ela parece ser
complexa, mas seu uso se torna simples pois apenas alguns dos campos fornecidos s˜ao
3.4. P´aginas Amarelas 49
utilizados. Para cada servi¸co publicado devemos fornecer(obrigatoriamente) a AID do
agente, o tipo e o nome do servi¸co. Podemos tamem fornecer os protocolos, linguagens e
ontologias que um agente manipula para que os demais possam conhecer e interagir com
este agente.
Para manipula¸ao destes dados, os seguintes m´etodos est˜ao dispon´ıveis:
static DFAgentDescription register: registra os servi¸cos de um agente no DF;
static void deregister: elimina o registro do DF os servi¸cos fornecidos pelo
agente;
Os servi¸cos s˜ao definidos com os m´etodos da classe ServiceDescription:
void setName: definimos o nome do servi¸co;
void setOwnership: definimos o propriet´ario do servi¸co;
void setType: definimos o tipo do servi¸co. Este valor ´e definido pelo desen-
volvedor, n˜ao existem tipos pr´e-definidos;
void addLanguages: adicionamos linguagens ao servi¸co;
void addOntologies: adicionamos ontologias ao servi¸co;
void addProtocols: adicionamos protocolos ao servi¸co;
void addProperties: adicionamos propriedades ao servi¸co. Este valor ´e defi-
nido pelo desenvolvedor, n˜ao existem propriedades pr´e-definidas.
A descri¸ao do agente que oferece o servi¸co ´e realizada com o uso dos m´etodos da
classe DFAgentDescription:
void setName: definimos o AID do agente;
void addServices: adicionamos o servi¸co passado como parˆametro deste m´e-
todo `a descri¸ao do agente;
void removeServices: removemos um servi¸co oferecido da descri¸ao deste
agente;
void addLanguages: adicionamos linguagens que o agente entende;
void addOntologies: adicionamos ontologias que o agente manipula;
void addProtocols: adicionamos protocolos que o agente manipula.
3.4. P´aginas Amarelas 50
3.4.1 Registro
Para que um agente divulgue seus servi¸cos, este deve se registrar nas p´aginas amarelas
da plataforma, isto ´e, deve se registrar no DF. Costuma-se definir o registro no DF como
a primeira a¸ao do agente em seu m´etodo setup(). Para isto, utilizamos o m´etodo
register() fornecendo como parˆametro um objeto DFAgentDescription. Este m´etodo
deve ser envolvido por um bloco de exce¸ao.
Por exemplo, considere que um agente ofere¸ca um determinado servi¸co. Este agente
poderia se registrar no DF da maneira descrita na Caixa de C´odigo 3.11.
odigo 3.11: Registro.java
import ja de . c o re . Agent ;
import ja de . c o re . AID ;
3import ja de . domain . DFService ;
import ja de . domain . FIPAAgentManagement . ;
import ja de . domain . FIPAException ;
6
public c l a s s R e g i s t r o extends Agent {
protected void s etu p ( ) {
9// Criamos uma entra da no DF
DFAgentDescription dfd = new DFAgentDescription () ;
df d . setName ( getAID ( ) ) ; // Informamos a AID do a g en t e
12
//Vamos c r i a r um s e r v i ¸c o
ServiceDescription sd = new ServiceDescription () ;
15 sd . setType ( "Tipo" ) ; // Tipo do S e r v i ¸c o
sd . setName ( "Servi¸co1" ) ; //Nome do S e r v i ¸c o
// adicionamos o Se rvi ¸c o1
18 df d . a d d S e r v i c e s ( sd ) ;
//Vamos c r i a r ou tr o s e r v i ¸c o
21 sd = new ServiceDescription () ;
sd . setType ( "Tipo de Servi¸co" ) ;
sd . setName ( "Servi¸co2" ) ;
24 df d . a d d S e r v i c e s ( sd ) ;
//Vamos r e g i s t r a r o a ge nt e no DF
27 try {
// r e g i s t e r ( a ge nt e que o f e r ec e , d e s c r i ¸c ˜a o )
DFService . r e g i s t e r ( this , dfd ) ;
30
}catch ( FIPAException e ) {
e . p ri nt St ac kT ra ce ( ) ;
33 }
}
}
 
3.4. P´aginas Amarelas 51
Uma boa pr´atica ´e remover o registro do agente quando este termina sua execu¸ao.
Quando um agente ´e finalizado, automaticamente seu registro ´e removido das p´aginas
brancas, mas n˜ao ´e removido das p´aginas amarelas. Por isto, costuma-se remover o
registro do agente no m´etodo takeDown(). O m´etodo takeDown() fica implementado da
seguinte maneira:
protected void takeDown ()
{
3try{DFService . d e r e g i s t e r ( this ) ; }
catch ( FIPAException e ) {
e . p ri nt St ac kT ra ce ( ) ;
6}
}
 
3.4.2 Busca
Para buscar no DF devemos criar um objeto DFAgentDescription, agora sem a AID
do agente. O processo ´e muito semelhante ao de registro, pois criamos a descri¸ao do
servi¸co buscado da mesma maneira que criamos a descri¸ao de um servi¸co oferecido por
um agente. A implementao de um agente que realiza a busca no DF est´a contida na
Caixa de C´odigo 3.12.
odigo 3.12: Busca.java
import ja de . c o re . Agent ;
import ja de . c o re . AID ;
3import ja de . domain . DFService ;
import ja de . domain . FIPAAgentManagement . ;
import ja de . domain . FIPAException ;
6import jav a . u t i l . I t e r a t o r ;
public c l a s s Busca extends Agent {
9
protected void s etu p ( ) {
12 // c r i o uma en tr ad a no DF
DFAgentDescription template = new DFAgentDescription () ;
15 // c r i o um o b j e t o contendo a d e sc r i ¸c ˜a o do s e r v i ¸c o
ServiceDescription sd = new ServiceDescription () ;
sd . setType ( "Tipo" ) ; // d e f in o o t i p o de s e r v i ¸c o
18 /Neste momento p od er ia d e f i n i r o ut ra s c a r a c t e r´ı s t i c a s
do s e r v i ¸c o buscado para f i l t r a r melhor a bu sca .
No caso , vamos b us ca r por s e r v i ¸c o s do t i p o Tipo ” /
21
3.4. P´aginas Amarelas 52
// a d ic io no o s e r v i ¸c o na en tr ada
24 t em p la t e . a d d S e r v i c e s ( sd ) ;
try {
27 //Vou b u s c ar p e l o s a g e n t e s
//A busca r et o rn a um a rray DFAgentDescription
//O parˆametro t h i s i n d ic a o a g en te que e s t ´a r e a l i z a n d o a bus ca
30 DFAgentDescription [ ] r e s u l t = DFService . s ea rc h ( this , t em plat e ) ;
// Imprimo os r e s u l t a d o s
33 for (int i = 0 ; i <r e s u l t . l en gt h ; i ++) {
// r e s u l t [ i ] . getName ( ) f o r n e c e a AID do a g e n te
S t ri ng out = r e s u l t [ i ] . getName ( ) . getLocalName ( ) + " prov^e " ;
36
// Para o bt e r os s e r v i ¸c o s do a ge nte invocamos
// o m´etodo g e t A l l S e r v i c e s ( ) ;
39 I t e r a t o r i t e r = r e s u l t [ i ] . g e t A l l S e r v i c e s ( ) ;
while ( i t e r . hasNext ( ) ) {
42 // Extrı mos os s e r v i c o s para um o b j e t o S e r v i c e D e s c r i p t i o n
S e r v i c e D e s c r i p t i o n SD = ( S e r v i c e D e s c r i p t i o n ) i t e r . ne xt ( ) ;
// Capturamos o nome do s e r v i ¸c o
45 out += " " + SD . getName ( ) ;
}
//Os s e r v i ¸c o s de cada a ge nte s˜ao impr es sos na t e l a
48 System . out . p r i n t l n ( out ) ;
}// fim do l a ¸c o f o r
51
}catch ( FIPAException e ) {
e . p ri nt St ac kT ra ce ( ) ;
54 }
}
}
 
3.4.3 Solicitando Ajuda
Considere a seguinte situa¸ao: um agente solicitante observa uma situa¸ao problema
em seu ambiente, tal como um assalto, uma pessoa doente e um incˆendio. Este agente
enao busca por outros agentes que possam resolver estes problemas. No caso um agente
policial, um agente m´edico e um agente bombeiro. Ap´os encontrar estes agentes, o agente
solicitante comunica o que est´a acontecendo. Este cen´ario est´a ilustrado na Figura 3.4.
No contexto multiagentes, o agente solicitante busca nas p´aginas amarelas da plata-
forma por agentes que ofere¸cam determinado servi¸co. Estes agentes devem, ao iniciar,
cadastrar seus servi¸cos nas p´aginas amarelas. Para a implementa¸ao deste contexto te-
3.4. P´aginas Amarelas 53
Figura 3.4: Cen´ario - Solicitando Ajuda.
mos as classes Solicitante, Bombeiro, Medico ePolicial. A primeira refere-se ao
agente solicitante e as demais aos agentes prestadores de servi¸cos. Estas classes est˜ao nas
Caixas de C´odigo 3.13, 3.14, 3.15 e 3.16, respectivamente.
odigo 3.13: Solicitante.java
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . ;
3import ja de . c o re . AID ;
import ja de . domain . DFService ;
import ja de . domain . FIPAAgentManagement . ;
6import ja de . domain . FIPAException ;
import ja de . la ng . a c l . ACLMessage ;
9public c l a s s S o l i c i t a n t e extends Agent {
protected void s etu p ( ) {
12 // Captura argumentos
Ob ject [ ] a rg s = getArguments ( ) ;
i f ( a rg s != n u l l && a r g s . l e n g t h >0) {
15 S t r i n g argumento = ( S t r i n g ) a r gs [ 0 ] ;
3.4. P´aginas Amarelas 54
// Se o argumento ´e fo g o
i f ( argumento . e q ua l sI gn or eC a se ( "fogo" ) ) {
18 ServiceDescription servico = new ServiceDescription () ;
//O s e r v i ¸c o ´e apagar f og o
s e r v i c o . setType ( "apaga fogo" ) ;
21 // busca por quem f or n ec e o s e r v i ¸c o
bu sca ( s e r v i c o , "fogo" ) ;
}
24 // Se o argu mento ´e l a d r ˜a o
i f ( argumento . e q ua l sI gn or eC a se ( "ladr~ao" ) ) {
ServiceDescription servico = new ServiceDescription () ;
27 //O s e r v i ¸c o p re nde r o l a dr ˜a o
s e r v i c o . setType ( "prende ladr~ao") ;
bu sca ( s e r v i c o , "ladr~ao" ) ;
30 }
// Se o argumento ´e do ente
i f ( argumento . e q ua l sI gn or eC a se ( "doente" ) ) {
33 ServiceDescription servico = new ServiceDescription () ;
//O s e r v i ¸c o ´e s a l v a r v i d as
s e r v i c o . setType ( "salva vidas" ) ;
36 bu sca ( s e r v i c o , "doente" ) ;
}
// Comportamento pa ra r e c e b e r mensagens
39 addBehaviour (new CyclicBehaviour(this){
public void a c t i o n ( ) {
42 ACLMessage msg = r e c e i v e ( ) ;
i f ( msg != n u ll ){
System . out . p r i n t l n ( msg . ge tS en de r ( ) + ":"+ msg .
getConten t ( ) ) ;
45 }e l s e
b lo ck ( ) ;
}
48 }) ;
}
}
51 // M´etodo que r e a l i z a a busca nas p ´a gi na s amarelas da p la ta fo rm a
protected void busca ( f i n a l ServiceDescription sd , f i n a l S t r i n g Pedido )
{
54 //A cada minuto t e n t a b u sc a r po r a g e n t e s que forn ecem
// o s e r v i ¸c o
addBehaviour (new Tick erBe ha viou r ( this , 60000) {
57
protected void onTick ( ) {
DFAgentDescription dfd = new DFAgentDescription () ;
60 df d . a d d S e r v i c e s ( sd ) ;
3.4. P´aginas Amarelas 55
try {
DFAgentDe scription [ ] r e s u l t a d o = DFService . s e a rc h (
myAgent , dfd ) ;
63 i f ( r e s u l t a d o . l e n gt h != 0 ) {
ACLMessage msg = new ACLMessage(ACLMessage .INFORM) ;
msg . a dd Re ce iv er ( r e s u l t a d o [ 0 ] . getName ( ) ) ;
66 msg . se tCon ten t ( Pedido ) ;
myAgent . send (msg) ;
st op ( ) ; // f i n a l i z a comportamento
69 }
}catch ( FIPAException e ) {
e . p ri nt St ac kT ra ce ( ) ;
72 }
}
}) ;
75 }
}
 
odigo 3.14: Bombeiro.java
import ja de . c o re . Agent ;
3import j a de . c o r e . b e h a vi o u r s . ;
import ja de . c o re . AID ;
import ja de . domain . DFService ;
6import ja de . domain . FIPAAgentManagement . ;
import ja de . domain . FIPAException ;
import ja de . la ng . a c l . ACLMessage ;
9
public c l a s s Bombeiro extends Agent {
12 protected void s etu p ( ) {
// D es cr i ¸c ˜a o do S e r v i ¸c o
ServiceDescription servico = new ServiceDescription () ;
15 // Seu s e r v i ¸c o ´e s a l v a r v i d as
s e r v i c o . setType ( "apaga fogo" ) ;
s e r v i c o . setName ( this . getLocalName ( ) ) ;
18 r e g i s t r a S e r v i c o ( s e r v i c o ) ;
RecebeMensagens ( "fogo " ,"Vou apagar o inc^endio" ) ;
21 }
// m´etodo para r e g i s t r a r s er v i ¸c o
24 protected void r e g i s t r a S e r v i c o ( S e r v i c e D e s c r i p t i o n sd ) {
DFAgentDescription dfd = new DFAgentDescription () ;
df d . a d d S e r v i c e s ( sd ) ;
27 try {
DFService . r e g i s t e r ( this , dfd ) ;
3.4. P´aginas Amarelas 56
}catch ( FIPAException e ) {
30 e . p ri nt St ac kT ra ce ( ) ;
}
33 }
// M´etodo p ara a d i c i o n a r um comportamento par a r e c e b e r mensagens
protected void RecebeMensagens ( f i n a l S t r i n g mensagem , f i n a l S t r i n g r es p
){
36 addBehaviour (new Cy cli cB eha vi our ( this){
public void a c t i o n ( ) {
39 ACLMessage msg = r e c e i v e ( ) ;
i f ( msg != n u ll ){
i f ( msg . g etConte nt ( ) . e q ua ls I gn or e Ca se ( mensagem ) ) {
42 ACLMessage r e p l y = msg . c r e at eR e pl y ( ) ;
r e p l y . s et Co nt e nt ( r e sp ) ;
myAgent . send ( r e p l y ) ;
45 }
}e l s e
b lo ck ( ) ;
48 }
}) ;
}
51 }
 
odigo 3.15: Medico.java
import ja de . c o re . Agent ;
3import j a de . c o r e . b e h a vi o u r s . ;
import ja de . c o re . AID ;
import ja de . domain . DFService ;
6import ja de . domain . FIPAAgentManagement . ;
import ja de . domain . FIPAException ;
import ja de . la ng . a c l . ACLMessage ;
9
public c l a s s Medico extends Agent {
12 protected void s etu p ( ) {
// D es cr i ¸c ˜a o do S e r v i ¸c o
ServiceDescription servico = new ServiceDescription () ;
15 // Seu s e r v i ¸c o ´e s a l v a r v i d as
s e r v i c o . setType ( "salva vidas" ) ;
s e r v i c o . setName ( this . getLocalName ( ) ) ;
18 r e g i s t r a S e r v i c o ( s e r v i c o ) ;
RecebeMensagens ( "doente" ," Vou salvar o doente" ) ;
21 }
3.4. P´aginas Amarelas 57
// m´etodo para r e g i s t r a r s er v i ¸c o
24 protected void r e g i s t r a S e r v i c o ( S e r v i c e D e s c r i p t i o n sd ) {
DFAgentDescription dfd = new DFAgentDescription () ;
df d . a d d S e r v i c e s ( sd ) ;
27 try {
DFService . r e g i s t e r ( this , dfd ) ;
}catch ( FIPAException e ) {
30 e . p ri nt St ac kT ra ce ( ) ;
}
33 }
// M´etodo p ara a d i c i o n a r um comportamento par a r e c e b e r mensagens
protected void RecebeMensagens ( f i n a l S t r i n g mensagem , f i n a l S t r i n g r es p
){
36 addBehaviour (new Cy cli cB eha vi our ( this){
public void a c t i o n ( ) {
39 ACLMessage msg = r e c e i v e ( ) ;
i f ( msg != n u ll ){
i f ( msg . g etConte nt ( ) . e q ua ls I gn or e Ca se ( mensagem ) ) {
42 ACLMessage r e p l y = msg . c r e at eR e pl y ( ) ;
r e p l y . s et Co nt e nt ( r e sp ) ;
myAgent . send ( r e p l y ) ;
45 }
}e l s e
b lo ck ( ) ;
48 }
}) ;
}
51 }
 
odigo 3.16: Policial.java
import ja de . c o re . Agent ;
3import j a de . c o r e . b e h a vi o u r s . ;
import ja de . c o re . AID ;
import ja de . domain . DFService ;
6import ja de . domain . FIPAAgentManagement . ;
import ja de . domain . FIPAException ;
import ja de . la ng . a c l . ACLMessage ;
9
public c l a s s Policial extends Agent {
12 protected void s etu p ( ) {
// D es cr i ¸c ˜a o do S e r v i ¸c o
ServiceDescription servico = new ServiceDescription () ;
3.4. P´aginas Amarelas 58
15 // Seu s e r v i ¸c o ´e s a l v a r v i d as
s e r v i c o . setType ( "prende ladr~ao") ;
s e r v i c o . setName ( this . getLocalName ( ) ) ;
18 r e g i s t r a S e r v i c o ( s e r v i c o ) ;
RecebeMensagens ( "ladr~ao " ,"Vou prender o ladr~ao" ) ;
21 }
// m´etodo para r e g i s t r a r s er v i ¸c o
24 protected void r e g i s t r a S e r v i c o ( S e r v i c e D e s c r i p t i o n sd ) {
DFAgentDescription dfd = new DFAgentDescription () ;
df d . a d d S e r v i c e s ( sd ) ;
27 try {
DFService . r e g i s t e r ( this , dfd ) ;
}catch ( FIPAException e ) {
30 e . p ri nt St ac kT ra ce ( ) ;
}
33 }
// M´etodo p ara a d i c i o n a r um comportamento par a r e c e b e r mensagens
protected void RecebeMensagens ( f i n a l S t r i n g mensagem , f i n a l S t r i n g r es p
){
36 addBehaviour (new Cy cli cB eha vi our ( this){
public void a c t i o n ( ) {
39 ACLMessage msg = r e c e i v e ( ) ;
i f ( msg != n u ll ){
i f ( msg . g etConte nt ( ) . e q ua ls I gn or e Ca se ( mensagem ) ) {
42 ACLMessage r e p l y = msg . c r e at eR e pl y ( ) ;
r e p l y . s et Co nt e nt ( r e sp ) ;
myAgent . send ( r e p l y ) ;
45 }
}e l s e
b lo ck ( ) ;
48 }
}) ;
}
51 }
 
Vamos rodar este cen´ario de uma nova maneira: utilizando ferramentas gr´aficas da
plataforma JADE. A plataforma JADE possui um agente que fornece uma interface gr´afica
de administra¸ao da plataforma. Trata-se do agente RMA (Remote Management Agent).
Existe um atalho para execu¸ao deste agente: basta incluir o parˆametro -gui na linha de
execu¸ao da plataforma (e.g, java jade.Boot -gui ...).
Com a invoca¸ao deste agente ´e exibida a interface gr´afica ilustrada na Figura 3.5.
Automaticamente com o comando -gui, os agentes AMS e DF tamb´em s˜ao carregados.
3.4. P´aginas Amarelas 59
Figura 3.5: Interface Gr´afica da Plataforma JADE.
Ao longo deste manual as funcionalidades desta interface ser˜ao abordadas. Mas no
momento estamos interessados em estudar apenas uma destas funcionalidades: o Agente
Sniffer. Este agente intercepta mensagens ACL e as mostra graficamente usando uma
nota¸ao semelhante aos diagramas de seq¨
uˆencia UML. A Figura 3.6 ilustra a atividade
deste agente.
3.4. P´aginas Amarelas 60
Figura 3.6: Agente Sniffer.
Vamos iniciar nosso agente Solicitante com a seguinte linha de comando:
java jade.Boot -gui Pedinte:Solicitante(fogo)
Com esta execu¸ao criamos um agente Pedinte que solicita `as p´aginas amarelas um
agente que combate o fogo, no caso o Bombeiro. A tela gr´afica desta execu¸ao est´a
ilustrada na Figura 3.7.
3.4. P´aginas Amarelas 61
Figura 3.7: Agente Pedinte na Plataforma.
Vamos iniciar o agente Sniffer. Clique sobre algum container ou sobre alguma plata-
forma. Agora vamos no menu Tools -> Start Sniffer. A tela do Sniffer ser´a aberta,
onde teremos a lista de agentes na plataforma. Para verificar o fluxo de mensagens entre
agentes temos que selecion´a-los, e para tanto basta clicar com o bot˜ao direito do mouse e
escolher a op¸ao Do sniff this agent(s). Estes passos est˜ao ilustrados na Figura 3.8.
Figura 3.8: Execu¸ao do Agente Sniffer.
Vamos adicionar os agentes Pedinte e DF. Observe que a cada minuto o Pedinte envia
uma mensagem para o DF buscando por agentes Bombeiros, e recebe uma mensagem de
resposta que no caso est´a vazia, pois n˜ao temos agente Bombeiro na plataforma.
Vamos adicionar o agente Bombeiro `a plataforma, com a seguinte linha:
3.4. P´aginas Amarelas 62
java jade.Boot -container Bombeiro:Bombeiro
Adicionalmente, vamos adicionar este agente ao Sniffer. Agora, quando o agente
Pedinte enviar uma mensagem para o DF, este responder´a com uma mensagem contendo
a AID do agente Bombeiro e enao, o agente Pedinte envia uma mensagem diretamente
para o agente Bombeiro. O resultado do contexto apresentado est´a ilustrado na Figura
3.9.
Figura 3.9: Troca de Mensagens entre os Agentes.
3.4.4 Notifica¸ao
Podemos tamem utilizar o servi¸co de notifica¸ao do DF para resolver este problema.
Ao ines do agente Pedinte ficar realizando uma busca de novos agentes que oferecem
determinado servi¸co a cada minuto, este pode pedir para que o DF notifique-o sempre
quando um novo agente que oferece o servco desejado se registrar nas p´aginas amarelas.
Para que isto seja poss´ıvel, a plataforma JADE disponibiliza um servi¸co denominado
DF Subscription Service que implementa um protocolo subscribe entre os agentes en-
volvidos. O c´odigo desta funcionalidade est´a descrito na Caixa de C´odigo 3.17. Todo o
odigo fonte est´a comentado para que seja plaus´ıvel o entendimento da implementa¸ao.
3.4. P´aginas Amarelas 63
odigo 3.17: Solicitante2.java
import ja de . c o re . Agent ;
import j a de . c o r e . b e h a vi o u r s . ;
3import ja de . c o re . AID ;
import ja de . domain . DFService ;
import ja de . domain . FIPAAgentManagement . ;
6import ja de . domain . FIPAException ;
import ja de . domain . FIPANames ;
import ja de . la ng . a c l . ACLMessage ;
9import ja de . la ng . a c l . MessageTemplate ;
import ja de . pr oto . S u b s c r i p t i o n I n i t i a t o r ;
12 public c l a s s Solicitante2 extends Agent {
protected void s etu p ( ) {
15 // Nada mudou n e s t e etodo , a pen as o m´etodo Busca ( )
// passou a se chamado de P ed eN ot if i ca ¸c ˜a o ( )
18 Ob ject [ ] a rg s = getArguments ( ) ;
i f ( a rg s != n u l l && a r g s . l e n g t h >0) {
S t r i n g argumento = ( S t r i n g ) a r gs [ 0 ] ;
21 i f ( argumento . e q ua l sI gn or eC a se ( "fogo" ) ) {
ServiceDescription servico = new ServiceDescription () ;
s e r v i c o . setType ( "apaga fogo" ) ;
24 P e de N ot i fi c a ca o ( s e r v i c o , "fogo" ) ;
}
i f ( argumento . e q ua l sI gn or eC a se ( "ladr~ao" ) ) {
27 ServiceDescription servico = new ServiceDescription () ;
s e r v i c o . setType ( "prende ladr~ao") ;
P e de N ot i fi c a ca o ( s e r v i c o , "ladr~ao" ) ;
30 }
i f ( argumento . e q ua l sI gn or eC a se ( "doente" ) ) {
ServiceDescription servico = new ServiceDescription () ;
33 s e r v i c o . setType ( "salva vidas" ) ;
P e de N ot i fi c a ca o ( s e r v i c o , "doente" ) ;
}
36
// Comportamento pa ra r e c e b e r mensagens
addBehaviour (new CyclicBehaviour(this){
39 /As mensagens de n o t i f i c a ¸c ˜a o do DF atendem ao p ro t oc o l o
FIPA Sub sc ri be , e e l a s possuem um m´etodo e x c l u s i v o para
sua rec ep¸c˜ao . ( S u b s c r i p t i o n I n i t i a t o r )
Ent˜ao , devemos l e r t o da s as mensagens , e x c e t o a s q ue
obdecem o p r o t o c o l o
42 FIPA S u b c r i b e . /
// Fa¸co um f i l t r o par a r e c e b e r mensagens do p r o t o c o l o
Subscribe
3.4. P´aginas Amarelas 64
MessageTemplate f i l t r o = MessageTemplate . MatchProtocol (
FIPANames . I n t e r a c t i o n P r o t o c o l . FIPA SUBSCRIBE) ;
45 // Cri o um novo f i l t r o que r e a l i z a uma i n v e r s ˜a o l ´o g i c a no
f i l t r o a n t e r i o r .
// ou se j a , n˜ao a c e i t a mensagens do p r o t o c o l o S u b s c r i b e
MessageTemplate f i l t r o 2 = MessageTemplate . not ( f i l t r o ) ;
48
public void a c t i o n ( ) {
// S´o r e c e b e mensagens do f i l t r o 2
51 ACLMessage msg = r e c e i v e ( f i l t r o 2 ) ;
i f ( msg != n u ll ){
System . out . p r i n t l n ( msg . ge tS en de r ( ) + ":"+ msg .
getConten t ( ) ) ;
54 }e l s e
b lo ck ( ) ;
}
57 }) ;
}
}
60 protected void PedeNotificacao( final ServiceDescription sd , f i n a l
S t r i n g Pe dido ) {
// Crio d e s c r i ¸c ˜a o da e nt r ad a no r e g i s t r o
63 DFAgentDescription dfd = new DFAgentDescription () ;
df d . a d d S e r v i c e s ( sd ) ;
66 // Crio mensagem de n o t i f i c a ¸c ˜a o
ACLMessage mgs = DF Ser vice . c r e a t e S u b s c r i p t i o n M e s s a g e ( this ,
getDef aultDF ( ) , dfd , null ) ;
69
// Agora in ic ia mo s o comportamento que f i c a r ´a espera ndo p e la
n o t i f i c a ¸c ˜a o do DF
72 addBehaviour (new SubscriptionInitiator(this , mgs ) {
//A mensagem de n o t i f i c a ¸c ˜a o ´e uma mensagem INFORM, en t˜ao
// u t i l i z o o m´etodo padr˜ao ha nd leInf or m ( ) . Est e ´e um m´etodo pr´e
definido para
75 // manipular mensagens do t i p o INFORM.
protected void ha nd le In fo rm ( ACLMessage in fo rm ) {
try {
78 // Retorna ar ra y de AIDs dos Agente s
DFAgentDescription [ ] d fd s = DFService .
d e c o d e N o t i f i c a t i o n ( i nf orm . getCo ntent ( ) ) ;
// Crio mensagem
81 ACLMessage mensagem =new ACLMessage(ACLMessage .INFORM) ;
// Capturo AID do a ge nt e
3.4. P´aginas Amarelas 65
mensagem . addR eceiv er ( df ds [ 0 ] . getName () ) ;
84 // Defino conte ´ud o da mensagem
mensagem . set Con ten t ( Pedido ) ;
// Envio a mensagem
87 myAgent . send ( mensagem ) ;
}catch ( FIPAException e ) {
90 e . p ri nt St ac kT ra ce ( ) ;
}
}
93 }) ;
}
}
 
Vamos executar o agente Pedinte, solicitando ajuda para um doente, e posteriormente
um agente edico. A troca de mensagens entre esses agentes e o DF est´a ilustrada na
Figura 3.10.
java jade.Boot Pedinte:Solicitante2(doente)
java jade.Boot Medico:Medico
3.4. P´aginas Amarelas 66
Figura 3.10: aginas Amarelas - Notifica¸ao.
Observe que o pedido de notifica¸ao ao DF ocorre com a seguinte linha de c´odigo:
ACLMessage mgs = DFService.createSubscriptionMessage(this, getDefaultDF(),
dfd, null);
Da mesma maneira que pedimos a notifica¸ao, podemos pedir para que n˜ao sejamos
mais notificados quando um determinado agente se registrar. Neste caso basta executar o
m´etodo createCancelMessage(Agent a, AID dfName, ACLMessage subscribe), onde
os parˆametros s˜ao respectivamente o agente notificado, a AID do DF, e a mensagem de
notifica¸ao inicial. No nosso exemplo, o objeto msg da classe ACLMessage ser´a a men-
sagem de notifica¸ao e podemos pedir que n˜ao sejamos notificados com a seguinte linha
(considerando que estamos dentro de um comportamento):
DFService.createCancelMessage(myAgent, getDefaultDF(), msg);
3.5. P´aginas Brancas 67
3.5 aginas Brancas
Podemos consultar os agentes existentes na plataforma com uma busca nas p´aginas bran-
cas da plataforma. De acordo com o padr˜ao FIPA, quem realiza este servi¸co ´e o AMS
(Agent Management Service). Para realizarmos a busca temos que importar as bibliotecas
jade.domain.AMSService,jade.domain.FIPAAgentManagement ejade.domain.AMSService,
para que os m´etodos de intera¸ao com o AMS estejam dispon´ıveis. Uma busca nas p´agi-
nas brancas d´a-se pelo m´etodo search() da classe AMSService. Este m´etodo retorna um
vetor de objetos AMSAgentDescription.
Por padr˜ao o resultado desta busca retorna apenas um agente na plataforma. Para
que possamos informar que desejamos obter todos os agentes da plataforma, devemos
passar como parˆametro do m´etodo search() um objeto da classe SearchConstraints.
Na Caixa de C´odigo 3.18 temos um agente que busca por todos os agentes contidos na
plataforma. A explica¸ao da implementa¸ao est´a contida nos comenarios do c´odigo.
odigo 3.18: AgenteBuscaAMS.java
import ja de . c o re . Agent ;
import ja de . c o re . AID ;
3import ja de . domain . AMSService ;
import ja de . domain . FIPAAgentManagement . ;
import ja de . domain . FIPAException ;
6
public c l a s s AgenteBuscaAMS extends Agent{
9
protected void s etu p ( ) {
try {
12 // Quero b u s c ar q u a i s a g e n t e s e s t ˜a o na p l a t a f or m a
AMSAgentDescription [ ] a ge nt es = nu l l ;
// Crio o b j e t o S ea rc hC on st ra in ts para d e f i n i r
15 // que d e se j o t od os os r e s u l t a d o s
SearchConstraints c = new S e a r c h C o n s t r a i n t s ( ) ;
//O m´etodo s et Max Res ul ts i n d ic a o n´umero de r e s u l t a d o s
18 // que d e s e j o o b t e r . Por d e f i n i ¸c ˜a o , 1 s i g n i f i c a to do s .
c . s etM axRe sult s (new Long( 1) ) ;
// busco p e l o s a ge nt e s
21 // AMSService . s ea rc h ( a ge nt e que b usca , v e t o r de re to rn o ,
caracter´ısticas)
a g e n t e s= AMSService . s e a r c h ( this ,new AMSAgentDescription ( ) , c ) ;
// Capturo minha AID
24 AID myAID = getAID ( ) ;
for(int i =0; i <a g e n t e s . l e n g t h ; i ++) {
AID agenteID = a g en te s [ i ] . getName ( ) ;
27 // Imprimo t o d o s o s a g e n t e s
// Este ag en te s er´a i d e n t i f i c a d o com ∗∗∗∗ para diferenciar
3.6. Protocolos de Intera¸ao 68
// dos demais
30 System . o ut . p r i n t l n ( ( a gen teI D . e q u a l s (myAID) ? "***" :" " )
+i+": " + agenteID . getName ( ) ) ;
}
33 }catch ( FIPAException ex ) {
ex . p ri nt St ac kT ra ce ( ) ;
}
36 // F i n a l i z o ag en te
doDelete () ;
// F i n a l i z o a p l i c a ¸c ˜a o
39 System . e x i t ( 0 ) ;
}
42
}
 
Vamos executar a seguinte linha de comando:
java jade.Boot -gui
Com esta linha, conforme j´a vimos, executamos as ferramentas gr´aficas da plataforma.
Mas tamb´em temos trˆes agentes que s˜ao criados com o parˆametro -gui: o AMS, o DF e o
RMA. Vamos agora executar o agente Buscador, que ir´a buscar nas p´aginas brancas quais
agentes que est˜ao na plataforma e imprimir a lista de agentes encontrados. Executamos
o agente Buscador com a seguinte linha de comando:
java jade.Boot -container Buscador:AgenteBuscaAMS
E obtemos o seguinte resultado:
***0: Buscador@lap:1099/JADE
1: RMA@lap:1099/JADE
2: df@lap:1099/JADE
3: ams@lap:1099/JADE
3.6 Protocolos de Intera¸ao
O padr˜ao FIPA especifica um conjunto de protocolos que podem ser empregados na padro-
niza¸ao das conversas entre os agentes. Para cada conversa, a plataforma JADE distingue
entre dois pap´eis: o papel do iniciador, atribu´ıdo ao agente que inicia a conversa, e o papel
do participante, representando o agente que responde ao ato comunicativo executado pelo
iniciador.
JADE proporciona as classes AchieveREIniciator eAchieveREResponder para a
implementa¸ao dos protocolos no estilo do fipa-request, tais como:
3.6. Protocolos de Intera¸ao 69
fipa query;
fipa request-when;
fipa subscribe.
Figura 3.11: Estrutura dos Protocolos Baseados no fipa-request.
O comportamento dessas classes ´e baseado em uma m´aquina de estados finito, seme-
lhante ao FSMBehaviour. A Figura 3.11 ilustra a estrutura dos protocolos de intera¸ao
do tipo fipa-request. O iniciador envia uma mensagem com um determinado ato co-
municativo. O participante pode responder um not-understood ou um refuse, assim
como pode enviar uma mensagem agree indicando que est´a disposto a realizar a a¸ao
do ato comunicativo.
3.6. Protocolos de Intera¸ao 70
O participante executa a a¸ao e, finalmente, deve responder com uma mensagem in-
form indicando o resultado da a¸ao, ou com uma mensagem failure caso algo de errado
ocorra.
3.6.1 Classe AchieveREInitiator
O iniciador envia uma mensagem aos agentes participantes e espera por suas respostas.
Ainda que esteja esperando uma mensagem inform como resposta, deve estar tamb´em
preparado para um refuse, not understood ou failure.
Por exemplo, considere um agente que inicia um protocolo fipa-request. Este deve
construir uma mensagem ACL indicando a performativa (request) e o protocolo empre-
gado. Com isto, basta informar o receptor o conte´udo da mensagem. Finalmente, o
agente adiciona um comportamento do tipo AchieveREInitiator passando como refe-
rˆencia o agente iniciador (ele, no caso) e a mensagem a ser enviada. Neste caso, nosso
agente est´a preparado para receber mensagens inform deste protocolo, por isto o mesmo
possui implementado o m´etodo handleInform(). Esta implementa¸ao est´a na Caixa de
odigo 3.19.
odigo 3.19: AchieveREInitiator
ACLMessage r e q u e s t = new ACLMessage(ACLMessage .REQUEST) ;
r e qu e s t . s e t P r o t o c o l ( FIPAProtocolNames . FIPA REQUEST) ;
3r e q u e s t . a dd Re ce iv er (new AID( " receptor " , AID .ISLOCALNAME) ;
myAgent . addBehaviour ( new A c h ie v eR E In i ti a to r ( myAgent , r e q u e s t ) {
protected void ha nd le In fo rm ( ACLMessage in fo rm ) {
6System . out . p r i n t l n ( "Protocolo Finalizado.") ;
}
}) ;
 
3.6.2 Classe AchieveREResponder
Esta classe proporciona a implementa¸ao do papel do participante. ´
E muito importante
passar as configura¸oes da mensagem como argumento no construtor desta classe, pois
assim ser´a poss´ıvel saber quais tipos de mensagens ACL ser˜ao recebidas. Utiliza-se um
MessageTemplate para criar o padao de mensagens a ser recebida, informando o protocolo
em que esta mensagem deve estar envolvida para poder ser lida.
A utiliza¸ao da classe AchieveREResponder ser´a implementada a seguir com a utili-
za¸ao de um exemplo.
3.6.3 Exemplo de Implementa¸ao do Protocolo FIPA-Request
O protocolo request ´e utilizado quando um agente solicita a outro que execute alguma
ao. O participante pode aceitar ou recusar o pedido, e em caso de aceit´a-lo, dever´a
3.6. Protocolos de Intera¸ao 71
Figura 3.12: Protocolo fipa-request.
realizar o que lhe foi pedido e indicar ao iniciador quando a execu¸ao do pedido estiver
conclu´ıda.
A Figura 3.12 ilustra a troca de mensagens entre os agentes iniciador e participante no
protocolo request. Observe que existe um m´etodo que representa uma ou mais respostas
neste protocolo.
Vamos desenvolver uma aplica¸ao mais robusta do nosso exemplo do agente Alarmado
e do agente Bombeiro. Nesta aplica¸ao n˜ao existe mais um agente Bombeiro e sim um
agente Central de Bombeiros. A comunica¸ao entre estes agentes ser´a regida pelo pro-
tocolo request. O agente Alarmado (instˆancia da classe FIPARequestAlarmado) avisa da
existˆencia de um incˆendio a uma determinada distˆancia aos agentes Bombeiro, que agora
est˜ao na Central de Bombeiros instˆancia da classe FIPARequestCentraldeBombeiros.
As centrais est˜ao sempre alertas sobre chamadas informando sobre incˆendios. Recebido
3.6. Protocolos de Intera¸ao 72
o aviso, cada central possui uma certa distˆancia m´axima que pode atuar e se a distˆan-
cia estiver dentro do limite permitido, a central ir´a apagar o fogo. Existe tamem uma
probabilidade de 20% de faltar ´agua para o combate ao incˆendio.
O c´odigo das classes FIPARequestAlarmado eFIPARequestCentraldeBombeiros es-
ao nas Caixas de C´odigo 3.20 e 3.21, respectivamente. Para auxiliar o entendimento dos
m´etodos, consulte a Figura 3.12 para entender o que cada m´etodo representa dentro do
protocolo e seu momento de execu¸ao.
odigo 3.20: FIPARequestAlarmado.java
import ja de . c o re . Agent ;
import ja de . c o re . AID ;
3import ja de . la ng . a c l . ACLMessage ;
import ja de . pro to . Ac hi e ve RE In it i at or ;
// para implem ent ar o p r o t o c o l o r e q u e s t importamos a s e g u i n t e c l a s s e :
6import ja de . domain . FIPANames ;
public c l a s s FIPARequestAlarmado extends Agent {
9
protected void s etu p ( ) {
12 Ob ject [ ] a rg s = getArguments ( ) ;
i f ( a rg s != n u l l && a r g s . l e n g t h >0) {
System . out . p r i n t l n ( " Solicitando ajuda a v´arias centrais de
bombeiros ..." ) ;
15 \\montando a mensagem a s e r e nv ia d a p o s t e r i o r m e n t e
ACLMessage msg = new ACLMessage(ACLMessage .REQUEST) ;
for (int i = 0 ; i <a r g s . l e n g t h ; i ++) {
18 msg . addR ec eiver (new AID ( ( S t r i n g ) a r g s [ i ] , AID . ISLOCALNAME) ) ;
}
msg . s e t P r ot o c o l (FIPANames . I n t e r a c t i o n P r o t o c o l . FIPA REQUEST) ;
21 msg . s etC on ten t ( "Fogo a 5 kms" ) ;
/A c l a s s e I n i c i a d o r ( a ba ix o ) e x te n de a c l a s s e
AchieveREInitiator , ela
atua como o i n i c i a d o r do p r o t o l o c o . Seu m´etodo c o n s t r u t o r en vi a
24 automaticamente a mensagem que e s t ´a no o b j e t o msg /
addBehaviour (new I n i c i a d o r ( this , msg) ) ;
}e l s e {
27 System . out . p r i n t l n ( " Especifique o nome de pelo menos uma
central de bombeiros " ) ;
}
30 }
class Iniciador extends AchieveREInitiator {
33
3.6. Protocolos de Intera¸ao 73
// e nv ia a mensagem r e q u e s t para os r e c e p t o r e s que foram e s p e c i f i c a d o s no
o b j e t o msg
public I n i c i a d o r ( Agent a , ACLMessage msg) {
36 super ( a , msg ) ; // p arˆa metros = ag en te que e s t ´a env iando ,
mensagem a s e r e n vi a da
}
//Os m´etodos a s e g u ir tratam a r esp o s ta do p a r t i c i p a n t e
39 // Se o p a r t i c i p a n t e concordar , i s t o ´e , e nv ia r uma mensagem AGREE
protected void h andleAg re e ( ACLMessage a g r ee ) {
System . out . p r i n t l n ( "Central de bombeiros " + a gr ee . g etS en de r ( ) .
getName ( ) + " informa que saiu para apagar o fogo" ) ;
42 }
// Se o p a r t i c i p a n t e se negar , enviand o uma mensagem REFUSE
45 protected void h an dleR ef use ( ACLMessage r e f u s e ) {
System . out . p r i n t l n ( "Central de bombeiros " + r e f u s e . g et Se nd er ( )
. getName ( ) + " responde que o fogo est´a muito longe " +
"e n~ao pode apag´a -lo" ) ;
48 }
// Se o p a r t i c i p a n t e n˜ao entendeu , enviando uma mensagem NOT
UNDERSTOOD
51 protected void ha ndl eNo tUn derst ood ( ACLMessage n otUn ders tood ) {
System . out . p r i n t l n ( "Central de bombeiros " + notUnderstood .
ge tS en de r ( ) . getName ( ) + "por algum motivo n~ao entendeu a
solicita¸c~ao" ) ;
54 }
// Se houve uma f a l h a na e xecu¸c˜ao do p ed id o
57 protected void h a n d l e F a i l u r e ( ACLMessage f a i l u r e ) {
// V e r i f i c a i n i c i a l m e n t e s e f o i um e rro nas p´a gi na s b ra nc as
i f ( f a i l u r e . g e tS en d er ( ) . e q u a l s ( getAMS ( ) ) ) {
60 System . out . p r i n t l n ( "Alguma das centrais de bombeiro n~ao
existe") ;
}
/O cont e´u do de uma mensagem e n v o l v i d a n e s t e p r o t o c o l o ´e a utoma ticam ente
co lo ca do en tr e par ˆe nte s es . Com o m´etodo s u b s t r i n g ( ) podemos l e r apenas
o que e s t ´a d en t ro d e l e s . /
63
e l s e {
System . out . p r i n t l n ( "Falha na central de bombeiros " +
f a i l u r e . ge tSen der ( ) . getName ( ) +
66 ": " + f a i l u r e . getContent ( ) . s ub st r i n g ( 1 , f a i l u r e . getConte nt
( ) . l e n g t h ( ) 1) ) ;
}
}
3.6. Protocolos de Intera¸ao 74
69
//Ao f i n a l i z a r o pr ot oc ol o , o p a r t i c i p a n t e en vi a uma mensagem
inform
protected void h an dle In fo rm ( ACLMessage i nf orm ) {
72 System . out . p r i n t l n ( "Central de bombeiros" + inf or m . g et Sen der ( ) .
getName ( ) + " informa que apagou o fogo" ) ;
}
}
75 }
 
odigo 3.21: FIPARequestCentraldeBombeiros.java
import ja de . c o re . Agent ;
import ja de . c o re . AID ;
3import ja de . la ng . a c l . ACLMessage ;
import ja de . pro to . Ac hi e ve RE In it i at or ;
import ja de . domain . FIPANames ;
6import ja de . domain . FIPAAgentManagement . NotUnderstoodException ;
import ja de . domain . FIPAAgentManagement . Re fuse Exce ptio n ;
import j a de . domain . FIPAAgentManagement . F a i l u r e E x c e p t i o n ;
9import ja de . la ng . a c l . MessageTemplate ;
import ja de . pr oto . AchieveREResponder ;
import j av a . u t i l . S t r i n g T o k e n i z e r ;
12
public c l a s s FIPARequestCentraldeBombeiros extends Agent {
15 public double DISTANCIA MAX;
protected void s etu p ( ) {
18
DISTANCIA MAX = ( Math . random ( ) 10 ) ;
System . out . p r i n t l n ( "Central " + getLocalName ( ) + ": Aguardando
alarmes ..." ) ;
21 //Meu a ge n te c on ve rs a sob o p r o t o c o l o FIPA REQUEST
MessageTemplate p r o t o c o l o = MessageTemplate . M atc hPro toc ol ( FIPANames
. I n t e r a c t i o n P r o t o c o l . FIPA REQUEST) ;
MessageTemplate p er fo r ma ti va = MessageTemplate . MatchPerformative (
ACLMessage .REQUEST) ;
24 MessageTemplate padrao = MessageTemplate . and ( p ro to co lo ,
pe r fo rm ati va ) ;
addBehaviour (new Participante(this , padrao ) ) ;
27 }
class Participante extends AchieveREResponder {
30
public P a r t i c i p a n t e ( Agent a , MessageTemplate mt) {
// De fi ne a ge nt e e p r o t o c o l o de comunica¸c˜ao
3.6. Protocolos de Intera¸ao 75
33 super ( a , mt) ;
}
36 /M´etodo que aguarda uma mensagem REQUEST, d e f i n i d a com o uso do
o b j et o mt , u t i l i z a n d o no c o n s t r ut o r d es ta c l a s s e .
O re t or no d e s t e m´etodo ´e uma mensagem que ´e e nv iad a automati came nte
para o i n i c i a d o r . /
protected ACLMessage p re pa re Re sp on se ( ACLMessage r e q u e s t ) throws
NotUnderstoodException , Re fuse Exce ptio n {
39
System . out . p r i n t l n ( "Central " + getLocalName ( ) + ": Recebemos
uma chamada de " + r e q u e s t . g e tS e nd er ( ) . getName ( ) +
" dizendo que observou um inc^endio " ) ;
42
/A c l a s s e S t r i n g T o k e n i z e r p er mi t e q ue v ocˆe s e p ar e
45 ou e n co n tr e p a l a v r a s ( t o ke n s ) em q u a l qu e r f or mato . /
S t r i n g T o k e n i z e r s t = new S t r i n g T o k e n i z e r ( r e q u e s t . g et Co nte nt ( ) ) ;
48 S t r i n g c onteu do = s t . nextToken ( ) ; // pego p ri mei ro t oken
i f ( conteudo . e qu al sI gn or eC a se ( "fogo" ) ) {// s e f o r f og o
s t . nextToken ( ) ; // pu lo o segundo
51 int d i s t a n c i a = I n t e g e r . p a r s e I n t ( s t . nextToken ( ) ) ; // ca pt uro
DIST
i f ( d i s t a n c i a <DISTANCIA MAX) {
System . out . p r i n t l n ( "Central " + getLocalName ( ) + ":
Saimos correndo !" ) ;
54
ACLMessage a g r ee = r e q u e s t . c r e a te R ep l y ( ) ;
a g re e . s e t P e r f o r m a t i v e ( ACLMessage .AGREE) ;
57 return agree ; // e nv ia mensagem AGREEE
}e l s e {
// Fogo e s t ´a l o n g e . Envia Mensagem R ef us e com o m oti vo
60 System . out . p r i n t l n ( "Central " + getLocalName ( ) + ":
Fogo est´a longe demais . N~ao podemos atender a
solicita¸c~ao." ) ;
throw new RefuseException (" Fogo est´a muito longe" ) ;
}
63 }// e nv ia mensagem NOT UNDERSTOOD
e l s e {
throw new NotUnderstoo dExcep tion ( " Central de Bombeiros n~ao
entendeu sua mensagem " ) ;
66 }
}
69
// Prepara r e s u l t a d o f i n a l , ca so ten ha a c e i t a d o
3.6. Protocolos de Intera¸ao 76
72 protected ACLMessage p r e p a r e R e s u l t N o t i f i c a t i o n ( ACLMessage re qu est ,
ACLMessage r e s p o n s e ) throws FailureException {
i f ( Math . random ( ) >0 . 2 ) {
System . out . p r i n t l n ( "Central " + getLocalName ( ) + ":
Voltamos de apagar o fogo ." ) ;
75 ACLMessage i nf or m = r e q u e s t . c r e at e R e pl y ( ) ;
i nf or m . s e t P e r f o r m a t i v e ( ACLMessage .INFORM) ;
return inform ; // env ia mensagem INFORM
78 }e l s e {
System . out . p r i n t l n ( "Central " + getLocalName ( ) + ": Ficamos
sem ´agua" ) ;
throw new FailureException("Ficamos sem ´agua" ) ;
81 }
}
84 }
}
 
Na classe FIPARequestCentraldeBombeiros existe os seguintes c´odigos em seu m´e-
todo setup():
MessageTemplate protocolo = MessageTemplate.MatchProtocol
(FIPANames.InteractionProtocol.FIPA_REQUEST);
MessageTemplate performativa=MessageTemplate.MatchPerformative
(ACLMessage.REQUEST);
MessageTemplate padrao=MessageTemplate.and(protocolo, performativa);
Um agente da classe FIPARequestCentraldeBombeiros implementa o papel de partici-
pante do protocolo request e, por isto, o mesmo implementa a classe AchieveREResponder,
e no construtor desta classe faz-se necess´ario passar qual ´e o padr˜ao de mensagens que ele
est´a aguardando. Estas linhas de c´odigo criam um objeto padrao da classe MessageTemplate
que ir´a fazer com que o agente aceite apenas mensagens do protocolo request e mensa-
gens do tipo request.
Para execu¸ao deste cen´ario vamos utilizar um ambiente distribu´ıdo. Conforme j´a
vimos, a plataforma JADE trabalha com o conceito de containers, representando um
ambiente onde os agentes podem executar seu ciclo de vida. Onde os agentes est˜ao
rodando, deve possuir uma JRE e as bibliotecas da plataforma JADE para que estes
funcionem perfeitamente. A Figura 3.13 ilustra este conceito.
Em uma plataforma sempre temos o main-container, aquele iniciado primeiro, com-
posto pelo DF e AMS, al´em de outros agentes. Observe que quando inici´avamos outro
agente em um mesmo computador, inclu´ıamos o parˆametro -container, isto representa
a cria¸ao de outro container.
3.6. Protocolos de Intera¸ao 77
Figura 3.13: Plataforma Distribu´ıda JADE.
O que vamos fazer nesta execu¸ao ´e alocar alguns agentes em uma m´aquina e outros
em outra que est˜ao ligadas em rede. O nosso agente Alarmado executar´a em um container
em uma m´aquina da plataforma. As centrais dos bombeiros estar˜ao na outra m´aquina da
rede.
Vamos definir que a m´aquina que contar´a o main-container da plataforma ´e a m´aquina
1, que cont´em as centrais. Vamos iniciar as centrais no main-container. Para isto, em
nossa m´aquina 1 (denominada de PC-1) executamos a seguinte linha:
java jade.Boot C1:FIPARequestCentraldeBombeiros
C2:FIPARequestCentraldeBombeiros
C3:FIPARequestCentraldeBombeiros
Com isto, temos o seguinte resultado:
Central C1: Aguardando Alarmes...
3.6. Protocolos de Intera¸ao 78
Central C2: Aguardando Alarmes...
Central C3: Aguardando Alarmes...
Na outra m´aquina da rede (PC-2) executamos o agente Alarmado, com a seguinte linha
de comando:
java jade.Boot -host PC-1 -container Alarmado:FIPARequestAlarmado(C1 C2 C3)
Com esta linha de comando, informamos onde o main-container est´a, no caso o pa-
ametro -host indica que este est´a no computador PC-1. Com a execu¸ao do agente
Alarmado, observamos no prompt da m´aquina PC-1:
Central C1: Recebemos uma chamada de Alarmado@PC-1:1099/JADE dizendo
que observou um inc^endio.
Central C2: Recebemos uma chamada de Alarmado@PC-1:1099/JADE dizendo
que observou um inc^endio.
Central C3: Recebemos uma chamada de Alarmado@PC-1:1099/JADE dizendo
que observou um inc^endio.
Observe que mesmo estando na m´aquina PC-2, as mensagens indicam que o agente
Alarmado est´a no PC-1. Isto ocorre pois o nome padr˜ao de uma plataforma ´e o nome
da m´aquina onde est´a o main-container. Mas o agente Alarmado est´a executando na
aquina PC-2.
Agora temos o seguinte resultado, de acordo com as probabilidades definidas para
nossos agentes centrais:
Central C1: Saimos correndo!
Central C2: Fogo est´a longe demais. N~ao podemos atender a solicita¸c~ao.
Central C3: Fogo est´a longe demais. N~ao podemos atender a solicita¸c~ao.
Neste mesmo instante, no prompt do PC-2 observamos o seguinte:
Central de bombeiros C1@PC-1:1099/JADE informa que saiu para apagar o fogo.
Central de bombeiros C2@PC-1:1099/JADE informa que o
fogo est´a muito longe e n~ao pode apag´a-lo.
Central de bombeiros C3@PC-1:1099/JADE informa que o
fogo est´a muito longe e n~ao pode apag´a-lo.
Agora, como a Central de Incˆendio C1 aceitou apagar o fogo, ela notifica que o fogo
est´a apagado para o agente alarmado. Obtemos a seguinte linha:
Central de bombeiros C1@PC-1:1099/JADE informa que apagou o fogo.
Referˆencias Bibliogr´aficas
[Bellifemine, Caire e Greenwood 2007]BELLIFEMINE, F. L.; CAIRE, G.; GRE-
ENWOOD, D. Developing Multi-Agent Systems with JADE (Wiley Series in Agent Te-
chnology). [S.l.]: John Wiley & Sons, 2007. ISBN 0470057475.
[Blaya 2005]BLAYA, J. A. B. Tutorial b´asico de JADE. [S.l.], Febrero 2005.
[JADE Wikispaces]JADE WIKISPACES. Programac´ıon JADE. [S.l.]. Dispon´ıvel em:
<http://programacionjade.wikispaces.com>. Acesso em: 22 Dez 2007.
[Vaucher e Ncho]VAUCHER, J.; NCHO, A. JADE Tutorial and Primer. [S.l.]. Dispon´ıvel
em: <www.iro.umontreal.ca/ vaucher/Agents/Jade/JadePrimer.html>. Acesso em: 22
Dez 2007.
79

Navigation menu