+ All Categories
Home > Documents > Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs )...

Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs )...

Date post: 26-May-2020
Category:
Upload: others
View: 0 times
Download: 0 times
Share this document with a friend
48
数値計算入門 http://kurasawa.c.ooco.jp 目次 0 GCC の使い方など 1 1 超越方程式:ニュートン法 3 2 直交多項式:エルミート, ルジャンドル多項式 7 3 数値積分:台形則とシンプソン則 9 4 連立一次方程式:ガウスの消去法 11 5 常微分方程式:ルンゲ・クッタ型公式 14 6 行列の固有値問題 : ヤコビ法 18 7 シュレディンガー方程式の数値解法 22 7.1 微分方程式を解く ....................................... 22 7.2 行列の対角化 .......................................... 26 8 モンテカルロ法 28 付録 A 数値計算の結果を図で表わす:T E X tpic special 34 付録 B 数値計算の結果を図で表わす:PostScript 40 付録 C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。 meadow ( emacs, mule ) の使い方は付録 C を参考 c 倉澤 治樹 参考書 柴田望洋 , 新版 明解 C 言語 入門編 ( ソフトバンク ) 浦 昭二 , 原田 賢一:C 入門 ( 培風館 ) 川上 一郎:理工系の数学入門コース8 数値計算 ( 岩波書店 ) 戸川 隼人:UNIX ワークステーションによる科学技術計算ハンドブック[基礎篇 C 言語版]( イエンス社 ) NUMERICAL RECIPES in C [日本語版]( 技術評論社 )
Transcript
Page 1: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

数値計算入門 http://kurasawa.c.ooco.jp

目 次0 GCCの使い方など 1

1 超越方程式:ニュートン法 3

2 直交多項式:エルミート, ルジャンドル多項式 7

3 数値積分:台形則とシンプソン則 9

4 連立一次方程式:ガウスの消去法 11

5 常微分方程式:ルンゲ・クッタ型公式 14

6 行列の固有値問題 : ヤコビ法 18

7 シュレディンガー方程式の数値解法 22

7.1 微分方程式を解く . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

7.2 行列の対角化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

8 モンテカルロ法 28

付録 A 数値計算の結果を図で表わす:TEXの tpic special 34

付録 B 数値計算の結果を図で表わす:PostScript 40

付録 C Mule( Emacs )のコマンド一覧 45

~ はサンプルプログラムにバグがあることを示す。meadow ( emacs, mule )の使い方は付録Cを参考

c⃝ 倉澤 治樹参考書• 柴田望洋 , 新版 明解 C言語 入門編 ( ソフトバンク )

• 浦 昭二 , 原田 賢一:C入門 ( 培風館 )

• 川上 一郎:理工系の数学入門コース8 数値計算 ( 岩波書店 )

• 戸川 隼人:UNIXワークステーションによる科学技術計算ハンドブック[基礎篇 C言語版]( サイエンス社 )

• NUMERICAL RECIPES in C [日本語版] ( 技術評論社 )

Page 2: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

0 GCCの使い方など 1

0 GCCの使い方などGCCの使い方test.c というファイルをコンパイルするには

gcc -o test test.c

と入力する。UNIXの場合にはオプション -lm が必要かもしれない。正常にコンパイルが終了したら,

cygwin版の GCC の場合には実行ファイル test.exe, Unixの場合は test が生成される。GCC は実行するときに多くのオプションがある。よく使うオプションを挙げておく。

-v コンパイルの途中経過を表示する。-c リンクしないで xxxx.o を作る。-o xxx 最終出力ファイルを xxx にする。cygwin版の GCC では xxx.exe を生成する。-g デバッグ情報を含める。-lxxx ライブラリ libxxx.a をリンクする。例えば -lm は libm.a をリンクする。libm.a は

数学関数のライブラリである。-s 実行ファイルからシンボルテーブルと再配置情報を全て削除する。実行ファイルは小

さくなる。-Wall 全ての警告メッセージ (あるいはエラー)を出す。

他に実行速度に関連するオプションとして

-On O はオーでありゼロではない。n は 0 ∼ 3。最適化のレベルを指定。数字が大きいほどレベルが高く, 生成した実行ファイルの実行速度は高速になる。

-ffast-math 実行速度最適のため ANSI や IEEE の規則や仕様を破ることを GCC に許す。例えば、sqrt関数の引数が負にならないと仮定する。

-malign-double double, long double, long long の計算が Pentium で若干速くなる-funroll-loops ループを展開する-fno-math-errno errno をセットしない(多少速くなる)

高速で実行サイズの小さな実行ファイルを作るには

gcc -s -O3 -ffast-math -o test test.c

とすればよい。cygwin版の場合 -mno-cygwin を付けると更に高速化する。Windows の場合, 次の 1行

gcc -s -O3 -ffast-math -mno-cygwin -o %1 %1.c

からなる拡張子が bat であるテキストファイル, 例えば cc.bat を作成すればcc test

と入力するとgcc -s -O3 -ffast-math -mno-cygwin -o test test.c

が実行され test.exe が生成される。入力の手間が軽減する。

コマンド行の引数をプログラムに渡すC言語では main関数で

main( int argc, char *argv[] )

とすると argc にプログラムを呼び出したコマンド行の引数の個数, argv に引数の文字列を指すポイ

Page 3: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

0 GCCの使い方など 2

ンタが入る ( argc, argv は argment count, argment vector の意味で慣例的に使われるが, 別の変数名でもよい )。例えば, test.exe というプログラムを test abc 12 xyz で起動すると argc は 4 で

argv[0]="test" argv[1]="abc" argv[2]="12" argv[3]="xyz"

になる。規約により argv[0] は起動したプログラム名であり, 実際の引数は argv[1] から始まる。下記のプログラムを引数を付けて実行してみよ。� �#include <stdio.h>

int main( int argc, char *argv[] ){

int i;for(i=0; i<=argc-1; i++ )

printf("argv[%d]=%sY=n",i,argv[i] );return 0;

}� �プログラムに数値を渡したい場合, 引数に例えば 12 を与えても, プログラムに渡されるのは文字列であるため, 文字列を数値に変換する必要がある。このための関数が C言語では用意されている。  文字列→整数 int atoi( char *s )

  文字列→実数 double atof( char *s )

argv[1]="12" のとき n=atoi(argv[1]) とすると n は整数値 12 になる。これらの関数を使うときはヘッダ stdlib.h を include する。

プログラム中で別のプログラムを実行する数値結果を TEX ファイルに出力した場合, プログラム終了後コマンド行で例えば platex test と入力して TEXファイルをコンパイルする必要がある。プログラム作成中には, これを何度も実行することになり結構面倒くさい。そこで, system関数 int system( char *s ) を使ってこの手間を省こう。system関数を使う場合にもヘッダ stdlib.h を include する。実行したいコマンドを文字列 s

に渡すだけである。使い方は, 例えば#include <stdio.h>#include <stdlib.h>.....int main(){

.....fptpic=fopen("test.tex","w");.....fclose(fptpic);system("platex test");.....

である。このプログラムを実行すれば, 自動的に platex test も実行される。

Page 4: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

1 超越方程式:ニュートン法 3

1 超越方程式:ニュートン法方程式 f(x) = 0 を解くためには, 漸化式

x0 = a, xn+1 = xn −f(xn)

f ′(xn)(1.1)

を適当な初期値 a に対して解いて, 数列 {xn} を構成する。初期値 a がうまく与えられれば, この数列は上述の方程式の1つの解 α に収束する。この方法をニュートン法あるいはニュートン・ラフソン法という。漸化式 (1.1) の意味とその収束の様子は, 次の図と式を見れば一目瞭然である。点 (x0, f(x0))

を通る接線の方程式はy − f(x0) = f ′(x0)(x− x0)

である。この接線と x軸との交点の x座標を x1 とすると

x1 = x0 −f(x0)

f ′(x0)(1.2)

これを繰り返せば上記の漸化式 (1.1)が得られる。x0 x1 x2 x3x1 を x0 に代入して再び (1.2) を使うと, 得られ

た x1 は実は x2 である。これから分かるように, プログラムする場合 x0, x1, · · · , xn のすべての変数を記憶する必要はなく, 2つの変数を用意すれば十分である。収束の判定は相対誤差 |(xn − xn−1)/xn| < ε で

判断する。10進で m桁の精度が欲しいときは ε =

10−m である。ところで, |xn| が非常に小さいときには, 左辺が桁溢れを起こすため判定できない。この場合には絶対誤差 |xn − xn−1| < εA で判定する。εA としては 0 以外で扱える絶対値最小の値を使う。εA = 10−70 としておけばよい。以上から |xn −xn−1| < ε|xn|+ εA を収束の条件とする。多くの場合, n ∼ 10 で eps= 10−8 程度の精度が得られるが,

解が求まらない場合も考慮して, n がある値 (例えば 20 )以上になったらプログラムを強制終了する。

問 1.1 sinx−x/2 = 0 の解を求めるサンプルプログラムを次に示す。プログラムソースの各行を理解した上で実行させてみよ。下図に y = sinx− x/2 を図示する。初期値 x0 に依存してどの解に収束するか, 予想してみよ。また, tanx − 1/x = 0 の解を求める様にサンプルプログラムを変更せよ。この場合, 解は無限個ある。

−3 −2 −1 0 1 2 3

−1.0

−0.5

0.5

1.0

Page 5: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

1 超越方程式:ニュートン法 4

~ � �#include <stdio.h>#include <math.h>#define EPSA 1.e-70double f( double x );double df( double x );int main(){

double x0, x1, eps;int n, nmax;eps=1.e-8;nmax=20;printf("初期値 x0 = ");scanf("%lf",&x0); /* l は一ではなくエル */for( n=1; n<=nmax; n++ ){

x1 = x0 - f(x0)/df(x0);if( fabs(x1-x0) < EPSA + eps*fabs(x1) ){

printf("---------------------------------------Y=n");printf("%2d %15.8e %15.8eY=n", n, x1, f(x1) );return 0;

}x0=x1;printf("%2d %15.8e %15.8eY=n", n, x1, f(x1) ); /* 途中経過を表示 */

}printf("解が見つかりません !!Y=n");return 0;

}

double f( double y ){

return sin(y)-y/2;}

double df( double y ){

return cos(y)-1/2;}� �

問 1.2 上のサンプルプログラムでは, ニュートン法は main関数に埋め込まれている。この部分を独立した関数にすると次のようになる。このようにすると, 解を求めたい関数 F (x), F ′(x) を用意すれば, ニュートン法の部分を修正せずに, 様々な方程式の解をえることができる。1つのプログラムで sinx− x/2 = 0 と tanx− 1/x = 0 の解を求めよ。double (*func)( double x ) は func が「1つの double型引数をもち doubleの値を返す関数」へのポインタであることを表す。double *func( double x ) は func が double型変数のポインタを返す関数ということになり意味は全く違う。最初は理解しずらい点であるが, こんなものと思って使いましょう。~ � �#include <stdio.h>#include <math.h>#define EPSA 1.e-70double f( double y );double df( double y );double newton( double (*func)( double x ), double (*dfunc)( double x ),

double x0, double dx );� �

Page 6: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

1 超越方程式:ニュートン法 5

� �int main(){

double y0, y1, eps;eps=1.e-8;printf("Y=n初期値 ==> ");scanf("%lf",&y0);y1 = newton( f, df, y0, eps );printf("%15.8e %15.8eY=n",y1, f(y1) );return 0;

}

double f( double x ){

return sin(x)-x/2;}

double df( double x ){

return cos(x)-1/2;}

double newton( double (*func)( double x ), double (*dfunc)( double x ),double x0, double dx )

{int n;double x1;n=0;while( n++ < 20 ){

x1 = x0 - func(x0)/dfunc(x0);if( fabs(x1-x0)<EPSA+dx*fabs(x1) )

return x1;x0=x1;

}printf("解が見つかりません !!Y=n");return x1;

}� �問 1.3 (1.1)で微分 f ′(x) を差分

f ′(xn) ≈f(xn)− f(xn−1)

xn − xn−1

で近似してxn+1 = xn − f(xn)

xn − xn−1

f(xn)− f(xn−1)

という漸化式で解を求める方法をセカント法という。セカント法は f ′(x) を定義しなくてよいのが利点であるが, 初期値として x0, x1 の 2点を与える必要がある。与えられた 2点 x0, x1 から上の式により x2 を求め, 次に x1, x2 から x3 を求める, これを収束するまで続ける。サンプルプログラムをセカント法に変更して解を求めよ。

問 1.4 [量子力学 ] ポテンシャルが井戸型 V (x)

V (x) =

