第2.1章 迭代法#

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import linregress
import pandas as pd

直接迭代法#

N = 12

def direct_iterations(φ, x0, N):
    x_list = np.zeros(N)
    x_list[0] = x0
    for j in range(1,N):
        x_list[j] = φ(x_list[j-1])
    return x_list

例子1:\(\varphi(x) = x^2\)#

φ = lambda x : x**2
plt.figure(figsize=(5,4))
plt.plot(direct_iterations(φ, -1/2, N),'o--', label=r"$x_0=-0.5$")
plt.plot(direct_iterations(φ, 1/2, N) ,'x--', label=r"$x_0=0.5$")
plt.plot(direct_iterations(φ, 1.001, N),'v--', label=r"$x_0=1.001$")
plt.title("Iteration method",fontsize=14)
plt.legend(fontsize=14)
plt.tight_layout()
plt.show()
_images/f2472fa5b0f9d54fb148babb4a2d8f6a5bb6634c1b29a28ede0a2978f5a4b6ac.png
φ = lambda x : x**2
plt.figure(figsize=(5,4))
plt.plot(direct_iterations(φ, 2, 10),'d--', label=r"$x_0=2$")
plt.yscale("log")
plt.title("Iteration method can fail",fontsize=14)
plt.legend(fontsize=14)
plt.tight_layout()
plt.show()
_images/01ad605222107fe47f35bd0acffc88afe665e3e981ca36668e907110089a4d46.png

例子2:\(\varphi(x) = c \sin(x)\)#

φ = lambda x : np.pi/2 * np.sin(x)
plt.figure(figsize=(5,4))
plt.plot(direct_iterations(φ, -1/2, N),'o--', label=r"$x_0=-0.5$")
plt.plot(direct_iterations(φ, -0.2, N),'d--', label=r"$x_0=-0.2$")
plt.plot(direct_iterations(φ, 0.2, N),'v--', label=r"$x_0=0.2$")
plt.plot(direct_iterations(φ, 1/2, N) ,'x--', label=r"$x_0=0.5$")
plt.title(r"Iteration method, $\varphi(x) = \frac{\pi}{2}\sin(x)$", fontsize=14)
plt.legend(fontsize=14)
plt.tight_layout()
plt.show()
_images/c8b487900691366c5c1a374409d4ece4db2ad605869f776b8cf4fd3a38b91619.png
φ = lambda x : 1/2 * np.sin(x)
plt.figure(figsize=(5,4))
plt.plot(direct_iterations(φ, -0.5, N),'o--', label=r"$x_0=-0.5$")
plt.plot(direct_iterations(φ, -0.2, N),'d--', label=r"$x_0=-0.2$")
plt.plot(direct_iterations(φ, 0.2, N),'v--', label=r"$x_0=0.2$")
plt.plot(direct_iterations(φ, 0.5, N) ,'x--', label=r"$x_0=0.5$")
plt.legend(fontsize=14)
plt.title(r"Iteration method, $\varphi(x) = \frac{1}{2}\sin(x)$")
plt.tight_layout()
plt.show()
_images/63f01967a1d87d41c67f3db722909e7a06709c513c166eaeecbf6e500def11f9.png
pd.DataFrame({"误差" : np.abs(direct_iterations(φ, 0.01, 10) - 0.0)})
误差
0 0.010000
1 0.005000
2 0.002500
3 0.001250
4 0.000625
5 0.000312
6 0.000156
7 0.000078
8 0.000039
9 0.000020

例子3:\(\varphi(x) = |x|^{1/2}\)#

φ = lambda x : np.abs(x)**(1/2)

plt.figure(figsize=(5,4))
plt.plot(direct_iterations(φ, -1/2, N),'o--', label=r"$x_0=-0.5$")
plt.plot(direct_iterations(φ, 1/2, N) ,'x--', label=r"$x_0=0.5$")
plt.plot(direct_iterations(φ, 1.001, N),'v--', label=r"$x_0=1.001$")
plt.plot(direct_iterations(φ, 2, N),'v--', label=r"$x_0=2$")
plt.title(r"Iteration method, $\varphi(x) = \sqrt{|x|}$",fontsize=14)
plt.legend(fontsize=14)
plt.tight_layout()
plt.show()
_images/0f0e0802eb3334ace21ffd1cbdd8466f07b1208876382fe7af578040dfaae7cd.png

验证收敛速度#

