Barycentric Lagrange interpolation

Let us interpolate the Runge function on $[-1,+1]$ $$ f(x) = \frac{1}{1 + 16 x^2} $$ using the Barycentric formula $$ p(x) = \frac{ \sum_{i=0}^N \frac{w_i}{x - x_i} f_i }{ \sum_{i=0}^N \frac{w_i}{x - x_i} } $$ where the weight $w_i$ is given by $$ w_i = \frac{1}{\prod_{j=0,j\ne i}^N (x_i - x_j)} $$

In [13]:
import numpy as np
from matplotlib import pyplot as plt
In [14]:
def fun(x):
    f = 1.0/(1.0+16.0*x**2)
    return f
In [15]:
def LagrangeInterpolation(X,Y,x):
    nx = np.size(x)
    nX = np.size(X)
    w = np.ones(nX)
    for i in range(nX):
        for j in range(nX):
            if i != j:
                w[i] = w[i]/(X[i]-X[j])
    num= np.zeros(nx)
    den= np.zeros(nx)
    eps=1.0e-14
    for i in range(nX):
        num = num + Y[i]*w[i]/((x-X[i])+eps)
        den = den + w[i]/((x-X[i])+eps)
    f = num/den
    return f
In [16]:
xmin, xmax = -1.0, +1.0
N = 20

We first interpolate on uniformly spaced points.

In [27]:
X = np.linspace(xmin,xmax,20)
Y = fun(X)
x = np.linspace(xmin,xmax,100)
fi = LagrangeInterpolation(X,Y,x)
fe = fun(x)
plt.plot(x,fe,'b--',x,fi,'r-',X,Y,'o')
plt.legend(("True function","Interpolation","Data"),'upper center')
Out[27]:
<matplotlib.legend.Legend at 0x10f92e350>

Next, we interpolate on Chebyshev points.

In [26]:
X = cos(np.linspace(0.0,pi,N))
Y = fun(X)
x = np.linspace(xmin,xmax,100)
fi = LagrangeInterpolation(X,Y,x)
fe = fun(x)
plt.plot(x,fe,'b--',x,fi,'r-',X,Y,'o')
plt.legend(("True function","Interpolation","Data"),'upper right')
Out[26]:
<matplotlib.legend.Legend at 0x10ecf3a10>