MATLAB有两种方法可以解决非线性方程:
因此,可以使用以下方法来求解n
非线性独立方程组:
fzero
fsolve
fsolve
一起解决问题我的直觉是:
n
,循环方法比单个系统更快,因为复杂度(梯度计算)为0(n ^ 2)n
,循环可能会慢一些,因为循环在MATLAB中有很高的开销,并且可能有一些不变的启动时间fzero
比fsolve
更快,因为它专门用于单个非线性方程。问题:解决此问题的最快方法是什么?应该使用哪些选项来加快流程?
相关主题
答案 0 :(得分:5)
评估某种方法性能的最佳方法是编写基准。考虑四种情况:
fzero
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
<强>结果
所有数字都显示了完整系统的计算时间n
,方程组的数量。
前两个数字将n
绘制为最多1000个,间隔为100.最后两个数字将n
绘制为最多100个,间隔为1.对于每个,第二个图是与第一个相同,但没有循环fzero ,因为它比其他的慢得多。
n
(n < ~20
的最快方法)n
(~20 < n < ~50
的最快方法,但与2和3的差异相对较小)。n
(~50 < n
的最快方法) 一般,您应该使用独立的fsolve ,仅适用于小n
循环fzero 可以代替使用,即使用fsolve
具有以下选项:
options.Algorithm = 'trust-region-reflective';
options.JacobPattern = speye(n);
options.PrecondBandWidth = 0;
懒人可能只使用默认fsolve ,因为它对于中等数量的等式具有合理的性能(n < ~200
)
<强>说明强>
fzero
和fsolve
在某些边界情况下可能会有不同的行为,因为fzero
搜索符号更改的位置,因此x^2
找不到select d.name, group_concat(c.name)
from documents d
join document_document_category dc on dc.document_id = d.id
join document_categories c on dc.document_category_id = c.id
group by d.name
的解决方案答案 1 :(得分:1)
我添加这个答案是为了详细说明我上面的评论。根据我目前的经验,最快的方法是使用文件交换中可用的 fzero 的矢量化版本:Link to vectorized bisection code
这里有几个基准将其性能与 (i) 循环 fzero 和 (ii) 独立 fsolve 进行比较。
f = @(x) x.^2-1; %the set of non-linear equations
ns = 1e5; %size of the problem
% method 1: looped fzero
t = timeit(@() fzero(f, rand(1)));
loopFZero = t*ns
% method 2: independent fsolve
options=optimset('Display','off'); % disable displaying
options.Algorithm = 'trust-region-reflective';
options.JacobPattern = speye(ns);
options.PrecondBandWidth = 0;
indepFSolve = timeit(@() fsolve(f, rand(ns,1), options))
% method 3: vectorized bisection, available here:
% https://www.mathworks.com/matlabcentral/fileexchange/28150-bisection-method-root-finding
vecBisection = timeit(@() bisection(f, zeros(ns,1), 2))
结果
%---------------
% ns = 10
loopFZero =
0.0027
indepFSolve =
0.0049
vecBisection =
5.0978e-05
%---------------
% ns = 1e5
loopFZero =
28.7574
indepFSolve =
7.7601
vecBisection =
0.0013