Está en la página 1de 9

Subrutinas en Fortran 95 para la resolucin de ecuaciones de una variable

Pablo Santamara v0.1 (Junio 2009)

1.

Introduccin

En general, las races de una ecuacin no lineal f (x) = 0 no pueden ser obtenidas por frmulas explcitas cerradas, con lo que no es posible obtenerlas en forma exacta. De este modo, para resolver la ecuacin nos vemos obligados a obtener soluciones aproximadas a travs de algn mtodo numrico. Estos mtodos son iterativos, esto es, a partir de una o ms aproximaciones iniciales para la raz, generan una sucesin de aproximaciones x0 , x1 , x2 , . . . que esperamos convergan al valor de la raz buscada. El proceso iterativo se contina hasta que la aproximacin se encuentra prxima a la raz dentro de una tolerancia > 0 preestablecida. Como la raz no es conocida, dicha proximidad, medida por el error absoluto |xn+1 |, no puede ser computada. Sin un conocimiento adicional de la funcin f (x) o su raz, el mejor criterio para detener las iteraciones consiste en proceder hasta que la desigualdad |xn+1 xn | < |xn+1 | se satisfaga, dado que esta condicin estima en cada paso el error relativo. Ahora bien, puede ocurrir en ciertas circunstancias que la desigualdad anterior nunca se satisfaga, ya sea por que la sucesin de aproximaciones diverge o bien que la tolerancia escogida no es razonable. En tal caso el mtodo iterativo no se detiene nunca. Para evitar este problema consideramos adems un nmero mximo de iteraciones a realizarse. Si este nmero es excedido entonces el problema debe ser analizado con ms cuidado. Cmo se escoge un valor correcto para las aproximaciones iniciales requeridas por los mtodos? No existe una respuesta general para esta cuestin. Para el mtodo de biseccin es suciente conocer un intervalo que contenga la raz, pero para el mtodo de Newton, por ejemplo, la aproximacin tiene que estar sucientemente cercana a la raz para que funcione 1 . En cualquier caso primeras aproximaciones iniciales para las races pueden ser obtenidas gracando la funcin f (x). En las siguientes secciones presentamos implementaciones de los mtodos numricos usuales como subrutinas Fortran. Con el n de proporcionar subrutinas de propsito general, las mismas tienen entre sus argumentos a la funcin f involucrada, la cual pude ser entonces implementada por el usuario como un subprograma FUNCTION externo con el nombre que quiera. Otros argumentos que requieren estas subrutinas son los valores para las aproximaciones iniciales que necesite el mtodo, una tolerancia para la aproximacin nal de la raz y un nmero mximo de iteraciones. La raz aproximada es devuelta en otro de los argumentos. Dado que el mtodo puede fallar utilizamos tambin una variable entera como clave de error para advertir al programa principal. Por convencin tomaremos que si dicha clave es igual a cero, entonces el mtodo funcion correctamente y el valor devuelto es la raz aproximada dentro de la tolerancia preescrita. En cambio, si la clave de
1 De hecho, efectuando algunas iteraciones del mtodo de biseccin podemos obtener una buena aproximacin para iniciar el mtodo de Newton.

error es distinta de cero, entonces ocurri un error. La naturaleza del error depender del mtodo, pero un error comn a todos ellos es que el nmero mximo de iteraciones fue alcanzado. Con el n de aprovechar la capacidad de Fortran 95 de detectar errores de tipo en los argumentos al llamar a las subrutinas, debemos hacer explcita la interface de las mismas. La forma ms simple y poderosa de efectuar sto consiste en agrupar las mismas en un mdulo, al que denominaremos roots. En nuestra implementacin todas las cantidades reales sern de la clase de doble precisin, la cual, para mxima exibilidad, est denida en forma paramtrica utilizando el modulo precision2 , el cual, por completitud en la exposicin, incluimos a continuacin junto con el esquema de nuestro mdulo roots.
MODULE precision IMPLICIT NONE INTEGER, PARAMETER :: SP = SELECTED_REAL_KIND(6,37) INTEGER, PARAMETER :: DP = SELECTED_REAL_KIND(15,307) END MODULE precision MODULE roots CONTAINS SUBROUTINE biseccion(f,a,b,n,tol,raiz,clave) .... END SUBROUTINE biseccion SUBROUTINE newton(f,df,x0,n,tol,raiz,clave) .... END SUBROUTINE newton SUBROUTINE birge_vieta(a,m,x0,n,tol,raiz,clave) .... END SUBROUTINE birge_vieta SUBROUTINE secante(f,x0,x1,n,tol,raiz,clave) .... END SUBROUTINE secante SUBROUTINE punto_fijo(f,x0,n,tol,raiz,clave) .... END SUBROUTINE punto_fijo END MODULE roots

