FORMIGAS



Introdução

No elenco das acções simples que as formigas executam, consta a procura incessante e aleatória de comida com o intuito de ser transportada para o ninho. Ao fazê-lo cheiram também a possível presença de feromonas, substância que elas próprias libertam ao longo do trajecto que efectuam ao transportar a comida para o ninho. Com efeito, uma vez encontrada comida, quer por acaso quer guiadas pelo olfacto, as formigas apanham um pedaço de comida que transportam de imediato para o ninho, ele próprio localizado por olfacto.

A simulação consegue reproduzir a capacidade das colónias de formigas de explorarem fontes de comida sequencialmente, começando pela que está mais perto e não pela que contém mais comida, uma característica associada ao modo aleatório de procurar comida por parte das formigas.



Utilização

Quando se prime o botão Preparar é criado um ninho de formigas (em azul com uma "fonte de formigas" ou "orifício" cor-de-laranja, no centro do ecrã). Para introduzir alimento na janela de visualização, deverá utilizar o botão "depositar-comida" onde, através da posição escolhida pelo ponteiro do rato, poderá colocar a comida numa posição específica.

A forma da migalha depositada pode ser escolhida entre duas opções: regular ou aleatória. No primeiro caso, a migalha tem uma forma circular possuindo mais comida na região central e menos nas regiões periféricas. No segundo caso, a distribuição de comida é aleatória dentro de circulo com raio igual ao raio da migalha-regular. A escolha da cor da migalha a depositar pode ser seleccionada através de uma caixa de opções denominada por cor-migalha.

O número de formigas que estão inicialmente no ninho é pré-determinado pelo slider correspondente. Através das caixa de opções do canto superior direito, poderá escolher a inteligência das formigas, sendo esta representativa do alcance olfactivo.

A taxa de evaporação das feromonas permite-nos controlar quanto tempo (medido relativamente à escala de tics discretos do relógio da simulação) é que as feromonas persistem com cheiro activo, sendo que existe uma difusão residual das feromonas para a sua vizinhança imediata. Com o slider "taxa-de-difusão-feromonas" poderá alterar este parametro.

Criado o cenário inicial com o botão "Preparar", é tempo de accionar o botão "Executar", que funciona como um botão de PLAY e PAUSE sequencial. O consumo de comida pelas formigas em cada fonte pode ser observado no gráfico, em que linhas com a cor de cada fonte evoluem à medida que o tempo passa. Tem à sua disposição um interruptor que lhe permite ligar/desligar o traçado de um gráfico, com o intuito de acelerar a simulação.

Depois de executar uma simulação, pode sempre repôr (através de um botão com o mesmo nome) a distribuição das migalhas iniciais, sendo possível estudar a variação de diversos parâmetros com a mesma configuração de alimento.

Início

Questões

1. Experimente primeiro a simulação com apenas uma fonte de comida. Estude o que sucede variando quer o número de formigas quer a taxa de evaporação das feromonas, mantendo constante, em 50%, a taxa de difusão de feromonas. Para um dado valor fixo da taxa de evaporação, qual o valor crítico a partir do qual se consegue um trilho estável de formigas ? Quantas simulações efectuou ao tentar encontrar o referido valor crítico ?

2. Para um mesmo número de fontes de comida e taxa de evaporação de feromonas, e para dimensões da colónia de formigas diferentes mas sempre superiores ao valor crítico, nota alguma diferença no comportamento da colónia ?

3. Modifique o programa de forma a colocar 2 fontes de comida à mesma distância do ninho. Que comportamento observa ? Na realidade, as formigas tipicamente optam por consumir em bloco uma fonte de comida de cada vez. Em particular, para um número considerável de espécies, nem sempre a fonte com mais comida é a escolhida preferencialmente. A explicação para "uma fonte de cada vez" é hoje aceite como uma consequência evolutiva da espécie, pois um trilho composto de muitas formigas é mais resistente a condições adversas e/ou a inimigos (o mesmo argumento serve, por exemplo, para as manadas de zebras que decidem atravessar um rio infestado de crocodilos). Mas consegue encontrar uma razão para que as formigas nem sempre optem pela fonte de comida mais bem recheada ? E consegue constatar este comportamento nesta simulação ?

4. Dado que a caixa onde podemos pré-definir a inteligência de cada formiga faz com que na prática modifiquemos o seu alcance olfactivo (inteligência baixa => alcance = 0 , inteligência média => alcance = 1 e inteligência alta => alcance = 7), que espera obter se efectuar simulações com inteligência baixa?

5. Repita a questão 3 pre-definindo a inteligência de cada formiga como "alta". Que alteração (se alguma) constata no comportamento das formigas?

6. Face aos resultados das questões 3, 4 e 5, qual o nível de inteligência que atribui como mais realista para as formigas?

Início

Análise do código





Visão global

