Making communications land - Are they received and understood as intended? we...
Natural and Clamped Cubic Splines
1. Math 4446 Project I
Natural and Clamped Cubic Splines
Mark Brandao
March 4, 2014
Abstract
The goal of this project is to employ our Linear Algebra, Calculus, and Matlab skills
for a specific application in the area of spline interpolation. The main goal at the end is to
approximate a parent function given a set of data points; we will try to approximate both the
parent function and its derivative in order to reduce error. The main tools used in achieving
this goal will be matrix reduction as well as computations of divided differences and other
properties of data points.
Problem I
Let the system Ax = f have n equations with n unknowns and nonzero entries
Aii = ai, i = 1, 2, . . . , n
A(i+1)i = bi, i = 1, 2, . . . , n − 1
Ai(i+1) = ci, i = 1, 2, . . . , n − 1
All other entries of the A matrix are zero. The following algorithm solves the system Ax = f
using Gaussian elimination for tridiagonal systems:
gesolve.m
1 function x = gesolve(a,b,c,f)
2 n=length(a);
3 d(1) = a(1);
4 z(1) = f(1);
5 for i=2:n
6 d(i) = a(i) − b(i−1)*c(i−1)/d(i−1);
7 z(i) = f(i) − b(i−1)*z(i−1)/d(i−1);
8 end
9
10 x(n) = z(n)/d(n);
2. 11 for i=n−1:−1:1
12 x(i) = (z(i) − c(i)*x(i+1))/d(i);
13 end
14 end
Indeed, when testing the system
5 2 0 0
4 13 −4 0
0 7 15 6
0 0 12 −16
x =
1
2
3
−4
, gesolve.m yields the result x =
0.1530
0.1175
0.0348
0.2761
, which is exactly what is yielded when typing the command Af into Matlab.
Problem II
We now wish to use our gesolve.m algorithm to help us find the natural cubic spline, Sk(x). We
will then write another function file for Sk(x). We know that, given mi, hi, xi, pi, and qi,
Sk(x) = −
mk
6hk
(x − xk+1)3
+
mk+1
6hk
(x − xk)3
+ pk(xk+1 − x) + qk(x − xk), k = 1, 2, . . . , n − 1
Thus, given an mk, and its sequential term, mk+1, xk and its sequential term, xk+1, as well as pk
and qk, we can compute Sk(x) for a given x:
spline.m
1 function Sk = spline(mk,mkp1,pk,qk,xk,xkp1,x)
2 hk = xkp1−xk;
3 Sk = −mk./(6.*hk).*(x−xkp1).ˆ3 + mkp1./(6.*hk).*(x−xk).ˆ3 + pk.*(xkp1−x) + ...
qk.*(x−xk);
4 end
Thus, were we to supply all the data points and coefficients, we could compute multiple values for
Sk(x) with x in the interval [xk, xk+1].
Now we wish to apply our algorithm for Sk(x) over one interval more generally; given a set of
data points, xi and yi, we wish to compute each Sk(x) across every interval and plot the resulting
natural cubic spline. To do this, we must find a solution to the system:
2(h1 + h2) h2
h2 2(h1 + h3) h3
... ... ...
hi 2(hi + hi+1) hi
...
...
hn−2 2(hn−2 + hn−1)
m2
m3
...
mn−1
=
u1
u2
...
un−2
3. Additionally, we set m1 = mn = 0. Solving this system for all the mi values (i = 1, 2, . . . , n) and
plotting the result is achieved by the following code:
spline nat.m
1 function spline nat(x0,y0)
2 n = length(x0);
3 x0=reshape(x0,1,n);
4 y0=reshape(y0,1,n);
5
6 % Computes the hk values and divided differences
7 h = x0(2:n) − x0(1:(n−1));
8 d = (y0(2:n) − y0(1:(n−1)))./h;
9
10
11 %Computes the values along the tridiagonal, as well as the solution vector
12 a = 2*(h(1:(n−2)) + h(2:(n−1)));
13 b = h(2:(n−2));
14 u = 6*(d(2:n−1) − d(1:n−2));
15
16 %Uses gesolve to solve the linear system for m i
17 m = gesolve(a,b,b,u);
18 m = [0 m 0];
19
20 %Computes pk and qk
21 p = y0(1:(n−1))./h − m(1:(n−1)).*h/6;
22 q = y0(2:n)./h − m(2:n).*h/6;
23
24 %Plots the result across all intervals in the x0 vector
25 hold on
26 for i = 1:(n−1)
27 x=linspace(x0(i),x0(i+1),1000);
28 Sk = spline(m(i),m(i+1),p(i),q(i),x0(i),x0(i+1),x);
29 plot(x,Sk,'linewidth',1.5)
30
31 end
32 xlabel('$x$','fontsize',18,'interpreter','latex')
33 ylabel('$f(x)$','fontsize',18,'interpreter','latex')
34 title('Natural cubic spline for $f(x)$','fontsize',18,'interpreter','latex')
35 end
If we apply this algorithm to the set of data: x =
−2
−1
0
1
2
and use the function y = |x|, we see the
following result:
4. −2 −1.5 −1 −0.5 0 0.5 1 1.5 2
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
2
x
f(x)
Natural cubic spline for f (x) = |x|
Indeed, this approximation is as accurate as we can expect; the derivative of |x| is not defined at
x = 0, so the natural cubic spline attempts to accommodate for this fact. Thus, the approximation
is somewhat inaccurate, but it maps a very good polynomial approximation of f(x) = |x|.
When running the instructor-provided script (and associated data files) for smile.m, the result
is as follows:
−1.5 −1 −0.5 0 0.5 1 1.5
−1
−0.8
−0.6
−0.4
−0.2
0
0.2
0.4
0.6
0.8
1
x
f(x)
S MI LE
Indeed, as the name suggests, the plot resembles a smile.
5. Problem III
We now wish to begin approaching the clamped cubic spline of a function. We also wish to plot the
derivative of the clamped spline versus the derivative of the actual function. So we will implement
a code to calculate the derivative, Sk(x), for a given x. We know that the derivative is
Sk(x) = −
mk
2hk
(x − xk+1)2
+
mk+1
2hk
(x − xk)2
− pk + qk, k = 1, 2, . . . , n − 1
Thus, the function we will use is:
dspline.m
1 function Skp = dspline(mk,mkp1,pk,qk,xk,xkp1,x)
2 hk = xkp1−xk;
3 Skp = −mk./(2.*hk).*(x−xkp1).ˆ2 + mkp1./(2.*hk).*(x−xk).ˆ2 − pk + qk;
4 end
Again, we want to apply our spline.m and dspline.m algorithms across multiple intervals to plot
the clamped cubic spline. We also want to plot the derivative of the spline, as well as the error.
However, we first need to solve the following system:
3
2
h1 + 2h2 h2
h2 2(h1 + h3) h3
... ...
...
hi 2(hi + hi+1) hi
... ...
hn−2 2hn−2 + 3
2
hn−1
m2
m3
...
mn−1
=
f1
f2
...
fn−2
Where fi = ui, i = 2, 3, . . . , n − 3. For the clamped cubic spline, f1 = u1 − 3(d1 − f (x0)) and
fn−2 = un−2 − 3(f (xn) − dn−1), where di are the divided differences.
Thus, we see that our algorithm is
spline clam.m
1 function spline clam(x0,y0,fp0,fp1,func,funcprime)
2 n = length(x0);
3 x0=reshape(x0,1,n);
4 y0=reshape(y0,1,n);
5
6 % Computes the hk values and divided differences
7 h = x0(2:n) − x0(1:(n−1));
8 d = (y0(2:n) − y0(1:(n−1)))./h;
9
10 %Computes the values along the tridiagonal
11 a = 2*(h(1:(n−2)) + h(2:(n−1)));
12 a(1) = 3*h(1)/2 + 2*h(2);
6. 13 a(n−2) = 3/2*h(n−1) + 2*h(n−2);
14 b = h(2:(n−2));
15
16 %Compues the right−hand side (solution) vector
17 f=6*(d(2:n−1) − d(1:n−2));
18 f(1) = f(1) − 3*(d(1) − fp0);
19 f(n−2) = f(n−2) − 3*(fp1 − d(end));
20
21 %Solves the clamped cubic spline linear system
22 m = gesolve(a,b,b,f);
23 m0 = 3*(d(1) − fp0)/h(1) − m(1)/2;
24 mn = 3*(fp1 − d(end))/h(end) − m(end)/2;
25 m =[m0 m mn];
26
27
28 %Computes pk and qk
29 p = y0(1:(n−1))./h − m(1:(n−1)).*h/6;
30 q = y0(2:n)./h − m(2:n).*h/6;
31
32 %Plots clamped spline and exact function
33 figure(1)
34 clf
35 hold on
36 for i = 1:(n−1)
37 x=linspace(x0(i),x0(i+1),100);
38 Sk = spline(m(i),m(i+1),p(i),q(i),x0(i),x0(i+1),x);
39 F = func(x);
40 plot(x,Sk,'linewidth',1.5)
41 plot(x,F,'linewidth',1.5)
42 end
43 xlabel('$x$','fontsize',18,'interpreter','latex')
44 ylabel('$f(x)$','fontsize',18,'interpreter','latex')
45 title('Clamped cubic spline and $f(x)$','fontsize',18,'interpreter','latex')
46 pause
47 figure(2)
48 clf
49 clear F
50 hold on
51 %Plots clamped spline derivative and exact function derivative
52 for i = 1:(n−1)
53 x=linspace(x0(i),x0(i+1),100);
54 Skp = dspline(m(i),m(i+1),p(i),q(i),x0(i),x0(i+1),x);
55 F = funcprime(x);
56 plot(x,Skp,'linewidth',1.5)
57 plot(x,F,'linewidth',1.5)
58 end
59 xlabel('$x$','fontsize',18,'interpreter','latex')
60 ylabel('$g(x)$','fontsize',18,'interpreter','latex')
61 title('Derivative of clamped cubic spline, ...
$g(x)$','fontsize',18,'interpreter','latex')
62 pause
63 figure(3)
64 clf
7. 65 clear F
66 hold on
67 %Plots error of clamped cubic spline
68 for i = 1:(n−1)
69 x=linspace(x0(i),x0(i+1),100);
70 Sk = spline(m(i),m(i+1),p(i),q(i),x0(i),x0(i+1),x);
71 F = func(x);
72 e = Sk − F;
73 plot(x,e,'linewidth',1.5)
74 end
75 xlabel('$x$','fontsize',18,'interpreter','latex')
76 ylabel('$f(x)$','fontsize',18,'interpreter','latex')
77 title('Error of the clamped cubic spline for ...
$f(x)$','fontsize',18,'interpreter','latex')
78
79
80 end
We then wish to apply our algorithm to the function f(x) = x3
with the x-points -1, 2, 5, and 8.
Upon applying the algorithm, we plot f(x) and Sk(x) on the same figure:
−1 0 1 2 3 4 5 6 7 8
−100
0
100
200
300
400
500
600
x
f(x)
Clamped cubic spline and f (x) = x3
Indeed, the original function and the clamped spline are indistinguishable; our approximation is
very accurate. Upon plotting the derivative of f(x) and the derivative of Sk(x), we see the following
plot:
8. −1 0 1 2 3 4 5 6 7 8
0
20
40
60
80
100
120
140
160
180
200
x
g(x)
Derivative of clamped cubic spline, g(x) = 3x2
Again, the original derivative and the spline derivative are indistinguishable. When we look at the
error, S(x) − f(x), for our spline approximation, we see the following picture:
−1 0 1 2 3 4 5 6 7 8
−6
−5
−4
−3
−2
−1
0
1
2
3
x 10
−14
x
f(x)
Error of the clamped cubic spline for f (x) = x3
The scale on this figure, though, is 10−14
, which is essentially zero with round-off error. So, indeed,
with f(x) = x3
, S(x) = f(x) for the clamped spline approximation.
9. We will now use our clamped spline approximation to interpolate the function f(x) = xex
. We
will use the x-coordinates 0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, and 2.0. Upon applying the
algorithm, we plot f(x) and Sk(x) on the same figure:
0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2
0
5
10
15
x
f(x)
Clamped cubic spline and f (x) = xex
Once more, the original function and the clamped spline interpolation are visually indistinguishable
from each other. As are the original function’s derivative and the clamped spline derivative:
0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2
0
5
10
15
20
25
x
g(x)
Derivative of clamped cubic spline, g(x) = ex
+ xex
However, in investigating the error, we find a nonzero result when plotting S(x) − f(x):
10. 0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2
−18
−16
−14
−12
−10
−8
−6
−4
−2
0
2
x 10
−5
x
f(x)
Error of the clamped cubic spline for f (x) = xex
Indeed, the maximum error appears to be around −1.8 × 10−4
, which is small, but it is not likely
to equal zero with round-off error. This is still a fairly accurate approximation, but it is not as
exact as in the previous example.
If all the files mentioned above are included in the directory (as well as an altered smile.m that
calls spline nat rather than spline-nat), then all the above results can be obtained by running
the included file Project 1.m.