El helecho de Barnsley es un fractal que lleva el nombre del matemático británico Michael Barnsley, quien lo describió por primera vez en su libro Fractals Everywhere . [1] Lo hizo para que se pareciera a la agripalma negra, Asplenium adiantum-nigrum .
Historia
El helecho es uno de los ejemplos básicos de conjuntos auto-similares , es decir, es un patrón generado matemáticamente que puede reproducirse con cualquier aumento o reducción. Al igual que el triángulo de Sierpinski , el helecho Barnsley muestra cómo se pueden construir estructuras gráficamente hermosas a partir de usos repetitivos de fórmulas matemáticas con computadoras. El libro Fractals Everywhere de Barnsley de 1988 se basa en el curso que impartió para estudiantes de pregrado y posgrado en la Escuela de Matemáticas del Instituto de Tecnología de Georgia , llamado Fractal Geometry . Después de publicar el libro, se desarrolló un segundo curso, llamado Teoría de la medida fractal . [1] El trabajo de Barnsley ha sido una fuente de inspiración para los artistas gráficos que intentan imitar la naturaleza con modelos matemáticos.
El código helecho desarrollado por Barnsley es un ejemplo de un sistema de función iterada (IFS) para crear un fractal. Esto se sigue del teorema del collage . Ha utilizado fractales para modelar una amplia gama de fenómenos en ciencia y tecnología, pero más específicamente en estructuras vegetales.
Los IFS proporcionan modelos para ciertas plantas, hojas y helechos, en virtud de la auto-similitud que a menudo ocurre en las estructuras ramificadas en la naturaleza. Pero la naturaleza también exhibe aleatoriedad y variación de un nivel a otro; no hay dos helechos exactamente iguales, y las frondas ramificadas se convierten en hojas a menor escala. Los fractales V-variable permiten tal aleatoriedad y variabilidad a través de escalas, mientras que al mismo tiempo admiten una dependencia continua de los parámetros que facilitan el modelado geométrico. Estos factores nos permiten hacer los modelos biológicos híbridos ... ... especulamos que cuando se encuentra un modelo fractal geométrico variable en V que tiene una buena correspondencia con la geometría de una planta dada, entonces existe una relación específica entre estos árboles de código y la información almacenada en los genes de la planta.
—Michael Barnsley y col. [2]
Construcción
El helecho de Barnsley usa cuatro transformaciones afines . La fórmula para una transformación es la siguiente:
Barnsley muestra el código IFS para su fractal de helecho Black Spleenwort como una matriz de valores que se muestran en una tabla. [3] En la tabla, las columnas "a" a "f" son los coeficientes de la ecuación y "p" representa el factor de probabilidad.
w | a | B | C | D | mi | F | pag | Porción generada |
---|---|---|---|---|---|---|---|---|
ƒ 1 | 0 | 0 | 0 | 0,16 | 0 | 0 | 0,01 | Madre |
ƒ 2 | 0,85 | 0,04 | −0,04 | 0,85 | 0 | 1,60 | 0,85 | Folletos sucesivamente más pequeños |
ƒ 3 | 0,20 | −0,26 | 0,23 | 0,22 | 0 | 1,60 | 0,07 | Folleto más grande a la izquierda |
ƒ 4 | −0,15 | 0,28 | 0,26 | 0,24 | 0 | 0,44 | 0,07 | Folleto más grande a la derecha |
Estos corresponden a las siguientes transformaciones:
Generación de computadoras
Aunque, en teoría, el helecho de Barnsley podría trazarse a mano con un bolígrafo y papel cuadriculado, el número de iteraciones necesarias asciende a decenas de miles, lo que hace que el uso de una computadora sea prácticamente obligatorio. Muchos modelos informáticos diferentes del helecho de Barnsley son populares entre los matemáticos contemporáneos. Siempre que las matemáticas se programen correctamente utilizando la matriz de constantes de Barnsley, se producirá la misma forma de helecho.
El primer punto dibujado está en el origen ( x 0 = 0, y 0 = 0) y luego los nuevos puntos se calculan iterativamente aplicando aleatoriamente una de las siguientes cuatro transformaciones de coordenadas: [4] [5]
ƒ 1
- x n + 1 = 0
- y n + 1 = 0,16 y n .
Esta transformación de coordenadas se elige el 1% del tiempo y simplemente asigna cualquier punto a un punto en el primer segmento de línea en la base del tallo. Esta parte de la figura es la primera que se completa durante el curso de las iteraciones.
ƒ 2
- x n + 1 = 0,85 x n + 0,04 y n
- y n + 1 = −0,04 x n + 0,85 y n + 1,6.
Esta transformación de coordenadas se elige el 85% de las veces y mapea cualquier punto dentro del folleto representado por el triángulo rojo a un punto dentro del folleto opuesto, más pequeño, representado por el triángulo azul en la figura.
ƒ 3
- x norte + 1 = 0,2 x norte - 0,26 y norte
- y n + 1 = 0,23 x n + 0,22 y n + 1,6.
Esta transformación de coordenadas se elige el 7% del tiempo y mapea cualquier punto dentro del folleto (o pabellón auricular ) representado por el triángulo azul a un punto dentro del triángulo correspondiente alterno a través del tallo (lo voltea).
ƒ 4
- x n + 1 = −0,15 x n + 0,28 y n
- y n + 1 = 0,26 x n + 0,24 y n + 0,44.
Esta transformación de coordenadas se elige el 7% del tiempo y mapea cualquier punto dentro del folleto (o pabellón auricular ) representado por el triángulo azul a un punto dentro del triángulo correspondiente alterno a través del tallo (sin voltearlo).
La primera transformación de coordenadas dibuja el tallo. El segundo genera copias sucesivas del tallo y las frondas inferiores para formar el helecho completo. El tercero dibuja la fronda inferior a la izquierda. El cuarto dibuja la fronda inferior a la derecha. La naturaleza recursiva del IFS garantiza que el conjunto sea una réplica más grande de cada fronda. Tenga en cuenta que el helecho completo está dentro del rango −2.1820 < x <2.6558 y 0 ≤ y <9.9983.
Variedades mutantes
Jugando con los coeficientes, es posible crear variedades de helechos mutantes. En su artículo sobre fractales V-variable, Barnsley llama a este rasgo un superfractal . [2]
Sin embargo, un experimentador ha elaborado una tabla de coeficientes para producir otro helecho de aspecto notablemente natural, parecido al helecho Cyclosorus o Thelypteridaceae . Estos son: [6] [7]
w | a | B | C | D | mi | F | pag |
---|---|---|---|---|---|---|---|
ƒ 1 | 0 | 0 | 0 | 0,25 | 0 | −0,4 | 0,02 |
ƒ 2 | 0,95 | 0,005 | −0,005 | 0,93 | −0,002 | 0,5 | 0,84 |
ƒ 3 | 0,035 | −0,2 | 0,16 | 0,04 | −0,09 | 0,02 | 0,07 |
ƒ 4 | −0,04 | 0,2 | 0,16 | 0,04 | 0.083 | 0,12 | 0,07 |
Ejemplos de sintaxis
Puede usar la siguiente sintaxis para dibujar el helecho usted mismo.
Pitón
importar tortuga importar al azarpluma = tortuga . Pluma de tortuga () . lápiz de velocidad ( 15 ) . bolígrafo de color ( "azul" ) . penup ()x = 0 y = 0 para n en el rango ( 110000 ): lápiz . goto ( 65 * x , 37 * y - 252 ) # 57 es escalar el helecho y -275 es comenzar el dibujo desde abajo. bolígrafo . pendown () pluma . bolígrafo de punto () . penup () r = aleatorio . aleatorio () # para obtener probabilidad r = r * 100 xn = x yn = y si r < 1 : # escalera elif basada en la probabilidad x = 0 y = 0.16 * yn elif r < 86 : x = 0.85 * xn + 0.04 * yn y = - 0.04 * xn + 0.85 * yn + 1.6 elif r < 93 : x = 0.20 * xn - 0.26 * yn y = 0.23 * xn + 0.22 * yn + 1.6 else : x = - 0.15 * xn + 0.28 * yn y = 0,26 * xn + 0,24 * yn + 0,44
R
# Helecho de Barnsley# Crear función de la probabilidad y el punto actual fractal_fern2 <- función ( x , p ) { si ( p <= 0,01 ) { m <- matriz ( c ( 0 , 0 , 0 , . 16 ), 2 , 2 ) f <- c ( 0 , 0 ) } otro si ( p <= 0,86 ) { m <- matriz ( c ( . 85 , -.04 , . 04 , . 85 ), 2 , 2 ) f <- c ( 0 , 1,6 ) } otro si ( p <= 0,93 ) { m <- matriz ( c ( . 2 , . 23 , -.26 , . 22 ), 2 , 2 ) f <- c ( 0 , 1,6 ) } más { m <- matriz ( c ( -.15 , . 26 , . 28 , . 24 ), 2 , 2 ) f <- c ( 0 , . 44 ) } m % *% x + f }# cuántas repeticiones determina qué tan detallado será el helecho repeticiones <- 10000# crear un vector con valores de probabilidad y una matriz para almacenar coordenadas p <- runif ( repeticiones )# inicializar un punto en las coordenadas de origen <- c ( 0 , 0 )# calcular coordenadas fractales m <- Reducir ( fractal_fern2 , p , acumular = T , init = coords ) m <- t ( do.call ( cbind , m ))# Crear diagrama de trazado ( m , type = "p" , cex = 0.1 , col = "darkgreen" , xlim = c ( -3 , 3 ), ylim = c ( 0 , 10 ), xlab = NA , ylab = NA , ejes = FALSO )
Procesando
/ * Helecho de Barnsley para procesamiento 3.4 * /// declarando las variables xey float x , y ;// creando la configuración del vacío del lienzo () { tamaño ( 600 , 600 ); fondo ( 255 ); } / * configurando el trazo, mapeando el lienzo y luego trazando los puntos * / void drawPoint () { stroke ( 34 , 139 , 34 ); strokeWeight ( 1 ); flotador px = mapa ( x , - 2.1820 , 2.6558 , 0 , ancho ); float py = map ( y , 0 , 9.9983 , altura , 0 ); punto ( px , py ); }/ * algoritmo para calcular el valor de (n + 1) el término de xey basado en las matrices de transformación * / void nextPoint () { float nextX , nextY ; float r = aleatorio ( 1 ); si ( r < 0.01 ) { nextX = 0 ; nextY = 0.16 * y ; } más si ( r < 0,86 ) { siguienteX = 0,85 * x + 0,04 * y ; siguienteY = - 0.04 * x + 0.85 * y + 1.6 ; } más si ( r < 0,93 ) { siguienteX = 0,20 * x - 0,26 * y ; siguienteY = 0.23 * x + 0.22 * y + 1.6 ; } más { siguienteX = - 0,15 * x + 0,28 * y ; siguienteY = 0.26 * x + 0.24 * y + 0.44 ; } x = siguienteX ; y = nextY ; }/ * itera las funciones de trazado y cálculo sobre un bucle * / void draw () { for ( int i = 0 ; i < 100 ; i ++ ) { drawPoint (); nextPoint (); } }
P5.JS
sea x = 0 ; sea y = 0 ; configuración de función () { createCanvas ( 600 , 600 ); fondo ( 0 ); }// rango −2.1820 función drawPoint () { trazo ( 255 ); strokeWeight ( 1 ); deje px = mapa ( x , - 2.1820 , 2.6558 , 0 , ancho ); sea py = mapa ( y , 0 , 9.9983 , altura , 0 ); punto ( px , py ); }función nextPoint () { dejar nextX ; dejar nextY ; sea r = aleatorio ( 1 ); si ( r < 0.01 ) { // 1 siguienteX = 0 ; nextY = 0.16 * y ; } más si ( r < 0,86 ) { // 2 siguienteX = 0,85 * x + 0,04 * y ; siguienteY = - 0.04 * x + 0.85 * y + 1.60 ; } más si ( r < 0,93 ) { // 3 siguienteX = 0,20 * x + - 0,26 * y ; siguienteY = 0.23 * x + 0.22 * y + 1.60 ; } else { // 4 nextX = - 0.15 * x + 0.28 * y ; siguienteY = 0.26 * x + 0.24 * y + 0.44 ; } x = siguienteX ; y = nextY ; }función dibujar () { para ( sea i = 0 ; i < 1000 ; i ++ ) { dibujarPunto (); nextPoint (); } }
JavaScript (HTML5)
< canvas id = "canvas" height = "700" width = "700" > canvas >< script > dejar lienzo ; let canvasContext ; sea x = 0 , y = 0 ; ventana . onload = function () { lienzo = documento . getElementById ( "lienzo" ); canvasContext = lienzo . getContext ( '2d' ); canvasContext . fillStyle = "negro" ; canvasContext . fillRect ( 0 , 0 , lienzo . ancho , lienzo . alto ); setInterval (() => { // Actualiza 20 veces cada fotograma para ( let i = 0 ; i < 20 ; i ++ ) update (); }, 1000 / 250 ); // 250 cuadros por segundo }; function update () { let nextX , nextY ; sea r = Math . aleatorio (); si ( r < 0.01 ) { nextX = 0 ; nextY = 0.16 * y ; } más si ( r < 0,86 ) { siguienteX = 0,85 * x + 0,04 * y ; siguienteY = - 0.04 * x + 0.85 * y + 1.6 ; } más si ( r < 0,93 ) { siguienteX = 0,20 * x - 0,26 * y ; siguienteY = 0.23 * x + 0.22 * y + 1.6 ; } más { siguienteX = - 0,15 * x + 0,28 * y ; siguienteY = 0.26 * x + 0.24 * y + 0.44 ; } // Escalado y posicionamiento let plotX = canvas . ancho * ( x + 3 ) / 6 ; deje plotY = lienzo . altura - lienzo . altura * (( y + 2 ) / 14 ); drawFilledCircle ( plotX , plotY , 1 , "verde" ); x = siguienteX ; y = nextY ; } const drawFilledCircle = ( centerX , centerY , radio , color ) => { canvasContext . beginPath (); canvasContext . fillStyle = color ; canvasContext . arco ( centroX , centroY , radio , 0 , 2 * Math . PI , verdadero ); canvasContext . llenar (); }; script >
QBasic
SCREEN 12 VENTANA ( -5 , 0 ) - ( 5 , 10 ) RANDOMIZE TIMER COLOR 10 DO SELECT CASE RND CASE IS < 0,01 nextX = 0 nextY = 0,16 * y CASE 0,01 A 0,08 nextX = 0,2 * x - .26 * y nextY = .23 * x + .22 * y + 1.6 CASE .08 TO .15 nextX = -.15 * x + .28 * y nextY = .26 * x + .24 * y + .44 CASE ELSE nextX = .85 * x + .04 * y nextY = -.04 * x + .85 * y + 1.6 END SELECT x = nextX y = nextY PSET ( x , y ) LOOP HASTA INKEY $ = CHR $ ( 27 )
VBA (CorelDraw)
Sub Barnsley () Dim iEnd Tan largo Dim i Tan largo Dim x Como doble dim y Como doble dim nextX como doble dim nextY como doble dim sShapeArray () como forma dim dSize como doble dim sColor como cadena dSize = 0.01 'Tamaño de los puntos sColor = "0,0,100" ' Color RGB de los puntos, rango de valores de 0 a 255 iEnd = 5000 'Número de iteraciones ReDim sShapeArray ( iEnd ) ' En Corel, cada objeto dibujado requiere un nombre de variable de su propio Aleatorizar 'Inicializar la función Rnd For i = 0 To iEnd ' Iterate ... Select Case Rnd Case Is < 0.01 ' f1 = Draw stem nextX = 0 nextY = 0.16 * y Case 0.01 To 0.08 'f3 nextX = 0.2 * x - 0.26 * y nextY = 0.23 * x + 0.22 * y + 1.6 Caso 0.08 a 0.15 'f4 siguienteX = -0.15 * x + 0.28 * y siguienteY = 0.26 * x + 0.24 * y + 0.44 Caso contrario ' f2 siguienteX = 0.85 * x + 0.04 * y siguienteY = - 0.04 * x + 0.85 * y + 1.6 Fin Seleccionar x = siguienteX y = siguienteY Establezca sShapeArray ( i ) = ActiveLayer . CreateEllipse2 ( x + 2.5 , y + 0.5 , dSize ) sShapeArray ( i ) . Estilo . StringAssign "{" "fill" ": {" "primaryColor" ":" "RGB255, USER," & sColor & ", 100,00000000-0000-0000-0000-000000000000" "," "secundarioColor" ":" " RGB255, USER, 255,255,255,100,00000000-0000-0000-0000-000000000000 "", "" tipo "": "" 1 "", "" fillName "": nulo}, "" contorno "": {"" ancho " ":" "0" "," "color" ":" "RGB255, USUARIO, 0,0,0,100,00000000-0000-0000-000000000000" "}," "transparencia" ": {}}" DoEvents próximo End Sub
Amola
addpackage ( "Forms.dll")conjunto ( "x", 0)conjunto ( "y", 0)set ( "ancho", 600)set ( "altura", 600) configuración del método ()createCanvas ( ancho , alto )rect ( 0 , 0 , 600 , 600 , color ( 0 , 0 , 0 ))finalmétodo drawPoint () set ( "curX", div (mult (ancho, agregar (x, 3)), 6)) set ( "curY", sub (altura, mult (altura, div (agregar (y, 2), 14)))) set ( "tamaño", 1)// registro ( curX )// log ( curY )rect ( redondo ( curX - tamaño / 2 ), redondo ( curY - tamaño / 2 ), redondo ( curX + tamaño / 2 ), redondo ( curY + tamaño / 2 ), color ( 34 , 139 , 34 ))finalmétodo nextPoint ()set ( "nextX", 0)establecer ( "siguienteY", 0)set ( "aleatorio", aleatorio (0, 100))si ( aleatorio < 1 )set ( "nextX", 0)set ( "nextY", 0.16 * y)finaldemássi ( aleatorio < 86 )conjunto ( "siguienteX", 0,85 * x + 0,04 * y)conjunto ( "siguienteY", -0.04 * x + 0.85 * y + 1.6)finaldemássi ( aleatorio < 93 )set ( "nextX", 0.2 * x - 0.26 * y)set ( "nextY", 0.23 * x + 0.22 * y + 1.6)finaldemásconjunto ( "siguienteX", -0,15 * x + 0,28 * y)establecer ( "nextY", 0.26 * x + 0.24 * y + 0.44)finalfinalfinalset ( "x", nextX)set ( "y", nextY)finalconfiguración ()mientras ( cierto )drawPoint ()nextPoint ()final
TSQL
/ * tabla de resultados * / declare @ fern table ( Fun int , X float , Y float , Seq int identity ( 1 , 1 ) clave principal , DateAdded datetime default getdate ()) declare @ i int = 1 / * iteraciones * / declare @ fun int / * función aleatoria * /declare @ x float = 0 / * inicializa X = 0 * / declare @ y float = 0 / * inicializa Y = 0 * / declara @ rand float inserta en @ fern ( Fun , X , Y ) valores ( 0 , 0 , 0 ) / * establecer el punto de partida * /while @ i < 5000 / * ¿cuántos puntos? * / comenzarestablecer @ rand = rand ()seleccione @ Fun = case / * obtenga la función aleatoria para usar - @fun = f1 = 1%, f2 = 85%, f3 = 7%, f4 = 7% * / when @ rand <= 0 . 01 luego 1 cuando @ rand <= 0 . 86 luego 2 cuando @ rand <= 0 . 93 luego 3 cuando @ rand <= 1 luego 4 finalseleccionar top 1 @ X = X , @ Y = Y de @ fern order by Seq desc / * obtener el punto anterior * /insert into @ fern ( Fun , X , Y ) / * transform usando cuatro expresiones de función diferentes * / select @ fun , case @ fun cuando 1 luego 0 cuando 2 luego 0 . 85 * @ x + 0 . 04 * @ y cuando 3 luego 0 . 2 * @ x - 0 . 26 * @ y cuando 4 entonces - 0 . 15 * @ x + 0 . 28 * @ y end X , case @ fun cuando 1 luego 0 . 16 * @ y cuando 2 entonces - 0 . 04 * @ x + 0 . 85 * @ y + 1 . 6 cuando 3 luego 0 . 23 * @ x + 0 . 22 * @ y + 1 . 6 cuando 4 luego 0 . 26 * @ x + 0 . 24 * @ y + 0 . 44 final Yestablecer @ i = @ i + 1 finalseleccione top 5000 * , geografía :: Punto ( Y , X , 4326 ) de @ fern order by newid ()
MATLAB
N = 1000000 ; xy = [ 0 ; 0 ]; helecho = ceros ( N , 2 ); f_1 = [ 0 0 ; 0 0,16] ; f_2 = [ 0,85 0,04 ; - 0,04 0,85 ]; f_3 = [ 0,2 - 0,26 ; 0,23 0,22 ]; f_4 = [ - 0,15 0,28 ; 0,26 0,24 ]; P = muestra aleatoria ( 1 : 4 , N , verdadero , [ 0,01 0,85 0,07 0,07 ]); para i = 2 : N p = P ( i - 1 ) si p == 1 % Vástago xy = f_1 * xy ; elseif p == 2 % Sub-folletos xy = f_2 * xy + [ 0 ; 1,6 ]; elseif p == 3 % Folleto izquierdo xy = f_3 * xy + [ 0 ; 1,6 ]; else % Folleto derecho xy = f_4 * xy + [ 0 ; 0,44 ]; final helecho ( i , 1 ) = xy ( 1 ); helecho ( i , 2 ) = xy ( 2 ); finalclearvars - excepto N helecho % R2008a + % Trazando el helecho% { % Mejor detalle, rendimiento más lento c = linspace (0, 0.35, N - 1); c (final + 1) = 1; mapa de colores (verano (N)); set (mcd, 'Color', 'k', 'posición', [10, 50, 800, 600]); esparcir (helecho (:, 1), helecho (:, 2), 0.1, c, 'o'); set (gca, 'Color', 'k'); %}%% Menos detalles, mejor rendimientoc = linspace ( 1 , 0.2 , N - 1 ); c ( final + 1 ) = 0 ; mapa de colores ( verano ( N ));set ( mcd , 'Color' , 'k' , 'posición' , [ 10 , 50 , 800 , 600 ]); esparcir ( helecho (:, 1 ), helecho (:, 2 ), 0.1 , c , '.' ); set ( gca , 'Color' , 'k' ); %}
Referencias
- ^ a b Fractales en todas partes , Boston, MA: Academic Press, 1993, ISBN 0-12-079062-9
- ^ a b Michael Barnsley , et al. , " " Fractales y superfractales V-variable " " (PDF) . (2,22 MB)
- ^ Fractales en todas partes , tabla III.3, código IFS para un helecho.
- ^ Barnsley, Michael (2000). Fractales por todas partes . Morgan Kaufmann. pag. 86. ISBN 0-12-079069-6. Consultado el 7 de enero de 2010 .
- ^ Weisstein, Eric. "Helecho de Barnsley" . Consultado el 7 de enero de 2010 .
- ^ Otras variedades de helechos con coeficientes proporcionados
- ^ Un generador de helechos Barnsley