19 nov 2016

Arte fractal: Coloreando el conjunto de Mandelbrot con Matlab

Los fractales pueden parecer entes incomprensibles, a los que sólo pueden acceder sabios matemáticos. Sin embargo, hay algunos bastante cotidianos: el romanesco, la lata de una famosa marca de levadura,... El más apasionante es el conjunto de Mandelbrot. Utilizando ciertas propiedades del mismo, podemos asociar un color a cada número que lo forma, obteniendo imágenes bellísimas que nos permiten ver el fractal desde otra perspectiva. Si no sabes Matlab, puedes saltarte los snippets de código y contemplar las imágenes que obtenemos con cada método.


No vamos a hacer hincapié en la definición rigurosa de fractales (nos basta con saber que un fractal es un objeto autosemejante a infinitas escalas) o en conceptos (¡interesantísimos!) asociados a ellos (como la dimensión fractal); hoy sólo vamos a usar los fractales pragmáticamente, para crear imágenes apasionantes.


Breve descripción del conjunto de Mandelbrot


El conjunto de Mandelbrot, pese a su infinita complejidad (nunca mejor dicho), es facilísimo de describir analíticamente. Cogemos un número complejo $z_0$, que equivale a un punto con coordenadas $(x,y)$ en el plano complejo (es decir, la coordenada $x$ es parte real de $z_0$ y la coordenada $y$ es la imaginaria) y sacamos un número que llamamos $z_1$ (en breve veréis para qué lo queremos) realizando con $z_0$ la siguiente operación:

$z_1=z_0^2+z_0$

Para sacar $z_2$ (¿para qué lo queremos? pronto lo verás), hacemos lo mismo pero cambiando $z_1$ por $z_2$ y $z_0^2$ por $z_1^2$:

$z_2=z_1^2+z_0$

Y ya os imagináis cómo sacar $z_3$...

$z_3=z_2^2+z_0$

Podemos generalizar esta fórmula para $z_n$ (siendo $n$ cualquier número natural):

$z_{n+1}=z_n^2+z_0$

Pues bien, si realizando esta operación (llamada iteración) infinitas veces no nos queda algo infinito (es decir, la serie no diverge), $z_0$ pertenece al conjunto de Mandelbrot y lo pintamos de de negro. En caso contrario, $z_0$ no pertenece al mismo y lo pintamos de blanco.


Nuestro primer plot. Los ejes indican el elemento de la matriz: un punto con coordenadas (x,y) es el elemento (y,x) de la matriz D.

Aquí tenemos el arte fractal más básico posible: la representación monocromática del conjunto, cuyo código es:




Este método no está mal, pero para colorear, nos viene mejor asociar a cada A(i,j) su número de iteraciones en vez de su pertenencia o no al conjunto (guardando c en D(i,j) en vez de un 1 o un 0). El programa que usaremos es el siguiente (y en el caso monocromático, el resultado es casi igual):

Repito que en esta entrada no voy a profundizar en filosofía fractal (que es abundante y muy interesante), pero sí que es importante aclarar un par de conceptos del programa para profanos del tema:
  1. Técnicamente, para saber si un punto está o no en el conjunto de Mandelbrot por fuerza bruta (que es como lo estamos haciendo nosotros), habría que hacer infinitas iteraciones. Como acostumbro a publicar una entrada semanal, me descuadraba un poco eso de tener que esperar infinitos segundos a que el programa dibuje cada punto, por lo que para el programa, infinito=100 (bastante razonable, aunque pintará de negro puntos que no estén realmente en el conjunto). Definimos "infinito" en la línea 3 del código de arriba.
  2. Por motivos que no explicaremos aquí, ningún número del conjunto de Mandelbrot tiene módulo mayor que 2, de ahí la condición del bucle de la línea 14.

La importancia de la escala

Como el conjunto de Mandelbrot se basa en la divergencia o no de la serie que hemos visto para cada punto, otra forma más directa de representarlo es haciendo las iteraciones un número determinado de veces para todos los puntos y representando directamente su valor. Pero tenemos que tener en cuenta que los módulos de los puntos que están fuera del conjunto se acercan más a infinito con cada iteración, por lo que su valor (y la diferencia entre ellos) será muy superior al del de los puntos internos (que diferirán mucho menos), siendo necesario escalar la matriz que en el programa de abajo llamamos Z para obtener un dibujo más equilibrado.

En física, esto se hace muy a menudo utilizando la función exponencial de -x, ($D=e^{-mod(Z)}$), ya que ésta suaviza las diferencias de manera proporcional a su valor: modera mucho los grandes contrastes y así realza los pequeños. Por eso, al pintar fractales usaremos mucho la escala exponencial.

Otra manera similar de hacer esto es tomar $D=\log(\mod(Z))$ (la escala de Richter de los terremotos es logarítmica, hace algo parecido a eso), que tiene el mismo efecto pero "suaviza" las diferencias más despacio que la exponencial de $-\mod(Z)$.

Todo se ve mucho más claro con esta gráfica:

La distancia entre las líneas continua y rayada rojas decrece más rápido que la que hay entre las azules. Obviamente, la distancia entre las rectas verdes con igual pendiente es constante,

