Top Qs
Timeline
Chat
Perspective
Monotone cubic interpolation
Variant of cubic interpolation that preserves monotonicity From Wikipedia, the free encyclopedia
Remove ads
In the mathematical field of numerical analysis, monotone cubic interpolation is a variant of cubic interpolation that preserves monotonicity of the data set being interpolated.
Monotonicity is preserved by linear interpolation but not guaranteed by cubic interpolation.
Monotone cubic Hermite interpolation
Summarize
Perspective

Monotone interpolation can be accomplished using cubic Hermite spline with the tangents modified to ensure the monotonicity of the resulting Hermite spline.
An algorithm is also available for monotone quintic Hermite interpolation.
Interpolant selection
There are several ways of selecting interpolating tangents for each data point. This section will outline the use of the Fritsch–Carlson method. Note that only one pass of the algorithm is required.
Let the data points be indexed in sorted order for .
- Compute the slopes of the secant lines between successive points:
for . - These assignments are provisional, and may be superseded in the remaining steps. Initialize the tangents at every interior data point as the average of the secants,
for .
For the endpoints, use one-sided differences:
If and have opposite signs, set ..
- For , where ever (where ever two successive are equal),
set as the spline connecting these points must be flat to preserve monotonicity.
Ignore steps 4 and 5 for those . - Let
If either or is negative, then the input data points are not strictly monotone, and is a local extremum. In such cases, piecewise monotone curves can still be generated by choosing if or if , although strict monotonicity is not possible globally..
- To prevent overshoot and ensure monotonicity, at least one of the following three conditions must be met:
- (a) the function
, or
- (b) , or
- (c) .
- Only condition (a) is sufficient to ensure strict monotonicity: must be positive.
- One simple way to satisfy this constraint is to restrict the vector to a circle of radius 3. That is, if , then set
and rescale the tangents via,
.
- Alternatively it is sufficient to restrict and . To accomplish this, if , then set , and if , then set .
- (a) the function
Cubic interpolation
After the preprocessing above, evaluation of the interpolated spline is equivalent to a cubic Hermite spline, using the data , , and for .
To evaluate at , find the index in the sequence where , lies between , and , that is: . Calculate
then the interpolated value is
where are the basis functions for the cubic Hermite spline.
Remove ads
Example implementation
Summarize
Perspective
The following Python implementation takes a data set and produces a monotone cubic spline interpolant function:
"""
Monotone Cubic Spline Interpolation.
"""
def create_interpolant(xs, ys):
n = len(xs)
if n != len(ys):
raise ValueError("xs and ys must have the same length.")
if n == 0:
return lambda x: (0.0, 0.0)
if n == 1:
value = float(ys[0])
return lambda x: (value, 0.0)
# Sort xs and ys together
sorted_pairs = sorted(zip(xs, ys), key=lambda p: p[0])
xs = [float(x) for x, _ in sorted_pairs]
ys = [float(y) for _, y in sorted_pairs]
# Compute consecutive differences and slopes
dxs = [xs[i + 1] - xs[i] for i in range(n - 1)]
dys = [ys[i + 1] - ys[i] for i in range(n - 1)]
ms = [dy / dx for dx, dy in zip(dxs, dys)]
# Compute first-degree coefficients (c1s)
c1s = [ms[0]]
for i in range(len(ms) - 1):
m, m_next = ms[i], ms[i + 1]
if m * m_next <= 0:
c1s.append(0.0)
else:
dx, dx_next = dxs[i], dxs[i + 1]
common = dx + dx_next
c1s.append(
3 * common / ((common + dx_next) / m + (common + dx) / m_next)
)
c1s.append(ms[-1])
# Compute second- and third-degree coefficients (c2s, c3s)
c2s, c3s = [], []
for i in range(len(c1s) - 1):
c1, m = c1s[i], ms[i]
inv_dx = 1 / dxs[i]
common = c1 + c1s[i + 1] - 2 * m
c2s.append((m - c1 - common) * inv_dx)
c3s.append(common * inv_dx * inv_dx)
def interpolant(x):
# Clamp x to range
if x <= xs[0]:
i = 0
elif x >= xs[-1]:
i = n - 2
else:
# Binary search for interval
low, high = 0, n - 2
while low <= high:
mid = (low + high) // 2
if xs[mid] < x:
low = mid + 1
else:
high = mid - 1
i = max(0, high)
dx = x - xs[i]
val = ys[i] + dx * (c1s[i] + dx * (c2s[i] + dx * c3s[i]))
dval = c1s[i] + dx * (2 * c2s[i] + dx * 3 * c3s[i])
return val, dval
return interpolant
# Example usage
if __name__ == "__main__":
X = [0, 1, 2, 3, 4]
Y = [0, 1, 4, 9, 16]
spline = create_interpolant(X, Y)
print("# Data")
print("x\tf(x)")
for x, y in zip(X, Y):
print(f"{x:.6f}\t{y:.6f}")
print("\n# Interpolated values")
print("x\tP(x)\tdP(x)/dx")
M = 25
for i in range(M + 1):
x = X[0] + (X[-1] - X[0]) * i / M
p, dp = spline(x)
print(f"{x:.6f}\t{p:.6f}\t{dp:.6f}")
Remove ads
References
- Fritsch, F. N.; Carlson, R. E. (1980). "Monotone Piecewise Cubic Interpolation". SIAM Journal on Numerical Analysis. 17 (2). SIAM: 238–246. Bibcode:1980SJNA...17..238F. doi:10.1137/0717021.
- Dougherty, R.L.; Edelman, A.; Hyman, J.M. (April 1989). "Positivity-, monotonicity-, or convexity-preserving cubic and quintic Hermite interpolation". Mathematics of Computation. 52 (186): 471–494. doi:10.2307/2008477. JSTOR 2008477.
External links
- GPLv2 licensed C++ implementation: MonotCubicInterpolator.cpp MonotCubicInterpolator.hpp
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads