Este documento resume um estudo sobre a programação de componentes definidos pelo usuário no Jason. Discute-se como estender as capacidades dos agentes implementados no Jason através de ações internas e personalização de classes. Apresenta exemplos de como definir novas ações internas em Java e como customizar a classe Agent para alterar o comportamento de seleção de eventos, intenções e mensagens.
1. Notas de estudo sobre
User-Defined Components
por
Nécio de Lima Veras
2. Objetivo
Estes slides objetivam documentar um estudo
sobre a programação de agentes em sistemas
multi-agentes, especificamente, o capítulo 7
(componentes definidos pelo usuário) do livro
Programming Multi-Agent Systems in
AgentSpeak Using Jason. A ideia é investigar
as formas de implementar arquiteturas
(diferentes à BDI) de agentes no Jason.
3. Introdução do capítulo
●
●
Jason é distribuído com um conjunto de funcionalidade
para desenvolvimento de Agentes;
No entanto, desenvolvedores sempre necessitam de
requisitos específicos em seus sistemas, tais como:
–
Acesso à base de dados;
–
Integração com sistemas legados;
–
Interfaces gráficas;
–
Capacidades e percepções personalizadas de agentes;
–
Manipulação de intenções especiais;
–
Muitos outros.....
4. Introdução do capítulo
●
●
●
●
Para atender a essas especificidades uma abordagem baseada em
extensibilidade foi adotada no projeto Jason;
Como o próprio Jason é escrito em Java, então essas extensões
envolvem também a linguagem Java;
É possível desenvolver agentes com uma linguagem totalmente
declarativa (AgentSpeak) e também estender a linguagem com
bibliotecas e componentes criados usando o paradigma tradicional
da OO;
Novos comandos podem ser adicionados à linguagem por meio de
ações internas e diversos componentes (ambos escritos em Java)
do interpretador podem ser personalizados;
–
Para isso, existe uma API disponível;
5. Introdução do capítulo
●
Há dois motivos para a criação de ação interna:
–
–
●
Ampliar as capacidades internas do Agentes (quando a OO for
mais cabível do que o paradigma do AgentSpeak);
Permitir que seja usado código legado já programado em Java
ou em outras linguagens (acessíveis por meio do JNI – Java
Native Interface);
Existem algumas ações (padrão) internas no Jason, tais como:
–
–
.send
–
.my_name
–
●
.print
Uma lista completa está no apêndice A.3 do livro.
Além disso é possível também personalizar e estender diferentes
componentes do interpretador;
6. Definindo uma nova ação interna
●
●
●
Ações internas definidas pelo usuário podem ser
organizadas em bibliotecas específicas;
Em AgentSpeak, uma AI é acessada pelo nome da
biblioteca seguido por um “.” e pelo nome da ação;
Exemplo:
–
Uma nova AI chamada de distance dentro de uma
biblioteca chamada math pode ser usada tanto no
contexto ou no corpo de um plano do código
AgentSpeak;
7. Definindo uma nova ação interna
●
●
Bibliotecas são definidas como packages em
Java e cada AI é uma classe Java dentro do
pacote;
Lembre-se que em AgentSpeak
identificadores que iniciam com letras
maiúsculas indicam variáveis;
–
Por isso nomes de bibliotecas e de ações internas
em Java devem iniciar com letras minúsculas
já que serão usadas no AgentSpeak;
Mesmo sendo um
antipadrão OO
8. Definindo uma nova ação interna
●
●
Todas as classes que definem uma AI deve implementar a
interface InternalAction;
Existe uma implementação padrão desta interface que
simplifica a criação de novas AI chamada de
DefaultInternalAction;
10. Definindo uma nova ação interna
●
Entendendo o exemplo:
–
O método sobrescrito execute é chamado pelo interpretador
AgentSpeak para executar a AI;
–
O argumento ts contém todas as informações sobre o estado
atual do agente;
–
O segundo (un) é uma função unificadora que é determinado
pela execução do plano onde a AI apareceu (ou a checagem
se o plano é aplicável);
●
●
–
Isso depende se a AI surgiu no contexto ou em um plano;
Essa função unificadora é importante para o caso do valor ligado a
variáveis AgentSpeak for necessário para a implementação da AI;
O terceiro é um array de termos e contém os argumentos
passados para a AI pelo usuário no código AgentSpeak que
chama a AI;
11. Definindo uma nova ação interna
●
O segundo método de DefaultInternalAction
–
Chamado de suspendIntention
●
Deve retornar true quando a AI causar uma suspensão
do estado da intenção, assim como
–
●
.at e também .send com askOne como performativa;
Por padrão o método retorna false;
–
O usuário precisa garantir que a intenção será
retomada quando for o caso (se o método
suspendIntention for sobrescrito);
–
O código Java para execução da ação interna
math.distance possui três etapas:
12. Passo 1:
● obter as referências dos parâmetros
Passo 2:
● Realizar os cálculos
Passo 3:
● Organizar, unificar e retornar os
resultados
13. Definindo uma nova ação interna
●
●
Para o caso da AI ter sido usada no contexto
do plano retornar falso significa que o plano
não é aplicável;
Quando usado em um corpo de um plano,
retornar falso irá causar uma falha no plano;
14. Exemplo alternativo (um bingo!)
●
●
Existe um ambiente (Cartago) será um “bingo” onde números serão
sorteados depois de X cartelas “vendidas”;
Existem dois agentes: um proprietário (owner) e um jogador (player);
–
O owner cria o artefato “Bingo” e monitora-o a fim de perceber se as X
cartelas foram vendidas. Feito isso, ele realiza uma operação no
ambiente para iniciar o sorteio;
–
O player fica “vagando” até encontrar o artefato “bingo”. Ao encontrar
realiza uma operação de “compra” para participar do sorteio. Após isso
sua função é monitorar o ambiente esperando por números sorteados
(informados por meio de sinais) e pelo final do sorteio.
●
Este possui uma internal action chamada de buildCard que fica
no pacote ias. Ela gera aleatoriamente uma cartela de N números
com um um teto T para o sorteio dos números.
15. Ação interna buildCard
package ias;
public class buildCard extends DefaultInternalAction{
private Set <Integer> box = new HashSet <Integer>();
@Override
public Object execute (TransitionSystem ts, Unifier un, Term[] args) throws Exception{
NumberTerm size = (NumberTerm) args[0];
NumberTerm max= (NumberTerm) args[1];
Random r = new Random();
while (box.size() < size.solve())
box.add(r.nextInt((int)max.solve()) + 1);
ListTerm result = new ListTermImpl();
for (Integer i : box){
Term t = new NumberTermImpl(i);
result.add(t);
}
return un.unifies(result, args[2]);
}
}
//tamanho da cartela
// TETO para um numero sorteado
//garantir a não repetição dos números da
cartela
//converter a cartela em um feedback para o
agente
16. Estrutura e planos do agente Player
/* Initial beliefs and rules */
/* Initial goals */
!participate.
/* Plans */
+!participate: true<?myArtifact (ID);
focus(ID);
sell; //buy
- adquire uma cartela
println("Comprei uma cartela ...no bingo:", ID);
Chamada para a ação interna
ias.buildCard(5, 40, Card);
.concat("Cartela:", Card,S);
println(S);
Registrando a cartela na base de crença
+myCard(Card);
Hit = 0;
Registrando o número de acertos na base de crença
+myHits(Hit).
+?myArtifact(C) : true <lookupArtifact("b0", C).
-?myArtifact(Art) : true <.wait(1000);
println("Esperando por um bingo.");
!participate.
17. Percepções do agente Player
//Perceptions of the signals
+status(S) : S == "sorted" & myCard(Card) & myHits(Hit) <?numSorted(V);
println("Opa, percebi um numero sorteado ... ", V);
if (.member(V, Card) ) {
+myHits(Hit+1);
println("acertei:", V, " Ate agora acertei ", Hit+1, " numero(s) em um total de ", .length(Card));
}.
+myHits(Hit) : myCard(Card) <if (Hit == .length(Card)){
print("Gaaaaaaaaaaaaaaaaaaaannnnnnnnnnnnhhhhhhhhhhheeeeeeeeiiiiiii!!");
winner;
}.
+status(S) :
S == "started" <println("Legal! Bingo inciado!").
+status(S) :
S == "stoped" <println("Ahhhh .. já acabou.").
//Percepctions of the Observable Properties
+numSorted(V).
18. Personalizando a classe Agente
●
Partindo do ponto de vista do interpretador AgentSpeak um
agente é:
–
Um conjunto de crenças;
–
Um conjunto de planos;
–
Algumas funções de seleção definidas pelo usuário;
–
Funções de confiança (uma relação socialmente aceitável para
mensagens recebidas);
–
A função de atualização de crença;
–
A função de revisão de crenças;
–
Elementos circunstanciais (eventos pendentes, intenções e outras
estruturas necessárias durante a interpretação de um agente em
AgentSpeak);
19. Personalizando a classe Agente
●
●
A implementação padrão destas funções está
na classe Agent que pode ser customizada
por desenvolvedores a fim de estender
funcionalidades básicas;
Alguns dos métodos da classe pode ser
enxergado no diagrama a seguir;
21. Personalizando a classe Agente
●
Métodos da classe Agent que
normalmente são
sobrescritos:
–
selectMessage
(Queue<Message> mailbox)
●
●
●
Seleciona a mensagem que será
manipulada no atual ciclo de
raciocínio;
Na implementação padrão o
método retorna e remove a
primeira mensagem na caixa do
agente;
Implementa a função SM
Recorte do ciclo de raciocínio Jason
22. Personalizando a classe Agente
●
Métodos da classe Agent
que normalmente são
sobrescritos:
–
selectEvent
(Queue<Event> events);
–
Seleciona o evento que será
manipulado no atual ciclo de
raciocínio;
–
A implementação padrão
remove e retorna o primeiro
evento na fila;
–
Implementa a função SE
Recorte do ciclo de raciocínio Jason
23. Personalizando a classe Agente
Recorte do ciclo de raciocínio Jason
●
Métodos da classe Agent que
normalmente são sobrescritos:
–
selectOption
(List<Option> options)
–
É usado para selecionar um
dentre várias opções para
manipular um evento;
–
A implementação padrão remove e
retorna a primeira opção de
acordo com a ordem de escrita
dos planos do código do agente;
–
Implementa a função S0
24. Personalizando a classe Agente
●
Métodos da classe Agent que
normalmente são sobrescritos:
–
selectIntention
(Queue<Intention> intentions)
–
Seleciona uma intenção para
continuar a ser executada no
atual ciclo do raciocínio;
–
A implementação padrão remove
e retorna a primeira intenção da
fila e após a execução da
intenção é inserida no final da fila
(como em um round robin)
–
Implementa a função SI
Recorte do ciclo de raciocínio Jason
25. Personalizando a classe Agente
●
Métodos da classe Agent que normalmente são sobrescritos:
–
socAcc(Message m)
●
Retorna true se a mensagem m é socialmente aceitável;
●
A implementação padrão retorna true para todas as mensagens;
●
Se segurança for um problema, então este método deve
sobrescrito;
Caso contrário, o agente ficará suscetível a simples ataques de
DoS;
buf(List<Literal> percepts)
–
–
●
●
Atualiza a base de crenças com as percepções dadas;
Adiciona todas as alterações efetivadas como novos eventos em
um conjunto de eventos;
26. Personalizando a classe Agente
●
Métodos da classe Agent que normalmente são sobrescritos:
–
brf(Literal add, Literal rem, Intention i)
●
●
●
Revisa a base de crença com um literal a ser adicionado (se
houver), outra a ser removido (se houver) e a estrutura da
intenção é requerida para alterar a crença
A implementação padrão não faz nada e o método deve ser
sobrescrito ( ou seja, não há um revisor padrão de crenças em
Jason);
Retorna duas listas em uma matriz (uma com os acréscimos na
base de crença e outra com as exclusões);
As listas podem ser úteis para gerar eventos relevantes;
É importante enfatizar que a função de atualização de crença em
Jason apenas atualiza a base de crenças e gera eventos externos de
acordo com as percepções atuais;
–
●
–
Ela NÃO garante consistência de crença;
27. Personalizando a classe Agente
●
A implementação padrão da função de
atualização da base de crença funciona da
seguinte forma:
Conjunto de todos os literais atualmente na
base de crença
Lista das percepções atuais recebidas
Conjunto de eventos
28. Um primeiro exemplo de
personalização da classe Agent
●
Vamos mudar a função de seleção de eventos do robô aspirador de
pó (descrito no cap. 5);
–
●
●
Agora, ela priorizará eventos criados quando a sujeira é percebida;
A fila de eventos possui eventos criados a partir das percepções
(sujo; pos(r); pos(l)) e ações internas criadas por intenções;
O método passa por todos os eventos da fila e verifica se o gatilho
é igual a sujo (dirty)
–
–
●
Se for, a função remove da fila e retorna esse como único a ser tratado
no atual ciclo de raciocínio;
Se não, ele invoca a implementação padrão (que retorna o evento no
início da fila);
A seguir a implementação …....
29. Gatilho de uma percepção de sujeira
Retorna o comportamento padrão
30. Um primeiro exemplo de
personalização da classe Agent
●
Lembrando que o arquivo de configuração
deve associar os agentes oriundos dessa
nova classe da seguinte forma:
Nossa classe
31. Um segundo exemplo...
●
Suponha que queremos indicar no código AgentSpeak de um agente
que uma intenção deve ser selecionada apenas quando não há mais
nada a fazer;
–
●
Vamos chamar essa intenção de “the idle intention”;
Assim, o agente deve:
–
–
●
Selecionar a intenção ociosa somente se for a única intenção do agente;
Ou seja, enquanto o agente possui muitos focos simultâneos então a
intenção ociosa jamais deve ser selecionada;
Para marcar uma intenção como ociosa, um programador deve
adicionar uma anotação “idle” em um rótulo de plano que irá
formar a intenção;
–
●
Quando este plano se torna a intenção significa que toda a intenção tornase “idle”;
O código a seguir mostra a implementação da função Si
32.
33. Considere o seguinte agente:
A saída seria:
Perceba que as duas intenções são executadas
concorrentemente.
Se adicionarmos uma anotação rotulando o “idle” no
último plano da seguinte forma:
Teremos então a seguinte saída:
34. Conclusões sobre a personalização
da classe Agent
●
●
Percebemos que é possível estender o Jason com
novas funcionalidades (como a intenção ociosa);
No entanto, vale enfatizar que ajustes nas funções de
seleção são perigosos, pois emergem problemas
típicos da programação concorrente como o
starvation de intenções ou eventos;
–
●
Estes devem ser feitos com muito cuidado;
Por outro lado, de qualquer maneira, na prática os
agentes podem precisar morrer por inanição de
eventos se o ambiente for bastante dinâmico;
35. Referência
●
Bordini, R. H., Hübner, J. F., and Wooldridge, M. 2007. Programming
Multi-Agent Systems in AgentSpeak Using Jason. John Wiley & Sons,
Ltd.