?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]