Polynomial Interpolation

def evalPoly(a,xData,x):
    n = len(xData) - 1  # Degree of polynomial
    p = a[n]
    for k in range(1,n+1):
        p = a[n-k] + (x -xData[n-k])*p
    return p
def coeffts(xData,yData):
    m = len(xData)  # Number of data points
    a = yData.copy()
    for k in range(1,m):
        a[k:m] = (a[k:m] - a[k-1])/(xData[k:m] - xData[k-1])
        print('k = ',k,a)
    return a
0.1s
import numpy as np
import matplotlib.pyplot as plt
xs = np.linspace(0,6,100)
x_set1 = np.array([0.0,1.0,3.0,4.0,6.0])
y_set1 = np.array([1.1,-2.1,3,7,-4])
ys = evalPoly(coeffts(x_set1,y_set1),x_set1,xs)
plt.plot(xs,ys)
plt.scatter(x_set1,y_set1)
1.6s
from numpy import sin,pi
x_set2 = np.linspace(0,2*pi,7)
y_set2 = np.sin(x_set2)
xs2 = np.linspace(-0.5,2.25*pi,100)
ys2 = evalPoly(coeffts(x_set2,y_set2),x_set2,xs2)
plt.plot(xs2,ys2)
plt.scatter(x_set2,y_set2)
0.8s
Extrapolating outside of data
xs2a = np.linspace(-1,8,200)
ys2a = evalPoly(coeffts(x_set2,y_set2),x_set2,xs2a)
plt.plot(xs2a,ys2a)
plt.scatter(x_set2,y_set2)
0.7s
Oscillations
x_set3 = np.array([-5,-4,-3,-2,-1,0,1,2,3,4,5],dtype=float)
y_set3 = np.array([0.0,0.0,0.05,0.25,0.70,1.0,0.65,0.25,0.05,0.0,0.0])
xs3 = np.linspace(-5.,5.,100)
ys3 = evalPoly(coeffts(x_set3,y_set3),x_set3,xs3)
plt.plot(xs3,ys3)
plt.scatter(x_set3,y_set3)
0.5s
x_set4 = np.array([-6,-4,-3,-2,-1,0,1,2,3,4,5],dtype=float)
y_set4 = np.array([-0.1,0.0,0.0,0.05,0.25,0.70,1.0,0.65,0.25,0.05,0.0,0.0])
xs4 = np.linspace(-6.,5.,100)
ys4 = evalPoly(coeffts(x_set4,y_set4),x_set4,xs4)
plt.plot(xs4,ys4)
plt.scatter(x_set4,y_set4)
0.8s
Choice of interpolating order

Sometimes, using high-order polynomials to interpolate something with an underlying, more simple, mathematical structure can be a bad idea.

x_set5 = np.linspace(0.1,2,5)
y_set5 = np.log(x_set5)
xs5 = np.linspace(0,3,100)
ys5 = evalPoly(coeffts(x_set5,y_set5),x_set5,xs5)
ys5a = np.log(xs5)
plt.plot(xs5,ys5)
plt.scatter(x_set5,y_set5)
plt.plot(xs5,ys5a,'--')
0.5s
x_set5
0.0s
0.0s
Runtimes (1)