def derivada(f, x_0, delta_x):
    pendiente = (f(x_0 + delta_x) - f(x_0))/delta_x 
    return pendiente

def raiz(f, x_0, delta_x):
    x_1 = x_0 - f(x_0)/derivada(f, x_0, delta_x)
    return x_1

"""
Explanation: Método de la secante modificada
En el método de la secante modificada se calcula la derivada usando diferenciación numérica
\begin{equation}
    f'(x_{i}) \approx \frac{f(x_{i} + \Delta x) - f(x_{i})}{\Delta x}
\end{equation}
se reemplaza en la fórmula del método de Newton-Raphson 
\begin{equation}
    x_{i+1} = x_{i} - \frac{1}{f'(x_{i})} f(x_{i}) = x_{i} - \frac{\Delta x}{f(x_{i} + \Delta x) - f(x_{i})} f(x_{i})
\end{equation}
Algoritmo
x_0 es la raiz aproximada actual
x_1 = x_0 - f(x_0)*(deltax)/f(x_0 + deltax) - f(x_0)
x_2 = x_1 - f(x_1)*(deltax)/f(x_1 + deltax) - f(x_1)
x_3 = x_2 - f(x_2)*(deltax)/f(x_2 + deltax) - f(x_2)
...

Ejemplo 1
Encontrar la raiz de
\begin{equation}
    y = x^{5} + x^{3} + 3
\end{equation}
usar $x = 0$ y $\Delta x = -0.5$ como valores iniciales
Iteración 0
Raíz aproximada
\begin{equation}
    x_{0} = 0
\end{equation}
Error relativo
\begin{equation}
    e_{r} = ? 
\end{equation}
Iteración 1
Raíz aproximada
\begin{equation}
    x_{1} = x_{0} - \frac{\Delta x}{f(x_{0} + \Delta x) - f(x_{0})} f(x_{0}) = 0 - \frac{-0.5}{f(-0.5) - f(0)} f(0) = -9.6
\end{equation}
Error relativo
\begin{equation}
    e_{r} = \bigg|\frac{x_{1} - x_{0}}{x_{1}}\bigg| \times 100\% = \bigg|\frac{-9.6 - 0}{-9.6}\bigg| \times 100\% = 100\% 
\end{equation}
Iteración 2
Raíz aproximada
\begin{equation}
    x_{2} = x_{1} - \frac{\Delta x}{f(x_{1} + \Delta x) - f(x_{1})} f(x_{1}) = -9.6 - \frac{-0.5}{f(-10.1) - f(-9.6)} f(-9.6) = -7.861884
\end{equation}
Error relativo
\begin{equation}
    e_{r} = \bigg|\frac{x_{2} - x_{1}}{x_{2}}\bigg| \times 100\% = \bigg|\frac{-7.861884 - (-9.6)}{-7.861884}\bigg| \times 100\% = 22.11\% 
\end{equation}
Iteración 3
Raíz aproximada
\begin{equation}
    x_{3} = x_{2} - \frac{\Delta x}{f(x_{2} + \Delta x) - f(x_{2})} f(x_{2}) = -7.861884 - \frac{-0.5}{f(-8.361884) - f(-7.861884)} f(-7.861884) = -6.467625
\end{equation}
Error relativo
\begin{equation}
    e_{r} = \bigg|\frac{x_{3} - x_{2}}{x_{3}}\bigg| \times 100\% = \bigg|\frac{-6.467625 - (-7.861884)}{-6.467625}\bigg| \times 100\% = 21.56\% 
\end{equation}
Implementación de funciones auxiliares
Seudocódigo para la derivada
pascal
function derivada(f(x), x_0, delta_x)
    f'(x) = f(x_0 + delta_x) - f(x_0)/delta_x
    return f'(x)
end function
Seudocódigo para obtener la raíz
pascal
function raiz(f(x), x_0, delta_x):
    x_1 = x_0 - f(x_0)/derivada(f(x), x_0, delta_x)
    return x_1
end function
End of explanation
"""


def secante_modificada(f, x_0, delta_x):
    print("{0:s} \t {1:15s} \t {2:15s} \t {3:15s}".format('i', 'x anterior', 'x actual', 'error relativo %'))
    x_actual = x_0
    i = 0
    print("{0:d} \t {1:15s} \t {2:.15f} \t {3:15s}".format(i, '???????????????', x_actual, '???????????????'))
    error_permitido = 0.000001
    while True:
        x_anterior = x_actual
        x_actual = raiz(f, x_anterior, delta_x)
        if x_actual != 0:
            error_relativo = abs((x_actual - x_anterior)/x_actual)*100
        i = i + 1
        print("{0:d} \t {1:.15f} \t {2:.15f} \t {3:15.11f}".format(i, x_anterior, x_actual, error_relativo))
        if (error_relativo < error_permitido) or (i>=20):
            break
    print('\nx =', x_actual)

"""
Explanation: Implementación no vectorizada
Seudocódigo
pascal
function secante_modificada(f(x), x_0, delta_x)
    x_actual = x_0
    error_permitido = 0.000001
    while(True)
        x_anterior = x_actual
        x_actual = raiz(f(x), x_anterior, delta_x)
        if x_raiz_actual != 0
            error_relativo = abs((x_raiz_actual - x_raiz_anterior)/x_raiz_actual)*100
        end if
        if error_relativo &lt; error_permitido
            exit
        end if
    end while
    mostrar x_actual
end function
o también
pascal
function secante_modificada(f(x), x_0, delta_x)
    x_actual = x_0
    for 1 to maxima_iteracion do
        x_anterior = x_actual
        x_actual = raiz(f(x), x_anterior, delta_x)
    end for
    mostrar x_actual
end function
End of explanation
"""


def f(x):
    # f(x) = x^5 + x^3 + 3
    y = x**5 + x**3 + 3
    return y

derivada(f, 0, -0.5)

raiz(f, 0, -0.5)

secante_modificada(f, 0, -0.5)

"""
Explanation: Ejemplo 2
Encontrar la raiz de
\begin{equation}
    y = x^{5} + x^{3} + 3
\end{equation}
usar $x = 0$ y $\Delta x = -0.5$
End of explanation
"""


secante_modificada(f, 0, -1)

"""
Explanation: Ejemplo 3
Encontrar la raiz de
\begin{equation}
    y = x^{5} + x^{3} + 3
\end{equation}
usar $x = 0$ y $\Delta x = -1$
End of explanation
"""