¡Al grano! Vamos a ver cómo queda el conjunto pintándolo según una escala exponencial:


Ya hemos empezado a tunearlo, usando este código:



Esto no ha hecho más que empezar...


Como el lector intuirá, para avanzar en el arte fractal, debemos familiarizarnos con los mapas de colores, que nos permiten obtener fractales policromados. Así que voy a hacer una introducción a los colormaps de Matlab.

Un colormap es una matriz de n filas y 3 columnas, en la que cada fila indica un color que se puede usar para el plot; y la 1ª, 2ª y 3ª columna, respectivamente, la cantidad (de 0 a 1) de rojo, verde y azul que contiene ese color. Cuando usemos imagesc para pintar una matriz, la función asociará a los elementos de menor valor de la misma el primer color definido y a los de mayor valor el último (es decir, el color definido por la última fila del colormap). Es decir, cuanto mayor sea el valor relativo de un elemento de la matriz, mayor será el índice de la fila del colormap que define su color.

Un ejemplo muy sencillo que incluye todo lo fundamental para trabajar con colormaps:

Si queremos pintar tres franjas de colores fáciles como el rojo, el amarillo y el violeta, definimos un colormap y lo dibujamos así:






Un último tecnicismo: para poner el color que quieras, puedes elegir el color RGB aquí y añadir al colormap el vector [R,G,B]/255 (el valor máximo habitual en RGB es 255, mientras que en Matlab es 1).


Et voilà!

Ya tenemos todos los conocimientos necesarios para iniciarnos en el arte fractal, así que os dejo una muestra de lo que se puede obtener combinando hábilmente los métodos descritos en la entrada:







He hecho un script que genera mapas de colores aleatorios y he elegido los que me parecían más bonitos.










Como ocurre mucho en física, si nos centramos en lo microscópico en vez de en lo macroscópico (que en nuestro caso se basa en aumentar la s de nuestros scripts)  todo se vuelve más irregular. 

Propina: coloreando según el argumento

Inspirado en las imágenes de Georg-Johann Lay en el artículo de Wikipedia del conjunto de Mandelbrot en alemán, que es una pasada.


Si aún no estás con la boca abierta, prepárate.

Los números complejos se pueden caracterizar por su módulo (distancia al origen) y argumento (ángulo en radianes que forma con el eje real la recta que une el número en el plano complejo al origen). Como hay infinitas maneras de dar un ángulo (por ejemplo, $0=2\pi =4\pi =2k\pi $ [radianes]) solemos tomarlos de forma que sean mayores que $-\pi$ y menores o iguales a $\pi$, de manera que no haya multiplicidades. A esto lo llamamos la determinación principal del argumento y, si la dibujamos, vemos que tiene una discontinuidad en el semieje real negativo (ya que pasa de valer $\pi$ a valer $-\pi$):


En la imagen, $\pi$ es negro, $-\pi$ es blanco y $0$ es naranja. Se observa claramente la discontinuidad mencionada en la zona izquierda del eje x. La imagen anterior equivale a la primera iteración (itM=1) del script expo.m, que hemos modificado para la ocasión:




Si iteramos dos veces, obtenemos esta bella simetría central:



Seguimos iterando:
itM=3

itM=4

itM=5

itM=6

itM=7

itM=10

itM=100

itM=1000

Observamos que simplemente representando el argumento de cada número complejo tras las iteraciones ¡también aparece el conjunto de Mandelbrot!

No solo eso: el pseudocírculo (cardioide) principal conserva el patrón del argumento del plano complejo, el secundario también pero girado $\pi$ radianes, el terciario, girado otros $\pi$ radianes respecto del segundo (es decir, igual que el primero),...

Si os fijáis, se pueden observar muchísimas más regularidades. Es francamente sorprendente y desconcertante para mí, ya que siempre había visto el conjunto como un grupo de números cuyo módulo no divergía, pero nunca había pensado en que podría pasar algo así con el argumento. Cuando me informe y pregunte a gente que sepa de verdad de variable compleja, escribiré otra entrada en la que ate los cabos matemáticos que he ido dejando sueltos en esta.


Fuentes y lectura recomendada


  • Representaciones eficientes del conjunto de Mandelbrot:


  • Poner snippets de código en el blog (¡¡gracias, GitHub!!):


http://stackoverflow.com/questions/679189/formatting-code-snippets-for-blogging-on-blogger

Demás fuentes y lectura recomendada:

https://es.wikipedia.org/wiki/Conjunto_de_Mandelbrot
https://fr.wikipedia.org/wiki/Ensemble_de_Mandelbrot#Barri.C3.A8re_du_module_.C3.A9gal_.C3.A0_2
http://www.rapidtables.com/web/color/RGB_Color.htm
http://di002.edv.uniovi.es/~dani/asignaturas/transparencias-leccion23.PDF
https://es.wikipedia.org/wiki/Argumento_(an%C3%A1lisis_complejo)#Valor_principal
https://es.wikipedia.org/wiki/Fractal

No hay comentarios:

Publicar un comentario