123456789

「数理物理」講義ノート

第四章:数値微分と数値積分

コンピューターで微分をしよう

微分の概念そのものは、数学者が考案されたかのように思われがちだが、かの物理学者ニュートンによって考え出されたものである。速度の考え方は、単位時間当たりに進んだ距離であるが、この時単位時間というのを限りなく微小な時間Δtにもっていくことに微分の本質がある。速度をVとするとこれは、刻々変化していくから時間tの関数V(t)と考えることができる。速度は微分を使って、X(t)を距離として、

[Graphics:Images/index_gr_1.gif]

と表せる。「Δtを限りなく0に近づける」という操作は、いかにも数学的である。これを、元々の物理的な考え方に戻せば、どうなるか。

[Graphics:Images/index_gr_2.gif]

のようになり、近似的に求まることになる。「十分ちいさな値」は、人間が用意するには大変であるが、コンピューターならできる。では、どのくらい小さな値でも良いのか?一章でも述べたように、コンピューターも有限の賜物であることを忘れてはならない。それは、一般にXの関数の性質による。実際に色々な初等関数をXに見立てて、「微分」してみよう。以下のプログラムでは、例として [Graphics:Images/index_gr_3.gif](t)=[Graphics:Images/index_gr_4.gif], [Graphics:Images/index_gr_5.gif](t)=[Graphics:Images/index_gr_6.gif], [Graphics:Images/index_gr_7.gif](t)=sin(t) についてt=1で計算を行った。

[Graphics:Images/index_gr_8.gif]

これを実行すれば、以下のようになる。

dt=0.100000 15.937431 10.000000 2.858844 2.718282 0.497364 0.540302
dt=0.010000 10.462201 10.000000 2.731919 2.718282 0.536090 0.540302
dt=0.001000 10.045647 10.000000 2.719879 2.718282 0.539958 0.540302
dt=0.000100 10.006428 10.000000 2.720356 2.718282 0.540614 0.540302
dt=0.000010 10.013581 10.000000 2.741814 2.718282 0.542402 0.540302
dt=0.000001 9.536743 10.000000 2.622604 2.718282 0.536442 0.540302
dt=0.000000 11.920929 10.000000 4.768372 2.718282 1.192093 0.540302
dt=0.000000 0.000000 10.000000 0.000000 2.718282 0.000000 0.540302
dt=0.000000 0.000000 10.000000 0.000000 2.718282 0.000000 0.540302
dt=0.000000 0.000000 10.000000 0.000000 2.718282 0.000000 0.540302

数字は、[Graphics:Images/index_gr_9.gif]と並んでいる。このように、単精度の計算では、「うまく」Δtを選ばないと良い結果が得られない。

次に、それでは倍精度で計算すればどうか?プログラム中の「float」の部分を全て「double」と書き直して実行すればよい。その結果は、期待していたように、

dt=0.100000 15.937425 10.000000 2.858842 2.718282 0.497364 0.540302
dt=0.010000 10.462213 10.000000 2.731919 2.718282 0.536086 0.540302
dt=0.001000 10.045120 10.000000 2.719641 2.718282 0.539881 0.540302
dt=0.000100 10.004501 10.000000 2.718418 2.718282 0.540260 0.540302
dt=0.000010 10.000450 10.000000 2.718295 2.718282 0.540298 0.540302
dt=0.000001 10.000045 10.000000 2.718283 2.718282 0.540302 0.540302
dt=0.000000 10.000005 10.000000 2.718282 2.718282 0.540302 0.540302
dt=0.000000 10.000000 10.000000 2.718282 2.718282 0.540302 0.540302
dt=0.000000 10.000001 10.000000 2.718282 2.718282 0.540302 0.540302
dt=0.000000 10.000001 10.000000 2.718283 2.718282 0.540302 0.540302

良い結果を得る。しかし、Δtをいくらでも小さく取れるとは限らないことを忘れないように。答えが正しいかどうかを知る簡単なチェックは、Δtを少し変化さてみると分かる。

コンピューターで積分をしよう

積分は微分の逆の演算であることを考え、上で行ったことをもとに、式を立てていこう。

[Graphics:Images/index_gr_10.gif]

これを式変形して、

[Graphics:Images/index_gr_11.gif]

と書ける。これは、漸化式になっている。一般化すれば、

[Graphics:Images/index_gr_12.gif]

