A Natural Cubic Spline Function Coefficient Command and examples of its use

© Copyright Joseph M. Herrmann 1994

This code was adapted from the Natural Cubic Spline Algorithm in Richard L. Burden, J. Douglas Faires, and Albert  C. Reynolds, Numerical Analysis, Prindle, Weber, and Schmidt, Boston, 1978, pp. 120-121.  

This command currently has no error checking capability and assumes that the list of data points is syntactically correct.

Natural cubic splines are used to create a function that interpolates a set of data points.  This function consists of piecewise cubic polynomials on each interval between the x coordinates of the data points and is constructed to be continuous with continuous first and second derivatives.  The natural cubic spline also has its second derivative equal zero at the x coordinate of the first and last data point.

The Natural Cubic Spline Function Coefficient Command

If S is a list of the data points with x coordinates ordered from minimum to maximum, the function NSplineCoef[S,a,b,c,d,n,t] computes the coefficients of the natural cubic spline functions in the vectors a, b, c, and d.  The number of data points is returned in the constant n and the x coordinates of the data is returned in the vector t. 

These coefficients can be used to build the natural cubic spline functions: 
Sp(x)=a1+b1(x-x1)+c1(x-x1)2+d1(x-x1)3   for     x1≤x≤x2
          =a2+b2(x-x2)+c2(x-x2)2+d2(x-x2)3   for     x2≤x≤x3
         . . .
         =an-1+bn-1(x-xn-1)+cn-1(x-xn-1)2+dn-1(x-xn-1)3   for     xn-1≤x≤xn

An example shows how to use this function to calculate the coefficients and then build the natural cubic spline functions automatically as Sp[1,x], ..., Sp[n-1,x] and then plot these functions with the data.  Execute the bold face Mathematica commands as you read the notebook.

NSplineCoef[S_,a_,b_,c_,d_,n_,t_]:=Module[{f,alpha,mu,z,L,h},
	n=Length[S];
	f=Table[S[[i,2]],{i,1,n}];
	t=Table[S[[i,1]],{i,1,n}]; 
	a=Table[0,{i,1,n}];
	b=Table[0,{i,1,n}];
	c=Table[0,{i,1,n}];
	d=Table[0,{i,1,n}];
	alpha=Table[0,{i,1,n}];
	mu=Table[0,{i,1,n}];
	z=Table[0,{i,1,n}];
	L=Table[0,{i,1,n}];
	h=Table[0,{i,1,n}];
	L[[1]]=1;
	mu[[1]]=0;
	z[[1]]=0;
	h[[1]]=t[[2]]-t[[1]];
	For[i=2,i<n,i++,
		h[[i]]=t[[i+1]]-t[[i]];
		alpha[[i]]=(3/(h[[i]]*h[[i-1]]))*(f[[i+1]]*h[[i-1]]-
			f[[i]]*(h[[i]]+h[[i-1]])+f[[i-1]]*h[[i]]);
		L[[i]]=2*(h[[i]]+h[[i-1]])-h[[i-1]]*mu[[i-1]];
		mu[[i]]=h[[i]]/L[[i]];
		z[[i]]=(alpha[[i]]-h[[i-1]]*z[[i-1]])/L[[i]]
		];
	L[[n]]=1;
	z[[n]]=0;
	c[[n]]=0;
	For[j=n-1,j>0,j--,
		c[[j]]=z[[j]]-mu[[j]]*c[[j+1]];
		b[[j]]=(f[[j+1]]-f[[j]])/h[[j]]-h[[j]]*
			(c[[j+1]]+2*c[[j]])/3;
		d[[j]]=(c[[j+1]]-c[[j]])/(3*h[[j]]);
		a[[j]]=f[[j]]
		];
	Print["finished"]]

Let's consider the following data points:

B={{46,40},{49,50},{51,55},{52,63},{54,72},{56,70},{57,77},
{58,73},{59,90},{60,93},{61,96},{62,88},{63,99},{64,110},
{66,113},{67,120},{68,127},{71,137},{72,132}}

