📄 optimfcnchk.m
字号:
elseif hessflag && ~gradflag
warnstr = ...
sprintf('%s\n%s\n%s\n','Hessian and gradient functions provided ', ...
' but OPTIONS.GradObj=''off''; ignoring Hessian and gradient functions.', ...
' Rerun with OPTIONS.Hessian=''on'' and OPTIONS.GradObj=''on'' to use derivative functions.');
warning('optimlib:optimfcnchk:GradientOptionOff',warnstr)
calltype = 'fun';
elseif ~hessflag && gradflag
hwarnstr = ...
sprintf('%s\n%s\n%s\n','Hessian function provided but OPTIONS.Hessian=''off'';', ...
' ignoring Hessian function,', ...
' Rerun with OPTIONS.Hessian=''on'' to use Hessian function.');
warning('optimlib:optimfcnchk:HessianOptionOff',hwarnstr);
calltype = 'fun_then_grad';
end
elseif isa(funstr, 'cell') && length(funstr)==3 ...
&& ~isempty(funstr{2}) && isempty(funstr{3}) % {fun, grad, []}
if hessflag
error('optimlib:optimfcnchk:NoHessianFunction','Hessian function expected but not found.')
end
[funfcn, idandmsg] = fcnchk(funstr{1},lenVarIn);
if funValCheck
userfcn = funfcn;
funfcn = @checkfun; %caller and userfcn are in scope in nested checkfun
end
if ~isempty(idandmsg)
if constrflag
error(nonlconid,nonlconmsg);
else
error(idandmsg);
end
end
[gradfcn, idandmsg] = fcnchk(funstr{2},lenVarIn);
if funValCheck
userfcn = gradfcn;
gradfcn = @checkfun; %caller and userfcn are in scope in nested checkfun
end
if ~isempty(idandmsg)
if constrflag
error(nonlconid,nonlconmsg);
else
error(idandmsg);
end
end
calltype = 'fun_then_grad';
if ~gradflag
warning(warnid,warnstr);
calltype = 'fun';
end
elseif isa(funstr, 'cell') && length(funstr)==3 ...
&& isempty(funstr{2}) && ~isempty(funstr{3}) % {fun, [], hess}
error('optimlib:optimfcnchk:NoGradientWithHessian','Hessian function given without gradient function.')
elseif ~isa(funstr, 'cell') %Not a cell; is a string expression, function name string or inline object
[funfcn, idandmsg] = fcnchk(funstr,lenVarIn);
if funValCheck
userfcn = funfcn;
funfcn = @checkfun; %caller and userfcn are in scope in nested checkfun
end
if ~isempty(idandmsg)
if constrflag
error(nonlconid,nonlconmsg);
else
error(idandmsg);
end
end
if gradflag % gradient and function in one function/M-file
gradfcn = funfcn; % Do this so graderr will print the correct name
end
if hessflag && ~gradflag
hwarnstr = ...
sprintf('%s\n%s\n%s\n','OPTIONS.Hessian=''on''', ...
' but OPTIONS.GradObj=''off''; ignoring Hessian and gradient functions.', ...
' Rerun with OPTIONS.Hessian=''on'' and OPTIONS.GradObj=''on'' to use derivative functions.');
warning('optimlib:optimfcnchk:GradientOptionOff',hwarnstr)
end
else
errmsg = sprintf('%s\n%s', ...
'FUN must be a function or an inline object;', ...
' or, FUN may be a cell array that contains these type of objects.');
error('optimlib:optimfcnchk:MustBeAFunction',errmsg)
end
allfcns{1} = calltype;
allfcns{2} = caller;
allfcns{3} = funfcn;
allfcns{4} = gradfcn;
allfcns{5} = hessfcn;
%------------------------------------------------------------
function [varargout] = checkfun(x,varargin)
% CHECKFUN checks for complex, Inf, or NaN results from userfcn.
% Inputs CALLER, USERFCN, and NTHETA come from the scope of OPTIMFCNCHK.
% We do not make assumptions about f, g, or H. For generality, assume
% they can all be matrices.
if nargout == 1
f = userfcn(x,varargin{:});
if any(any(isnan(f)))
error('optimlib:optimfcnchk:checkfun:NaNFval', ...
'User function ''%s'' returned NaN when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
elseif ~isreal(f)
error('optimlib:optimfcnchk:checkfun:ComplexFval', ...
'User function ''%s'' returned a complex value when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
elseif any(any(isinf(f)))
error('optimlib:optimfcnchk:checkfun:InfFval', ...
'User function ''%s'' returned Inf or -Inf when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
else
varargout{1} = f;
end
elseif nargout == 2 % Two output could be f,g (from objective fcn) or c,ceq (from NONLCON)
[f,g] = userfcn(x,varargin{:});
if any(any(isnan(f))) || any(any(isnan(g)))
error('optimlib:optimfcnchk:checkfun:NaNFval', ...
'User function ''%s'' returned NaN when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
elseif ~isreal(f) || ~isreal(g)
error('optimlib:optimfcnchk:checkfun:ComplexFval', ...
'User function ''%s'' returned a complex value when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
elseif any(any(isinf(f))) || any(any(isinf(g)))
error('optimlib:optimfcnchk:checkfun:InfFval', ...
'User function ''%s'' returned Inf or -Inf when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
else
varargout{1} = f;
varargout{2} = g;
end
elseif nargout == 3 % This case only happens for objective functions
[f,g,H] = userfcn(x,varargin{:});
if any(any(isnan(f))) || any(any(isnan(g))) || any(any(isnan(H)))
error('optimlib:optimfcnchk:checkfun:NaNFval', ...
'User function ''%s'' returned NaN when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
elseif ~isreal(f) || ~isreal(g) || ~isreal(H)
error('optimlib:optimfcnchk:checkfun:ComplexFval', ...
'User function ''%s'' returned a complex value when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
elseif any(any(isinf(f))) || any(any(isinf(g))) || any(any(isinf(H)))
error('optimlib:optimfcnchk:checkfun:InfFval', ...
'User function ''%s'' returned Inf or -Inf when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
else
varargout{1} = f;
varargout{2} = g;
varargout{3} = H;
end
elseif nargout == 4 & ~isequal(caller,'fseminf')
% In this case we are calling NONLCON, e.g. for FMINCON, and
% the outputs are [c,ceq,gc,gceq]
[c,ceq,gc,gceq] = userfcn(x,varargin{:});
if any(any(isnan(c))) || any(any(isnan(ceq))) || any(any(isnan(gc))) || any(any(isnan(gceq)))
error('optimlib:optimfcnchk:checkfun:NaNFval', ...
'User function ''%s'' returned NaN when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
elseif ~isreal(c) || ~isreal(ceq) || ~isreal(gc) || ~isreal(gceq)
error('optimlib:optimfcnchk:checkfun:ComplexFval', ...
'User function ''%s'' returned a complex value when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
elseif any(any(isinf(c))) || any(any(isinf(ceq))) || any(any(isinf(gc))) || any(any(isinf(gceq)))
error('optimlib:optimfcnchk:checkfun:InfFval', ...
'User function ''%s'' returned Inf or -Inf when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
else
varargout{1} = c;
varargout{2} = ceq;
varargout{3} = gc;
varargout{4} = gceq;
end
else % fseminf constraints have a variable number of outputs, but at
% least 4: see semicon.m
% Also, don't check 's' for NaN as NaN is a valid value
T = cell(1,ntheta);
[c,ceq,T{:},s] = userfcn(x,varargin{:});
nanfound = any(any(isnan(c))) || any(any(isnan(ceq)));
complexfound = ~isreal(c) || ~isreal(ceq) || ~isreal(s);
inffound = any(any(isinf(c))) || any(any(isinf(ceq))) || any(any(isinf(s)));
for ii=1:length(T) % Elements of T are matrices
if nanfound || complexfound || inffound
break
end
nanfound = any(any(isnan(T{ii})));
complexfound = ~isreal(T{ii});
inffound = any(any(isinf(T{ii})));
end
if nanfound
error('optimlib:optimfcnchk:checkfun:NaNFval', ...
'User function ''%s'' returned NaN when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
elseif complexfound
error('optimlib:optimfcnchk:checkfun:ComplexFval', ...
'User function ''%s'' returned a complex value when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
elseif inffound
error('optimlib:optimfcnchk:checkfun:InfFval', ...
'User function ''%s'' returned Inf or -Inf when evaluated;\n %s cannot continue.', ...
functiontostring(userfcn),upper(caller));
else
varargout{1} = c;
varargout{2} = ceq;
varargout(3:ntheta+2) = T;
varargout{ntheta+3} = s;
end
end
end %checkfun
%----------------------------------------------------------
end % optimfcnchk
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -