Fastest way to solve multiple nonlinear independent equations in MATLAB?

MATLAB has two methods for solving a nonlinear equation:

Therefore n

, the following methods can be used to solve a system of nonlinear independent equations :

  • Use a loop to solve equations separately using fzero

  • Use a loop to solve equations separately using fsolve

  • Use fsolve

    to solve them.

My intuition would be that:

  • The loop method is faster than one system for large n

    , since the complexity (calculating the gradient) is 0 (n ^ 2)
  • The loop can be slower for small n

    , as the loop has high overhead in MATLAB and there may be some constant startup time
  • fzero

    faster than fsolve

    because it is specifically designed for one non-linear equation.

Question: What's the fastest way to fix this problem? What parameters should be used to speed up the process?

Related Topics

+3


source to share


2 answers


The best approach for assessing the performance of a method is to record a test. Four cases are considered:

  • loop fzero: uses a loop to solve equations separately using fzero

  • loop fsolve: uses a loop to solve equations separately with fsolve

  • default fsolve: Solves equations together as one system of equations
  • independent fsolve: same as fsolve by default, but specifies that equations are independent

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

      

results

All figures show the computation time for the entire system as a function n

, the number of equations.

The first two digits are drawn n

up to 1000 with an interval of 100. The last two digits are drawn n

up to 100 with an interval of 1. For every second, the graph is the same as the first one, but without the fzero loop as it is much slower than the others.



enter image description here enter image description here enter image description here enter image description here Conclusion

  • loop fsolve: don't use it, startup time is too long.
  • loop fzero: you can use it for small n

    (fastest method for n < ~20

    )
  • default fsolve: you can use it for relatively small n

    (fastest method for ~20 < n < ~50

    , but the difference with 2 and 3 is relatively small).
  • independent fsolve: you should use it for large n

    (fastest method for ~50 < n

    )

In general you should use an independent fsolve, only for small n

ones the fzero loop can be used, i.e. use fsolve

with the following parameters:

options.Algorithm = 'trust-region-reflective';
options.JacobPattern = speye(n);
options.PrecondBandWidth = 0;

      

Lazy people can just use the default fsolve as it has reasonable performance for a moderate number of equations ( n < ~200

)

Notes

  • Note that the time complexity of fsolve is O (n ^ 2) by default, and the rest are O (n).
  • Note that fzero

    and fsolve

    may behave differently in some edge cases, fe fzero

    will not find a solution for x^2

    when looking for a sign change location.
+5


source


The file sharing service has a vectorized version of fzero:

https://www.mathworks.com/matlabcentral/fileexchange/28150-bisection-method-root-finding



In my experience, it beats the independent fsolve (using the 'JacoPattern' = speye (n) option) by an order of magnitude.

0


source







All Articles