となり、任意のtについて求まる。このような方法を線形近似法または、オイラー法という。精度はΔtを小さくすれば良いが、和を多く行わなくてはならなくなる。X(T)をもとめたいとすれば、

[Graphics:Images/index_gr_13.gif]

n回行う必要がある。(CPU-TIMEがかかる)V(t)=[Graphics:Images/index_gr_14.gif], V(t)=[Graphics:Images/index_gr_15.gif]およびV(t)=sin(t)の場合、X(1)=1の初期値から、X(2)を計算した。C言語での、プログラムは以下のようになる。

[Graphics:Images/index_gr_16.gif]

結果は、以下のようになる。

dt=0.100000 140.186573 187.090909 5.441127 5.670774 1.952261 1.956449
dt=0.010000 182.018491 187.090909 5.647459 5.670774 1.956102 1.956449
dt=0.001000 186.579835 187.090909 5.668439 5.670774 1.956415 1.956449
dt=0.000100 187.039763 187.090909 5.670541 5.670774 1.956446 1.956449
dt=0.000010 187.085794 187.090909 5.670751 5.670774 1.956449 1.956449
dt=0.000001 187.090398 187.090909 5.670772 5.670774 1.956449 1.956449
dt=0.000000 187.090858 187.090909 5.670774 5.670774 1.956449 1.956449
dt=0.000000 187.090904 187.090909 5.670774 5.670774 1.956449 1.956449
dt=0.000000 187.090909 187.090909 5.670774 5.670774 1.956449 1.956449

このように関数系によって、Δtの大きさがまちまちである。微分の時と同じく収束しているかのチェックが大切である。
9行目のばあいΔt=0.000000001であるから、和の計算のループは、10億回行ってることになる。積分和をほんの20回ぐらいで同じ精度の計算をすることができる方法がある。その方法の一つにガウス・ルジャンドル積分法がある。(後述)

この他、等間隔に関数を求め、積分する方法に台形公式シンプソンの公式がある。

[Graphics:Images/index_gr_17.gif]

「科学技術は、補間だ!」

関数をモデルに考えてみよう。初等関数([Graphics:Images/index_gr_18.gif]、sin(x) ,exp, log など)で表せる関数ならば、xのとりえる範囲で、自由に計算できる。しかし、現実の問題は、大抵、データと呼ばれる離散型の数値で与えられている。
例えば、{x、f(x)}のデータを以下のように与えて、プロットさせると、[mathematica]

[Graphics:Images/index_gr_19.gif]

[Graphics:Images/index_gr_20.gif]

このように描ける。「補間」とは、この場合、データに載っていない値を予想することである。それには、2種類の補間がある。
•変数の区間内の補間 ⇒ 内挿補間  (interpolation)
•変数の区間外の補間 ⇒ 外挿補間  (extrapolation)
例の場合、区間とは1<x<10である。これを、私は「知られている世界(既知領域)」、また、区間外(x<1とx>10)は「知らない世界(未知領域)」と考えたい。 そのように考えると、内挿補間をより詳しく予想していくことは、「技術」で、外挿していく作業は、「科学」をすることに類似性を感じとれる。パラダイム1 パラダイム2

例の場合を考えると、x=3.5のf(x)の内挿は、f(3)とf(4)が知られているから、それは丁度真中の値であることから、f(3.5)~[Graphics:Images/index_gr_21.gif](f(3)+f(4))=[Graphics:Images/index_gr_22.gif]と「予想」する。しかし、x=12の値は、簡単には予想できない。

皆さんは、既に想像できたと思いますが、これはf(x)=[Graphics:Images/index_gr_23.gif]が考えられる。これは「仮説」で、これが正しければ、x=12は当然、f(12)=144と求まる。また、f(3.5)=[Graphics:Images/index_gr_24.gif]と計算ができる。では、上の[Graphics:Images/index_gr_25.gif]は、全くの間違いだったのかというと、そうではない。「誤差」を計算すると、

[Graphics:Images/index_gr_26.gif]

2.04%になり、そんなに悪くない。なぜ悪かったのかというと、たった2つのデータ(f(3)とf(4))しか使わなかったからである。多くのデータ点を使って、精度の良い内挿を行う方法が知られている。そのなかには、スプライン内挿法、ラグランジュ内挿法が代表的である。ラグランジュ内挿法について考えていこう。

