function [x,FVAL,EXITFLAG,OUTPUT,JACOB] = fsolve(FUN,x,options,varargin)
%优化工具箱函数,可求多元非线性方程组的实根. 用法与fzero类似。
%例 先写一个M函数rooteg4fun.m
% function y=rooteg4fun(x)
% y(1)=4*x(1)-x(2)+exp(x(1))/10-1;
% y(2)=-x(1)+4*x(2)+x(1).^2/8;
% 使用
% [x,f,h]=fsolve('rooteg4fun',[0,0]) %初值x(1)=0,x(2)=0
% x返回解向量,f返回误差向量,h>0表明算法收敛
% 注意:方程变量必须拼成一个向量变量,即用x(1),x(2),...
%
%FSOLVE Solves nonlinear equations by a least squares method.
%
% FSOLVE solves equations of the form:
%
% F(X)=0 where F and X may be vectors or matrices.
%
% X=FSOLVE(FUN,X0) starts at the matrix X0 and tries to solve the
% equations described in FUN. FUN is usually an M-file which returns
% an evaluation of the equations for a particular value of X: F=FUN(X).
%
% X=FSOLVE(FUN,X0,OPTIONS) minimizes with the default optimization
% parameters replaced by values in the structure OPTIONS, an argument
% created with the OPTIMSET function. See OPTIMSET for details. Used
% options are Display, TolX, TolFun, DerivativeCheck, Diagnostics, Jacobian,
% JacobPattern, LineSearchType, LevenbergMarquardt, MaxFunEvals, MaxIter,
% DiffMinChange and DiffMaxChange, LargeScale, MaxPCGIter, PrecondBandWidth,
% TolPCG, TypicalX. Use the Jacobian option to specify that FUN may be called
% with two output arguments where the second, J, is the Jacobian matrix:
% [F,J] = feval(FUN,X). If FUN returns a vector (matrix) of m components when
% X has length n, then J is an m-by-n matrix where J(i,j) is the partial
% derivative of F(i) with respect to x(j). (Note that the Jacobian J is the
% transpose of the gradient of F.)
%
% X=FSOLVE(FUN,X0,OPTIONS,P1,P2,...) passes the problem-dependent
% parameters P1,P2,... directly to the function FUN: FUN(X,P1,P2,...).
% Pass an empty matrix for OPTIONS to use the default values.
%
% [X,FVAL]=FSOLVE(FUN,X0,...) returns the value of the objective function
% at X.
%
% [X,FVAL,EXITFLAG]=FSOLVE(FUN,X0,...) returns a string EXITFLAG that
% describes the exit condition of FSOLVE.
% If EXITFLAG is:
% > 0 then FSOLVE converged to a solution X.
% 0 then the maximum number of function evaluations was reached.
% < 0 then FSOLVE did not converge to a solution.
%
% [X,FVAL,EXITFLAG,OUTPUT]=FSOLVE(FUN,X0,...) returns a structure OUTPUT
% with the number of iterations taken in OUTPUT.iterations, the number of
% function evaluations in OUTPUT.funcCount, the algorithm used in OUTPUT.algorithm,
% the number of CG iterations (if used) in OUTPUT.cgiterations, and the first-order
% optimality (if used) in OUTPUT.firstorderopt.
%
% [X,FVAL,EXITFLAG,OUTPUT,JACOB]=FSOLVE(FUN,X0,...) returns the
% Jacobian of FUN at X.
% Copyright (c) 1990-98 by The MathWorks, Inc.
% $Revision: 1.26 $ $Date: 1998/10/22 19:28:31 $
% Andy Grace 7-9-90.
% Grandfathered FSOLVE call for Optimization Toolbox versions prior to 2.0:
% [X,OPTIONS]=FSOLVE(FUN,X0,OPTIONS,GRADFUN,P1,P2,...)
%
% ------------Initialization----------------
defaultopt = optimset('display','final','LargeScale','on', ...
'TolX',1e-6,'TolFun',1e-6,'DerivativeCheck','off',...
'Jacobian','off','MaxFunEvals','100*numberOfVariables',...
'Diagnostics','off',...
'DiffMaxChange',1e-1,'DiffMinChange',1e-8,...
'PrecondBandWidth',0,'TypicalX','ones(numberOfVariables,1)','MaxPCGIter','max(1,floor(numberOfVariables/2))', ...
'TolPCG',0.1,'MaxIter',400,'JacobPattern',[], ...
'LineSearchType','quadcubic','LevenbergMarq','off');
% If just 'defaults' passed in, return the default options in X
if nargin==1 & nargout <= 1 & isequal(FUN,'defaults')
x = defaultopt;
return
end
if nargin < 2, error('FSOLVE requires two input arguments');end
if nargin < 3, options=[]; end
% These are added so that we can have the same code as in lsqnonlin which
% actually has upper and lower bounds.
LB = []; UB = [];
%[x,FVAL,EXITFLAG,OUTPUT,JACOB] = fsolve(FUNin,x,options,varargin)
% Note: don't send varargin in as a comma separated list!!
numargin = nargin; numargout = nargout;
[calltype, GRADFUN, varargin] = parse_call(FUN,options,numargin,numargout,varargin);
if isequal(calltype,'new') % fsolve version 2.*
xstart=x(:);
numberOfVariables=length(xstart);
large = 'large-scale';
medium = 'medium-scale';
l = []; u = [];
options = optimset(defaultopt,options);
switch optimget(options,'display')
case {'off','none'}
verbosity = 0;
case 'iter'
verbosity = 2;
case 'final'
verbosity = 1;
case 'testing'
verbosity = Inf;
otherwise
verbosity = 1;
end
diagnostics = isequal(optimget(options,'diagnostics','off'),'on');
gradflag = strcmp(optimget(options,'Jacobian'),'on');
line_search = strcmp(optimget(options,'largescale','off'),'off'); % 0 means trust-region, 1 means line-search
% Convert to inline function as needed
if ~isempty(FUN) % will detect empty string, empty matrix, empty cell array
[funfcn, msg] = fprefcnchk(FUN,'fsolve',length(varargin),gradflag);
else
errmsg = sprintf('%s\n%s', ...
'FUN must be a function name, valid string expression, or inline object;', ...
' or, FUN may be a cell array that contains these type of objects.');
error(errmsg)
end
x(:) = xstart;
switch funfcn{1}
case 'fun'
fuser = feval(funfcn{3},x,varargin{:});
f = fuser(:);
nfun=length(f);
JAC = zeros(nfun,numberOfVariables);
case 'fungrad'
[fuser,JAC] = feval(funfcn{3},x,varargin{:});
f = fuser(:);
nfun=length(f);
case 'fun_then_grad'
fuser = feval(funfcn{3},x,varargin{:});
f = fuser(:);
JAC = feval(funfcn{4},x,varargin{:});
nfun=length(f);
otherwise
error('Undefined calltype in FSOLVE');
end
% check size of JAC
[Jrows, Jcols]=size(JAC);
if Jrows~=nfun | Jcols ~=numberOfVariables
errstr = sprintf('%s\n%s%d%s%d\n',...
'User-defined Jacobian is not the correct size:',...
' the Jacobian matrix should be ',nfun,'-by-',numberOfVariables);
error(errstr);
end
YDATA = []; caller = 'fsolve';
% trustregion and enough equations (as many as variables)
if ~line_search & nfun >= numberOfVariables
OUTPUT.algorithm = large;
% trust region and not enough equations -- switch to line_search
elseif ~line_search & nfun < numberOfVariables
warnstr = sprintf('%s\n%s\n', ...
'Large-scale method requires at least as many equations as variables; ',...
' switching to line-search method instead.');
warning(warnstr);
OUTPUT.algorithm = medium;
% line search and no bounds
elseif line_search & isempty(l) & isempty(u)
OUTPUT.algorithm = medium;
% line search and bounds and enough equations, switch to trust region
elseif line_search & (~isempty(LB) | ~isempty(UB)) & nfun >= numberOfVariables
warnstr = sprintf('%s\n%s\n', ...
'Line-search method does not handle bound constraints; ',...
' switching to trust-region method instead.');
warning(warnstr);
OUTPUT.algorithm = large;
% can't handle this one:
elseif line_search & (~isempty(LB) | ~isempty(UB)) & nfun < numberOfVariables
errstr = sprintf('%s\n%s\n%s\n', ...
'Line-search method does not handle bound constraints ',...
' and trust-region method requires at least as many equations as variables; ',...
' aborting.');
error(errstr);
end
if diagnostics > 0
% Do diagnostics on information so far
constflag = 0; gradconstflag = 0; non_eq=0;non_ineq=0;lin_eq=0;lin_ineq=0;
confcn{1}=[];c=[];ceq=[];cGRAD=[];ceqGRAD=[];
hessflag = 0; HESS=[];
msg = diagnose('fsolv