El juego de la vida de Conway en Python

¡ Otro ejemplo de simulación basado en agentes de mi parte! En este artículo, implementaré el juego de la vida de Conway en Python, utilizando el marco de trabajo de modelado basado en agentes abm_framework . Puede encontrar el marco haciendo clic en el siguiente enlace.

El juego de la vida de Conway es una buena introducción al modelado basado en agentes y también se enseña en las universidades exactamente por esta razón. También es una buena introducción a la programación en Python en general.

Recientemente he compartido una variedad de ejemplos sobre cómo puede implementar abm_framework en Python para el modelado basado en agentes. Puedes encontrar el marco aquí:

La siguiente sección describe las reglas del juego de la vida de Conway. Después de eso implemento el juego de la vida en Python.

Reglas del juego de la vida de Conway

Concepcionalmente, el juego de la vida consiste en una cuadrícula. Cada cuadrícula de la celda se rellena con un agente. El agente está vivo o muerto. A partir de un estado inicial, el juego de la vida se actualiza iteración tras iteración. Durante cada iteración se aplican las siguientes reglas:

  • Si un agente está vivo y sus celdas vecinas contienen 2 o 3 agentes vivos, el agente sobrevive hasta la siguiente ronda. Entonces está vivo en la siguiente ronda. De lo contrario, el agente muere y muere en la siguiente ronda.
  • Si un agente muerto tiene exactamente 3 agentes vivos en su vecindario, el agente renace y está vivo en la siguiente ronda.

Estas reglas son suficientes para modelar el juego de la vida de Conway. El estado inicial, definido por los agentes muertos o vivos al comienzo de la simulación, es la única entrada que necesita la simulación para ejecutarse. En este artículo ejecuto tres versiones del modelo. Las dos primeras versiones tienen una distribución inicial aleatoria de células de agentes vivos. La tercera versión tiene un patrón semilla inicial específico de agentes vivos. En la primera y tercera versión la grilla es interminable. Esto significa que si sale de la cuadrícula por la izquierda, ingresará a la cuadrícula por el lado derecho, y si sale de la cuadrícula por la parte superior, ingresará a la cuadrícula por la parte inferior. La segunda versión aplica una cuadrícula con límites, es decir, una cuadrícula que no es infinita.

Implementando el juego de la vida en Python

Usando abm_framework en Python (disponible por mí en Github) implemento el modelo en Python. Creo una grilla de simulación con 100 celdas. El estado inicial (denominado semilla) consta de 50 agentes vivos que se distribuyen aleatoriamente en la cuadrícula. El siguiente código implementa la versión de cuadrícula sin fin del modelo de simulación .

__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")

En una segunda versión del modelo, implementé una cuadrícula que no es infinita. El único ajuste en el código está en la llamada al constructor Environment, estableciendo el argumento de cuadrícula sin fin en False en lugar de True.

Animación del juego de la vida de Conway

A continuación se muestra la animación del juego de la vida de Conway en Python. La primera animación representa el modelo con una cuadrícula sin fin.

La segunda animación, que se muestra a continuación, representa el modelo con una cuadrícula delimitada.

Por último, ejecuto un escenario en el que definí un estado de modelo inicial específico. La animación se puede ver a continuación y representa una cuadrícula sin fin.

Puede encontrar varios ejemplos de juegos de la vida haciendo una simple consulta en Google. También hay varias herramientas disponibles para especificar su propia semilla y ejecutar el modelo paso a paso.

Observaciones finales

En este artículo, implementé el juego de la vida de Conway en Python, utilizando un marco que denominé abm_framework . Ejecuté tres escenarios, que diferían en la definición de los límites de la cuadrícula (sin fin frente a no interminable) y la semilla inicial (semilla inicial aleatoria versus semilla inicial específica). Si desea aprender el modelado basado en agentes, implementar el juego de la vida en Python podría ser un buen primer paso para usted.

You May Also Like

Leave a Reply

Leave a Reply

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.