MATLAB Answers

Using lsqnonlin with a joint boundary for multiple parameters

8 views (last 30 days)
Jessica Vidmark
Jessica Vidmark on 13 May 2020
Commented: Walter Roberson on 22 May 2020
Hi MATLAB community,
My question is similar to this one, but I still cannot figure out how to apply that solution (if even possible) to my problem.
I am using lsqnonlin to find the best fit of a function with specific parameters to a dataset ("data"). This is working, but after visual inspection of my results, I would now like to force the difference between the sum of three of the parameters (exponential amplitude 1, exponential amplitude 2, and the DC offset), and the first data point, to be within +/- the standard deviation of the data - perhaps easier to understand in this mathematical equation:
abs(expAmp1+expAmp2+DCoffs-data(1)) <= std(data)
Hence, I would like to add this into my code so that the fit results don't violate this boundary condition, but I have yet to figure out how to. Let's assume for simplicity's sake that I am fitting my data to only two exponential decays and a DC offset, with an objective function like so:
function diff = objFunc(param,time,data)
%param(1)=exponential1 amplitude
%param(2)=exponential1 time constant
%param(3)=exponential2 amplitude
%param(4)=exponential2 time constant
%param(5)=DC offset
fitFunc=param(1)*exp(param(2)*time)+param(3)*exp(param(4)*time)+param(5); %Function composed of two exponentials and one DC offset (horizontal line)
diff=fitFunc-data; %Fit function to data by making diff as close to 0 as possible
I can make boundary conditions for the individual parameters, but I cannot figure out how/where I could include a boundary condition that combines three of the parameters, similar to this:
abs(param(1)+param(3)+param(5)-data(1)) <= std(data)
I've spent hours searching MATLAB Answers, reading the lsqnonlin documentation, and trying to logically come up with a solution, but I just can't figure it out on my own.
Your help would be so greatly appreciated! Thank you!
Jessica Vidmark
Jessica Vidmark on 21 May 2020
Shoot, OK. Thanks for letting me know. Do you know if it could work with lsqlin? I might be able to use a linear solver. Or can you think of any other workaround? Combining the three variables into another one that has these boundaries, or something of the sort? Or using another MATLAB function for this fit?

Sign in to comment.

Answers (1)

Walter Roberson
Walter Roberson on 21 May 2020
lsqnonlin() relies upon a function returning a vector of values, and internally it minimizes the sum of squares of what is returned. The algorithm involved permits static upper and lower bounds, but no linear or nonlinear bounds.
What you need to do is build another layer,
LSQ = @(param) sum(objFunc(param, time, data).^2)
Now pass LSQ to fmincon(). As you know your data ahead of time, you can add in a pair of linear constraints
sd = std(data);
A = [ 1 0 1 0 1;
-1 0 -1 0 -1];
b = [sd+data(1);
You would use Aeq = [], beq = [], use appropriate lb and ub, and would use [] for the nonlinear constraints.
As you extend your constraints you might find that you need to add nonlinear constraints. The search will be more efficient if you can avoid nonlinear constraints by rewriting them as linear inequalities or linear equalities.
  1 Comment
Walter Roberson
Walter Roberson on 22 May 2020
fmincon is a local minimizer and for this kind of work it would be common for it to get stuck. Running a few times with different initial values can be advised. if you have the Global Optimization Toolbox then multistart can help

Sign in to comment.




Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by