Piecewise Interpolation: Piecewise Linear Spline Interpolation
Piecewise Linear (Piecewise Affine) Spline Interpolation
Given a set of
data points
, a piecewise linear (piecewise affine) spline can be defined as:
![Rendered by QuickLaTeX.com \[ y=\begin{cases} a_1x+b_1,&x\in [x_1, x_2) \\ a_2x+b_2,&x\in [x_2, x_3) \\ \vdots & \vdots \\ a_{k-1}x+b_{k-1},&x\in [x_{k-1}, x_k] \end{cases} \]](https://engcourses-uofa.ca/wp-content/ql-cache/quicklatex.com-544c377230cdcd60073a9bc981e6e96d_l3.png)
The
data points have
intervals. The linear function for each interval is defined using two coefficients, and therefore, we need to find
coefficients
. The coefficients
and
can be found by solving the two equations:
![]()
Therefore:
![Rendered by QuickLaTeX.com \[\begin{split} a_i&=\frac{y_i-y_{i+1}}{x_i-x_{i+1}}\\ b_i&=\frac{y_{i+1}x_i-y_ix_{i+1}}{x_i-x_{i+1}} \end{split} \]](https://engcourses-uofa.ca/wp-content/ql-cache/quicklatex.com-c80334dbe04b695772bc3df7f0b9c1b4_l3.png)
Example
Consider the following 11 data points: (-1.00,0.038),(-0.80,0.058),(-0.60,0.100),(-0.4,0.200),(-0.20,0.500),(0.00,1.000),(0.20,0.500),(0.40,0.200),(0.60,0.100),(0.80,0.0580),(1.00,0.038) which were generated using the Runge function. Find the explicit representation of the linear spline interpolating function for these data points.
Solution
There are 11 data points surrounding 10 intervals. For each interval
, a set of coefficients
and
are required for the linear interpolation. For the first interval, the coefficients are:
![Rendered by QuickLaTeX.com \[\begin{split} a_1&=\frac{y_1-y_2}{x_1-x_2}=\frac{0.038-0.058}{-1-(-0.8)}=0.1\\ b_1&=\frac{y_2x_1-y_1x_2}{x_1-x_2}=\frac{0.058(-1)-0.038(-0.8)}{-1-(-0.8)}=0.138 \end{split} \]](https://engcourses-uofa.ca/wp-content/ql-cache/quicklatex.com-1152e06b8f181a3a166ee34b3da13532_l3.png)
Similarly:
![Rendered by QuickLaTeX.com \[\begin{split} a_2&=\frac{y_2-y_3}{x_2-x_3}=\frac{0.058-0.1}{-0.8-(-0.6)}=0.21\\ b_2&=\frac{y_3x_2-y_2x_3}{x_2-x_3}=\frac{0.1(-0.8)-0.058(-0.6)}{-0.8-(-0.6)}=0.226 \end{split} \]](https://engcourses-uofa.ca/wp-content/ql-cache/quicklatex.com-d5c65d7c7622548503bb5a00d0b5ad5c_l3.png)
Repeating for the other coefficients, the required explicit equation has the form:
![Rendered by QuickLaTeX.com \[ y=\begin{cases} 0.1x+0.138,&x\in [-1, -0.8) \\ 0.21x+0.226,&x\in [-0.8, -0.6) \\ 0.5x+0.4,&x\in [-0.6, -0.4)\\ 1.5x+0.8,&x\in [-0.4, -0.2)\\2.5x+1,&x\in [-0.2, 0.0)\\-2.5x+1,&x\in [0.0, 0.2)\\-1.5x+0.8,&x\in [0.2, 0.4)\\-0.5x+0.4,&x\in [0.4, 0.6)\\-0.21x+0.226,&x\in [0.6, 0.8)\\-0.1x+0.138,&x\in [0.8, 1.0] \end{cases} \]](https://engcourses-uofa.ca/wp-content/ql-cache/quicklatex.com-c52da1e0980385538c3aba7ad3592fc8_l3.png)
Notice that for the procedure to work, the
components of the data points have to satisfy:
. The following Mathematica code utilizes a user defined procedure “Spline1” that creates the required piecewise linear function.
Data = {{-1, 0.038}, {-0.8, 0.058}, {-0.60, 0.10}, {-0.4,0.20}, {-0.2, 0.50}, {0, 1}, {0.2, 0.5}, {0.4, 0.2}, {0.6,0.1}, {0.8, 0.058}, {1, 0.038}};
Spline1[Data_] := (
k1 = Length[Data] - 1;
atable = Table[(Data[[i, 2]] - Data[[i + 1, 2]])/(Data[[i, 1]] -Data[[i + 1, 1]]), {i, 1, k1}];
btable = Table[(Data[[i + 1, 2]]*Data[[i, 1]] -Data[[i, 2]]*Data[[i + 1, 1]])/(Data[[i, 1]] - Data[[i + 1, 1]]), {i, 1, k1}];
pf = Table[{atable[[i]] x + btable[[i]],Data[[i, 1]] <= x <= Data[[i + 1, 1]]}, {i, 1, k1}];
Piecewise[pf]
)
y = Spline1[Data]
a = Plot[{y, yactual}, {x, -1, 1}, Epilog -> {PointSize[Large], Point[Data]}, AxesLabel -> {"x", "y1"}, ImageSize -> Medium, PlotRange -> All, PlotLegends -> {"y1", "yactual"}, PlotLabel -> "Linear splines"]
import numpy as np
import matplotlib.pyplot as plt
Data = [[-1, 0.038], [-0.8, 0.058], [-0.60, 0.10], [-0.4,0.20], [-0.2, 0.50], [0, 1], [0.2, 0.5], [0.4, 0.2], [0.6, 0.1], [0.8, 0.058], [1, 0.038]]
def Spline1(x, Data):
k1 = len(Data) - 1
atable = [(Data[i][1] - Data[i + 1][1])/(Data[i][0] - Data[i + 1][0]) for i in range(k1)]
btable = [(Data[i + 1][1]*Data[i][0] - Data[i][1]*Data[i + 1][0])/(Data[i][0] - Data[i + 1][0]) for i in range(k1)]
display([['{:15}'.format(str(round(atable[i],3))+'x + '+str(round(btable[i],3))),
'{:15}'.format(str(round(Data[i][0],3))+' <=x<= '+str(round(Data[i + 1][0],3)))] for i in range(k1)])
return np.piecewise(x, [(x >= Data[i][0])&(x <= Data[i + 1][0]) for i in range(k1)],
[lambda x, j=i: atable[j]*x + btable[j] for i in range(k1)])
x = np.arange(-1,1,0.01)
y = Spline1(x, Data)
yactual = 1/(1 + 25*x**2)
plt.plot(x,yactual, label="yactual")
plt.plot(x, y, label="y1")
plt.scatter([point[0] for point in Data],[point[1] for point in Data], c='k')
plt.title("Linear splines")
plt.xlabel("x"); plt.ylabel("y1")
plt.legend(); plt.grid(); plt.show()
