Exercício Programa 10: Modelos baseados em agentes

Introdução

Um modelo baseado em agentes (agent-based model) é uma classe de modelos computacionais para simulação de ações e iterações de agentes autônomos (indivíduos ou entidades coletivas como organizações e grupos) com a intenção de estimar o seu efeito no sistema como um todo. Ele combina elementos de teoria so jogos (game theory), sistema complexos (complex systems), emergência (emergence), sociologia computacional (computacional sociology), sistemas de agentes mútiplos (multi-agent system) e programação evolucionária (evolutionary programming).

O modelamento baseado em agentes é uma ferramenta computacional bastante poderosa para investigar certos fenômenos dinâmicos. Um dos primeiros modelos foi proposto por Thomas Schelling em 1971 em seu trabalho Dynamics Models of Segregation. O seu objetivo era demonstrar possíveis causas de segregação [1] racial em cidades americanas. Em seu modelo, uma cidade é representada por uma matriz retangular (nesse exercício consideraremos matrizes quadradas), onde cada elemento da matriz é uma casa. Uma casa pode ser ocupada por um agente vermelho ou azul, ou ficar vazia. O número de agentes vermelhos é aproximadamente o mesmo de azuis, com uma certa porcentagem de casas vazias.

A cada instante da simulação, um agente pode estar feliz ou infeliz com relação aos seus vizinhos e, caso infeliz, ele se muda para uma casa vazia qualquer. Cada casa pode ter até 8 vizinhos.

Vamos considerar que um agente está feliz se possui ao menos 2 vizinhos como ele. Caso ele esteja feliz nada acontece. Caso haja 1 ou zero vizinhos como ele, o agente fica infeliz. Um agente infeliz tenta mudar para uma outra casa.

O que você deve fazer (entrega dia 13/11)

Antes de mais nada, instale o NumPy seguindo o link que está na página arrays do Guia interativo de estudos. c Escreva um programa em Python que permita observar a evolução desse processo.

Inicialmente o seu programa deve ler do teclado os seguintes valores inteiros:

  • o valor da semente a ser utilizada para o gerador de números pseudo-aleatórios;
  • a dimensão n da cidade que será representada por um array (= objeto da classe numpy.ndarray) quadrado de dimensão n x n;
  • a porcentagem de agentes azuis;
  • a porcentagem de agentes vermelhos;
  • o número mínimo de vizinhos que deixa um agente feliz.

A soma das porcentagens de agentes azuis e vermelhos deve ser sempre menor que 100, para permitir a existência de casas vazias. Por exemplo, quando a porcentagem de azuis é 45 e a de vermelhos é 35, o restante 20% é de casas vazias.

A partir dessas informações, o seu programa deve sortear uma certa distribuição de casas na cidade, que define a condição inicial, utilizando para isso a função sorteia_cidade() fornecida abaixo:

import numpy as np

def sorteia_cidade(s, a, v):
    ''' (int, int, int) -> array

    Recebe um inteiro s com o tamanho do mapa (s x s) e a
    porcentagem de agentes azuis (a) e vermelhos (v)
    e retorna um mapa respeitando a distribuição fornecida
    '''

    # cria um array com números pseudo-aleatórios
    M = np.random.randint(100, size=(s,s))
    vazio = M >= v+a
    verm = (M >= a) & (M < v+a)
    azul = M < a

    M[vazio] = VAZIO
    M[azul]  = AZUL
    M[verm]  = VERMELHO

    # cria borda com zeros
    M[:,0] = M[0,:] = M[-1,:] = M[:,-1] = BORDA

    return M

A seguir, o seu programa deve executar iterações da simulação até que o usuário digite a palavra fim.

A cada iteração da simulação, o seu programa deve primeiro identificar todos os agentes infelizes. A seguir, cada um desses agentes se move, aleatoriamente para uma casa vazia. Ao se mudar, sua própria casa fica vazia e disponível para o sorteio do próximo agente insatisfeito.

Veja o exemplo de execução abaixo. Implemente o seu programa de tal forma que tenha exatamente o mesmo comportamento do exemplo abaixo.

Bem vindo ao simulador do modelo de segregação de Schelling

Digite a semente para o gerador de números pseudo-aleatórios: 5
Digite a dimensão n da cidade: 5
Digite a porcentagem da população azul: 40
Digite a porcentagem da população vermelha: 40
Digite o número mínimo de vizinhos desejado: 2

