Com o objetivo de explorar a COLABORAÇÃO entre agentes - algo que não foi diretamente abordado durante o curso, o projeto escolhido foi o de criar um mecanismo para permitir que as criaturas do WorldServer3D se comuniquem; para utilizá-lo, foi criada uma variação do agente CLARION - construído para realizar a busca de leaflets (aulas 10 e 11) - com capacidade de se comunicar.
Assim, foram entregues os seguintes artefatos:
- WorldServer3D modificado para conter capacidade de comunicação;
- Cliente CLARION utilizando o mecanismo de comunicação implementado;
Um ambiente sugerido para a execução é similar ao utilizado para
desenvolvimento, consistindo em:
ClarionDEMO.exe <IP-WorldServer3D> [<indicação-para-não-criar-jóias>]
Onde:
<IP-WorldServer3D> : endereço IP de onde o WorldServer3D está executando
<indicação-para-não-criar-jóias> : se for passado "false", o cliente iniciará sem criar um conjunto base de jóias e alimentos e também sem criar as paredes delimitadoras do tabuleiro.
A sugestão é executar primeiramente o cliente sem a criação das jóias com o comando:
ClarionDemo.exe <IP-servidor> false
A primeira criatura criada permanecerá em rotação horária, procurando jóias para buscar.
Depois fazer a criação da próxima criatura, com as jóias e alimentos:
ClarionDemo.exe <IP-servidor>
Com esse segundo comando as criaturas passarão a buscar as jóias e entregá-las no delivery-spot conforme seus leaflets forem sendo completados. Sempre que elas estiverem a uma distância mínima de 60, elas farão o processo de comunicação.
Teclando-se <SPACE> em qualquer um dos agentes em execução são criadas aleatoriamente 1 jóia de cada cor e mais alguns alimentos não perecíveis.
As limitações e problemas existentes nessa implementação estão descritas
aqui.
O código fonte do agente pode ser encontrado
aqui; nele foram incluídas mensagens de
debug que trazem a indicação do seu processamento interno; abaixo um pequeno trecho:
(700, 500)
. Jewel - lastMovementFeedback: 0.652257630094817, currentFeedbackValue: 0.655757630094816
. Jewel - needValue: 0.4875, distance: 0.824015260189633, feedback: 0.655757630094816
No delegate: - externalAction: GO_POSITION - whichThing: WorldServerLibrary.Model.Thing
>>>>>>>>>>>>>>>>>CommNetwork - creatureNear: True communicatonDone: False
>>>>>>>>>>>>>>>>>MovementNetwork - creatureNear: True communicatonDone: False
Contour: 0
Has choosen LISTEN action. Label: listen_1
[COMM] >>>>>>>>>> LISTENING
No delegate: - externalAction: LISTEN - whichThing:
[COMM] No one talked.
[COMM] Listening attempts 1
Todas as mensagens relacionadas ao processo de comunicação implementado possuem o prefixo "[COMM]" e podem ser filtradas para produzir um
log específico; abaixo um exemplo da conversação de um agente até completar o primeiro ciclo de comunicação:
[COMM] >>>>>>>>>> LISTENING
[COMM] No one talked.
[COMM] Listening attempts 1
[COMM] <<<<<<<<<< Listening. Total communication attempts: 1
[COMM] >>>>>>>>>> LISTENING
[COMM] No one talked.
[COMM] Listening attempts threshold reached 1.
[COMM] <<<<<<<<<< Listening. Total communication attempts: 2
[COMM] >>>>>>>>>> LISTENING
[COMM] No one talked.
[COMM] Listening attempts 1
[COMM] <<<<<<<<<< Listening. Total communication attempts: 3
[COMM] >>>>>>>>>> TALKING
[COMM] Trying to talk < carring >, but should be talking < OPEN_GREETING >
[COMM] <<<<<<<<<< Talking. Total communication attempts: 4
[COMM] >>>>>>>>>> LISTENING
[COMM] No one talked.
[COMM] Listening attempts 1
[COMM] <<<<<<<<<< Listening. Total communication attempts: 5
[COMM] >>>>>>>>>> TALKING
[COMM] TALKING CORRECT CYCLE: Talked < hello >
[COMM] <<<<<<<<<< Talking. Total communication attempts: 6
[COMM] >>>>>>>>>> TALKING
[COMM] Trying to talk < hello >, but should be listening
[COMM] <<<<<<<<<< Talking. Total communication attempts: 7
[COMM] >>>>>>>>>> TALKING
[COMM] Trying to talk < bye >, but should be listening
[COMM] <<<<<<<<<< Talking. Total communication attempts: 8
[COMM] >>>>>>>>>> LISTENING
[COMM] LISTENING CORRECT CYCLE: Creature Creature_1372812458876 talked < hello >
[COMM] COMPLETED CYCLE OPEN_GREETING
O mecanismo de comunicação adotado foi o de permitir que um agente FALE uma mensagem ou ESCUTE uma mensagem que outro agente próximo tenha falado. Embora esse mecanismo pareça intuitivo, existe uma primeira dificuldade de como SINCRONIZAR os 2 eventos - um agente falando e outro escutando - decorrente do fato de que cada agente se comunica de forma SERIAL com o WorldServer3D.
Para permitir a sincronização desses eventos utilizou-se o conceito de TEMPO DE VALIDADE de uma mensagem falada: ao ser falada, uma mensagem tem a validade de 1 segundo; durante esse intervalo, qualquer outra criatura é capaz de ouví-la e a criatura que falou não pode ouvir nada: este último aspecto é para modelar a situação em que tenta-se falar e ouvir ao mesmo tempo e o que se tem é ruído.
Se pelo menos 2 criaturas falarem ao mesmo tempo, uma terceira criatura que tentar escutar ouvirá apenas ruído.
Resumindo, o mecanismo de comunicação implementado tem as seguintes características:
- Cada criatura é capaz de FALAR uma mensagem;
- Cada mensagem falada tem um TEMPO DE VALIDADE de 1 segundo (ou 2 segundos no programa variante); durante esse tempo, a criatura que a falou não consegue escutar nada;
- Cada criatura é capaz de ESCUTAR uma mensagem falada por outra criatura que esteja a uma distância mínima 60. Se mais de uma criatura estiver falando ao mesmo tempo numa distância mínima de 60, qualquer outra criatura que tentar escutar ouvirá ruído.
Para implementar as duas novas operações foram criados os seguintes comandos:
Comando "talk", com o seguinte formato:
Comando:
talk <creature-ID> <message>
Resposta:
Ok. Talked <message>
Comando "listen", com o seguinte formato:
Comando:
listen <creature-ID>
Respostas possíveis:
Ok. <creature-name> talked <<message>>
Nok. creature closer
Nok. no one talked
Nok. Talking: cannot listen at the same time
Nok. Creatures talked at the same time: <talking-creature-name-1> ... <talking-creature-name-n>
Para a implementação desses comandos foram modificados 2 arquivos do código fonte do WorldServer3D:
- /src/worldserver3d/Main.java: tratamento dos 2 comandos através das funções "ProcessTalk()" e "ProcessListen()", descritas brevemente a seguir:
ProcessTalk(): Esta função simplesmente registra a mensagem na criatura cujo ID foi passado; a única situação de erro tratada é a passagem de um ID inválido/inexistente.
ProcessListen(): Esta função tem um tratamento maior, realizando as seguintes operações:
- Verificação de quais criaturas estão dentro do raio em que é possível ouví-las; na implementação atual é até a distância de 60.
- Caso encontre criaturas dentro dessa distância, busca em cada uma delas uma eventual mensagem falada que ainda esteja válida.
- Retorna a mensagem ouvida, caso apenas 1 criatura tenha falado uma mensagem que ainda esteja válida.
- /src/model/Creature.java: infraestrutura de armazenamento e controle de validade das mensagens faladas por cada criatura, com as seguintes alterações:
- Criação do método "talk()": registro da mensagem falada e do seu "timestamp", necessário para controle de sua validade.
- Criação do método "getTalkedMessage()": consulta da mensagem falada, caso ela ainda esteja dentro do seu período de validade, verificado a partir do "timestamp" de sua criação.
Todo o código fonte com essas modificações pode ser encontrado
aqui; todas as modificações estão demarcadas com comentários, como no exemplo abaixo (arquivo
Main.java):
// ia006b - 940011 - start
final static double LISTENING_DISTANCE_THRESHOLD = 60;
// ia006b - 940011 - end
Foram disponibilizadas 3 versões de executáveis Webstart para contemplar pequenas variações no tempo de validade das mensagens (definição continda no arquivo fonte "Creature.java":
- Versão com tempo de validade de 10 segundos: esta versão foi disponibilizada para permitir testes manuais dos comandos "talk" e "listen", via "telnet"; com 10 segundos de validade é possível enviar comandos manuais via essa interface para testar o mecanismo.
- Versão com tempo de validade de 1 segundo: esta é a principal versão de teste, utilizada e validada durante o ambiente de desenvolvimento, que consistia em:
- 1 laptop MacBook Pro com processador Core i5 para executar o servidor WorldServer3D
- 1 desktop Core2Duo para executar os 2 clientes CLARION
- Conexão via rede local wifi
- Versão alternativa com tempo de validade 2 segundos: esta versão foi disponibilizada como alternativa para execução em ambientes onde a execução e comunicação entre o servidor WorldServer3D e os clientes sofre um maior atraso, como é o caso do laboratório da disciplina.
As modificações realizadas para suporte aos comandos "talk" e "listen" foram bastante simples, mas já fornecem uma infra-estrutura básica para comunicação entre criaturas.
Uma extensão que, durante os testes dos clientes CLARION, demonstrou-se interessante de ser implementada é a externalização do "timestamp" das mensagens lidas através do comando "listen", de forma a permitir que os clientes verifiquem se já "ouviram" ou não uma mesma mensagem.
Sem aprofundar no estudo e discussão sobre como implementar a capacidade de comunicação, o objetivo foi criar agentes CLARION que fossem capazes de utilizar a infra-estrutura implementada no WorldSever3D para trocar mensagens, deixando o máximo possível as etapas de decisão, dentro do processo de comunicação, para o framework do CLARION.
Foi utilizado como base o mesmo agente criado durante a atividade das aulas 10 e 11, onde o objetivo foi construir um agente CLARION capaz de interagir com o WorldServer3D, buscando completar um leaflet de jóias a serem recolhidas; com a implementação do mecanismo de comunicação, quando houver mais de 1 criatura no ambiente e elas se encontrarem durante o processo de completar seus leaflets, elas terão a oportunidade de se comunicar.
Uma definição importante foi a do protocolo de comunicação a ser implementado nos agentes; embora os comandos "talk" e "listen" façam referência a uma linguagem natural, foi preciso reduzir muito o escopo do processo de comunicação para implementá-lo. Dessa forma, estes são os principais pontos do processo implementado:
A comunicação baseia-se na sequência de operações FALAR-ESCUTAR ou ESCUTAR-FALAR; a princípio não é esperado que num evento normal de comunicação uma mesma operação se repita sucessivamente; sequências FALAR-FALAR ou ESCUTAR-ESCUTAR só deverão ocorrer em situações definidas como erradas no processo de comunicação.
Foram consideradas apenas 3 tipos de mensagem, os quais devem se suceder numa determinada sequência de ciclos para completar uma comunicação com sucesso. Durante cada ciclo, um agente deve FALAR e ESCUTAR a mensagem correspondente para que possa evoluir ao ciclo seguinte. Foram considerados os seguintes ciclos:
Ciclo de saudação: neste ciclo cada agente deve saudar e ouvir a mesma saudação do outro agente com o qual tenta se comunicar; como o mecanismo de comunicação implementado é SERIAL, esse ciclo pode se iniciar com a operação de falar a saudação ou ouvir a saudação.
Ciclo de mensagem: neste ciclo a dinâmica é igual, mas ao invés da saudação uma mesma mensagem genérica de comunicação deve ser trocada entre os agentes; um exemplo seria cada um deles informar quais jóias está carregando. O ciclo é terminado quando cada agente falou e ouviu a mensagem, comunicando-se com seu interlocutor.
Ciclo de despedida: neste ciclo a mensagem que deve ser trocada é a de despedida; depois que cada agente ouvir e falar a mensagem de despedida, o processo de comunicação é finalizado.
- A partir do processo de comunicação descrito, é possível identificar a dificuldade de SINCRONIZAÇÃO da comunicação entre os dois agentes, considerando o caráter serial do canal de comunicação implementado pelos comandos WorldServer3D; de fato a maior dificuldade na implementação foi criar o mecanimo pelo qual essa sequência de ciclos de comunicação foi garantido, o que acabou sendo feito FORA do framework do CLARION.
Para suporte às operações de comunicação via o frameowork CLARION foi adotada a seguinte abordagem:
- Criação de uma rede neural - via classe SimplifiedQBPNetwork, com a seguinte configuração de entrada e saída:
Entradas:
- Distância relativa de todas as criaturas visualizadas no ambiente;
- Indicadores do estado atual nos ciclos do processo de comunicação;
Saídas:
- Comandos a serem executados;
- Criação de delegates "EligibilityChecker" para selecionar a rede neural que deve estar ativa: a rede neural de comunicação deve permanecer inativa enquanto o não houver criaturas próximas; nessa situação, a rede neural de movimentação (já existente na solução implementada para integração inicial CLARION/WorldServer3D) deve estar ativa. Os delegates criados foram os seguintes:
A configuração do suporte à comunicação é feita sobretudo na função "SetupTalkingNetwork()" reproduzida abaixo:
Nesta função é possível identificar os seguintes pontos:
- Na primeira parte são criados os pares DV que irão fornecer o estado atual da conversação, indicando cada um dos seus ciclos (saudação, mensagem ou despedida) e também a operação executada (falar, escutar, escutou barulho, escutou silêncio).
- Na segunda parte está a criação dos diversos ExternalActionChunks, utilizados para identificar a operação a ser executada; vale o detalhe da criação de 3 chunks referentes ao mesmo comando LISTEN: essa abordagem foi escolhida para diminuir a diferença de proporção de escolha entre os comandos TALK e LISTEN: com apenas um chunk do comando LISTEN, a proporção de TALKs era, pelo menos inicialmente, muito maior, o que provocava uma maior demora na convergência do sincronismo na comunicação, uma vez que em cada ciclo um agente começa FALANDO e o outro OUVINDO.
- Na terceira parte está a configuração inicial da rede neural, ressaltando-se a falta ainda das entradas relativas a cada uma das criaturas visualizadas.
A adição na rede neural de comuinicação de chunks referentes às criaturas visualizadas ocorre na função MakePerceptionFromSensorialInput(), conforme apresentado abaixo:
Também representado acima está a configuração do SensoryInput, com a definção do grau de ativação de cada um dos pares DV relativos ao processo de comunicação.
Conforme comentado anteriormente, o objetivo inicial era de que a maior parte das operações de decisão fossem resolvidas pelo framework CLARION; entretanto, um pouco pela necessidade de treinamento das redes neurais e provavelmente por uma falta de sofisticação no uso do framework, o tratamento das operações TALK e LISTEN acabou ficando complexo, com uma ênfase na segunda operação.
A operação de TALK possui o seguinte tratamento:
Neste tratamento ressaltam a verificação da adequação da mensagem indicada para ser falada com o ciclo atual e também a atualização consistente de todos os vários FLAGs de controle da comunicação.
Já o tratamento do comando LISTEN é mais complexo, uma vez que o comando tem múltiplas respostas e foram adicionados os seguintes mecanismos para facilitar o sincronismo entre os agentes:
- Retorno ao ciclo de comunicação anterior, caso seja detectado - através de múltiplas mensagens recebidas - que o interlocutor ainda está preso nesse ciclo;
- Caso seja detectado silêncio, tenta ainda ouvir por mais algumas vezes, mantendo o estado atual dos FLAGs de controle do estado da comunicação, antes de atualizá-los.
A adoção do mecanismo indicado no item 1 foi feita a partir dos testes, onde foi verificado que o sincronismo nunca era atingido caso um dos agentes avançasse sozinho no ciclo de comunicação, situação bastante comum, dada a característica serial da comunicação. O diagrama abaixo apresenta essa situação:
O tratamento completo do comando LISTEN é reproduzido abaixo:
Considerando a versão desenvolvida para as aulas 10 e 11, foram necessárias alterações para corrigir o correto suporte à interação com o WorldServer3D quando múltiplas criaturas estavam no tabuleiro:
- Tratamento de jóias e alimentos que são coletadas/ingeridas por outras criaturas
Considerando a abordagem que havia sido implementada, o agente armazenava internamente todas as jóias e alimentos que avistou em algum momento e, a partir dessas informações, orientava-se nas suas operações de movimentação; uma vez visualizadas, as jóias e alimentos só eram removidos quando o agente as coletava ou ingeria; as únicas atualizações que haviam sido implementadas eram da atualização da localização da jóia/alimento - uma vez visualizados, era verificado se o objeto não havia sido movimentado - e também da alteração de cor da jóia.
Com múltiplas criaturas no tabuleiro, uma jóia ou alimento pode também desaparecer caso tenha sido coletada ou ingerida por uma outra criatura. Nesse caso, não havia suporte para que essa percepção ocorresse e uma criatura continuaria a se orientar pela posição em que originalmente viu uma jóia (ou alimento), eventualmente dirigindo-se à ela e até mesmo tentando coletá-la.
Para corrigir esse comportamento foi implementado um mecanismo de timestamp para as jóias e alimentos visualizados: toda vez que o agente avista um desses objetos associa a ele um timestamp - o valor atual do CurrentCognitiveCycle:
Quando o agente decidir ir até esse objeto, o comando de GO_POSITION deverá ser selecionado pelo CLARION muitas vezes; se depois da primeira vez a diferença entre o timestamp armazenado para o objeto e o valor atual de CurrentCognitiveCycle for maior que um determinado limite, significa que a criatura está indo para a posição do objeto sem vê-lo, apenas pela informação que tinha anteriormente. Isso significa que o objeto já foi coletado por outra criatura e pode então ser ignorado:
- Suporte para definição de endereço IP do servidor WorldServer3D via linha de comando
Para permitir que o cliente seja executado a partir da linha de comando, foi criado esse suporte modificando-se o arquivo ClarionDEMO/Main.cs.
- Criação das criaturas em posições aleatórias
Também para facilitar a execução de múltiplas criaturas no WorldServer3D, foi modificado o processo de criação de novas criaturas, posicionando-as aleatoriamente no tabuleiro; modificação também em ClarionDEMO/Main.cs.
Embora o tratamento dos comandos TALK e LISTEN, fora do framework CLARION, tenha ficado um tanto extenso e complexo, existe a expectativa de que o agente seja capaz de aprender como deve ser o processo de comunicação e, com isso, conseguir executá-lo com maior eficiência, o que poderia ser detectado com o uso de um menor número de ciclos cognitivos de comunicação empregados na comunicação, grandeza registrada pela variável communicationAttempts.
Entretanto, os poucos testes executados não permitiram comprovar essa hipótese, como
a análise dos logs de comunicação coletados (veja aqui o processo de coleta) pode demonstrar:
| Agente 1 | Agente 2 |
Ciclos para conclusão conversa 1 | 138 | 167 |
Ciclos para conclusão conversa 2 | 22 | 18 |
Ciclos para conclusão conversa 3 | 103 | 109 |
Ciclos para conclusão conversa 4 | 98 | 97 |
Uma segunda rodada de testes gerou os seguintes resultados:
| Agente 1 | Agente 2 |
Ciclos para conclusão conversa 1 | 27 | 16 |
Ciclos para conclusão conversa 2 | 49 | 18 |
Ciclos para conclusão conversa 3 | 52 | 41 |
Ciclos para conclusão conversa 4 | 62 | 60 |
Ciclos para conclusão conversa 5 | 38 | 44 |
Ciclos para conclusão conversa 6 | 49 | 28 |
Ciclos para conclusão conversa 7 | 55 | 61 |
Ciclos para conclusão conversa 8 | 89 | 95 |
Ciclos para conclusão conversa 9 | 48 | 18 |
Ciclos para conclusão conversa 10 | 82 | 72 |
Para essa segunda rodada de testes, os aqui estão os logs do
agente 1 e do
agente 2.
São poucas as conclusões obtidas com a partir da pequena carga de testes e análises. É possível verificar uma grande variabilidade nos resultados, considerando a medida realizada; uma conclusão é a de que essa variabilidade é decorrente da sensibilidade do mecanismo de comunicação implementado, no que se refere à sincronização entre os agentes.
Para avaliar o processo decisório realizado no framework CLARION, talvez o mais adequado fosse tentar remover os problemas de sincronização e verificar com qual precisão o agente definiu a correta ação, considerando o ciclo e o estado da comunicação.
- Problemas ou pendências pré-existentes da implementação anterior do agente, utilizada como base;
- Dificuldade na sincronização entre os agentes, decorrentes da infra-estrutura implementada (ausência de timestamp das mensagens fazendo com que o agente escute várias vezes a mesma mensagem) e também da abordagem de comunicação escolhida (necessidade de ciclos combinados FALAR/ESCUTAR num agente e ESCUTAR/FALAR noutro, para avançar na comunicação.
- O mecanismo de comunicação implementado ficou muito sensível à variações de velocidade do ambiente de execução, especialmente porque a abordagem de mensagens utilizadas depende bastante de uma sincronia entre os agentes, a qual só é atingida em alguns pontos do processo (ciclos) de comunicação.
- Uma possibilidade de melhoria poderia ser o acréscimo de uma ação NÃO FAZER NADA, na expectativa de criar mais pontos de sincronização entre os agentes; de certa forma isso foi tentado com os thresholds adotados para o comando LISTEN no caso de silêncio.
- Comunicação só ocorre quando as criaturas se encontram por acaso, durante os seus processos de completar leaflets.
- As criaturas não tem algorítmo para desviar uma das outras; portanto, ficam travadas se encostarem.
- A criação de jóias/alimentos via tecla <SPACE> posiciona os novos objetos aleatoriamente, sem levar em consideração o que já está no tabuleiro; com isso uma criatura pode ficar travada, caso uma nova jóia ou alimento seja posicionada muito próximo mas fora de sua vista.
- Não foram realizados testes com mais de 2 criaturas no tabuleiro; dada a complexidade da comunicação, muito provavelmente os algoritmos de tratamento dos comandos TALK e LISTEN não irão funcionar para manter conversas paralelas com várias criaturas ao mesmo tempo.
Embora o objetivo inicial do projeto tenha sido a exploração da colaboração entre agentes, praticamente pouco foi feito nesse sentido, uma vez que todo o esforço foi empregado na criação de um mecanismo de comunicação o que, por si só, já representou um desafio.