El cdigo correspondiente a cada subrutina, que debe insertarse donde se encuentran los puntos suspensivos, ser discutido por separado en las siguientes secciones.

2.

Mtodo de biseccin

El mtodo de biseccin comienza con un intervalo [a, b ] que contiene a la raz. Entonces se computa el punto medio x0 = (a + b)/2 del mismo y se determina en cual de los dos subintervalos [a, x0 ] o [x0 , b ] se encuentra la raz analizando el cambio de signo de f (x) en los extremos. El procedimiento se vuelve a repetir con el nuevo intervalo as determinado.
2 La discusin sobre el uso de este mdulo se encuentra en el apunte Un mdulo para parametrizar las clases de tipos de datos reales.

Es claro que la raz es acotada en cada paso por el intervalo as generado y que una estimacin del error cometido en aproximar la raz por el punto medio de dicho intervalo es igual a la mitad de la longitud del mismo. Esta estimacin es utilizada, en la siguiente implementacin del mtodo, como criterio de paro para la sucesin de aproximaciones.
SUBROUTINE biseccion(f,a,b,n,tol,raiz,clave) ! --------------------------------------------------! METODO DE BISECCION para encontrar una solucin ! de f(x)=0 dada la funcin continua f en el intervalo ! [a,b] donde f(a) y f(b) tienen signos opuestos. ! --------------------------------------------------! Bloque de declaracin de argumentos ! --------------------------------------------------USE precision, WP => DP IMPLICIT NONE INTERFACE FUNCTION f(x) ! Funcin que define la ecuacin USE precision, WP => DP IMPLICIT NONE REAL(WP) :: f REAL(WP), INTENT(IN) :: x END FUNCTION f END INTERFACE REAL(WP), INTENT(IN) :: a ! Extremo izquierdo del intervalo inicial REAL(WP), INTENT(IN) :: b ! Extremo derecho del intervalo inicial INTEGER, INTENT(INOUT) :: n ! Nmero mximo de iteraciones/ iteraciones realizadas REAL(WP), INTENT(IN) :: tol ! Tolerancia para el error absoluto REAL(WP), INTENT(OUT) :: raiz ! Aproximacin a la raiz INTEGER, INTENT(OUT) :: clave ! Clave de xito: ! 0 : xito ! >0 : iteraciones excedidas ! <0 : no se puede proceder (f de igual signo en a y b) ! --------------------------------------------------! Bloque de declaracin de variables locales ! --------------------------------------------------INTEGER :: i REAL(WP) :: xl, xr, signfxl, error ! --------------------------------------------------! Bloque de procesamiento ! --------------------------------------------------xl = a xr = b signfxl = SIGN(1.0_WP,f(xl)) IF (signfxl*f(xr) > 0.0_WP) THEN clave = -1 RETURN ENDIF DO i=1,n error = (xr-xl)*0.5_WP raiz = xl + error IF (error < tol) THEN clave = 0 n = i RETURN ENDIF IF (signfxl*f(raiz) > 0.0_WP) THEN xl = raiz ELSE

xr = raiz ENDIF ENDDO clave = 1 RETURN END SUBROUTINE biseccion

3.

Mtodo de NewtonRaphson

El mtodo de Newton comienza con una aproximacin inicial x0 dada, a partir de la cual se genera la sucesin de aproximaciones x1 , x2 , . . ., siendo xn+1 la abscisa del punto de interseccin del eje x con la recta tangente a f (x) que pasa por el punto (xn , f (xn )). Esto conduce a la frmula de iteracin f (xn ) , n = 1, 2, . . . xn+1 = xn f (xn ) Nuestra implementacin de la subrutina correspondiente requiere que se pase tambin como argumento no slo la funcion f (x), sino tambin su derivada f (x), la cual debe ser implementada por el usuario, al igual que f (x), como una FUNCTION.
SUBROUTINE newton(f,df,x0,n,tol,raiz,clave) ! --------------------------------------------------! Metodo DE NEWTON-RAPHSON para encontrar una ! solucin de f(x)=0 dada la funcin derivable ! f y una aproximacin inicial x0. ! --------------------------------------------------! Bloque de declaracin de argumentos ! --------------------------------------------------USE precision, WP => DP IMPLICIT NONE INTERFACE FUNCTION f(x) ! Funcin que define la ecuacin USE precision, WP => DP IMPLICIT NONE REAL(WP) :: f REAL(WP), INTENT(IN) :: x END FUNCTION f FUNCTION df(x) ! Derivada de la funcin que define la ecuacin USE precision, WP => DP IMPLICIT NONE REAL(WP) :: df REAL(WP), INTENT(IN) :: x END FUNCTION df END INTERFACE REAL(WP), INTENT(IN) :: x0 ! Aproximacin inicial a la raz INTEGER, INTENT(INOUT) :: n ! Nmero mximo de iteraciones/ iteraciones realizadas REAL(WP), INTENT(IN) :: tol ! Tolerancia para el error relativo REAL(WP), INTENT(OUT) :: raiz ! Aproximacin a la raiz INTEGER, INTENT(OUT) :: clave ! Clave de xito: ! 0 : xito ! >0 : iteraciones excedidas ! --------------------------------------------------! Declaracin de variables locales ! --------------------------------------------------INTEGER :: i REAL(WP) :: xx0

