Investigación

Fractales a partir de caminantes aleatorios

Usando sistemas-L y agregación limitada por difusión para crear fractales.

corazón

La canción que traía en la cabeza mientras hacía esto era:

TLDR;

¡Prometiste fractales! ¡Llévame a los fractales! (o sea, las respuestas de la tarea)

El del 6.5 de Flake

Hazlo tú mismo

Fractales chidos

DLA

Esto fue una tarea de mi curso de Modelación de Sistemas Complejos, pero como me salieron unas gráficas tan bonitas decidí hacer un post mostrando los resultados.

Lo primero que quiero contar es que mi resultado principal de esa clase va a ser un paquete de julia julia (que está alojado justo aquí github). Está en una etapa muy temprana, así que va a cambiar rápido (estén atentos); los PR, issues y comentarios son bienvenidos y los invito a mandarlos.

Sistemas-L

La primera parte de la tarea era arreglar un código de sistemas-L escrito en Matlab, pero todo mundo sabe que para arreglar un código de Matlab lo primero que tienes que hacer es escribirlo en otro lenguaje (libre y de código abierto), así que ahí fue donde decidí hacer mi propia implementación en Julia desde cero. No me gustó la dirección orientada a objetos que se tomó en el original y decidí irme por el lado de los diccionarios.

Antes que nada, para quienes todavía no saben qué es un sistema-L (que significa sistema de Lindenmayer): es un sistema de reescritura iterativo que consiste en ciertas reglas. Estas reglas son de coincidencia de patrones, así que en cada iteración tienes que buscar cierto patrón y reemplazarlo con una regla dada.

Ejemplo:

Tenemos la siguiente cadena: FGFGFFF

Y una regla F -> FG

Entonces:

| Iteración | Cadena resultante | | 0 | FGFGFFF | | 1 | FGGFGGFGFGFG | | 2 | FGGFGGGFGGFGGFGG |

Y así sucesivamente.

El primer problema era reproducir una figura del libro de Flake The Computational Beauty of Nature con nuestro software nuevecito. Pero primero queremos ver si obtenemos el mismo resultado que el código de ejemplo de Matlab (que creo que estaba alojado aquí).

El conjunto de reglas era:

F -> FF

G -> F[+G][-G]F[+G][-G]FG

Hay que saber que [ ] significa que las reglas dentro de los corchetes solo valen ahí adentro, así que cuando llegamos a ] regresamos los parámetros a los que teníamos antes de entrar, y los signos + - significan un cambio en el ángulo de movimiento. Entonces necesitamos un punto de inicio, un ángulo inicial y una tasa de cambio Δ\Delta para ese ángulo. La posición inicial se llama axioma y es una cadena semilla. En este caso tenemos axioma = G y Δ\Delta = 27.5°.

La figura que resulta después de 2 iteraciones es ejemplo

Ahora queremos reproducir la figura que nos pidieron. Tiene los siguientes parámetros:

Hierba 1

| Reglas | Δ\Delta | Axioma | | F -> F[-F]F[+F]F | 25 | F |

hierba

No tengo la imagen original aquí, pero te puedo decir que es la misma 😜

Construyendo tu fractal

A veces necesitamos cambiar el ángulo más de una vez, así que podemos poner un número antes de los signos + - para decirle a la tortuga (así se le conoce) que cambie de dirección varias veces. Por ejemplo, si tenemos Δ\Delta = 10°, entonces 4+ va a cambiar el ángulo 40° en sentido contrario a las manecillas del reloj (igual que como normalmente medimos los ángulos). Eso nos lleva a la segunda pregunta de la tarea, que era implementar esto y tratar de reproducir una figura chida que se nos ocurriera.

Como soy un romántico, voy a intentar hacer una versión fractal o pseudo-fractal de esto

corazón

Y lo voy a hacer con el siguiente conjunto de parámetros

| Reglas | Δ\Delta | Axioma | |F -> FF[+F][-F] | 45° | F | |+ -> +F[+2F][-2F] | | |- -> -F[-3F][+3F] | |

Es un conjunto de reglas muy básico, pero lo que quería era evitar que las ramas se tocaran (por lo menos las chiquitas).

El resultado final

corazón

Esto se logró con de 1 a 4 iteraciones de esas reglas, pero también podemos ver cómo crece (en un proceso de 3 iteraciones)

construcción

Aquí hay otros ejemplos chidos de lo que se puede hacer

Cosas chidas

sierpinski penrose picos

Agregación limitada por difusión

DLA

Para esto sí usé una especie de algoritmo orientado a objetos, pero es muy sencillo. Para que todo fuera más rápido aproveché la velocidad de Julia y traté de hacer el código lo más modular posible para sacarle el máximo provecho al compilador JIT. Y resultó que corre bastante rápido.

Usé 1000 caminantes aleatorios en una caja de 10x10 y los hice dejar de moverse si tocaban a un caminante que ya no se movía, y puse uno de esos primero en medio de la caja. Lo que obtuve fue esta cosa que se ve bien chida

dla

Algoritmo de conteo de cajas

La última pregunta era medir la dimensión de Minkowski de la figura que obtuvimos. El algoritmo es muy sencillo: tienes que dividir el espacio en una cuadrícula de cajas del mismo tamaño y contar cuántas se necesitan para cubrir toda la figura. Entonces esa dimensión va a ser

D=lim⁡a→∞ln⁡(N)ln⁡(1a)D = \lim_{a \rightarrow \infty} \frac{\ln(N)}{\ln(\frac{1}{a})}

donde a es el tamaño de la caja y N el número de cajas necesarias.

Para lograrlo usé el poder de GEOS, que es el software que está detrás de PostGIS y GeoPandas. Construí una cuadrícula de cajas con propiedades de relleno y revisé si estaban vacías o no.

Una figura de la dimensión en función del tamaño de caja

dla

La a más pequeña que usé fue 0.01 y obtuve una dimensión de 1.437

Con eso podríamos decir que tiene estructura fractal. Pero habría que probar con tamaños de caja más pequeños.