無限評価の防止

式の評価で Mathematica の取る基本操作は,式に変化が見られなくなるまで別の変換規則を適用していくというものである.このため,のような割当て式を入力すると,評価が永久に終らないことになりかねない.そこで,有限回のステップが過ぎると(再帰回数の上限は大域変数$RecursionLimitで決定される)Mathematica は自動的に処理を強制停止するようになっている.もちろん,ユーザは手動でいつでも停止させることができる.

わざと無限ループになる式を入力する.$RecursionLimitの回数以上の評価ステップが繰り返されると処理が停止してしまう.
In[1]:=
Click for copyable input
Out[1]=
評価自体は終っていないので,保留とされた結果が返される.特別にReleaseHoldを呼び出すことで,中断した評価を続行させることも可能である.
In[2]:=
Click for copyable input
Out[2]=
$RecursionLimit評価スタックの深さの上限
$IterationLimitループ等の評価チェーンにおける最大繰返し数

無限評価を防止するための大域変数

わざと循環する定義を作る.この場合,評価は$IterationLimitのループ上限で停止する.
In[3]:=
Click for copyable input
Out[3]=

大域変数$RecursionLimit$IterationLimitは,2つの基本的な繰返し方法を制御し,無限の評価処理が起らないようにするためにある.$RecursionLimitは評価スタックの最大量を決定する.また,Traceのリスト出力におけるネストレベル上限にもこのパラメータが使われる.これに対して,$IterationLimitは1つの評価チェーンの許容する最大ステップ数を決定する.このパラメータは,Traceのリスト出力における単一サブリストの長さにも相当する.

$RecursionLimit$IterationLimit自体のデフォルト値はよくある計算負荷と平均的なコンピュータシステムの能力に合わせて設定してある.ユーザが上限パラメータを他の整数値に変更するのは構わないが,(デフォルトの下限より大きく)無限大Infinityより小さい整数値を指定する.特殊なシステムを使っていない限り,$RecursionLimit=Infinityとは設定してはいけない(「メモリ管理」を参照のこと).

$RecursionLimit$IterationLimitに設定する.
In[4]:=
Click for copyable input
Out[4]=
20回反復して処理が停止する.
In[5]:=
Click for copyable input
Out[5]=
最終条件がないので,この定義を実行すると無限回反復してしまう.
In[6]:=
Click for copyable input
20にしておいても,かなり大きなリストになってしまう.
In[7]:=
Click for copyable input
Out[7]=
反復定義をもう1つ行う.
In[8]:=
Click for copyable input
今度は,複雑な式は何もできない.計算自体は$IterationLimitの上限で停止する.
In[9]:=
Click for copyable input
Out[9]=

注意点として,無限ループを行うとコンピュータのメモリが多量に消費されてしまう.反復処理の上限が$IterationLimitで決定されるような計算では,中間結果として生成される構造体が巨大になるというようなことはない.しかし,$RecursionLimitで上限が決まる計算では,そのようなことがあり得る.再帰的な処理で生成される構造体は$RecursionLimitの上限値に正比例して増大し,計算する式によっては,$RecursionLimitに指数関数的に比例して増えるものもある.

のような式が循環してしまうことは明白である.しかし,再帰的関係が少し込み入ったものになると,いつ計算が終了するかを確実に判断することは難しい.これは,基本的な注意事項だが,変換規則を適用する前には,必ず式の右辺と左辺で記述内容が違っていることを確認する.そうすれば,少なくとも,同じ変換規則を同じ式に繰り返し適用してしまうような初歩的な間違いを防ぐことができる.

まぎらわしいのは,規則がの条件に依存する場合である(の条件は「パターン適用範囲の制限」を参照のこと).その条件が大域変数を参照しているときはさらにまぎらわしくなってしまう.式が変化しなくなりさえすれば,Mathematica にとって評価は終了したことになる.しかし,他の式の評価で大域変数の値が変わってしまい,評価結果が狂ってしまう可能性がある.このような状況を防ぐには,まず,大域変数をの条件では使わないようにする.それでも疑わしい場合は,Update[s]の書式を使い強制的に s を参照している式をすべて更新させる.また,Update[]と入力すれば,すべての式を無差別に更新させることができる.

New to Mathematica? Find your learning path »
Have a question? Ask support »