{− V0 , |x| < R

0 , |x| > R, V0 > 0

Page 7: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

1 超越方程式:ニュートン法 6

の場合, エネルギー固有値 E ( この場合 −V0 < E < 0 )は

ψ(x) が偶関数のとき f(k) = k2 − v20 cos2 k = 0 , tan k > 0

ψ(x) が奇関数のとき g(k) = k2 − v20 sin2 k = 0 , tan k < 0(1.3)

の解で与えられる [ 量子力学 Aの講義ノート ]。ただし

k =

√2m(V0 + E)

ℏ2R , v0 =

√2mV0ℏ2

R

π

0

−10

−20

ε

v0

v0 を与えたときニュートン法により (1.3)を解き固有値 ε = 2mR2E/ℏ2 = k2 − v20 を求めよ。解は 1 つとは限らない。f(k) = 0 の解は直線k/v0 と曲線 | cos k | の交点で与えられるから

(n− 1)π < v0 ≤ nπ , n = 1, 2, · · ·

のとき n個の解が存在する。g(k) = 0 についても同様である。v0 →∞ の場合, (1.3)の k は解析的に求まる。これと数値結果を比較せよ。

(1.3)の f(k) と g(k) は k だけでなく v0 にも依存するから関数 newton をこれに合わせて修正してもよいが, ここでは次のようにして無修正で済むようにする。

.....double v0;int main(){

.....v0 = ... ;.....newton( f, df, x0, eps );.....

}

double f( double x ){

return x*x-v0*v0*cos(x)*cos(x);

}

関数内 ( mainも一種の関数 )で宣言した変数は, その関数内だけで有効で, 他の関数からは直接扱えない。このような変数を局所変数または自動変数という。一方, 関数の前 (上)で, 通常 main の前で, 変数を宣言することもできる。これを外部変数という。外部変数は全ての関数で共通に扱える変数である。上の例では, v0 を表す変数 v0 を外部変数として宣言し, v0 に依存する関数 f と df が newton で使用される前に v0 の値を与える。これにより f と df 内の v0 も与えた値になる。なお, 不必要に外部変数にすると, 関数ごとに本来は独立であるべき変数が共通になったりして, 思わぬ副作用をもたらす。また, 外部変数の変数名を簡単な変数名にすると, 局所変数と共通になることがあるから, 何を表しているか分かるような名前にするとよい。

Page 8: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

2 直交多項式:エルミート, ルジャンドル多項式 7

2 直交多項式:エルミート, ルジャンドル多項式エルミート (Hermite)多項式 Hn(x) , ルジャンドル (Legendre)多項式 Pn(x) は漸化式

H0(x) = 1 , H1(x) = 2x , Hn(x)− 2xHn−1(x) + 2(n− 1)Hn−2(x) = 0 ,

P0(x) = 1 , P1(x) = x , nPn(x)− (2n− 1)xPn−1(x) + (n− 1)Pn−2(x) = 0

を満たす。これらの漸化式を用いて Hn(x) , Pn(x) を求める関数double hermite( int n, double x ) double legendre( int n, double x )

を作成する。hermite( int n, double x ) のサンプルを次に示す。

~ � �double hermite( int n, double x ){

int k;double y0, y1, y2;

y0=1.;if( n==0 )

return y0;y1=2.*x;for( k = 2; k<=n; k++ ){

y2 = 2.*( x*y1 - (k-1)*y0 );y1 = y2;y0 = y1;

}return y1;

}� �問 2.1 x = 0.05k ( k = 0, 1, 2, · · · , 20 )に対して, 下記の具体例と数値が一致することを確かめよ。

H5(x) = 32x5 − 160x3 + 120x , P5(x) =1

8

(63x5 − 70x3 + 15x

)問 2.2 Pn(x) は −1 < x < 1 に n個の零点をもつ。0 < x < 1 における零点を次の方法ですべて求め

る。0 ≤ x ≤ 1 を kmax 個に分割する。xk = k/kmax , ( k = 0, 1, 2, · · · , kmax ) とするとき

Pn(xk)Pn(xk+1) < 0 , k = 0, 1, 2, · · · , kmax − 1

ならば xk < x < xk+1 に零点が存在する。初期値を (xk + xk+1)/2 としてニュートン法で零点を求める。求まった解が [n ]/2個より少ないなら kmax を大きくする。導関数 P ′

n(x) はP14(x)

−0.4

−0.2

0.0

0.2

0.5 1.0

P ′n(x) = n

Pn−1(x)− xPn(x)

1− x2

である。Pn(x) を図示し, 求めた解が Pn(x) = 0

を満たすことをグラフ上で確かめよ。1章で作成したニュートン法のプログラム newton を無修正で使用するためには, 問 1.4 と同様にして, Pn(x)

の n を次のように外部変数として宣言すればよい。

Page 9: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

2 直交多項式:エルミート, ルジャンドル多項式 8

� �.....int nl;int main(){

.....nl = 5;.....newton( f, df, x0, eps );.....

}

double f( double x ){

return legendre(nl,x);}

double df( double x ){

return nl*( legendre(nl-1,x) - x*legendre(nl,x) )/(1-x*x);}

.....� �問 2.3 [量子力学 ] 規格化した一次元調和振動子の固有関数は

ψn(x) =

√α√π 2nn!

Hn(q) e−q2/2 , q = αx , α =

√mω/ℏ (2.1)

である。x と x+ dx に粒子を見出す確率は ψ2n(x) dx になる。一方, 古典力学では x と x+ dx に粒子

を見出す確率 Pcl(x) dx は, この区間を通過する時間 dt に比例するから

Pcl ∝dt

dx=

1

v, v =粒子の速さ

調和振動子の場合, E = mv2/2 +mω2x2/2 より規格化定数を C として

Pcl =C√

E −mω2x2/2, ただし E > mω2x2/2

n = 2

0 2

0.2

0.4したがって E が量子力学の固有値 ℏω(n+ 1/2) に等しいとき, 規格化した Pcl は

Pcl =α

π√2n+ 1− q2

, q2 < 2n+ 1

になる [ 量子力学 A の講義ノート ]。n = 2 の場合ψ2n(q)/α と Pcl(q)/α を図示すると右図のようになり

q 依存性は異なる。n ≫ 1 ( 例えば n = 50 )の場合,

両者を比較せよ。 整数を 4バイト (32ビット)で表すシステムでは

13! = 6, 227, 020, 800 > 232 = 4, 294, 967, 296

であるから, n ≥ 13 では n! を整数として扱うと不正確な値になる。n ≥ 13 の階乗も扱う場合を考慮して, 整数 n に対して実数で n! を返す関数を作成する。n ≤ 20 に対して n! を整数と実数で扱った場合を比較せよ。xy = pow(x, y)

Page 10: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

3 数値積分:台形則とシンプソン則 9

3 数値積分:台形則とシンプソン則関数 F (x) を a から b まで積分するとき, 区間 [a, b] を n等分して, その分点を

x0 = a, x1 = a+ h, · · · , xn−1 = a+ (n− 1)h, xn = a+ nh = b

とする。F (xk) = Fk で表わす。

台形則 区間 [xk, xk+1] の積分値を台形の面積 h

2

(Fk + Fk+1

)で近似し, これをすべての区間で足し

あわせれば ∫ b

a

F (x) dx ≈ h

(F0 + Fn

2+

n−1∑k=1

Fk

)である。

シンプソン則 n を偶数にとる。xk ≤ x ≤ xk+2 ( k は偶数 ) における F (x) を 3 点 (xk, Fk) ,

(xk+1, Fk+1) , (xk+2, Fk+2) を通る 2次式

y(x) =(x− xk+1)(x− xk+2)

(xk − xk+1)(xk − xk+2)Fk +

(x− xk)(x− xk+2)

(xk+1 − xk)(xk+1 − xk+2)Fk+1

+(x− xk)(x− xk+1)

(xk+2 − xk)(xk+2 − xk+1)Fk+2

で近似する。[xk, xk+2] での積分値は∫ xk+2

xk

dx y(x) =

∫ h

−h

dx y(x+ xk+1) =h

3

(Fk + 4Fk+1 + Fk+2

)である。したがって∫ b

a

F (x) dx ≈ h

3

(F0 +

n−1∑k=1

ckFk + Fn

), ck =

{4 kが奇数2 kが偶数

台形則, シンプソン則により積分値を与える関数double daikei( double (*func)( ), double a, double b, int n )

double sympson( double (*func)( ), double a, double b, int n )

を作成せよ。台形則のプログラム例� �double daikei( double (*func)( ), double a, double b, int n ){

int i;double dx, s;dx=( b - a )/n;s=0.5*func( a );for( i=1; i<n; i++)

s+=func( a+dx*i );s+=0.5*func( b );return s*dx;

}� �問 3.1 n = 2, 4, 8, 16, · · · , 1024 として, 台形則とシンプソン則により次の積分値を求めよ。∫ 1

0

dx

1 + x= log 2 ,

∫ 1

0

√1− x2 dx =

π

4

Page 11: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

3 数値積分:台形則とシンプソン則 10

問 3.2 n = 2, 4, 8, 16, · · · , 1024 として, 台形則とシンプソン則により次の直交性を確かめよ。2k + 1

2

∫ 1

−1

dxPk(x)Pℓ(x) = δkℓ ,1√

π 2k k!

∫ ∞

−∞dx exp(−x2)Hk(x)Hℓ(x) = δkℓ

k と ℓ を外部変数として宣言し daikei と sympson は修正しない。2番目の積分区間では被積分関数が実質的に 0 になる |x| = xmax で置き換える。たとえば e−x2

max ∼ 10−16, つまり,

xmax ∼ 6 である。xmax = 3, 4, 5, 6, 7, 8 としたとき, 積分値がどう変化するか調べよ。この積分の場合, 台形則はシンプソン則より早く収束することに注意せよ。

問 3.3 [量子力学 ] 任意の関数 φ(x) は調和振動子の固有関数 (2.1)を用いて

φ(x) =

∞∑n=0

cn ψn(x) , cn =

∫ ∞

−∞dxψn(x)φ(x)

と展開できる。

φ(x) =

√α

π1/4exp

(− α2(x− x0)2

2

)=

√α

π1/4exp

(− (q − q0)2

2

), q = αx , q0 = αx0

とする。ただし, α は (2.1)と同じである。cn を台形則で数値積分して求めよ。この積分は解析的に行えて

cn =

√ρn e−ρ

n!, ただし ρ =

q202,

∞∑n=0

c2n = 1

である [ 量子力学 Aの講義ノート ]。

φN (x) =

N∑n=0

cn ψn(x)

とする。q0 = 3 のとき, N を変化させて φN (q) と元の関数 φ(q) を図示し比較せよ。下図はq0 = 1.5 の結果である。

N = 1

−4 −2 0 2 4

N = 2

−4 −2 0 2 4

N = 3

−4 −2 0 2 4

N = 4

−4 −2 0 2 4

Page 12: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

4 連立一次方程式:ガウスの消去法 11

4 連立一次方程式:ガウスの消去法n個の未知数 x1, x2, · · · , xn についての連立一次方程式

a11x1 + a12x2 + · · ·+ a1nxn = b1

a21x1 + a22x2 + · · ·+ a2nxn = b2

· · · · · · (4.1)

an1x1 + an2x2 + · · ·+ annxn = bn

をガウスの消去法で解く。最初に, 2行目以下の方程式から x1 を消去する。1行目を pi 倍して i行目に加えると

(ai1 + a11pi)x1 + (ai2 + a12pi)x2 + · · ·+ (aij + a1jpi)xj + · · ·+ (a1n + a1npi)xn

= bi + b1pi

となる。したがって pi = −ai1/a11 とすれば i番方程式から x1 が消去でき

a11x1 + a12x2 + · · ·+ a1nxn = b1

a22x2 + · · ·+ a2nxn = b2

a32x2 + · · ·+ a3nxn = b3 (4.2)

· · · · · ·

an2x2 + · · ·+ annxn = bn

となる。ただし

aij = aij −ai1a1ja11

( i, j = 2, 3, · · · , n ), , bi = bi −ai1b1a11

( i = 2, 3, · · · , n )

上の 2式は左辺の値を右辺で置き換えることを意味する。(4.2)の 2行目以下の係数の値は (4.1)の係数とは異なっている。第二段の消去は (4.2)の 3行目以下から x2 を消去する。(4.2)を導いたのと同様にすると

a11x1 + a22x2 + a23x3 + · · ·+ a2nxn = b1

a22x2 + a23x3 + · · ·+ a2nxn = b2

a33x3 + · · ·+ a3nxn = b3 (4.3)

· · · · · ·

an3x3 + · · ·+ annxn = bn

ただしaij = aij −

ai2a2ja22

( i, j = 3, 4, · · · , n ), bi = bi −ai2b2a22

( i = 3, 4, · · · , n )

以下 x3, x4, · · · , xn−1 を消去することができる。

Page 13: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

4 連立一次方程式:ガウスの消去法 12

以上の消去の手順をまとめるとk = 1, 2, · · · , n− 1

{i = k + 1, k + 2, · · · , n{

p = akk (4.4)

j = k + 1, k + 2, · · · , n{

aij = aij − aikakj/p (4.5)

}bi = bi − aikbk/p

}}

である。akk = 0 になると (4.5)からこれ以上計算は継続できない。akk が厳密に 0 でなくても非常に小さな数の場合, (4.5)の右辺の第二項が非常に大きくなるため第一項 aij の情報が失われ (桁落ち), 新たに計算した aij は無視できない誤差を含んでしまうことがある (計算機上では数値は有限桁で表現されている)。この誤差をできるだけ小さくするには, p として aij ( i, j ≥ k ) の中で絶対値が最大の要素が k

行 k 列にくるように行と列を入れ替えればよい。p として選ぶ行列要素は重要な働きをする。この行列要素をピボットという。通常は k列だけの要素

akk , ak+1 k , · · · , ank

の中から絶対値最大のものを探す。amk (m > k ) の絶対値が最大であったなら, k行とm行を入れ替える。この入れ替えはもとの連立方程式の k 行目の方程式と m行目の方程式を交換することになるが, 方程式の順序を入れ替えても解は変わらない。この方法を部分選択ピボット法という。実際のプログラムでは (4.4)の前にピボット選択のルーチンが必要である。xn−1 まで消去を繰り返すと, 連立方程式は

a11x1 + a12x2 + a13x3 + · · ·+ a1nxn = b1

a22x2 + a23x3 + · · ·+ a2nxn = b2

a33x3 + · · ·+ a3nxn = b3 (4.6)

· · · · · ·

annxn = bn

となる。したがって xn = bn/ann と直ちに求まる。xn が求まれば xn−1 は

xn−1 =bn−1 − an−1n xn

an−1n−1

で与えられる。同様にして xn から x1 に向かって計算を行うとすべての解

xk =1

akk

bk − n∑j=k+1

akj xj

が求まる。xn, xn−1, · · · , xk+1 はすでに求まっているから xk を決定できる。

ガウスの消去法により連立一次方程式を解く関数プログラム

Page 14: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

4 連立一次方程式:ガウスの消去法 13

void gauss( double a[], double b[], int n )

を作成せよ。ただしn = n , a[i+n*j] = aij , b[i] = bi

である。解 xi は b[i] に返す。aij 用に 2次元配列を用いてもよいが, 1次元配列ならば関数に引き渡すとき配列の大きさを明示する必要がないので, プログラムに柔軟性を持たせることができる。ただし, a[] の大きさは n2 + 1 以上確保すること。また, main において n, aij , bi の値を

n

a11 a12 · · · a1n b1

a21 a22 · · · a2n b2...

......

......

an1 an2 · · · ann bn

(4.7)

という形式で標準入力 (キーボード)から入力できるようにする。

問 4.1 次の連立方程式をガウスの消去法で解け。

8x1 +3x2 + x3 =14

3x1 +4x2 + x3 =13.8

x1 + x2 +2x3 =9

x1 +2x2 + x3 +5x4 =20.5

8x1 + x2 +3x3 + x4 =14.5

x1 +7x2 + x3 + x4 =18.5

x1 + x2 +6x3 + x4 =9

得られた解が連立方程式を満たすことを確かめよ。

問 4.2 次のデータ

aij =

4 i = j

1 i = j ± 1

0 その他, bi =

n∑j=1

aijj

を (4.7)の形式で標準出力 (ディスプレイ)に出力するプログラムを作成せよ。ただし, n の値をコマンド行の引数として渡せるようにする。つまり, 実行プログラム名を program とした場合

program 20

と入力すると, n の値が 20 になるようにする。このプログラムの出力を DOS あるいは UNIX

のパイプ機能によりガウス消去法のプログラムにデータとして読み込ませよ。ガウス消去法の実行プログラム名が gauss ならば

program 30 | gauss

と入力する。コマンド行の引数をプログラムに渡す方法は 1ページを参照。

Page 15: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

5 常微分方程式:ルンゲ・クッタ型公式 14

5 常微分方程式:ルンゲ・クッタ型公式次のような1階の n元連立微分方程式を考える。

dX1

dt= F1(X1, X2, · · · , Xn, t )

dX2

dt= F2(X1, X2, · · · , Xn, t )

...dXn

dt= Fn(X1, X2, · · · , Xn, t )

この微分方程式はただ 1つの変数 t の微分を含む。これを常微分方程式という。物理でよく出てくる2階の微分方程式, 例えば

d2x

dt2= − ω2 x (5.1)

は X1 = x, X2 = dx/dt とするとdX1

dt= X2 ,

dX2

dt= − ω2X1

と表わせるから, F1(X1, X2, t ) = X2, F2(X1, X2, t ) = − ω2X1 とした 1階の 2元連立微分方程式に還元できる。独立変数 t を t0 から一定の刻み幅 h で tk = t0 + kh ( k = 1, 2, 3, · · · ) と増やしていき,

各分点 tk における未知の関数 Xi(tk) を数値的に求める。tk における導関数を

dXi

dt

∣∣∣∣tk

≈ Xi(tk+1)−Xi(tk)

h

で近似すると, 元の微分方程式から

Xi(tk+1) = Xi(tk) + hFi(X1(tk), X2(tk), · · · , Xn(tk), tk )

となる。すべての Xi(t0) , ( i = 1, 2, · · · , n ) を初期条件として与えれば, この式から

Xi(t1) = Xi(t0) + hFi(X1(t0), X2(t0), · · · , Xn(t0), t0 )

Xi(t2) = Xi(t1) + hFi(X1(t1), X2(t1), · · · , Xn(t1), t1 )...

と次々に求められる。これは常微分方程式の最も簡単な数値解法であり, オイラー法と呼ばれる。オイラー法は h のオーダーまで正しい結果を与える。tk+1 の関数を求めるとき, tk での傾き Fi より中間点の傾きを用いた方が正確である。そこで, ス

テップ幅 h/2 のオイラー法を組み合わせて ( tk+1/2 = tk + h/2 )

Xi(tk+1/2) = Xi(tk) +h

2Fi(X1(tk), X2(tk), · · · , Xn(tk), tk) (5.2)

Xi(tk+1) = Xi(tk) + hFi(X1(tk+1/2), X2(tk+1/2), · · · , Xn(tk+1/2), tk+1/2) (5.3)

として, Xi(tk) から Xi(tk+1) を求める。これを改良オイラー法という。改良オイラー法は h2 のオーダーまで正確である。Xi(tk) から Xi(tk+1) を求める関数プログラムを次のようにして作成する。• Xi(tk) ( i = 1, 2, · · · , n ) の値を 1次元配列 x[] に入れる。x[i] = Xi(tk) である。x[] のサイズは n+ 1 以上である。

Page 16: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

5 常微分方程式:ルンゲ・クッタ型公式 15

• Xi(tk) ( i = 1, 2, · · · , n ) から Fi(X1(tk), X2(tk), · · · , Xn(tk), tk) を求める関数を別途用意する。この関数名を例えば func とすると

void func( double x[], double f[], double t )

である。f[] はサイズが n+ 1 以上の 1次元配列で, 求めた Fi を f[i] に返す。• x[], f[] から Xi(tk + h) を求め, その値を x[i] に返す。改良オイラー法では Xi(tk+1/2) 用にもう一つ 1次元配列が必要である。以下の例では wrk[] がそのための配列である。

作成する関数プログラムの形式は, オイラー法ではvoid euler( void (*func)(), double x[], double f[], double t, double h, int n )

改良オイラー法ではvoid meuler( void (*func)(), double x[], double f[], double wrk[],

double t, double h, int n )

となる。ただし, n =連立微分方程式の個数n , h =刻み幅h , t = tの初期値 tk である。改良オイラー法のサンプル� �void meuler( void (*func)(), double x[], double f[], double wrk[],

double t, double h, int n ){

int i;func( x, f, t );for(i=1; i<=n; i++ )

wrk[i]=x[i]+h*f[i]/2;

func( wrk, f, t+h/2 );for(i=1; i<=n; i++ )

x[i]+=h*f[i];

}� �最初の func( x, f, t ) で Xi(tk) が与えられたとき (5.2)の右辺で必要になる Fi を f[i] に求める。次の forループで (5.2)の左辺の Xi(tk+1/2) を計算しこれを wrk[i] に保存する。(5.3)に対しても同様の処理をする。ただし, Fi を求めるとき Xi(tk) ではなく Xi(tk+1/2), つまり wrk[i] を使う。func は, (5.1)の場合は

void vib( double x[], double f[], double t ){

f[1]=x[2];f[2]=-w*w*x[1];

}

(5.4)の場合はvoid damped( double x[], double f[], double t ){

f[1]=x[2];f[2]=-2*gamma*x[2]-x[1]+force*cos( w*t );

}

とすればよい。これらの関数を例えば euler( vib, · · · ) として使う。w, gamma, force は外部引数とし, 引数として渡さなくてもよいようにする。

問 5.1 h = 0.02 としてd2x

dt2= −x , x(0) = 1 ,

dx

dt

∣∣∣∣t=0

= 0 , 0 ≤ t ≤ 20

をオイラー法と改良オイラー法で解け。解析解 cos t との差を図示せよ。euler, meuler では

Page 17: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

5 常微分方程式:ルンゲ・クッタ型公式 16

t での x[i] を与えて t+h での x[i] が求まることに注意すること。

問 5.2 [古典力学 ] 次の微分方程式 (減衰強制振動)を改良オイラー法で解く。

d2x

dt2+ 2γ

dx

dt+ x = f cosωt (5.4)

1. f = 0 のとき, γ = 0.1, 0.2, 0.5, 1, 2 として解析解と数値解を比較せよ。2. 例えば f = 0.2, γ = 0.1 のとき, ω = 0.5, 0.6, · · · , 1.4, 1.5 として時間が十分経過したときの振幅の ω依存性を調べよ。

古典的ルンゲ・クッタ法オイラー法と改良オイラー法は, ルンゲ・クッタ型公式と総称されるものの特別な場合である。実際の数値計算ではオイラー法や改良オイラー法はあまり使われない。より精度の良い結果を与える古典的ルンゲ・クッタ法がよく使われる。古典的ルンゲ・クッタ法は

Xi(tk+1) = Xi(tk) +1

6

(ki + 2li + 2mi + ni

)+O(h5)

ただし

ki = hFi

(X1(tk) , · · · , Xn(tk), tk

)li = hFi

(X1(tk) + k1/2 , · · · , Xn(tk) + kn/2, tk+1/2

)mi = hFi

(X1(tk) + l1/2 , · · · , Xn(tk) + ln/2, tk+1/2

)ni = hFi

(X1(tk) +m1 , · · · , Xn(tk) +mn, tk+1

)である。Xi(tk+1) を t = tk でテイラー展開すると, 真の解 Xi(tk + h) のテイラー展開と h4 のオーダーまでは一致する。上式のプログラム例を示す。

~ � �void runge( void (*func)(), double x[], double f[], double wrk1[],

double wrk2[], double t, double h, int n ){

int i;func( x, wrk2, t ); /* k_i = h*wrk2[i] */for(i=1; i<=n; i++ ) {

f[i] = x[i] + h*wrk2[i]/6;wrk1[i] = x[i] + h*wrk2[i]/2;

}func( wrk1, wrk2, t+h/2 ); /* l_i = h*wrk2[i] */for(i=1; i<=n; i++ ) {

f[i] += h*wrk2[i]/3;wrk1[i] = x[i] + h*wrk2[i]/2;

}func( wrk1, wrk2, t+h/2 ); /* m_i = h*wrk2[i] */for(i=1; i<=n; i++ ) {

f[i] += h*wrk1[i]/3;wrk1[i] = x[i] + h*wrk2[i];

}func( wrk1, wrk2, t+h ); /* n_i = h*wrk2[i] */for(i=1; i<=n; i++ )

x[i] = f[i] + h*wrk2[i]/6;}� �

Page 18: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

5 常微分方程式:ルンゲ・クッタ型公式 17

問 5.3 [古典力学 ] 中心力 − rα の 2次元ニュートン方程式

d2x

dt2= − rαx

r,

d2y

dt2= − rα y

r, r =

√x2 + y2

を改良オイラー法とルンゲ・クッタ法で解け。この場合, 1階の 4元連立微分方程式になる。初期条件としては, 例えば x(0) = 2, y(0) = 0, vx(0) = 0, vy(0) = 0.5, h = 0.1

1. 様々な α の値に対して軌道を図で表せ。α = −2 または α = 1 のとき, 束縛運動の軌道は初期条件に依らずに閉じる。

2. 力学的エネルギーと角運動量の z成分 Lz

E =1

2

(v2x + v2y

)+ V (r) , Lz = xvy − yvx , V (r) =

rα+1

α+ 1, α = −1

log r , α = −1

は時間的に一定であるが, 数値計算の結果ではどうなるか。3. α > − 3 の場合, 軌道は同心円で限られた領域 rmin ≤ r ≤ rmax になる。ところで, 中心力ポテンシャル V (r) の場合, 力学的エネルギー E は極座標で表すと

E =1

2r2 +

L2z

2r2+ V (r)

これから運動可能な r は1

2r2 = E − L2

z

2r2− V (r) ≥ 0

を満たす領域である。上式 = 0 を満たす r をニュートン法で求め, この半径の円を軌道の図に描いてみよ。E と Lz は初期条件を与えれば決まる。

実線はルンゲ・クッタ, 破線は改良オイラーα = −1.80

h = 0.10

0 ≤ t ≤ 50

x(0) = 2.0

y(0) = 0.0

vx(0) = 0.0

vy(0) = 0.50

Page 19: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

6 行列の固有値問題 : ヤコビ法 18

6 行列の固有値問題 : ヤコビ法行列成分 aij が実数で aij = aji を満たす n×n 実対称行列 A0 = (aij) の固有値 λ と固有ベクトル X

A0X = λX , X =

x1

x2...

xn

(6.1)

をヤコビ法で求める。P 1 = (pij) として 2次元の回転に対応する

P 1 =

1 0 0 · · ·

00 1 0 · · ·. . .

1 0

cosϕ · · · sinϕ · · · 0...

......

− sinϕ · · · cosϕ · · · 0

0 ......

. . .

0 0 1

p行

q行

p列 q列つまり

pij = δij pi + (δip δjq − δiq δjp) sinϕ , pi =

1 i = p, q

cosϕ i = p, q

を考える。P 1 は P−11 = PT

1 を満たすから直交行列である ( PT1 は P 1 の転置行列を表わす )。ここ

で (a′ij) = A1 = P−11 A0P 1 とすると

a′ij = aij , i = p, q j = p, qr (6.2)

a′pk = a′kp = apk cosϕ− aqk sinϕ , k = p, q (6.3)

a′qk = a′kq = apk sinϕ+ aqk cosϕ , k = p, q (6.4)

a′pp = app cos2 ϕ+ aqq sin

2 ϕ− apq sin 2ϕ (6.5)

a′qq = app sin2 ϕ+ aqq cos

2 ϕ+ apq sin 2ϕ (6.6)

a′pq = a′qp =app − aqq

2sin 2ϕ+ apq cos 2ϕ (6.7)

になる。非対角成分の中で絶対値が最大のものを apq とし, 変換後の行列 A1 の pq成分 a′pq が 0 になるように ϕ を選ぶ。(6.7)から ϕ は

tan 2ϕ = − 2apqapp − aqq

である。このとき非対角成分の二乗和に対して不等式∑i=j

a′ij2 ≤ r

∑i=j

a2ij , r = 1− 2

n(n− 1)(6.8)

が成り立つ。証明はこの章の最後にある。以上の変換を行列 A1 に対して再度行い A2 を求める。この操作を繰り返し行う。変換に番号を付け

Am = P−1m Am−1Pm , m = 1, 2, · · ·

Page 20: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

6 行列の固有値問題 : ヤコビ法 19

とすると

Am = P−1m P−1

m−1Am−2Pm−1Pm = · · · = T−1m A0Tm , Tm = P 1 · · ·Pm−1Pm

になる。Am の非対角成分の二乗和を Sm とすると (6.8) より Sm ≤ rSm−1 ≤ · · · ≤ rmS0 であり0 ≤ r < 1 であるから, m → ∞ のとき Sm → 0 になる。したがって, 非対角成分はすべて 0 になるから

Λ = T−1A0T , T = limm→∞

Tm

は対角行列である。Λ の対角成分を λ1, λ2, · · · , λn とし, T の k列成分からなる列ベクトルをXk , つまり, (Xk)i = tik とすると, A0T = TΛ は

A0Xk = λkXk

と書ける。したがって, Λ の対角成分 λk が A0 の固有値であり, Xk が固有値 λk に属する固有ベクトルになる。以上のようにして固有値と固有ベクトルを求める方法をヤコビ法という。なお, Pm =

(pij), Tm−1 = (tij), Tm = (t′ij) とすると Tm = Tm−1Pm より

t′ij = tij ( j = p, q ) , t′ip = tip cosϕ− tiq sinϕ , t′iq = tip sinϕ+ tiq cosϕ

である。実対称行列 A0 = (aij)が与えられたとき,ヤコビ法で固有値 λk と T を求める関数を作成する。Am

の非対角成分の最大絶対値がある値 (例えば 10−8 )以下になったら対角化されたとする。1 ≤ i, j ≤ nの場合, 配列の大きさは (n+ 1)× (n+ 1)以上確保する。プログラムの流れは� �#define NDIM 100 /** 必要な配列の大きさ **/

double a[NDIM][NDIM], t[NDIM][NDIM];

void yacobi( int n, double aa[NDIM][NDIM], double tt[NDIM][NDIM], double eps );

int main(){

n=10;

a に行列 A0 を与えるyacobi( n, a, t, 1.e-8 );

.....

}

void yacobi( int n, double aa[NDIM][NDIM], double tt[NDIM][NDIM], double eps )

{

tt を単位行列として初期化count = 0; maxvalue = 1;

while( ++count < 10000 && maxvalue > eps ){

aa の非対角成分で絶対値が最大の aa[p][q] を検索。maxvalue = |aa[p][q]|角度 ϕ を求めA′ = P−1AP , T ′ = TP を計算する。A′ を A に , T ′ を T に代入 ( いきなり A = P−1AP , T = TP としてはダメ )

}

}� �(6.2)∼(6.7)は i = p, q などの条件を if文で正直にプログラムすると結構複雑になるが, i = p, q などの条件は無視して (6.2)∼(6.7)の順番でプログラムすればよい。例えば, (6.2)で i = p の場合は (6.3)

で上書きされる。

Page 21: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

6 行列の固有値問題 : ヤコビ法 20

問 6.1 次の行列の固有値と固有ベクトルを求めよ。また, (A0Tm)ik = λk(Tm)ik が数値的に成り立つことを確かめよ。

6.0 5.0 4.0 3.0 2.0 1.0

5.0 5.0 4.0 3.0 2.0 1.0

4.0 4.0 4.0 3.0 2.0 1.0

3.0 3.0 3.0 3.0 2.0 1.0

2.0 2.0 2.0 2.0 2.0 1.0

1.0 1.0 1.0 1.0 1.0 1.0

固有値は 17.20686, 1.98816, 0.77472, 0.44622, 0.31886, 0.26519 になる。

問 6.2 [量子力学 ] 角運動量 J2, Jz の同時固有状態 |j m⟩ を基底にとる ( ただし ℏ = 1 )。j を与えたときハミルトニアン

H = J2z − ωJx

の行列を対角化することにより, H の固有値と固有状態における Jx の期待値を求める。j =

13/2 のとき, 固有値と Jx 期待値を ω の関数として図示せよ。j = 13/2 の場合 2j + 1 = 14次元の行列になる。ω が小さいときは縮退がある場合の 1次の摂動, 一方, ω が非常に大きいときは H ≈ −ωJx としてよいから, 固有値と Jx の期待値がどうなるか予想できる。これと数値計算の結果を比較せよ。  |n ⟩ = | j m=n−j−1⟩ , ( n = 1, 2, · · · , 2j + 1 )とする。H|E⟩ = E|E⟩ である |E⟩ は

|E⟩ =2j+1∑n=1

Xn |n ⟩

と展開できる。したがって ∑n′

H|n′ ⟩Xn′ = E∑n′

Xn′ |n′ ⟩

である。⟨n | をかけ直交性 ⟨n |n′ ⟩ = δnn′ を使うと∑n′

hnn′Xn′ = EXn , hnn′ = ⟨n |H|n′ ⟩

(A0)nn′ = hnn′ とすれば (6.1)である。k 番目の固有値を Ek , 対応する Xn を Xkn とするとXkn = (T )nk であるから, 期待値は

⟨Ek|Jx|Ek⟩ =∑nn′

XknXkn′⟨n |Jx|n′ ⟩ =∑nn′

(T )nk⟨n |Jx|n′ ⟩(T )n′k =(TTJxT

)kk

ただし Jx は行列 (Jx)nn′ = ⟨n |Jx|n′ ⟩ である。

| 1 ⟩

| 2 ⟩

| 3 ⟩

| 4 ⟩

| 5 ⟩

0 5 ω

j = 2

−10

0

10| 1 ⟩

| 2 ⟩

| 3 ⟩

| 4 ⟩

| 5 ⟩

0 5 ω

j = 2

⟨Jx⟩

−2

0

2

Page 22: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

6 行列の固有値問題 : ヤコビ法 21

(6.8)の証明P−1

1 = PT1 , A

T0 = A0 であるから

AT1 = (P−1

1 A0P 1)T= PT

1 AT0 P 1 = P−1

1 A0P 1 = A1

A1 も実対称行列である。a′ij = a′ji より∑i, j

a′ij2 =

∑i, j

a′ija′ji = Tr(A1A1) = Tr(P−1

1 A0P 1P−11 A0P 1) = Tr(A0A0) =

∑i, j

a2ij

となる。非対角成分の二乗和は∑i=j

a′ij2 =

∑i, j

a′ij2 −

∑i

a′ii2 =

∑i, j

a2ij −∑i

a′ii2 (6.9)

(6.5), (6.6), (6.7)より a′pp2 + 2a′pq

2 + a′qq2 = a2pp + 2a2pq + a2qq になるが, a′pq = 0 であるから

a′pp2 + a′qq

2 = a2pp + 2a2pq + a2qq

i = p, q のとき a′ii = aii であるから∑i

a′ii2 =

∑i=p, q

a2ii + a′pp2 + a′qq

2 =∑i=p, q

a2ii + a2pp + 2a2pq + a2qq =∑i

a2ii + 2a2pq

これを (6.9)に代入すると∑i=j

a′ij2 =

∑i, j

a2ij −∑i

a2ii − 2a2pq =∑i=j

a2ij − 2a2pq

になる。apq は非対角成分の中で絶対値が最大であるから∑i=j

a2ij ≤∑i=j

a2pq = n(n− 1)a2pq , i.e. a2pq ≥1

n(n− 1)

∑i=j

a2ij

したがって ∑i=j

a′ij2 =

∑i=j

a2ij − 2a2pq ≤(1− 2

n(n− 1)

)∑i=j

a2ij

Page 23: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

7 シュレディンガー方程式の数値解法 22

7 シュレディンガー方程式の数値解法7.1 微分方程式を解く境界条件がある 1点だけで与えられる場合 (例えば, 初期条件を与えてニュートン方程式を解く), 境界条件を出発点にとりルンゲ・クッタ公式を繰り返し適用すれば, 微分方程式の数値解を逐次得ることができる。一方, 例えば, 1次元シュレディンガー方程式(

− ℏ2

2m

d2

dx2+ V (x)

)ψ(x) = Eψ(x)

の束縛状態を求める場合, 区間 a ≤ x ≤ b の両端で境界条件が与えられる。ただし, 境界が無限遠の場合には波動関数がほぼ 0 となる適当な有限区間で置き換える。適当な E を与えた場合, 片側の境界条件から出発して求めた解 ψ(x) は, 一般にはもう 1つの境界条件を満たさない。E がある値のときだけ両方の境界条件を満たす。このときの値が離散的固有値を与える。シュレディンガー方程式の束縛状態を数値的に求める問題は, 微分方程式を解くと同時に, 固有値も求めなければならない。1次元調和振動子ハミルトニアンの場合, x = 0 で ψ(x) = 0 として x→∞ に向けてルンゲ・クッタ公式で解いた波動関数 ψin(x) と x が十分大きい点で ψ(x) = 0 として x → 0 に向けて解いた解いた波動関数 ψout(x) を下図に示す。ただし, 適当な点 xm で ψin(xm) = ψout(xm) になるように定数倍した。E = ℏω(n + 1/2) , ( 以下の例では n = 3 )の場合, ψin は x → ∞ での境界条件を, ψout は x = 0

での境界条件を満たさない。また, x = xm で両者は連続であるが, 導関数 ψ′(x) は不連続である。一方, E = ℏω(n+ 1/2) の場合, ψin と ψout は一致し 2つの境界条件を満たす。

xm

E/ℏω = 3.30

ψin(x)

ψout(x)

xm

E/ℏω = 3.50

離散的固有値を求める 1つの方法を示す。∗) x = a での境界条件から x を増加させて得られる解をψa(x,E), x = b での境界条件から x を減少させて得られる解を ψb(x,E) とし, これらを x = xm でつなぐことを考える。一般に ψa(xm, E) = ψb(xm, E) であり x = xm で連続ではないが, 定数倍した関数も微分方程式を満たすから

ϕa(x,E) =ψa(x,E)

ψa(xm, E), ϕb(x,E) =

ψb(x,E)

ψb(xm, E)

とすれば ϕa(xm, E) = ϕb(xm, E) = 1 になり x = xm で連続である。しかし, パラメータ E が固有値に等しい場合を除けば, 導関数は x = xm で連続にならない。したがって

ϕ′a(xm, E)− ϕ′b(xm, E) =W (E)

ψa(xm, E)ψb(xm, E)

ただしW (E) = ψ′

a(xm, E)ψb(xm, E)− ψa(xm, E)ψ′b(xm, E)

とし, W (E) = 0 の解を求めれば固有値が得られる。W (E) = 0 の解はセカント法で求める。n番目の近似解を En とすると, さらに精度の良い n+ 1番目の近似解は

En+1 = En −W (En)

W (En)−W (En−1)

En − En−1

∗) 櫻井捷海, コンピュータで学ぶ量子力学 [基礎編](裳華房, 1992)

