3.2. Error Formulas for Polynomial Collocation#

References:

3.2.1. Introduction#

When a polynomial \(P_n\) is given by collocation to \(n+1\) points \((x_i, y_i)\), \(y_i = f(x_i)\) on the graph of a function \(f\), one can ask how accurate it is as an approximation of \(f\) at points \(x\) other than the nodes: what is the error \(E(x) = f(x) - P(x)\)?

As is often the case, the result is motivated by considering the simplest “non-trival case”: \(f\) a polynomial of degree one too high for an exact fit, so of degree \(n+1\). The result is also analogous to the familiar error formula for Taylor polynonial approximations.

import numpy as np
from matplotlib.pyplot import figure, plot, title, grid, legend
from numericalMethods import fitPolynomial, evaluatePolynomial
# showPolynomial

3.2.2. Error in \(P_n(x)\) when collocating with a sufficiently differentiable function#

Theorem 3.2

For a function \(f\) with continuous derivative of order \(n+1\) \(D^{n+1}f\), the polynomial \(P_n\) of degree at most \(n\) that fits the points \((x_i, f(x_i))\) \(0 \leq i \leq n\) differs from \(f\) by

(3.1)#\[E_n(x) = f(x) - P_n(x) = \frac{D^{n+1}f(\xi_x)}{(n+1)!}\prod\limits_{i=0}^n (x - x_i)\]

for some value of \(\xi_x\) that is amongst the \(n+2\) points \(x_0, \dots x_n\) and \(x\).

In particular, when \(a \leq x_0 < x_1 \cdots < x_n \leq b\) and \(x \in [a,b]\), then also \(\xi_x \in [a, b]\).

Observation 3.1

This is rather similar to the error formula for the Taylor polynomial \(p_n\) with center \(x_0\):

(3.2)#\[e_n(x) = f(x) - p_n(x) = \frac{D^{n+1}f(\xi_x)}{(n+1)!} (x-x_0)^{n+1},\, \text{some $\xi_x$ between $x_0$ and $x$.} \]

This is effectively the limit of Equation (3.1) when all the \(x_i\) congeal to \(x_0\).

3.2.3. Error bound with equally spaced nodes is \(O(h^{n+1})\), but …#

An important special case is when there is a single parameter \(h\) describing the spacing of the nodes; when they are the equally spaced values \(x_i = a + i h\), \(0 \leq i \leq n\), so that \(x_0 = a\) and \(x_n = b\) with \(h = \displaystyle \frac{b-a}{n}\). Then there is a somewhat more practically usable error bound:

Theorem 3.3

For \(x \in [a,b]\) and the above equaly spaced nodes in that interval \([a,b]\),

(3.3)#\[| E_n(x) | = \left| f(x) - P_n(x)\right| \leq \frac{M_{n+1}}{n+1} h^{n+1}, = O(h^{n+1}),\]

where \(M_{n+1} = \max\limits_{x \in [a,b]} | D^{n+1}f(x)|\).

3.2.4. Possible failure of convergence#

A major practical problem with this error bound is that is does not in general guarantee convergence \(P_n(x) \to f(x)\) as \(n \to \infty\) with fixed interval \([a, b]\), because in some cases \(M_{n+1}\) grows too fast.

A famous example is the “Witch of Agnesi” (so-called because it was introduced by Maria Agnesi, author of the first textbook on differential and integral calculus).

def agnesi(x):
    return 1/(1+x**2)
def graph_agnesi_collocation(a, b, n):
    figure(figsize=[14, 5])
    title(f"The Witch of Agnesi and collocating polynomial of degree {n=}")
    x = np.linspace(a, b, 200)  # Plot 200 points instead of the default 50, as some fine detail is needed
    agnesi_x = agnesi(x)
    plot(x, agnesi_x, label="Witch of Agnesi")
    xnodes = np.linspace(a, b, n+1)
    ynodes = agnesi(xnodes)
    c = fitPolynomial(xnodes, ynodes)
    P_n = evaluatePolynomial(x, c)
    plot(xnodes, ynodes, 'r*', label="Collocation nodes")
    plot(x, P_n, label="P_n(x)")
    legend()
    grid(True)

    figure(figsize=[14, 5])
    title(f"Error curve")
    E_n = P_n - agnesi_x
    plot(x, E_n)
    grid(True);

Start with \(n=4\), which seems somewhat well-behaved:

graph_agnesi_collocation(a=-4, b=4, n=4)
../_images/c5fa33a7bc7b10049cac4316d3346234442ebf331f14d4e9d0cd1619c592a9c6.png ../_images/3426d34790dc8866cd547652dac9f48c7416a78d315bdd50c8fa2a9d2a051f7d.png

Now increase the number of inervals, doubling each time.