! --------------------------------------------------! Bloque de procesamiento ! --------------------------------------------------xx0 = x0 DO i=1,n raiz = xx0 - f(xx0)/df(xx0) IF (ABS((raiz-xx0)/raiz) < tol) THEN clave = 0 n = i RETURN ENDIF xx0 = raiz END DO clave = 1 RETURN END SUBROUTINE newton

4.

Mtodo de Newton para ecuaciones algebraicas

En el caso particular en que f (x) es un polinomio, el mtodo de Newton puede ser ecientemente implementado si la evaluacin de f (xn ) (y su derivada) es realizada por el mtodo iterativo de Horner. En efecto, supongamos que f (x) es un polinomio de grado m: f (x) = a0 + a1 x + a2 x2 + + am xm , la evaluacin de f (xn ) por la regla de Horner procede computando bm = am bk = ak + bk+1 xn siendo, entonces b0 = f (xn ), en tanto que f (xn ) es computada haciendo cm = bm ck = bk + ck+1 xn siendo, entonces c1 = f (xn ). El mtodo de Newton se reduce as a xn+1 = xn b0 c1

k = m 1, . . . , 0

k = m 1, . . . , 1

El procedimiento resultante se conoce a menudo como mtodo de BirgeVieta. Nuestra implementacin en la siguiente subrutina pasa los coecientes del polinomio en un arreglo a de (m+1) componentes, siendo m el grado del polinomio (valor que tambin es requerido como argumento). En la subrutina, para simplicar el tratamiento de los subndices, el arreglo es declarado con el ndice inferior 0, no 1, de manera que a(0) = a0 , a(1) = a1 , . . . , a(M ) = am .
SUBROUTINE birge_vieta(a,m,x0,n,tol,raiz,clave) ! --------------------------------------------------! METODO DE BIRGE-VIETA para resolver ECUACIONES ! ALGEBRAICAS: P (x) = 0 donde P es un polinomio de

! grado m de coeficientes reales. ! El mtodo se basa en el mtodo de Newton-Raphson ! implementando el esquema de Horner para la evalua! cin del polinomio y su derivada. ! --------------------------------------------------! Bloque de declaracin de argumentos ! --------------------------------------------------USE precision, WP => DP IMPLICIT NONE INTEGER, INTENT(IN) :: m ! Grado del polinomio REAL(WP), DIMENSION(0:m), INTENT(IN) :: a ! Vector de m+1 elementos conteniendo ! los coeficientes del polinomio REAL(WP), INTENT(IN) :: x0 ! Aproximacin inicial a la raz REAL(WP), INTENT(IN) :: tol ! Tolerancia para el error absoluto INTEGER, INTENT(INOUT) :: n ! Max. iteraciones/iteraciones realizadas REAL(WP), INTENT(OUT) :: raiz ! Aproximacin a la raiz INTEGER, INTENT(OUT) :: clave ! Clave de xito: ! 0 : xito ! >0 : iteraciones excedidas ! --------------------------------------------------! Bloque de declaracin de variables locales ! --------------------------------------------------INTEGER :: i, j REAL(WP):: xx0,b,c ! --------------------------------------------------! Bloque de procedimiento ! --------------------------------------------------xx0 = x0 DO i=1,n ! ------------------------! Esquema de Horner ! ------------------------b = a(m) c = a(m) DO j=m-1,1,-1 b = b*xx0+a(j) c = c*xx0+b ENDDO b = b*xx0+a(0) ! ------------------------! Mtodo de Newton ! ------------------------raiz = xx0 - b/c IF (ABS((raiz-xx0)/raiz) < tol) THEN clave = 0 n = i RETURN END IF xx0 = raiz END DO clave = 1 RETURN END SUBROUTINE birge_vieta

5.

Mtodo de la secante