Page 24: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

7 シュレディンガー方程式の数値解法 23

である。最初の E1 と E2 を与えて, |(En+1 − En)/En| < ε ( ε は非常に小さい定数 )になるまで繰り返し実行する。最終的に得られた En が固有値, その時のルンゲ・クッタ公式の数値解が固有関数になる。W (E) はロンスキー行列式 (あるいはロンスキアン)である。W (E) は xm に依存しない。3次元中心力ポテンシャル V (r) の場合に, 以上の方法をもう少し具体的に考えよう。

ψ(r) =u(r)

rYℓm(θ, ϕ)

とおくと u(r) はd2u

dr2=

(ℓ(ℓ+ 1)

r2+

2M

ℏ2(V (r)− E

))u(r) (7.1)

を満たす。X1 = u, X2 = u′ とするとdX1

dr= X2 ,

dX2

dr=

(ℓ(ℓ+ 1)

r2+

2M

ℏ2(V (r)− E

))X1

である。したがって, ルンゲ・クッタ型公式の関数は

F1(X1, X2, r) = X2 , F2(X1, X2, r) =

(ℓ(ℓ+ 1)

r2+

2M

ℏ2(V (r)− E

))X1

とすればよい。• r = 0 から r を増加させて解く場合r = 0 とすると ℓ(ℓ + 1)/r2 は発散するから, rmin を適当な微小値として r = rmin から解き始める。r → 0 のとき r2V (r)→ 0 ならば

