www.gusucode.com > signal 工具箱matlab源码程序 > signal/private/lclfminbnd.m
function [xf,fval,exitflag,output] = lclfminbnd(funfcn,ax,bx,options,varargin) %LCLFMINBND Scalar bounded nonlinear function minimization. % % NOTE: This is a copy of the toolbox\matlab\funfun\fminbnd.m which % shipped in R12.1. There were changes made to the R13 version of this % file which affected the CHEB1ORD, CHEB2ORD, BUTTORD, and ELLIPORD functions % in the Signal Processing Toolbox (g142835). % % X = FMINBND(FUN,x1,x2) starts at X0 and finds a local minimizer X of the % function FUN in the interval x1 < X < x2. FUN accepts scalar input X and returns % a scalar function value F evaluated at X. % % X = FMINBND(FUN,x1,x2,OPTIONS) minimizes with the default optimization % parameters replaced by values in the structure OPTIONS, created with % the OPTIMSET function. See OPTIMSET for details. FMINBND uses these options: % Display, TolX, MaxFunEval and MaxIter. % % X = FMINBND(FUN,x1,x2,OPTIONS,P1,P2,...) provides for additional % arguments, which are passed to the objective function, FUN(X,P1,P2,...). % (Use OPTIONS = [] as a place holder if no options are set.) % % [X,FVAL] = FMINBND(...) also returns the value of the objective function, % FVAL, computed in FUN, at X. % % [X,FVAL,EXITFLAG] = FMINBND(...) also returns a string EXITFLAG that % describes the exit condition of FMINBND. % If EXITFLAG is: % 1 then FMINBND converged with a solution X based on OPTIONS.TolX % 0 then the maximum number of function evaluations was reached % % [X,FVAL,EXITFLAG,OUTPUT] = FMINBND(...) also returns a structure % OUTPUT with the number of iterations taken in OUTPUT.iterations. % % Examples % FUN can be specified using @: % X = fminbnd(@cos,3,4) % computes pi to a few decimal places and gives a message upon termination. % [X,FVAL,EXITFLAG] = fminbnd(@cos,3,4,optimset('TolX',1e-12,'Display','off')) % computes pi to about 12 decimal places, suppresses output, returns the % function value at x, and returns an EXITFLAG of 1. % % FUN can also be an anonymous function handle: % f = @(x) sin(x)+3; % x = fminbnd(f,2,5); % % See also OPTIMSET, FMINSEARCH, FZERO, @. % Reference: "Computer Methods for Mathematical Computations", % Forsythe, Malcolm, and Moler, Prentice-Hall, 1976. % Original coding by Duane Hanselman, University of Maine. % Copyright 1984-2009 The MathWorks, Inc. defaultopt = struct('Display','notify',... 'MaxFunEvals',500,'MaxIter',500,'TolX',1e-4); % If just 'defaults' passed in, return the default options in X if nargin==1 & nargout <= 1 & isequal(funfcn,'defaults') xf = defaultopt; return end if nargin < 3 error(message('signal:lclfminbnd:Nargchk')) end % initialization if nargin<4, options = []; end printtype = optimget(options,'Display',defaultopt,'fast'); tol = optimget(options,'TolX',defaultopt,'fast'); maxfun = optimget(options,'MaxFunEvals',defaultopt,'fast'); maxiter = optimget(options,'MaxIter',defaultopt,'fast'); % fun evals are the same as iterations, so just check the minimum maxcount = min(maxfun,maxiter); switch printtype case 'notify' print = 1; case {'none','off'} print = 0; case 'iter' print = 3; case 'final' print = 2; otherwise print = 1; end % checkbounds if ax > bx exitflag = -1; output = []; xf=[]; fval = []; if print > 0 msg=sprintf([getString(message('signal:lclfminbnd:ExitingDueToInfeasibility'))]); disp(msg) end return end % Assume we'll converge exitflag = 1; header = ' Func-count x f(x) Procedure'; step=' initial'; % Convert to inline function as needed. funfcn = fcnchk(funfcn,length(varargin)); seps = sqrt(eps); c = 0.5*(3.0 - sqrt(5.0)); a = ax; b = bx; v = a + c*(b-a); w = v; xf = v; d = 0.0; e = 0.0; x= xf; fx = feval(funfcn,x,varargin{:}); num = 1; fmin_data = [ 1 xf fx ]; if print > 2 disp(' ') disp(header) disp([sprintf('%5.0f %12.6g %12.6g ',fmin_data), step]) end fv = fx; fw = fx; xm = 0.5*(a+b); tol1 = seps*abs(xf) + tol/3.0; tol2 = 2.0*tol1; % Main loop while ( abs(xf-xm) > (tol2 - 0.5*(b-a)) ) gs = 1; % Is a parabolic fit possible if abs(e) > tol1 % Yes, so fit parabola gs = 0; r = (xf-w)*(fx-fv); q = (xf-v)*(fx-fw); p = (xf-v)*q-(xf-w)*r; q = 2.0*(q-r); if q > 0.0, p = -p; end q = abs(q); r = e; e = d; % Is the parabola acceptable if ( (abs(p)<abs(0.5*q*r)) & (p>q*(a-xf)) & (p<q*(b-xf)) ) % Yes, parabolic interpolation step d = p/q; x = xf+d; step = ' parabolic'; % f must not be evaluated too close to ax or bx if ((x-a) < tol2) | ((b-x) < tol2) si = sign(xm-xf) + ((xm-xf) == 0); d = tol1*si; end else % Not acceptable, must do a golden section step gs=1; end end if gs % A golden-section step is required if xf >= xm, e = a-xf; else, e = b-xf; end d = c*e; step = ' golden'; end % The function must not be evaluated too close to xf si = sign(d) + (d == 0); x = xf + si * max( abs(d), tol1 ); fu = feval(funfcn,x,varargin{:}); num = num+1; fmin_data = [num x fu]; if print > 2 disp([sprintf('%5.0f %12.6g %12.6g ',fmin_data), step]) end % Update a, b, v, w, x, xm, tol1, tol2 if fu <= fx if x >= xf, a = xf; else, b = xf; end v = w; fv = fw; w = xf; fw = fx; xf = x; fx = fu; else % fu > fx if x < xf, a = x; else,b = x; end if ( (fu <= fw) | (w == xf) ) v = w; fv = fw; w = x; fw = fu; elseif ( (fu <= fv) | (v == xf) | (v == w) ) v = x; fv = fu; end end xm = 0.5*(a+b); tol1 = seps*abs(xf) + tol/3.0; tol2 = 2.0*tol1; if num >= maxcount exitflag = 0; output.iterations=num; output.funcCount=num; fval = fx; if print > 0 terminate(x,exitflag,fval,maxfun,maxiter,tol,print); end return end end fval = fx; output.iterations = num; output.funcCount = num; output.algorithm = 'golden section search, parabolic interpolation'; if print > 0 terminate(x,exitflag,fval,maxfun,maxiter,tol,print); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function terminate(x,exitflag,finalf,maxfun,maxiter,tol,print) switch exitflag case 1 if print > 1 % only print success if not 'off' or 'notify' convmsg1 = getString(message('signal:lclfminbnd:OptimizationTerminatedSuccessfully', sprintf('%e',tol))); disp(convmsg1) end case 0 if maxfun <= maxiter disp(' ') warning(message('signal:lclfminbnd:DidNotConvergeFunctionEvals', 'MaxFunEvals')); else disp(' ') warning(message('signal:lclfminbnd:DidNotConvergeIters', 'MaxIter')); msg = sprintf([' ' getString(message('signal:lclfminbnd:CurrentFunctionValue')) ': %f \n'], finalf); disp(msg) end case -1 ; otherwise ; end