www.gusucode.com > optim 案例源码 matlab代码程序 > optim/FitaModeltoComplexValuedDataExample.m

    %% Fit a Model to Complex-Valued Data  
% This example shows how to perform nonlinear fitting of complex-valued
% data. While most Optimization Toolbox(TM) solvers and algorithms operate
% only on real-valued data, least-squares solvers and |fsolve| can work on
% both real-valued and complex-valued data for unconstrained problems. The
% objective function must be analytic in the complex function sense.
%
% Do not set the |FunValCheck| option to |'on'| when using complex data.
% The solver errors.   

%% Data Model 
% The data model is a simple exponential:
%
% $$y(x) = v_1 + v_2 e^{v_3 x}.$$
%
% The $x$ is input data, $y$ is the response, and $v$ is a complex-valued
% vector of coefficients. The goal is to estimate $v$ from $x$ and noisy
% observations $y$. The data model is analytic, so you can use it in a
% complex solution.

%% Artificial Data with Noise 
% Generate artificial data for the model. Take the complex coefficient vector
% $v$ as |[2;3+4i;-.5+.4i]|. Take the observations $x$ as exponentially
% distributed. Add complex-valued noise to the responses $y$. 
rng default % for reproducibility
N = 100; % number of observations
v0 = [2;3+4i;-.5+.4i]; % coefficient vector
xdata = -log(rand(N,1)); % exponentially distributed
noisedata = randn(N,1).*exp((1i*randn(N,1))); % complex noise
cplxydata = v0(1) + v0(2).*exp(v0(3)*xdata) + noisedata;  

%% Fit the Model to Recover the Coefficient Vector 
% The difference between the response predicted by the data model and an
% observation (|xdata| for $x$ and response |cplxydata| for $y$) is: 
objfcn = @(v)v(1)+v(2)*exp(v(3)*xdata) - cplxydata;  

%% 
% Use either |lsqnonlin| or |lsqcurvefit| to fit the model to the data.
% This example first uses |lsqnonlin|. Because the data is complex, set
% the |Algorithm| option to |'levenberg-marquardt'|. 
opts = optimoptions(@lsqnonlin,...
    'Algorithm','levenberg-marquardt','Display','off');
x0 = (1+1i)*[1;1;1]; % arbitrary initial guess
[vestimated,resnorm,residuals,exitflag,output] = lsqnonlin(objfcn,x0,[],[],opts);
vestimated,resnorm,exitflag,output.firstorderopt 

%%
% |lsqnonlin| recovers the complex coefficient vector to about one significant
% digit. The norm of the residual is sizable, indicating that the noise
% keeps the model from fitting all the observations. The exit flag is |3|,
% not the preferable |1|, because the first-order optimality measure is
% about |1e-3|, not below |1e-6|.  

%% Alternative: Use lsqcurvefit 
% To fit using |lsqcurvefit|, write the model to give just the responses,
% not the responses minus the response data. 
objfcn = @(v,xdata)v(1)+v(2)*exp(v(3)*xdata);  

%% 
% Use |lsqcurvefit| options and syntax. 
opts = optimoptions(@lsqcurvefit,opts); % reuse the options
[vestimated,resnorm] = lsqcurvefit(objfcn,x0,xdata,cplxydata,[],[],opts) 

%%
% The results match those from |lsqnonlin|, because the underlying algorithms
% are identical. Use whichever solver you find more convenient.  

%% Alternative: Split Real and Imaginary Parts 
% To include bounds, or simply to stay completely within real values, you
% can split the real and complex parts of the coefficients into separate
% variables. For this problem, split the coefficients as follows:
%
% $$ \begin{array}{l}
% y = {v_1} + i{v_2} + ({v_3} + i{v_4})\exp \left( {({v_5} + i{v_6})x} \right)\\
% \ \  = \left( {{v_1} + {v_3}\exp ({v_5}x)\cos ({v_6}x) - {v_4}\exp ({v_5}x)\sin ({v_6}x)} \right)\\
% \ \ + i \left( {{v_2} + {v_4}\exp ({v_5}x)\cos ({v_6}x) + {v_3}\exp ({v_5}x)\sin ({v_6}x)} \right). 
% \end{array}$$
%
% Write the response function for |lsqcurvefit|.
%
% <include>cplxreal.m</include>
%
%%
% Save this code as the file |cplxreal.m| on your MATLAB(R) path.  

%% 
% Split the response data into its real and imaginary parts. 
ydata2 = [real(cplxydata),imag(cplxydata)];  

%% 
% The coefficient vector |v| now has six dimensions. Initialize it as all
% ones, and solve the problem using |lsqcurvefit|. 
x0 = ones(6,1);
[vestimated,resnorm,residuals,exitflag,output] = ...
    lsqcurvefit(@cplxreal,x0,xdata,ydata2);
vestimated,resnorm,exitflag,output.firstorderopt 

%%
% Interpret the six-element vector |vestimated| as a three-element complex
% vector, and you see that the solution is virtually the same as the previous
% solutions.