El mtodo de la secante procede a partir de dos aproximaciones iniciales obteniendo la aproximacin xn+1 como la abscisa del punto de interseccin del eje x con la recta secante que pasa por los puntos (xn1 , f (xn1 )) y (xn , f (xn )). La frmula de iteracin es entonces xn+1 = xn f (xn ) (xn xn1 ) , f (xn ) f (xn1 ) n = 2, 3, . . .

El mtodo de la secante, si bien no converge tan rpido como Newton, tiene la gran ventaja de no requerir la derivada de la funcin. Eso s, ahora se necesitan dos aproximaciones iniciales para arrancar el mtodo.
SUBROUTINE secante(f,x0,x1,n,tol,raiz,clave) ! --------------------------------------------------! ALGORITMO DE LA SECANTE para encontrar una solucin ! de f(x)=0, siendo f una funcin continua, dada las ! aproximaciones iniciales x0 y x1. ! --------------------------------------------------! Bloque de declaracin de argumentos ! --------------------------------------------------USE precision, WP => DP IMPLICIT NONE INTERFACE FUNCTION f(x) ! Funcin que define la ecuacin USE precision, WP => DP IMPLICIT NONE REAL(WP) :: f REAL(WP), INTENT(IN) :: x END FUNCTION f END INTERFACE REAL(WP), INTENT(IN) :: x0,x1 ! Aproximaciones iniciales a la raz INTEGER, INTENT(INOUT) :: n ! Nmero mximo de iteraciones/ iteraciones realizadas REAL(WP), INTENT(IN) :: tol ! Tolerancia para el error relativo REAL(WP), INTENT(OUT) :: raiz ! Aproximacin a la raiz INTEGER, INTENT(OUT) :: clave ! Clave de xito: ! 0 : xito ! >0 : iteraciones excedidas ! --------------------------------------------------! Bloque de declaracin de variables locales ! --------------------------------------------------INTEGER :: i REAL(WP):: xx0, xx1, fx0, fx1 ! --------------------------------------------------! Bloque de procesamiento ! --------------------------------------------------xx0 = x0 xx1 = x1 fx0 = f(x0) fx1 = f(x1) DO i= 2,n raiz = xx1 - fx1*((xx1-xx0)/(fx1-fx0)) IF (ABS((raiz-xx1)/raiz) < tol) THEN clave = 0 n = i RETURN ENDIF

xx0 = xx1 fx0 = fx1 xx1 = raiz fx1 = f(raiz) END DO clave = 1 RETURN END SUBROUTINE secante

6.

Iteracin de punto jo
El mtodo de punto jo requiere que se reescriba la ecuacin f (x) = 0 en la forma x = (x)

y entonces, a partir de una aproximacin inicial x0 , se obtiene la sucesin de aproximaciones x1 , x2 , ... segn xn+1 = (xn ), n = 1, 2, . . . En la siguiente implementacin, es importante recordar que la funcin que es pasada por argumento es ahora (x) y no f (x), funcin que debe ser implementada por el usuario como una FUNCTION.
SUBROUTINE punto_fijo(f,x0,n,tol,raiz,clave) ! --------------------------------------------------! ALGORITMO DE PUNTO FIJO o DE APROXIMACIONES SUCESIVAS ! para encontrar una solucin de x=f(x) dada una ! aproximacin inicial x0. ! --------------------------------------------------! Bloque de declaracin de argumentos ! --------------------------------------------------USE precision, WP => DP IMPLICIT NONE INTERFACE FUNCTION f(x) ! Funcin que define la ecuacin USE precision, WP => DP IMPLICIT NONE REAL(WP) :: f REAL(WP), INTENT(IN) :: x END FUNCTION f END INTERFACE REAL(WP), INTENT(IN) :: x0 ! Aproximacin inicial a la raz INTEGER, INTENT(INOUT) :: n ! Nmero mximo de iteraciones/ iteraciones realizadas REAL(WP), INTENT(IN) :: tol ! Tolerancia para el error relativo REAL(WP), INTENT(OUT) :: raiz ! Aproximacin a la raiz INTEGER, INTENT(OUT) :: clave ! Clave de xito: ! 0 : xito ! >0 : iteraciones excedidas ! --------------------------------------------------! Bloque de declaracin de variables locales ! --------------------------------------------------INTEGER :: i REAL(WP) :: xx0 ! --------------------------------------------------! Bloque de procesamiento ! ---------------------------------------------------

xx0 = x0 DO i=1,n raiz = f(xx0) IF (ABS((raiz-xx0)/raiz) < TOL) THEN clave = 0 n = i RETURN ENDIF xx0 = raiz END DO clave = 1 RETURN END SUBROUTINE punto_fijo

También podría gustarte