Tendo em conta a complexidade do seu código, o módulo "formigas" possui características que se destacam dos anteriores. A construção foi efectuada tendo em conta a facilidade de utilização, originando um enriquecimento das linhas de código com procedimentos e funções que saem fora do algorítmo principal, pelo que importa distinguir os procedimentos principais dos procedimentos auxiliares.

O algorítmo principal pode ser esquematizado da seguinte forma:

Neste módulo a maioria das definições afectam as propriedades dos patches, utilizando-se turtles apenas para definir as formigas. Estas movem-se livremente por cima dos patches, e utilizam recorrentemente a capacidade das turtles acederem às variáveis das patches que estão por baixo.

A fase de preparação (Preparar), vai ser caracterizada pela definição das características das formigas (Preparar-Formigas), pela definição dos patches constituintes do ninho e dos patches que contêm comida Preparar-Patches.

A fase de execução (Executar) é essencialmente caracterizada pela definição do movimento das formigas (Mover-Formigas) e pela actualização dos patches (Actualizar-Patches). O movimento das formigas pode ser dividido em duas situações: se possuem comida então têm de regressar ao formigueiro (função Regressar-ao-Ninho), caso contrário, têm de a procurar (função Procurar-Comida).

O regresso das formigas ao ninho, é caracterizado na função Cheirar-Ninho. As formigas nesta situação servem-se de uma propriedade dos patches, designada por cheiro-de-ninho, que possui um valor máximo no centro do ninho e será tanto menor quanto mais afastado estiver do centro do ninho. Este gradiente de cheiro vai ser essencial para a orientação das formigas quando retornam ao formigueiro. No momento em que as formigas passam a transportar comida e iniciam o caminho de regresso, passam a deixar nos patches por onde passam feromonas (cor verde na janela de visualização) que serão posteriormente utilizadas por outras formigas para chegar à comida. A variável feromonas constitui uma propriedade dos patches, sendo máxima a quantidade de feromonas depositada no momento em que a formiga encontra a comida, diminuindo à medida que as formigas se aproximam do ninho.

Em Procurar-Comida, a direcção de propagação das formigas é definida pela quantidade de feromonas presentes. Se a quantidade de feromonas tiver um valor considerável (definido como maior que 2), a formiga não muda de direcção. Por outro lado, se tiver um valor muito baixo (menor que 0.05), a direcção é definida aleatoriamente. No caso intermédio, o sentido de propagação é definido pelo procedimento Cheirar-Feromonas. Esta função mede todas as feromonas dos patches à frente, à direita e à esquerda da formiga. O alcance desta busca é definido pela função alcance-olfactivo, que depende da inteligência definida pelo utilizador.

Depois de mover todas as formigas é necessário actualizar os patches (Actualizar-Patches). Aqui é definida a cor dos patches assim como a taxa de evaporação das feromonas presentes no tabuleiro de simulação.

Para além destas funções existem outras que têm uma participação mais secundária no algorítmo. A descrição destas funções pode ser encontrada na explicação individual fornecida para cada um dos procedimentos desenvolvidos.



Lista das funções
Início
0. Variáveis
 globals[
   tempo                         
   horizonte-olfactivo          
   tamanho-migalha              
   quantidade-inicial-feromonas  
                                 
   Patch-Fronteira              
   c-c                           
   lista-x                       
   lista-y                       
   lista-tipo                    
]

turtles-own
[
   transporta-comida?
   quantidade-depositada        
]

patches-own
[
   feromonas
   comida
   ninho?              
   cheiro-de-ninho    
]

Variáveis globais:

tempo Número de iterações desde o início da simulação.
horizonte-olfactivo o horizonte olfactivo das formigas (o mesmo para todas) determina o ângulo máximo de abertura que as formigas exploram quando se movem ou quando cheiram quer o ninho quer a comida. O utilizador não tem a possibilidade de mudar este parâmetro, permanecendo constante e igual a atribuição dada na função Preparar.
tamanho-migalha Raio das migalhas. É apenas utilizada nas funções auxiliares Depositar-Comida, Depositar-Migalha-Regular e Depositar-Migalha-Aleatoria
quantidade-inicial-feromonas Quando uma formiga procede ao seu regresso ao formigueiro vai deixando feromonas nos patches por onde passa. A quantidade de feromonas depositadas vai sendo progressivamente menor à medida que a formiga enceta o seu regresso, sendo a quantidade de feromonas a depositar máxima no momento em que a formiga inicia o seu regresso. Esta quantidade máxima de feromonas a depositar é registada nesta variável quantidade-inicial-feromonas.
Patch-Fronteira agentset de patches pertencentes à fronteira da janela de visualização. O conjunto é criado na função Preparar-Patches.
c-c Não tendo qualquer relevância na construção do algorítmo, esta variável é usada no procedimento auxiliar do-plotting que trata da actualização do gráfico da quantidade de comida presente no tabuleiro. Aí esta variável corresponde à quantidade de comida de uma determinada cor a ser actualizada (comida-corrente).
lista-x e lista-y Com o objectivo de guardar as posições das migalhas, usa-se uma estrutura list para cada coordenada. Estas listas vão ser usadas pela função/botão Repor para testar diversos parâmetros com a mesma disposição de migalhas.
lista-tipo Esta lista surge associada às listas anteriores. Consiste num registo do tipo de migalha assim como da sua cor. Cada elemento da lista regista um valor numérico da cor, sendo esse valor negativo no caso de se tratar de uma migalha aleatória e positivo no caso de pertencer a uma migalha regular.

