Creando fractales con el método de Newton Pablo Santamaría v0.1 (Junio 2009) El método de Newton, ideado por Isacc Newton alrededor de 1670, constituye una de las técnicas numéricas más poderosas para aproximar raíces de una ecuación f (x) = 0. El método comienza con una aproximación inicial x0 para la raíz y genera una sucesión de aproximaciones x1 , x2 , . . . según la fórmula xn+1 = xn − f (xn ) , f 0 (xn ) n = 1, 2, . . . sucesión que converge rápidamente a la raíz si la aproximación inicial se encuentra suficientemente próxima a la misma. Nótese que el método no está restringido a los números reales, sino que, de hecho, puede ser aplicado por igual a funciones sobre el campo complejo. Consideremos en particular la ecuación z 4 − 1 = 0. En el campo real la misma sólo tiene una raíz, a saber, 1. Pero en el campo complejo, la ecuación tiene cuatro raíces: ζ1 = 1, ζ2 = −1, ζ3 = i, ζ4 = −i. Supongamos que, entonces, aplicamos el método de Newton a esta ecuación. En 1876, Arthur Cayley propuso el siguiente problema: dado un valor inicial z0 cualquiera del plano complejo, ¿a cual de las cuatro raíces convergerá el método de Newton? La respuesta a este problema conduce sorprendentemente a una figura de naturaleza fractal. Para ver ésto procederemos como sigue: En el cuadrado [−2, 2 ]×[−2, 2 ] consideramos un gran número de valores iniciales z0 escogidos al azar. Aplicamos el método de Newton a la ecuación z 4 − 1 = 0 para cada valor z0 escogido. Coloreamos el punto z0 en el plano complejo ya sea de rojo, verde, azul o magenta según a que raíz ζ1 , ζ2 , ζ3 o ζ4 , respectivamente, ha convergido el método. Un programa en Fortran 77 para realizar tal procedimiento es dado a continuación. En apuntes anteriores ya hemos implementado el método de Newton en sendas subrutinas de Fortran 77 y Fortran 951 . Llevar tal subrutina al campo complejo no reviste mayor dificultad que reemplazar las correspondientes variables reales por variables complejas. Esto conduce a la siguiente subrutina. * * * * * * SUBROUTINE NEWTON(F,DF,XX0,NMAX,TOL,RAIZ,ICLAVE) --------------------------------------------------METODO DE NEWTON-RAPHSON para encontrar una solución de f(x)=0 dada la función derivable f y una aproximación inicial x0. --------------------------------------------------Bloque de identificación de argumentos 1 Ver los apuntes Subrutinas para la resolución de ecuaciones de una variable o Subrutinas en Fortran 95 para la resolución de ecuaciones de una variable 1 * * * * * * * * * * * * * * * * * * --------------------------------------------------F = Función que define la ecuación (arg entrada) DF = Función derivada de F (arg entrada) XX0 = Aproximación inicial (arg entrada) NMAX = Número máximo de iteraciones (arg entrada) TOL = Tolerancia del error relativo (arg entrada) RAIZ = Estimación de la solución (arg salida) ICLAVE = Clave de éxito (arg salida) 0 = éxito 1 = iteraciones excedidas --------------------------------------------------Bloque de declaración de tipo --------------------------------------------------IMPLICIT NONE INTEGER NMAX, ICLAVE DOUBLE COMPLEX F, DF, XX0, RAIZ DOUBLE PRECISION TOL --------------------------------------------------INTEGER I DOUBLE COMPLEX X0 --------------------------------------------------Bloque de procesamiento --------------------------------------------------ICLAVE = 0 X0 = XX0 DO I=1,NMAX RAIZ = X0 - F(X0)/DF(X0) IF (ABS((RAIZ-X0)/RAIZ).LT.TOL) RETURN X0 = RAIZ END DO ICLAVE = 1 RETURN END --------------------------------------------------- El método de Newton requiere de la función que define a la ecuación y su derivada, las cuales son implementadas en apropiadas FUNCTION complejas. DOUBLE COMPLEX FUNCTION F(Z) IMPLICIT NONE DOUBLE COMPLEX Z F = Z**4 -(1.0D0,0.0D0) RETURN END DOUBLE COMPLEX FUNCTION DF(Z) IMPLICIT NONE DOUBLE COMPLEX Z DF = (4.0D0,0.0D0)*Z**3 RETURN END Finalmente consideremos el programa principal. En el cuadrado de semilado A = 2, conteniendo el origen, generamos NPOINTS = 50 0000 números complejos Z0 = (X0,Y0) como condiciones iniciales para el método de Newton. Para ello utilizamos un generador de números aleatorios, provisto por las subrutinas intrínsecas RANDOM_SEED, que inicializa el generador, y RANDOM_NUMBER, la cual devuelve un número al azar entre 0 y 1. Puesto que nosotros queremos números aleatorios en el rango [-A:A] efectuamos una simple transformación lineal para llevarlos a tal rango. Con el fin de distinguir a cual de las cuatro raíces converge el método creamos cuatro archivos, uno para cada 2 raíz. Entonces dependiendo la solución obtenida con el método de Newton, la condición inicial es guardada en el archivo que corresponde a la raíz a la cual ha convergido. * PROGRAM FRACTAL_NEWTON ------------------------------------------------------------------IMPLICIT NONE INTEGER NROOTS INTEGER NPOINTS INTEGER NMAX REAL A DOUBLE PRECISION TOL PARAMETER (NROOTS = & NPOINTS = & NMAX = & A = & TOL = ! ! ! ! ! 4, 500000, 100, 2.0, 1.0D-8) DOUBLE COMPLEX ROOTS(NROOTS) DATA ROOTS/( 1.0D0, 0.0D0), & (-1.0D0, 0.0D0), & ( 0.0D0, 1.0D0), & ( 0.0D0,-1.0D0)/ * * * * * * * ! Raíces de la ecuación ! 1 ! -1 ! i ! -i INTEGER CLAVE INTEGER UNIDAD INTEGER I,J ! Clave de error de la subrutina Newton ! Número de unidad para archivos de salida DOUBLE COMPLEX F,DF EXTERNAL F,DF ! Funcion y derivada de la ecuación DOUBLE COMPLEX Z0,RAIZ DOUBLE PRECISION X0,Y0 REAL R * * * Número de raíces Número de aproximaciones iniciales Número máximo de iteraciones en Newton Semilado del cuadrado [-A:A][-A:A] Cota para el error relativo en Newton ! Aproximación inicial y solución ! Parte real e imaginaria de la aprox. inicial ! Número al azar entre 0 y 1 CHARACTER(7) ARCHIVO CHARACTER(2) NUMSTRING LOGICAL SEGUIR ------------------------------------------------------------------Crear archivos de salida para cada una de las raíces ------------------------------------------------------------------DO J=1,NROOTS UNIDAD = 10+J WRITE(NUMSTRING,’(I2.2)’) J ARCHIVO = ’raiz-’ // NUMSTRING OPEN(UNIDAD,FILE=ARCHIVO) ENDDO ------------------------------------------------------------------Proceder ------------------------------------------------------------------CALL RANDOM_SEED() ! Inicializar semilla DO I = 1,NPOINTS ---------------------------------------------------------------Construir una aproximación inicial compleja dentro del del cuadrado [-A:A][-A:A] ---------------------------------------------------------------CALL RANDOM_NUMBER(R) X0 = DBLE(-A+2.0*A*R) 3 * * * * * * * * * * CALL RANDOM_NUMBER(R) Y0 = DBLE(-A+2.0*A*R) Z0 = COMPLEX(X0,Y0) ---------------------------------------------------------------Resolver la ecuación con el método de Newton con tal aproximación ---------------------------------------------------------------CLAVE = 0 CALL NEWTON(F,DF,Z0,NMAX,TOL,RAIZ,CLAVE) ---------------------------------------------------------------Imprimir la condición inicial en el archivo correspondiente según la raíz obtenida ---------------------------------------------------------------IF (CLAVE.EQ.0) THEN J = 1 SEGUIR = .TRUE. DO WHILE(SEGUIR.AND.J.LE.NROOTS) IF (ABS(RAIZ-ROOTS(J)).LE.TOL) THEN UNIDAD = 10 + J WRITE (UNIDAD,*) X0, Y0 SEGUIR = .FALSE. ENDIF J = J + 1 ENDDO ENDIF END DO ---------------------------------------------------------------Cerrar archivos de salida y terminar ---------------------------------------------------------------DO J=1,NROOTS UNIDAD = 10+J CLOSE(UNIDAD) END DO STOP END Con los cuatro archivos, raiz-01, raiz-02, raiz-03 y raiz-04, generados por la ejecución del programa, utilizamos las siguientes sentencias en el programa gnuplot para obtener el mapa de aproximaciones. gnuplot> gnuplot> gnuplot> gnuplot> set size square set xrange [-2:2] set yrange [-2:2] plot "raiz-01" w d, "raiz-02" w d, "raiz-03" w d, "raiz-04" w d El resultado obtenido se ilustra en la figura 1. Las amplias regiones de un solo color corresponden a puntos que convergen rápidamente a la respectiva raíz. Pero entre tales áreas de convergencia obtenemos estructuras fractales donde la convergencia no está bien comportada. Estructuras fractales similares resultan para otras ecuaciones. Por ejemplo, la figura 2 ilustra la distribución de √ las aproximaciones iniciales para la ecuación z 3 − 1 = 0, cuyas raíces son 1, −1/2 ± i 3/2. Es fácil generalizar el programa para analizar la convergencia de las aproximaciones iniciales z0 para una ecuación algebraica cualquiera dados los n ceros ζi , i = 1, . . . , n de la misma: f (z) = n Y (z − ζi ) = 0. i=1 En este caso, aplicando la regla de derivación de un producto tenemos que: f 0 (z) = n Y n X X (z − ζj ) = i=1 j6=i i=1 n n X Y 1 1 (z − ζj ) = f (z) (z − ζi ) j=1 (z − ζi ) i=1 4 2 1.5 1 0.5 0 -0.5 -1 -1.5 -2 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 Figura 1. Distribución en el plano complejo de las aproximaciones iniciales z0 para la ecuación z 4 − 1 = 0 según la convergencia por el método de Newton a la raíz ζ1 = 1 (en rojo), ζ2 = −1 (en verde), ζ3 = i (en azul) o ζ4 = −i (en magenta). con lo cual, un paso del método de Newton puede ser calculado en forma simple como: xn+1 X −1 n 1 f (xn ) = xn − . = xn − 0 f (xn ) (xn − ζi ) i=1 De este modo no se requiere especificar la función f ni su derivada, sino que simplemente se necesita especificar los ceros. A continuación presentamos el programa que hace uso de este resultado, donde la subrutina que implementa el método de Newton ha sido modificada para éste propósito. Como caso particular consideramos la ecuación: (z − 3)(z − 2)(z − 1)(z + 1)(z + 2)(z + 3) = 0, (1) la cual tiene 6 raíces. La estructura fractal obtenida, ilustrada en la figura 3, es mucho más pequeña comparada con la estructura general, sin embargo, en los bordes de las zonas de convergencia bien comportada, ésta se presenta nuevamente. * PROGRAM FRACTAL_NEWTON ------------------------------------------------------------------IMPLICIT NONE INTEGER NROOTS INTEGER NPOINTS INTEGER NMAX ! Número de raíces ! Número de aproximaciones iniciales ! Número máximo de iteraciones en Newton 5 2 1.5 1 0.5 0 -0.5 -1 -1.5 -2 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 Figura 2. Distribución en el plano complejo de las aproximaciones iniciales z0 para la ecuación z 3 − 1 = 0 según la convergencia √ por el método de Newton a la √ raíz ζ1 = 1 (en rojo), ζ2 = −1/2 + i 3/2 (en verde) ó ζ3 = −1/2 − i 3/2 (en azul). REAL A DOUBLE PRECISION TOL PARAMETER (NROOTS = & NPOINTS = & NMAX = & A = & TOL = ! Semilado del cuadrado [-A:A][-A:A] ! Cota para el error relativo en Newton 6, 500000, 100, 3.0, 1.0D-8) DOUBLE COMPLEX ROOTS(NROOTS) ! Raíces de la ecuación DATA ROOTS/( 3.0D0, 0.0D0), & ( 2.0D0, 0.0D0), & ( 1.0D0, 0.0D0), & (-1.0D0, 0.0D0), & (-2.0D0, 0.0D0), & (-3.0D0, 0.0D0)/ INTEGER CLAVE INTEGER UNIDAD INTEGER I,J DOUBLE COMPLEX Z0,RAIZ DOUBLE PRECISION X0,Y0 REAL R ! Clave de error de la subrutina Newton ! Número de unidad para archivos de salida ! Aproximación inicial y solución ! Parte real e imaginaria de la aprox. inicial ! Número al azar entre 0 y 1 6 * * * * * * * * * * * * * * * * * * * * CHARACTER(7) ARCHIVO CHARACTER(2) NUMSTRING LOGICAL SEGUIR ------------------------------------------------------------------Crear archivos de salida para cada una de las raíces ------------------------------------------------------------------DO J=1,NROOTS UNIDAD = 10+J WRITE(NUMSTRING,’(I2.2)’) J ARCHIVO = ’raiz-’ // NUMSTRING OPEN(UNIDAD,FILE=ARCHIVO) ENDDO ------------------------------------------------------------------Proceder ------------------------------------------------------------------CALL RANDOM_SEED() ! Inicializar semilla DO I = 1,NPOINTS ---------------------------------------------------------------Construir una aproximación inicial compleja dentro del del cuadrado [-A:A][-A:A] ---------------------------------------------------------------CALL RANDOM_NUMBER(R) X0 = DBLE(-A+2.0*A*R) CALL RANDOM_NUMBER(R) Y0 = DBLE(-A+2.0*A*R) Z0 = COMPLEX(X0,Y0) ---------------------------------------------------------------Resolver la ecuación con el método de Newton con tal aproximación ---------------------------------------------------------------CLAVE = 0 CALL NEWTON(ROOTS,NROOTS,Z0,NMAX,TOL,RAIZ,CLAVE) ---------------------------------------------------------------Imprimir la condición inicial en el archivo correspondiente según la raíz obtenida ---------------------------------------------------------------IF (CLAVE.EQ.0) THEN J = 1 SEGUIR = .TRUE. DO WHILE(SEGUIR.AND.J.LE.NROOTS) IF (ABS(RAIZ-ROOTS(J)).LE.TOL) THEN UNIDAD = 10 + J WRITE (UNIDAD,*) X0, Y0 SEGUIR = .FALSE. ENDIF J = J + 1 ENDDO ENDIF END DO ---------------------------------------------------------------Cerrar archivos de salida y terminar ---------------------------------------------------------------DO J=1,NROOTS UNIDAD = 10+J CLOSE(UNIDAD) END DO STOP 7 END * * * * * * * * * * * * * * * * * * * * * * * * * SUBROUTINE NEWTON(ROOTS,NROOTS,XX0,NMAX,TOL,RAIZ,ICLAVE) --------------------------------------------------METODO DE NEWTON-RAPHSON para encontrar la solución de f(x)=(x -x1)...(x-xN) = 0 dadas los N ceros de la ecuación a la cual conduce la aproximación inicial. --------------------------------------------------Bloque de identificación de argumentos --------------------------------------------------NROOTS = Número de raices (arg entrada) ROOTS(NROOTS) = Vector de raíces (arg entrada) XX0 = Aproximación inicial (arg entrada) NMAX = Número máximo de iteraciones (arg entrada) TOL = Tolerancia del error relativo (arg entrada) RAIZ = Estimación de la solución (arg salida) ICLAVE = Clave de éxito (arg salida) 0 = éxito 1 = iteraciones excedidas --------------------------------------------------Bloque de declaración de tipo --------------------------------------------------IMPLICIT NONE INTEGER NROOTS,NMAX,ICLAVE DOUBLE COMPLEX ROOTS(NROOTS) DOUBLE COMPLEX XX0,RAIZ DOUBLE PRECISION TOL --------------------------------------------------INTEGER I,J DOUBLE COMPLEX X0,SUMA --------------------------------------------------Bloque de procesamiento --------------------------------------------------ICLAVE = 0 X0 = XX0 DO I=1,NMAX SUMA = (0.0D0,0.0D0) DO J = 1,NROOTS SUMA = SUMA + (1.0D0,0.0D0)/(X0 - ROOTS(J)) ENDDO RAIZ = X0 - (1.0D0,0.0D0)/SUMA IF (ABS((RAIZ-X0)/RAIZ).LT.TOL) RETURN X0 = RAIZ END DO ICLAVE = 1 RETURN END --------------------------------------------------- 8 3 2 1 0 -1 -2 -3 -3 -2 -1 0 1 2 3 Figura 3. Distribución en el plano complejo de las aproximaciones iniciales z0 para la ecuación (z − 3)(z − 2)(z − 1)(z + 1)(z + 2)(z + 3) = 0 según la convergencia por el método de Newton a la raíz correspondiente ( 3 en rojo, 2 en verde, 1 en azul, −1 en magenta, −2 cian, −3 amarillo.) 9