from numpy import *
from scipy import linalg
from scipy.linalg import norm
from matplotlib.pyplot import *
from prettytable import PrettyTable
from timeit import default_timer as timer
import sys
sys.path.append('fncbook/')
import fncbook as FNC
# This (optional) block is for improving the display of plots.
# from IPython.display import set_matplotlib_formats
# set_matplotlib_formats("svg","pdf")
# %config InlineBackend.figure_format = 'svg'
rcParams["figure.figsize"] = [7, 4]
rcParams["lines.linewidth"] = 2
rcParams["lines.markersize"] = 4
rcParams['animation.html'] = "jshtml" # or try "html5"
From a practical standpoint, one of the biggest drawbacks of Newton’s method is the requirement to supply f′ in Function 4.3.1. It is both a programming inconvenience and a step that requires computational time. We can avoid using f′, however, by making a simple but easily overlooked observation:
Let’s call this the principle of approximate approximation.
In the Newton context, the principle of approximate approximation begins with the observation that the use of f′ is linked to the construction of a linear approximation q(x) equivalent to a tangent line. The root of q(x) is used to define the next iterate in the sequence. We can avoid calculating the value of f′ by choosing a different linear approximation.
The example in Example 4.4.1 demonstrates the secant method. In the secant method, one finds the root of the linear approximation through the two most recent root estimates. That is, given previous approximations x1,…,xk, define the linear model function as the line through (xk−1,f(xk−1)) and (xk,f(xk)):
Graphically, a secant line usually looks like a less accurate model of f than the tangent line. How will that affect the convergence?
As before, let ϵk=xk−r be the errors in the successive root approximations, and assume that r is a simple root. If the initial errors are small, then a lengthy but straightforward Taylor expansion shows that, to lowest order,
for an unknown constant C. Treating the approximation as an equality, this becomes solvable if and only if the exponents match, i.e., α2=α+1. The only positive root of this equation is the golden ratio,
In terms of the error as a function of the iteration number k, the secant method converges at a rate strictly between linear and quadratic, which is slower than Newton’s method. But error versus iteration count may not be the best means of comparison.
Often we analyze rootfinding methods by assuming that the bulk of computing time is spent evaluating the user-defined functions f and f′. (Our simple examples and exercises mostly don’t support this assumption, but many practical applications do.) In this light, we see that Newton’s method requires two evaluations, f(xk) and f′(xk), for each iteration. The secant method, on the other hand, while it uses the two function values f(xk) and f(xk−1) at each iteration, only needs to compute a single new one. Note that Function 4.4.1 keeps track of one previous function value rather than recomputing it.
Now suppose that ∣ϵk∣=δ. Roughly speaking, two units of work (i.e., function evaluations) in Newton’s method brings us to an error of δ2. If one spreads out the improvement in the error evenly across the two steps, using
it seems reasonable to say that the rate of convergence in Newton per function evaluation is 2≈1.41. This is actually less than the comparable rate of about 1.62 for the secant method.
Not only is the secant method easier to apply than Newton’s method in practice, it’s also more efficient—a rare win-win!
At each iteration, the secant method constructs a linear model function that interpolates the two most recently found points on the graph of f. Two points determine a straight line, so this seems like a sensible choice. But as the iteration progresses, why use only the two most recent points? What would it mean to use more of them?
If we interpolate through three points by a polynomial, we get a unique quadratic function. Unfortunately, a parabola may have zero, one, or two crossings of the x-axis, potentially leaving some doubt as to how to define the next root estimate. On the other hand, if we turn a parabola on its side, we get a graph that intersects the x-axis exactly once, which is ideal for defining the next root estimate.
This leads to the idea of defining q(y) as the quadratic interpolant to the points (yk−2,xk−2), (yk−1,xk−1), and (yk,xk), where yi=f(xi) for all i, and setting xk+1=q(0). The process defined in this way (given three initial estimates) is called inverse quadratic interpolation. Rather than deriving lengthy formulas for it here, we demonstrate how to perform inverse quadratic interpolation using fit to perform the interpolation step.
Like Newton’s method, the secant and inverse quadratic interpolation methods cannot guarantee convergence. One final new idea is needed to make a (nearly) foolproof algorithm.
If f is continuous on the interval [a,b] and f(a)f(b)<0—that is, f changes sign on the interval—then f must have at least one root in the interval, due to the Intermediate Value Theorem from calculus. If we come up with a new root estimate c∈(a,b), then whatever sign f(c) is, it is different from the sign at one of the endpoints. (Of course, if f(c) is zero, we are done!) So either [a,c] or [c,b] is guaranteed to have a root too, and in this way we can maintain not just individual estimates but an interval that always contains a root.
The best algorithms blend the use of fast-converging methods with the guarantee provided by a bracket. For example, say that an iteration begins with a bracketing interval. Make a list of the inverse quadratic estimate, the secant estimate, and the midpoint of the current interval, and pick the first member of the list that lies within the current interval. Replace the interval with the bracketing subinterval, and start a new iteration. This is the idea behind Brent’s method, which is a very successful rootfinding algorithm.
For each of Exercises 1–3, do the following steps.
(a) ✍ Rewrite the equation into the standard form for rootfinding, f(x)=0.
(b) ⌨ Make a plot of f over the given interval and determine how many roots lie in the interval.
(c) ⌨ Find a reference value for each root.
(d) ⌨ Determine a bracketing interval for each root. Then use Function 4.4.1, starting with the endpoints of the bracketing interval, to find each root.
(e) ⌨ For one of the roots, use the errors in the resulting sequence to determine numerically whether the convergence is apparently between linear and quadratic.