Natural and Clamped Cubic Splines

8,496 views

Published on

Published in: Education
  • Be the first to comment

Natural and Clamped Cubic Splines

  1. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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.

×