fminunc.m
Upload User: ypzh139
Upload Date: 2009-07-14
Package Size: 1141k
Code Size: 12k
Category:

matlab

Development Platform:

Matlab

  1. function [x,FVAL,EXITFLAG,OUTPUT,GRAD,HESSIAN] = fminunc(FUN,x,options,varargin)
  2. %FMINUNC finds the minimum of a function of several variables.
  3. %   X=FMINUNC(FUN,X0) starts at X0 and attempts to find a local minimizer X 
  4. %   of the function FUN. FUN accepts input X and returns a scalar function 
  5. %   value F evaluated at X. X0 can be a scalar, vector or matrix. 
  6. %
  7. %   X=FMINUNC(FUN,X0,OPTIONS) minimizes with the default optimization
  8. %   parameters replaced by values in the structure OPTIONS, an argument
  9. %   created with the OPTIMSET function.  See OPTIMSET for details.  Used
  10. %   options are Display, TolX, TolFun, DerivativeCheck, Diagnostics,
  11. %   FunValCheck, GradObj, HessPattern, Hessian, HessMult, HessUpdate,
  12. %   InitialHessType, InitialHessMatrix, MaxFunEvals, MaxIter, DiffMinChange
  13. %   and DiffMaxChange, LargeScale, MaxPCGIter, PrecondBandWidth, TolPCG,
  14. %   PlotFcns, OutputFcn, and TypicalX. Use the GradObj option to specify
  15. %   that FUN also returns a second output argument G that is the partial
  16. %   derivatives of the function df/dX, at the point X. Use the Hessian
  17. %   option to specify that FUN also returns a third output argument H that
  18. %   is the 2nd partial derivatives of the function (the Hessian) at the
  19. %   point X. The Hessian is only used by the large-scale method, not the
  20. %   line-search method. 
  21. %
  22. %   X = FMINUNC(PROBLEM) finds the minimum for PROBLEM. PROBLEM is a
  23. %   structure with the function FUN in PROBLEM.objective, the start point
  24. %   in PROBLEM.x0, the options structure in PROBLEM.options, and solver
  25. %   name 'fminunc' in PROBLEM.solver. Use this syntax to solve at the command
  26. %   line a problem exported from OPTIMTOOL. The structure PROBLEM must have 
  27. %   all the fields.
  28. %
  29. %   [X,FVAL]=FMINUNC(FUN,X0,...) returns the value of the objective 
  30. %   function FUN at the solution X.
  31. %
  32. %   [X,FVAL,EXITFLAG]=FMINUNC(FUN,X0,...) returns an EXITFLAG that describes 
  33. %   the exit condition of FMINUNC. Possible values of EXITFLAG and the 
  34. %   corresponding exit conditions are
  35. %
  36. %     1  Magnitude of gradient smaller than the specified tolerance. 
  37. %     2  Change in X smaller than the specified tolerance.
  38. %     3  Change in the objective function value smaller than the specified 
  39. %         tolerance (only occurs in the large-scale method).
  40. %     0  Maximum number of function evaluations or iterations reached.
  41. %    -1  Algorithm terminated by the output function.
  42. %    -2  Line search cannot find an acceptable point along the current
  43. %         search direction (only occurs in the medium-scale method).
  44. %   
  45. %   [X,FVAL,EXITFLAG,OUTPUT]=FMINUNC(FUN,X0,...) returns a structure OUTPUT
  46. %   with the number of iterations taken in OUTPUT.iterations, the number
  47. %   of function evaluations in OUTPUT.funcCount, the algorithm used in
  48. %   OUTPUT.algorithm, the number of CG iterations (if used) in
  49. %   OUTPUT.cgiterations, the first-order optimality (if used) in
  50. %   OUTPUT.firstorderopt, and the exit message in OUTPUT.message.
  51. %
  52. %   [X,FVAL,EXITFLAG,OUTPUT,GRAD]=FMINUNC(FUN,X0,...) returns the value 
  53. %   of the gradient of FUN at the solution X.
  54. %
  55. %   [X,FVAL,EXITFLAG,OUTPUT,GRAD,HESSIAN]=FMINUNC(FUN,X0,...) returns the 
  56. %   value of the Hessian of the objective function FUN at the solution X.
  57. %
  58. %   Examples
  59. %     FUN can be specified using @:
  60. %        X = fminunc(@myfun,2)
  61. %
  62. %   where myfun is a MATLAB function such as:
  63. %
  64. %       function F = myfun(x)
  65. %       F = sin(x) + 3;
  66. %
  67. %     To minimize this function with the gradient provided, modify
  68. %     the function myfun so the gradient is the second output argument:
  69. %        function [f,g]= myfun(x)
  70. %         f = sin(x) + 3;
  71. %         g = cos(x);
  72. %     and indicate the gradient value is available by creating an options
  73. %     structure with OPTIONS.GradObj set to 'on' (using OPTIMSET):
  74. %        options = optimset('GradObj','on');
  75. %        x = fminunc(@myfun,4,options);
  76. %
  77. %     FUN can also be an anonymous function:
  78. %        x = fminunc(@(x) 5*x(1)^2 + x(2)^2,[5;1])
  79. %
  80. %   If FUN is parameterized, you can use anonymous functions to capture the problem-
  81. %   dependent parameters. Suppose you want to minimize the objective given in the 
  82. %   function myfun, which is parameterized by its second argument c. Here myfun is 
  83. %   an M-file function such as
  84. %
  85. %     function [f,g] = myfun(x,c)
  86. %
  87. %     f = c*x(1)^2 + 2*x(1)*x(2) + x(2)^2; % function
  88. %     g = [2*c*x(1) + 2*x(2)               % gradient
  89. %          2*x(1) + 2*x(2)];
  90. %
  91. %   To optimize for a specific value of c, first assign the value to c. Then 
  92. %   create a one-argument anonymous function that captures that value of c 
  93. %   and calls myfun with two arguments. Finally, pass this anonymous function 
  94. %   to FMINUNC:
  95. %
  96. %     c = 3;                              % define parameter first
  97. %     options = optimset('GradObj','on'); % indicate gradient is provided 
  98. %     x = fminunc(@(x) myfun(x,c),[1;1],options)
  99. %
  100. %   See also OPTIMSET, FMINSEARCH, FMINBND, FMINCON, @, INLINE.
  101. %   When options.LargeScale=='on', the algorithm is a trust-region method.
  102. %   When options.LargeScale=='off', the algorithm is the BFGS Quasi-Newton 
  103. %   method with a mixed quadratic and cubic line search procedure. 
  104. %   Copyright 1990-2006 The MathWorks, Inc.
  105. %   $Revision: 1.26.4.13 $  $Date: 2006/05/19 20:18:47 $
  106.  
  107. % ------------Initialization----------------
  108. defaultopt = struct('Display','final','LargeScale','on', ...
  109.    'TolX',1e-6,'TolFun',1e-6,'DerivativeCheck','off',...   
  110.    'Diagnostics','off','FunValCheck','off',...
  111.    'GradObj','off','MaxFunEvals','100*numberOfVariables',...
  112.    'DiffMaxChange',1e-1,'DiffMinChange',1e-8,...
  113.    'PrecondBandWidth',0,'TypicalX','ones(numberOfVariables,1)',...
  114.    'MaxPCGIter','max(1,floor(numberOfVariables/2))', ...
  115.    'TolPCG',0.1,'MaxIter',400,...
  116.    'Hessian','off','HessMult',[],...
  117.    'HessPattern','sparse(ones(numberOfVariables))',...
  118.    'HessUpdate','bfgs','OutputFcn',[],'PlotFcns',[], ...
  119.    'InitialHessType','scaled-identity','InitialHessMatrix',[]); 
  120. % If just 'defaults' passed in, return the default options in X
  121. if nargin==1 && nargout <= 1 && isequal(FUN,'defaults')
  122.    x = defaultopt;
  123.    return
  124. end
  125. if nargin < 3, options=[]; end 
  126. % Detect problem structure input
  127. if nargin == 1
  128.     if isa(FUN,'struct')
  129.         [FUN,x,options] = separateOptimStruct(FUN);
  130.     else % Single input and non-structure.
  131.         error('optim:fminunc:InputArg','The input to FMINUNC should be either a structure with valid fields or consist of at least two arguments.');
  132.     end
  133. end
  134. if nargin == 0 
  135.   error('optim:fminunc:NotEnoughInputs','FMINUNC requires two input arguments.')
  136. end
  137. if nargout > 5
  138.   computeHessian = true;
  139. else
  140.   computeHessian = false;    
  141. end
  142. % Check for non-double inputs
  143. if ~isa(x,'double')
  144.   error('optim:fminunc:NonDoubleInput', ...
  145.         'FMINUNC only accepts inputs of data type double.')
  146. end
  147. XOUT=x(:);
  148. numberOfVariables=length(XOUT);
  149. medium = 'medium-scale: Quasi-Newton line search'; 
  150. large = 'large-scale: trust-region Newton'; 
  151. switch optimget(options,'Display',defaultopt,'fast')
  152. case {'off','none'}
  153.    verbosity = 0;
  154. case 'notify'
  155.    verbosity = 1;  
  156. case 'final'
  157.    verbosity = 2;   
  158. case 'iter'
  159.    verbosity = 3;
  160. case 'testing'
  161.    verbosity = Inf;
  162. otherwise
  163.    verbosity = 2;
  164. end
  165. diagnostics = isequal(optimget(options,'Diagnostics',defaultopt,'fast'),'on');
  166. mtxmpy = optimget(options,'HessMult',defaultopt,'fast');
  167. if isequal(mtxmpy,'hmult')
  168.    warning('optim:fminunc:HessMultNameClash', ...
  169.       ['Potential function name clash with a Toolbox helper function:n' ...
  170.        ' Use a name besides ''hmult'' for your HessMult function to' ...
  171.        ' avoid errorsn or unexpected results.'])
  172. end
  173. gradflag =  strcmp(optimget(options,'GradObj',defaultopt,'fast'),'on');
  174. hessflag = strcmp(optimget(options,'Hessian',defaultopt,'fast'),'on');
  175. % line_search: 0 means trust-region, 1 means line-search
  176. line_search = strcmp(optimget(options,'LargeScale',defaultopt,'fast'),'off'); 
  177. funValCheck = strcmp(optimget(options,'FunValCheck',defaultopt,'fast'),'on');
  178. computeLambda = 0;
  179. % Convert to inline function as needed
  180. if ~isempty(FUN)  % will detect empty string, empty matrix, empty cell array
  181.    funfcn = optimfcnchk(FUN,'fminunc',length(varargin),funValCheck,gradflag,hessflag);
  182. else
  183.    error('optim:fminunc:InvalidFUN','FUN must be function handle or a cell array of two function handles.')
  184. end
  185. GRAD = zeros(numberOfVariables,1);
  186. HESS = [];
  187. switch funfcn{1}
  188. case 'fun'
  189.    f = feval(funfcn{3},x,varargin{:});
  190. case 'fungrad'
  191.    [f,GRAD(:)] = feval(funfcn{3},x,varargin{:});
  192. case 'fungradhess'
  193.    [f,GRAD(:),HESS] = feval(funfcn{3},x,varargin{:});
  194. case 'fun_then_grad'
  195.    f = feval(funfcn{3},x,varargin{:}); 
  196.    GRAD(:) = feval(funfcn{4},x,varargin{:});
  197. case 'fun_then_grad_then_hess'
  198.    f = feval(funfcn{3},x,varargin{:}); 
  199.    GRAD(:) = feval(funfcn{4},x,varargin{:});
  200.    HESS = feval(funfcn{5},x,varargin{:});
  201. otherwise
  202.    error('optim:fminunc:UndefCalltype','Undefined calltype in FMINUNC.');
  203. end
  204. % Check that the objective value is a scalar
  205. if numel(f) ~= 1
  206.    error('optim:fminunc:NonScalarObj','User supplied objective function must return a scalar value.')
  207. end
  208. % Determine algorithm
  209. % If line-search and no hessian,  then call line-search algorithm
  210. if line_search  && ...
  211.       (~isequal(funfcn{1}, 'fun_then_grad_then_hess') && ~isequal(funfcn{1}, 'fungradhess'))
  212.   output.algorithm = medium; 
  213.     
  214.   % Line-search and Hessian -- no can do, so do line-search after warning: ignoring hessian.   
  215. elseif line_search && ...
  216.         (isequal(funfcn{1}, 'fun_then_grad_then_hess') || isequal(funfcn{1}, 'fungradhess'))
  217.     warning('optim:fminunc:HessIgnored', ...  
  218.         ['Medium-scale method is a Quasi-Newton method and does not use analytic Hessian.n' ...
  219.         ' Hessian flag in options will be ignored (user-supplied Hessian will not be used).'])
  220.     if isequal(funfcn{1}, 'fun_then_grad_then_hess')
  221.         funfcn{1} = 'fun_then_grad';
  222.     elseif isequal(funfcn{1}, 'fungradhess')
  223.         funfcn{1} = 'fungrad';
  224.     end
  225.     output.algorithm = medium;
  226.     % If not line-search (trust-region) and Hessian, call trust-region   
  227. elseif ~line_search && ...
  228.         (isequal(funfcn{1}, 'fun_then_grad_then_hess') || isequal(funfcn{1}, 'fungradhess'))
  229.    l=[]; u=[]; Hstr=[];
  230.    output.algorithm = large; 
  231. % If not line search (trust-region) and no Hessian but grad, use sparse finite-differencing.
  232. elseif ~line_search && ...
  233.       (isequal(funfcn{1}, 'fun_then_grad') || isequal(funfcn{1}, 'fungrad'))
  234.    n = length(XOUT); 
  235.    Hstr = optimget(options,'HessPattern',defaultopt,'fast');
  236.    if ischar(Hstr) 
  237.       if isequal(lower(Hstr),'sparse(ones(numberofvariables))')
  238.       % Put this code separate as it might generate OUT OF MEMORY error
  239.          Hstr = sparse(ones(n));
  240.       else
  241.          error('optim:fminunc:InvalidHessPattern', ...
  242.                'Option ''HessPattern'' must be a matrix if not the default.')
  243.       end
  244.    end
  245.    l=[]; u=[];
  246.    output.algorithm = large;
  247.    
  248.    % Trust region but no grad, no can do; warn and use line-search    
  249. elseif ~line_search
  250.    warning('optim:fminunc:SwitchingMethod', ...
  251.       ['Gradient must be provided for trust-region method;n ' ...
  252.       ' using line-search method instead.'])
  253.    output.algorithm = medium;
  254. else
  255.    error('optim:fminunc:InvalidProblem','Problem not handled by FMINUNC.')   
  256. end
  257. if diagnostics > 0
  258.    % Do diagnostics on information so far
  259.    constflag = 0; gradconstflag = 0; non_eq=0;non_ineq=0;lin_eq=0;lin_ineq=0;
  260.    LB=[]; UB =[];confcn{1}=[];c=[];ceq=[];cGRAD=[];ceqGRAD=[];
  261.    msg = diagnose('fminunc',output,gradflag,hessflag,constflag,gradconstflag,...
  262.       line_search,options,defaultopt,XOUT,non_eq,...
  263.       non_ineq,lin_eq,lin_ineq,LB,UB,funfcn,confcn,f,GRAD,HESS,c,ceq,cGRAD,ceqGRAD);
  264.    
  265. end
  266. % If line-search and no hessian,  then call line-search algorithm
  267. if isequal(output.algorithm, medium)
  268.    [x,FVAL,GRAD,HESSIAN,EXITFLAG,OUTPUT] = fminusub(funfcn,x,verbosity, ...
  269.       options,defaultopt,f,GRAD,HESS,computeHessian,varargin{:});
  270. elseif isequal(output.algorithm, large)
  271.    [x,FVAL,LAMBDA,EXITFLAG,OUTPUT,GRAD,HESSIAN] = sfminbx(funfcn,x,l,u, ...
  272.       verbosity,options,defaultopt,computeLambda,f,GRAD,HESS,Hstr,varargin{:});
  273.    OUTPUT.algorithm = large; % override sfminbx output: not using the reflective 
  274.                              % part of the method   
  275. end