Showing posts with label Juego de la vida. Show all posts
Showing posts with label Juego de la vida. Show all posts

Friday, February 17, 2023

Un descubrimiento personal


En la Facultad de Ciencias doy un curso de Vida Artificial", la cual es una asignatura que trata de simulaciones -a través de la computadora- de manera que se puedan estudiar algunos conceptos de la vida misma, por ejemplo, la reproducción. Para ello se usan los autómatas celulares en una y dos dimensiones (en general), los cuales han sido estudiados ya en los años 70s, 80s y 90s del siglo pasado por Conway (Juego de la vida) y Wolfram (autómatas celulares en una dimensión). De hecho, existe mucha información en la red sobre este tema. Wolfram, por ejemplo, ha escrito un libro enorme, llamado "A New Kind of Science", el cual puede leerse gratuitamente aquí. Por otro lado, el sitio obligado para estudiar el Juego de la Vida de Conway es éste

Pues bien, en el libro de Wolfram, (el cual a pesar de intimidar sólo por su tamaño, es bastante accesible y diría que en general es un libro de divulgación), se habla de los autómatas unidmensionales. Se analizan las 256 reglas. Se hace un análisis de la complejidad de las mismas, etcétera. Wolfram entonces experimenta cambiando reglas y situaciones para la reproducción de los autómatas. Eventualmente demuestra que con ciertas reglas de sustitución, se pueden crear los elementos fundamentales de la máquina de Turing, la cual es una máquina conceptual que puede hacer en principio, cualquier cálculo.

Por ejemplo, en la página 82 de su libro, pone el siguiente gráfico que ilustra un sistema simple de sustitución, el cual genera que se dupliquen los elementos en cada generación. 

Y aunque Wolfram lo muestra con puntos de tonos de gris, su sistema de sustitución es simplemente:

A --> AB

B --> BA

Así, si tenemos una configuración inicial con solamente el elemento A, podeos sustituir y quedarnos lo siguiente:

A --> AB

AB --> ABBA

ABBA --> ABBABAAB

etcétera...

Si contamos los elementos que hay en cada generación, encontraremos que estos se duplican.

La serie de Fibonacci, por ejemplo, puede expresarse como el siguiente esquema de sustitución:

A --> B

B --> BA

Si tenemos la configuración inicial A obtendremos en las siguientes generaciones:

A --> B

B --> BA

BA --> BAB

BAB --> BABBA

BABBA --> BABBABAB

BABBABAB --> BABBABABBABBA

Si contamos los elementos en cada generación, obtendremos la secuencia de Fibonacci: 1, 2, 3, 5. 8. 13, etcétera.

Pues bien, defnir un autómata como un sistema de sustitución generauna gramática y esta es simplemente una serie de símbolos que se manipulan a través de ciertas reglas. Así, aplicando dichas reglas se obtienen las "frases" legales y válidas de acuerdo a la gramática definida.

Los autómatas formales, como los lenguajes, tienen en muchos casos la posibilidad de ser recursivos, se llaman así mismo. Por ejemplo, en el caso de las reglas de sustitución del autómata que duplica los valores de sus elementos en cada generación, podemos ver que A se sustituye por AB y B se sustituye por BA. Hay una suerte de llamada a sí misma en cada regla. Y esto es bastante común en los lenguajes. Por ejemplo, pensemos en la definición recursiva del factorial:

0! = 1 (condición terminal)

n! = n * (n-1)! (recursión)

Por ejemplo, para calcular 3! diremos lo siguiente:

3! = 3 * 2!

necesitamos ahora conocer cuánto es 2!

2! = 2 * 1!

necesitamos ahora conocer cuánto es 1!

1! = 1 * 0!

necesitamos ahora conocer cuánto es 0!, pero eso ya lo sabemos, 0! = 1. 

Entonces empezamos a resolver cada ecuación:

1! = 1 * 0! = 1 * 1 = 1

entonces 2! = 2 * 1! = 2 * 1 = 2

por ende, 3! = 3 * 2! = 3 * 2 = 6.


Otro ejemplo de los lenguajes humanos: Si buscamos la definición de "perro", hallaremos que es "can". Si buscamos la definición de "can", se nos dirá que es "perro". Aquí hay una función recursiva que se cicla, porque no tiene una manera de terminar, de detenerse, como en el caso de la definición de factorial, en donde 0! termina con el cálculo y el ciclado infinito (porque 0! = 1).