Campos característicos das turtles:

transporta-comida? Variável booleana que indica se a formiga (turtle) transporta comida. Quando esta variável é verdadeira, a formiga regressa ao ninho através da função Regressar-ao-Ninho. Caso contrário, recorre à função Procurar-Comida.
quantidade-depositada Quando a formiga encontra comida, dá meia-volta e inicia o seu regresso ao formigueiro, deixando feromonas nos patches por onde passa. A quantidade de feromonas a depositar é definida por esta variável, sendo mais pequeno o seu valor quanto mais tempo demorar o regresso ao formigueiro.

Campos característicos dos patches:

feromonas quantidade de feromonas depositadas no patch
comida quantidade de comida depositada no patch
cor cor do patch
ninho? Variável booleana que indica se o patch pertence ou não ao ninho.
cheiro-de-ninho Esta característica de cada patch é um indicador da sua distância ao ninho e é utilizada pelas formigas como modo de orientação aquando do seu regresso ao formigueiro


Análise do código
1. Preparar
to Preparar
  clear-all

  set tempo 0
  set horizonte-olfactivo 45
  set tamanho-migalha 3
  set quantidade-inicial-feromonas 40   

  set lista-x (list)        
  set lista-y (list)        
  set lista-tipo (list)      

  Preparar-Formigas                      
  Preparar-Patches

  do-plotting
end

A função Preparar está associada ao botão com o mesmo nome. Esta função é responsável pela inicialização dos patches, das variáveis globais e das formigas.

Começa por inicializar a variável tempo, fazer a atribuição do valor de 45 graus à variável horizonte-olfactivo (ver Variáveis), define o raio das migalhas tamanho-migalha e define a quantidade máxima de feromonas que uma formiga pode depositar (quantidade-inicial-feromonas).

Com o objectivo de registar as posições iniciais das migalhas, usaram-se 3 listas. Para a utilização destas estruturas é necessário inicializá-las fazendo uma atribuição do nome da lista à instrução list (Ver tópicos avançados).

De seguida, trata-se de inicializar as formigas e os patches com as funções Preparar-Formigas e Preparar-Patches.


Análise do código
1.1 Preparar-Formigas
to Preparar-Formigas
  set-default-shape turtles "ant"
  cct formigas    ;; (cct = create-custom-turtles)
  [ set size 2
    set color orange
    rt random-float 360
    set transporta-comida? false ]
end

set-default-shape turtles string Especifica a forma de todos os agentes turtles. O NetLogo possui diversas formas disponíveis, entre elas a forma "ant".

Depois de fazer a atribuição da forma de todas as turtles a construir, utiliza-se o comando create-custom-turtles que, além de criar um número de turtles igual a formigas (variável definida por um slider), corre as linhas de código seguintes para cada uma das turtles recém criadas. Desta forma, atribui-se o tamanho 2, a cor laranja e uma direcção aleatória. Todas as formigas iniciam a sua vida sem possuir qualquer comida ( transporta-comida? = false ).


Análise do código
1.2 Preparar-Patches
to Preparar-Patches
  set Patch-Fronteira patches with [ abs pxcor = screen-edge-x or abs pycor = screen-edge-y ]
  ask patches
  [ set feromonas 0
    set comida 0
    set ninho? distancexy 0 0 < 5  
    set cheiro-de-ninho 200 - distancexy 0 0       ;; cria um gradiente de cheiro-de-ninho
    if ninho?
    [ set pcolor blue ] ]
end

distancexy xcoord ycoord Retorna a distância da posição do patch corrente, ao patch de coordenadas t (xcoord, ycoord).

Vai ser aqui que se procede à inicialização dos patches do tabuleiro.

Antes de tudo, trata-se de definir os patches da região fronteira (Patch-Fronteira) como um conjunto de patches que possuem coordenada x igual, em módulo, ao screen-edge-x (maior valor absoluto de uma coordenada no tabuleiro de simulação), ou possuem um valor absoluto da coordenada y igual a screen-edge-y. Definido este agentset, poderemos facilmente definir o comportamento das formigas nas regiões fronteira (ver a função Universo-Finito).

Depois disso, são inicializados os campos característicos de cada um dos patches. Utilizando a tradicional instrução ask, corremos todos os patches inicializando a zero os campos comida e feromonas. Além disso, se o patch em causa estiver a uma distância inferior a 5 do centro do tabuleiro, o patch passa a pertencer ao ninho. Neste caso, ninho? passa a verdadeiro, tomando em seguida a cor azul.


