# Constraining a fitted curve

12 views (last 30 days)
David on 9 Jan 2012
Hi all,
I'm created cubic fitted curves in matlab based on a set of data points. There is however one requirement that I have to meet: the fitted curve can not decrease in y value as x increases. What I would like to happen is that whenever the fitted curve is supposed to decrease in y value, the curve is somehow constrained so that it flattens out (slope of 0). Is there any possible way to do this?

Richard Willey on 9 Jan 2012
I'd strongly recommend that you look at a file exchange submission by John D'Errico titled "Shape Modeling Language"

Andrew Newell on 9 Jan 2012
Tricky. Suppose that your fit is
y = p(1)*x^3 + p(2)*x^2 + p(3)*x+p(4);
You'll need to ensure that the first derivative
yp = @(x) 3*p(1)*x^2 + 2*p(2)*x^2 + p(3);
is positive across the entire interval [x1,x2]. Certainly
yp(x1) >= 0 && yp(x2) >= 0
must be satisfied. If the slope doesn't have a minimum in the interval, you're done. Taking the derivative of yp shows that an extremum occurs at
x0 = -p(2)/3/p(1)
(for this analysis it doesn't really matter if it is a minimum or maximum). If
x(1) >= x0 || x0 >= x1
the extremum is outside the interval. Otherwise, you need to calculate the minimum and ensure it is nonnegative:
3*p(1)*p(3)-p(2)^2 >= 0
Putting the constraints together,
-yp(x1) <= 0
-yp(x2) <= 0
(x1 <= x0 && x0 <= x1)*(p(2)^2-3*p(1)*p(3)) <= 0
You could use this to create a constraint function c(p) that you can use in fmincon (you would be minimizing the sum of squares).
On the other hand, if your data are monotonically increasing, you could discard the cubic fit and interpolate using pchip.

Dr. Seis on 9 Jan 2012
Here is an example using "pchip":
a = sort(rand(1,15),'ascend');
b = sort(rand(1,15),'ascend');
x = a(1):0.001:a(end);
y = pchip(a,b,x);
figure; plot(a,b,'b',x,y,'r');
z = sum(diff(y)<0)
It looks like as long as you are interpolating between points (no extrapolation) the result from "pchip" will not give you any decreasing "y" values for increasing "x" values when your data values (i.e., "a" and "b") are also increasing. As a test, the result of "z" should be 0 and it was for all my test runs (ran 10000 tests).