MATLAB中求解多个非线性独立方程组的最快方法?
MATLAB有两种方法来求解非线性方程:MATLAB中求解多个非线性独立方程组的最快方法?,matlab,performance,equation-solving,nonlinear-optimization,Matlab,Performance,Equation Solving,Nonlinear Optimization,MATLAB有两种方法来求解非线性方程: :解一个非线性方程 :解非线性方程组 因此,可以使用以下方法来求解n非线性独立方程组: 使用循环分别使用fzero 使用循环分别使用fsolve 使用fsolve一起解决这些问题 我的直觉是: 对于大型n,循环方法比单个系统更快,因为复杂度(梯度计算)为0(n^2) 对于较小的n,循环可能较慢,因为循环在MATLAB中的开销较高,并且可能有一些恒定的启动时间 fzero比fsolve更快,因为它是专门为单个非线性方程设计的 问题:求解n非线性独立
- :解一个非线性方程
- :解非线性方程组
n
非线性独立方程组:
fzero
fsolve
fsolve
一起解决这些问题- 对于大型
,循环方法比单个系统更快,因为复杂度(梯度计算)为0(n^2)n
- 对于较小的
,循环可能较慢,因为循环在MATLAB中的开销较高,并且可能有一些恒定的启动时间n
比fzero
更快,因为它是专门为单个非线性方程设计的fsolve
n
非线性独立方程组的最快方法是什么?还有其他方法吗?应该使用哪些选项来加快流程
示例问题:(可用于对不同答案进行基准测试)
i
介于1和n之间
相关线程
%---------------
% ns = 10
loopFZero =
0.0027
indepFSolve =
0.0049
vecBisection =
5.0978e-05
%---------------
% ns = 1e5
loopFZero =
28.7574
indepFSolve =
7.7601
vecBisection =
0.0013
评估某种方法性能的最佳方法是编写基准测试。考虑了四种情况:
循环fzero:使用循环分别使用fzero
loop fsolve:使用循环分别使用fsolve
默认fsolve:将方程作为一个方程组一起求解
独立fsolve:与默认fsolve相同,但
结果
%---------------
% ns = 10
loopFZero =
0.0027
indepFSolve =
0.0049
vecBisection =
5.0978e-05
%---------------
% ns = 1e5
loopFZero =
28.7574
indepFSolve =
7.7601
vecBisection =
0.0013
所有的图都显示了整个系统在n
函数中的计算时间,方程的数量
前两个数字绘制的n
最大值为1000,间隔为100。最后两个数字以1为间隔绘制100。对于每个图,第二个图与第一个图相同,但没有循环fzero,因为它比其他图慢得多
结论
循环fsolve:不要使用它,启动时间太长
循环fzero:您可以将其用于较小的n
(最快的n<~20
)中
默认fsolve:您可以将其用于相对较小的n
(最快的方法是~20
,但与2和3的差异相对较小)
独立的fsolve:您应该将其用于大型n
(最快的~50
方法)
一般情况下,您应该使用独立的fsolve,仅对于较小的n
循环,可以使用fzero,即使用fsolve
和以下选项:
options.Algorithm = 'trust-region-reflective';
options.JacobPattern = speye(n);
options.PrecondBandWidth = 0;
懒惰的人可能只会使用默认的fsolve,因为它对中等数量的方程有合理的性能(n<~200
)
重要评论
Bob指出,a可能要快几个数量级。根据Bob的测试结果,他的方法对于问题的每一个大小,即大小n
,都是最快的方法
备注
%---------------
% ns = 10
loopFZero =
0.0027
indepFSolve =
0.0049
vecBisection =
5.0978e-05
%---------------
% ns = 1e5
loopFZero =
28.7574
indepFSolve =
7.7601
vecBisection =
0.0013
- 请注意,默认fsolve的时间复杂度为O(n^2),而其他fsolve的时间复杂度为O(n)
- 请注意,在某些边界情况下,
fzero
和fsolve
的行为可能不同,f.efzero
在搜索符号更改的位置时,不会找到x^2
的解决方案
我添加此答案是为了详细说明我的上述评论。根据我的经验,到目前为止,最快的方法是使用文件交换上提供的fzero矢量化版本:
这里有两个基准测试,将其性能与(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
在文件交换上有一个矢量化版本的fzero:根据我的经验,它比独立的fsolve(使用“JacoPattern”=speye(n)选项)强一个数量级。请审阅者注意:添加了示例问题,以便能够更好地比较不同的答案。请注意,Bob已经指出了另一种方法,它应该有自己的基准答案。不幸的是,它被mods删除了,所以我不确定是否有人能看到它。我应该重新发布吗?如果其他人看不到我下面的答案,这里有一个总结:使用与另一个答案相同的基准问题,我对ns=10
的计时是:0.0027s
通过循环vs0.0049s
通过indep fsolve vs5.0978e-05s
通过矢量化代码。对于ns=1e5
我得到:28.7574s
通过循环vs7.7601s
通过indep fsolve vs0.0013s
通过矢量化代码。@Bob,我同意重新发布答案。一、 OP,看不到你的答案。因此,几乎没有人会这么做。请注意,我在问题中明确添加了示例/基准问题。在这一行动之后,问题被重新打开(因为需要更多关注而关闭)。但是,首选的解决方案可能是标记您的答案以引起适度注意。@mods:这是我以前的答案的重新发布,该答案因不符合社区标准而被删除。我之所以重新发帖,是因为OP明确要求我这么做(见上面对他们问题的评论),而且我仍然相信我的方法比其他答案更有效,希望对其他人有用。@mods:注意,这个问题现在包含一个明确的基准问题,我接受了你的答案,因为这显然是迄今为止最好的方法。我希望它会提前