Análise do código
2. Executar
to Executar
  ask turtles
  [ Mover-Formigas ]
  diffuse feromonas taxa-difusao-feromonas / 100
  ask Patch-Fronteira
  [ set feromonas 0 ]
  ask patches
  [ Actualizar-Patches ]
  set tempo tempo + 1
  do-plotting
end

diffuse variavel-do-patch valor Faz com que cada patch partilhe uma percentagem igual a (valor*100) da variável variavel-do-patch com os seus 8 primeiros vizinhos (note-se que valor deve estar compreendido entre 0 e 1). Este comando é utilizado do ponto de vista do observador e não do ponto de vista do patch, ou seja, o comando é aplicado automaticamente a todos os patches e não a um patch específico.

Esta função é chamada quando o utilizador prime o botão executar. É executada repetidas vezes em resultado da opção forever associada ao referido botão. Basicamente, esta função limita-se a chamar outras funções onde, aí sim, o núcleo do algorítmo está implementado.

Para cada uma das turtles formigas, é chamada a função Mover-Formigas que é responsável pela evolução da posição de cada formiga e da quantidade de comida e feromonas presentes na janela de simulação. Depois de se moverem as formigas, a função usa o comando diffuse para proceder à evaporação das feromonas para patches vizinhos. A variável taxa-difusao-feromonas é introduzida pelo utilizador através de um slider no interface gráfico. Para que não existam feromonas nas regiões fronteira, faz-se um ciclo ask para colocar a zero as feromonas dos patches destas regiões. Para tal, usa-se o agentset Patch-fronteira criado em Preparar-Patches

Para a actualização da informação gráfica, aplica-se para cada patch a função actualizar-patches. Esta função também vai ser responsável pela evaporação das feromonas. Em seguida, faz-se um incremento no "tempo" de simulação e procede-se à actualização da informação do gráfico através da função do-plotting.


Análise do código
2.1 Actualizar-Patches
to Actualizar-Patches
  ifelse ninho?
  [ set pcolor blue ]
  [ ifelse comida > 0
    [ set pcolor cor ]
    [ set feromonas feromonas * (100 - taxa-evap-feromonas) / 100
      set pcolor scale-color green feromonas 0 50 ] ]
end

scale-color cor numero c1 c2 Retorna um tom de cor proporcional à variável numero. Se c1 < c2, quanto maior for o numero mais claro é o tom da cor. Se, pelo contrário, c2 < c1, quanto mais próximo numero estiver de c2, mais escura é a cor. Neste caso, a cor utilizada é o verde, correspondendo à cor das feromonas.

Esta função é chamada no final de cada iteração da função Executar, depois da actualização da posição de cada uma das formigas. É aplicada do ponto de vista dos patches actuando sobre um patch específico.

O objectivo é pintar os patches da cor conveniente, de acordo com as variáveis comida, feromonas e ninho?. Para tal, usaram-se duas instruções ifelse encadeadas. A primeira, trata de pintar de azul no caso de se tratar de um patch pertencente ao ninho. Caso contrário, a função avança para outro ifelse que testa se o patch tem comida. Se assim for, o patch é pintado com a cor depositada na variável cor do patch em questão, caso contrário do patch não possuir comida, a linha

 set feromonas feromonas * (100 - taxa-evap-feromonas) / 100

é responsável pela evaporação das feromonas, e a linha

 set pcolor scale-color green feromonas 0 50

trata de produzir um gradiente de cor, de acordo com a quantidade de feromonas depositada no patch. A variável taxa-evap-feromonas é definida por um slider do interface e é um factor determinante para a orientação das formigas. No caso da taxa de evaporação ser nula, a quantidade de feromonas presentes num patch será constante ao longo do tempo, fazendo com que as formigas passem a dirigir-se sempre para o mesmo conjunto de patches, independentemente da comida existente nessa região.


Análise do código
2.2 Mover-Formigas
to Mover-Formigas
  if who < tempo  ;; impede a saida simultanea das formigas do ninho
  [ ifelse transporta-comida?
    [ 
      set color brown + 1   ;;formiga com comida fica com cor diferente
      Regressar-ao-Ninho 
    ]
    [ 
      set color orange
      Procurar-Comida 
     ] 
   ]
end

who trata-se de uma variável "de origem" de cada turtle. Corresponde a um número de identificação, variando de 0 até ao número total de turtles - 1, não sendo possível alterar este valor.

Este procedimento, consiste na base das funções que geram a o movimento das formigas sendo chamado dentro de um ciclo ask na função Executar. Corre do ponto de vista das turtles, visando uma turtle específica.

Todas as linhas desta função estão inseridas dentro de uma condição

if who < tempo

que apenas serve para, no início da simulação, impedir uma saída confusa e simultânea das formigas do ninho. Sendo assim, quando no ciclo ask na função Executar for chamada esta função, a turtle com identificação dada por who, apenas sairá do ninho se possuir um valor inferior ao tempo de simulação. Os motivos desta condição são puramente estéticos.

