在MATLAB中求解多个非线性独立方程的最快方法?

m79*_*13d 3 performance matlab nonlinear-optimization equation-solving

MATLAB有两种方法来解决非线性方程:

  • fzero:求解单个非线性方程
  • fsolve:求解非线性方程组

因此,可以使用以下方法来求解n非线性独立方程组:

  1. 使用循环分别使用求解方程 fzero
  2. 使用循环分别使用求解方程 fsolve
  3. 用fsolve它们一起解决它们

我的直觉是:

  • n由于复杂度(梯度计算)为0(n ^ 2),因此循环方法比单个系统更快
  • 循环可能较慢,n因为循环在MATLAB中具有较高的开销,并且可能存在一些恒定的启动时间
  • fzero比fsolve单个非线性方程专用的更快.

问题:解决此问题的最快方法是什么?应该使用哪些选项来加快流程?

相关主题

m79*_*13d 6

评估某种方法性能的最佳方法是编写基准.考虑四种情况:

  1. loop fzero:使用循环分别求解方程式fzero
  2. loop fsolve:使用循环分别求解方程式fsolve
  3. default fsolve:将方程一起解算为一个方程组
  4. 独立fsolve:与默认fsolve相同,但指定方程式是独立的

f = @(x) x.^2-1; % the set of non-linear equations
ns = 1:1:100; % the sizes for which the benchmark is performed
options=optimset('Display','off'); % disable displaying

figure
hold on
plot(ns, loopFSolve(f, ns, options), 'DisplayName', 'loop fsolve')
plot(ns, loopFZero(f, ns, options), 'DisplayName', 'loop fzero')
plot(ns, defaultFSsolve(f, ns, options), 'DisplayName', 'default fsolve')
plot(ns, independentFSolve(f, ns, options), 'DisplayName', 'independent fsolve')

legend ('Location', 'northwest')

function t = loopFZero(f, ns, options)
  t1 = timeit(@() fzero(f, rand(1), options));
  t = ns * t1;
end

function t = loopFSolve(f, ns, options)
  t1 = timeit(@() fsolve(f, rand(1), options));
  t = ns * t1;
end

function t = defaultFSsolve(f, ns, options)
  t = zeros(size(ns));
  for i=1:length(ns)
    n = ns(i);
    un = rand(n, 1);
    t(i) = timeit(@() fsolve(f, un, options));
  end
end

function t = independentFSolve(f, ns, options)
  t = zeros(size(ns));
  for i=1:length(ns)
    n = ns(i);
    un = rand(n, 1);
    options.Algorithm = 'trust-region-reflective';
    options.JacobPattern = speye(n);
    options.PrecondBandWidth = 0;

    t(i) = timeit(@() fsolve(f, un, options));
  end
end
Run Code Online (Sandbox Code Playgroud)

结果

所有图都显示了完整系统的计算时间n,方程的数量.

前两个数字n最多可绘制1000个,间隔为100.最后两个数字n最多可绘制为100,间隔为1.对于每个数据,第二个绘图与第一个绘图相同但没有循环fzero因为它很多比其他人慢.

在此输入图像描述 在此输入图像描述 在此输入图像描述 在此输入图像描述 结论

  1. loop fsolve:不要使用它,启动时间太长
  2. loop fzero:你可以用它来做小n(最快的方法n < ~20)
  3. 默认fsolve:您可以将它用于相对较小的n(最快的方法~20 < n < ~50,但与2和3的差异相对较小).
  4. 独立的fsolve:你应该用它来做大n(最快的方法~50 < n)

一般情况下,您应该使用独立的fsolve,仅用于小循环n fzero可以代替使用,即使用fsolve以下选项:

options.Algorithm = 'trust-region-reflective';
options.JacobPattern = speye(n);
options.PrecondBandWidth = 0;
Run Code Online (Sandbox Code Playgroud)

懒人可能只使用默认的fsolve,因为它对于中等数量的方程具有合理的性能(n < ~200)

备注

  • 注意,默认fsolve的时间复杂度是O(n ^ 2),而其他的是O(n).
  • 请注意,fzero并且fzero在某些边界情况下可能会有不同的行为,fe fsolve将无法找到解决方案,fzero因为它会搜索符号更改的位置.