import numpy as np
from math import exp
"""
リチャードソン補外法による数値微分を実装します。
このスクリプトは、指数関数exp(x)の微分をリチャードソン補外法を用いて数値的に計算し、
その結果を解析解と比較します。計算過程でステップサイズhを徐々に小さくし、
D行列を構築して精度の高い近似値を求めます。
指定された収束条件を満たすまで計算を継続します。
:doc:`diff_richardson_usage`
"""
# define function to be differentiated
[ドキュメント]
def func(x):
"""微分対象の関数f(x)を定義します。
この関数は、xの指数関数 `exp(x)` を返します。
:param x: 微分対象の関数の入力値です。
:returns: 入力xに対する `exp(x)` の値です。
"""
return exp(x)
# define analytical deviation of f(x)
[ドキュメント]
def dfdx(x):
"""微分対象の関数f(x)の解析的な導関数f'(x)を定義します。
この関数は、`exp(x)` の導関数である `exp(x)` を返します。
:param x: 微分対象の関数の入力値です。
:returns: 入力xに対する `exp(x)` の解析的な導関数の値です。
"""
return exp(x)
#===================
# parameters
#===================
h0 = 1.0
nhmax = 15
eps = 1.0e-6
x0 = 1.0
#===================
# main routine
#===================
print("Numerical differentiation using by Richardson extrapolation method")
fx = func(x0)
f1x = dfdx(x0)
print("")
print("eps for convergnece: {}".format(eps))
print("Analytical values:")
print(" f({})={}".format(x0, fx))
print(" df/dx({})={}".format(x0, f1x))
print("")
# create 2D array by specifing the size to be nhmax * nhmax
D = []
for i in range(nhmax):
D.append([])
for j in range(nhmax):
D[i].append([])
D[0][0] = (func(x0+h0) - func(x0-h0)) / 2.0 / h0
print("D{}{}: {}".format(0, 0, D[0][0]))
for m in range(1, nhmax+1):
h0 *= 0.5
D[0][m] = (func(x0+h0) - func(x0-h0)) / 2.0 / h0
print("D0{}: {}".format(m, D[0][m]))
for k in range(m-1, -1, -1):
m1 = m - k
D[m1][k] = (4.0**m1 * D[m1-1][k+1] - D[m1-1][k]) / (4.0**m1 - 1)
print("D{}{}: {}".format(m1, k, D[m1][k]))
diff = D[m][0] - D[m-1][0]
print(" diff = D[{}][0] - D[{}][0] = {} - {} = {}".format(m, m-1, D[m][0], D[m-1][0], diff))
if abs(diff) < eps:
break