u(r)→ C rℓ+1 , C =定数

である。そこでu(rmin) = rℓ+1

min , u′(rmin) = (ℓ+ 1)rℓmin

を初期条件としてルンゲ・クッタを用いる。• r =∞ から r を減少させて解く場合r = rmax から解き始める。rmax としては, 多くの場合 rmax = (3 ∼ 4) × rT とすれば問題ない。ただし, E − V (rT) = 0 であり, 古典力学的には rT より外側では運動は禁止される。u, u′ の初期値は r →∞ での漸近形が解析的に求まるならば漸近形の値を使う。求まらない場合は

u(rmax) = 0 , u′(rmax) = ε , εは微小量

として解く。2つの数値解の接続点 rm は何処にとってもよいわけだが, 実際に数値計算すると rm の取り方により,

求まるはずの固有値が得られなかったりする。rm の取り方には注意すべきである。

具体的なプログラム例 ℓ と E は main の前で宣言しておく。これらの変数を参照するとき引数として渡さなくて済む。また, 5章で作成した関数 runge を変更しないために, V (r) に含まれる定数もmain の前で宣言する。区間 [ rmin , rmax ] を imax 等分する。h = (rmax − rmin)/imax とし, 接続点 rm

を rm = rmin + imh にとる。これらの変数も main の前で宣言し, 具体的値は main の中で与える。以下では

ll = ℓ , eigen = E , hbarm = 2M/ℏ2

hh = h , rmin = rmin , rmax = rmax , imax = imax , im = im ,

とする。

Page 25: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

7 シュレディンガー方程式の数値解法 24

wronskian ℓ, E を与えたときロンスキアンを返す関数。ただし pot(r) = V (r)。get eigen 初期値 E1, E2 を与えてセカント法で固有値を求める関数。w1, w2 という変数を用いず

にde = - wronskian(e2)*(e2-e1)/( wronskian(e2)-wronskian(e1) );

でもよいが, ロンスキアンの計算回数が 3倍, したがって, 計算時間も 3倍程度かかる。� �void schr( double *x, double *f, double r ){

f[1]=x[2];f[2]=( ll*(ll+1)/(r*r) + hbarm*( pot(r) - eigen ) )*x[1];

}

double wronskian( double energy ){

int i;double x[3], f[3], wrk1[3], wrk2[3], r, wf, dwf;eigen = energy;

/*** rmin --> rm ***/x[1] = pow(rmin, ll+1); /** u(rmin)の値 **/x[2] = (ll+1)*pow(rmin,ll); /** u’(rmin)の値 **/for(i=0; i<im; i++ ){ /** i=im は含まない **/

r = rmin+hh*i;runge( schr, x, f, wrk1, wrk2, r, hh, 2 );

}wf = x[1]; dwf = x[2];

/*** rmax --> rm ***/x[1] = 0; /** u(rmax)の値 **/x[2] = 1.e-6; /** u’(rmax)の値 **/for(i = imax; i>im; i-- ){

r = rmin+hh*i;runge( schr, x, f, wrk1, wrk2, r, - hh, 2 );

}return dwf*x[1] - x[2]*wf;

}

double get_eigen( double e1, double e2 ){

int n;double de, eps, w1, w2;de = 1.e6; /** 適当な大きな値 **/eps = 1.e-8; /** 収束条件 **/w1 = wronskian( e1 );n = 0;while( fabs(de/e1) > eps ){

if( n++>20 ){printf("収束せずY=n");return 1.e20; /** 無意味な値 **/

}w2 = wronskian( e2 );de = - w2*(e2-e1)/(w2-w1);e1 = e2; w1 = w2;e2+= de;

}return e2;

}� �

Page 26: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

7 シュレディンガー方程式の数値解法 25

問 7.1 合流型超幾何関数 M(β, γ, x) は

M(β, γ, x) = 1 +β

γ

x

1!+β(β + 1)

γ(γ + 1)

x2

2!+β(β + 1)(β + 2)

γ(γ + 1)(γ + 2)

x3

3!+ · · ·

で定義される。n = 0, 1, 2, · · · のときM(−n, γ, x)はn次の多項式になる。Mn =M(−n, γ, x)とおくと Mn は漸化式

(n+ γ)Mn+1 = (2n+ γ − x)Mn − nMn−1 , M0 = 1 , M1 = 1− x/γ

を満たす。M(−n, γ, x) を求める関数 hyper( int n, double gamma, double x )を作成せよ。エルミート多項式が

H2n(x) = (−1)n (2n)!n!

M(−n, 1/2, x2 )

H2n+1(x) = (−1)n (2n+ 1)!

n!2xM(−n, 3/2, x2 )

になることを数値的に確かめよ。

問 7.2 ポテンシャルがV (r) =

1

2Mω2 r2

の場合, 3次元シュレディンガー方程式を数値的に解き, 固有値が

Enℓ = ℏω(ℓ+ 2n+

3

2

), ℓ = 0, 1, 2, · · · , n = 0, 1, 2, · · · (7.2)

になることを確かめる。パラメータの値は

ℏω = 41/A1/3 MeV , Mc2 = 939MeV , ℏc = 197.33MeV fm (7.3)

とする。2M

ℏ2=

2Mc2

(ℏc)2, V (r) =

Mc2(ℏω)2

2(ℏc)2r2

であるから, Mc2 , E , V (r) をMeV単位, r を fm = 10−15 m単位で表せばよい。A は核子数であり適当な値 ( 例えば A = 100 )を用いる。

1. 0 ≤ E ≤ 10ℏω を 50等分して Ei = ℏω×0.2 i , ( 0 ≤ i ≤ 50 )とする。W (Ei)W (Ei−1) < 0

になる Ei−1, Ei を求め Ei−1 < Enℓ < Ei を確かめよ。2. 1.で求めた Ei−1, Ei を初期値としてセカント法によりW (E) = 0となる E を求め, E/ℏωと ℓ+ 2n+ 3/2 を比較せよ。n は u(r) = 0 になる点の個数 ( r = 0 は除く)である。

3. 数値的に求めた波動関数を規格化し

unℓ(r) =√αNnℓ q

