Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Como implementar o Segregation Model em Python?

+2 votos
14 visitas
perguntada Out 15 em Ciência da Computação por Gustavo Medeiros (36 pontos)  

Considere os modelos baseados em agentes apresentados no capítulo 3 do livro "An Introduction to Agent-Based Modeling: Modeling Natural, Social, and Engineered Complex Systems with NetLogo - Wilensky, Uri; Rand, William (2015)". Implemente em Python, possivelmente usando a biblioteca Mesa. Explique/Descreva o modelo, explique cuidadosamente o código que você desenvolveu em Python, replique todas as tabelas e figuras apresentadas para cada um dos modelos apresentados.
c) Segregation Model

Compartilhe

1 Resposta

0 votos
respondida Out 16 por Gustavo Medeiros (36 pontos)  
editado Out 18 por Gustavo Medeiros

Schelling, em seus estudos sobre a natureza da segregação, desenvolveu um modelo de agrupamento de vizinhança. Ele se perguntou o que aconteceria se assumíssemos que todos os indivíduos querem viver em bairros onde uma parte considerável dos seus vizinhos fossem semelhantes a si mesmo, ou seja, os indivíduos teriam aversão a serem minorias. Note que a resistência existe em ser minoria, e não à integração entre etnias distintas\(^1\).

Schelling explorou o problema usando um tabuleiro de damas como plataforma e colocou, aleatoriamente no tabuleiro, moedas diferentes para representar etnias diferentes (\(\textit pennies\) e \(\textit dimes\)). Então, manualmente, ele contou o número de \(\textit pennies\) que cercavam um \(\textit dime\) e dividiu esse numero pelo total de moedas que estavam ao redor desse \(\textit dime\) especifico. Se essa proporção excedesse determinado valor, ele moveria o \(\textit dime\) para um lugar vazio até ocorrer a situação em que o \(\textit dime\) não fosse uma minoria na sua vizinhança. O processo foi repetido inúmeras vezes até chegar ao resultado final, onde foi constatado um tabuleiro segregado em áreas de somente \(\textit pennies\) e áreas de somente \(\textit dimes\). Esse resultado se dava não por vontade individual, mas sim por comportamento dos agentes como grupo. Schelling descreveu o fenômeno como macro comportamento derivado de micro motivos\(^2\).

O modelo original previa somente dois tipos de pessoas diferentes e preferências homogêneas. Existem algumas extensões do modelo no qual mais etnias são incluídas ou os agentes passam a ser heterogêneos, possuindo tolerâncias diferentes em relação a ser minoria.

O modelo de segregação descrito é um exemplo de modelagem habitacional, que é fundamental para modelagens urbanas. Tais modelos podem ser combinados com outros modelos de urbanização (como industrial e comercial) para criar um modelo integrado de cidade. Por exemplo, a política de moradias implementada em Cingapura pelo 1\(^o\) Ministro Lee Hsien Loong (ex-aluno de Schelling em Havard) que tinha como objetivo a integração étnica foi inspirada pelo trabalho de Schellin\( ^3\).

Como podemos implementar o modelo em Python?

O modelo consiste em agente espalhados em um plano quadriculado, onde cada quadrado pode conter somente um agente. Iremos dividir os agentes em azul e vermelho. Eles ficarão satisfeitos se \(x\) dos seus oitos vizinhos possíveis forem de sua cor, e insatisfeitos caso contrário. Quando um agente está insatisfeito ele vai procurar aleatoriamente um quadrado desocupado até que esteja finalmente feliz. O modelo irá rodar até que todos os agentes estejam satisfeitos/felizes.

Vamos começar importando as bibliotecas que serão usadas e criando o Agente do modelo

from mesa import Model, Agent
from mesa.time import RandomActivation
from mesa.space import SingleGrid
from mesa.datacollection import DataCollector


class SchellingAgent(Agent):
# Iniciando
def __init__(self, pos, model, agent_type):
    super().__init__(pos, model)
    self.pos = pos
    self.type = agent_type

# Definindo o Step/turno
def step(self):
    similar = 0
    #  Calculo de vizinhos similares
    for neighbor in self.model.grid.neighbor_iter(self.pos):
        if neighbor.type == self.type:
            similar += 1

    #  Mover para espaço vazio se esiver infeliz
    if similar < self.model.homophily:
        self.model.grid.move_to_empty(self)
    else:
        self.model.happy += 1

O código acima cria o Agente, define uma função \( \textit step \) que seria o turno do modelo onde o agente verifica o número de semelhantes na vizinhança e, caso esteja infeliz, muda para um local vazio.

Em seguida, ainda no mesmo arquivo, vamos definir o modelo propriamente dito.

class Schelling(Model):
"""
Model class for the Schelling segregation model.
"""

def __init__(self, height=20, width=20, density=0.8, minority_pc=0.5, homophily=3):
    """
    """

    self.height = height
    self.width = width
    self.density = density
    self.minority_pc = minority_pc
    self.homophily = homophily


        self.schedule = RandomActivation(self)
    self.grid = SingleGrid(width, height, torus=True)

    self.happy = 0
    self.datacollector = DataCollector(
        {"happy": "happy"},  # Contagem
        # Utilizando x e y para teste
        {"x": lambda a: a.pos[0], "y": lambda a: a.pos[1]},
    )

        for cell in self.grid.coord_iter():
        x = cell[1]
        y = cell[2]
        if self.random.random() < self.density:
            if self.random.random() < self.minority_pc:
                agent_type = 1
            else:
                agent_type = 0

            agent = SchellingAgent((x, y), self, agent_type)
            self.grid.position_agent(agent, (x, y))
            self.schedule.add(agent)

    self.running = True
    self.datacollector.collect(self)

