?NumericQを使って計算の順序を変更する方法
NIntegrateやNMaximizeのような数値関数を使うときは,評価の順序が大切です.以下の関数fの例をご覧ください.
f[a_] := NIntegrate[ (2 - a) Sin[a x], {x, 0, Pi}]
関数fは,f[0.5]等の数値について計算でき,明確に定義された関数であるように見えます.しかし,関数fに数ではなく記号が与えられると,問題が発生します.
f[a]
NIntegrate::inumr : 被積分関数(2 - a) Sin[a x]は境界{{0, Pi}}の領域のすべてのサンプル点について,評価後に非数値になりました.
aが定義されていないので,Wolfram言語は式(2 - a) Sin[a x]をxについて数値的に積分することができないのです.これはaに値が与えられる前にf[a]を計算することがある関数すべてで問題となります.例えば,Wolfram言語は関数fを数値的に最大化することはできません.
NMaximize[f[a], a]
NIntegrate::inumr : 被積分関数(2 - a) Sin[a x]は境界{{0, Pi}}の領域のすべてのサンプル点について,評価後に非数値になりました.
このコードもf[a]を評価したときと同じエラーメッセージを生成します.この例では,NMaximize文全体が評価される前にf[a]が評価されます.
評価の順序を変更するには,NumericQとパターンのテストを使って,関数fが数値を受け取った場合にのみこれを評価するように定義します.関数fの引数にパターン?NumericQを付け加えます.
Clear[f]
f[a_?NumericQ] := NIntegrate[ (2 - a) Sin[a x], {x, 0, Pi}]
f[a]を評価すると,エラーメッセージは生成されず,関数は未評価のまま返されます.パターン ?NumericQによって計算の順序が変更されるので,Wolfram言語はfの新しい定義を数値的に最大化することができます.
NMaximize[f[a], a]
{3.05716, {a -> 0.581569}}}
[English]