Pues bien, se sabe que toda función recursiva se puede poner de forma iterativa. Por ejemplo, el factorial iterativo en Python (no recursivo) es:

def factorial(n):

    result = 1

    for i in range(1, n + 1):

        result *= i

    return result

(gracias a chatgpt)


En cambio, en Python, el factorial recursivo se escribe así:

def factorial(n):

    if n == 0:

        return 1

    else:

        return n * factorial(n-1)

(de nuevo, gracias a chatgpt)

La versión iterativa usa menos recursos de cómputo que la versión recursiva. Entonces, ¿por qué los autómatas celulares e incluso, los seres vivos, usan la recursión para crear otros seres vivos (a su imagen y semejanza)? ¿No debería la Naturaleza usaR la máxima economía en recursos?

Esta es la pregunta que no podía resolver, pero el otro día, caminando por avenida del IMAN, encontré una posible respuesta. De pronto me sentí como el episodio que narra Bertrando Russell cuando se dio cuenta del concepto de la verdad ontológica. Dice Russell que sintió una especie de iluminación, experiencia que pocas veces se da sin la necesidad de sustancias alucinógenas u otros artilugios.

Pues bien, la respuesta a las preguntas que me había planteado sobre los autómatas celulares y a que prácticamente todos usan la recursión, es porque en la misma se encuentra una imagen a escala de lo que está representando. En el caso de la iteracción, necesitamos pasarle los parámetros correctos para que se ejecuten los algoritmos que queremos, pero en la recursión, los datos se incluyen en el mismo algoritmo. Russell, por ejemplo, habla de la paradoja del barbero, en donde se puede expresar en Prolog, donde el paradigma de ese lenguaje hace que las instrucciones y los datos sean indistintos. Véase aquí  para esa discusión.

Así, a mí me queda clarísima la razón por la cual los seres vivos usan funciones recursivas, que se llaman a sí mismas, para la reproducción y creación de los elementos hijos. Y sí, aparentemente ocupa más recursos pero la realidad es que es mucho más eficiente que los algoritmos iterativos.



Saturday, November 03, 2018

Nuevo reto lúdico: el juego de la vida de Conway



Hoy en día estamos acostumbrados a luminosos videojuegos que emociona, excitan a los jugadores y en ocasiones incluso pueden jugarse por muchas personas al mismo tiempo en servidores dedicados a ello. Muchos videojuegos hacen énfasis en las habilidades manuales del jugador y sus reflejos, los cuales bien pueden convertirse en juegos populares e incluso adictivos.

Pero también hay juegos que caen en categorías que resultan hasta curiosas. Este es el caso del juego de, la vida de Conway, un juego de cero-personas, inventado por el matemático John Conway, cuando éste trabajaba en la Universidad de Cambridge. El juego se conoció ampliamente a partir del artículo de Martin Gardner en Scientific American, de octubre de 1970 e inmediatamente se volvió un ejercicio adictivo en cómputo.


John Conway con la Morsa, en la plática que dio el primero en la Facultad de Ciencias

El juego se desarrolla en una malla cuadriculada, en donde en los casilleros de la misma (llamadas celdas), se colocan células o bien se dejan vacíos. Las reglas son sencillas, cuando hay una configuración de celdas ocupadas y vacías, se tiene que:


  1. Cada célula con una o sin células vecinas se muere, por soledad.
  2. Cada célula con cuatro o más células vecinas mueren, por sobrepoblación.
  3. Cada células con dos o tres vecinas, sobrevive.


Así, el juego consiste en que el usuario genere una configuración de células y aplique las reglas mencionadas en paralelo para cada celda. Eso hará la siguiente generación, a la cual se le aplicará el mismo algoritmo. Un ejemplo del juego de la vida de Conway puede verse aquí, en donde el lector podrá generar las configuración que quiera y ver cómo evoluciona en el tiempo. En eso, de hecho, consiste el juego. No hay que interactuar de ninguna manera una vez que se ha generado una configuración de celdas.

Conway y mucha gente dedicó muchas horas al juego de la vida tratando de encontrar las propiedades de las diferentes configuraciones y se tienen conclusiones fantásticas, por ejemplo, que el juego de la vida es "Turing completo", es decir, se puede crear una máquina de Turing que pueda hacer cualquier cálculo. Tal vez por ello la importancia de este "juego". Cabe decir que además, Conway redujo la idea de los autómatas celulares que en un principio von Neumann había estudiado y en donde -según él- su diseño requería de 29 propiedades y reglas, a algo mucho más escueto pero igualmente poderoso.

