You are here

Aula 4

Objetivos

Na aula de hoje, seguiremos o tutorial 3 do SOAR. Neste tutorial, o objetivo é lidar com problemas mais complexos, que exigem a decomposição de uma meta em metas intermediárias (subgoals), de forma a ser resolvido. Para isso, utilizaremos o pequeno jogo TankSoar, desenvolvido pelo grupo do SOAR para ilustrar situações mais complexas. O nosso agente no TankSoar possuirá agora um grande número de possíveis ações e comportamentos possíveis, e o Soar deverá ser capaz de elaborar uma estratégia que coordene essas ações no tempo. Isso exigirá o uso do mecanismo de impasses e a criação de sub-estados, que iremos exercitar durante a aula.

Atividade 1

Execute o programa TankSoar e se familiarize com seu funcionamento. Verifique quais os sensores disponíveis e quais as ações possíveis a cada tanque, bem como os objetos que podem ser encontrados no ambiente. Crie 2 agentes com a base de regras simple-bot.soar e execute o programa.

Atividade 2

Execute as atividades previstas no Tutorial 3. Registre as atividades realizadas no seu relatório.

Atividade 3

Desenvolva um programa Soar, utilizando o mapa do ambiente, para fazer com que o tanque, além de suas atividades normais, dirija-se aos carregadores de energia e saúde, quando estiverem com baixa energia ou baixa saúde.

Relatório

Após a instalação e a execução inicial do TankSoar, foi estudado o comportamento inicial do Tank e seus sensores. Durante a depuração do simple-bot.soar, pode se identificar os elementos conforme notados nas figuras abaixo.

Figura1 - Exemplificação dos WME de entrada com diversos sensores ativos

 

Figura2 - Representação dos sensores na aplicação TankSoar

Nas figuras Figura1 e Figura2 acima é possível notar sensores primários e secundários como Blocked (WME B1), direção, energia, pontuação atual (WME C3), ou por exemplo o cheiro (WME S3) ou até mesmo detector de ondas de radar (WME R4).

A figura a seguir mostra mais detalhadamente as informações coletadas do Radar, tanto na representação no TankSoar quanto na representação dos WMEs em Soar.

Figura3 - Elementos de Radar R14, incluindo os obstaculos (por exemplo WMEs O5, O6, O7) e também elementos de Saúde (WME H1) e suas respectivas posições e distâncias.

Um outro elemento visto foi o recarregamento do Tank após pegar um elemento de energia, conforme ilustrado na Figura4.

Figura4 - Sensor de Recarga de Energia

Outros dois elementos analisados foram os Sensores de Vinda e o lançamento de Mísseis (Incomming Sensor e Fire Missile) conforme Figura5 e Figura6 abaixo.

Figura5 - Incomming Sensor

Figura6 - Ouput - Fire Missile

Durante a execução do tutorial, foi possível notar a hierarquia dos subgoals conforme representados na figura abaixo.

Figura7 - Divisão dos subgoals

A decisão para cada subgoal é definida baseado em uma série de parametros lidos dos sensores. Por exemplo, o ataque deve ocorrer caso tenha um tanque identificado e tenha energia suficiente para a batalha. Nesse subgoal o tanque tomará a decisão necessária (virar, mover, deslizar) para então disparar. Outro exemplo é o de perseguir, onde baseado na proximidade de um tanque (medido pelo sensor de som), ele começará a perseguir o tanque até encontrar a fonte geradora do som.

Um detalhamento para cada subgoal e quais parametros são considerados pode ser notado na representação em árvore abaixo.

Figura8 - Representação da árvore com os elementos de decisão para cada subgoal.

Como resultado podemos ver o Soar seguindo o caminho correto conforme execução abaixo.

Figura9 - Wander, Chase e Attack

É possível notar que nos casos acima, os tanques tinham energia e mísseis suficientes para enfrentar o ataque, logo a perseguição e o ataque aconteceram.

Em um momento posterior, com os tanques ja desgastados, podemos notar a fuga, conforme mostrado na figura a seguir.

Figura10 - Fuga quando contato a vista porém sem energia para enfrentar a batalha

Nesse ponto podemos notar tambem a presenca das esperas. Nesse caso a espera é premeditada, pois o tanque sem energia fica escondido esperando o outro tanque passar sem encontra-lo. Há cenários onde por questão de um problema na aplicação, o Soar se depara em uma situação onde nenhum operador é proposto. Nessas condiçoes, o operador wait é necessário para impedir sobrecarga da pilha e esperar até que alguma condição dos sensores mude, fazendo com que um novo operador se faça proposto.

Figura11 - Crescimento desordenado da pilha

Na Figura11 foi forçada uma situação onde o wait seria necessário. É possível notar um crescimento desordenado da pilha, que se prolongado por muito tempo causaria sobrecarga da pilha.

