logo

数値積分 📂数値解析

数値積分

定義 1

f:[a,b]Rf : [a,b] \to \mathbb{R}[a,b][a,b]で積分可能であり、[a,b][a,b]a=x0<<xn=ba = x_{0} < \cdots < x_{n} = bのようなノードポイントで分割したとする。

  1. 積分オペレータIII(f):=abf(x)dx\displaystyle I(f) := \int_{a}^{b} f(x) dxのように定義する。
  2. 積分オペレータInI_{n}In(f):=k=1nxk1xkf(x)dx\displaystyle I_{n} (f) := \sum_{k=1}^{n} \int_{x_{k-1}}^{x_{k}} f(x) dxのように定義する。
  3. エラーEnE_{n}En(f):=I(f)In(f)E_{n} (f) := I (f) - I_{n} ( f )のように定義する。
  4. limnE~n(f)En(f)=1\displaystyle \lim_{n \to \infty} {{\tilde{E}_{n} (f) } \over { E_{n} (f) }} = 1を満たすE~n\tilde{E}_{n}EnE_{n}アシンプトティックエラーという。

説明

定積分を計算することは数値解析の目標の一つであることに誰もが異論はないだろう。実際、区分求積法のアイデアを思い起こせば、空間を可能な限り細かく分割すればするほど、積分値をよく近似できるだろうと予測できる。だから、数値解析で興味を持つ数値的積分とは、具体的にその誤差がどれくらいか、閉区間でない場合はどのように積分すべきかなどであろう。

例示

台形則

数値積分の例として、fC2[a,b]f \in C^2 [a,b]に対する台形則を見てみよう。台形則I(f)I(f)に対してffを区間[a,b][a,b]リニアインターポレーションしてその関数の積分値としてI(f)I(f)を近似する方法である。

20190611\_151146.png

I11(f):=(ba2)[f(a)+f(b)] I_{1}^{1} (f) := \left( {{ b - a } \over { 2 }} \right) [ f(a) + f(b) ] この場合、実際のI(f)I(f)I11(f)I_{1}^{1} (f)の誤差E11(f)E_{1}^{1} (f)はあるξ[a,b]\xi \in [a,b]に対して以下のように計算される。

ポリノミアルインターポレーション:

  • [4] 実際の関数との誤差:(n+1)(n+1)回微分可能なf:RRf : \mathbb{R} \to \mathbb{R}とあるξH{x0,,xn}\xi \in \mathscr{H} \left\{ x_{0} , \cdots , x_{n} \right\}に対して、ffのポリノミアルインターポレーションpnp_{n}はあるtRt \in \mathbb{R}に対してf(t)pn(t)=(tx0)(txn)(n+1)!f(n+1)(ξ)\displaystyle f(t) - p_{n} (t) = {{ (t - x_{0}) \cdots (t - x_{n}) } \over { (n+1)! }} f^{(n+1)} ( \xi )を満たす。

E11(f):=I(f)I11(f)=ab[f(x)f(b)(xa)f(a)(xb)ba]dx=ab[f(x)p1(x)]dx=12f(ξ)ab(xa)(xb)dx=[12f(ξ)][16(ba)3]=112(ba)3f(ξ) \begin{align*} \displaystyle E_{1}^{1} (f) :=& I(f) - I_{1}^{1} (f) \\ =& \int_{a}^{b} \left[ f(x) - {{ f(b) ( x - a ) - f(a) (x - b) } \over { b - a }} \right] dx \\ =& \int_{a}^{b} \left[ f(x) - p_{1} (x) \right] dx \\ =& {{1} \over {2}} f '' ( \xi ) \int_{a}^{b} (x-a) (x-b) dx \\ =& \left[ {{1} \over {2}} f '' ( \xi ) \right] \left[ - {{1} \over {6}} (b-a)^{3} \right] \\ =& - {{1} \over {12}} (b-a)^{3} f '' ( \xi ) \end{align*}

合成台形則