N = 10
x0_list = [-0.5, 0.5, 1.001, 2]
y_list = np.zeros((len(x0_list),N))
plt.figure(figsize=(6,4))
for j in range(len(x0_list)):
    y_list[j,:] =  direct_iterations(φ, x0_list[j], N)

plt.plot(np.abs(y_list[0,:]-1), 'o--',label=r"$x_0=-0.5$")
plt.plot(np.abs(y_list[1,:]-1), 'o--',label=r"$x_0=0.5$")
plt.plot(np.abs(y_list[2,:]-1), 'o--',label=r"$x_0=1.001$")
plt.plot(np.abs(y_list[3,:]-1), 'o--',label=r"$x_0=2$")
plt.yscale('log')
plt.title(r"Error of iteration method, $\varphi(x) = \sqrt{|x|}$",fontsize=14)
plt.legend(fontsize=14, loc=(1.01,0.2))
plt.tight_layout()
_images/52afd69c5b25c5bca95b1290f91584a9fc56182f41bd34b6572f82d3ed54f33e.png
x = np.array(range(N))
slope0, _,r,_,se = linregress(x[-5:], np.log(np.abs(y_list[0,:]-1))[-5:])
slope1, _,_,_,_ = linregress(x[-5:], np.log(np.abs(y_list[1,:]-1))[-5:])
slope2, _,_,_,_ = linregress(x[-5:], np.log(np.abs(y_list[2,:]-1))[-5:])
slope3, _,_,_,_ = linregress(x[-5:], np.log(np.abs(y_list[3,:]-1))[-5:])
print("slope 0 =             {:.4f}".format(slope0))
print("slope 1 =             {:.4f}".format(slope1))
print("slope 2 =             {:.4f}".format(slope2))
print("slope 3 =             {:.4f}".format(slope3))
print("Prediction (theory) = {:.4f}".format(np.log(1/2)))

print()
print("R = {:4f}".format(r))
slope 0 =             -0.6907
slope 1 =             -0.6907
slope 2 =             -0.6932
slope 3 =             -0.6956
Prediction (theory) = -0.6931

R = -0.999999

Aitken加速法#

def aitken_iterations(φ, x0, N):
    x_list = np.zeros(N)
    x_list[0] = x0
    for j in range(1,N):
        x0_tmp = x_list[j-1]
        x1_tmp = φ(x0_tmp)
        x2_tmp = φ(x1_tmp)
        x_list[j] = x2_tmp - (x2_tmp-x1_tmp)**2/(x0_tmp + x2_tmp - 2*x1_tmp) 
    return x_list

例子1:对于\(\varphi(x) = x^2\),简单的迭代法无法成功收敛到\(x=1\),但是Aitken可以#

N = 8
φ = lambda x : x**2
plt.figure(figsize=(5,4))
plt.plot(aitken_iterations(φ, -1/2, N),'o--', label=r"$x_0=-0.5$")
plt.plot(aitken_iterations(φ, 1/2, N) ,'x--', label=r"$x_0=0.5$")
plt.plot(aitken_iterations(φ, 2, N),'v--', label=r"$x_0=2$")
plt.title(r"Aitken iteration method, $\varphi(x)=x^2$",fontsize=14)
plt.legend(fontsize=14)
plt.tight_layout()
plt.show()
_images/6c4f798063730dc0546b00e98fad5e43e91992921b5abe88a5f1fb07a8e8e52a.png

例子2:\(\varphi(x) = |x|^{1/2}\),Aitken收敛速度比较快#

φ = lambda x : np.abs(x)**(1/2)
x0 = 5
N = 6
direct_iter_soln = direct_iterations(φ, x0, N)
aitken_iter_soln = aitken_iterations(φ, x0, N)

plt.figure(figsize=(7,3))
plt.subplot(1,2,1)
plt.plot(direct_iter_soln, 'o-.', label='direct')
plt.plot(aitken_iter_soln, 'd-.', label='aitken')
plt.legend(fontsize=14)
plt.xlabel("N")
plt.title("Iteration solution",fontsize=14)

plt.subplot(1,2,2)
plt.plot(range(N),np.abs(direct_iter_soln-1), 'o-.', label='direct')
plt.plot(range(N), np.abs(aitken_iter_soln-1), 'd-.', label='aitken')
plt.yscale('log')
plt.legend(fontsize=14)
plt.xlabel("N")
plt.title("Iteration error",fontsize=14)
plt.tight_layout()
_images/f3171433f91892342b39bca622f0df1a74e61a2583ca407a1d2941852f7b5f38.png