Um artifício que podemos adicionar para melhorar a inteligência de nossos tanques é o mapeamento do cenário. Baseado nas medições dos sensores (principalmente radar e de bloqueio), o tanque pode armazenar essas informações de tal modo a mapear as áreas conhecidas do cenário e seus elementos, como por exemplo ondé há elementos de recarga de saúde e energia, onde estão os bloqueios e os caminhos abertos. Com isso é possível implementar táticas bem mais complexas, de forma a não deixar o tanque vulnerável, ou então buscar rapidamente uma recarga em fala de energia ou saúde, entre outros.

A implementação do mapeamento do cenário pode ser estudada a partir da execução do mapping-bot.soar do tutorial.

Figura12 - Operador para o mapeamento do cenário setando a informação de posição limpa

Podemos identificar na memória de trabalho onde estão posicionados os elementos já identificados pelo tanque. Na figura abaixo é possível ver a posição onde o elemento de recarga de energia se encontra.

Figura13 - Posição do elemento de recarga identificado pelo tanque

Com isso foi possível juntar todos os elementos e chegar ao objetivo dessa aula.

Para a sugestão da aplicação dessa aula, podemos propor uma alteração nos subgoals, criando um novo subgoal para recarga. Esse subgoal deve ter prioridade sobre Wander, porém case o tanque esteja sendo perseguido, é melhor fugir do que procurar uma recarga e ter que enfrentar uma batalha no caminho.

Figura 14 - Novo subgoal - Recharge

Figura15 - Nova árvore com o subgoal de Recharge para Energia e Saúde

Com essa idéia, podemos identificar a posição dos recarregadores checando os atributos no mapa:

  • Para energia
   (state <s> ^name recharge
              ^superstate <ss>)
   (<ss> ^map.square <sq>)
   (<sq> ^x <x>
         ^y <y>
         ^energy *yes*)
  • Para saúde
   (state <s> ^name recharge
              ^superstate <ss>)
   (<ss> ^map.square <sq>)
   (<sq> ^x <x>
         ^y <y>
         ^health *yes*)
 
Com isso é possível elaborar a lógica de detecção de direção a mover. Muito parecido com o Chase, é posível utilizar as coordenadas X e Y dos elementos e a direção atual do tanque para guia-lo até uma posição.
#atividade3
sp {elaborate*recharge*energy
   (state <s> ^name recharge
              ^superstate <ss>)
   (<ss> ^map.square.energy *yes*
    <ss> ^map.square.x <x>
    <ss> ^map.square.y <y>)
-->
  #definir uma direção relativa a ser movido
   (write (crlf) | Elaborate Energy Position | <x> | & | <y>)
   }
 
sp {elaborate*recharge*health
   (state <s> ^name recharge
              ^superstate <ss>)
   (<ss> ^map.square.health *yes*
    <ss> ^map.square.x <x>
    <ss> ^map.square.y <y>)
-->
  #definir uma direção relativa a ser movido
   (write (crlf) | Elaborate Health Position| <x> | & | <y>)
   }
#end
 
Da mesma forma podemos propor o operador de recharge para nosso subgoal.
#atividade3
sp {propose*recharge*health
   (state <s> ^name tanksoar
              -^sound
              ^health-energy low
              ^io.input-link <io>)
   (<io> -^radar.tank
        -^incoming.<dir> yes)
   -->
   (<s> ^operator <o> + =)
   (<o> ^name recharge)
(write (crlf) | Propose Recharge Health  Low |)}
 
sp {propose*recharge*energy
   (state <s> ^name tanksoar
              -^sound
              ^missiles-energy low
              ^io.input-link <io>)
   (<io> -^radar.tank
        -^incoming.<dir> yes)
   -->
   (<s> ^operator <o> + = )
   (<o> ^name recharge)
   (write (crlf) | Propose Recharge Energy  Low |)}
#end
 
Para que essa lógica funcione, a validação dos valores de energia e saúde devem ser elaboradas no top-state, conforme segue:
#atividade3
sp {elaborate*state*health*low
   (state <s> ^name tanksoar
              ^io.input-link.health <= 200)
   -->
   (<s> ^health-energy low)
   (write (crlf) | Health  Low |)}
#endf
 
sp {elaborate*state*energy*low
   (state <s> ^name tanksoar
              ^io.input-link.energy <= 200)
   -->
#atividade3
   (<s> ^energy-energy low)
#end
   (write (crlf) | Energy  Low |)}
 
Para evitar a concorrencia do Recharge com o Wander, uma pequena mudança é sugerida para que o operador não seja proposto em caso de energia ou saúde baixa.
 
sp {propose*wander
   (state <s> ^name tanksoar
             -^sound
#atividade3
             -^health-energy low
             -^energy_energy low
#end
              ^io.input-link <io>)
   (<io> -^radar.tank
        -^incoming.<dir> yes)
-->
   (<s> ^operator.name wander)
}
 
Baseado na elaboração da direção, podemos propor os movimentos (move e turn) muito similares aos do Chase de forma a ter o tanque "perseguindo" energia ou saúde, conforme necessidade.
 
Durante a execução podemos ver a identificação da posição do elemento.
 
Figura16 - Trace de recharge

Referências: Tutorial 3 e Manual do pacote de documentação do Soar e codigos de exemplo do tutorial - mapping-bot e simple-bot

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer