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

Out[1]= 
評価自体は終っていないので,保留とされた結果が返される.特別にReleaseHoldを呼び出すことで,中断した評価を続行させることも可能である.
In[2]:= ReleaseHold[%]

Out[2]= 

無限評価を防止するための大域変数
わざと循環する定義を作る.この場合,評価は$IterationLimitのループ上限で停止する.
In[3]:= {a, b} = {b, a}


Out[3]= 
大域変数$RecursionLimit,$IterationLimitは,2つの基本的な繰返し方法を制御し,無限の評価処理が起らないようにするためにある.$RecursionLimitは評価スタックの最大量を決定する.また,トレースのリスト出力におけるネストレベル上限にもこのパラメータが使われる.これに対して,$IterationLimitは1つの評価チェーンの許容する最大ステップ数を決定する.このパラメータは,トレースのリスト出力における単一サブリストの長さにも相当する.
$RecursionLimitと$IterationLimit自体のデフォルト値はよくある計算負荷と平均的なコンピュータシステムの能力に合わせて設定してある.ユーザが上限パラメータを他の整数値に変更するのは構わないが,(デフォルトの下限より大きく)無限大Infinityより小さい整数値を指定する.特殊なシステムを使っていない限り,$RecursionLimit = Infinityとは設定してはいけない(2.14.4を参照のこと).
両パラメータの上限を20に設定する.
In[4]:= $RecursionLimit = $IterationLimit = 20
Out[4]= 
20回反復して処理が停止する.
In[5]:= t = {t}

Out[5]= 
最終条件がないので,この定義を実行すると無限回反復してしまう.
In[6]:= fn[n_] := {fn[n-1], n}
20にしておいても,かなり大きなリストになってしまう.
In[7]:= fn[10]

Out[7]= 
反復定義をもう1つ行う.
In[8]:= fm[n_] := fm[n - 1]
今度は,複雑な式は何もできない.計算自体は$IterationLimitの上限で停止する.
In[9]:= fm[0]

Out[9]= 
注意点として,無限ループを行うとコンピュータのメモリが多量に消費されてしまう.反復処理の上限が$IterationLimitで決定されるような計算では,中間結果として生成される構造体が巨大になるというようなことはない.しかし,$RecursionLimitで上限が決まる計算では,そのようなことがあり得る.再帰的な処理で生成される構造体は反復回数の上限値に正比例して増大し,計算する式によっては,上限値に指数関数的に比例して増えるものもある.
x = x + 1のような式が循環してしまうことは明白である.しかし,再帰的関係が少し込み入ったものになると,いつ計算が終了するかを確実に判断することは難しい.これは,基本的な注意事項だが,変換規則を適用する前には,必ず式の右辺と左辺で記述内容が違っていることを確認する.そうすれば,少なくとも,同じ変換規則を同じ式に繰り返し適用してしまうような初歩的な間違いを防ぐことができる.
まぎらわしいのは,規則が/;の条件に依存する場合である(/;の条件は2.3.5を参照のこと).さらに,その条件が大域変数を参照しているときはさらにまぎらわしくなってしまう.式が変化しなくなりさえすれば,Mathematicaにとって評価は終了したことになる.しかし,他の式の評価で大域変数の値が変わってしまい,評価結果がくるってしまう可能性がある.このような状況を防ぐには,まず,大域変数を/;の条件では使わないようにする. それでも疑わしい場合は,Update[s]の書式を使い強制的にsを参照している式をすべて更新させる.また,Update[ ]と入力すれば,すべての式を無差別に更新させることができる.
|