Funciones continuas

Método de la bisección

El método de demostración que hemos utilizado en la prueba del teorema de Bolzano se conoce con el nombre de método de la bisección. La ventaja del método es que puede ser implementado en un ordenador para obtener los ceros de una función de forma aproximada, pero con precisión arbitraria.

La idea esencial es partir de un intervalo en el que la función cambie de signo una única vez y tomando el punto medio de dicho intervalo y uno de los extremos del intervalo anterior, adecuadamente elegido, generar un nuevo intervalo en el que también se produzca un cambio del signo de la función pero cuya longitud sea la mitad.

El siguiente código se ocupa realizar esa construcción a partir de una lista del tipo datos:[f,a,b,error]. En sentido estricto, para esta etapa, el elemento error no es necesario, lo incluimos por comodidad para tareas que realizaremos más tarde.

kill(IntervaloSiguiente)$ /* Definimos las variables locales obtenidas de la lista "datos" */ IntervaloSiguiente(datos):= block([f:datos[1],a:datos[2],b:datos[3],err:datos[4],xm:(datos[2]+datos[3])/2], /* Verificamos que los datos tienen sentido */ if ev(f,x=datos[2])*ev(f,x=datos[3])=0 then print(" se anula en un extremo " ) elseif ev(f,x=datos[2])*ev(f,x=datos[3])>0 then print(" no hay cambio de signo ") /* Comprobamos si el punto medio es el cero */ elseif ev(f,x=xm)=0 then print(" solución exacta ", xm) /* Si no, cambiamos uno de los extremos por el punto medio para el siguiente */ else if (ev(f,x=xm)*ev(f,x=a)<0) then [f,a,xm,err] else [f,xm,b,err] );

Comprobemos el funcionamiento del comando, por ejemplo, en la resolución de la ecuación log(1+x)=cos(x). Para lo cual dibujamos la función adecuada.

plot2d(log(1+x)-cos(x),[x,-1,20]);

Esto nos permite ver que existe un único cero para la función, que corresponde a la solución de la ecuación. Podemos fijar la lista con los datos iniciales, por ejemplo, mediante

datos:[log(1+x)-cos(x),0,2,10^-6];

Y aplicar una vez el proceso de construcción del intervalo siguiente.

IntervaloSiguiente(datos);

En el nuevo intervalo, cuya longitud es la mitad, también se produce un cambio de signo en los extremos (verifíquelo en la gráfica) y puede ser utilizado como punto de partida en una nueva etapa. El proceso puede repetirse cuantas veces se desee, ejecutando el código que aparece a continuación. Ejecútelo unas diez veces para comprobar como van cambiando los resultados.

IntervaloSiguiente(%);

Maxima expresa los extremos de los intervalos como fracciones para evitar errores de redondeo, pero si lo desea puede ver expresado el intervalo en forma decimal, lo cual le permitirá percatarse de cuales son las primeras cifras decimales de la ecuación.

float(%);

En lugar de repetir manualmente varias veces la construcción del intervalo siguiente podemos pedirle a Maxima que haga ese trabajo por nosotros, por ejemplo 20 veces.

datos:[log(1+x)-cos(x),0,2,10^-6]; for i:1 thru 20 do (datos:IntervaloSiguiente(datos))$ print(" la solución está en el intervalo ",float(datos))$

Comprobemos que nos estamos acercando a la solución dibujando la gráfica en el último de los intervalos.

plot2d(%[1],[x,%[2],%[3]]);

¿Cuál es el número adecuado de iteraciones? Eso depende de la precisión que deseemos en la solución y, obviamente, de la longitud del intervalo inicial. Y aunque no es difícil determinarlo podemos hacer que de eso se ocupe Maxima, para ello habíamos incluido en los datos el parámetro "error", que hasta ahora no ha sido utilizado.

biseccionI(datos):=while abs(datos[2]-datos[3])>datos[4] do (print(datos), print(" solución aproximada: ", float((datos[2]+datos[3])/2) ), datos:IntervaloSiguiente(datos)); /* Lo aplicamos a unos datos concretos */ datos:[log(1+x)-cos(x),0,2,10^-6]; biseccionI(datos)$

Una variante de lo anterior, si nos basta con la solución aproximada y no necesitamos tener el detalle de los intervalos, aparece acontinuación.

biseccion(datos):= while abs(datos[2]-datos[3])>=datos[4] do(datos:IntervaloSiguiente(datos), if abs(datos[2]-datos[3])<datos[4] then return (float((datos[2]+datos[3])/2)) ); /* Lo aplicamos a unos datos concretos */ datos:[log(1+x)-cos(x),0,2,10^-6]; biseccion(datos);

El resultado que proporciona el algoritmo construido puede compararse con el que se obtiene mediante el comando find_root implementado en Maxima

find_root(log(1+x)-cos(x),0,2);

Ejercicios

Calcule las soluciones aproximadas de la ecuación x-x^2-log(1+x)

 

Indice