Widht e Height definem o tamanho do plano quadriculado, Density varia entre 0 e 1 para determinar a densidade populacional no sistema, ou seja, a porcentagem do plano que será ocupada por agentes. Fraction minority é a fração entre azul e vermelho. Se for abaixo de 0.5, vermelho será maioria total, acima de 0.5 azul é a maioria. Se for igual a 0.5 a quantidade de azul e vermelho é igual. Homophily determina quantos vizinhos iguais são necessários para que o agente fique satisfeito. Varia de 0 a 8.

Para o plano quadriculado e ordenação de movimento dos agente, usamos o SingleGrid e o RandomActivation. Para coletar informação após cada \( \textit step \) da simulação e verificar a condição de felicidade do agente usamos DataCollector. Depois temos a configuração da interação do agente com o \( \textit grid\).

Agora a última parte do código do modelo, ainda na classe Schelling. \( \textit Step\) define cada turno do modelo. Reseta a contagem de agentes felizes, conta novamente e para o modelo assim que todos os agente estão felizes.

def step(self):
    """
   Roda um turno do modelo. Se todos estiverem felizes, para de rodar
    """
    self.happy = 0  # Reset counter of happy agents
    self.schedule.step()
    # Coletar dados
    self.datacollector.collect(self)

    if self.happy == self.schedule.get_agent_count():
        self.running = False

Todos esses códigos acima representam o arquivo model.py. Vamos criar agora outro arquivo, chamado server.py. O arquivo server.py, por sua vez, define como exibir a simulação de forma dinâmica através de elementos gráficos em um arquivo HTML, além de permitir, pelo próprio navegador, ajustar alguns parâmetros do modelo. Segue o código do arquivo server.py

from mesa.visualization.ModularVisualization import ModularServer
from mesa.visualization.modules import CanvasGrid, ChartModule, TextElement
from mesa.visualization.UserParam import UserSettableParameter                                               
from model import Schelling

class HappyElement(TextElement):
"""
Mostrar quantos agentes estão felizes.
"""

def __init__(self):
    pass

def render(self, model):
    return "Happy agents: " + str(model.happy)

def schelling_draw(agent):
"""
Chamando canvas
"""
if agent is None:
    return
portrayal = {"Shape": "circle", "r": 0.5, "Filled": "true", "Layer": 0}

if agent.type == 0:
    portrayal["Color"] = ["#FF0000", "#FF9999"]
    portrayal["stroke_color"] = "#00FF00"
else:
    portrayal["Color"] = ["#0000FF", "#9999FF"]
    portrayal["stroke_color"] = "#000000"
return portrayal

happy_element = HappyElement()
canvas_element = CanvasGrid(schelling_draw, 20, 20, 500, 500)
happy_chart = ChartModule([{"Label": "happy", "Color": "Black"}])

model_params = {
    "height": 20,
    "width": 20,
    "density": UserSettableParameter("slider", "Agent density", 0.8, 0.1, 1.0, 0.1),
    "minority_pc": UserSettableParameter(
        "slider", "Fraction minority", 0.5, 0.00, 1.0, 0.05
    ),
    "homophily": UserSettableParameter("slider", "Homophily", 3, 0, 8, 1),
}

server = ModularServer(
    Schelling, [canvas_element, happy_element, happy_chart], "Schelling", model_params
)

Note que é nesse arquivo server.py que você vai escolher os parâmetros. No caso foi definido um tabuleiro 20x20, densidade dos agente 0.8 (80%). A quantidade entre azul e vermelho é igual e o número mínimo de vizinho iguais para que o agente fique feliz é igual a 3.
Ao executar o código tambem teremos o um gráfico mostrando quantos individuos estão felizes a cada \( \textit step\).

Para rodar o modelo basta, em outro arquivo, rodar:

from server import server

server.launch()

A figura abaixo apresenta como o modelo é exibido no browser:

A imagem será apresentada aqui.

No canto esquerdo estão os parâmetros escolhidos e opções para mudar-los. No centro temos o \( \textit grid\) onde ocorrerá a interação entre os agente e embaixo temos o gráfico representativo de quantos agentes estão satisfeitos a cada rodada ou \(\textit step\). No canto direito superior temos os botões para comecar o modelo, para ir de passo em passo ou para reseta-lo.

Após rodar o modelo, ao clicar o butão Start, com os parâmetros especificados anteriormente, temos o seguinte resultado:

A imagem será apresentada aqui.

Fica evidente os \(\textit clusters \) de azul e vermelho.

Mas vamos buscar uma demonstração mais visualmente apelativa do fenomeno da segregação. Utilizando a aba esquerda para mudar as condições e definindo Homophily = 4 (número mínimo de vizinhos semelhantes) e mantendo os outros parâmetros iguais, temos inicialmente:

A imagem será apresentada aqui.

Após as primeiras 4 rodadas, temos:

A imagem será apresentada aqui.

E no final, depois de 63 \(\textit steps \), chegamos a:

A imagem será apresentada aqui.

Referencias

  1. Wilensky, Uri, and William Rand. An Introduction to Agent-Based Modeling: Modeling Natural, Social, and Engineered Complex Systems with NetLogo. The MIT Press, 2015.

  2. Dodge, Robert V., (2012), Schelling's Game Theory: How to Make Decisions, Oxford University Press.

  3. Dodge, Robert V., (2006), The Strategist: The Life and Times of Thomas Schelling, Hollis Publishing Company, Hollis, NH.

...