ℓ+1e−q2/2M(−n , ℓ+ 3/2 , q2 ) (7.4)

ただしq = αr , α =

√Mω

ℏ=

√Mc2 ℏωℏc

, Nnℓ =

√2Γ (ℓ+ 3/2 + n)

n! (Γ (ℓ+ 3/2))2

と一致することを確かめよ。ただし, M(β, γ, x) は合流型超幾何関数, Γ はガンマ関数でn を負でない整数とするとき

Γ (n+ 1/2) =(2n)!

22nn!

√π , Γ (n+ 1) = n!

である。

Page 27: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

7 シュレディンガー方程式の数値解法 26

問 7.3 調和振動子ポテンシャルの代わりにWoods–Saxonポテンシャル

V (r) = − V01 + exp((r −R)/a)

(7.5)

を考える。ただし, パラメータの値は (7.3)及び

V0 = 51MeV , R = 1.25A1/3 fm

とする。束縛状態の固有値 E は V (0) ≈ −V0 < E < 0 であるから, この区間を適当に等分し,

W (Ei)W (Ei−1) < 0 である Ei−1, Ei を初期値としてセカント法を用いる。

HO WS

A = 80 rmax/R = 3.0 imax = 200

1s (−42.95 )

1p (−35.61 )

1d (−27.11 )

2s (−24.81 )

1f (−17.72 )

2p (−14.82 )

1g (−7.71 )

2d (−5.22 )3s (−4.67 )

1s

1p

2s, 1d

2p, 1f

3s, 2d, 1g

0

−10

−20

−30

−40

MeV

1. ℓ = 0 のとき (7.1)はポテンシャルが V (r) である 1 次元シュレディンガー方程式になる。ところで, a→ +0 とすると (7.5)は井戸型ポテンシャル

V (r) =

