问题简介
非线性方程 f(x)=0 的数值求解是科学计算的核心问题之一,其通常不存在闭式解,需借助区间收缩或不动点迭代等方法来逼近根。
定义(根与重根):
若存在 x∗ 使得 f(x∗)=0,则称 x∗ 为方程的根或零点。若 f(x) 可分解为:
f(x)=(x−x∗)mg(x),g(x∗)=0
其中 m 为正整数,则称 x∗ 为方程的 m 重根。
定理(根的存在性定理):
设 f(x)∈C[a,b] 且 f(a)⋅f(b)<0,则方程 f(x)=0 在 (a,b) 内至少存在一个根。
二分法
数学基础
二分法基于根的存在性定理来进行区间收缩,通过不断将含根区间对半分割,并以区间中点作为根的近似。
算法实现
fa = f(a)
while b - a > EPS:
p = a + (b - a) / 2.0 # 中点(避免 a+b 溢出)
fp = f(p)
if fp == 0:
return p
if fa * fp < 0: # 符号与 f(a) 相反
b = p
else:
a = p
fa = fp
res = a + (b - a) / 2.0
稳定性与复杂度分析
稳定性:
二分法的误差随区间长度线性减小,属于稳定算法。
但终止条件 ∣bn−an∣<ε 受浮点精度限制,若 ε 过小会导致无限循环。
一般选取:
ε=max{∣a∣,∣b∣}⋅2εmach
其中 εmach 为机器精度,IEEE 754 双精度下 εmach≈2.22×10−16。
复杂度分析:
| 指标 | 结果 | 说明 |
|---|
| 时间复杂度 | O(log2εb−a) | 迭代区间减半 1 次需 1 次函数求值 |
| 空间复杂度 | O(1) | 仅存储端点与中点 |
注:
二分法对函数要求极低(连续性),但收敛速度仅为线性,且无法处理偶数重根。
不动点迭代法
数学基础
定义(不动点):
对于函数 φ(x),若 x∗=φ(x∗),则称 x∗ 为 φ 的不动点。
构造迭代格式:
xk+1=φ(xk),k=0,1,2,…
该格式仅依赖前一步 xk,故为单步法;右端不含 xk+1,故为显式算法。
注:将 f(x)=0 等价改写为 x=φ(x) 的方式不唯一,不同方式的效果不同。
全局收敛的充分条件
定理(不动点存在唯一性与收敛性):
设 φ(x)∈C1[a,b] 且满足
- 封闭性(closure):∀x∈[a,b],φ(x)∈[a,b];
- 压缩性(contraction):∃L∈[0,1),s.t.∣φ′(x)∣≤L,∀x∈[a,b]。
则:
- φ 在 [a,b] 上存在唯一不动点 x∗;
- ∀x0∈[a,b],迭代序列 {xk},xk+1=φ(xk) 均收敛到 x∗;
- k→∞limxk−x∗xk+1−x∗=φ′(x∗)。
注:条件中的 a 可为 −∞,b 可为 +∞。
证明:
-
存在性:
构造 h(x)=φ(x)−x。
由封闭性:
h(a)=φ(a)−a≥0,h(b)=φ(b)−b≤0
因 h∈C[a,b],根据介值定理,∃x∗∈[a,b] 使 h(x∗)=0,即 x∗=φ(x∗)。
-
唯一性:
假设存在两个不动点 x1,x2∈[a,b]。由微分中值定理,
∣x1−x2∣=∣φ(x1)−φ(x2)∣=∣φ′(ξ)∣⋅∣x1−x2∣≤L∣x1−x2∣
因 L<1,必有 ∣x1−x2∣=0,即 x1=x2。
-
收敛性与渐近误差常数:
反复应用中值定理,
∣xk−x∗∣=∣φ(xk−1)−φ(x∗)∣≤L∣xk−1−x∗∣≤⋯≤Lk∣x0−x∗∣
故 k→∞ 时 xk→x∗。再由中值定理,∃ξk 介于 xk 与 x∗ 之间,使得
xk−x∗xk+1−x∗=xk−x∗φ(xk)−φ(x∗)=φ′(ξk)
令 k→∞,由 ξk→x∗ 及 φ′ 的连续性,得极限为 φ′(x∗)。
局部收敛的充要条件
定理(不动点迭代的局部收敛性判别):
设 x∗ 为 φ 的不动点,且 φ 在 x∗ 的某邻域内连续可微。则:
-
收敛:
若 ∣φ′(x∗)∣<1,则存在 x∗ 的邻域 U,使得 ∀x0∈U,迭代序列 {xk},xk+1=φ(xk) 均收敛到 x∗,且
k→∞limxk−x∗xk+1−x∗=φ′(x∗)
-
发散:
若 ∣φ′(x∗)∣>1,则存在 x∗ 的邻域 U,使得 ∀x0∈U 且 x0=x∗,迭代序列 {xk} 不收敛到 x∗,且 ∣xk+1−x∗∣>∣xk−x∗∣。
-
临界:
若 ∣φ′(x∗)∣=1,收敛性不确定,需通过 φ 的更高阶导数以及具体结构判断。
证明:
情形 1(∣φ′(x∗)∣<1):
由连续性,存在 δ>0 和 L∈[0,1),使得
∣φ′(x)∣≤L,∀x∈U=[x∗−δ,x∗+δ]
对任意 x∈U,由中值定理:
∣φ(x)−x∗∣=∣φ′(ξ)∣⋅∣x−x∗∣≤L∣x−x∗∣<δ
故 φ(x)∈U,即封闭性成立。从而可知收敛。
情形 2(∣φ′(x∗)∣>1):
由连续性,存在 δ>0 和 L>1,使得
∣φ′(x)∣≥L,∀x∈U=[x∗−δ,x∗+δ]
对任意 x0∈U 且 x0=x∗,由中值定理:
∣x1−x∗∣=∣φ(x0)−φ(x∗)∣=∣φ′(ξ0)∣⋅∣x0−x∗∣≥L∣x0−x∗∣>∣x0−x∗∣
故不收敛。
误差估计
定理(先验与后验误差估计):
在全局收敛的必要条件中的条件下,有先验估计:
∣xk−x∗∣≤1−LLk∣x1−x0∣
以及后验估计:
∣xk−x∗∣≤1−L1∣xk+1−xk∣
证明:
对任意正整数 p,利用三角不等式与压缩性:
∣xk+p−xk∣≤i=1∑p∣xk+i−xk+i−1∣≤(Lk+p−1+⋯+Lk)∣x1−x0∣=1−LLk(1−Lp)∣x1−x0∣
令 p→∞ 即得先验估计。同理,
∣xk+p−xk∣≤(Lp−1+⋯+1)∣xk+1−xk∣=1−L1−Lp∣xk+1−xk∣
令 p→∞ 即得后验估计。
注:后验估计表明,当相邻两次迭代值之差足够小时,真实误差也足够小,可用于停机判断。
算法实现
x = x0
res = None
for _ in range(N):
x_new = phi(x)
if abs(x_new - x) < EPS:
res = x_new
break
x = x_new
收敛阶与误差分析
定义(收敛阶):
设 limk→∞xk=x∗,记 ek=xk−x∗。若存在实数 p≥1 及常数 c=0,使得
k→∞lim∣ek∣p∣ek+1∣=c
则称序列 {xk} 为 p 阶收敛。特别地:
- p=1,0<c<1:线性收敛;
- p=2:平方收敛;
- p=1,c=0:超线性收敛。
定理(高阶收敛判据):
设迭代函数 φ(x) 满足:
- x∗=φ(x∗),且在 x∗ 附近有 p 阶连续导数;
- φ′(x∗)=φ′′(x∗)=⋯=φ(p−1)(x∗)=0;
- φ(p)(x∗)=0。
则不动点迭代为 p 阶收敛,且
k→∞limekpek+1=p!φ(p)(x∗)
证明:
对 φ(xk) 在 x∗ 处作 Taylor 展开:
φ(xk)=φ(x∗)+j=1∑p−1j!φ(j)(x∗)ekj+p!φ(p)(ξ)ekp=φ(x∗)+p!φ(p)(ξ)ekp
其中 ξ 介于 xk 与 x∗ 之间。于是:
ekpek+1=ekpφ(xk)−φ(x∗)=p!φ(p)(ξ)
令 k→∞,由 ξ→x∗ 得证。
注:也即高阶导数为 0 会带来更高阶的收敛性,这也是下面迭代加速法的基本思想。
迭代加速方法
松弛法
思想:
从 x=φ(x) 出发,引入参数 λ 构造等价形式
x=1+λλx+1+λ1φ(x)≡ψ(x)
其导数为
ψ′(x)=1+λλ+φ′(x)
若选取 λ 使 ∣ψ′(x)∣<∣φ′(x)∣,则新格式收敛更快。理论上最优 λ=−φ′(x∗)。
但 x∗ 未知,故以当前迭代值近似:
λk=−φ′(xk),ωk=1+λk1
得到松弛迭代格式:
xk+1=(1−ωk)xk+ωkφ(xk)
松弛法算法实现
x = x0
res = None
for k in range(N):
lamb = -dphi(x)
omega = 1.0 / (1.0 + lamb)
x_new = (1 - omega) * x + omega * phi(x)
if abs(x_new - x) < EPS:
res = x_new
break
x = x_new
注:松弛法需额外计算 φ′(x),适用于导数易求的情形。
Steffensen 法
思想:
若原序列 {xk} 线性收敛,当 k 充分大时近似有
xk+1−x∗xk+2−x∗≈xk−x∗xk+1−x∗
交叉相乘解出 x∗ 的近似:
x∗≈xk−xk+2−2xk+1+xk(xk+1−xk)2
定义(差分算子):
- 向前差分:Δxk=xk+1−xk
- 二阶差分:Δ2xk=Δ(Δxk)=xk+2−2xk+1+xk
定义(Aitken 加速序列):
x^k=xk−Δ2xk(Δxk)2=xk−xk+2−2xk+1+xk(xk+1−xk)2
Steffensen 法:
使用 Aitken 加速序列来进行不动点迭代就是 Steffensen 法。也即令:
xk+1=xk−φ(φ(xk))−2φ(xk)+xk(φ(xk)−xk)2
等价于使用新的迭代函数:
φ^(x)=φ(φ(x))−2φ(x)+xxφ(φ(x))−φ2(x)
验证正确性:
由 L’Hôpital 法则可得:
x→x∗limφ^(x)=x→x∗limφ′(φ(x))φ′(x)−2φ′(x)+1φ(φ(x))+xφ′(φ(x))φ′(x)−2φ(x)φ′(x)=(φ′(x∗))2−2φ′(x∗)+1x∗+x∗(φ′(x∗))2−2x∗φ′(x∗)=(1−φ′(x∗))2x∗(1−φ′(x∗))2=x∗
故 x∗ 仍为 φ^ 的不动点。
Steffensen 法算法实现
x = x0
res = None
for k in range(N):
x1 = phi(x)
x2 = phi(x1)
denom = x2 - 2*x1 + x
if abs(denom) < 1e-15:
res = x
break
x_new = x - (x1 - x)**2 / denom
if abs(x_new - x) < eps:
res = x_new
break
x = x_new
注:Steffensen 法无需计算导数,每步仅需两次 φ 求值,即可将线性收敛提升为平方收敛。
Ramanujan 迭代法
数学基础
Ramanujan 迭代法是通过幂级数系数递推求模最小根的方法。
考虑方程:
f(x)=1−(a1x+a2x2+⋯)=0
对 [1−∑n=1∞anxn]−1=∑n=0∞bnxn 比较系数,得到递推关系:
b0=1,bn=i=1∑naibn−i(n≥1)
不加证明地指出,若极限 limn→∞bn/bn+1=c 存在,则 c 即为 f(x)=0 的模最小根。
算法实现
def ramanujan(coeffs, max_n):
"""
coeffs: list [a_1, a_2, ..., a_m]
返回序列 b 以及近似根序列 b[n-1]/b[n]
"""
b = [1.0] # b_0
roots = []
for n in range(1, max_n + 1):
bn = 0.0
for i in range(1, min(n, len(coeffs)) + 1):
bn += coeffs[i-1] * b[n - i]
b.append(bn)
if n >= 1 and abs(bn) > 1e-15:
roots.append(b[n-1] / bn)
return b, roots
方法对比与复杂度总表
| 方法 | 收敛条件 | 收敛阶 | 时间复杂度/步 | 空间复杂度 |
|---|
| 二分法 | f∈C[a,b],f(a)f(b)<0 | 线性 p=1 | O(log(1/ε)) | O(1) |
| 不动点迭代 | φ 压缩映射 | 线性 p=1 | O(log(1/ε)) | O(1) |
| 松弛法 | φ′ 存在且连续 | 线性(加速) | O(log(1/ε)) | O(1) |
| Steffensen | φ∈C2 附近 | 平方 p=2 | O(loglog(1/ε)) | O(1) |
| Ramanujan | 幂级数形式,模最小根唯一 | 线性 | O(n2) 递推 n 项 | O(n) |