%% Nonlinear Curve Fitting with lsqcurvefit
% lsqcurvefit enables you to fit parameterized nonlinear functions to data easily. You can also use lsqnonlin; lsqcurvefit is simply a convenient way to call lsqnonlin for curve fitting.
% In this example, the vector xdata represents 100 data points, and the vector ydata represents the associated measurements. Generate the data for the problem.

rng(5489,'twister') % reproducible
xdata = -2*log(rand(100,1));
ydata = (ones(100,1) + .1*randn(100,1)) + (3*ones(100,1)+...
    0.5*randn(100,1)).*exp((-(2*ones(100,1)+...
   .5*randn(100,1))).*xdata);

% The modeled relationship between xdata and ydata is
% \[{\rm ydata}_i = {a_1} + {a_2}\exp ( - {a_3}\,{\rm xdata}_i) + {\varepsilon _i}.\]
% The code generates xdata from 100 independent samples of an exponential distribution with mean 2. The code generates ydata from its defining equation using a = [1;3;2], perturbed by adding normal deviates with standard deviations [0.1;0.5;0.5].
% The goal is to find parameters \hat{a}_i, i = 1, 2, 3, for the model that best fit the data.
% In order to fit the parameters to the data using lsqcurvefit, you need to define a fitting function. Define the fitting function predicted as an anonymous function.

predicted = @(a,xdata) a(1)*ones(100,1)+a(2)*exp(-a(3)*xdata); 

% To fit the model to the data, lsqcurvefit needs an initial estimate a0 of the parameters.

a0 = [2;2;2];

% Call lsqcurvefit to find the best-fitting parameters {\hat a}_i.

[ahat,resnorm,residual,exitflag,output,lambda,jacobian] =...
   lsqcurvefit(predicted,a0,xdata,ydata);

% Examine the resulting parameters.

disp(ahat)

% The fitted values ahat are within 8% of a = [1;3;2].
% If you have the Statistics and Machine Learning Toolbox™ software, use the nlparci function to generate confidence intervals for the ahat estimate.
% Copyright 2019 The MathWorks, Inc.