今、[a,b][a,b]nn個の区間に分割し、各[xk1,xk][x_{k-1} , x_{k} ]で台形則で積分を近似すると考えよう。この方法を合成台形則という。 In1(f):=k=1nh2(f(xk1)+f(xk)) I_{n}^{1} (f) := \sum_{k=1}^{n} {{ h } \over { 2 }} \left( f (x_{k-1}) + f( x_{k} ) \right) では、実際のI(f)I(f)In1(f)I_{n}^{1} (f)の誤差はあるξk[xk1,xk]\xi_{k} \in [x_{k-1}, x_{k} ]に対して以下のように計算される。 En1(f)=I(f)In1(f)=k=1n(h312f(ξk))=h3n12(1nk=1nf(ξk)) \begin{align*} \displaystyle E_{n}^{1} (f) =& I (f) - I_{n}^{1} (f) \\ =& \sum_{k=1}^{n} \left( - {{ h^3 } \over { 12 }} f '' ( \xi_{k} ) \right) \\ =& - {{ h^3 n } \over { 12 }} \left( {{ 1 } \over { n }} \sum_{k=1}^{n} f '' ( \xi_{k} ) \right) \end{align*} ここで、(1nk=1nf(ξk))\displaystyle \left( {{ 1 } \over { n }} \sum_{k=1}^{n} f '' ( \xi_{k} ) \right)f’’(ξk)f’’ ( \xi_{k} )の平均なので、中間値の定理により、あるξ[a,b]\xi \in [a,b]が存在してminx[a,b]f(x)f(ξ)maxx[a,b]f(x)\displaystyle \min_{x \in [a,b]} f ''(x) \le f ''( \xi ) \le \max_{x \in [a,b]} f ''(x)を満たすべきである。したがって、 En1(f)=(ba)h212f(ξ) E_{n}^{1} (f) = - {{ (b-a) h^2 } \over {12}} f '' (\xi ) このように誤差を直接式で見ることで、積分区間[a,b][a,b]が広がるほど誤差が大きくなり、hhが小さいほど正確になることがわかる。しかし、f’’(ξ)f’’ ( \xi ) のために具体的にどれほど間違っているかはわからない。これを克服するために以下のようにアシンプトティックエラーを求める。 limnEn1(f)h2=limn1h2k=1n(h312f(ξk))=112limnk=1nhf(ξk)=112abf(x)dx=112[f(b)f(a)] \begin{align*} \lim_{n \to \infty} {{ E_{n}^{1} (f) } \over { h^2 }} =& \lim_{n \to \infty} {{1} \over {h^2}} \sum_{k=1}^{n} \left( - {{ h^3 } \over { 12 }} f '' ( \xi_{k} ) \right) \\ =& - {{ 1 } \over { 12 }} \lim_{ n \to \infty} \sum_{k=1}^{n} h f '' ( \xi_{k} ) \\ =& - {{ 1 } \over { 12 }} \int_{a}^{b} f ''(x) dx \\ =& - {{ 1 } \over { 12 }} [ f '(b) - f '(a) ] \end{align*} 誤差En1(f)E_{n}^{1} (f)だけを知っていても定理によればf’’(ξ)f’’ ( \xi )が存在することはわかるが、具体的な数値をつけることはできなかった。しかし、今、 E~n1(f):=limnEn1(f) \tilde{E}_{n}^{1} (f) := \lim_{n \to \infty} E_{n}^{1} (f) とした場合、十分に大きいnnに対して En1(f)h212[f(b)f(a)]=E~n1(f) E_{n}^{1} (f) \approx - {{ h^2 } \over { 12 }} [ f '(b) - f '(a) ] = \tilde{E}_{n}^{1} (f) であることがわかり、f(a),f(b)f ' (a) , f '(b)の計算は比較的簡単なので、比較的簡単かつ正確に誤差を把握することができる。しかも、ここまで来れば誤差がその程度であると終わる理由もない。計算をする前からこのように誤差が出ると予測できるならば、始めから誤差を補正することもできる。 I(f)In1(f)E~n1(f)    I(f)In1(f)+E~n1(f) I(f) - I_{n}^{1} (f) \approx \tilde{E}_{n}^{1} (f) \implies I(f) \approx I_{n}^{1} (f) + \tilde{E}_{n}^{1} (f)

修正台形則

I(f)I(f)を計算するオペレータとして以下のようにCTnCT_{n}を定義しよう。 CTn(f):=h[12f(x0)+f(x1)++f(xn1)+12f(xn)]h212[f(b)f(a)] CT_{n} (f) := h \left[ {{1} \over {2}} f (x_{0} ) + f (x_{1} ) + \cdots + f (x_{n-1} ) + {{1} \over {2}} f (x_{n} ) \right] - {{ h^2 } \over { 12 }} [ f '(b) - f '(a) ]

この方法を修正台形則と言う。[ 注記: 上で台形則が改良される過程を見ていれば、わざわざこれらを明確に区別する必要はない。単に台形則と言っても意味は通じる。 ]

実装

実際に0πexcos(x)dx=eπ+1212.0703\displaystyle \int_{0}^{\pi} e^{x} \cos (x) dx = -{{e^{\pi} + 1} \over {2}} \approx - 12.0703In1I_{n}^{1}CTnCT_{n}で計算してみた結果は以下の通り。

20190611\_125046.png

最初の列はnnを示し、2番目の列はI(f)In1(f)\left| I(f) - I_{n}^{1} (f) \right|、3番目の列はI(f)CT(f)\left| I(f) - CT (f) \right|を示している。合成台形則はノードを2倍に増やすたびに誤差が14\displaystyle {{1} \over {4}}倍に減少し、修正台形則は116\displaystyle {{1} \over {16}}倍に減少していることが確認できる。数値だけを見ても修正台形則がはるかに優れていることは明らかだが、特に速度が非常に速い点が良い。

以下は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))))

  1. アトキンソン. (1989). 数値解析入門(第2版): p249. ↩︎