{− V0 , 0 ≤ r < R

0 , r > R

になるから, ℓ = 0 の固有値 E は (1.3) のg(k) = 0 で与えられる。a = 0.01 fm 及びa = 0.1 fmのとき (7.1)をルンゲ・クッタで解いて得られた固有値と g(k) = 0 から求めた固有値を比較せよ。

2. a = 0.65 fm とする。Enℓ と (7.2)を比較して図示せよ。ただし, (7.2)に定数を加えて n =

0, ℓ = 0 を一致させる。(7.2)では ℓ + 2n が同じ (n, ℓ) の状態は縮退している。また, 得られた固有関数を (7.4)と比較してみよ。

7.2 行列の対角化行列の対角化によりシュレディンガー方程式を解く。あるハミルトニアン H0

H0 = − ℏ2

2m∇2 + V0(r)

の固有値 E0(i) と固有関数 | i ⟩ が分かっているとする:

H0| i ⟩ = E0(i)| i ⟩

ここで i は一般に量子数の組である。ハミルトニアン H

H = − ℏ2

2m∇2 + V (r) = H0 + δV , δV = V − V0

の固有値 E と固有関数 |ψ⟩ を求める。|ψ⟩ =

∑i

ci | i ⟩

と展開できるから, これを H|ψ⟩ = E|ψ⟩ に代入すると∑j

cj H| j ⟩ = E∑j

cj | j ⟩

Page 28: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

7 シュレディンガー方程式の数値解法 27

ブラ ⟨ i | を掛け直交性 ⟨ i | j ⟩ = δij を使うと∑j

Hij cj = E ci , Hij = ⟨ i |H0 + δV | j ⟩ = E0(i) δij + ⟨ i |δV | j ⟩

となる。これはエルミート行列 Hij の固有値と固有ベクトルを求めることに他ならない。

数値計算する上での注意• 行列 Hij が無限次元の場合, 適当な次元数で計算し, 次元数を変化させても固有値が求めたい精度内で不変であることを確かめる。

• 行列 Hij を求めるとき対称性を考慮し, できるだけ行列の次元を小さくする。例えば, 球対称の場合 ( V , V0 が r だけの関数 )を考える。この場合, H0, H は角運動量演算子ℓ と交換するから, H0, H の固有状態は ℓ2, ℓ3 の固有状態でもある。| i ⟩ として H0, ℓ

2, ℓ3 の同時固有状態 |nℓm ⟩ を採用すれば, 一般に

|ψ⟩ =∑nℓm

cnℓm |nℓm ⟩ , H0|nℓm ⟩ = E0(nℓ) |nℓm ⟩

であるが, |ψ⟩ が ℓ2, ℓ3 の固有状態であることを要請すると

|ψ⟩ =∑n

cnℓm |nℓm ⟩

となり, ℓ, m について和をとる必要はない。|nℓm ⟩ の波動関数をunℓ(r)

rYℓm(θ, ϕ)

とすると, 必要な行列要素は

⟨nℓm|δV |n′ℓm⟩ =∫ ∞

0

dr unℓ(r)un′ℓ(r) δV (r)

である。

問 7.4 ℏω = 41/A1/3 MeV である調和振動子ポテンシャルの固有関数を基底にとり, 問 7.3 のハミルトニアンを対角化して固有値を求めよ。

δV (r) = − V01 + exp((r −R)/a)

− 1

2Mω2r2

である。δV の行列要素を求めるとき, 積分は台形則でよい。(7.4)より

⟨nℓm|δV |n′ℓm⟩

= NnℓNn′ℓ

∫ ∞

0

dq e−q2q2ℓ+2 δV (q/α)M(−n , ℓ+ 3/2 , q2

)M(−n′ , ℓ+ 3/2 , q2

)ただし n, n′ = 0, 1, 2, · · · である。q の積分範囲は問 3.2 を参照せよ。δV = 1 とすれば ⟨nℓm|δV |n′ℓm⟩ = δnn′ になるはずである。行列要素を計算する関数が正しいか, これでチェックすること。

Page 29: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

8 モンテカルロ法 28

8 モンテカルロ法• 独立な確率変数 x1, x2, · · · が同じ確率分布 (平均 µ = ⟨x ⟩ , 分散 σ2 = ⟨x2 ⟩ − ⟨x ⟩2 )に従うとき, lim

n→∞

n∑k=1

xk − µ√nは平均 0, 分散 σ2 の正規分布 (ガウス分布)に収束する (中心極限定理 )。証

明は 31ページ。• x = (x1, x2, · · · , xn), y = (y1, y2, · · · , yn) の確率密度をそれぞれ ρ(x), ρ(y) とする。xk = xk(y)

の場合

ρ(x) dx1 · · · dxn = ρ(y) dy1 · · · dyn , dy1 · · · dyn =

∣∣∣∣ ∂(y1, · · · , yn)∂(x1, · · · , xn)

∣∣∣∣ dx1 · · · dxnである。∂(y1, · · · , yn)/∂(x1, · · · , xn) はヤコビアンである。これから

ρ(x) = ρ(y)

∣∣∣∣ ∂(y1, · · · , yn)∂(x1, · · · , xn)

∣∣∣∣ , 1変数の場合 ρ(x) = ρ(y)

∣∣∣∣dydx∣∣∣∣ (8.1)

になる。特に,ρ(y) が [ 0, 1 ]n で一様分布ならば ρ(y) = 1 である。• 独立な x1, x2 の確率密度を ρ1(x1) , ρ2(x2) とするとき,x = x1 + x2 の確率密度 ρ(x) は

ρ(x) =

∫ ∞

−∞dx1 dx2 ρ1(x1)ρ2(x2)δ(x1 + x2 − x) =

∫ ∞

−∞dx1 ρ1(x1)ρ2(x− x1) (8.2)

である。x1, x2 が ρ1, ρ2 で分布する乱数のとき,x1 + x2 は ρ(x) で分布する。• 区間 [ 0, 1 )の一様乱数の生成以下の関数を使うには #include <stdlib.h> , time()の場合 #include <time.h>

1. #define drand() ((double)random()/(RAND_MAX+1.))

として drand() を使う ( RAND_MAX= 231 − 1 )。16×(231 − 1) ≈ 3.4×1010 個の異なる擬似乱数を生成する。初期化は void srandom(unsigned int) で行う。ソースの最初で 1度だけsrandom((unsigned int)time(NULL)) とすると,プログラム実行ごとに異なる乱数になる。

2. double drand48(void), 初期化は void srand48(long int) で行う。248 ≈ 2.8×1014 個の異なる乱数を生成する。

モンテカルロ法の適用例として区間 [ 0, 1 ] の積分を考える。この区間を M 個に等分割すると

I =

∫ 1

0

dq f(q) ≈ 1

M

M−1∑i=0

f(qi) , qi =i

M

である。x1, x2, · · · , xN を区間 [ 0,1 ]での一様乱数とする。qi < xk < qi+1 である xk は N/M 個存在する。この xk を xij で表す ( j = 1, 2, · · · , N/M)。M が十分大きければ f(xij) ≈ f(qi) になるから

I ≈ 1

M

M−1∑i=0

1

N/M

N/M∑j=1

f(xij) =1

N

M−1∑i=0

N/M∑j=1

f(xij) =1

N

N∑k=1

f(xk) (8.3)

である。n次元の領域 V = [ 0, 1 ]n での積分は

I =

∫V

dnx f(x) ≈ 1

N

N∑k=1

f(x(k)1 , · · · , x(k)n

)になる。ここで x

(k)1 , · · · , x(k)n は独立に選んだ区間 [ 0, 1 ]の一様乱数であり Nn個の乱数を生成する。

Page 30: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

8 モンテカルロ法 29

問 8.1 3次元の半径 1の球の体積は

I = 8

∫ 1

0

dxdydz f(x, y, z) ≈ 8

N

N∑k=1

f(xk, yk, zk) , f(x, y, z) = θ(1− x2 − y2 − z2

)である。I を求めよ。

特定の分布をする乱数区間 [ a, b ] で ρ(x) で分布するN 個の乱数 x(k) を考える。a ≤ x ≤ b を間隔∆x で等分し

ρN (x) =[x−∆x/2, x+∆x/2 ]の x(k)の個数

N∆x

とする。x = a+ n∆x のとき (n− 1/2)∆x ≤ x(k) − a < (n+ 1/2)∆x より

ρN (a+ n∆x) =Nn

N∆x, Nn =

x(k) − a∆x

+1

2の整数部分が nになる x(k)の個数 (8.4)

端点の場合 2Nn/(N∆x) にする。N →∞ , ∆x→ 0 で ρN (x)→ ρ(x) になる。(8.3)と同様にして∫ b

a

dx f(x)ρ(x) ≈∑n

f(a+ n∆x)ρN (a+ n∆x)∆x =1

N

∑n

f(a+ n∆x)Nn ≈1

N

N∑k=1

f(x(k)

)である。

逆関数法確率密度 ρ(x) , a ≤ x ≤ b のとき

y(x) =

∫ x

a

dx′ρ(x′) ,

∫ b

a

dx′ρ(x′) = 1 (8.5)

とする。(8.1)より [ 0, 1 ]の一様乱数 y に対して ( ρ(y) = 1 ),y = y(x) で決まる x は ρ(x) で分布する。逆関数法は x = x(y) が簡単に求まる場合に適用できる。

問 8.2 ρ(x) = λe−λx , λ > 0 , 0 ≤ x <∞ の場合

y =

∫ x

0

dx′ρ(x′) = 1− e−λx , ∴ x = − log(1− y)λ

または x = − log y

λ

0 2 40

0.5

1

N = 104 ∆x = 0.05である。(8.4)の ρN (x)と ρ(x)を図示して比較せよ。右図は λ = 1 の場合である。曲線は ρ(x) = e−x を示す。

1

N

N∑k=1

xnk ≈∫ ∞

0

dxxnρ(x) =n!

λn

を確かめよ。

正規分布 (ガウス分布)

平均 µ, 分散 σ2 の正規分布

ρ(x) =1√2πσ2

exp

(− (x− µ)2

2σ2

), −∞ < x <∞ (8.6)

の場合,(8.5)の y(x) はエラー関数になり x = x(y) を求めることは複雑である。別の方法を考える。

Page 31: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

8 モンテカルロ法 30

yk を [−1, 1 ] の一様乱数とし

x =

√3

n∑k=1

yk + µ =1√n

n∑k=1

Yk + µ , Yk =√3σyk (8.7)

とする。|x− µ | ≤ √3nσ である。⟨ yk ⟩ = 0 , ⟨ y2k ⟩ = 1/3 であるから ⟨Yk ⟩ = 0 , ⟨Y 2k ⟩ − ⟨Yk ⟩2 = σ2

になる。n≫ 1 の場合,中心極限定理より x− µ の分布は近似的に平均 0, 分散 σ2 の正規分布になるから,x の分布 ρ(n)(x) は平均 µ, 分散 σ2 の正規分布 (8.6)になる。上の方法は多数の一様乱数が必要で効率が悪い。これを回避する方法にボックス・ミューラー法がある。r, θ を [ 0, 1 ]での一様乱数として ( ρ(r, θ) = 1 )

x =√− 2σ2 log r cos(2πθ) + µ , y =

√− 2σ2 log r sin(2πθ) + µ (8.8)

とする。0 ≤√− log r <∞, 0 ≤ 2πθ ≤ 2π であるから,(x, y) は平面上の任意の点になる。

r = exp

(− (x− µ)2 + (y − µ)2

2σ2

), tan(2πθ) =

y − µx− µ

よりρ(x, y) = ρ(r, θ)

∣∣∣∣ ∂(r, θ)∂(x, y)

∣∣∣∣ = e−(x−µ)2/2σ2

√2πσ2

e−(y−µ)2/2σ2

√2πσ2

になるから,x, y は独立にガウス分布する。ボックス・ミューラー法は 2個の一様乱数から 2個の正規乱数を生成するが,log と三角関数の計算が必要になる。三角関数の計算を回避する方法もある。

問 8.3 n = 2 と n = 12 の場合,問 8.2と同様に ρ(n)N (x) を図示し (8.6)と比較せよ。ρ(2)(x) が二等辺

三角形の分布になることを (8.2)より示せ。(8.8)と n = 12の (8.7)と計算速度を比較せよ。

棄却法逆関数法の適用が困難な ρ(x) , a ≤ x ≤ b に対して,f(x) ≥ ρ(x) である簡単な関数 f(x) を考える。

F (x) =

∫ x

a

dx f(x) , Fmax =

∫ b

a

dx f(x) , Fmax >

∫ b

a

dx ρ(x) = 1

とする。逆関数法より [ 0, Fmax ]の一様乱数を u とすると,u = F (x) である x の分布は f(x) になる。v を [ 0, 1 ]の一様乱数とするとき,ρ(x)/f(x) ≥ v を満たす x だけ採用する。(x, vf(x)) は a ≤ x ≤ b ,0 ≤ y ≤ ρ(x) に一様に分布するから,ランダムな点を [x, x+ dx ] に見出す確率は ρ(x) dx になる。したがって,ρ(x) で分布する乱数が求まる。

問 8.4 ガンマ分布 ρ(x) = xne−x/n! を考える (x ≥ 0 , n = 0, 1, · · · )。an =√2n+ 1 として

f(x) =ρ(n)

1 + (x− n)2/a2n, Fmax =

∫ ∞

0

dx f(x) = anρ(n)(π/2 + θ

), θ = tan−1 n

an

でローレンツ分布する x は,y を [ 0, 1 ]の一様乱数とすると

x = an tan((π/2 + θ

)y − θ

)+ n

になることを示せ。f(x) ≥ ρ(x) である。棄却法により ρ(x) で分布する乱数を生成する。棄却前の乱数が f(x), 棄却後の乱数が ρ(x) で分布することを確かめよ。なお,yk を [ 0, 1 ]の一様乱数とするとき x = − log

(y1y2 · · · yn+1

) は ρ(x) で分布する。

メロトポリス法一般に n次元の確率密度 ρ(x) で分布する点列 x(1), x(2), · · · の発生方法を考える。x(1) を適当に与えたとき,x(k) から x(k+1) を次のようにして決める。x(k) を中心とした 1辺 2 δx の箱 V を考え

x′ = x(k) + δx(2y − 1

), yi =独立な [ 0, 1 ]の一様乱数

Page 32: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

8 モンテカルロ法 31

とする。x′ は V に一様に分布する。r = ρ(x′)/ρ(x) とするとき

r ≥ 1 のとき x(k+1) = x′ , r < 1 のとき確率 r で x(k+1) = x′

にする。[ 0, 1 ]の一様乱数 v が r ≥ v になる確率は,r ≥ 1 のとき 1 , r < 1 のとき r であるから

r = ρ(x′)/ρ(x) ≥ v のとき x(k+1) = x′ , ρ(x′)/ρ(x) < v のとき x(k+1) = x(k) (8.9)

である。ρ(y) > ρ(x) の場合を考える ( ρ(y) < ρ(x) の場合も同様 )。x近傍の乱数の個数を N(x) とする。

x→ y になる確率は 1,y → x になる確率は ρ(x)/ρ(y) であるから

x→ y に移動する乱数 N(x) , y → x に移動する乱数 N(y)ρ(x)

ρ(y)

したがって x→ y に移動する正味の個数は

N(x)−N(y)ρ(x)

ρ(y)= N(y)

(N(x)

N(y)− ρ(x)

ρ(y)

), ∴ N(x)

N(y)≷ ρ(x)

ρ(y)のとき x ⇄ y に移動

これから,最終的には N(x)/N(y) = ρ(x)/ρ(y) になり N(x) は ρ(x) で分布する。メトロポリス法では δx のとり方が問題になる。δx が小さいと棄却 (x(k+1) = x(k) )回数は少ないが,x(k) が x(1) から離れる確率は低くなり,効率よく ρ(x) を生成できない。一方,δx が大きすぎると棄却回数が多くなり,やはり非効率である。目安としては,棄却率が 1/2程度になる δx である。

問 8.5 (8.9)をN 回繰り返して 1次元の正規分布する乱数 x を生成する。問 8.2と同様の分布図を求め,δx依存性を調べよ。

中心極限定理の証明xk の確率密度 ρ(x) をフーリエ変換して

ρ(x) =1

∫ ∞

−∞dq eiq(x−µ)φ(q) , φ(q) =

∫ ∞

−∞dx eiq(µ−x)ρ(x)

とする。全確率は 1 であるから φ(0) = 1 になる。また

φ′(q) =

∫ ∞

−∞dx i

(µ− x

)eiq(µ−x)ρ(x) , φ′′(q) = −

∫ ∞

−∞dx(µ− x

)2eiq(µ−x)ρ(x)

より φ′(0) = iµ− i⟨x ⟩ = 0 , φ′′(0) = µ2 − ⟨x2 ⟩ = −σ2 であるから φ(q) = 1− σ2q2/2 + · · · になる。y =

(x− µ

)/√n とすると

ρ(y) =dx

dyρ(x) =

√nρ(x) =

√n

∫ ∞

−∞dq ei

√n qyφ(q) , ∴

∫ ∞

−∞dy e−ipyρ(y) = φ

(p/√n)

である。(8.2)より X = y1 + · · ·+ yn の確率密度は

ρ(X) =

∫ ∞

−∞dy1 · · · dyn ρ(y1) · · · ρ(yn) δ

(X −

∑k

yk)

=

∫ ∞

−∞dy1 · · · dyn ρ(y1) · · · ρ(yn)

1

∫ ∞

−∞dp exp

(ipX − ip

∑k

yk

)=

1

∫ ∞

−∞dp eipX

(∫ ∞

−∞dy e−ipyρ(y)

)n

=1

∫ ∞

−∞dp eipX

(φ(p/√n))n

Page 33: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

8 モンテカルロ法 32

になる。(φ(p/√n))n

=

(1− σ2p2

2n+ · · ·

)n

, ∴ ρ(X)n→∞−−−−→ 1

∫ ∞

−∞dp eipXe−σ2p2/2 =

e−X2/2σ2

√2πσ2

である。

無限に深い井戸型ポテンシャルの基底状態エネルギー

H = − ℏ2

2M

d2

dx2, 0 < x < L のとき

ψ(x, t) = e−Ht/ℏψ0(x) , ψ0(0) = ψ0(L) = 0 , 0 < x < L では ψ0(x) > 0

とする。H の固有値 En の固有関数を φn(x) とすると ( E0 < E1 < · · · )

ψ0(x) =

∞∑n=0

Cnφn(x) , Cn =

∫ L

0

dxφ∗n(x)ψ0(x)

と展開できるから

P (t) ≡ 1

L

∫ L

0

dxψ(x, t) =

∞∑n=0

Dne−Ent/ℏ t→∞−−−−→ D0e

−E0t/ℏ , Dn =Cn

L

∫ L

0

dxφn(x)

になる。ψ0(x) は基底状態 φ0(x) と直交しないから D0 > 0 にできる。logP (t) を t の関数としてプロットしたとき,直線の傾きから基底状態のエネルギー E0 が求まる。ψ(x, t) は ℏ ∂tψ = −Hψ の解である。これを無次元の変数 q = x/L , τ = ℏt/(ML2) で表すと

∂ψ(q, τ)

∂τ=

1

2

∂2ψ(q, τ)

∂q2, ψ(0, τ) = ψ(1, τ) = 0 (8.10)

である。この方程式の解析解は求まるが,ここでは使わない。∆τ ≪ 1 のとき

ψ(q, τ +∆τ) ≈ 1√2π∆τ

∫ 1

0

dq′ exp

(− (q − q′)2

2∆τ

)ψ(q′, τ) (8.11)

になる。実際,∆τ ≪ 1 の場合 q′ ≈ q近傍だけが寄与するから,テイラー展開

ψ(q′, τ) = ψ(q, τ) +√2∆τ uψ′(q, τ) +∆τ u2ψ′′(q, τ) + · · · , u =

q′ − q√2∆τ

を代入すると

ψ(q, τ +∆τ) =1√π

∫ u1

−u0

du e−u2(ψ(q, τ) +

√2∆τ uψ′(q, τ) +∆τ u2ψ′′(q, τ) + · · ·

)ただし u0 = q/

√2∆τ , u1 = (1− q)/

√2∆τ である。0 < q < 1 のとき u0, u1

∆τ→0−−−−→∞ より

ψ(q, τ +∆τ) = ψ(q, τ) +∆τ

2ψ′′(q, τ) + · · ·

になり (8.10)を満たす。ψ(0, τ) = ψ(1, τ) = 0 ではないから,q ≤ 0, q ≥ 1 では ψ(q, τ) = 0 とする。ψ(q, τ) で分布するNτ 個の乱数を qk とする ( 0 < qk < 1 )。ψ(q, τ) は規格化されていないから

P (τ) = CNτ , C = τに依存しない定数

である。ψ0(q) で分布する乱数が N0 個のとき,C = 1/N0 とすれば P (0) = 1 になる。(8.11) のψ(q, τ +∆τ) は,平均 0, 分散∆τ の正規分布と分布 θ(q)θ(1− q)ψ(q, τ) の畳み込みである。(8.2)より

Qk = qk +√∆τ vk , vk =平均 0, 分散 1の正規乱数

Page 34: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

8 モンテカルロ法 33

は ψ(q, t+∆τ) で分布する。Qk ≤ 0, Qk ≥ 1 の Qk を棄却すると P (τ +∆τ) =Qkの個数

N0である。

logP (τ)τ→∞−−−−→ −E0t/ℏ+ const. = − ε0τ + const. , ε0 =ML2E0/ℏ2

になる。解析解は ε0 = π2/2 である。n が奇数のとき φn(x) の 0 ≤ x ≤ L での積分は 0 になるから

P (t) = D0e−E0t/ℏ

(1 +

D2

D0e−(E2−E0)t/ℏ + · · ·

), En = (n+ 1)2E0

したがって(E2 − E0)t

ℏ=

τ

τ0≫ 1 , τ0 =

1

8ε0=

1

4π2≈ 0.025

では P (t) ≈ D0e−E0t/ℏ になる。

問 8.6 ψ0(q) = 1 とする。この分布をする乱数は [ 0, 1 ]の一様乱数である。ε0 と ψ(q, τ) を求め,解析解と比較せよ。下図に波動関数を示す。曲線は φ0(q) = (π/2) sinπq である。

N0 = 105 ∆τ = 10−4 ∆q = 0.02

• τ = 0.12 × τ = 0.01

0 0.5 10

1

2

ψ(q,τ)

q

Page 35: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 A 数値計算の結果を図で表わす:TEXの tpic special 34

付録 A 数値計算の結果を図で表わす:TEXの tpic special

数値計算の結果を図で表わすにはいろいろな方法があるが, ここでは TEXの tpic Y=special を用いて表現しよう。TEXについては当面何も知らなくてよい。以下のようなテキストファイル (拡張子はtex )を作成する (数値結果を出力する場合, 計算プログラム自体に texファイルを作成させる)。なお,

円記号 Y= とバックスラッシュ \ は同じである。� �Y=documentclass{jarticle}Y=begin{document}Y=unitlength 0.001inY=begin{picture}(x_size,y_size)(x_move,y_move)この間にtpic命令が入るY=end{picture}Y=end{document}� �

x_size, y_size, x_move, y_moveは数値である。tpicでは長さの単位はミリインチであるため, TEX側の単位もミリインチを指定する ( Y=unitlength 0.001in )。picture命令は横幅 x_sizeミリインチ,

縦 y_sizeミリインチの図を挿入するための領域を確保する。x_move と y_move は図全体の位置を移動するためのパラメータである。x_move は左方向に x_moveミリインチ, y_move は下方向に y_move

ミリインチずらす (負の値を指定すると逆方向にずれる)。例えば, 次のような内容の test.tex というファイルを作成する。� �Y=documentclass{jarticle}Y=begin{document}Y=unitlength 0.001inY=begin{picture}(1100,600)(0,-550)Y=special{pn 20}%Y=special{pa 0 0}%Y=special{pa 1000 0}%Y=special{pa 1000 500}%Y=special{fp}%Y=special{pn 8}%Y=special{pa 1000 500}%Y=special{pa 0 500}%Y=special{pa 0 0}%Y=special{fp}%Y=end{picture}Y=end{document}� �

pn, pa, fp が tpic の命令でY=special{tpic命令 必要ならパラメータ}%

という形式である。tpic命令の具体的意味は次節を参照せよ。test.tex を LATEXで処理する。処理法はシステムで異なる。Windows ならばコマンド・プロンプト ( MS–DOSプロンプト )を起動し

platex test

と入力して Enterキーを押す。拡張子 .texは省略できる。各種のファイルが新たに作成されるが, 拡張子が dvi というファイルに出力イメージが格納されている。今の場合 test.dvi である。dviファイルはテキストファイルではないので, 出力イメージを画面上で見るためにはプレビュアと呼ばれるプログラムを起動する。Windowsの場合 dviout.exe である。画面左上に右図が現れるはずである。

Page 36: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 A 数値計算の結果を図で表わす:TEXの tpic special 35

曲線の表現 xmin ≤ x ≤ xmax , ymin ≤ y ≤ ymax の範囲を横 xsize, 縦 ysizeミリインチの領域にマップしよう。tpic座標では x軸は右が正, y軸は下向きが正方向である (次節参照)。したがって

(xmin, ymin) −→ (0, ysize) , (xmax, ymax) −→ (xsize, 0)

となればよいから, 点 (x, y) の tpic座標 (X,Y ) は

X =xsize

xmax − xmin(x− xmin) , Y = ysize− ysize

ymax − ymin(y − ymin) (付録 A.1)

である。曲線 y = f(x) ( a ≤ x ≤ b ) を描くには, 区間 [a, b] を n等分して, n+ 1個の点(xk, f(xk)

), xk = a+

b− an

k ( k = 0, 1, 2, · · · , n )

を tpic座標に変換しこれらを直線で結ぶ。n をある程度大きくとれば曲線に見える。次ページの Cプログラムは f(x) = sinx sin 9x と g(x) = exp(− x) cos 9x を図示する TEXファイル

sin.tex を出力する。このファイルを LATEXで処理すると下図を得る。Cプログラムのファイルはhttp://physics.s.chiba-u.ac.jp/~kurasawa/fig_tpic.c

にある。

0.5 1.0 1.5 2.0 2.5 3.0

この例では, 横 5インチ, 縦 2インチの領域に幅 20ミリインチの実線で f(x), 破線で g(x) を描き, x軸と y軸を幅 8ミリインチの直線で描く。上の曲線は各々 100個の線分からなる。• 関数 tp_conv は (付録 A.1)式に従い x, y を tpic座標に変換する。return では 1つの値しか返せないので, ここでは tpic座標 (X,Y ) の 2つのポインタを引数にしている。• tp_line は 2点 (x1, y1), (x2, y2) を結ぶ線分を引く。また, tp_func は配列 x[], y[] が与えられたとき, 点 (x[imin], y[imin]), · · · ,(x[imax],y[imax]) を線分で結ぶ。tp_line, tp_func では描画命令を文字列 fmt に与える。例えば, 実線なら "fp" である。• 図に文字列を貼り付けるには, picture 環境の Y=put 命令を使う。Y=put 命令の原点と tpic 原点は同じだが, y 軸の向きは逆である。したがって, tpic 座標 (X,Y ) に文字列を表示するにはY=put(X, −Y ){文字列} とする。ただし, Y=unitlength=0.001in として, picture環境での長さの単位をミリインチにしておく。• Cの文字列中では Y= と % はエスケープキャラクタであり特別な意味をもつ。Y= , % それ自身はそれぞれ Y=Y= , %% で表わす。

• TEXは改行を space 1つと解釈することがある。これを行わせないため, Y=specail{ }% として行末に % を付加し, 継続行としてある。

Page 37: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 A 数値計算の結果を図で表わす:TEXの tpic special 36

� �#include <stdio.h>

#include <math.h>

#include <stdlib.h>

#ifndef PI

#define PI 3.14159265358979323846

#endif

#define NMAX 100

void tp_conv( double x, double y, double *tpx, double *tpy );

void tp_pa( double x, double y );

void tp_line( double x1, double y1, double x2, double y2, char *fmt );

void tp_func( double *x, double *y, int imin, int imax, char *fmt );

FILE *fp_tpic;

double xd[NMAX+1], yd1[NMAX+1], yd2[NMAX+1];

double cx, cy, xmin, ymin, ysize;

int main()

{

double h, x, y, xmax, ymax, xsize, tpx, tpy;

int k;

char *filename, string[128];

xmin = 0;

xmax = PI;

ymin = -1;

ymax = 1;

h = ( xmax - xmin )/NMAX;

for(k=0; k<=NMAX; k++){

xd[k] = xmin + h*k;

yd1[k] = sin(xd[k])*sin(9*xd[k]);

yd2[k] = exp( -xd[k] )*cos(9*xd[k]);

}

/********* TeX出力 **********/

xsize = 5000;

ysize = 2000;

cx = xsize/( xmax - xmin );

cy = ysize/( ymax - ymin );

filename = "sin.tex";

fp_tpic = fopen(filename,"w");

fprintf(fp_tpic,"Y=Y=documentclass{jarticle}Y=n");

// fprintf(fp_tpic,"Y=Y=usepackage[dvips]{color}Y=n");

// fprintf(fp_tpic,"Y=Y=ExecuteOptions{usenames}Y=n");

fprintf(fp_tpic,"Y=Y=begin{document}Y=n");

fprintf(fp_tpic,"Y=Y=unitlength 0.001inY=n");

fprintf(fp_tpic,"Y=Y=begin{picture}(5000,2000)(0,-2000)Y=n");

/******* 関数描画 ******/

fprintf(fp_tpic,"Y=Y=special{pn 16}%%Y=n");

tp_func( xd, yd1, 0, NMAX, "fp" );

tp_func( xd, yd2, 0, NMAX, "da 0.05 0.05" );

// tp_func_color( xd, yd1, 0, NMAX, "fp", 1, 0, 0 );

// tp_func_color( xd, yd2, 0, NMAX, "fp", 0, 1, 0 );

// tp_func_ncolor( xd, yd1, 0, NMAX, "fp", "Cyan" );

// tp_func_ncolor( xd, yd2, 0, NMAX, "fp", "VioletRed" );

/******** 座標軸 *******/

fprintf(fp_tpic,"Y=Y=special{pn 8}%%Y=n");

tp_line( xmin, 0., xmax, 0., "fp" ); /*** x-軸 ***/

tp_line( 0., ymin, 0., ymax, "fp" ); /*** y-軸 ***/� �

Page 38: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 A 数値計算の結果を図で表わす:TEXの tpic special 37

� �for(k=1; k<=6; k++ ){ /*** x-軸目盛り ***/

x=0.5*k;

y=0;

tp_line( x, -0.05, x, 0.05, "fp" );

tp_conv( x, y, &tpx, &tpy );

fprintf(fp_tpic,"Y=Y=put(%.0f,%.0f){Y=Y=large$%.1f$}%%Y=n",

tpx-100, -tpy-200, x );

}

fprintf(fp_tpic,"Y=Y=end{picture}Y=n");

fprintf(fp_tpic,"Y=Y=end{document}Y=n");

fclose(fp_tpic);

/********* pLaTeX 実行 ********/

sprintf(string,"platex %s", filename );

system(string);

return 0;

}

void tp_conv( double x, double y, double *tpx, double *tpy )

{

*tpx = cx*( x - xmin );

*tpy = ysize - cy*( y - ymin );

}

void tp_pa( double x, double y )

{

double tpx, tpy;

tp_conv( x, y, &tpx, &tpy );

fprintf(fp_tpic,"Y=Y=special{pa %.0f %.0f}%%Y=n",tpx, tpy);

}

void tp_line( double x1, double y1, double x2, double y2, char *fmt )

{

tp_pa( x1, y1 );

tp_pa( x2, y2 );

fprintf(fp_tpic,"Y=Y=special{%s}%%Y=n", fmt );

}

void tp_func( double *x, double *y, int imin, int imax, char *fmt )

{

int i;

for( i=imin; i<=imax; i++ )

tp_pa( x[i], y[i] );

fprintf(fp_tpic,"Y=Y=special{%s}%%Y=n", fmt );

}� �カラーcolorパッケージを使うと文字や曲線に色を付けて出力できる。色の指定には幾つか方法がある。• 色指定を赤 (red), 緑 (g), 青 (b) の強度指定で行う。tpic の出力コマンド ( fp, da 等 ) 前にY=textcolor[rgb]{cr,cg,cb} を挿入して, 例えば

Y=textcolor[rgb]{0.5,0.9,0.8}{Y=special{fp}}

とする。cr, cg, cb は 0 から 1 の間の数値で, 基本的な色の組み合わせ (cr, cg, cb) は黒 (1, 1, 1),

青 (0, 0, 1), 赤 (1, 0, 0), 緑 (0, 1, 0), 水色 (0, 1, 1) などである。上のサンプルプログラムで

Page 39: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 A 数値計算の結果を図で表わす:TEXの tpic special 38

// fprintf(fp_tpic,"Y=Y=usepackage[dvips]{color}Y=n");

のコメントを外し, tp_func を下記のものに置き換えてみよ。� �void tp_func_color( double *x, double *y, int imin, int imax, char *fmt,

double r, double g, double b )

{

int i;

for( i=imin; i<=imax; i++ )

tp_pa( x[i], y[i] );

fprintf(fp_tpic,"Y=Y=textcolor[rgb]{%f,%f,%f}{%%Y=n", r, g, b );

fprintf(fp_tpic,"Y=Y=special{%s}%%Y=n", fmt );

fprintf(fp_tpic,"}%%Y=n" );

}� �• colorパッケージで定義済みの 68色を使う。Y=textcolor[rgb]{...}{...} の代わりに

Y=textcolor[named]{定義済みの色}{...}

とする。� �void tp_func_ncolor( double *x, double *y, int imin, int imax, char *fmt,

char *color )

{

int i;

for( i=imin; i<=imax; i++ )

tp_pa( x[i], y[i] );

fprintf(fp_tpic,"Y=Y=textcolor[named]{%s}{%%Y=n", color );

fprintf(fp_tpic,"Y=Y=special{%s}%%Y=n", fmt );

fprintf(fp_tpic,"}%%Y=n" );

}� �使いたい色名を文字列で指定する。例えば, GreenYellow を使いたければ

tp_func_ncolor( ..... , "GreenYellow" );

である。定義済みの色名については dviout に含まれる color.dvi を参照。

GreenYellow Yellow Goldenrod Dandelion Apricot

Peach Melon YellowOrange Orange BurntOrange

Bittersweet RedOrange Mahogany Maroon BrickRed

Red OrangeRed RubineRed WildStrawberry Salmon

CarnationPink Magenta VioletRed Rhodamine Mulberry

RedViolet Fuchsia Lavender Thistle Orchid

DarkOrchid Purple Plum Violet RoyalPurple

BlueViolet Periwinkle CadetBlue CornflowerBlue MidnightBlue

NavyBlue RoyalBlue Blue Cerulean Cyan

ProcessBlue SkyBlue Turquoise TealBlue Aquamarine

BlueGreen Emerald JungleGreen SeaGreen Green

ForestGreen PineGreen LimeGreen YellowGreen SpringGreen

OliveGreen RawSienna Sepia Brown Tan

Gray Black White

Page 40: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 A 数値計算の結果を図で表わす:TEXの tpic special 39

tpic 2.2 コマンドセット仕様TEXが保持している「ページ上の現在位置」を原点にとり, x軸は右が正、y軸は下が正方向になる ( y

軸は picture環境と逆向き )。座標は整数で表し, 単位はミリインチ。角度は時計回りが正で, ラジアン単位で記述する。pn s 線幅を s ミリインチに設定する。pa x y 点 (x, y) をパスに付け加える。x と y の単位はミリインチ。fp それまでに定義したパスを現在の線幅で実際に描く。パス内の点の数はゼロにリセット。シ

ェーディングが設定され, かつパスが閉じていれば, パス内部を塗りつぶす。ip fp と同じだがパスを描かない。シェーディングは条件が満たされれば行う。da f パスを破線で描く。f は実数でダッシュ当たりの長さ (インチ単位)。dt f パスを点線で描く。f は実数で点の間隔 (インチ単位)。sp d パスをスプライン曲線で描く。d は実数で, 曲線の種類を指定する。d = 0 か d が省略され

た場合, 実線で描く。d > 0 の場合, 破線で描く。d はダッシュの長さ。d < 0 の場合, 点線で描く。−d は点間隔。

ar x y rx ry s e

中心 (x, y) の弧を描く。s は開始角度, e は終了角度である。完全な円か楕円である場合は,

rx, ry はそれぞれ x, y 半径を表す。そうでない場合は rx = ry であり, s から e へ弧を描く。条件が満たされればシェーディングも行う。x, y, rx, ry の単位はミリインチ。

ia x y rx ry s e

これは ar と同じだが, 弧は描かず, 条件が満たされればシェーディングのみ行う。sh s シェーディングを行なう。このコマンドの次に定義される閉じた図形の内部を塗りつぶす。

s は 0(白)以上 1(黒)以下の実数である。0 < s < 1 のとき, 図形の下のものは消去せずに灰色で塗り加える。s が指定されていなければ 0.5 の値を用いる。シェーディングは図形の内側のみに対して行い, 境界線はそれとは独立に現在の線幅を用いて描かれる。

Windows用プレビュア dviout は以下の拡張機能をサポートしている。一般に dviout以外ではサポートされないので、これらを使用して作成した dviファイルは、互換性の点で問題がある。

daコマンドの拡張da コマンドを拡張し, 複数の引数が取れる。引数は交互に実線部分, 空白部分の長さをインチ単位の実数で指定する。この場合, 破線はこの指定パターンのくり返しで描かれ, パスの各点を「連続に」通過する。例えば

Y=special{da 0.1}% o___ ___ ___o___ ___Y=special{da 0.1 0.1}% o___ ___ ___ o ___ ___Y=special{da 0.1 0.01 0.01 0.01} % 一点鎖線

rt 回転や拡大, 鏡映などの線形変換を施した描画を行う。詳しくは dviout の HELP参照。rt h v

カレントポイントを原点として、以後の全てのテキストおよびグラフィックス出力を横方向にh倍、縦方向に v倍にスケール変換する。負の値も可能。rt 1 1 でリセットrt x y f

以後の全てのテキストおよびグラフィックス出力を (x, y)の回りに角度 f だけ回転させる。rt

x y 0 でリセット。Bz n spコマンドで描画する曲線をベジェ ( n = 0 )またはスプライン ( n = 1 )にする。

Page 41: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 B 数値計算の結果を図で表わす:PostScript 40

付録 B 数値計算の結果を図で表わす:PostScript

PostScript言語は汎用ページ記述言語であり, DTPでは事実上の標準である。通常, PostScript言語を直接プログラミングすることはなく, お絵描きソフトなどのアプリケーションが PostScriptコードを生成する。ユーザは PostScript言語について知る必要はない。しかし, 前節の tpic 程度のことならば, 自分で PostScriptコードを出力するプログラムを書くことは簡単である。ここでは tpic に対応する PostScriptの演算についてまとめておく。これは PostScript全体の極一部である。なお, 他の言語にない PostScript言語の特徴は次の 2点である。• 逆ポーランド法 (後置記法)

数学で用いられる記法には, 演算子 (オペレータ)とその引数 (オペランド)の並び方により, ポーランド法 (前置記法), 中間記法, 逆ポーランド法 (後置記法)がある。ポーランド法は引数列の前に演算子を記す方法で, sin θ, f(x, y) などがポーランド法である。中間記法の典型は四則演算子±, ×, ÷ である。多くのプログラミング言語は, 数学で使われている記法に近い設計がなされ,

引数列の後に演算子くる逆ポーランド法はめったにないが, PostScriptは逆ポーランド法の言語である。a + b は a b add と書き, sin a も a sin と表す (これは電卓で sin を計算するときと同じ)。

• オペランド・スタックPostScriptでは, 演算子への引数の引き渡しにスタックを陽に使う。引数は一旦 1次元配列のスタックに格納される (pushする)。次々に値を追加するとき, 後から格納する値は先に格納した値の上になる。演算子はこのスタックから必要な個数の引数を取り出す (popする)。この時, 原則として一番上にあるものから取り出す。取り出された値はスタックから消去される。演算の実行時に引数がスタックに正しい順序で格納されていればよい。それさえ正しければ, PostScriptのソースコードで演算子と引数の間に関係のない演算子や引数があってもよい。一般に演算の結果はスタックに格納される。

表記形式 引数 1 引数 2 · · · operator 結果 1 結果 2 · · ·。引数, 結果がない場合は - で表す。

座標系デフォルトの座標系は, 原点が左下隅, x 軸は水平右向き, y 軸は垂直上向きである。長さの単位は1 pt = 1/72 inch = 0.3528mm。角度は度単位で正のとき反時計周り。x y translate - 新しい原点を ( x, y ) に移動する。x y scale - x は x軸方向, y は y軸方向の拡大率。デフォルトに対して 72 72 scale とするとイ

ンチ単位になる。θ rotate - 座標系を θ度回転させる。

描画- showpage - カレントページを出力し, ページをクリアして初期化する。- newpath - パスを初期化する。x y moveto - パスに初めてカレントポイントを加える。x y lineto - パスに新しいカレントポイントを加え, 古いカレントポイントと新しいカレントポイ

ントを線分で結ぶ。moveto を実行していない場合エラーになる。x y r θ1 θ2 arc - 中心 ( x, y ), 半径 r の円弧 ( 開始角 θ1, 終了角 θ2) をパスに追加する。カレント

ポイントがあれば, この点から円弧の開始点までの線分も付加する。

Page 42: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 B 数値計算の結果を図で表わす:PostScript 41

- closepath - パスに始点 (movetoで指定した点)とカレントポイントを結ぶ直線を加えてパスを閉じる。

- stroke - 実際にパスに沿って線を描く。色, 線幅, パターンについては次のグラフィック状態を参照。描画後, newpath を実行する。

- fill - カレントカラーでパスで囲まれた領域を塗りつぶし, newpath を実行する。パスが閉じてないときは始点と終点を結ぶ。

グラフィック状態r g b setrgbcolor - カレントカラーを赤 r, 緑 g, 青 b で指定した色にする。パラメータは 0 から

1の範囲。線, 領域, 文字を描く際に用いる色を指定する。x setgray - カレントカラーを x で指定した明度の灰色にする。パラメータは 0(黒) から 1(白)

の範囲である。線, 領域, 文字を描く際に用いる色を指定する。pattern offset setdash - stroke で描く破線を設定する。pattern は [ x1 x2 · · · ] という形式で,

左から右へ順に線, 隙間の長さを表し, 右端にきたら再び左端に戻る。奇数個指定した場合, パターンは逆転する。offset は破線パターンを offset だけ線方向にずらす。実線に戻すには [ ] 0 setdash とする。

x setlinewidth - stroke で描く線の幅を設定する。

フォントfontname findfont font fontname はフォント名に / を付けたもので /Times-Roman など。font は

選択したフォントに関する情報を含む。具体的にどのようなものかは知らなくてよい。スタックに置いておき, 次の scalefont で使う。フォント名については, ファイル Fontmap を見よ。

font s scalefont font フォントの大きさを s にする。font setfont - 指定したフォントをカレントフォントにする。実際のフォント指定は

fontname findfont s scalefont setfont

string show - カレントポイントを印字位置として文字列 string をカレントフォントで出力する。カレントポイントを moveto などで最初に定義しておく必要がある。文字列は括弧で区切る。特殊文字は括弧と Y=。文字列中の括弧は Y=( , Y=) で表す。

簡単な例次のソースを適当なファイル名で保存し GhostScript で表示させてみよ。ただし, % より右側はコメント文である。GhostScriptについては http://www.cs.wisc.edu/~ghost/index.html を参照。Win-

dows用の GhostScriptが入手できる (Freeware)。

線幅を変えながら破線を描く。� �2 setlinewidth % 線幅を2ptにする 。newpath100 100 moveto % ( x, y ) = ( 100, 100 )450 100 lineto % ( x, y ) = ( 450, 100 )stroke % ( 100, 100 )と( 450, 100 )を結ぶ実線を引く 。3 setlinewidth[10 20] 0 setdash % 破線 - - - - の設定newpath 100 140 moveto 450 140 lineto strokeshowpage� �

Page 43: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 B 数値計算の結果を図で表わす:PostScript 42

信号機� �newpath40 40 moveto 360 40 lineto360 160 lineto 40 160 linetoclosepath fill % 黒い長方形(デフォルトは黒)1 0 0 setrgbcolor % 色を赤に設定newpath 100 100 40 0 360 arc % 中心 (100, 100 ), 半径 40 の円fill % 円の内部を赤で塗りつぶす1 1 0 setrgbcolor newpath 200 100 40 0 360 arc fill % 黄色い円0 0 1 setrgbcolor newpath 300 100 40 0 360 arc fill % 青い円showpage� �

フォント� �/Times-Roman findfont 24 scalefont setfont100 100 moveto (Times-Roman) show/Courier findfont 24 scalefont setfont(Courier) showshowpage� �

計算結果を PostScriptで表示する次の Cプログラムは f(x) = sinx sin 9x , g(x) = exp( − x) cos 9x のグラフを描く PostScriptファイル sin.ps を出力する。方法は tpic の場合と同じである。座標 (x, y) から PostScript座標への変換はps_conv で行なう。PostScript座標を (X, Y ) とすると

X =xsize

xmax − xmin(x− xmin) , Y =

ysize

ymax − ymin(y − ymin)

である。ファイル sin.ps を GhostScript で表示してみよ。� �#include <stdio.h>#include <math.h>#ifndef PI#define PI 3.14159265358979323846#endif#define NMAX 100void ps_line( double x1, double y1, double x2, double y2 );void ps_func( double *x, double *y, int imin, int imax );void ps_conv( double x, double y, double *psx, double *psy );FILE *fp_ps;double cx, cy, xmin, ymin, xd[NMAX+1], yd1[NMAX+1], yd2[NMAX+1];int main(){

double h, x, y, xmax, ymax, xsize, ysize, ux, uy;int k;xmin = 0;xmax = PI;ymin = -1;ymax = 1;h = ( xmax - xmin )/NMAX;for(k=0; k<=NMAX; k++){

xd[k] = xmin + h*k;� �

Page 44: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 B 数値計算の結果を図で表わす:PostScript 43

� �yd1[k] = sin(xd[k])*sin(9*xd[k]);yd2[k] = exp(-xd[k])*cos(9*xd[k]);

}/***** PS出力 ****/

xsize = 5*72; /* 横 5inch */ysize = 2*72; /* 縦 2inch */cx = xsize/( xmax - xmin );cy = ysize/( ymax - ymin );fp_ps=fopen("sin.ps","w");fprintf(fp_ps,"50 50 translate 1.5 setlinewidthY=n");ps_func( xd, yd1, 0, NMAX );fprintf(fp_ps,"[5] 0 setdashY=n");ps_func( xd, yd2, 0, NMAX );fprintf(fp_ps,"[ ] 0 setdashY=n");fprintf(fp_ps,"0.5 setlinewidthY=n");ps_line( xmin, 0., xmax, 0 ); /** x-軸 **/ps_line( 0., ymin, 0, ymax ); /** y-軸 **/fprintf(fp_ps,"/Helvetica-Narrow findfont 14 scalefont setfontY=n");for( k=1; k<=6; k++ ){ /** x-軸目盛り **/

x=0.5*k;y=0.;ps_line( x, -0.05, x, 0.05 );ps_conv( x, y, &ux, &uy );fprintf(fp_ps,"%.3f %.3f moveto (%.1f) showY=n",ux-8, uy-18, x );

}fprintf(fp_ps,"showpageY=n");fclose(fp_ps);return 0;

}