Pues bien, el juego de la vida de Conway eventualmente fue programado infinidad de meses y se tienen reiteradas sospechas de que usó mucho "tiempo de máquina" en computadoras grandes, en aquellas máquinas que solamente las podían tener en esos tiempos las instituciones académicas y las instancias gubernamentales. Sin embargo, el juego -como ya dijimos- es mucho más que un simple juego, y quizás sea un interesante modelo teórico para desarrollar ideas en matemáticas e inclusive, en la biología.

Pues bien, considerando eso, el reto consiste en desarrollar un programa que juegue al juego de la vida de Conway. Se puede desarrollar en cualquier lenguaje y sería interesante (puntos extras), a quien lo desarrolle en algún lenguaje que no haya sido ya escrito en Rosetta Code. Es cierto que en este sitio pueden verse ya mucho código fuente que resuelve el problema pero aquí el reto es que usted lector/lectora, lo resuelva.

Para ser más claros, el juego de la vida se representa así:

Una célula C se representa por 1 cuando está viva y 0 cuando está muerta, en una matriz cuadrada de m x m casilleros o celdas. Calculamos N, la suma de las células vidas en las ocho celdas en la vecindad de cada célula C, y entonces tenemos a una célula que sobrevive o que muere en la siguiente generación basándose en lo siguiente:


  • Si una célula está en 1  y tiene 0 o 1 vecino (una célula en 1), entonces en la posición de la célula se pinta un 0 (muerte por soledad).
  • Si una célula está en 1 y hay una vecindad con 4, 5, 6, 7 y 8 celdas vecinas ocupadas, entonces se pinta un 0 en la siguiente generación (muerte por sobrepoblación)
  • Si la célula de interés tiene un 1 y la vecindad de la misma tiene 2 o 3 células en 1, entonces sobrevive con un 1 en la siguiente generación.
  • Si la célula tiene 0 en el punto de interés y hay 3 células alrededor, se pondrá un 1 en la siguiente generación (tres células dan el nacimiento de una nueva).
  • Si la célula es 0 y hay  0, 1, 2, 4, 5, 6, 7, 8  entonces en la siguiente generación se pondrá un 0.


El programa a escribir debe hacerse en cualquier lenguaje que se deseé. Puede ser compilado o interpretado y tiene puntos extras si el lenguaje usado no está en las implementaciones hechas ya en el sitio de Rosetta Code. Desde luego, se puede hacer en un algún lenguaje ya usado, por ejemplo C, C#, Haskell incluso, pero si alguien me va a mandar el código le suplico que no lo copie y que busque ser original. Si detecto copia lo descalifico.

La idea es pues aprender y este es un ejercicio simple pero interesante, además de que puede ser muy útil para probar una serie de teorías al respecto de los patrones, de ciertas configuraciones, de la estabilidad de algunas de estas células, etcétera. En Conway Life hay mucha información interesante.



Al ganador (si es de la Ciudad de México), le daré una taza con el logotipo de la Morsa. Si es de otro país o de provincia, le mandaré un USB de al menos 8 GB. La razón de esto es que mandar una taza por mensajería es estúpidamente caro.

Las soluciones me las pueden mandar a morsa@la-morsa.com.

Cabe señalar que este concurso busca simplemente alentar el trabajo de la programación y mostrar que puede ser lúdica. Es un concurso de buena fe. Si hay, por ejemplo, dos o más respuestas satisfactorias, ganará quien la haya mandado primero o que cumpla con más características que le den mejores resultados. El ganador es inapelable y cede su código fuente a la comunidad. Es decir, se promueve el código abierto.


Wednesday, April 11, 2012

El juego de la vida de Conway

 

Hay un juego de computadora fascinante, llamado Juego de la Vida, el cual fue diseñado en 1970 por el matemático británico John Horton Conway, de la Universidad de Cambridge, Inglaterra. Se hizo muy popular desde que Martin Gardner, en su columna de octubre de ese año en la revista Scientific American hablara de las ideas de Conway. Y a partir de ese momento miles de programadores lo codificaron y jugaron con las ideas del británico en sus respectivos tiempos libres.