Com objectivos menos estéticos, as linhas seguintes são bastante simples. No caso da formiga transportar comida, a sua cor torna-se castanha, regressando ao ninho através da função Regressar-ao-ninho. Se pelo contrário, a formiga não possuir comida, terá de a procurar, utilizando para tal a função Procurar-Comida. Nestas condições, a formiga torna-se da cor laranja.


Análise do código
2.2.1. Regressar-ao-Ninho
to Regressar-ao-Ninho
  ifelse ninho?     ;; as turtles conseguem aceder às variáveis da patch que está por baixo!!!
  [ 
    set transporta-comida? false
    rt 180
    forward 1 
  ]
  [ 
    set feromonas feromonas + quantidade-depositada
    set quantidade-depositada quantidade-depositada - 1

    if quantidade-depositada < 1 [ set quantidade-depositada 1 ] 

    Cheirar-Ninho
    rt random horizonte-olfactivo - random horizonte-olfactivo
    forward 1 
  ]
end

O procedimento regressar-ao-ninho é chamado na secção Mover-Formigas quando a turtle formigas possui como verdadeira a variável booleana transporta-comida?. A formiga nestas condições, pode ser colocada em duas situações: no caso de se encontrar sobre patches pertencentes ao ninho, a formiga deve deixar de transportar comida e rodar 180° para reiniciar a sua busca por comida; caso contrário, deverá regressar ao ninho seguindo o percurso mais curto possível.

Para discernir entre estes dois casos, usou-se uma instrução ifelse. Como qualquer turtle pode aceder às variáveis características do patch que se encontra por baixo de si, basta-nos testar a variável intrínseca do patch ninho?. Se o teste for positivo, então alteramos o registo booleano transporta-comida? para false, produzimos uma rotação de 180 graus à formiga e fazemos avançar uma casa.

Caso contrário, começamos por incrementar a variável do patch feromonas com a variável da turtle quantidade-depositada. Esta quantidade de feromonas que uma formiga deixa nos patches onde passa é variável no tempo. Assim sendo, por cada movimento que a formiga faz em direcção ao ninho, a quantidade de feromonas a depositar vai sendo cada vez menor. Para produzir este efeito, juntou-se a linha que retira uma unidade de feromonas à quantidade a depositar na iteração seguinte. No caso da quantidade a depositar ser inferior à unidade, então a quantidade-depositada será sempre igual a 1 (instrução if quantidade-depositada < 1 ... ).

Resta-nos definir a direcção de propagação da formiga antes de a avançar uma unidade. Para tal, criou-se uma função Cheirar-Ninho, que provoca um dos seguintes três resultados: faz uma rotação com ângulo igual ao horizonte-olfactivo para a esquerda ou para a direita, ou não modifica a orientação da formiga. Esta decisão é efectuada a partir da quantidade de cheiro a ninho presente nos patches destas direcções. Depois desta decisão, a linha

rt random horizonte-olfactivo - random horizonte-olfactivo

provoca mais uma rotação aleatória de um ângulo escolhido aleatoriamente entre (-horizonte-olfactivo) e (horizonte-olfactivo).


Análise do código
2.2.2. Procurar-Comida
to Procurar-Comida
  ifelse comida > 0   
  [ 
    set transporta-comida? true
    set comida comida - 1
    set quantidade-depositada quantidade-inicial-feromonas  
    rt 180 
  ]
  [ 
    Universo-Finito              ;; se tiver na fronteira --> reflecte direcção do movimento
    ifelse feromonas < 0.05      
    [ 
      rt random horizonte-olfactivo - random horizonte-olfactivo 
    ]
    [ 
      if feromonas < 2
      [ Cheirar-Feromonas ] 
    ]
  forward 1 
  ]
end

Esta função é chamada no procedimento Mover-Formigas, e é a base do algorítmo de busca de comida, sendo chamada do ponto de vista de uma turtle formigas.

Tal como a maioria das funções sobre turtles deste módulo, usa-se a capacidade das formigas acederem às varáveis especificas dos patches que se encontram por baixo. Deste modo, torna-se muitíssimo fácil verificar se uma formiga se encontra por cima de um patch com comida. Através de uma instrução ifelse, começamos por testar a variável comida do patch que possui a formiga. No caso de a condição ser verdadeira, o indicador booleano transporta-comida? passa a verdadeiro e a comida depositada no patch sofre uma diminuição de uma unidade. Para definir a quantidade de feromonas a depositar na iteração seguinte, atribui-se à variável quantidade-depositada a quantidade quantidade-inicial-feromonas que indica o valor máximo de feromonas a depositar por uma formiga que transporta comida. A quantidade-depositada será cada vez menor à medida que a formiga prossegue o seu percurso em direcção ao ninho.

