In [1]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
Este metodo tiene las siguientes hipotesis:
Bajo estas condiciones se asegura que siempre existe al menos una raiz de $f$ en $[a, b]$ gracias al Teorema de Valor Intermedio.
El algoritmo para el metodo de la biseccion sigue de la siguiente manera:
$$ a_{n}, b_{n} \\ p_{n} = \frac{a_{n}+b_{n}}{2} \\ \Bigg\{ \begin{array}{c} g(a_n)\cdot g(p_n) > 0 \rightarrow a_{n+1} = p_{n} \\ g(b_n)\cdot g(p_n) < 0 \rightarrow a_{n+1} = p_{n} \end{array} \\ \Bigg\{ \begin{array}{c} g(a_n)\cdot g(p_n) < 0 \rightarrow b_{n+1} = p_{n} \\ g(b_n)\cdot g(p_n) > 0 \rightarrow b_{n+1} = p_{n} \end{array} $$En palabras:
In [2]:
def bisection(f, a, b, eps=1e-5):
'''
Bisection busca la raiz de la funcion f a traves del metodo de la biseccion.
Parameters
----------
f : function
Funcion a evaluar.
a : int or double
Valor inical del intervalo.
b : int or double
Valor final del intervalo.
eps : int or double
Tolerancia pedida.
Returns
-------
root : float
Cero de la funcion.
Raises
------
ValueError
Cuando a y b tienen el mismo signo.
'''
if a*b > 0:
raise ValueError("a y b deben tener signos opuestos (a={}, b={}).".format(a,b))
root = (a+b)/2.
while abs(root-a)>eps or abs(root-b)>eps:
if f(a)*f(root) < 0:
b = root
else:
a = root
root = (a+b)/2.
return root
In [3]:
x = np.linspace(0, np.pi, 100)
plt.plot(x, np.sin(x), 'b', label='sin(x)')
plt.plot(x, np.cos(x), 'r', label='cos(x)')
plt.xlabel('x [radianes]')
plt.legend()
Out[3]:
In [4]:
def sin_menos_cos(x):
'''
sin_menos_cos calcula la resta entre sin(x) y cos(x).
Parameters
----------
x : int or float
Punto a evaluar la funcion.
Returns
-------
res : float
sin(x)-cos(x).
'''
res = np.sin(x) - np.cos(x)
return res
In [5]:
cero = bisection(sin_menos_cos, 0., 1.5, eps=.1)
plt.plot(x, np.sin(x), 'b', label='sin(x)')
plt.plot(x, np.cos(x), 'r', label='cos(x)')
plt.xlabel('x [radianes]')
plt.axvline(cero, color='g')
plt.legend()
Out[5]:
In [6]:
cero_2 = bisection(sin_menos_cos, 0., 1.5, eps=1e-10)
plt.plot(x, np.sin(x), 'b', label='sin(x)')
plt.plot(x, np.cos(x), 'r', label='cos(x)')
plt.xlabel('x [radianes]')
plt.axvline(cero, color='brown')
plt.axvline(cero_2, color='g')
plt.legend()
Out[6]: