O método mais rápido para resolver múltiplas equações independentes não lineares em MATLAB?
MATLAB tem dois métodos para resolver uma equação não linear:
Portanto, pode-se usar os seguintes métodos para resolver um sistema de equações independentes não lineares:
- usar um laço para resolver as equações separadamente usando
fzero
- usa um laço para resolver as equações separadamente usando
fsolve
- usar
fsolve
para os resolver juntos
- um método de ciclo é mais rápido do que um sistema único para o Grande
n
Dado que a complexidade (cálculo do gradiente) é 0 (n^2) - um loop pode ser mais lento para o pequeno
n
como um loop tem uma sobrecarga elevada em MATLAB e pode haver algum tempo de arranque constante -
fzero
é mais rápido que {[1] } porque é feito especificamente para um único não linear Equacao.
pergunta: Qual é o método mais rápido para resolver este problema? Que opções devem ser usadas para acelerar o processo?
tópicos relacionados
1 answers
A melhor abordagem para avaliar o desempenho de algum método é escrever uma referência. São considerados quatro casos:
-
loop fzero: usa um loop para resolver as equações separadamente usando
fzero
-
loop fsolve: usa um loop para resolver as equações separadamente usando
fsolve
- resolução default : resolve as equações juntas como um sistema de equações {[[27]}
- resolução independente : igual a predefinição fsolve , mas especifica que as equações são independentes
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
Resultados
Todas as figuras mostram o tempo de cálculo para o sistema completo em função de n
, o número de equações.
As duas primeiras figuras plot n
até 1000, com um intervalo de 100. As duas últimas figuras plot n
até 100 com um intervalo de 1. Para cada um, o segundo lote é o mesmo que o primeiro, mas sem loop fzero como ele é muito mais lento que os outros.
- loop fsolve : não o utilize, o tempo de arranque é demasiado elevado
-
loop fzero: pode usá-lo para o small
n
(método mais rápido paran < ~20
) -
o fsolve por omissão: pode usá-lo para o relativamente pequeno
n
(método mais rápido para~20 < n < ~50
, mas a diferença com 2 e 3 é relativa pequeno). -
fsolve independente: deve usá-lo para o large
n
(método mais rápido para~50 < n
)
De um modo geral , deve utilizar fsolve independente , apenas para pequenas n
em vez disso, pode utilizar-se o loop fzero, ou seja, utilizar fsolve
com as seguintes opções:
options.Algorithm = 'trust-region-reflective';
options.JacobPattern = speye(n);
options.PrecondBandWidth = 0;
As pessoas preguiçosas podem apenas usar o padrão fsolve porque tem um desempenho razoável para um número moderado de equações (n < ~200
)
Observações
- Note que a complexidade temporal da solução por omissãoé O(n^2) enquanto os outros são O(n).
- Note que
fzero
efsolve
podem comportar-se de forma diferente em alguns casos limite, F. efzero
não irá encontrar uma solução parax^2
à medida que procura a localização de uma mudança de sinal.