void ps_line( double x1, double y1, double x2, double y2 ){

double ux1, uy1, ux2, uy2;ps_conv( x1, y1, &ux1, &uy1 );ps_conv( x2, y2, &ux2, &uy2 );fprintf(fp_ps,"newpath %.3f %.3f %.3f %.3f moveto lineto strokeY=n",

ux2, uy2, ux1, uy1 );}

void ps_func( double *x, double *y, int imin, int imax ){

double ux, uy;int i;ps_conv( x[imin], y[imin], &ux, &uy );fprintf(fp_ps,"newpath %.3f %.3f movetoY=n",ux, uy);for(i=imin+1; i<=imax; i++ ){

ps_conv( x[i], y[i], &ux, &uy );fprintf(fp_ps,"%.3f %.3f linetoY=n",ux, uy);

}fprintf(fp_ps,"strokeY=n");

}

void ps_conv( double x, double y, double *psx, double *psy ){

*psx = cx*( x - xmin );*psy = cy*( y - ymin );

}� �

Page 45: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 B 数値計算の結果を図で表わす:PostScript 44

EPS( Encapsulated PostScript)形式複数の PostScriptファイルを合成する場合の形式として EPS形式がある。EPS形式はPostScriptファイルが他の PostScript ファイルに挿入されたときに副作用を起こさないための規約である。例えば,