El juego de la vida ocurre en un tablero cuadriculado, en donde cada cuadro puede haber una célula o estar vacío. La idea es acomodar una serie de células en la malla cuadriculada y observando las vecindades de cada célula, cada cuadro pues -utilizando las reglas de Conway- ir calculando las nuevas configuraciones de células que aparecerán en la siguiente generación. Puede verse que el juego de la vida de Conway no es estrictamente un juego de video, pues el “jugador” no hace nada más que ver la evolución que en cada tiempo, en cada generación, aparece en la pantalla.

Cabe decir que las reglas que se definan para el juego de la vida deben ser tales que la conducta de la población resulte a un tiempo interesante e impredecible. Las reglas de evolución, dadas por el propio matemático, llamadas también reglas genéticas, son de una sencillez deliciosa y pensamos que Conway las fue descubriendo (¿inventando?) poco a poco.



Tomemos un plano cuadriculado entonces de dimensiones infinitas. Cada sitio, cuadro o casilla, tiene 8 casillas vecinas: cuatro ortogonalmente adyacentes (2 en vertical y 2 en horizontal). En cada sitio es posible poner un valor binario (hay célula o no hay en esa casilla). Las reglas son:

  • Supervivencia: cada célula (digámosle ficha), que tenga dos o tres fichas vecinas sobrevive y pasa a la generación siguiente.
  • Fallecimiento: cada ficha que tenga cuatro o más vecinas muere y es retirada del tablero, por sobrepoblación. Las fichas con una vecina o solas fallecen por aislamiento.
  • Nacimientos: cada casilla vacía, adyacente a exactamente tres cifras vecinas -tres, ni más ni menos- es casilla generatriz. Es decir, en la siguiente generación habrá de colocarse una ficha en esa casilla.

Es importante hacer notar que todos los natalicios y fallecimientos ocurren simultáneamente, y constituyen en su conjunto una generación en particular, al paso del tiempo t, también llamado tic del reloj.

Con el mismísimo Conway, en su plática que dio en junio del 2010 en la Facultad de Ciencias de la UNAM.

En un principio el inventor de este singular “juego” conjeturó que ningún patrón inicial podría crecer ilimitadamente. Dicho en otras palabras, ninguna configuración compuesta por un número finito de fichas puede crecer hasta rebasar un límite superior finito, que limita el número de fichas que puede contener el campo del juego. Seguramente esta sea la cuestión más difícil y profunda que planteé el juego.

Conway ofreció un premio de 50 dólares a la primera persona capaz de probar o de refutar la conjetura antes de finalizar el año 1970. Una forma de refutarla sería dar con configuraciones que, generación tras generación, añadiesen más piezas al terreno de juego: un cañón (es decir, una configuración qaue repetidamente dispara objetos en movimiento), o bien el tren puf-puf (configuración que al paso del tiempo t avanza dejando tras de sí una estela de “humo”).

La conjetura de Conway se refutó en noviembre de 1970. Un grupo integrado en el proyecto de inteligencia artificial del MIT, comandado por William Gosper, halló un cañón lanza-deslizadores, el cual genera un deslizador cada 30 pulsos de reloj (o generaciones). La existencia de tal cañón suscita una interesante posibilidad de que el juego de Conway pueda simular una máquina de Turing, la cual es capaz de hacer, en principio, cualquier computación, cualquier cálculo. Si el juego permite esta alternativa, entonces la siguiente pregunta a resolver es si sería capaz de poderse crear un constructor universal. De lo cual se encontraría una máquina con capacidad de autorreproducción no trivial. Desafortunadamente, a la fecha, no ha podido construírse.

El carácter universal del juego de la vida significa que, en principio, es posible usar deslizadores para llevar a cabo cualquier cómputo que pueda efectuarse con la más potente de las computadoras digitales. Mediante la disposición de cañones lanza-deslizadores y otras formas de “vida”, es posible calcular π, e, la raíz cuadrada de 2, o de cualquier otro número, con cualquier número de cifras decimales.

 Hay muchísimos programas de código abierto y gratuito para jugar con el juego inventado por Conway. Vale la pena probar alguno de ellos e intentar configuraciones diferentes. Hay mucha información sobre el juego de la vida del matemático británico y podría asegurarles que es francamente apasionante. El único inconveniente es que esto comienza a hacerse obsesivo.

Algunas fuentes de interés:

Juego de la vida en HTML5
Juego de la vida de Conway
Juego de la vida con fuentes (Delphi)
LifeWiki
________

(*) En la foto inicial del artículo están, de izquierda a derecha: Erik Demaine, Martin Demaine, Bill Spight y John Conway