ラグランジュ内挿法

この補間法は、関数を多項式で表すことを仮定する。これは自然な仮定で、一般に正則な関数は、テーラー展開できるからである。

[Graphics:Images/index_gr_27.gif]

つまり、データの点{[Graphics:Images/index_gr_28.gif]}(i=1,...,N)で、f(x)がデータの値{[Graphics:Images/index_gr_29.gif]}を満たす、

[Graphics:Images/index_gr_30.gif]

を要請すれば、係数[Graphics:Images/index_gr_31.gif]のかずは、N個で、M=N-1となる。(未知数の数と式の数)ここで、係数[Graphics:Images/index_gr_32.gif]を求めることを考えずに、或る多項式[Graphics:Images/index_gr_33.gif]を用いて、

[Graphics:Images/index_gr_34.gif]

を仮定すれば、f([Graphics:Images/index_gr_35.gif]を満たすためには、

[Graphics:Images/index_gr_36.gif]

であれば良い。(但し、[Graphics:Images/index_gr_37.gif]=1(i=jの場合)、[Graphics:Images/index_gr_38.gif]=0(その他の場合) )これを満たすN-1次の多項式は、ユニークに与えられる。

[Graphics:Images/index_gr_39.gif]

N-1次式になるのは、分子[Graphics:Images/index_gr_40.gif]がないことに注意。これを、ラグランジュの積関数と呼ぶ。

ガウス・ルジャンドル積分法

定積分の計算をしよう。変数変換すれば、任意の積分区間を -1<t<1とすることができる。( x⇒ [Graphics:Images/index_gr_41.gif]

[Graphics:Images/index_gr_42.gif]

上のラグランジュの補間の考え方から、関数f(x)を、ラグランジュの積関数とで、

[Graphics:Images/index_gr_43.gif]

と書けるので、積分 I は、

[Graphics:Images/index_gr_44.gif]

と書き換わる。ここでは[Graphics:Images/index_gr_45.gif]を積分の「重み」という。この重みは、積分点が既知ならば、予め求めておくことができる。

シンプソンの公式の証明:

連続する3点を2次関数で近似して、その解析的な積分値を積み重ね加えていく方法。
3点を(−1,[Graphics:Images/index_gr_46.gif])(0,[Graphics:Images/index_gr_47.gif]),(1,[Graphics:Images/index_gr_48.gif])とすれば、それぞれの点での、[Graphics:Images/index_gr_49.gif][Graphics:Images/index_gr_50.gif]がもとまる。

[Graphics:Images/index_gr_51.gif]

問い)4点を選び、3次関数で近似する場合はどうか?

次に、積分を行う前に、積分点{[Graphics:Images/index_gr_52.gif]}を決めることができる場合を考える。今、N次の関数[Graphics:Images/index_gr_53.gif]を仮定すると、

[Graphics:Images/index_gr_54.gif]

ラグランジュ積関数は、

[Graphics:Images/index_gr_55.gif]

と書ける。ここで、[Graphics:Images/index_gr_56.gif]ルジャンドル関数という特殊関数に選び、積分点{[Graphics:Images/index_gr_57.gif]}をそのゼロ点([Graphics:Images/index_gr_58.gif]=0)に選ぶと、重みは解析的に求まる。(厳密には、ルジャンドル関数を[Graphics:Images/index_gr_59.gif]とおくには定数倍違うが、ラグランジュ積関数は変わらない。)

[Graphics:Images/index_gr_60.gif]

問題:ガウス・ルジャンドル積分のプログラム

ルジャンドル関数のゼロ点と重みは、N=2,4,6について、次の様に与えられている。
n  [Graphics:Images/index_gr_61.gif]                          [Graphics:Images/index_gr_62.gif]
2    +-  0.57735027      1.00000000  
4    +-  0.86113631      0.34785458
      +-  0.33998104      0.65214515
6    +-  0.93246951      0.17132449
      +-  0.66120939      0.36076157
      +-  0.23861919      0.46791393      

これらを用いて、オイラー法で行なった、V(t)=[Graphics:Images/index_gr_63.gif], V(t)=[Graphics:Images/index_gr_64.gif]およびV(t)=sin(t)について

[Graphics:Images/index_gr_65.gif]

の計算を求めよ。

第五章へ       第三章へ

                                                    H.Kamada


Converted by Mathematica      March 15, 2002