数値計算のヒント  1/11/27(火)

(改訂: 1/11/28(水))

理論の研究の道具として、数値計算は大変有用であるので、僕は、院生の間に大きな数値計算をすることを推奨している。ところで、数値計算にはバグとか誤差がつきものである。数値計算を始めると、かなりの時間を、バグや誤差との戦いに費やすことになるのが普通である。

数値計算は、僕自身、数値繰り込み(A. Shimizu, H. Aoki and H. Kamimura, J. Phys. C19, 725-738 (1986))とか、 会社にいた頃にやったかなり複雑なデバイスシミュレーション(A. Shimizu and T. Hara, IEEE J. Quantum Electron. QE-23, 293 (1987)) の経験があるものの、それ以外はたいした数値計算をしていないので、専門家ではない。しかし、何人かの人の数値計算を見て来て気付いたのは、僕が犯しそうなミスとは違うパターンの、似たようなミスが目立つことである。似たようなミスを、少なからぬ人たちが、しかも何度も繰り返す、という事実から、これらのミスの対策を公開しておくのが有用だと思うので、ここにまとめておく。

● まず、極端な数字を入れて、もっともらしい結果が出ることを確認せよ

手では解けない/傾向すらわからない、だから数値計算をするのであるが、モデルに出てくるパラメータを極端な値(ゼロとかすごく大きな値)にすれば、手で解けたり、解けなくても傾向が解ったり、摂動で近似解が求まったりするものである。まず、そういう、答えが解っているケースを計算してみて、正しい結果が出てくることを見るのが、基本中の基本である。

● 結果を直感的に解釈せよ

数値計算の結果は、結果が出た後では、たいていは、直感的に解釈できるものである。直感と合わなければ、可能性は3つだ: (1) 数値計算にバグがある。(2) 自分の直感にバグがある。(3) 意外な現象を発見した!まあ、99%のケースでは、(1) か (2) だろうが、それらのバグを取り除くことを繰り返すことによって、数値計算と直感の信頼性が上がっていく。そして、(3) を逃さないためにも、結果を直感的に解釈することが重要である。だって、意外かどうかは、直感的解釈とどれくらい乖離があるかをチェックしてみて初めて解るものだから、それをさぼってしまっては、発見も見逃してしまうでしょ?

● どんなパラメータ領域を調べているのか、常に念頭に置け

学生さんと話していて面食らうのは、結果のグラフを見せてくれるときに、「どんなパラメータ領域でこうなるの?」と質問しても、「えーと、どうだっけな…」という反応が返ってくることが少なからずあることである。このため、ある日の説明では、その結果はパラメーターの値に依存しない普遍的な結果という説明だったのに、翌日には、ちょっとパラメーターを変えてみたら違っちゃいました、なんて報告が来ることさえある。思うに、数値計算をするときに、入力するパラメータの値について、あまり考えていないんじゃないだろうか?パラメーターは、系統的に振り、結果は、パラメーターの値ごとに系統的に整理しましょうね。

● データに相互矛盾がないかチェックせよ

出てきたデータを全て信じるのはやめて、相互矛盾がないかチェックしましょう。それだけで、ずいぶんバグつぶしになります。

● 結果の分析を自動化しすぎるな

数値計算の結果の生データは、膨大な量の数値の集まりであることが多い。そこで、その数値の海の中から、どうやって必要な情報を抜き出すかが問題になる。そのとき、適当に定義した平均値に注目してみたり、いくつかのグループ分けをして比較してみたり、と試行錯誤をするだろう。そういう生データの加工の作業は、計算機に自動的にやらせて、その結果のグラフも計算機に描かせれば楽である。しかし、つい計算機で自動化しすぎて失敗する人が多いように思う。まず、自動化するアルゴリズムを間違える人が少なくない。さらに、アルゴリズムは正しくても、生データを加工するということは、計算結果の一部分だけに着目することに相当する。ところが、数値計算の初期の段階では、まさに、結果のどこに着目すれば良いかを自分で見つけださなければならないのであるから、はじめから特定の方法で加工されたものしか見なかったら、大事な点を見逃す可能性が大きい。従って、最初は、電卓とグラフ用紙を使って、自分の頭であれこれ生データ(あるいは、自動化の途中で出てきたデータ)を分析することも必要なのである。そういう泥臭い、時間のかかる分析の結果をみて、自動化のプログラムを見直すのが良い。ようするに、結果の分析をすべて自動化するのは、計算の最後の段階、パラメータの値をたーくさん振りつつ何回も計算する、という段階になるまで待った方が良い。

● 細かいところは、細かい精度で見よ

データのある部分は1桁の精度で見れば充分かもしれないが、他の部分は3桁目が重要、なんてことはよくある。一カ所だけをみて桁数を決めてしまって分析するようなことのないようにするべし。

● 刻んだら、結果が刻み幅に依存しないことを確認せよ

数値計算では、連続変数を離散変数に離散化して計算することが多い。そうした場合、最低限のチェックとして、刻み幅を変えても結果が変わらないことを確認しなければならない。

● ミスが見つかったら、その原因をきちんと突き止める

ミスが見つかった時、ミスがないバージョンのプログラムができたら、古い方のプログラムのミスの原因を突き止めることをやめてしまう人がいます。つまり、「前のプログラムのどこがいけなかったの?」と訊いても、「さあ、どこだったんでしょう…」という返事しか返ってこない場合があります。しかし、それではまた同じミスを繰り返す危険性が大ですし、新しいプログラムだって、また別のミスがあるかもしれません。ミスの原因は、きちんと突き止め、そこさえ直したら正しい結果が出ることを確認することが大事です。(往々にして、他にもミスがあって、そこだけ直してもダメだったりします。そして、そのミスが新しいプログラムにもある…。)
 

実を言うと、以上のようなことに思いが至らない事が、僕にはひどく予想外であったので、これらのことは当然チェック済みだろうと思いこんでいた。そのために後で慌てたりしたのであるが、ミスのパターンが違うのは、世代の相違なのかな?逆に言えば、僕が犯すミスの中にも、他の人からみたら首をかしげたくなるようなものがあるんだろうなぁ。