20.1 求解器

Octave 可以求解以下形式的非线性方程组

F (x) = 0

使用的函数是 fsolve,它基于 MINPACK 子程序 hybrd。这是一种迭代技术,因此必须提供一个起始点。 这也意味着即使解存在,也不能保证收敛。

 
x = fsolve (fcn, x0)
x = fsolve (fcn, x0, options)
[x, fval] = fsolve (…)
[x, fval, info] = fsolve (…)
[x, fval, info, output] = fsolve (…)
[x, fval, info, output, fjac] = fsolve (…)

求解由函数 fcn 定义的非线性方程组。

fcn 是一个函数句柄、内联函数或字符串,包含要计算的函数的名称。fcn 应接受一个定义未知变量的向量(数组),并返回方程左侧的向量。方程右侧定义为零。换句话说,此函数试图确定一个向量 x,使得 fcn (x) 给出(近似)全零。

x0 是对解的初始猜测。x0 的形状在所有对 fcn 的调用中保持不变,但在其他情况下被视为列向量。

options 是一个结构体,指定控制算法的附加参数。目前,fsolve 识别以下选项: "AutoScaling""ComplexEqn""FinDiffType""FunValCheck""Jacobian""MaxFunEvals""MaxIter""OutputFcn""TolFun""TolX""TypicalX""Updating"

如果 "AutoScaling""on",变量将根据(估计的)雅可比矩阵的列范数自动缩放。因此 "TolFun" 变得与缩放无关。默认情况下,此选项为 "off",因为它有时可能会返回意想不到的(尽管在数学上是正确的)结果。

如果 "ComplexEqn""on"fsolve 将尝试求解复变量中的复方程,假设方程具有复导数(即全纯函数)。如果这不是你想要的,你应该将系统的实部和虚部分开,得到一个实数系统。

如果 "Jacobian""on",它指定 fcn — 当使用 2 个输出参数调用时 — 也会在指定点返回右侧的雅可比矩阵。

"MaxFunEvals" 限制优化停止前的最大函数评估次数。默认值为 100 * number_of_variables,即 100 * length (x0)。该值必须是正整数。

如果 "Updating""on",函数将尝试使用 Broyden 更新来更新雅可比矩阵,以减少雅可比计算次数。如果用户函数总是计算雅可比矩阵(无论输出参数数量如何),则此选项没有任何优势,应禁用。

"TolX" 指定未知变量的终止容限,而 "TolFun" 是方程的容限。默认为 1e-6,适用于 "TolX""TolFun"

有关其他选项的描述, 请参阅 optimset。要使用 fsolve 的默认值初始化选项结构体,请使用 options = optimset ("fsolve")

第一个输出 x 是解,第二个输出 fval 包含在 x 处计算的函数 fcn 的值(理想情况下是全零向量)。

第三个输出 info 报告算法是否成功,可能取以下值之一:

1

收敛到解点。相对残差小于 TolFun 指定的值。

2

最后相对步长小于 TolX

3

残差的最后相对减小量小于 TolFun

0

迭代限制(MaxIterMaxFunEvals)已超过。

-1

OutputFcn 停止。

-2

雅可比矩阵变得过小,搜索停滞。

-3

信赖域半径变得过小。

output 是一个结构体,包含有关 fsolve 算法的运行时信息。结构体中的字段有:

iterations

循环迭代次数。

successful

成功迭代的次数。

funcCount

函数评估次数。

最后一个输出 fjac 包含在 x 处计算的雅可比矩阵的值。

注意:如果你只有一个变量的单个非线性方程,使用 fzero 通常是更好的选择。

关于用户提供的雅可比矩阵的注意事项: 作为算法的固有属性,对于残差向量已知的解向量,总是会请求雅可比矩阵,并且这是最后一个被接受的成功步骤。这通常是最后两次调用中的一次,但并非总是如此。如果从残差计算中重用中间结果在雅可比矩阵计算中能显著节省成本,最佳策略是使用 OutputFcn:在评估向量的残差之后,如果 OutputFcn 用该向量被调用,则应将中间结果保存以供将来的雅可比矩阵求值使用,并应保留到请求雅可比矩阵求值或被 OutputFcn 用不同的向量调用为止,此时应丢弃旧结果并支持最新的向量。以下是实现此目的的一个简短示例:

function [fval, fjac] = user_fcn (x, optimvalues, state)
persistent sav = [], sav0 = [];
if (nargin == 1)
  ## evaluation call
  if (nargout == 1)
    sav0.x = x;  # mark saved vector
    ## calculate fval, save results to sav0.
  elseif (nargout == 2)
    ## calculate fjac using sav.
  endif
else
  ## outputfcn call.
  if (all (x == sav0.x))
    sav = sav0;
  endif
  ## maybe output iteration status, etc.
endif
endfunction

## ...

fsolve (@user_fcn, x0, optimset ("OutputFcn", @user_fcn, ...))

另请参阅: fzerooptimset

以下是一个完整示例。要求解方程组

-2x^2 + 3xy   + 4 sin(y) = 6
 3x^2 - 2xy^2 + 3 cos(x) = -4

首先需要编写一个函数来计算给定函数的值。例如:

function y = f (x)
  y = zeros (2, 1);
  y(1) = -2*x(1)^2 + 3*x(1)*x(2)   + 4*sin(x(2)) - 6;
  y(2) =  3*x(1)^2 - 2*x(1)*x(2)^2 + 3*cos(x(1)) + 4;
endfunction

然后,在给定初始条件下调用 fsolve 求出方程组的根。例如,给定上面定义的函数 f

[x, fval, info] = fsolve (@f, [1; 2])

得到解

x =

  0.57983
  2.54621

fval =

  -5.7184e-10
   5.5460e-10

info = 1

info = 1 表示解已收敛。

当没有提供雅可比矩阵时(如上例所示),它将通过数值方法近似。这需要更多函数评估,因此效率较低。在上例中,我们可以解析计算雅可比矩阵:

function [y, jac] = f (x)
  y = zeros (2, 1);
  y(1) = -2*x(1)^2 + 3*x(1)*x(2)   + 4*sin(x(2)) - 6;
  y(2) =  3*x(1)^2 - 2*x(1)*x(2)^2 + 3*cos(x(1)) + 4;
  if (nargout == 2)
    jac = zeros (2, 2);
    jac(1,1) =  3*x(2) - 4*x(1);
    jac(1,2) =  4*cos(x(2)) + 3*x(1);
    jac(2,1) = -2*x(2)^2 - 3*sin(x(1)) + 6*x(1);
    jac(2,2) = -4*x(1)*x(2);
  endif
endfunction

然后,雅可比矩阵可以通过以下调用用于 fsolve

[x, fval, info] = fsolve (@f, [1; 2], optimset ("jacobian", "on"));

这给出与之前相同的解。

 
x = fzero (fcn, x0)
x = fzero (fcn, x0, options)
[x, fval] = fzero (…)
[x, fval, info] = fzero (…)
[x, fval, info, output] = fzero (…)

求单变量函数的零点。

fcn 是一个函数句柄、内联函数或字符串,包含要计算的函数的名称。

x0 应为一个二元素向量,指定包含零点的两个点。换句话说,函数在 x0(1) 和 x0(2) 之间必须改变符号。更数学地说,以下条件必须成立:

sign (fcn (x0(1))) * sign (fcn (x0(2))) <= 0

如果 x0 是单个标量,则会探测几个附近和远处的值,试图获得有效的括号区间。如果不成功,则函数失败。

options 是一个指定附加参数的结构体。目前,fzero 识别这些选项: "Display""FunValCheck""MaxFunEvals""MaxIter""OutputFcn""TolX"

"MaxFunEvals" 限制搜索停止前的最大函数评估次数。默认值为 Inf。该值必须是正整数。

"MaxIter" 限制搜索停止前的最大算法迭代次数。默认值为 Inf。该值必须是正整数。

"TolX" 指定解 x 的终止容限。默认值为 eps

有关其他选项的描述, 请参阅 optimset。 要使用 fzero 的默认值初始化选项结构体,请使用 options = optimset ("fzero")

退出时,函数返回 x(近似零点)和 fval(在 x 处计算的函数值)。

第三个输出 info 报告算法是否成功,可能取以下值之一:

  • 1 算法收敛到一个解。
  • 0 已达到最大迭代次数或最大函数评估次数。
  • -1 算法已被用户的 OutputFcn 终止。
  • -5 算法可能收敛到一个奇异点。
  • -6 未找到有效的符号变化起始括号区间。

output 是一个结构体,包含有关 fzero 算法的运行时信息。结构体中的字段有:

  • intervaliterations 搜索括号区间的迭代次数。
  • iterations 搜索零点的迭代次数。
  • funcCount 函数评估次数。
  • algorithm 字符串 "bisection, interpolation"
  • message 算法的最终状态字符串。
  • bracketx 一个二元素向量,包含零点沿 x 轴的最终括号区间。
  • brackety 一个二元素向量,包含零点沿 y 轴的最终括号区间。

编程注意事项:该算法依赖于函数穿过 x 轴,并且同时具有正值和负值。它通常不适用于仅触及 x 轴的函数,例如 x^2。 如果提供了二元素括号区间 x0,函数通常会更快,因为不会进行区间搜索。

另请参阅: fsolvefminbndoptimset


版权所有 © 2024-2026 Octave中文网

ICP备案/许可证号:黑ICP备2024030411号-2