Raíces de una ecuación (II)
Método de las aproximaciones sucesivas
El método de las aproximaciones sucesivas es uno de los procedimientos más importantes y más sencillos de codificar. Supongamos la ecuación
f(x)=0
donde f(x) es una función continua que se desea determinar sus raíces reales. Se sustituye f(x) por la ecuación equivalente
x=g(x)
Se estima el valor aproximado de la raíz x0 y se sustituye en el segundo miembro de la ecuación para obtener x1.
x1=g(x0)
Poniendo x1 como argumento de g(x), obtendremos un nuevo número x2 y así, sucesivamente. Este proceso se puede sintetizar en la fórmula.
xn=g(xn-1)
Si esta secuencia es convergente es decir, tiende hacia un límite, la raíz buscada ξ es
El método de iteración se explica geométricamente mediante el gráfico de la figura. Se dibuja la curva y=g(x), y la recta y=x, bisectriz del primer cuadrante. La abscisa ξ del punto de intersección es la raíz buscada.
Un ejemplo típico, es la de encontrar la raíz de la ecuación x=cos(x)
Para encontrar la raíz, se comienza en el punto cualquiera de abscisa x0 dentro del intervalo (0, π/2), y se traza la línea vertical hasta que interseca la curva, luego, desde este punto, se traza una línea horizontal hasta que se alcanza la recta bisectriz, este punto tendrá por abscisa x1. Se traza de nuevo, una línea vertical hasta encontrar a la curva, y otra línea horizontal hasta encontrar la línea recta, el punto de intersección tiene de abscisa x2 y así, sucesivamente. Como podemos apreciar en la figura, la sucesión x1, x2, x3... tiende hacia la raíz ξ de la ecuación x=cos(x).
Vamos ahora a crear un script para calcular la raíz de la ecuación x=cos(x) en el intervalo 0 a π/2.
Tomamos una aproximación inicial a la raíz x0, en dicho intervalo y aplicamos la fórmula xn=g(xn-1). Su codificación no presenta grandes dificultades.
x=input ('valor inicial: '); iter=input('número de iteracciones: '); for i=1:iter; x=cos(x); end disp(x)
En la ventana de comandos corremos el script y obtenemos una aproximación a la raíz buscada después de 100 iteraciones
valor inicial: 0.5 número de iteracciones: 100 0.7391
La condición de finalización
Primero, introducimos el valor inicial x, la primera aproximación, calculamos el valor del coseno de x, el valor devuelto (segunda aproximación), lo guardamos de nuevo en la variable x y repetimos el proceso indefinidamente. El código aunque correcto, necesita terminarse en algún momento, cumpliendo una determinada condición.
Cuando el valor absoluto del cociente entre la diferencia de dos términos consecutivos de la sucesión y uno de los términos, sea menor que cierta cantidad ε.
Este criterio, no es completamente riguroso, pero es un buen punto de partida para el estudio de este método.
Modificamos el script para sustituir el bucle
x0=input ('valor inicial: '); ERROR=0.001; while(1) %bucle que se ejecuta indefinidamente x=cos(x0); if abs((x-x0)/x)<ERROR break end x0=x; end disp(x)
En primer lugar, fijamos el valor de la constante ε o
Regresamos a la ventana de comandos para correr el script y obtenemos una aproximación a la raíz buscada
valor inicial: 0.5 0.7387
El criterio de convergencia
No todas las ecuaciones pueden resolverse por este método, solamente si el valor absoluto de la derivada de la función g(x) en la vecindad de la raíz ξ es menor que la unidad (la pendiente de la recta bisectriz del primer cuadrante es uno). En la figura, podemos ver como es imposible encontrar la solución marcada por un puntito negro en la intersección entre la curva y la recta bisectriz del primer cuadrante, ya que la sucesión xi diverge.
Por ejemplo, la ecuación
x3-x-1=0
tiene una raíz en el intervalo (1, 2) ya que f(1)=-1<0 y f(2)=5>0. Esta ecuación puede escribirse de la forma
x=x3-1
En este caso,
g(x)= x3-1 y su derivada es g'(x)= 3x2
y por tanto,
g'(x)≥3 para 1≤x≤2
en consecuencia, no se cumplen las condiciones de convergencia del proceso de iteración. Si escribimos la ecuación en la forma
como podrá verificar fácilmente el lector, cumple las condiciones de convergencia, obteniéndose rápidamente un valor aproximado de la raíz buscada mediante el procedimiento de iteracción.
Transformamos el script en una función que denominamos
function x=raiz_trascendente(x0, ERROR) while(1) x=cos(x0); if abs((x-x0)/x)<ERROR break end x0=x; end end
En la ventana de comandos probamos la función
>>raiz_trascedente (0.5,0.0001) ans = 0.7391
Vamos a hacer que este código sea independiente de la función x=g(x) cuya raíz queremos calcular. En el capítulo funciones, ya hemos visto que a una función se le pueden pasar diversos tipos de datos.
Modificamos la definición de la función
function x=raiz_trascendente(f,x0,ERROR) while(1) x=f(x0); if abs((x-x0)/x)<ERROR break end x0=x; end end
En la ventana de comandos, definimos la función anónima g(x) y calculamos la raíz de la ecuación trascendente x=g(x).
>> g=@(x) cos(x) >> raiz_trascendente(g,0.5,0.001) ans = 0.7393
Para aplicar el método de las aproximaciones sucesivas hemos de escribir la ecuación f(x)=0 como x=g(x) y deberán además, cumplirse las condiciones de convergencia en el proceso de iteracción.
Ejemplo en el curso de Física
Velocidad límite constante de una gota de agua que cae en el aire
Método de Newton-Raphson
El desarrollo en serie de la función f(x) en el punto x es
Si h es pequeño, podemos despreciar los términos en h2 y superiores. Si x+h es la raíz de la ecuación, entonces f(x+h)=0,
Para calcular la raíz mediante un proceso iterativo de la siguiente forma
Definimos el procedimiento de Newton-Raphson de un modo similar al de las aproximaciones sucesivas
function x=newton_raphson(f,f_prima,x0,ERROR) while(1) x=x0-f(x0)/f_prima(x0); if abs((x-x0)/x)<ERROR break end x0=x; end end
A la función
Consideremos la función f(x)=x-cos(x), cuya derivada es f'(x)=1+sin(x). En la ventana de comandos escribimos
>> func=@(x) x-cos(x); >> func_prima=@(x) 1+sin(x); >> newton_raphson(func,func_prima,0.5,0.0001) ans = 0.7391
En el siguiente ejemplo, vamos a ver como se aproxima gráficamente a la solución.
Sea la función y=x·sin(πx)-exp(-x)
Dibujamos la función en color rojo. Probamos con x0=0.1, trazamos la recta tangente a la curva que pasa por el punto (x0,y0), punto señalado en la gráfica con 0. Esta recta corta al eje X en el punto de abscisa x1. Trazamos la tangente a la curva en el punto (x1,y1), punto señalado en la gráfica con 1. Esta recta corta al eje X en el punto de abscisa x2 y así, sucesivamente.
f=@(x) x.*sin(pi*x)-exp(-x); fp=@(x) sin(pi*x)+x*pi*cos(pi*x)+exp(-x); hold on x=linspace(0,0.8,50); plot(x,f(x),'r') x0=0.1; for i=1:5 x1=x0-f(x0)/fp(x0); h=line([x0,x0],[0,f(x0)],'color','g'); set(h,'lineStyle', '--') line([x1,x0],[0,f(x0)],'color','b') x0=x1; end hold off grid on xlabel('x') ylabel('y') title('Método de Newton-Raphson')
Calculamos la raíz
>> f=@(x) x*sin(pi*x)-exp(-x); >> fp=@(x) sin(pi*x)+x*pi*cos(pi*x)+exp(-x); >> newton_raphson(f,fp,0.1,0.0001) ans = 0.5783
Calculamos la derivada de la función aplicando la definición de derivada
Tomamos un valor estimativo de δ=10-6 que cambiaremos dependiendo del problema. La fórmula de Newton-Raphson se convierte en
function x=newton_raphson_1(f,x0,ERROR) DELTA=1.0e-6; while(1) x=x0-DELTA*f(x0)/(f(x0+DELTA)-f(x0)); if abs((x-x0)/x)<ERROR break end x0=x; end end
A la función
>> func=@(x) x-cos(x); >> newton_raphson_1(func,0.5,0.0001) ans = 0.7391
Ejemplo en el curso de Física
El perfil de una gota de rocío
Disco sobre la superficie del agua
Método de la secante
Este método comienza con dos puntos (x0, f(x0)) y (x1, f(x1)), tales que los signos de f(x0) y f(x1) son opuestos, es decir, f(x0)·f(x1)<0
Se dibuja una línea recta entre los dos puntos cuya ecuación es
El valor de x=x2 para el cual y se aproxima a la raíz buscada es
En la siguiente iteracción, tomamos un intervalo más pequeño comprendido entre x2 y x1 que es donde se encuentra la raíz. Por lo que hacemos x0=x2 y volvemos a calcular un nuevo valor x2 cada vez más próximo a la raíz buscada.
Definimos un nuevo procedimiento denominado
donde m=(an+bn)/2 es el punto medio del intervalo (an, bn) cada vez más pequeño.
O bien, cuando se han completado el bucle, sin que se haya encontrado la raíz emitiendo un mensaje de error.
function x2=secante(f,x0,x1,MAXITER) ERROR=0.0001; for i=1:MAXITER f0=f(x0); f1=f(x1); x2=x0-f0*(x1-x0)/(f1-f0); if (abs(2*(x2-x1)/(x2+x1))<ERROR | abs(2*(x2-x0)/(x2+x0))<ERROR) break; end if f(x2)*f0<0 x1=x2; else x0=x2; end end if(i==MAXITER) error('no se ha encontrado la raiz') end end
A la función
Consideremos la función f(x)=cos(x)-x, en la ventana de comandos escribimos
>> func=@(x) cos(x)-x; >> secante(func,0.5,1,10) ans = 0.7391