No caso de a formiga não se encontrar sobre um patch com comida, esta deverá orientar-se de maneira a encontrar alimento. Nesta fase do algorítmo, as opções reduzem-se a 3: se a quantidade de feromonas depositadas for muito pequena (< 0.05), a formiga escolherá uma direcção aleatória dentro do intervalo definido pelo horizonte olfactivo; no caso de feromonas ser superior a 0.05 e inferior a 2, a formiga deverá pesquisar as feromonas existentes na sua vizinhança e, a partir dessa informação, decidir a direcção de propagação ; se a quantidade de feromonas for superior 2, é razoável supor que a formiga está na direcção certa, ficando inalterado sentido do movimento. A pesquisa de feromonas referida no segundo caso, é definida através da função Cheirar-Feromonas.


Análise do código
2.2.3. Cheirar-Feromonas
to Cheirar-Feromonas
  locals [ alcance cheiro-esquerda cheiro-frente cheiro-direita ]
  Universo-Finito
  rt random horizonte-olfactivo - random horizonte-olfactivo  
  set alcance alcance-olfactivo     ;;ver função alcance-olfactivo
  set cheiro-esquerda 0
  set cheiro-frente 0
  set cheiro-direita 0
  while [ alcance > 0 ]
  [ 
    set cheiro-esquerda cheiro-esquerda + feromonas-of patch-left-and-ahead horizonte-olfactivo alcance
    set cheiro-frente cheiro-frente + feromonas-of patch-ahead alcance
    set cheiro-direita cheiro-direita + feromonas-of patch-right-and-ahead horizonte-olfactivo alcance
    set alcance alcance - 1 
  ]
  if (cheiro-direita > cheiro-frente) or (cheiro-esquerda > cheiro-frente)
  [ ifelse cheiro-direita > cheiro-esquerda
    [ rt horizonte-olfactivo ]
    [ lt horizonte-olfactivo ] ]
end

patch-left-and-ahead ang dist / patch-right-and-ahead ang dist Retorna um único patch a uma distância dist, numa direcção definida pela rotação para a direita ou para a esquerda de um ângulo ang.

VARIÁVEL-of agente Retorna o valor da VARIÁVEL característica do agente.

Na função Procurar-Comida, quando o número de feromonas presentes no patch é inferior a 2 e superior a 0.05, é chamada a função Cheirar-Feromonas que consiste na análise realizada por uma formiga sobre as quantidades de feromonas presentes no seu universo mais próximo.

Utilizam-se 3 variáveis locais: o alcance vai ser igual à distância de pesquisa, sendo definida através da função alcance-olfactivo; cheiro-esquerda, cheiro-direita e cheiro-frente vão acumular as feromonas dos patches situados nas direcções esquerda, direita e frente. A quantidade de patches analisados em cada uma das direcções é definida pela variável alcance.

A função começa por aplicar Universo-Finito, seguido de uma rotação aleatória dentro da gama do horizonte-olfactivo. Atribui-se à variável alcance o output da função alcance-olfactivo e inicializa-se a zero as restantes variáveis locais.

Em seguida, procede-se, através de um ciclo while, à soma das feromonas presentes nos patches das 3 direcções. O número de ciclos realizados vai ser igual ao alcance olfactivo da formiga, não existindo qualquer ciclo no caso de alcance ser igual a zero (inteligência "baixa"). Se o cheiro à frente for maior que os restantes, nada acontece. Caso contrário, a formiga roda um ângulo igual ao horizonte olfactivo para a direita ou para a esquerda, dependendo da quantidade de feromonas existentes nestas duas direcções.


Análise do código
2.2.4. alcance-olfactivo
to-report alcance-olfactivo
  ifelse inteligencia = "baixa"
  [ report 0 ]
  [ ifelse inteligencia = "alta"
    [ report 7 ]
    [ report 1 ] ]
end

Esta função retorna um valor, e é chamada na função Cheirar-Feromonas.

Aqui é definido o efeito da inteligência escolhida pelo utilizador. A inteligência de uma formiga vai ser equivalente ao raio de pesquisa de feromonas na sua vizinhança. Formigas mais inteligentes, poderão chegar ao numero de feromonas depositadas em patches mais distantes, sendo a sua decisão uma consequência do resultado da análise de muito mais informação.

No caso da inteligência baixa, as formigas apenas conseguem chegar à variável feromonas do patch que está por baixo, ou seja, o raio de pesquisa é igual a zero. Neste caso, a escolha da direcção de propagação vai ser totalmente aleatória, dentro do gama de ângulos definida pelo horizonte olfactivo. Formigas com inteligência média conseguem analisar os seus primeiros vizinhos. Formigas com inteligência alta já conseguem analisar patches a uma distância igual 7. As diferenças na janela de simulação são bastante notórias, sendo, para além do mais, muito fácil mudar a correspondência entre inteligência e alcance-olfactivo.