We shall now determine the coefficients of the spline functions in the vectors a, b, c, and d.

NSplineCoef[B,a,b,c,d,n,t]
a
b
c
d

The following creates the natural cubic spline functions automatically as Sp[1,x], ..., Sp[n-1,x]

Clear[Sp]
For[i=1,i<n,i++,
		Sp[i,x_]=a[[i]]+b[[i]]*(x-t[[i]])+
			c[[i]]*(x-t[[i]])^2+d[[i]]*(x-t[[i]])^3]
?Sp

What is the function value when x=47?  Since 47 is between 46 and 49, we use the cubic spline function for the first interval and find:

N[Sp[1,47]]

What is the function value when x=70?  Since 70 is between 68 and 71, we use the 17th spline function and find:

N[Sp[17,70]]

The following code will plot each spline function separately and then plot them together with the data.

For[i=1,i<n,i++,
	P[i]=Plot[Sp[i,x],{x,t[[i]],t[[i+1]]}]]
B1=ListPlot[B,Prolog->PointSize[.015]]
SP=Show[Table[P[i],{i,1,n-1}]]
Show[B1,SP]

The use of the natural cubic spline function to calculate the derivative or integral of a function which interpolates the data points

The natural cubic spline function can be used to estimate the derivative or integral of a function approximated by the set of data points.  This can be accomplished by differentiating or integrating the natural cubic spline function formed from the data points.

For example, to estimate the derivative at x=61.5 of a function approximated by the data points 

B={{46,40},{49,50},{51,55},{52,63},{54,72},{56,70},{57,77},
{58,73},{59,90},{60,93},{61,96},{62,88},{63,99},{64,110},
{66,113},{67,120},{68,127},{71,137},{72,132}}

we first note that 

Sp[11, x_] = 
  96 - (580052348861*(-61 + x))/137154968124 - 
   (516764741777*(-61 + x)^2)/34288742031 + 
   (1549871570977*(-61 + x)^3)/137154968124

describes the natural cubic spline function for the interval 61≤x≤62 and determine the derivative of this function at x=61.5.  Thus

Clear[x,g]
g[x_]=D[Sp[11,x],x]
g[61.5]

Thus an estimate for the derivative of a function approximated by the set of data points is -10.825.  Note from the graph above or from the data that the graph dips from x=61 to x=62.  This dip causes the derivative to be negative at x=61.5.  

In a similar manner, if the integral of a function approximated by the set of data points from x=59.5 to 61.5 is to be computed then the spline functions 

Sp[9, x_] = 
  90 + (579693333391*(-59 + x))/45718322708 - 
   (642801432740*(-59 + x)^2)/34288742031 + 
   (1243590635159*(-59 + x)^3)/137154968124    for 59≤x≤60
 
Sp[10, x_] = 
  93 + (163720221865*(-60 + x))/68577484062 + 
   (1159566174517*(-60 + x)^2)/137154968124 - 
   (358513904625*(-60 + x)^3)/45718322708      for 60≤x≤61
 
Sp[11, x_] = 
  96 - (580052348861*(-61 + x))/137154968124 - 
   (516764741777*(-61 + x)^2)/34288742031 + 
   (1549871570977*(-61 + x)^3)/137154968124    for 61≤x≤62
   
can be integrated to determine an estimate.  In particular, the integral of Sp[9,x] from 59.5 to 60 + the integral of Sp[10,x] from 60 to 61 + integral of Sp[11,x] from 61 to 61.5 would form the estimate of the integral of a function approximated by the set of data points from x=59.5 to 61.5.  This estimate may be computed by the commands below.

Integrate[Sp[9,x],{x,59.5,60}]+
Integrate[Sp[10,x],{x,60,61}]+
Integrate[Sp[11,x],{x,61,61.5}]