showpage があるとその部分でページ出力されてしまうから, EPSファイルは showpage を含んではいけない。また, 色などのグラフィック状態を変更したら元に戻す。そのためには EPSファイルの先頭に gsave, 終わりに grestore を置く。gsave はカレントのグラフィック状態を複製して保存する演算, grestore は gsave で保存したグラフィック状態を回復する演算である。EPSファイルで, 必ず含まなければならないコメント文として

%%BoundingBox: x1 y1 x2 y2

がある。これは EPSファイルの描画領域を指定するコメント文で, x1, y1 は領域の左下の座標, x2, y2

は右上の座標である。TEXファイルに PostScriptの図を挿入するとき, styファイルによっては, このコメント文で図の位置や大きさ合わせをする。EPSファイルの基本形は

%%BoundingBox: x_1 y_1 x_2 y_2gsave

PostScriptコードgrestore

である。

Page 46: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 C Mule( Emacs )のコマンド一覧 45

付録 C Mule( Emacs )のコマンド一覧C-x CTRLキーを押しながら xキーを押す。 M-x ESCキーを押してから xキーを押す。RET Enterキーを押す。 SPC スペース

特殊キー矢印キー ( →, ←, ↑, ↓ ) 1文字移動Insertキー 上書きモード←→ 挿入モードDeleteキー カーソル位置の文字削除 Back spaceキー カーソル位置前の文字削除

ファイル操作などC-x C-f ファイル読み込みC-x C-v 現ファイルと置き換えてファイル読み込み。C-x i 現在位置にファイルを挿入する。C-x C-s ファイルを保存する。C-x C-w バッファを指定ファイルに書き出す。C-x C-c 終了する。C-l 画面描画しカーソルを画面中央に移動C-z 一時停止しコマンドプロンプトに移行する。exit か fg で戻る。C-g 現在のコマンドを中止する。C-h オンラインヘルプに入る。C-x ( キーボードマクロ定義開始。 C-x ) 定義終了 C-x e マクロ実行M-n command command を n回繰り返す。C-u n command command を n回繰り返す。nを指定しないと 4回繰り返す。

カーソル移動C-p 前行へ C-n 次行へ C-b 1文字左へC-f 1文字右へ C-a 行頭へ C-e 行末へM-b ワード単位で戻る。 M-f ワード単位で進む。 M-a センテンス先頭にM-e センテンス末尾に M-> ファイル末尾に M-< ファイル先頭にM-x goto-line ファイル先頭から n行目に移動

削除C-d カーソル位置の文字 M-d カーソル位置からワードの最後C-k カーソル位置から行末 M-0 C-k 行頭からカーソル位置 (0はゼロ)

M-k カーソル位置からセンテンス最後 C-y 直前に削除した内容を復元

カット & ペーストC-@, C-SPC 領域の始端 (終端)をマーク M-h パラグラフをマークC-x h バッファ全体をマーク C-w マークした領域を削除M-w マークした領域のコピー C-y 削除・コピーした部分をペーストC-x C-x カーソルとマークの位置を交換

その他の編集機能M-c ワード先頭を大文字 M-u ワード全体を大文字 M-l ワード全体を小文字M-x overwrite-mode 上書きモード←→ 挿入モード

Page 47: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 C Mule( Emacs )のコマンド一覧 46

ミニバッファTAB 補完 SPC 1ワード補完 ? 補完候補一覧M-p 入力履歴 up M-n 入力履歴 down

検索C-s, C-r 順方向 ( C-s), 逆方向 (C-r)にインクリメンタルサーチを開始。

文字を入力せず RET で単純サーチ。更に C-w でワードサーチ。

C-s, C-r : 次のサーチ文字列を検索。 RET : 終了DEL : サーチ文字列から文字を削除 C-g : 中断して開始位置に戻る。

置換M-x replace-string カーソル位置以降に表れるすべてのワードを確認なしに置換する。

M-% 対話的置換SPC : 置換する n : 置換しない ! : 残りの置換を確認なしに行う M : 終了C-r : リカーシブエディット (置換を中断して編集)

M-C-c : リカーシブエディットを抜け置換再開C-] : リカーシブエディットと置換の両方を抜ける。

マルチプルバッファC-x b バッファ変更 ( TAB でバッファ一覧) C-x k バッファ削除。C-x s 複数バッファのセーブ

マルチウィンドウC-x 0 現ウィンドウ削除 ( 0 はゼロ ) C-x 1 現ウィンドウ以外をすべて削除C-x 2 現ウィンドウを上下に分割 C-x 3 現ウィンドウを左右に分割C-x o 他のウィンドウに移動 C-x 4 f 他ウィンドウにファイル読込みC-x ^ 現ウィンドウを 1行増やす C-x 4 b 他ウィンドウのバッファ変更

シェルM-! Unixコマンドを実行 M-| マークした領域を Unixコマンドに渡して実行M-x shell Unixシェル

C-c C-c ジョブ強制終了 C-c C-z ジョブ一時停止C-c C-y 直前の入力コマンド表示 C-c C-o 直前のコマンド出力削除C-c C-r 直前のコマンド出力の最初に移動

言語モードM-; コメント挿入 M-j コメントを次行に続ける。M C-Y= マーク領域をインデント M-m 行の最初の非ブランク文字に移動M-^ 前行と現在行を結合 C-x ‘ エラー行に移動 ( ‘ はバッククォート )

M-x compile コンパイル

C言語モードM C-a 関数先頭に移動 M C-e 関数末尾に移動 M C-h 関数全体をマーク

Page 48: Kurasawa's Home Page - 数値計算入門kurasawa.c.ooco.jp/compute.pdf付録C Mule( Emacs ) のコマンド一覧 45 ~ はサンプルプログラムにバグがあることを示す。meadow(

付録 C Mule( Emacs )のコマンド一覧 47

YaTEX

プロセスC-c t j コンパイル。実行コマンドは (setq tex-command "platex")等で指定。C-c t r 領域を指定してコンパイルC-c t p プレビューア起動。プレビューアは (setq dvi2-command "dviout")

C-c ’ エラー行に移動。タイプセットバッファでエラー表示行にカーソルを合わせて SPCを押すとエラー行に移動。

%#記法 本文に %#!<command> と書くと <command> をそのまま shellに渡す。例 : %#!latex main.tex

%#BEGIN と %#END で囲むと C-c tr でその領域だけコンパイルできる。

補完C-c b Y=begin{xxx} 型の補完 C-c B マーク領域を Y=begin{xxx} 型で囲むC-c s Y=command{xxx} 型の補完 C-c S マーク領域を Y=command{xxx} にC-c l {Y=command } 型の補完 C-c L マーク領域を {Y=command xxx} にC-c e Y=end 補完 C-c a アクセント記号補完C-c SPC 先頭が Y= で始まる文字列を入力中に補完するC-c e Y=end 補完C-c a アクセント記号補完; 数式モード中で矢印や記号を入力: 数式モード中でギリシャ文字を入力。:aで Y=alpha

コメントアウトC-c > マーク領域をコメントアウト。

カーソルが Y=begin あるいは Y=end にあるときは Y=begin ∼ Y=end をコメントアウトC-c < マーク領域のコメントを外す。

カーソルが Y=begin あるいは Y=end にあるときは Y=begin ∼ Y=end のコメントを外す。C-c . カーソルのあるパラグラフ全体をコメントアウトC-c , カーソルのあるパラグラフのコメントを外す。

ジャンプC-c g 対応する場所にジャンプ。

Y=begin{} ←→ Y=end{} Y=label{} ←→ Y=ref{} Y=bibitem{} ←→ Y=cite{}

Y=include{} −→ 対応するファイルC-c 4 g 対応する場所にジャンプ。ただし、ジャンプ先を別ウィンドウに表示M C-a Y=begin へジャンプM C-e Y=end へジャンプM C-@ Y=begin ∼ Y=end をマーク

その他C-c c 変更したいコマンドにカーソルを合わせて C-c c を押す。C-c k コマンドの削除C-c & tabular, array環境で現在のカラム数を表示M RET tabular, array, itemize, enumerate, tabbing環境でその環境に応じたエントリーを挿入

する。C-c ? オンラインヘルプ。デフォルトではカーソル位置のコマンドについて。C-c / オンライン apropos。入力したキーワードを説明文に含む項目をすべて表示


Recommended