[ Bisección ] [ Ejercicio ] [ Analítico ] [ Algoritmo ] [ función ]
..
1. Ejercicio
Referencia: Burden 2.1 ejemplo 1 p38
La ecuación mostrada tiene una raíz en [1,2], ya que f(1)=-5 y f(2)=14 y existe cambio de signo. Muestre los resultados parciales del algoritmo de la bisección con una tolerancia de 0.0001
f(x) = x^3 + 4x^2 -10 =0[ Bisección ] [ Ejercicio ] [ Analítico ] [ Algoritmo ] [función]
..
2. Desarrollo Analítico
El desarrollo del ejercicio tradicionalmente realizado con lápiz, papel y calculadora, muestra el orden y detalle de las operaciones que se pueden traducir a un algoritmo en Python. El objetivo además de desarrollar la comprensión del método, permite en una evaluación observar si el estudiante conoce el método y usa apropiadamente los valores en cada iteración.
iteración 1
a = 1, b=2 c = \frac{a+b}{2} = \frac{1+2}{2} = 1.5 f(1) = (1)^3 + 4(1)^2 -10 = -5 f(1.5) = (1.5)^3 + 4(1.5)^2 -10= 2.37 f(2) = (2)^3 + 4(2)^2 -10 =14cambio de signo a la izquierda
a = 1, b= c = 1.5 tramo = |1.5-1| =0.5iteración 2
a = 1, b=1.5 c = \frac{1+1.5}{2} = 1.25 f(1) = -5 f(1.25) = (1.25)^3 + 4(1.25)^2 -10 = -1.794 f(1.5) = 2.37cambio de signo a la derecha
a = c = 1.25, b=1.5 tramo = |1.5-1.25| = 0.25iteración 3
continuar como tarea.
La tabla resume los valores de las iteraciones
i | a | c | b | f(a) | f(c) | f(b) | tramo |
---|---|---|---|---|---|---|---|
1 | 1 | 1.5 | 2 | -5 | 2.37 | 14 | 0.5 |
2 | 1 | 1.25 | 1.5 | -5 | -1.79 | 2.37 | 0.25 |
3 | 1.25 | … | 1.5 |
La misma tabla se puede realizar con un algoritmo para tener los resultados más rápido y observar el comportamiento del método.
Observe los resultados de f(c), principalmente en la iteración i=9 con tramo=0.00097 que representa el error de estimación del valor vs tolerancia.
i ['a', 'c', 'b'] ['f(a)', 'f(c)', 'f(b)'] tramo 0 [1, 1.5, 2] [-5. 2.375 14. ] 0.5 1 [1, 1.25, 1.5] [-5. -1.7969 2.375 ] 0.25 2 [1.25, 1.375, 1.5] [-1.7969 0.1621 2.375 ] 0.125 3 [1.25, 1.3125, 1.375] [-1.7969 -0.8484 0.1621] 0.0625 4 [1.3125, 1.34375, 1.375] [-0.8484 -0.351 0.1621] 0.03125 5 [1.34375, 1.359375, 1.375] [-0.351 -0.0964 0.1621] 0.015625 6 [1.359375, 1.3671875, 1.375] [-0.0964 0.0324 0.1621] 0.0078125 7 [1.359375, 1.36328125, 1.3671875] [-0.0964 -0.0321 0.0324] 0.00390625 8 [1.36328125, 1.365234375, 1.3671875] [-3.2150e-02 7.2025e-05 3.2356e-02] 0.001953125 9 [1.36328125, 1.3642578125, 1.365234375] [-3.2150e-02 -1.6047e-02 7.2025e-05] 0.0009765625 raíz en: 1.3642578125 >>>
Se realiza la gráfica los puntos [c,f(c)] de la tabla para observar el resultado, resaltando que los puntos al final se aglomeran alrededor de la solución o raíz de la ecuación.
[ Bisección ] [ Ejercicio ] [ Analítico ] [ Algoritmo ] [función]
..
3. Algoritmo en Python
El video presenta el desarrollo básico conceptual del algoritmo en Python para una comprensión del proceso paso a paso.
Instrucciones en Python del Algoritmo básico del video
# Algoritmo de Bisección # [a,b] se escogen de la gráfica de la función # error = tolera import numpy as np import matplotlib.pyplot as plt # INGRESO fx = lambda x: x**3 + 4*x**2 - 10 a = 1 b = 2 tolera = 0.001 # PROCEDIMIENTO tramo = b-a while not(tramo<tolera): c = (a+b)/2 fa = fx(a) fb = fx(b) fc = fx(c) cambia = np.sign(fa)*np.sign(fc) if cambia < 0: a = a b = c if cambia > 0: a = c b = b tramo = b-a # SALIDA print(' raiz en: ', c) print('error en tramo: ', tramo)
[ Bisección ] [ Ejercicio ] [ Analítico ] [ Algoritmo ] [función]
4. Algoritmo en Python como función
El algoritmo presentado en el video se puede mejorar, por ejemplo simplificando los dos condicionales en uno.
if (cambia<0): b = c fb = fc else: a = c fa = fc
Considere que en cada iteración, se evalúa la función en tres puntos, fa y fb se calculan en la iteración anterior. Se puede optimizar sustituyendo los valores de los extremos y solo evaluando el centro fc.
fa = fx(a) fb = fx(b) tramo = np.abs(b-a) itera = 0 ... while (tramo>=tolera and itera<=iteramax): c = (a+b)/2 fc = fx(c) cambia = np.sign(fa)*np.sign(fc)
Para el desarrollo con lápiz y papel sería necesario observar los valores calculados en cada iteración, por lo que se añade una variable «vertabla» para activar las instrucciones que muestran los cálculos en cada iteración.
if vertabla==True: print('método de Bisección') print('i', ['a','c','b'],[ 'f(a)', 'f(c)','f(b)']) print(' ','tramo') np.set_printoptions(precision)
Se incluye validar que el intervalo disponga de fa y fb con signos opuestos, antes de intentar usar el algoritmo
if cambia<0: # existe cambio de signo f(a) vs f(b)
Finalmente se puede convertir el procedimiento en una función de Python.
Algoritmo en Python como función
# Algoritmo de Bisección # [a,b] se escogen de la gráfica de la función # error = tolera import numpy as np def biseccion(fx,a,b,tolera,iteramax = 50, vertabla=False, precision=4): ''' Algoritmo de Bisección Los valores de [a,b] son seleccionados desde la gráfica de la función error = tolera ''' fa = fx(a) fb = fx(b) tramo = np.abs(b-a) itera = 0 cambia = np.sign(fa)*np.sign(fb) if cambia<0: # existe cambio de signo f(a) vs f(b) if vertabla==True: print('método de Bisección') print('i', ['a','c','b'],[ 'f(a)', 'f(c)','f(b)']) print(' ','tramo') np.set_printoptions(precision) while (tramo>=tolera and itera<=iteramax): c = (a+b)/2 fc = fx(c) cambia = np.sign(fa)*np.sign(fc) if vertabla==True: print(itera,[a,c,b],np.array([fa,fc,fb])) if (cambia<0): b = c fb = fc else: a = c fa = fc tramo = np.abs(b-a) if vertabla==True: print(' ',tramo) itera = itera + 1 respuesta = c # Valida respuesta if (itera>=iteramax): respuesta = np.nan else: print(' No existe cambio de signo entre f(a) y f(b)') print(' f(a) =',fa,', f(b) =',fb) respuesta=np.nan return(respuesta) # INGRESO fx = lambda x: x**3 + 4*x**2 - 10 a = 1 b = 2 tolera = 0.001 # PROCEDIMIENTO respuesta = biseccion(fx,a,b,tolera,vertabla=True) # SALIDA print('raíz en: ', respuesta)
La gráfica se puede obtener añadiendo las siguientes instrucciones:
# GRAFICA import matplotlib.pyplot as plt muestras = 21 xi = np.linspace(a,b,muestras) fi = fx(xi) plt.plot(xi,fi, label='f(x)') plt.axhline(0) plt.xlabel('x') plt.ylabel('f(x)') plt.grid() plt.legend() plt.show()
5. Función en librería Scipy.optimize.bisect
El método de la bisección se encuentra también implementado en las librería Scipy, que también puede ser usado de la forma:
>>> import scipy.optimize as opt
>>> fx = lambda x: x**3 + 4*x**2 - 10
>>> opt.bisect(fx,1,2,xtol=0.001)
1.3642578125
que es el resultado de la raíz para la última iteración del ejercicio. Lo que muestra que el algoritmo realizado tiene un valor más aproximado.
Sin embargo por didáctica y mejor comprensión de los métodos y su implementación en algoritmos que es parte del objetivo de aprendizaje, se continuará desarrollando la forma básica y detallada con Python.
Referencia: https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.bisect.html
[ Bisección ] [ Ejercicio ] [ Analítico ] [ Algoritmo ] [función]