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.
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 the
Extreme Optimization Numerical
Libraries for .NET
are defined by the
CubicSplineKind
enumeration type, whose members are listed below:
Kinds of cubic splines
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.
|
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
VectorT
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);
Dim xValues = Vector.Create(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)
Dim yValues = Vector.Create(1.0, 3.0, 4.0, 3.0, 4.0, 2.0)
Dim naturalSpline1 As CubicSpline = New CubicSpline(xValues, yValues)
Dim 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)}
Dim naturalSpline2 As CubicSpline = New CubicSpline(dataPoints)
Dim naturalSpline3 As CubicSpline = CubicSpline.CreateNatural(xValues, yValues)
Dim naturalSpline4 As CubicSpline = CubicSpline.CreateNatural(dataPoints)
No code example is currently available or this language may not be supported.
let xValues = Vector.Create(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)
let yValues = Vector.Create(1.0, 3.0, 4.0, 3.0, 4.0, 2.0)
let naturalSpline1 = CubicSpline(xValues, yValues)
let dataPoints = [|
Point(1.0, 1.0); Point(2.0, 3.0); Point(3.0, 4.0);
Point(4.0, 3.0); Point(5.0, 4.0); Point(6.0, 2.0) |]
let naturalSpline2 = CubicSpline(dataPoints)
let naturalSpline3 = CubicSpline.CreateNatural(xValues, yValues)
let 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);
Dim clampedSpline1 As CubicSpline = New CubicSpline(xValues, yValues, -1.0, 1.0)
Dim clampedSpline2 As CubicSpline = New CubicSpline(dataPoints, -1.0, 1.0)
Dim clampedSpline3 As CubicSpline = CubicSpline.CreateClamped(xValues, yValues, -1.0, 1.0)
Dim clampedSpline4 As CubicSpline = CubicSpline.CreateClamped(dataPoints, -1.0, 1.0)
No code example is currently available or this language may not be supported.
let clampedSpline1 = CubicSpline(xValues, yValues, -1.0, 1.0)
let clampedSpline2 = CubicSpline(dataPoints, -1.0, 1.0)
let clampedSpline3 = CubicSpline.CreateClamped(xValues, yValues, -1.0, 1.0)
let 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);
Dim akimaSpline1 As CubicSpline = New CubicSpline(xValues, yValues, CubicSplineKind.Akima)
Dim akimaSpline2 As CubicSpline = New CubicSpline(dataPoints, CubicSplineKind.Akima)
Dim akimaSpline3 As CubicSpline = CubicSpline.CreateAkima(xValues, yValues)
Dim akimaSpline4 As CubicSpline = CubicSpline.CreateAkima(dataPoints)
No code example is currently available or this language may not be supported.
let akimaSpline1 = CubicSpline(xValues, yValues, CubicSplineKind.Akima)
let akimaSpline2 = CubicSpline(dataPoints, CubicSplineKind.Akima)
let akimaSpline3 = CubicSpline.CreateAkima(xValues, yValues)
let 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.Create(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);
Dim weights = Vector.Reciprocal(yValues)
Dim smoothingSpline1 As CubicSpline = New CubicSpline(xValues, yValues, 0.5, weights)
Dim smoothingSpline2 As CubicSpline = New CubicSpline(dataPoints, 0.5, weights)
Dim smoothingSpline3 As CubicSpline = CubicSpline.CreateSmooth(xValues, yValues, 0.5)
Dim smoothingSpline4 As CubicSpline = CubicSpline.CreateSmooth(dataPoints, 0.5)
No code example is currently available or this language may not be supported.
let weights = Vector.Reciprocal(yValues)
let smoothingSpline1 = CubicSpline(xValues, yValues, 0.5, weights)
let smoothingSpline2 = CubicSpline(dataPoints, 0.5, weights)
let smoothingSpline3 = CubicSpline.CreateSmooth(xValues, yValues, 0.5)
let 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);
Dim monotonicSpline1 As CubicSpline = New CubicSpline(xValues, yValues, CubicSplineKind.Monotonic)
Dim monotonicSpline2 As CubicSpline = New CubicSpline(dataPoints, CubicSplineKind.Monotonic)
Dim monotonicSpline3 As CubicSpline = CubicSpline.CreateMonotonic(xValues, yValues)
Dim monotonicSpline4 As CubicSpline = CubicSpline.CreateMonotonic(dataPoints)
No code example is currently available or this language may not be supported.
let monotonicSpline1 = CubicSpline(xValues, yValues, CubicSplineKind.Monotonic)
let monotonicSpline2 = CubicSpline(dataPoints, CubicSplineKind.Monotonic)
let monotonicSpline3 = CubicSpline.CreateMonotonic(xValues, yValues)
let 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);
Dim derivatives = Vector.Create(0.5, 0.0, -0.5, 0.0, 0.5, 1.0)
Dim hermiteSpline1 As CubicSpline = New CubicSpline(xValues, yValues, derivatives)
Dim hermiteSpline2 As CubicSpline = New CubicSpline(dataPoints, derivatives)
Dim hermiteSpline3 As CubicSpline = CubicSpline.CreateHermiteInterpolant(xValues, yValues, derivatives)
Dim hermiteSpline4 As CubicSpline = CubicSpline.CreateHermiteInterpolant(dataPoints, derivatives)
No code example is currently available or this language may not be supported.
let derivatives = Vector.Create(0.5, 0.0, -0.5, 0.0, 0.5, 1.0)
let hermiteSpline1 = CubicSpline(xValues, yValues, derivatives)
let hermiteSpline2 = CubicSpline(dataPoints, derivatives)
let hermiteSpline3 = CubicSpline.CreateHermiteInterpolant(xValues, yValues, derivatives)
let 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));
Console.WriteLine("naturalSpine1.ValueAt(2) = {0}", naturalSpline1.ValueAt(2))
Console.WriteLine("naturalSpine1.SlopeAt(2) = {0}", naturalSpline1.SlopeAt(2))
No code example is currently available or this language may not be supported.
Console.WriteLine("naturalSpine1.ValueAt(2) = {0}", naturalSpline1.ValueAt(2.0))
Console.WriteLine("naturalSpine1.SlopeAt(2) = {0}", naturalSpline1.SlopeAt(2.0))
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);
Dim integral As Double = naturalSpline1.Integral(2.2, 5.4)
No code example is currently available or this language may not be supported.
let 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.