数値積分
📂数値解析数値積分
定義
f:[a,b]→Rが[a,b]で積分可能であり、[a,b]をa=x0<⋯<xn=bのようなノードポイントで分割したとする。
- 積分オペレータIをI(f):=∫abf(x)dxのように定義する。
- 積分オペレータInをIn(f):=k=1∑n∫xk−1xkf(x)dxのように定義する。
- エラーEnをEn(f):=I(f)−In(f)のように定義する。
- n→∞limEn(f)E~n(f)=1を満たすE~nをEnのアシンプトティックエラーという。
説明
定積分を計算することは数値解析の目標の一つであることに誰もが異論はないだろう。実際、区分求積法のアイデアを思い起こせば、空間を可能な限り細かく分割すればするほど、積分値をよく近似できるだろうと予測できる。だから、数値解析で興味を持つ数値的積分とは、具体的にその誤差がどれくらいか、閉区間でない場合はどのように積分すべきかなどであろう。
例示
台形則
数値積分の例として、f∈C2[a,b]に対する台形則を見てみよう。台形則はI(f)に対してfを区間[a,b]でリニアインターポレーションしてその関数の積分値としてI(f)を近似する方法である。

I11(f):=(2b−a)[f(a)+f(b)]
この場合、実際のI(f)とI11(f)の誤差E11(f)はあるξ∈[a,b]に対して以下のように計算される。
ポリノミアルインターポレーション:
- [4] 実際の関数との誤差:(n+1)回微分可能なf:R→Rとあるξ∈H{x0,⋯,xn}に対して、fのポリノミアルインターポレーションpnはあるt∈Rに対してf(t)−pn(t)=(n+1)!(t−x0)⋯(t−xn)f(n+1)(ξ)を満たす。
E11(f):======I(f)−I11(f)∫ab[f(x)−b−af(b)(x−a)−f(a)(x−b)]dx∫ab[f(x)−p1(x)]dx21f′′(ξ)∫ab(x−a)(x−b)dx[21f′′(ξ)][−61(b−a)3]−121(b−a)3f′′(ξ)
合成台形則
今、[a,b]をn個の区間に分割し、各[xk−1,xk]で台形則で積分を近似すると考えよう。この方法を合成台形則という。
In1(f):=k=1∑n2h(f(xk−1)+f(xk))
では、実際のI(f)とIn1(f)の誤差はあるξk∈[xk−1,xk]に対して以下のように計算される。
En1(f)===I(f)−In1(f)k=1∑n(−12h3f′′(ξk))−12h3n(n1k=1∑nf′′(ξk))
ここで、(n1k=1∑nf′′(ξk))はf’’(ξk)の平均なので、中間値の定理により、あるξ∈[a,b]が存在してx∈[a,b]minf′′(x)≤f′′(ξ)≤x∈[a,b]maxf′′(x)を満たすべきである。したがって、
En1(f)=−12(b−a)h2f′′(ξ)
このように誤差を直接式で見ることで、積分区間[a,b]が広がるほど誤差が大きくなり、hが小さいほど正確になることがわかる。しかし、f’’(ξ)のために具体的にどれほど間違っているかはわからない。これを克服するために以下のようにアシンプトティックエラーを求める。
n→∞limh2En1(f)====n→∞limh21k=1∑n(−12h3f′′(ξk))−121n→∞limk=1∑nhf′′(ξk)−121∫abf′′(x)dx−121[f′(b)−f′(a)]
誤差En1(f)だけを知っていても定理によればf’’(ξ)が存在することはわかるが、具体的な数値をつけることはできなかった。しかし、今、
E~n1(f):=n→∞limEn1(f)
とした場合、十分に大きいnに対して
En1(f)≈−12h2[f′(b)−f′(a)]=E~n1(f)
であることがわかり、f′(a),f′(b)の計算は比較的簡単なので、比較的簡単かつ正確に誤差を把握することができる。しかも、ここまで来れば誤差がその程度であると終わる理由もない。計算をする前からこのように誤差が出ると予測できるならば、始めから誤差を補正することもできる。
I(f)−In1(f)≈E~n1(f)⟹I(f)≈In1(f)+E~n1(f)
修正台形則
I(f)を計算するオペレータとして以下のようにCTnを定義しよう。
CTn(f):=h[21f(x0)+f(x1)+⋯+f(xn−1)+21f(xn)]−12h2[f′(b)−f′(a)]
この方法を修正台形則と言う。[ 注記: 上で台形則が改良される過程を見ていれば、わざわざこれらを明確に区別する必要はない。単に台形則と言っても意味は通じる。 ]
実装
実際に∫0πexcos(x)dx=−2eπ+1≈−12.0703をIn1とCTnで計算してみた結果は以下の通り。

最初の列はnを示し、2番目の列はI(f)−In1(f)、3番目の列は∣I(f)−CT(f)∣を示している。合成台形則はノードを2倍に増やすたびに誤差が41倍に減少し、修正台形則は161倍に減少していることが確認できる。数値だけを見ても修正台形則がはるかに優れていることは明らかだが、特に速度が非常に速い点が良い。
以下はPythonで書かれた例示コードである。
import numpy as np
def f(x) :
return np.exp(x)*np.cos(x)
def d(f,x,tol=10**(-8)) :
h=1
d1=1
d2=0
while(abs(d1-d2)>tol) :
d1=d2
d2=(f(x+h)-f(x))/h
h=h/2
return(d2)
def I(f,a,b,n) :
h=(b-a)/n
x=np.linspace(a,b,n+1)
x=f(x)
x[0]=x[0]/2
x[-1]=x[-1]/2
return(h*sum(x))
def CT(f,a,b,n) :
h=(b-a)/n
x=np.linspace(a,b,n+1)
x=f(x)
x[0]=x[0]/2
x[-1]=x[-1]/2
return(h*sum(x)-(h**2)*(d(f,b)-d(f,a))/12)
TV=-(np.exp(np.pi)+1)/2
print("True Value : %2.4f" % TV)
print("| n | I(f) Err | CT(f) Err |")
print("="*30)
for n in range(1,10) :
print("| %3d | %8.2e | %8.2e |" % (2**n,abs(TV-I(f,0,np.pi,2**n)),abs(TV-CT(f,0,np.pi,2**n))))