1.简述
用于求某个给定函数的最小值点。
使用方法是:
x=fminbnd(func,x1,x2)
func是函数句柄,然后x1和x2就是函数的区间,得到的结果就是使func取最小值的x值
当然也可以使用[x,fv]=fminbnd(func,x1,x2)的方式,这个时候fv就是函数 的最小值,即有:fv=f(x)
测试程序如下:
>> f=@(x) exp(x)-4*sin(x)+5;
>> [x,fv]=fminbnd(f,0,1)
x =
0.9048
fv =
4.3262
当然,如果在某个区间上是单调的,结果就有点意思了:
>> clear
>> f=@(x) x^-2*x-3;
>> [x,fv]=fminbnd(f,2,3)
x =
2.9999
fv =
-2.6667
看样子MATLAB是使用了定长小区间的方式计算的,而且结果也是错误的,这不免让人对这个函数的可靠性产生怀疑……
2.代码
主程序:
%% 最大容积问题
[xo,fo]=fminbnd('f1216',0,2)
子程序:
function [xf,fval,exitflag,output] = fminbnd(funfcn,ax,bx,options,varargin)
%FMINBND Single-variable bounded nonlinear function minimization.
% X = FMINBND(FUN,x1,x2) attempts to find a local minimizer X of the function
% FUN in the interval x1 < X < x2. FUN is a function handle. 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, MaxIter, FunValCheck, PlotFcns,
% and OutputFcn.
%
% X = FMINBND(PROBLEM) finds the minimum for PROBLEM. PROBLEM is a
% structure with the function FUN in PROBLEM.objective, the interval
% in PROBLEM.x1 and PROBLEM.x2, the options structure in PROBLEM.options,
% and solver name 'fminbnd' in PROBLEM.solver.
%
% [X,FVAL] = FMINBND(...) also returns the value of the objective function,
% FVAL, computed in FUN, at X.
%
% [X,FVAL,EXITFLAG] = FMINBND(...) also returns an EXITFLAG that
% describes the exit condition. Possible values of EXITFLAG and the
% corresponding exit conditions are
%
% 1 FMINBND converged with a solution X based on OPTIONS.TolX.
% 0 Maximum number of function evaluations or iterations reached.
% -1 Algorithm terminated by the output function.
% -2 Bounds are inconsistent (that is, ax > bx).
%
% [X,FVAL,EXITFLAG,OUTPUT] = FMINBND(...) also returns a structure
% OUTPUT with the number of iterations taken in OUTPUT.iterations, the
% number of function evaluations in OUTPUT.funcCount, the algorithm name
% in OUTPUT.algorithm, and the exit message in OUTPUT.message.
%
% 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 be an anonymous function:
% X = fminbnd(@(x) sin(x)+3,2,5)
%
% FUN can be a parameterized function. Use an anonymous function to
% capture the problem-dependent parameters:
% f = @(x,c) (x-c).^2; % The parameterized function.
% c = 1.5; % The parameter.
% X = fminbnd(@(x) f(x,c),0,1)
%
% See also OPTIMSET, FMINSEARCH, FZERO, FUNCTION_HANDLE.
% References:
% "Algorithms for Minimization Without Derivatives",
% R. P. Brent, Prentice-Hall, 1973, Dover, 2002.
%
% "Computer Methods for Mathematical Computations",
% Forsythe, Malcolm, and Moler, Prentice-Hall, 1976.
% Original coding by Duane Hanselman, University of Maine.
% Copyright 1984-2018 The MathWorks, Inc.
% Set default options
defaultopt = struct( ...
'Display','notify', ...
'FunValCheck','off', ...
'MaxFunEvals',500, ...
'MaxIter',500, ...
'OutputFcn',[], ...
'PlotFcns',[], ...
'TolX',1e-4);
% If just 'defaults' passed in, return the default options in X
if nargin==1 && nargout <= 1 && strcmpi(funfcn,'defaults')
xf = defaultopt;
return
end
% initialization
if nargin<4
options = [];
end
% Detect problem structure input
problemInput = false;
if nargin == 1
if isa(funfcn,'struct')
problemInput = true;
[funfcn,ax,bx,options] = separateOptimStruct(funfcn);
else % Single input and non-structure.
error('MATLAB:fminbnd:InputArg',...
getString(message('MATLAB:optimfun:fminbnd:InputArg')));
end
end
if nargin < 3 && ~problemInput
error('MATLAB:fminbnd:NotEnoughInputs',...
getString(message('MATLAB:optimfun:fminbnd:NotEnoughInputs')));
end
% Check for non-double inputs
if ~isa(ax,'double') || ~isa(bx,'double')
error('MATLAB:fminbnd:NonDoubleInput',...
getString(message('MATLAB:optimfun:fminbnd:NonDoubleInput')));
end
% Check that options is a struct
if ~isempty(options) && ~isa(options,'struct')
error('MATLAB:fminbnd:ArgNotStruct',...
getString(message('MATLAB:optimfun:commonMessages:ArgNotStruct', 4)));
end
printtype = optimget(options,'Display',defaultopt,'fast');
tol = optimget(options,'TolX',defaultopt,'fast');
funValCheck = strcmp(optimget(options,'FunValCheck',defaultopt,'fast'),'on');
maxfun = optimget(options,'MaxFunEvals',defaultopt,'fast');
maxiter = optimget(options,'MaxIter',defaultopt,'fast');
% Check that MaxFunEvals and MaxIter are scalar double values;
% Their default values for some solvers are strings
if ischar(maxfun) || isstring(maxfun)
error('MATLAB:fminbnd:CharMaxFunEvals',...
getString(message('MATLAB:optimfun:fminbnd:CharMaxFunEvals')));
end
if ischar(maxiter) || isstring(maxiter)
error('MATLAB:fminbnd:CharMaxIter',...
getString(message('MATLAB:optimfun:fminbnd:CharMaxIter')));
end
funccount = 0;
iter = 0;
xf = []; fx = [];
switch printtype
case {'notify','notify-detailed'}
print = 1;
case {'none','off'}
print = 0;
case {'iter','iter-detailed'}
print = 3;
case {'final','final-detailed'}
print = 2;
otherwise
print = 1;
end
% Handle the output
outputfcn = optimget(options,'OutputFcn',defaultopt,'fast');
if isempty(outputfcn)
haveoutputfcn = false;
else
haveoutputfcn = true;
% Parse OutputFcn which is needed to support cell array syntax for OutputFcn.
outputfcn = createCellArrayOfFunctions(outputfcn,'OutputFcn');
end
% Handle the plot
plotfcns = optimget(options,'PlotFcns',defaultopt,'fast');
if isempty(plotfcns)
haveplotfcn = false;
else
haveplotfcn = true;
% Parse PlotFcns which is needed to support cell array syntax for PlotFcns.
plotfcns = createCellArrayOfFunctions(plotfcns,'PlotFcns');
end
% checkbounds
if ax > bx
exitflag = -2;
xf=[]; fval = [];
msg=getString(message('MATLAB:optimfun:fminbnd:ExitingLowerBoundExceedsUpperBound'));
if print > 0
disp(' ')
disp(msg)
end
output.iterations = 0;
output.funcCount = 0;
output.algorithm = 'golden section search, parabolic interpolation';
output.message = msg;
% Have not initialized OutputFcn; do not need to call it before returning
return
end
% Assume we'll converge
exitflag = 1;
header = ' Func-count x f(x) Procedure';
procedure=' initial';
% Convert to function handle as needed.
if isstring(funfcn)
funfcn = char(funfcn);
end
funfcn = fcnchk(funfcn,length(varargin));
if funValCheck
% Add a wrapper function, CHECKFUN, to check for NaN/complex values without
% having to change the calls that look like this:
% f = funfcn(x,varargin{:});
% x is the first argument to CHECKFUN, then the user's function,
% then the elements of varargin. To accomplish this we need to add the
% user's function to the beginning of varargin, and change funfcn to be
% CHECKFUN.
varargin = [{funfcn}, varargin];
funfcn = @checkfun;
end
% Initialize the output and plot functions.
if haveoutputfcn || haveplotfcn
[xOutputfcn, optimValues, stop] = callOutputAndPlotFcns(outputfcn,plotfcns,xf,'init',funccount,iter, ...
fx,procedure,varargin{:});
if stop
[xf,fval,exitflag,output] = cleanUpInterrupt(xOutputfcn,optimValues);
if print > 0
disp(output.message)
end
return;
end
end
% Compute the start point
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 = funfcn(x,varargin{:});
funccount = funccount + 1;
% Check that the objective value is a scalar
if numel(fx) ~= 1
error('MATLAB:fminbnd:NonScalarObj',...
getString(message('MATLAB:optimfun:fminbnd:NonScalarObj')));
end
% Display the start point if required
if print > 2
disp(' ')
disp(header)
fprintf('%5.0f %12.6g %12.6g %s\n',funccount,xf,fx,procedure)
end
% OutputFcn and PlotFcns call
% Last x passed to outputfcn/plotfcns; has the input x's shape
if haveoutputfcn || haveplotfcn
[xOutputfcn, optimValues, stop] = callOutputAndPlotFcns(outputfcn,plotfcns,xf,'iter',funccount,iter, ...
fx,procedure,varargin{:});
if stop % Stop per user request.
[xf,fval,exitflag,output] = cleanUpInterrupt(xOutputfcn,optimValues);
if print > 0
disp(output.message)
end
return;
end
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 % Yes, parabolic interpolation step % f must not be evaluated too close to ax or bx % The function must not be evaluated too close to xf iter = iter + 1; % Update a, b, v, w, x, xm, tol1, tol2 if funccount >= maxfun || iter >= maxiter fval = fx; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% switch exitflag %-------------------------------------------------------------------------- % For the 'done' state we do not check the value of 'stop' because the xOutputfcn = x; % Set xOutputfcn to be x end %-------------------------------------------------------------------------- % Call plot function driver to finalize the plot function figure window. If x = xOutputfcn; %-------------------------------------------------------------------------- f = userfcn(x,varargin{:}); if ischar(fcn) 3.运行结果
if ( (abs(p)
d = p/q;
x = xf+d;
procedure = ' parabolic';
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;
procedure = ' golden';
end
si = sign(d) + (d == 0);
x = xf + si * max( abs(d), tol1 );
fu = funfcn(x,varargin{:});
funccount = funccount + 1;
if print > 2
fprintf('%5.0f %12.6g %12.6g %s\n',funccount, x, fu, procedure);
end
% OutputFcn and PlotFcns call
if haveoutputfcn || haveplotfcn
[xOutputfcn, optimValues, stop] = callOutputAndPlotFcns(outputfcn,plotfcns,x,'iter',funccount,iter, ...
fu,procedure,varargin{:});
if stop % Stop per user request.
[xf,fval,exitflag,output] = cleanUpInterrupt(xOutputfcn,optimValues);
if print > 0
disp(output.message);
end
return;
end
end
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;
exitflag = 0;
output.iterations = iter;
output.funcCount = funccount;
output.algorithm = 'golden section search, parabolic interpolation';
fval = fx;
msg = terminate(xf,exitflag,fval,funccount,maxfun,iter,maxiter,tol,print);
output.message = msg;
% OutputFcn and PlotFcns call
if haveoutputfcn || haveplotfcn
callOutputAndPlotFcns(outputfcn,plotfcns,xf,'done',funccount,iter,fval,procedure,varargin{:});
end
return
end
end % while
output.iterations = iter;
output.funcCount = funccount;
output.algorithm = 'golden section search, parabolic interpolation';
msg = terminate(xf,exitflag,fval,funccount,maxfun,iter,maxiter,tol,print);
output.message = msg;
% OutputFcn and PlotFcns call
if haveoutputfcn || haveplotfcn
callOutputAndPlotFcns(outputfcn,plotfcns,xf,'done',funccount,iter,fval,procedure,varargin{:});
end
function msg = terminate(~,exitflag,finalf,funccount,maxfun,~,~,tol,print)
case 1
msg = ...
getString(message('MATLAB:optimfun:fminbnd:OptimizationTerminatedXSatisfiesCriteria', sprintf('%e',tol)));
if print > 1 % only print msg if not 'off' or 'notify'
disp(' ')
disp(msg)
end
case 0
if funccount >= maxfun
msg = getString(message('MATLAB:optimfun:fminbnd:ExitingMaxFunctionEvals', sprintf('%f',finalf)));
if print > 0
disp(' ')
disp(msg)
end
else
msg = getString(message('MATLAB:optimfun:fminbnd:ExitingMaxIterations', sprintf('%f',finalf)));
if print > 0
disp(' ')
disp(msg)
end
end
end
function [xOutputfcn, optimValues, stop] = callOutputAndPlotFcns(outputfcn,plotfcns,x,state,funccount,iter, ...
f,procedure,varargin)
% CALLOUTPUTANDPLOTFCNS assigns values to the struct OptimValues and then calls the
% outputfcn/plotfcns. outputfcn and plotfcns are assumed to not be string
% objects but can be strings or handles.
%
% state - can have the values 'init','iter', or 'done'.
% optimization is already done.
optimValues.funccount = funccount;
optimValues.iteration = iter;
optimValues.fval = f;
optimValues.procedure = procedure;
stop = false;
state = char(state); % in case string objects are ever passed in the future
% Call output functions
if ~isempty(outputfcn)
switch state
case {'iter','init'}
stop = callAllOptimOutputFcns(outputfcn,xOutputfcn,optimValues,state,varargin{:}) || stop;
case 'done'
callAllOptimOutputFcns(outputfcn,xOutputfcn,optimValues,state,varargin{:});
end
end
% Call plot functions
if ~isempty(plotfcns)
switch state
case {'iter','init'}
stop = callAllOptimPlotFcns(plotfcns,xOutputfcn,optimValues,state,varargin{:}) || stop;
case 'done'
callAllOptimPlotFcns(plotfcns,xOutputfcn,optimValues,state,varargin{:});
end
function [x,FVAL,EXITFLAG,OUTPUT] = cleanUpInterrupt(xOutputfcn,optimValues)
% CLEANUPINTERRUPT updates or sets all the output arguments of FMINBND when the optimization
% is interrupted.
% no plot functions have been specified or the plot function figure no
% longer exists, this call just returns.
callAllOptimPlotFcns('cleanuponstopsignal');
FVAL = optimValues.fval;
EXITFLAG = -1;
OUTPUT.iterations = optimValues.iteration;
OUTPUT.funcCount = optimValues.funccount;
OUTPUT.algorithm = 'golden section search, parabolic interpolation';
OUTPUT.message = getString(message('MATLAB:optimfun:fminbnd:OptimizationTerminatedPrematurelyByUser'));
function f = checkfun(x,userfcn,varargin)
% CHECKFUN checks for complex or NaN results from userfcn.
% Note: we do not check for Inf as FMINBND handles it naturally.
if isnan(f)
error('MATLAB:fminbnd:checkfun:NaNFval',...
getString(message('MATLAB:optimfun:fminbnd:checkfun:NaNFval', localChar( userfcn ), sprintf( '%g', x ))));
elseif ~isreal(f)
error('MATLAB:fminbnd:checkfun:ComplexFval',...
getString(message('MATLAB:optimfun:fminbnd:checkfun:ComplexFval', localChar( userfcn ), sprintf( '%g', x ))));
end
%--------------------------------------------------------------------------
function strfcn = localChar(fcn)
% Convert the fcn to a character array for printing
strfcn = fcn;
elseif isstring(fcn) || isa(fcn,'inline')
strfcn = char(fcn);
elseif isa(fcn,'function_handle')
strfcn = func2str(fcn);
else
try
strfcn = char(fcn);
catch
strfcn = getString(message('MATLAB:optimfun:fminbnd:NameNotPrintable'));
end
end