graph_agnesi_collocation(a=-4, b=4, n=8)
../_images/c5ff1908946a9fc60e3c11cf71ae9e751cf1d3693dfd7bd4edfda82c11a94386.png ../_images/f82815eafadb6ccc8e709c2392b51a191be73fb0240df4838e46d664bad41bd6.png

The curve fits better in the central part, but gets worse towards the ends!

One hint as to why is to plot the polynomial factor in the error formula above:

def graph_error_formula_polynomial(a, b, n):
    figure(figsize=[14, 5])
    title(f"The polynomial factor in the error formula for degree {n=}")
    x = np.linspace(a, b, 200)  # Plot 200 points instead of the default 50, as some fine detail is needed
    xnodes = np.linspace(a, b, n+1)
    polynomial_factor = np.ones_like(x)
    for x_node in xnodes:
        polynomial_factor *= (x - x_node)
    plot(x, polynomial_factor)
    grid(True);
graph_error_formula_polynomial(a=-4, b=4, n=4)
graph_error_formula_polynomial(a=-4, b=4, n=8)
../_images/e142a1b0a024bc9a20b689067fb2b408e726350f9ecc280ee81099e8afc6bbf1.png ../_images/54302e08d3fd80b07c309ced1a3872725118835af7cd10e34e9215bb3ac9d4f9.png

As n increases, it just gets worse:

graph_agnesi_collocation(a=-4, b=4, n=16)
graph_error_formula_polynomial(a=-4, b=4, n=16)
../_images/6d50a85619394e713447932535c8c11613068a1429c2370c9013e7827da0d9b4.png ../_images/24e32ff2fa3b4b15a72e5ad3aa8f03ee1e7013f0c1340a8d89b8770407d0ffdd.png ../_images/ffee7e64441be002f291e6813c7f345d48d10b08d739d79029787886984e2bab.png

3.2.5. Two solutions: piecewise interpolation and least squares approximation#

The approach of least squares approximation is introduced in the next section Least-squares Fitting to Data; that can be appropriate when the original data is not exact (due to measurement error in an experiment, for example) so a good approximation at each node can be more appropriate than exact collocation at each but with implausable behavior between the nodes.

When instead exact collocation is sought, piecewise interpolation is typically used. This involves collocation with multiple polynomials of a fixed degree, each on a part of the domain. Then for each such polynomial \(M_{m+1}\) in the above error formula is independent of the number \(N\) of nodes and with the nodes on interval \([a, b]\) at equal spacing \(h = (b-a)/(N-1)\), one has the convergence result

\[ | E_m(x) \leq \frac{M_{m+1}}{m+1} h^{m+1} = O(h^{m+1}) = O \left( \frac{1}{N^{m+1}} \right), \to 0 \text{ as } N \to \infty. \]

This only requires that \(f\) has a continuous derivatives up to order \(m+1\).

The simplest case of this — quite often used in computer graphics, including matplotlib.pyplot.plot — is to divide the domain into \(N-1\) sub-intervals of equal width separated by nodes \(x_i = a + i h\), \(0 \leq i \leq N\), and then approximate \(f(x)\) linearly on each sub-interval by using the two surrounding nodes \(x_i\) and \(x_{i+1}\) determined by having \(x_i \leq x \leq x_{i+1}\): this is piecewise linear interpolation.

This gives the approximating function \(L_N(x)\), and the above error formula, now with \(m=1\), says that the worst absolute error anywhere in the interval \([a, b]\) is

\[ |E_2(x)| = |f(x) - L_N(x)| \leq \frac{M_2}{2} h^2, \quad M_2 = \max\limits_{x \in [a,b]} | f''(x)|. \]

Thus for any \(f\) that is is twice continuously differentiable the error at each \(x\)-value converges to zero as \(N \to \infty\). Further, it is uniform convergence: the maximum error over all points in the domain goes to zero.

Preview: definite integrals (en route to solving differential equations)#

Integrating this piecewise linear approximation over interval \([a, b]\) gives the Compound Trapezoid Rule approximation of \(\int_a^b f(x) dx\). As we will soon see, this also has error at worst \(O(h^2), = O(1/N^2)\): each doubling of effort reduces errors by a factor of about four.

Also, you might have heard of Simpson’s Rule for approximating definite integrals (and anyway, you will soon!): that uses piecewise quadratic interpolation and we will see that this improves the errors to \(O(h^4), = O(1/N^4)\): each doubling of effort reduces errors by a factor of about 16.

Remark 3.1 (Computer graphics and smoother approximating curves)

As mentioned, computer graphics often draws graphs from data points this way, most often with either piecewise linear or piecewise cubic (\(m=3\)) approximation.

However, this can give sharp “corners” at the nodes, so many modes are needed to make this visually acceptable. That is unavoidable with piecewise linear curves, but for higher degrees there are modifications of this strategy that give smoother curves: piecewise cubics turn out to work very nicely for that, and these are introduced in the section Piecewise Polynomial Approximating Functions and Spline Interpolation.