Análise do código
2.2.5. Cheirar-Ninho
to Cheirar-Ninho
  locals [ cheiro-esquerda cheiro-frente cheiro-direita ]
  Universo-Finito
  set cheiro-esquerda cheiro-de-ninho-of patch-left-and-ahead horizonte-olfactivo 1
  set cheiro-frente cheiro-de-ninho-of patch-ahead 1
  set cheiro-direita cheiro-de-ninho-of patch-right-and-ahead horizonte-olfactivo 1
  if (cheiro-direita > cheiro-frente) or (cheiro-esquerda > cheiro-frente)
  [ ifelse cheiro-direita > cheiro-esquerda
    [ rt horizonte-olfactivo ]
    [ lt horizonte-olfactivo ] ]
end

Neste procedimento é implementado o algorítmo de procura do ninho por parte das formigas no regresso ao formigueiro. Estas linhas são chamadas na função Regressar-ao-ninho quando as formigas possuídoras de comida ainda não se encontram em patches pertencentes ao ninho. O seu objectivo consiste em rodar a formiga para a direcção com maior quantidade de cheiro-de-ninho.

A função começa por declarar 3 variáveis locais onde ficarão registadas as quantidades de cheiro a ninho nas direcções frente, esquerda e direita. Depois de assegurar as condições fronteira estabelecidas neste modelo (Universo-Finito), atribui-se às 3 variáveis locais o valor de cheiro dos patches nas 3 direcções analisadas. Por exemplo, na direcção esquerda, a variável cheiro-esquerda, toma o valor do cheiro-de-ninho do patch definido pela rotação à esquerda de um ângulo igual ao horizonte olfactivo.

Se cheiro-frente for maior que as restantes variáveis, nada acontece, caso contrário, a formiga optará por rodar um ângulo igual ao horizonte-olfactivo, para o lado onde existir mais cheiro a ninho.


Análise do código
3. Universo-Finito
to Universo-Finito
  if abs xcor > screen-edge-x - 1
  [ set heading towardsxy-nowrap 0 ycor ]
  if abs ycor > screen-edge-y - 1
  [ set heading towardsxy-nowrap xcor 0 ]
end

towardsxy-nowrap x y Retorna a orientação do agente de modo a que este fique direccionado para o ponto de coordenadas (x,y).

Esta função trata de proceder à limitação do universo das formigas. Se uma formiga possuir o módulo da coordenada x maior que o screenedge-x - 1, então a formiga passa a apontar para o patch de coordenada (0,y_original). Na prática, estamos a provocar uma reflexão do movimento das formigas quando estas atingem os patches fronteira.


Análise do código
4. Depositar-Comida
to Depositar-Comida
  locals [ mx my ]
  set mx round mouse-xcor
  set my round mouse-ycor
  if mouse-down?
  [ set lista-x lput mx lista-x  ;;pega na lista inicial e devolve a lista inicial com o novo elemento
    set lista-y lput my lista-y  ;; ""
    ifelse forma-da-migalha = "regular"
    [ Depositar-Migalha-Regular mx + 0.75 my + 0.75
      set lista-tipo lput 1 lista-tipo ]
    [ Depositar-Migalha-Aleatoria mx + 0.75 my + 0.75
      set lista-tipo lput -1 lista-tipo ]
    ask patches with [ distancexy-nowrap mx my <= tamanho-migalha ]
    [ if cor-migalha = "amarela"
      [ set cor yellow ]
      if cor-migalha = "vermelha"
      [ set cor red ]
      if cor-migalha = "verde"
      [ set cor lime ]
      if cor-migalha = "azul"
      [ set cor cyan ] ]
    ask random-one-of patches with [ distancexy-nowrap mx my <= tamanho-migalha ]
    [ set lista-tipo replace-item (length lista-tipo - 1) lista-tipo (last lista-tipo * cor) ]
    ask patches
    [ Actualizar-Patches ]
    stop ]
end

A esta função está associado o botão "Depositar comida". Analisa a posição do cursor do rato, depositando uma migalha nessa posição no caso do utilizador pressionar o botão esquerdo. Para acrescentar comida aos patches, recorre às funções Depositar-Migalha-Regular e Depositar-Migalha-Aleatoria, de acordo com a escolha do utilizador.

Esta função é responsável pelo registo nas listas anteriormente declaradas, da posição de cada migalha que deposita, sendo esta informação posteriormente utilizada pela função Repor para reconstruir as condições iniciais de uma simulação realizada anteriormente.


Análise do código
4.1. Depositar-Migalha-Regular
to Depositar-Migalha-Regular [ x y ]
  ask patches with [ distancexy-nowrap x y <= tamanho-migalha ]
  [ set comida comida + 10 * (tamanho-migalha - distancexy-nowrap x y) ]
  ask Patch-Fronteira
  [ set comida 0 ]
end

Para todos os patches localizados a uma distância tamanho-migalha do ponto (x,y), soma-se ao campo comida um valor não nulo de comida. Esse valor vai ser tanto maior quanto menor for a distância ao centro.


Análise do código
4.2. Depositar-Migalha-Aleatoria
to Depositar-Migalha-Aleatoria [ x y ]
  locals [ comida-total migalha ]
  set comida-total tamanho-migalha * tamanho-migalha
  while [ comida-total > 0 ]
  [ ask patches with [ distancexy-nowrap x y <= tamanho-migalha ]
    [ without-interruption
      [ set migalha 1 + random-float comida-total
        set comida comida + migalha
        set comida-total comida-total - migalha ] ] ]
  ask Patch-Fronteira
  [ set comida 0 ]
end

Tal como em Depositar-Migalha-Regular, esta função recebe como input as coordenadas de um patch. Define-se uma variável local comida-total que possui a quantidade total de comida a depositar nesta migalha. Esta vai ser igual ao quadrado do raio da migalha. Para proceder à distribuição aleatória da comida no espaço circular definido pela variável tamanho-da-migalha e centrado nas coordenadas x e y, utilizou-se um ciclo while onde, até a comida depositada ser inferior à comida-total, escolhe-se um patch aleatoriamente e acrescenta-se ao campo comida um número aleatorio entre 1 e comida-total.


Análise do código
5. repor
to repor
  locals [ mcor ]
  clear-all-plots
  clear-graphics
  set tempo 0
  set horizonte-olfactivo 45
  set tamanho-migalha 3
  set quantidade-inicial-feromonas 40
  Preparar-Formigas
  Preparar-Patches
  ( foreach lista-tipo lista-x lista-y
    [ ifelse ?1 > 0
      [ Depositar-Migalha-Regular ?2 + 0.75 ?3 + 0.75
        set mcor ?1 ]
      [ Depositar-Migalha-Aleatoria ?2 + 0.75 ?3 + 0.75
        set mcor -1 * ?1 ]
      ask patches with [ distancexy-nowrap ?2 ?3 <= tamanho-migalha ]
      [ set cor mcor ] ] )
  ask patches
  [ Actualizar-Patches ]
  do-plotting

Esta função auxiliar está associada ao botão "repor", sendo utilizada para repôr a disposição inicial das migalhas depois de se proceder a uma simulação. Na prática funciona exactamente como a função Preparar, mas, além de proceder à inicialização de variáveis, patches e formigas, é responsável pela deposição de comida. Para tal, recorre às listas declaradas anteriormente, e, através delas, recoloca as migalhas na posição da última simulação. O uso das listas consiste num dos temas abordados na secção Tópicos avançados, e sai fora do algorítmo principal apresentado neste módulo.


Análise do código
6. do-plotting
to do-plotting
  if not plot?
  [ stop ]
  set-current-plot "Comida Disponivel"
  set-current-plot-pen "comida amarela"
  set c-c 0
  ask patches with [ pcolor = yellow ]
  [ without-interruption
    [ set c-c c-c + comida ] ]
  plot c-c
  set-current-plot-pen "comida vermelha"
  set c-c 0
  ask patches with [ pcolor = red ]
  [ without-interruption
    [ set c-c c-c + comida ] ]
  plot c-c
  set-current-plot-pen "comida verde"
  set c-c 0
  ask patches with [ pcolor = lime ]
  [ without-interruption
    [ set c-c c-c + comida ] ]
  plot c-c
  set-current-plot-pen "comida azul"
  set c-c 0
  ask patches with [ pcolor = cyan ]
  [ without-interruption
    [ set c-c c-c + comida ] ]
  plot c-c
end

Esta função auxiliar é responsável pela actualização do gráfico da quantidade de comida presente no tabuleiro de simulação. Para uma determinada cor, regista-se na variável c-c a soma de toda comida dessa cor. Depois dessa contabilização, basta registar o resultado no gráfico "Comida Disponível" com a cor conveniente. Este procedimento é repetido para todas as cores em cada uma das iterações.


Análise do código
Início

Variantes e extensões

1. Consegue estabelecer relações ou interdependências entre os diferentes parâmetros disponibilizados no interface de simulação, nomeadamente, taxas de evaporação e de difusão de feromonas, número de formigas e nível de inteligência?

2. Que espera que aconteça quando modifica o horizonte olfactivo de uma formiga ? Experimente.

3. E no que concerne à identificação do ninho? Consegue imaginar outros critérios que possam ser usados alternativamente?

Tópico avançado:

4. Modifique o programa original por forma a permitir que a concentração de (por exemplo) glucose na comida varie. Em conformidade, faça com que a formiga deposite feromonas proporcionalmente à concentração de glucose da comida que encontrar. Se repetir as simulações com esta nova versão, verificará que as formigas conseguem detectar qual das fontes de comida tem maior concentração, o que contradiz a evidência empírica dobre as formigas em geral e sobre a Lasius Niger em particular (a formiga negra dos jardins) que não conseguem efectuar tal distinção. Assim sendo, qual dos argumentos acima está errado? Consegue transformar estas super-formigas em formigas normais?

Início