Cubic Splines
Cubic splines are piecewise polynomials of order three. They are often used to interpolate a data series. Cubic splines come in many shapes and are implemented by the CubicSpline class.
Types of cubic splines
Cubic splines are interpolating curves and so they are defined in part by a set of data points. In addition, the first derivative (slope) of the curve is required to be continuous. This still does not fully define the conditions on all the coefficients of the piecewise polynomials, so additional conditions are usually applied. Choosing different conditions leads to different types of cubic splines. The kinds supported by Numerics.NET are defined by the CubicSplineKind enumeration type, whose members are listed below:
Value | Description |
---|---|
Natural | A natural cubic spline with continuous second derivative in the interior and zero second derivative at the end points. |
Clamped | A clamped cubic spline with continuous second derivative in the interior and fixed values for the derivatives at the end points. |
Hermite | A Hermite interpolating cubic spline with specific values for the first derivative at each data point. |
Akima | An Akima spline, suitable for situations with rapidly changing second derivatives. |
Not-a-knot | A type of cubic spline where the second and third derivative at the first and last interior data points are continuous. The interpolating polynomial is the same on the first two and the last two intervals. |
Smoothing spline | A cubic spline that finds a compromise between interpolating the data (using a natural spline) and minimizing the curvature of the curve. |
Constructing cubic splines
The CubicSpline class has four sets of constructors, one set each for each kind of spline. In addition, the CubicSpline class has a number of static methods that construct splines of a specific kind.
There are three constructors that create a natural spline. The first constructor takes two Double arrays as arguments. The first array contains the x-values of the data points. The second array contains the y-values. As mentioned before, the x values must be provided in ascending order. The second constructor takes two Vector<T> objects, with the same meaning as before. The third constructor has only one argument: an array of Point structures. The following example illustrates the use of these constructors:
Vector<double> xValues = Vector.Create(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
Vector<double> yValues = Vector.Create(1.0, 3.0, 4.0, 3.0, 4.0, 2.0);
CubicSpline naturalSpline1 = new CubicSpline(xValues, yValues);
Point[] dataPoints = new Point[]
{new Point(1, 1), new Point(2, 3), new Point(3, 4),
new Point(4, 3), new Point(5, 4), new Point(6, 2)};
CubicSpline naturalSpline2 = new CubicSpline(dataPoints);
CubicSpline naturalSpline3 = CubicSpline.CreateNatural(xValues, yValues);
CubicSpline naturalSpline4 = CubicSpline.CreateNatural(dataPoints);
Natural splines can also be created with the static CreateNatural method, which accepts the same arguments.
To construct a clamped spline, the same three options are available, but two additional parameters are required: the slopes at the left and right end point. The following example constructs a clamped cubic spline through the same data points as above, and forces the slope at the lower bound to be -1, and the slope at the upper bound to be 1:
CubicSpline clampedSpline1 = new CubicSpline(xValues, yValues, -1.0, 1.0);
CubicSpline clampedSpline2 = new CubicSpline(dataPoints, -1.0, 1.0);
CubicSpline clampedSpline3 = CubicSpline.CreateClamped(xValues, yValues, -1.0, 1.0);
CubicSpline clampedSpline4 = CubicSpline.CreateClamped(dataPoints, -1.0, 1.0);
As the above code shows, clamped splines can also be created with the static CreateClamped method, which accepts the same arguments.
To construct an Akima spline, the same options are once again available, but an additional argument should be supplied: a CubicSplineKind value with a value of Akima. Akima splines can also be created with the static CreateAkima method, which accepts the same arguments while omitting the extra argument.
CubicSpline akimaSpline1 = new CubicSpline(xValues, yValues, CubicSplineKind.Akima);
CubicSpline akimaSpline2 = new CubicSpline(dataPoints, CubicSplineKind.Akima);
CubicSpline akimaSpline3 = CubicSpline.CreateAkima(xValues, yValues);
CubicSpline akimaSpline4 = CubicSpline.CreateAkima(dataPoints);
To construct a smoothing spline, the same options are again available as for natural splines, but one or two additional arguments should be supplied. The first is the smoothing parameter. This is a value, usually between 0 and 1, that specifies the relative weight of the smoothness and interpolation error. A value of 0 corresponds to a least squares fit of a horizontal line. A value of 1 corresponds to a natural spline. The second additional argument is an array or vector that contains the weights of each data point. If no weights are supplied, they are assumed to all be equal to 1.
Smoothing splines can also be created with the static CreateSmooth method, which accepts the same arguments as the constructors. It also has overloads that omit the weights. In this case, the weights are assumed to be all equal to 1.
Vector<double> weights = Vector.CreateFromFunction(xValues.Length, i => 1 / yValues[i]);
CubicSpline smoothingSpline1 = new CubicSpline(xValues, yValues, 0.5, weights);
CubicSpline smoothingSpline2 = new CubicSpline(dataPoints, 0.5, weights);
CubicSpline smoothingSpline3 = CubicSpline.CreateSmooth(xValues, yValues, 0.5);
CubicSpline smoothingSpline4 = CubicSpline.CreateSmooth(dataPoints, 0.5);
To construct a monotonic cubic spline, the same options are once again available. They do not require any additional parameters. Cubic Hermite splines can also be created with the static CreateMonotonic method, which accepts the same arguments as the constructors.
CubicSpline monotonicSpline1 = new CubicSpline(xValues, yValues, CubicSplineKind.Monotonic);
CubicSpline monotonicSpline2 = new CubicSpline(dataPoints, CubicSplineKind.Monotonic);
CubicSpline monotonicSpline3 = CubicSpline.CreateMonotonic(xValues, yValues);
CubicSpline monotonicSpline4 = CubicSpline.CreateMonotonic(dataPoints);
To construct a cubic Hermite interpolating spline, the same options are once again available, but an additional array or vector should be supplied that contains the first derivatives at each of the data points. Cubic Hermite splines can also be created with the static CreateHermiteInterpolant method, which accepts the same arguments as the constructors.
Vector<double> derivatives = Vector.Create(0.5, 0.0, -0.5, 0.0, 0.5, 1.0);
CubicSpline hermiteSpline1 = new CubicSpline(xValues, yValues, derivatives);
CubicSpline hermiteSpline2 = new CubicSpline(dataPoints, derivatives);
CubicSpline hermiteSpline3 = CubicSpline.CreateHermiteInterpolant(xValues, yValues, derivatives);
CubicSpline hermiteSpline4 = CubicSpline.CreateHermiteInterpolant(dataPoints, derivatives);
Working with cubic splines
Once created, there is no real difference between any of the types of cubic splines.
CubicSpline implements most methods and properties of the Curve class.
The ValueAt method returns the value of the spline at a specified point. If the x value is less than the lower bound of the first interval, the value is that of the cubic polynomial on the first interval extended to the left. If the x value is greater than the upper bound of the last interval, the value is that of the cubic polynomial on the last interval extended to the right.
The SlopeAt method returns the derivative. It is defined everywhere. The GetDerivative method is not available.
Console.WriteLine("naturalSpine1.ValueAt(2) = {0}", naturalSpline1.ValueAt(2));
Console.WriteLine("naturalSpine1.SlopeAt(2) = {0}", naturalSpline1.SlopeAt(2));
Integral evaluates the definite integral over a specified interval. The integral is calculated exactly and efficiently. In fact, a common application of cubic splines is the approximation of the integral of a tabulated function. The example below illustrates this procedure:
double integral = naturalSpline1.Integral(2.2, 5.4);
This type of approximation turns out to be of good quality in most cases.
The FindRoots method is specialized to return all zeros of the cubic spline function.