Configuração Inicial
[[-1 -1 -1 -1 -1 -1 -1]
 [-1  1  0  1  2  1 -1]
 [-1  1  2  2  2  2 -1]
 [-1  0  0  1  1  2 -1]
 [-1  0  1  2  1  2 -1]
 [-1  1  1  2  1  1 -1]
 [-1 -1 -1 -1 -1 -1 -1]]

 8 querem mudar:
 [[-1 -1 -1 -1 -1 -1 -1]
  [-1  1  0  1  0  1 -1]
  [-1  1  1  0  0  0 -1]
  [-1  0  0  0  0  0 -1]
  [-1  0  0  1  0  1 -1]
  [-1  0  0  1  0  0 -1]
  [-1 -1 -1 -1 -1 -1 -1]]

  Mudaram de casa:   4 da cor azul
  Mudaram de casa:   4 da cor vermelha
  Estado após 1 iterações
  [[-1 -1 -1 -1 -1 -1 -1]
   [-1  2  0  2  2  1 -1]
   [-1  0  0  2  2  2 -1]
   [-1  1  1  1  1  2 -1]
   [-1  1  1  2  1  2 -1]
   [-1  1  1  0  1  1 -1]
   [-1 -1 -1 -1 -1 -1 -1]]

  Digite fim para terminar, ou enter para mais uma iteração:

  4 querem mudar:
  [[-1 -1 -1 -1 -1 -1 -1]
   [-1  1  0  0  0  1 -1]
   [-1  0  0  0  0  0 -1]
   [-1  0  0  0  0  0 -1]
   [-1  0  0  1  0  1 -1]
   [-1  0  0  0  0  0 -1]
   [-1 -1 -1 -1 -1 -1 -1]]

  Mudaram de casa:   1 da cor azul
  Mudaram de casa:   3 da cor vermelha
  Estado após 2 iterações
  [[-1 -1 -1 -1 -1 -1 -1]
   [-1  0  2  2  2  0 -1]
   [-1  1  2  2  2  2 -1]
   [-1  1  1  1  1  2 -1]
   [-1  1  1  0  1  0 -1]
   [-1  1  1  2  1  1 -1]
   [-1 -1 -1 -1 -1 -1 -1]]

   Digite fim para terminar, ou enter para mais uma iteração:

   1 querem mudar:
   [[-1 -1 -1 -1 -1 -1 -1]
    [-1  0  0  0  0  0 -1]
    [-1  0  0  0  0  0 -1]
    [-1  0  0  0  0  0 -1]
    [-1  0  0  0  0  0 -1]
    [-1  0  0  1  0  0 -1]
    [-1 -1 -1 -1 -1 -1 -1]]

   Mudaram de casa:   0 da cor azul
   Mudaram de casa:   1 da cor vermelha
   Estado após 3 iterações
   [[-1 -1 -1 -1 -1 -1 -1]
    [-1  0  2  2  2  2 -1]
    [-1  1  2  2  2  2 -1]
    [-1  1  1  1  1  2 -1]
    [-1  1  1  0  1  0 -1]
    [-1  1  1  0  1  1 -1]
    [-1 -1 -1 -1 -1 -1 -1]]

   Digite fim para terminar, ou enter para mais uma iteração:

   0 querem mudar:
   [[-1 -1 -1 -1 -1 -1 -1]
    [-1  0  0  0  0  0 -1]
    [-1  0  0  0  0  0 -1]
    [-1  0  0  0  0  0 -1]
    [-1  0  0  0  0  0 -1]
    [-1  0  0  0  0  0 -1]
    [-1 -1 -1 -1 -1 -1 -1]]

   Mudaram de casa:   0 da cor azul
   Mudaram de casa:   0 da cor vermelha
   Estado após 4 iterações
   [[-1 -1 -1 -1 -1 -1 -1]
    [-1  0  2  2  2  2 -1]
    [-1  1  2  2  2  2 -1]
    [-1  1  1  1  1  2 -1]
    [-1  1  1  0  1  0 -1]
    [-1  1  1  0  1  1 -1]
    [-1 -1 -1 -1 -1 -1 -1]]

   Digite fim para terminar, ou enter para mais uma iteração: fim

Dicas e Detalhes

. Não deixe o EP para a última hora

. Siga as Instruções para entrega de EPs

. Para saber mais sobre números pseudo-aleatórios usando NumPy, visite a documentação

disponível em http://docs.scipy.org/doc/numpy/reference/routines.random.html

. Coloque as suas dúvidas no fórum de discussão da disciplina.

. Venha tirar as dúvidas nos plantões.

Footnotes

[1]Forma de dissociação que se realiza quando unidades similares, obedecendo ao mesmo impulso, se concentram, distanciando-se, ao mesmo tempo, de outras unidades consideradas diferentes ou divergentes. Essa separação ou distância social e física é oriunda de fatores biológicos e sociais: raça, riqueza, educação, religião, profissão, nacionalidade.