Newton-Raphson’s method: tangent lines and quadratic convergence#

Newton and Raphson’s iteration replaces \(f\) by its tangent line at the current guess and steps to where that line crosses zero, \(x_{n+1} = x_n - f(x_n)/f'(x_n)\). This script draws the first tangent steps for \(f(x) = x^3 - 2x - 5\) (the cubic Newton himself used as his example) and shows the number of correct digits roughly doubling at every step, i.e. convergence of order 2.

import matplotlib.pyplot as plt
import numpy as np

from mathematicskit.numerical_analysis import NewtonRaphson, estimate_convergence_order

f = lambda x: x**3 - 2.0 * x - 5.0
fp = lambda x: 3.0 * x**2 - 2.0

result = NewtonRaphson(f, fp, x0=3.0, tol=1e-15).solve()
root = result.root
print(f"root = {root:.15f} after {result.iterations} iterations")
root = 2.094551481542327 after 7 iterations

Tangent-line steps#

x = np.linspace(1.8, 3.2, 400)
fig1, ax1 = plt.subplots(figsize=(7, 4.5))
ax1.axhline(0.0, color="black", lw=0.8)
ax1.plot(x, f(x), color="black", label=r"$f(x) = x^3 - 2x - 5$")
for n, xn in enumerate(result.history[:3]):
    x_next = xn - f(xn) / fp(xn)
    ax1.plot([xn, x_next], [f(xn), 0.0], color="steelblue", lw=1.2)
    ax1.plot([xn, xn], [0.0, f(xn)], ":", color="gray")
    ax1.plot(xn, f(xn), "o", color="steelblue")
    ax1.annotate(f"$x_{n}$", (xn, 0.0), textcoords="offset points", xytext=(0, -14), ha="center")
ax1.set_xlabel("$x$")
ax1.set_title("Newton-Raphson: follow the tangent to its zero")
ax1.legend()
fig1.tight_layout()
Newton-Raphson: follow the tangent to its zero

Correct digits double every step#

err = np.abs(result.history - root)
for n, e in enumerate(err):
    if e > 0:
        print(f"step {n}: error = {e:.2e}  correct digits ~ {-np.log10(e):.1f}")
print(f"empirical order ~ {estimate_convergence_order(result.history[:-1], root):.2f}")

fig2, ax2 = plt.subplots(figsize=(6, 4))
ax2.semilogy(np.where(err == 0, np.nan, err), "o-", color="steelblue")
ax2.set_xlabel("iteration $n$")
ax2.set_ylabel(r"$|x_n - x^*|$")
ax2.set_title("Quadratic convergence: the error exponent doubles")
fig2.tight_layout()

plt.show()
Quadratic convergence: the error exponent doubles
step 0: error = 9.05e-01  correct digits ~ 0.0
step 1: error = 2.65e-01  correct digits ~ 0.6
step 2: error = 3.26e-02  correct digits ~ 1.5
step 3: error = 5.85e-04  correct digits ~ 3.2
step 4: error = 1.92e-07  correct digits ~ 6.7
step 5: error = 2.09e-14  correct digits ~ 13.7
empirical order ~ 1.99

Total running time of the script: (0 minutes 0.081 seconds)

Gallery generated by Sphinx-Gallery