sábado, 27 de junho de 2015

Autômatos Celulares Não Determinísticos (projeto 9)

Utilizando o Modelo de Ising, simular a evolução de sistemas com dimensões mínimas de 300 x 300 ao longo de 400 gerações considerando configurações iniciais aleatórias e beta inicial = 0.
Em cada um dos três casos a seguir, a variável beta deve ser incrementada em cada geração de:

  • a) beta = 0.0001
  • b) beta = 0.0008
  • c) beta = 0.002
O que acontece em cada caso? Gere animações do processo de modo a ilustrar a dinâmica da evolução através de imagens do processo. Plote a configuração final obtida em cada caso.
Deve ser computada a entropia do sistema H(t) em cada geração e plotado um gráfico que expressa a variação de H(t) no tempo (gerações). 

H(t) = - [p0*log(p0) + p1*log(p1)] 

p0 = h0/N e p1 = h1/N, sendo h0 e h1 as componentes do histograma (números de 0's e 1's na configuração atual), e N a área do sistema (300*300)



Programa e sua execução para os 3 casos:

(clique na imagem para ampliá-la)

 Observação: infelizmente não foi possível transferir a animação para o blog, então estou colocando a imagem final da animação para os 3 casos.
 
Figura 1: primeira parte dos códigos

Figura 2: segunda e última parte dos códigos

Figura 3: Executando o programa para acréscimo de Beta = 0.0001

Figura 4: Gráfico de entropia das gerações para o acréscimo 0.0001
Figura 5: Último frame da animação das gerações com acréscimo de 0.0001 em Beta

Figura 6: Entropia das gerações, sob acréscimo de 0.0008

Figura 7: Último quadro da animação da simulação com acréscimo de 0.0008

Figura 8: Entropia sob acréscimo de 0.002
Figura 9: Final da animação da simulação sob acréscimo em Beta de 0.002 a cada geração


Podemos observar que conforme o valor de Beta aumenta, certa "organização" vai aparecendo e o "caos" torna-se pequeno, as células agrupam-se com maior facilidade, porque beta representa a "importância" que se dá à vizinhança de uma célula para calcular seu futuro estado. Por se tratar de um modelo não determinístico, toda vez que o programa for executado novamente (inclusive com mesmo valor de acréscimo) uma animação e gráfico diferentes serão gerados.

 Código para ser copiado:

#importando bibliotecas necessárias ao programa
import numpy as np
import math as math
import matplotlib.pyplot as plt
import matplotlib.animation as animation

MAX = 400 #número de gerações
SIZE = 300 #dimensões do sistema
beta = 0 #beta inicial
#pedir ao usuário o valor de quanto beta cresce em cada geração
crescimento_beta = float(input('Quanto Beta deve crescer a cada geração?( 0.0001; 0.0008; 0.002 ) '))

geracao = np.random.randint(0, 2, (SIZE,SIZE)) #gerando matriz inicial com 0's ou 1's aleatórios
nova_geracao = np.zeros((SIZE, SIZE)) #matriz onde será armazenada a proxima geração, preenchida com zeros
matriz_evolucao = np.zeros((SIZE, SIZE, MAX)) #matriz 3D onde será gravado todo o processo
entropia = [] #lista vazia onde será armazenado o valor da entropia em cada geração

# laço principal, criará todas as gerações
for k in range(MAX):

      print("Processando geração %d..." %k)#mostra a geração em processo
      matriz_evolucao[:,:,k] = geracao #k-ésima geração será feita
     
      for i in range(1, SIZE-1): #desconsidera as bordas da matriz, p/ que exista vizinhança das células nas extremidades
            for j in range(1, SIZE-1): #confere as 8 células vizinhas a uma célula central

                  # seleciona janela 3X3 (vizinhança: 1 central com 8 ao seu redor)
                  bloco = geracao[i-1:i+2, j-1:j+2]

                  # soma elementos da janela para verificar o nº de 0s e 1s ao redor da célula
                  numero_ums = sum(sum(bloco)) - geracao[i,j]#subtrai o elemento central(queremos apenas a vizinhança dele)
                  numero_zeros = 8 - numero_ums #obtendo o nº de zeros nessa vizinhança

                  #probabilidade que usa a vizinhança (ou não se beta=0) para definir se a célula em questão se tornará 0 ou 1
                  p = np.exp(beta*numero_zeros)/(np.exp(beta*numero_zeros)+np.exp(beta*numero_ums))

                  # X é nº aleatório entre 0 e 1
                  x = np.random.random()

                  # aplicar decisão, com auxilio da probabilidade e do X
                  if x<=p:
                        nova_geracao[i,j] = 0
                  else:
                        nova_geracao[i,j] = 1
      geracao = nova_geracao.copy() #após calculada a nova geração, ela passa a ser a atual
      beta = beta + crescimento_beta #atualização do beta

      #cálculo da entropia do sistema
      p1 = (np.sum(nova_geracao[:,:]))/(SIZE*SIZE) #proporção de células em estado 1, na geração atual, ou seja,
                                                    #soma todas os valores da matriz e divide pelo seu tamanho
      p0 = 1 - p1 #proporção de células em estado 0, na atual geração
      h = -( p0*(np.log10(p0)) + p1*(np.log10(p1)) ) #valor da entropia nessa geração
      entropia.append(h) #acrescentando a entropia atual na lista das entropias
     
     

# gerando animação
fig = plt.figure(1)
lista = [] #lista vazia que conterá os frames da animação
for i in range(MAX):
      im = plt.imshow(matriz_evolucao[:,:,i], cmap='gray')#cada frame da animação representa uma geração
      lista.append([im]) #acrescenta o novo frame a lista
anime = animation.ArtistAnimation(fig, lista, interval=50, blit=True, repeat_delay=1000)
plt.show()

    
#gerando o gráfico dos valores da entropia em cada geração
plt.plot(entropia)
plt.show()
  
#fim


Nenhum comentário:

Postar um comentário