O jogo da vida de Conway em Python

Outro exemplo de simulação baseado em agente do meu lado! Neste artigo vou implementar o jogo da vida de Conway em Python, usando o framework de modelagem baseado em agente abm_framework . Você pode encontrar a estrutura clicando no link abaixo.

O jogo da vida de Conway é uma boa introdução à modelagem baseada em agentes e também é ensinado nas universidades exatamente por esse motivo. Também é uma boa introdução à programação em Python em geral.

Recentemente, compartilhei uma série de exemplos de como você pode implementar o abm_framework em Python para modelagem baseada em agente. Você pode encontrar a estrutura aqui:

A seção a seguir descreve as regras do jogo da vida de Conway. Depois disso implemento o jogo da vida em Python.

Regras do jogo da vida de Conway

Conceitualmente, o jogo da vida consiste em uma grade. Cada grade na célula é preenchida por um agente. O agente está morto ou vivo. A partir de um estado inicial, o jogo da vida atualiza iteração após iteração. Durante cada iteração, as seguintes regras se aplicam:

  • Se um agente está vivo e suas células vizinhas contêm 2 ou 3 agentes vivos, o agente sobrevive até a próxima rodada. É então vivo na próxima rodada. Caso contrário, o agente morre e está morto na próxima rodada.
  • Se um agente morto tiver exatamente 3 agentes vivos em sua vizinhança, o agente renasce e fica vivo na próxima rodada.

Essas regras são suficientes para modelar o jogo da vida de Conway. O estado inicial, definido pelos agentes mortos ou vivos no início da simulação, é a única entrada que a simulação precisa para rodar. Neste artigo eu executo três versões do modelo. As duas primeiras versões têm uma distribuição inicial aleatória de células de agentes vivos. A terceira versão tem um padrão inicial específico de agentes vivos. Na primeira e terceira versão a grade é infinita. Isso significa que, se você sair da grade à esquerda, entrará na grade do lado direito e, se sair da grade na parte superior, entrará na grade na parte inferior. A segunda versão aplica uma grade com limites, ou seja, uma grade que não é infinita.

Implementando o jogo da vida em Python

Usando o abm_framework em Python (disponibilizado por mim no Github) implemento o modelo em Python. Eu crio uma grade de simulação com 100 células. O estado inicial (referido como semente) consiste em 50 agentes vivos que são distribuídos aleatoriamente pela grade. O código abaixo implementa a versão de grade infinita do modelo de simulação .

__author__ = "Linnart Felkl"
__email__ = "LinnartSF@gmail.com"

if __name__ == "__main__":

    print("demo starts")

    import sys
    from pathlib import Path
    file = Path(__file__).resolve()
    parent, root = file.parent, file.parents[1]
    sys.path.append(str(root))

    # remove the current file's directory from sys.path, unless already removed
    try:
        sys.path.remove(str(parent))
    except ValueError:
        pass

    import data
    import stats
    import config
    import framework
    import random
    import animation

    # setup database manager and connection
    db = data.Database("sqlite3", config.path_databasefile)
    db_manager = data.Manager(db)
    
    # create an empty environment
    env = framework.Environment(1, True, 10, 10, db_manager) # Environment constructor implicitly resets environment table in database

    # create initial population of healthy humans
    attrs = ["life_t0","life_t1"]
    datatypes = ["INTEGER","INTEGER"]
    pops = framework.Populations(amount = 1, env = env, db_manager = db_manager, attributes = attrs, datatypes = datatypes)
    pops.add_population(name = "units", 
                        size = 100, 
                        attributes = attrs, 
                        datatypes = datatypes, 
                        initialvals = [0, 0]
                        )
   
    # set seed of simulation (number of agents alive and their pattern)
    agents = pops.get_agents()
    random.shuffle(agents)
    for i in range(50):
        agents[i].set_attr_value("life_t0",1)

    # setup simulation
    sim = framework.Simulation(50)

    # make sure that environment and agents tables in database are setup at this time
    pops.write_env_to_db(sim.Iteration)
    pops.write_agents_to_db(sim.Iteration)

    # execute simulation run; with centralized simulation control
    while sim.run():
        
        for agent in agents:

            # get that agents neighbourhood
            neighbours = env.get_neighbourhood(agent, mode = "moore", radius = 1)

            _neighbours_alive = 0
            for neighbour in neighbours:
                
                if neighbour.get_attr_value("life_t0") == 1: 
                    _neighbours_alive  += 1

            if agent.get_attr_value("life_t0") == 1: 

                if _neighbours_alive == 2 or _neighbours_alive == 3: 
                    
                    agent.set_attr_value("life_t1", 1)

                else:

                    agent.set_attr_value("life_t1", 0)

            elif _neighbours_alive == 3:

                agent.set_attr_value("life_t1", 1)

            else:

                agent.set_attr_value("life_t1", 0)
                
        # update results in database, for agents and for environment
        pops.write_agents_to_db(sim.Iteration)
        pops.write_density_to_db(sim.Iteration)

        # update attributes for next round
        for agent in agents:

            agent.set_attr_value("life_t0", agent.get_attr_value("life_t1"))
    
    # get dataframes with simulation results
    density_df = db_manager.get_densitydf()

    # visualize simulation data
    stats.set_fontsizes(8,10,12)

    animation.animate_density(
        df = density_df,
        filename = "gol_randomendless",
        attr = "life_t1",
        defaultsize = 50,
        color = "black",
        tpf = 0.30
    )

    # end program
    db.close()
    print("demo ends")

Em uma segunda versão do modelo implementei uma grade que não é infinita. O único ajuste no código está na chamada do construtor Environment, definindo o argumento de grade sem fim como False em vez de True.

Animação do jogo da vida de Conway

Abaixo está a animação do jogo da vida de Conway em Python. A primeira animação representa o modelo com uma grade infinita.

A segunda animação, exibida abaixo, representa o modelo com uma grade limitada.

Por fim, executo um cenário no qual defini um estado de modelo inicial específico. A animação pode ser vista abaixo e representa uma grade sem fim.

Você pode encontrar vários exemplos de jogos da vida fazendo uma simples consulta no Google. Existem também várias ferramentas disponíveis para especificar sua própria semente e executar o modelo passo a passo.

Observações finais

Neste artigo eu implementei o jogo da vida de Conway em Python, usando um framework que chamei de abm_framework . Eu executei três cenários, diferindo na definição do limite da grade (sem fim versus não sem fim) e semente inicial (semente inicial aleatória versus semente inicial específica). Se você deseja aprender modelagem baseada em agente, implementar o jogo da vida em Python pode ser um bom primeiro passo para você.

You May Also Like

Leave a Reply

Leave a Reply

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.