En esta ocasión empezaremos a implementar un método para obtener una raiz real de una ecuación no lineal. Este método se le conoce como punto fijo, pero la variante especificamente que implementaremos ahora es la de aproximaciones sucesivas.
Tenemos un polinomio $f(x) = 2 x^2 - x - 5$ y un valor inicial $x_0 = 1$ y queremos saber cuales son sus raices reales. Lo primero que tenemos que hacer es pasarlo a la siguiente forma:
$$x = g(x)$$Podemos notar que hay muchas maneras de hacer esto, como por ejemplo:
Pero no todas estas formas nos proveerán de un calculo que converja hacia la solución, por lo que tenemos que analizar la convergencia de cada una, hasta que encontremos una que nos acomode.
Sabemos que si el valor absoluto de la primera derivada de $g(x)$ es menor a 1, $\left| g'(x) < 1 \right|$, converjerá adecuadamente, por lo que esto es lo que analizaremos ahora:
De aqui podemos ver que $g_1'(x_0) = 4$, por lo que no converjerá a la solución. $g_2'(x_0) = \frac{1}{2\sqrt{12}}$ en cambio, si nos da un numero menor a 1, por lo que es indicada para hacer iteraciones.
In [ ]:
from numpy import sqrt
In [ ]:
1/(2*sqrt(12))
Entonces ya tenemos una formula para iterar a través:
$$x_1 = g(x_0)$$es decir:
$$x_1 = \sqrt{\frac{x_0 + 5}{2}}$$
In [ ]:
x_0 = 1
g = lambda x: sqrt((x+5)/2)
x_1 = g(x_0)
x_1
Y ya tenemos la primera iteración. Cuando dejaremos de iterar? Cuando el error $\varepsilon = x_1 - x_0$ sea menor a $0.001$ (para este ejemplo).
In [ ]:
abs(x_1 - x_0)
Como podemos ver, aun falta mucho... pero podemos decirle a la computadora que lo siga haciendo sin notsotros. Primero creamos una funcion que itere la funcion g hasta que la diferencia de las ultimas iteraciones sea menor al error.
In [ ]:
def aprox_sucesivas(g, x0, error):
xs = [x0]
while True:
xs.append(g(xs[-1]))
if abs(xs[-1] - xs[-2]) <= error:
return xs[-1]
Y ahora le damos a esta funcion nuestra $g(x)$, el punto donde queremos que inicie $x_0$ y el error maximo permitido.
In [ ]:
r = aprox_sucesivas(g, 0, 0.001)
r
In [ ]:
from numpy import sin
Creamos una funcion en codigo, que contiene la función original, para evaluar que tan bien se aproximo la raiz.
In [ ]:
f = lambda x: 2*x**2 - x - 5
In [ ]:
f(r)
Y como podemos ver hizo un muy buen trabajo sin nuestra supervision :)