MBA: Caminhante aleatório

De Física Computacional
Revisão de 20h18min de 20 de julho de 2022 por Jhordan (discussão | contribs) (Criou página com '{{Ecologia| Por que usar e o que são modelos baseados em indivíduos |Contexto}} = Caminhante aleatório = O problema do caminhante aleatório pode ser definido da se...')
(dif) ← Edição anterior | Revisão atual (dif) | Versão posterior → (dif)
Ir para navegação Ir para pesquisar

Anterior: Por que usar e o que são modelos baseados em indivíduos | Índice: Ecologia | Próximo: Contexto

Caminhante aleatório

O problema do caminhante aleatório pode ser definido da seguinte forma: Um homem começa de um ponto 0 e caminha 1 metro em uma linha reta, então ele vira um ângulo qualquer e anda outro 1 metro em uma linha reta. Ele repete esse processo n vezes, qual é a probabilidade de após estes N passos que o homem esteja a uma distância entre r e r+δr da origem.

Inspirado por este problema, propõe-se uma situação bidimensional similar. A principal diferença constitui-se no fato de que o ângulo não é mais aleatório. Reescrevendo o problema, agora em cada um dos eixos, nos quais o homem se move de maneira independe, há uma probabilidade p de se mover 1 metro em um sentido e uma probabilidade q=1p de se mover no sentido contrário.

Trabalhando inicialmente apenas com uma dimensão, executando N passos, um caminho possível para o homem terminar a simulação em uma posição m=n1n2 tendo dado n1 passos à direita e n2 passos à esquerda, é dado por:

pn1qn2=pN+m2qNm2Pois sendo N=n1+n2 podemo escrever: n1=N+m2,n2=Nm2Porém, está é a probabilidade de obtermos apenas um dos caminhos que leva o homem a m. O número total de caminhos indistinguíveis com n1 passos à direita e n2 passos a esquerda é dado por: N!n1!n2!=N!n1!(Nn1)!=N!(N+m2)!(Nm2)! Temos então que a probabilidade estar na posição m após N passos é dado por: p(m,N)=N!(N+m2)!(Nm2)!pN+m2qNm2 Ou reescrevendo n1=n para facilitar, e lembrando que n1=N+m2 e N=n1+n2: p(n)=N!n!(Nn)!pnqNn=(Nn)pnqNn Onde (Nn)=CnN também é chamado de combinatória. Utilizando o binômio de Newton: (x+y)n=k=0n(nk)xnkykTemos a normalização: n=0np(n)=n=0n(Nn)qNnpn=(p+q)N=1Uma vez que p+q=1. E lembrando que p(n) é a probabilidade de estar em m=2nN, ou seja de obtermos n vezes passo a direita em N passos no total, então o valor médio de n pode ser dado por: n=n=0Nnp(n)Derivando o binômio de Newton: pddp(p+q)N=pN(p+q)N1=pNE também: pddp(p+q)N=pddp[n=0n(Nn)qNnpn]=pn=0nn(Nn)qNnpn1=n=0nn(Nn)qNnpn=n=0nnp(n)Então: pN=n=0nnp(n)=nE com isso podemos obter a posição final média m. Utilizando a notação anterior posição final exata é m=n1n2, ou ainda podemos rescrever como m=2nN, pois: n1n2=n1(Nn1)=2n1N A partir destes resultados podemos obter: m=n=0Nmp(n)=n=0N(2nN)p(n)=2n=0Nnp(n)n=0NNp(n)=2nNn=0Np(n)=2nN A princípio, não temos motivos para dar preferência para o movimento em nenhuma direção, logo é razoável utilizar p=q=1/2, o que resulta em n=N/2 consequentemente m=0. O que pode parecer contra-intuitivo para nosso modelo, mas além de distribuirmos animais por todo o espaço, o que resultado implica é a posição final média, mas é preciso entender que não impede que ao longo da simulação cada indivíduo percorra diferentes áreas do espaço.


Distribuição Gaussiana

Quando N tendo p≉1 temos a distribuição Gaussiana: p(n)=(Nn)pnqNn12πNpqexp((nNp)22Npq)


Foi realizada uma simulação utilizando Python e o módulo Mesa, grande parte do código segue a mesma discussão feita anteriormente no Jogo da Vida. A figura ilustra uma simulação com 10.000 caminhantes aleatórios em uma grade 100 X 100, iniciando na posição P=(50,50).

Resultado da simulação com a distribuição gaussiana sobreposta para N=100 para ambas as coordenadas.


Código

#Bibliotecas necessárias
from mesa import Agent, Model                                      #Classes Agente e Modelo
from mesa.time import SimultaneousActivation                       #Agendador simultâneo
from mesa.space import MultiGrid                                   #Malha multigrid
import random                                                      #Número aleatórios

#AGENTE---------------------------------------------------------------------------------
class Agente(Agent):
    """Classe do agente"""
    def __init__(self,modelo):
      """Bibliotecas necessárias"""
      #modelo     - Modelo que ao qual o agente pertence
      super().__init__(self,modelo)             #Necessário para funcionar o modelo
      self.ppos=(0,0)
      
    def step(self):
      """Método obrigatório que prepara as mudanças"""
      dx = (+1) if (random.random()<0.5) else(-1)
      dy = (+1) if (random.random()<0.5) else (-1)
      self.ppos = (self.pos[0]+dx,self.pos[1]+dy)                                 #Próxima posição
          
    def advance(self):
        """Método obrigatório que aplica as mudanças"""
        self.model.grid.move_agent(self, self.ppos)

#MODELO
class Modelo(Model):
    """Modelo geral"""

    def __init__(self, modelo,N,seed=None):
        """Função chamada quando o modelo é inicializazdo"""
        # Modelo   - Dicionário com especificações do modelo
        # N        - Quantiade de caminhantes
        # seed     - Seed dos números aleatórios do modelo do mesa
        
        largura = modelo["Largura"];altura=modelo["Altura"];seed_random=modelo["Seed"]
        random.seed(seed_random)                                 #Seed dos números aleatórios
        self.grid     = MultiGrid(largura, altura, True)         #Configura a grade
        self.schedule = SimultaneousActivation(self)             #Configura o agendador
        self.running  = True                                     #Condiçao para seguir executando o modelo
        for n in range(N):
          a = Agente(self)
          self.schedule.add(a)
          X= 50
          Y= 50
          self.grid.place_agent(a, (X, Y))
            
    def step(self):
        """Avançar um passo do modelo"""
        self.schedule.step()                              #Avançamos os agentes


MAX =100
N=10000
modelo  = {"Largura":100   ,"Altura":100       ,"Seed":0} 
M = Modelo(modelo,N)
for i in range(MAX):
    M.step()
    if ((i+1)%(MAX/100)==0):
      print(str(100*(1+i)/MAX)+"%")

E o gráfico foi gerado utilizando:

import numpy as np
import matplotlib.pyplot as plt


x=[];y=[]
for a in M.schedule.agents:
  x.append(a.pos[0])
  y.append(a.pos[1])

a,b,c=plt.hist(x, 70, density=True, facecolor='g', alpha=0.75)
m=1
K=100
X=np.arange(0,100, 0.1)
sigma = 2*np.pi*K*0.5*0.5
plt.plot(X,np.exp(-((X-K*0.5)**2)/sigma)/(np.sqrt(sigma)))

Acima fazendos um histograma das posições em x, uma alteração simples permite visualizarmos o equivalente em y.

Principais materiais utilizados:


Anterior: Por que usar e o que são modelos baseados em indivíduos | Índice: Ecologia | Próximo: Contexto