朝气蓬勃的野马 · Windows Docker ...· 1 周前 · |
微醺的凉茶 · 2022年全球光模块企业TOP10(附榜单) ...· 4 月前 · |
可爱的滑板 · 卫裤男潮牌春秋季20...-Taobao ...· 9 月前 · |
威武的馒头 · JUnit 5 参数化测试· 1 年前 · |
体贴的拐杖 · 世界和平的捍卫者——中国军队积极参与联合国维 ...· 1 年前 · |
对非线性方程组求解
此示例说明如何求解包含两个变量的两个非线性方程。这些方程包括
将方程转换为 形式。
运行此示例时提供的
root2d.m
函数计算这些值。
type root2d.m
function F = root2d(x) F(1) = exp(-exp(-(x(1)+x(2)))) - x(2)*(1+x(1)^2); F(2) = x(1)*cos(x(2)) + x(2)*sin(x(1)) - 0.5;
从
[0,0]
点开始求解方程组。
fun = @root2d; x0 = [0,0]; x = fsolve(fun,x0)
Equation solved. fsolve completed because the vector of function values is near zero as measured by the value of the function tolerance, and the problem appears regular as measured by the gradient.
x = 1×2
0.3532 0.6061
深入了解非线性方程组的求解过程。
将选项设置为无显示和显示一阶最优性的绘图函数,该函数应在算法迭代时收敛于 0。
options = optimoptions('fsolve','Display','none','PlotFcn',@optimplotfirstorderopt);
非线性方程组中的方程是
将方程转换为 形式。
root2d
函数计算这两个方程的左侧。
type root2d.m
function F = root2d(x) F(1) = exp(-exp(-(x(1)+x(2)))) - x(2)*(1+x(1)^2); F(2) = x(1)*cos(x(2)) + x(2)*sin(x(1)) - 0.5;
从点
[0,0]
开始求解非线性方程组,并观察求解过程。
fun = @root2d; x0 = [0,0]; x = fsolve(fun,x0,options)
x = 1×2
0.3532 0.6061
您可以按照
传递额外参数
主题中所述对方程进行参数化。例如,
此示例末尾
的
paramfun
辅助函数会创建由
参数化的以下方程组:
要将方程组求解为某个特定值(本例中为
),请在工作区中设置
,并基于
paramfun
在
x
中创建匿名函数。
c = -1; fun = @(x)paramfun(x,c);
从点
x0 = [0 1]
开始求解方程组。
x0 = [0 1]; x = fsolve(fun,x0)
Equation solved. fsolve completed because the vector of function values is near zero as measured by the value of the function tolerance, and the problem appears regular as measured by the gradient.
x = 1×2
0.1976 0.4255
要求解
的不同值,请在工作区中输入
并再次创建
fun
函数,使其有新的
值。
c = -2;
fun = @(x)paramfun(x,c); % fun now has the new c value
x = fsolve(fun,x0)
Equation solved. fsolve completed because the vector of function values is near zero as measured by the value of the function tolerance, and the problem appears regular as measured by the gradient.
x = 1×2
0.1788 0.3418
辅助函数
以下代码会创建
paramfun
辅助函数。
function F = paramfun(x,c) F = [ 2*x(1) + x(2) - exp(c*x(1)) -x(1) + 2*x(2) - exp(c*x(2))]; end
为
fsolve
创建问题结构体并求解问题。
求解与 使用非默认选项的求解 中相同的问题,但使用问题结构体来表示问题。
设置问题的相关选项,不显示迭代输出,使用绘图函数显示一阶最优性,一阶最优性应随着算法迭代而收敛于 0。
problem.options = optimoptions('fsolve','Display','none','PlotFcn',@optimplotfirstorderopt);
非线性方程组中的方程是
将方程转换为 形式。
root2d
函数计算这两个方程的左侧。
type root2d
function F = root2d(x) F(1) = exp(-exp(-(x(1)+x(2)))) - x(2)*(1+x(1)^2); F(2) = x(1)*cos(x(2)) + x(2)*sin(x(1)) - 0.5;
在问题结构体中创建其余字段。
problem.objective = @root2d;
problem.x0 = [0,0];
problem.solver = 'fsolve';
求解。
x = fsolve(problem)
x = 1×2
0.3532 0.6061
此示例返回迭代输出,展示了一个包含两个方程和两个未知数的方程组的求解过程
以 形式重写方程:
从
x0 = [-5 -5]
开始搜索解。
首先,编写一个函数用来计算
F
(方程在
x
处的值)。
F = @(x) [2*x(1) - x(2) - exp(-x(1)); -x(1) + 2*x(2) - exp(-x(2))];
创建初始点
x0
。
x0 = [-5;-5];
设置选项以返回迭代输出。
options = optimoptions('fsolve','Display','iter');
求解方程。
[x,fval] = fsolve(F,x0,options)
Norm of First-order Trust-region Iteration Func-count ||f(x)||^2 step optimality radius 0 3 47071.2 2.29e+04 1 1 6 12003.4 1 5.75e+03 1 2 9 3147.02 1 1.47e+03 1 3 12 854.452 1 388 1 4 15 239.527 1 107 1 5 18 67.0412 1 30.8 1 6 21 16.7042 1 9.05 1 7 24 2.42788 1 2.26 1 8 27 0.032658 0.759511 0.206 2.5 9 30 7.03149e-06 0.111927 0.00294 2.5 10 33 3.29525e-13 0.00169132 6.36e-07 2.5 Equation solved. fsolve completed because the vector of function values is near zero as measured by the value of the function tolerance, and the problem appears regular as measured by the gradient.
x = 2×1
0.5671
0.5671
fval = 2×1
10-6 ×
-0.4059
-0.4059
迭代输出显示
f(x)
,这是函数
F(x)
的范数的平方。随着迭代的进行,该值减小到接近于零。随着迭代的进行,一阶最优性测度同样减小到接近于零。这些条目显示迭代收敛于一个解。有关其他条目的含义,请参阅
迭代输出
。
fval
输出给出函数值
F(x)
,该值在解处应为零(在
FunctionTolerance
容差内)。
找到满足下式的矩阵
,
初始点为
x0 = [1,1;1,1]
。创建匿名函数来计算矩阵方程并创建点
x0
。
fun = @(x)x*x*x - [1,2;3,4]; x0 = ones(2);
将选项设置为不显示。
options = optimoptions('fsolve','Display','off');
检查
fsolve
输出,了解求解过程和解的质量。
[x,fval,exitflag,output] = fsolve(fun,x0,options)
x = 2×2
-0.1291 0.8602
1.2903 1.1612
fval = 2×2
10-9 ×
-0.2742 0.1258
0.1876 -0.0864
exitflag = 1
output = struct with fields:
iterations: 11
funcCount: 52
algorithm: 'trust-region-dogleg'
firstorderopt: 4.0197e-10
message: 'Equation solved....'
退出标志值 1 表示解是可靠的。要手动验证解的可靠性,请计算残差(fval 的平方和)并观察它与零的接近程度。
sum(sum(fval.*fval))
ans = 1.3367e-19
这里残差很小,证实
x
是一个解。
您可以在
output
结构体中看到
fsolve
执行了多少次迭代和函数计算才求得解。
fun
—
要求解的非线性方程
要求解的非线性方程,指定为函数句柄或函数名称。
fun
函数接受向量
x
,并返回向量
F
,即在
x
处计算的非线性方程。对于
F
的所有分量,要求解的方程是
F
= 0。对于函数文件,函数
fun
可以指定为函数句柄
x = fsolve(@myfun,x0)
其中
myfun
是一个 MATLAB
®
函数,例如
function F = myfun(x) F = ... % Compute function values at x
fun
也可以是匿名函数的函数句柄。
x = fsolve(@(x)sin(x.*x),x0);
fsolve
以
x0
参量的形状将
x
传递给目标函数。例如,如果
x0
是 5×3 数组,则
fsolve
将
x
以 5×3 数组的形式传递给
fun
。
如果雅可比矩阵也可以计算
并且
'SpecifyObjectiveGradient'
选项为
true
,设置如下
options = optimoptions('fsolve','SpecifyObjectiveGradient',true)
函数
fun
必须在第二个输出参量中返回
x
处的雅可比值
J
,它是一个矩阵。
如果
fun
返回由
m
个分量组成的向量(矩阵)并且
x
的长度为
n
,其中
n
是
x0
的长度,则雅可比值
J
是
m
×
n
矩阵,其中
J(i,j)
是
F(i)
关于
x(j)
的偏导数。(雅可比值
J
是
F
的梯度的转置。)
示例:
fun = @(x)x*x*x-[1,2;3,4]
数据类型:
char
|
function_handle
|
string
x0
—
初始点
options
—
优化选项
optimoptions
的输出
|
optimset
返回的结构体
优化选项,指定为
optimoptions
的输出或
optimset
等返回的结构体。
一些选项适用于所有算法,其他选项则与特定算法相关。有关详细信息,请参阅 优化选项参考 。
optimoptions
显示中缺少某些选项。这些选项在下表中以斜体显示。有关详细信息,请参阅
查看优化选项
。
所有算法 | |
Algorithm
|
在
对于部分算法选项,要使用
|
CheckGradients
|
将用户提供的导数(目标或约束的梯度)与有限差分导数进行比较。选择项是
对于
以后的版本中将会删除
|
Diagnostics |
显示关于要最小化或求解的函数的诊断信息。选择项是
|
DiffMaxChange |
有限差分梯度变量的最大变化(正标量)。默认值为
|
DiffMinChange |
有限差分梯度变量的最小变化(正标量)。默认值为
|
Display
|
显示级别(请参阅 迭代输出 ):
|
FiniteDifferenceStepSize
|
有限差分的标量或向量步长因子。当您将
sign′(x) = sign(x)
(例外是
sign′(0) = 1
)。中心有限差分是
FiniteDifferenceStepSize
扩展为向量。对于正向有限差分,默认值为
sqrt(eps)
;对于中心有限差分,默认值为
eps^(1/3)
。
对于
|
FiniteDifferenceType
|
用于估计梯度的有限差分是
当同时估计这两种类型的有限差分时,该算法小心地遵守边界。因此,例如,为了避免在边界之外的某个点进行计算,它可能采取一个后向差分,而不是前向差分。
对于
|
FunctionTolerance
|
函数值的终止容差,非负标量。默认值为
对于
|
FunValCheck |
检查目标函数值是否有效。如果选择
|
MaxFunctionEvaluations
|
允许的最大函数计算次数,非负整数。对于
对于
|
MaxIterations
|
允许的最大迭代次数,非负整数。默认值为
对于
|
OptimalityTolerance
|
一阶最优性的终止容差(非负标量)。默认值为
|
OutputFcn
|
指定优化函数在每次迭代中调用的一个或多个用户定义的函数。传递函数句柄或函数句柄的元胞数组。默认值是“无”(
|
PlotFcn
|
对算法执行过程中的各种进度测量值绘图,可以选择预定义的绘图,也可以自行编写绘图函数。传递内置绘图函数名称、函数句柄或由内置绘图函数名称或函数句柄组成的元胞数组。对于自定义绘图函数,传递函数句柄。默认值是“无”(
自定义绘图函数使用与输出函数相同的语法。请参阅 Optimization Toolbox 的输出函数 和 Output Function and Plot Function Syntax 。
对于
|
SpecifyObjectiveGradient
|
如果为
对于
|
StepTolerance
|
对于
|
TypicalX
|
典型的
|
UseParallel
|
此选项为
|
信赖域算法 | |
JacobianMultiplyFcn
|
雅可比矩阵乘法函数,指定为函数句柄。对于大规模结构问题,此函数计算雅可比矩阵乘积
W = jmfun(Jinfo,Y,flag)
其中
[F,Jinfo] = fun(x)
以上任一情形都没有显式构造
注意
请参阅 Minimization with Dense Structured Hessian, Linear Equalities 了解类似示例。
对于
|
JacobPattern |
用于有限差分的雅可比矩阵稀疏模式。当
如果不方便计算
在最坏的情形下,如果结构未知,不要设置
|
MaxPCGIter |
PCG(预条件共轭梯度)迭代的最大次数,正标量。默认值为
|
PrecondBandWidth |
PCG 的预条件子上带宽,非负整数。
|
SubproblemAlgorithm
|
确定迭代步的计算方式。相比
|
TolPCG |
PCG 迭代的终止容差,正标量。默认值为
|
莱文贝格-马夸特算法 | |
InitDamping |
莱文贝格-马夸特参数的初始值,正标量。默认值是
|
ScaleProblem |
|
示例:
options = optimoptions('fsolve','FiniteDifferenceType','central')
problem
—
问题结构体
问题结构体,指定为含有以下字段的结构体:
字段名称 | 条目 |
---|---|
|
目标函数 |
|
x
的初始点
|
|
'fsolve'
|
|
用
optimoptions
创建的选项
|
数据类型:
struct
fval
— 解处的目标函数值
解处的目标函数值,以实数向量形式返回。通常,
fval
=
fun(x)
。
exitflag
—
fsolve
停止的原因
fsolve
停止的原因,以整数形式返回。
|
方程已解。一阶最优性很小。 |
|
方程已解。
|
|
方程已解。残差的变化小于指定容差。 |
|
方程已解。搜索方向的模小于指定容差。 |
|
迭代次数超出
|
|
输出函数或绘图函数使算法停止。 |
|
方程未得解。退出消息可能包含详细信息。 |
|
方程未得解。信赖域半径变得太小(
|
output
— 有关优化过程的信息
有关优化过程的信息,以包含下列字段的结构体形式返回:
iterations
|
执行的迭代次数 |
funcCount
|
函数计算次数 |
algorithm
|
使用的优化算法 |
cgiterations
|
PCG 迭代总数(仅适用于
|
stepsize
|
|
firstorderopt
|
一阶最优性的测度 |
message
|
退出消息 |
jacobian
— 解处的雅可比矩阵
解处的雅可比矩阵,以实矩阵形式返回。
jacobian(i,j)
是
fun(i)
关于解
x
处的
x(j)
的偏导数。
对于在解处有活动约束的问题,
jacobian
不适用于估计置信区间。
要求解的函数必须为连续的。
成功求解后,
fsolve
只给出一个根。
仅当方程组为方阵(即方程的数目等于未知数的数目)时,才使用默认的信赖域 dogleg 方法。如使用莱文贝格-马夸特方法,方程组不必为方阵。
对于大型问题,即变量数以千计、甚至更多的问题,将
Algorithm
选项设置为
'trust-region'
并将
SubproblemAlgorithm
选项设置为
'cg'
以节省内存(同时也可能节省时间)。
莱文贝格-马夸特和信赖域方法基于非线性最小二乘算法,该算法在
lsqnonlin
中也有使用。如果方程组不能包含零,请使用这些方法之一。该算法仍返回残差很小的点。然而,如果方程组的雅可比矩阵是奇异的,则算法收敛到的点可能并非方程组的解(请参阅
局限性
)。
默认情况下,
fsolve
选择信赖域 dogleg 算法。该算法是
[8]
中所述的鲍威尔 dogleg 方法的变体。它在本质上类似于在
[7]
中实现的算法。请参阅
信赖域 dogleg 算法
。
信赖域算法是一种子空间信赖域方法,基于 [1] 和 [2] 中所述的内部反射牛顿法。每次迭代都涉及使用预条件共轭梯度法 (PCG) 来近似求解大型线性系统。请参阅 信赖域算法 。
参考文献 [4] 、 [5] 和 [6] 中描述了莱文贝格-马夸特方法。请参阅 莱文贝格-马夸特方法 。
优化
实时编辑器任务为
fsolve
提供可视化界面。
[1] Coleman, T.F. and Y. Li, “An Interior, Trust Region Approach for Nonlinear Minimization Subject to Bounds,” SIAM Journal on Optimization, Vol. 6, pp. 418-445, 1996.
[2] Coleman, T.F. and Y. Li, “On the Convergence of Reflective Newton Methods for Large-Scale Nonlinear Minimization Subject to Bounds,” Mathematical Programming, Vol. 67, Number 2, pp. 189-224, 1994.
[3] Dennis, J. E. Jr., “Nonlinear Least-Squares,” State of the Art in Numerical Analysis, ed. D. Jacobs, Academic Press, pp. 269-312.
[4] Levenberg, K., “A Method for the Solution of Certain Problems in Least-Squares,” Quarterly Applied Mathematics 2, pp. 164-168, 1944.
[5] Marquardt, D., “An Algorithm for Least-squares Estimation of Nonlinear Parameters,” SIAM Journal Applied Mathematics, Vol. 11, pp. 431-441, 1963.
[6] Moré, J. J., “The Levenberg-Marquardt Algorithm: Implementation and Theory,” Numerical Analysis, ed. G. A. Watson, Lecture Notes in Mathematics 630, Springer Verlag, pp. 105-116, 1977.
[7] Moré, J. J., B. S. Garbow, and K. E. Hillstrom, User Guide for MINPACK 1, Argonne National Laboratory, Rept. ANL-80-74, 1980.
[8] Powell, M. J. D., “A Fortran Subroutine for Solving Systems of Nonlinear Algebraic Equations,” Numerical Methods for Nonlinear Algebraic Equations, P. Rabinowitz, ed., Ch.7, 1970.
fsolve
支持使用
codegen
(MATLAB Coder)
函数或
MATLAB Coder™
生成代码。您必须拥有
MATLAB Coder
许可证才能生成代码。
目标硬件必须支持标准双精度浮点计算。您不能为单精度或定点计算生成代码。
代码生成目标与 MATLAB 求解器不使用相同的数学核心函数库。因此,代码生成解可能不同于求解器解,尤其是对于病态问题。
生成的所有代码必须为 MATLAB 代码。特别是,您不能将自定义黑盒函数用作
fsolve
的目标函数。您可以使用
coder.ceval
计算用 C 或 C++ 编码的自定义函数。但是,自定义函数必须在 MATLAB 函数中调用。
在生成代码时,
fsolve
不支持
problem
参量。
[x,fval] = fsolve(problem) % Not supported
您必须使用函数句柄(而不是字符串或字符名称)来指定目标函数。
x = fsolve(@fun,x0,options) % Supported % Not supported: fsolve('fun',...) or fsolve("fun",...)
对于涉及嵌入式处理器的高级代码优化,您还需要 Embedded Coder ® 许可证。
您必须包括适用于
fsolve
的选项,并使用
optimoptions
指定这些选项。选项中必须包括
Algorithm
并将其设置为
'levenberg-marquardt'
。
options = optimoptions('fsolve','Algorithm','levenberg-marquardt'); [x,fval,exitflag] = fsolve(fun,x0,options);
代码生成支持以下选项:
Algorithm
- 必须为
'levenberg-marquardt'
FiniteDifferenceStepSize
FiniteDifferenceType
FunctionTolerance
MaxFunctionEvaluations
MaxIterations
SpecifyObjectiveGradient
StepTolerance
TypicalX
生成的代码只会对选项进行有限的错误检查。更新选项的推荐方法是使用
optimoptions
,而不是圆点表示法。
opts = optimoptions('fsolve','Algorithm','levenberg-marquardt'); opts = optimoptions(opts,'MaxIterations',1e4); % Recommended opts.MaxIterations = 1e4; % Not recommended
不要从文件中加载选项。否则会导致代码生成失败。请在代码中创建选项。
通常,如果您指定了不受支持的选项,在代码生成过程中会以静默方式忽略该选项。但是,如果使用圆点表示法指定绘图函数或输出函数,代码生成可能引发错误。为确保可靠性,请仅指定支持的选项。
由于不支持输出函数和绘图函数,求解器不会返回退出标志 –1。
有关示例,请参阅 为 fsolve 生成代码 。
要并行运行,请将
'UseParallel'
选项设置为
true
。
options = optimoptions('
solvername
','UseParallel',true)
有关详细信息,请参阅 在 Optimization Toolbox 中使用并行计算 。
JacobianMultiplyFcn
接受任何数据类型
JacobianMultiplyFcn
选项的语法是
W = jmfun(Jinfo, Y, flag)
MATLAB 传递给函数
jmfun
的
Jinfo
数据现在可以是任何数据类型。例如,现在
Jinfo
可以采用结构体类型。在以前的版本中,
Jinfo
必须为标准的双精度数组。
Jinfo
数据是目标函数的第二个输出:
[F,Jinfo] = myfun(x)
CheckGradients
选项将被删除
以后的版本中将会删除
CheckGradients
选项。要检查目标函数或非线性约束函数的一阶导数,请使用
checkGradients
函数。
威武的馒头 · JUnit 5 参数化测试 1 年前 |