假设我正在解决一个非线性方程组。一个简单的例子是:
function example
x0 = [15; -2];
options = optimoptions('fsolve','Display','iter','TolFun',eps,'TolX',eps);
[x,fval,exitflag,output] = fsolve(@P1a,x0,options);
end
function f1 = P1a(x)
f1 = [x(1)+x(2)*(x(2)*(5-x(2))-2)- 13; x(1)+x(2)*(x(2)*(1+x(2))-14)-29];
end
如何确定收敛率? 'Display'
,'iter'
向我展示了每一步的标准,但我无法找到提取这些值的方法。 (对于这个特定的例子,我认为fsolve
不会收敛到正确的解决方案,而是收敛到局部最小值。但这不是问题。我只是想找到一种估算收敛速度的方法。)
答案 0 :(得分:0)
你可以从fsolve
获得足够的资金。但是,您需要做一些工作。阅读'OutputFcn'
选项并为Matlab的优化方法编写output functions。这与Matlab的ODE求解器使用的同名选项类似。这是一个复制'Display','iter'
的{{1}}选项值的示例(具体为默认的fsolve
算法):
'trust-region-dogleg'
然后您可以通过以下方式调用此方法:
function stop = outfun(x,optimValues,state)
% See private/trustnleqn
stop = false;
switch state
case 'init'
header = sprintf(['\n Norm of First-order Trust-region\n',...
' Iteration Func-count f(x) step optimality radius']);
disp(header);
case 'iter'
iter = optimValues.iteration; % Iteration
numFevals = optimValues.funccount; % Func-count
F = optimValues.fval; % f(x)
normd = optimValues.stepsize; % Norm of step
normgradinf = optimValues.firstorderopt; % First-order optimality
Delta = optimValues.trustregionradius; % Trust-region radius
if iter > 0
formatstr = ' %5.0f %5.0f %13.6g %13.6g %12.3g %12.3g';
iterOutput = sprintf(formatstr,iter,numFevals,F'*F,normd,normgradinf,Delta);
else
formatstr0 = ' %5.0f %5.0f %13.6g %12.3g %12.3g';
iterOutput = sprintf(formatstr0,iter,numFevals,F'*F,normgradinf,Delta);
end
disp(iterOutput);
case 'done'
otherwise
end
这仍然只是打印到命令窗口。从这里开始,创建一个可以将数据写入数组,文件或其他数据结构的输出函数。您可以通过global variable(通常不是一个好主意)来实现这一目标:
function example
P1a=@(x)[x(1)+x(2)*(x(2)*(5-x(2))-2)- 13; x(1)+x(2)*(x(2)*(1+x(2))-14)-29];
x0 = [15; -2];
opts = optimoptions('fsolve','Display','off','OutputFcn',@outfun,'TolFun',eps,'TolX',eps);
[x,fval,exitflag,output] = fsolve(P1a,x0,opts);
然后在调用function stop = outfun2(x,optimValues,state)
stop = false;
global out; % Global variable, define in main function too
switch state
case 'init'
out = [];
case 'iter'
iter = optimValues.iteration; % Iteration
numFevals = optimValues.funccount; % Func-count
F = optimValues.fval; % f(x)
normd = optimValues.stepsize; % Norm of step
normgradinf = optimValues.firstorderopt; % First-order optimality
Delta = optimValues.trustregionradius; % Trust-region radius
out = [out;iter numFevals F'*F normd normgradinf Delta];
case 'done'
otherwise
end
之前,在主函数中声明global out;
。您还可以通过使输出函数为nested function来实现此目的,在这种情况下,fsolve
数组将与外部主函数共享。
第二个输出函数示例执行动态内存分配,而不是重新分配整个out
数组。由于我们和算法都不知道收敛需要多少次迭代,因此无法解决这个问题。但是,对于几百次迭代,动态内存分配将非常快。
我将离开"确定收敛速度"现在你手头有工具......