对于非线性方程,我们可以使用迭代的方式求出近似解。下面介绍两种比较经典的算法:简单迭代法、牛顿法
简单迭代法
对于待求解方程,先把方程写成
f
(
x
)
=
0
f(x)=0
f(x)=0 的形式,然后改成如下同解形式:
x
=
φ
(
x
)
x = \varphi(x)
x=φ(x)选一个初始值
x
0
x_0
x0,然后做迭代:
x
k
+
1
=
φ
(
x
k
)
,
k
=
1
,
2
,
3
,
…
x_{k+1}=\varphi(x_{k}), \;\;\;\;k=1,2,3,\dots
xk+1=φ(xk),k=1,2,3,…如果迭代序列
{
x
k
}
\{x_k\}
{xk} 收敛于真解,则称简单迭代法使收敛的。
简单迭代法的收敛条件
根据压缩映射原理,如果 φ ( x ) \varphi(x) φ(x) 为定义域上的压缩映射,则 φ ( x ) \varphi(x) φ(x) 在定义域上有唯一的不动点,且对于任何初值,由迭代格式 x k + 1 = φ ( x k ) x_{k+1}=\varphi(x_{k}) xk+1=φ(xk) 产生的迭代序列 { x k } \{x_k\} {xk} 收敛于该不动点。
另外我们还常常讨论简单迭代法的局部收敛性,感兴趣的同学查阅相关书籍,此处不再赘述。
简单迭代法的Aitken加速算法
假设
φ
(
x
)
\varphi(x)
φ(x) 在
α
\alpha
α 处可导,有
x
k
+
1
−
α
=
φ
′
(
ξ
1
)
(
x
k
−
α
)
x
k
+
2
−
α
=
φ
′
(
ξ
2
)
(
x
k
+
1
−
α
)
x_{k+1} - \alpha=\varphi'(\xi_1)(x_k-\alpha)\\ x_{k+2} - \alpha=\varphi'(\xi_2)(x_{k+1}-\alpha)
xk+1−α=φ′(ξ1)(xk−α)xk+2−α=φ′(ξ2)(xk+1−α)假设
φ
′
(
ξ
1
)
≈
φ
′
(
ξ
2
)
\varphi'(\xi_1)\approx \varphi'(\xi_2)
φ′(ξ1)≈φ′(ξ2),有
x
k
+
1
−
α
x
k
+
2
−
α
=
x
k
−
α
x
k
+
1
−
α
\frac{x_{k+1}-\alpha}{x_{k+2} - \alpha}=\frac{x_k-\alpha}{x_{k+1} - \alpha}
xk+2−αxk+1−α=xk+1−αxk−α得到
α
=
x
k
−
(
x
k
+
1
−
x
k
)
2
x
k
+
2
−
2
x
k
+
1
+
x
k
\alpha=x_k-\frac{(x_{k+1}-x_k)^2}{x_{k+2}-2x_{k+1} +x_k}
α=xk−xk+2−2xk+1+xk(xk+1−xk)2记
x
^
k
=
x
k
−
(
x
k
+
1
−
x
k
)
2
x
k
+
2
−
2
x
k
+
1
+
x
k
k
=
1
,
2
,
3
,
…
\widehat x_k=x_k-\frac{(x_{k+1}-x_k)^2}{x_{k+2}-2x_{k+1} +x_k} \;\;\;\;k=1,2,3,\dots
x
k=xk−xk+2−2xk+1+xk(xk+1−xk)2k=1,2,3,…以上即为Aitken加速算法的迭代格式,序列
{
x
^
k
}
\{\widehat x_k\}
{x
k} 要比序列
{
x
k
}
\{x_k\}
{xk} 更快地收敛于
α
\alpha
α 。
为方便计算可构造如下Aitken加速算法
{
y
k
=
φ
(
x
k
)
z
k
=
φ
(
x
k
)
x
k
+
1
=
x
k
−
(
y
k
−
x
k
)
2
z
k
−
2
y
k
+
x
k
,
k
=
0
,
1
,
2
,
⋯
\left\{\begin{array}{l}y_k=\varphi(x_k)\\z_k=\varphi(x_k)\\x_{k+1}=x_k-\frac{{(y_k-x_k)}^2}{z_k-2y_k+x_k},\;\;k=0,1,2,\cdots\end{array}\right.
⎩⎨⎧yk=φ(xk)zk=φ(xk)xk+1=xk−zk−2yk+xk(yk−xk)2,k=0,1,2,⋯
基于Pyhton实现的Aitken加速算法
算法代码
import numpy as np
import math
def Aitken(x0,epsilon,iternum,phi):#初值,精度要求,最大迭代次数,迭代函数
xk_1 = x0
for i in range(iternum):
y = phi(xk_1)
z = phi(y)
if (z - 2*y +xk_1)!= 0:
xk = xk_1 - (y - xk_1)**2 / (z - 2*y +xk_1)
print("第",i+1,"次迭代 ","xk=",xk," xk-1=",xk_1," |xk - xk-1|=",abs(xk-xk_1));
if abs(xk-xk_1)<epsilon:
return xk
else:
xk_1 = xk
else:
return x
print("方法失败")
return 0
实验
计算 x k + 1 = 1.6 + 0.99 c o s ( x ) x_{k+1}=1.6+0.99cos(x) xk+1=1.6+0.99cos(x) 在初值取 x 0 = π 2 x_0=\frac\pi2 x0=2π 时的根。
def phi(x): #φ
return 1.6+0.99*math.cos(x)
Aitken(1.57080,1/(10)**7,10,phi)#初值1.57080,精度10^-7,最大迭代次数为10
实验结果
最终结果为 1.585471801521943
牛顿迭代法
设函数
f
(
x
)
=
0
f(x)=0
f(x)=0 在有根区间
[
a
,
b
]
[a,b]
[a,b] 上二阶连续可微,
x
0
x_0
x0 是
α
\alpha
α 的近似值,将
f
(
x
)
f(x)
f(x) 在
x
0
x_0
x0 处作Taylor展开,有
f
(
x
)
=
f
(
x
0
)
+
f
′
(
x
0
)
(
x
−
x
0
)
+
f
′
′
(
ξ
0
)
(
x
−
x
0
)
2
2
f(x) = f(x_0) + f'(x_0)(x - x_0)+f''(\xi_0)\frac{(x-x_0)^2}{2}
f(x)=f(x0)+f′(x0)(x−x0)+f′′(ξ0)2(x−x0)2用其线性主部近似
f
(
x
)
f(x)
f(x)
f
(
x
)
≈
f
(
x
0
)
+
f
′
(
x
0
)
(
x
−
x
0
)
f(x) \approx f(x_0) + f'(x_0)(x - x_0)
f(x)≈f(x0)+f′(x0)(x−x0)将非线性方程
f
(
x
)
=
0
f(x)=0
f(x)=0 近似化为线性方程
f
(
x
0
)
+
f
′
(
x
0
)
(
x
−
x
0
)
=
0
f(x_0) + f'(x_0)(x - x_0)=0
f(x0)+f′(x0)(x−x0)=0若
f
′
(
x
0
)
f'(x_0)
f′(x0) 不为0,则有
x
1
=
x
0
−
f
(
x
0
)
f
′
(
x
0
)
x_1 = x_0-\frac{f(x_0)}{f'(x_0)}
x1=x0−f′(x0)f(x0)一般地,有
x
k
+
1
=
x
k
−
f
(
x
k
)
f
′
(
x
k
)
x_{k+1} = x_k-\frac{f(x_k)}{f'(x_k)}
xk+1=xk−f′(xk)f(xk)以上迭代格式称为牛顿迭代格式。
基于Pyhton实现的牛顿迭代法
算法代码
import numpy as np
import math
from scipy.misc import derivative
def Newton(x0,epsilon,iternum,f):#初值,精度要求,最大迭代次数,迭代函数
xk_1 = x0
for i in range(iternum):
fx = f(xk_1)
fdx = derivative(f,xk_1,dx=1e-6)
if fdx!= 0:
xk = xk_1 - fx / fdx
print("第",i+1,"次迭代 ","xk=",xk," xk-1=",xk_1," |xk - xk-1|=",abs(xk-xk_1));
if abs(xk-xk_1)<epsilon:
return xk
else:
xk_1 = xk
else:
break
print("方法失败")
return 0
实验
求方程
x
e
x
−
1
=
0
xe^x-1=0
xex−1=0 在
0.5
0.5
0.5 处的根,要求精度为
ε
=
1
0
−
5
\varepsilon=10^{-5}
ε=10−5 。
def func(x): #f
return x*math.exp( x )-1
Newton(0.5,1/(10**5),10,func)
实验结果
最终结果为 0.5671432904097838