関数の数値処理

数の四則演算
Wolfram言語における数の四則演算は電卓と同様にできる.
2数の和を求める:
/は割り算を,^はベキ乗を表す:
Wolfram言語では空白(スペース)は掛け算と解釈される.数の間のスペースは,フロントエンドにより自動的に灰色の乗算記号に置き換えられる:
乗算には*を使うこともできる:
丸カッコで式をくくることができる:
x^y
ベキ乗
-x
マイナス化
x/y
割り算
x y z
または
x*y*z
掛け算
x+y+z
足し算
四則演算とベキ乗の演算記号
複数の項からなる式がグループ化されているとき,数学で標準的な優先順位に従って計算が行われる.例えば,2^3+4(2^3)+4に等しいが,2^(3+4)には等しくない.丸カッコを使えば計算の優先順位を制御することができる.
結果は科学表記で返される:
科学表記で数を入力することもできる:
このように入力しても同じである:
Wolfram言語では,通常の計算よりも高い特定の精度で計算を実行することができる.厳密な数値が与えられると,Wolfram言語はそれを近似表現に変換せず厳密な結果を与える.
有理数で結果を出力する:
数値結果の近似を与える:
次は数値結果の近似を有効桁数40桁で与える:
Wolfram言語における数値解析
Wolfram言語の最も重要な機能のひとつに計算結果を正確な代数式で得ることができる,ということがある.最も,解く問題によっては答を「閉じた形」で得ることが数学的にできないときもあるが,そのようなときでも,問題を数値解析手法を用い近似的に解くことは可能である.
は「閉じた形」では解けない.このため,シンボル的な形で積分が返ってくる:
それでも,シンボル的な積分をもとに数値解析で近似値を求めることができる:
定積分のような計算で具体的な結果が見出せなかった場合,結果はシンボル的な記述形で返される.そして,求まったシンボル式にNを適用させることで数値解析で近似解を求めることができる.
Nの第2引数として数値計算の桁精度が指定できる:
積分を数値解析で求めるとき,Integrateを使って求めた積分にNを適用させるといった手順はあまり効率がよいとは言えない.代数的な解法はせずに,始めから関数NIntegrateを使い直接数値的な答を得る方がよい.Integrateを使うと積分が解けないときでも解けないという結果が出るまでそれなりの時間を費やしてしまう.
代数的には解かずに,NIntegrateを使い直接数値解析的に積分する:
IntegrateNIntegrate
定積分
SumNSum
和,総和
ProductNProduct
積,乗積
SolveNSolve
代数方程式の解
DSolveNDSolve
微分方程式の解
MaximizeNMaximize
最大化
代数計算的な関数と数値計算的な関数
数値解析の不確定性
Wolframシステムにおいて,数値積分に代表される数値解析は代数計算的な解析とかなり違った手法に基づいて行われる.
代数的に積分するようにWolframシステムに積分式を与えると,式は関数形式で取り込まれ,式には積分操作を表すための一連の厳密でシンボル的な変換規則が次々に適用される.そして,積分した結果を評価することで積分処理を終える.
しかしながら,Wolframシステムが数値積分を行う場合,若干の最初の記号的な前処理を除き,積分式に関してWolframシステムが保持する情報は一連の積分式の数値のみである.実際に数値的に積分を決定するために,Wolframシステムは積分式の滑らかさや他の特性に関して事実上ある種の仮定を行わなければならない.十分に病的な被積分関数を与えると,この仮定が有効ではなくなるかも可能性があり,結果としてWolframシステムがこの積分の間違った答を返すこともある.
例えば,積分しようとする関数が特定の位置にスパイク状の幅の狭い突起部を持つとする.Wolframシステムは特定の点で積分式をサンプリングし,それらのサンプリング区間において式が滑らかであるとみなす.ここで,もしサンプリング点が上記の突起部を外れたなら,突起部はないと同然になり,求まる積分には反映されなくなってしまう.
関数をプロットする:
NIntegrateからの範囲でならこの積分を正確に求めることができる:
範囲をからに拡大する.デフォルト設定のNIntegrateは,近傍にあるピークを逃してしまうため,不正確な答になってしまう:
NIntegrateは,被積分関数の数値に関して得られるだけの情報を最大限に利用する.そのため,例えば,特定の領域内で積分誤差が大きいと予測されるときは,NIntegrateはその領域のサンプリング数を増やしている.このようにNIntegrateでは積分式に応じた解析ができるように解析手順の「適応化」が行われている.
NIntegrateの適応化は,少なくともその考え方において,滑らかな曲線を描画するために使うPlotの手順に似ている.いずれの場合も,特定の領域で滑らかな近似が得られるまでサンプリング点を増加させるという考え方に基づいている.
この種の数値積分で遭遇する問題は,他の数値計算でも見られる.
例えば,無限級数の和を近似するとき,まず,Wolframシステムは一定の項までサンプリングし,そのサンプリング値に基づいた外挿処理により残りの項の寄与量を推定しようとする.このため,級数の後の方に大きな項を入れると,その項は検知されずに間違った和が求まってしまうという問題が起る.
関数の最小を近似値で求める場合も同様な問題が起る.つまり,関数が有限数の点においてサンプリングされ,サンプリング区間では関数が滑らかで補間可能なものとみなされる.しかし,特定の領域に急な窪みが存在するとそれは検知されずに間違った最小値が求まってしまうかもしれない.
関数の値を純粋に数値計算手法のみで求めようとする限り,上記の問題は常につきまとう.シンボル的な手法を使い厳密な代数計算をしなければこの問題は回避できない.
したがって,場合によっては,まずシンボル的に問題を解いておき,そうして求まった代数式を数値解析する,という手順が有効にもなり得る.そのような手順を使えば,数値解析だけだと起るような問題が回避できるかもしれない.
数値計算による和,積,積分
NSum[f,{i,imin,Infinity}]
数値解析による総和
NProduct[f,{i,imin,Infinity}]
数値解析による乗積
NIntegrate[f,{x,xmin,xmax}]
数値解析による積分
NIntegrate[f,{x,xmin,xmax},{y,ymin,ymax}]
数値解析による多重積分
数値計算による和,積,積分
を数値解析的に近似する:
NIntegrateを使えば,積分範囲の特異点を扱うことができる:
無限大範囲の数値積分もできる:
これは,三角形の領域上の二重積分である.変数の順序に注意:
これは,より複雑な領域上の二重積分である:
積分の数値解析
N[Integrate[expr,{x,xmin,xmax}]]
厳密に積分を求め,その後に積分の値を数値近似する
NIntegrate[expr,{x,xmin,xmax}]
数値解析で積分を求める
NIntegrate[expr,{x,xmin,xmax},{y,ymin,ymax},]
数値解析で多重積分 を計算する
NIntegrate[expr,{x,xmin,x1,x2,,xmax}]
から の各点を通って に至る線に沿って数値積分する
数値積分の関数
積分 を数値近似する:
二重積分 を数値近似する:
NIntegrateの重要な機能のひとつに,既知の点で発散するような関数に対処できることがある.NIntegrateでは積分領域の両端についてこのような問題が起らないか自動的に判定が行われるようになっている.
関数の点で発散してしまう.それでも,NIntegrateを使うと,正確に積分してくれる:
の積分は厳密に求めることも可能である:
において が特異点を持つことをNIntegrateは検知し,積分不能なことが判明する:
NIntegrateは,積分領域および被積分関数の区分関数(PiecewiseAbs等)により定義されるすべての部分領域の終点における特異点を自動的に検知しようとする.したがって,両端以外に特異点が存在する場合,NIntegrateの返す答は正しくない可能性がある.それでも,適応化の中でNIntegrateが特異点を検出できるときがある.そのようなときは,警告が発せられる.
NIntegrateは,積分区間にある特異点のために問題が起る可能性があるということを警告してくれる.求まる答は数値的に極めて正解に近い:
もし,積分する関数がどこで特異点を持つかあらかじめ判明していれば,NIntegrateにそのことを伝え,適切な処置を取るように指示することができる.NIntegrate[expr,{x,xmin,x1,x2,,xmax}]とすると,xmin から xmax の区間にある各中間点 xi において特異点が存在する可能性があるとして式 expr の積分が行われる.
再度計算する.今度は,に特異点があることを指示してあるので,正しい答が求まる:
また,NIntegrateに複素平面上の積分路を表す中間点 xi のリストを与えることもできる.この場合,積分路は xmin から始まり xi を通って xmax で終る折れ線区間からなるとみなされる.
を始点とし を順に通り,を終点とした複素平面上の閉じた積分路において を積分する:
コーシーの定理から分かるように,この積分は になる:
オプション
デフォルト値
MinRecursion0
積分法の再帰の最小回数
MaxRecursionAutomatic
積分法の再帰の最大回数
MaxPointsAutomatic
積分式のサンプリングの最大合計回数
NIntegrateの特別オプション
NIntegrateで数値積分すると,積分式が一連の点でサンプリングされる.その際に特定の領域で積分式に急激な変化が認められると,その領域は細分化され,サンプリングが再帰的に行われ,それと同時にサンプリング点の数が増やされる.パラメータMinRecursionMaxRecursionを使い,再帰の最大・最小回数が指定できる.MinRecursionの値を増やせば,NIntegrateにおけるサンプリング点の数が必ず増えるようになる.MaxPointsMaxRecursionは,NIntegrateが使うサンプリング点の数の上限を決定する.MinRecursionまたはMaxRecursionの値を高く取ると,NIntegrateの計算時間が余計にかかるようになる.
NIntegrateのオプション設定はすべてデフォルト値のままにしておき,を数値積分する.近傍のピークが見逃され,答は間違いになってしまう:
MinRecursion->3のオプション設定をして再度積分してみる.NIntegrateは,十分な数のサンプリングを行い,近傍のピークを検出する.しかし,MaxRecursionがデフォルト値なので,NIntegrateはサンプリング点が足りず正確な答が得られない:
MaxRecursionをこのように設定すると,NIntegrateは十分な精度で積分を求める:
別の解き方として,特にピーク近傍が細分化するように積分領域を分割してからNIntegrateする,という方法もある:
多次元の積分をNIntegrateで計算すると,非常に長い時間がかかるときがよくある.そのようなときは,オプションMaxPointsを小さい値に設定しNIntegrateで限られたサンプリングを行うようにすることで,推定的な積分値を求めるようにしたらよいだろう.
計算に時間のかかる積分でおおよその推定値を得る方法である:
総和および乗積の数値計算
NSum[f,{i,imin,imax}]
総和 を数値近似で求める
NSum[f,{i,imin,imaxdi}]
総和の数値計算において刻み幅を とする
NProduct[f,{i,imin,imax}]
乗積 を数値近似で求める
数値解析による総和と乗積
を数値近似する:
厳密な答が見付からないため,和はシンボル的な形で返される:
それでも,Nを適用すれば数値的な答が求まる:
NSumでは,まず,いくつかの項が実際に計算され,その結果をもとに残る項の寄与量が推定される.この推定を行うには2つのアプローチが取られる.その1つはオイラー・マクローリン(EulerMaclaurin)法と呼ばれ,積分をもとに総和を推定する手法に基づいたアプローチである.2番目は,ウィン(Wynn)のイプシロン法として知られ,和の項を余分にサンプリングし,その求めた値をある指数減少関数を掛け合せた多項式にフィット処理する,という手法に基づくアプローチである.3番目のアプローチは級数の交代に有効なもので,符号交代法を用いる.この方法もまた,和の項を余分にサンプリングし,2つの多項式の比からその和を推定する(パデ近似)というものである.
オプション
デフォルト値
MethodAutomatic
Automatic"EulerMaclaurin""WynnEpsilon"あるいは"AlternatingSigns"
NSumTerms15
和の計算に含める項数
VerifyConvergenceTrue
級数の収束を証明するかどうか
NSumの特別オプション
特に評価法を上記の手法のどちらかに指定しなければ,NSumは自動的にEulerMaclaurinWynnEpsilonのどちらを選択する.どちらを使うにせよ,和を求めようとする関数に特定の仮定がなされる.もし仮定した条件が実際の式に合わないと,答は間違ったものになる.
NSumは,無限大の極限を持った和を求める問題で最もよく使われる.もちろん,有限の極限を持った和にも使える.NSumでは総和を取るオブジェクトに関して特定の条件を仮定することで,Sumで必要になるような大量な関数評価を避けることが可能になる.
を外挿処理で数値計算する:
今度は,代数的に和を求め,その結果を数値計算する.先の方法よりだいぶ遅いが,正確な答が見付かる:
NProductは基本的にNSumと同様に機能し,オプションも同じように使う.
方程式の数値解法
NSolve[lhs==rhs,x]
整方程式を数値解析的に解く
NSolve[{lhs1==rhs1,lhs2==rhs2,},{x,y,}]
連立整方程式を数値解析的に解く
FindRoot[lhs==rhs,{x,x0}]
を初期値とし方程式の数値解を探す
FindRoot[{lhs1==rhs1,lhs2==rhs2,},{{x,x0},{y,y0},}]
連立方程式の数値解を探す
方程式の数値解法
NSolveを使い整方程式の持つすべての根の近似値を求める:
NSolveは,連立方程式の数値解法にも使える:
方程式が線形関数や多項式からなるとき,NSolveを使うことで,存在するすべての解に対する数値解析的な近似値を得ることが可能である.しかし,より複雑な関数,例えば超越関数を含む方程式においては,一般に体系化された手法がないことから,数値解析でも解を求めることができない.そのような場合でも,FindRootを使い数値解を探索することは可能である.FindRootを使うには,探索の初期値を指定する必要がある.
超越関数方程式の数値解を探す.初期値は とした:
この方程式は複数の解を持つ.違った の点から始めると,FindRootは異なった解を返してくる:
連立方程式の解を探すことも可能である.この例の解は複素数からなる:
整方程式の数値解
Solveでは,根基による整方程式の解が求められないとき,Rootオブジェクトを使って記号的な形で解が返される:
上の結果にNを適用すると数値解が求まる:
25桁精度で数値解を得る:
NSolveを使えば整方程式を直接解くことができる.この場合,厳密解の探索は行わない:
NSolve[poly==0,x]
整方程式を数値解析で解く
NSolve[poly==0,x,n]
数値解を 桁精度で出力する
NSolve[{eqn1,eqn2,},{var1,var2,}]
多項式系の解を与える
整方程式と整方程式系の数値解法
NSolveを使えば,整方程式あるいは整方程式系なら完全な数値解が求まる.
NSolveを適用すると,連立整方程系の解が求まる:
数値解析による根の探索
NSolveは整方程式の解を数値近似するために使う.「一変数の方程式」で説明したように,多項式よりさらに一般化された方程式を数値的に解くことは極めて難しい.それでも,FindRootを使って関数の数値根や,任意な単一方程式・連立方程式の数値解を探索することは可能である.
FindRoot[f,{x,x0}]
x=x0を初期値として f の数値根を探索する
FindRoot[lhs==rhs,{x,x0}]
x=x0を初期値として方程式 lhs==rhs の数値根を探索する
FindRoot[f1,f2,,{{x,x0},{y,y0},}]
すべての fi の連立数値根を求める
FindRoot[{eqn1,eqn2,},{{x,x0},{y,y0},}]
連立方程式 eqni の数値解を求める
数値解析による根の探索
の曲線が の直線と1点で交差している:
交点における の値を数値解析的に求める.FindRootの記述にある0 の初期値の点で探索の始点を示す:
FindRootを使った解の探索では,指定した初期値の点を始点として,そこから徐々に解に向かって接近していく.複数の方程式を解くときでも,FindRootでは最初に見付かった解だけが返される.見付かった答がどの解に相当するのかは初期値により違ってくる.与えた初期値が特定の解に十分近付いていれば通常はFindRootはその解を求める.
関数の根を探す.根は で与えられ,無数にある.特定の根に十分近い初期値を与えると,FindRootはその根を求める:
を初期値として根を探す. の根の近似値が求まる:
FindRootを使って解を複素平面上で探すときは,初期値として複素数を与える:
リーマンゼータ関数の零点を求める:
このようにして連立方程式系を解く:
FindRootが使う変数はリストを値として持つことができる.これにより,ベクトルを引数に取る関数の根を求めることができる.
このようにして変数 についての線形方程式を解く:
これで正規化された固有ベクトル と固有値 を求める:
微分方程式の数値解法
NDSolve[eqns,y,{x,xmin,xmax}]
独立変数 xxmin から xmax の区間において,関数 y について数値解析的に解く
NDSolve[eqns,{y1,y2,},{x,xmin,xmax}]
yi について連立方程式を解く
微分方程式の数値解法
における微分方程式 の数値解を生成する.結果は,補間関数InterpolatingFunctionの形で与えられる:
これは,の値である:
のような代数方程式では,個々の の解は単なる1つの数である.一方,微分方程式では,解は数ではなく関数である.例えば,の方程式では,独立変数 の区間を限定した上で,関数 の近似解を得るようにしたい.
Wolfram言語は,関数の近似解をInterpolatingFunctionオブジェクトとして返す.このオブジェクトは,特定の の値に適用されるとき,その点における の近似値を返す関数である.このときInterpolatingFunctionは,の値から構成されるテーブルを保持し,このテーブルで補間することで特定の点 における の近似値を求める.
y[x]/.solution
y[x]の値を求めるのに関数 y にリスト規則を適用する
InterpolatingFunction[data][x]
x で補間式を計算する
Plot[Evaluate[y[x]/.solution],{x,xmin,xmax}]
微分方程式の解をプロットする
NDSolveで求まった解の応用
連立微分方程式を解く:
これは,解に従って求めたz[2]の値である:
第3行で求めたz[x]の解をプロットする.Plotの使い方は「基本的なプロット」を参照:
NDSolve[eqn,u,{x,xmin,xmax},{t,tmin,tmax},]
偏微分方程式を解く
偏微分方程式の数値解
微分方程式の数値解
「微分方程式の数値解法」で説明したNDSolveを使うと,微分方程式を数値解析的に解くことができる.また,単独の微分方程式でも連立の微分方程式でもNDSolveで解ける.さらに,広い範囲の常微分方程式と偏微分方程式の一部が扱える.常微分方程式系の場合,未知の関数 がいくつあっても構わないが,すべて単一の独立変数 のみに依存しているものとする.偏微分方程式の場合は,複数の独立変数を含んでいる.NDSolveは微分方程式と代数方程式が混ざった「微分代数方程式」も扱うことができる.
NDSolve[{eqn1,eqn2,},y,{x,xmin,xmax}]
xmin から xmax の範囲で関数 の数値解を求める
NDSolve[{eqn1,eqn2,},{y1,y2,},{x,xmin,xmax}]
複数の関数 の数値解を求める
微分方程式の数値解法
NDSolveで求まる関数 の解は,InterpolatingFunctionオブジェクトを使って表される.InterpolatingFunctionオブジェクトは,独立変数 から で指定される範囲にあるとき の近似を与える.
NDSolveでは解を求めるために反復手法が使われる.それは のある値を始点とし,一連の刻みを取りながら から の範囲をくまなく探索していく.
探索を開始するには,NDSolveの式の中に とその導関数に関する適切な初期条件や境界条件が備わっている必要がある.これらの条件を与えることで, の特定点における ,さらに導関数 の値を決定していく.少なくとも常微分方程式において,この条件は のどの点でもよい.それはNDSolve から の全範囲をくまなく自動的に探すからである.
yについて解く.y[0]の初期条件を与え,x0から2の範囲で探索する:
xの探索範囲は0から2のままだが,初期値はy[3]について与えている:
簡単な境界値の問題を解く:
NDSolveを使う際は, の解を完全に決定するのに十分な初期条件,または,境界条件を与えておく必要がある.DSolveを使って微分方程式の厳密解を求めるときには,初期条件が足りなくてもどうにかなる.これは,指定しなかった初期条件のため発生する自由度を明示化するため,積分定数C[i]DSolveにより自動的に挿入されるからである.ところが,NDSolveでは解は数値として与えなければならないので,数値では余分に発生する自由度が表せない.このため,解を決定するのに十分な初期条件,または,境界条件を明示的に与えなければならない.
階の微分方程式を解くとき,通常,最大で次までの導関数について初期条件を与えるか,または, 点における境界条件を与える必要がある.
三階の微分方程式を解く.三階なので,最大で二次までの導関数を与えなければいけない:
得られた解をプロットする:
別の三階微分方程式を解く.境界条件を3点について与える:
Wolfram言語では,線形結合した関数値や微分値なら何でも境界条件として使える:
多くの場合,与える初期条件は必ず同一の 値,例えば を含む必要がある.このため, から の範囲は別に与えなくてもよくなる. の範囲をとして指定すると,Wolfram言語では自動的に から の範囲で有効な解が生成される.
0〜2の範囲で有効な解を求める:
初期条件とする方程式はどんな種類のものでもよい.場合によっては,これらの方程式は複数の解を持つことがある.そのような場合は,それに対応した形でNDSolveが複数の解を生成する.
この初期条件は,複数の解を与える:
求まる解をすべてプロットする:
NDSolveを使って,結合された微分方程式の系を解くことも可能である.
結合した方程式の対を数値的に解く:
求まったyの解をプロットする:
xyの両方を使いパラメトリックプロットを生成する:
微分方程式に未知の関数を使うとき,関数の名前として必ずしも単一のシンボルを与える必要はない.未知の関数が複数個あるとき等は,例えば といった関数名にするとよい.
5組の微分方程式と初期条件を構築する:
この方程式を解く:
解をプロットする:
NDSolveは値がリストや配列である関数も扱える.y[0]=={v1,v2,,vn}のような初期条件を与えると,NDSolve を値が長さ のリストである関数だと仮定する.
これは4つの微分方程式が組み合された系の解を求める:
これが解である:
オプション名
デフォルト値
MaxStepsAutomatic
の最大ステップ数
StartingStepSizeAutomatic
が使用する初期刻み幅
MaxStepSizeAutomatic
が使用する最大刻み幅
NormFunctionAutomatic
誤差推定で使用するノルム
NDSolveの特別オプション
NDSolveには方程式を解く多くのメソッドが備わっているが,基本的にはすべてのメソッドが独立変数 内で一連のステップを取ることで解を求める.この手順は適応型であり,刻み幅は常に適当であるように自動調整される.値が特定の領域で急激に変化するときは,NDSolveが解を見逃さないように刻み幅が徐々に狭められるか,あるいはメソッドが変更される.
導関数に不連続点がある微分方程式を解いてみる:
NDSolveの解の探索において,の近傍では刻み幅が狭められ,折れ部でも正確に追跡ができている:
NDSolveの探索手順は適応型であるから,変数 の変化率が大きく異なるいくつかの要素を持つ,いわゆる「扱いにくい」微分方程式を解くこともできる.
これらの方程式において,yzより急激に変化する:
それでも,両方ともNDSolveで正確に追跡できている:
NDSolveは,正確に解を追跡するまで刻み幅を減らすという一般的な手続きに従う.しかし,真の解に特異点がある場合,または積分区間が大きすぎる場合は問題がある.前者の場合は,NDSolveは指定された積分区間に対して意味をなすとみなす最小の刻み幅を制限する.後者の場合は,オプションMaxStepsを使って,NDSolveが解を見付けるために取ることのできるステップの最大数を指定する.常微分方程式では,デフォルトの設定はMaxStepsAutomaticである.Automatic設定では,NDSolveは初期の刻み幅に基づいて,問題の方程式を解くのに必要なステップ数を推定する.
NDSolveは,刻み幅があまりに小さくなると停止する:
確かに,において解は特異点を持つ:
解が滑らかなほとんどの関数では,MaxStepsのデフォルト値で十分間に合う.解が複雑な構造を取るようなときは,MaxStepsを大きく取っておくとよいだろう.また,MaxSteps->Infinityと設定しておくとステップの上限なしで探索ができる.
ローレンツ(Lorenz)方程式の解をここまで求めるためには,MaxStepsのデフォルトによる制限を除いておく必要がある:
求まった解を3Dパラメトリック形式でプロットする:
連立した微分方程式を解くとき,NDSolveではすべての方程式に適応するように刻み幅が自動調整される.しかし,場合によっては,NDSolveで最初に取るステップ幅が大きすぎて解の重要な特徴を見逃しかねない.このような問題を避けるには,オプションStartingStepSizeを使い第1ステップの幅を特別に指定しておく.
NDSolveに与える方程式すべてが導関数を含んでいる必要はない.単に代数的なだけでもよい.NDSolveを用いて多くの「微分代数方程式」を解くことができる.
これは微分代数方程式系を解く:
これが解である:
NDSolve[{eqn1,eqn2,},u,{t,tmin,tmax},{x,xmin,xmax},]
偏微分方程式系を について解く
NDSolve[{eqn1,eqn2,},{u1,u2,},{t,tmin,tmax},{x,xmin,xmax},]
偏微分方程式系を複数の関数 について解く
偏微分方程式を数値的に解く
これは波動方程式の数値解を求める.結果は二次元の補間関数である:
結果のプロットを生成する:
これで非線形波動方程式の数値解を求める:
これは結果の3Dプロットである:
これは結果の高解像度密度プロットである:
これはこの方程式の2+1次元におけるバージョンである:
これで方程式を解く:
これは解のプロットの配列を生成する:
数値最適化
FindMinimum[f,{x,x0}]
x=x0を初期値として f の極小値を求める
FindMinimum[f,x]
f の極小値を求める
FindMinimum[f,{{x,x0},{y,y0},}]
複数の変数における極小値を求める
FindMinimum[{f,cons},{{x,x0},{y,y0},}]
x=x0, y=y0, を初期値として,制約条件 cons のもとで極小値を求める
FindMinimum[{f,cons},{x,y,}]
制約条件 cons のもとで極小値を求める
FindMaximum[f,x]
極大値を求める
極小値と極大値の探索
を始点としてを最小にする の値を求める:
リストの最後の要素が最小に達する値を与える:
FindRootと同様にFindMinimumFindMaximumもある点から始めて次第に最小値または最大値を求める.しかしこれらの関数は何かが見付かり次第結果を返すので,大域的な値ではなく極小値あるいは極大値を返す可能性がある.
この曲線には2つの極小値がある:
を始点とすると右側の極小値が求まる:
こうすると左側の極小値が求まる.この場合はこれが大域的最小値でもある:
初期値なしで変数を指定することができる:
制約条件を指定することができる:
NMinimize[f,x]
f の大域的最小値を求めようとする
NMinimize[f,{x,y,}]
複数の変数について大域的最小値を求めようとする
NMaximize[f,x]
f の大域的最大値を求めようとする
NMaximize[f,{x,y,}]
複数の変数について大域的最大値を求めようとする
大域的最小値と最大値の探究
これは即座に大域的最小を見付ける:
NMinimizeNMaximizeは数値用のMinimizeMaximizeと考えることができる.しかし,MinimizeMaximizeとは異なり,大域的最小や最大を必ず見付けられるとは限らない.関数 f がある程度滑らかで極小と極大の数が限られていればこれらの関数はかなり効果がある.
NMinimize[{f,cons},{x,y,}]
制約条件 cons に従って f の大域的最小を求める
NMaximize[{f,cons},{x,y,}]
制約条件 cons に従って f の大域的最大を求める
制約条件に従って大域的最大と最小を求める
という制約条件の下では,NMinimizeは右側の極小を与える:
これは単位円内の の最小を求める:
この場合,Minimizeは厳密な結果を返す:
しかしこの場合には厳密な結果は返せない:
これはNMinimizeを使うのと同じことで,数値近似を与える:
目的関数 f と制約条件 cons の両方がすべての変数について線形の場合,最小化と最大化は「線形計画問題」に対応することになる.このような問題は明示的な方程式で記述するのではなく行列やベクトルで記述する方が便利なことがある.
LinearProgramming[c,m,b]
制約条件 に従って を最小にするベクトル を求める
LinearProgramming[c,m,b,l]
制約条件 を使う
行列形式の線形計画法
これは方程式の形をした線形計画法の問題である:
これは同じ問題を行列形式にしたものである:
リスト をペアの列の形にすると方程式と不等式の制約条件を混ぜて指定することができる.なら 番目の制約条件は である.もし なら制約条件は である.もし ならそれは である.
最初の不等式がを使うようにする:
LinearProgramming[c,m,b,l] の上界と下界を表すペアのリストにすることができる.
大規模な線形計画法の問題を解く場合には行列 SparseArrayオブジェクトとして与えると便利なことが多い.
結果精度のコントロール
NDSolveNMinimizeのような数値操作を行う場合,Wolfram言語はデフォルトにより機械数を使う.しかし,オプションWorkingPrecision->n とすることで n 桁精度の任意精度数が使えるようになる.
これは数値積分を機械精度で計算する:
これは30桁の任意精度数で計算する:
WorkingPrecisionを設定すると,これは通常計算結果の精度の上限を定義する.しかし,この制約条件内でWolfram言語に目標精度と目標確度を指示することができる.多くの数値操作において目的精度と目的確度を数桁大きくするだけではるかに長い計算時間がかかるようになることは理解しておいた方がよい.それでもなお,高精度・高確度が確実に達成できることが重要な場合も多い.
WorkingPrecision
計算に使う桁数
PrecisionGoal
目標精度の桁数
AccuracyGoal
目標確度の桁数
精度と確度のコントロールオプション
これは25桁精度の結果を与える:
作業精度が30桁では50桁精度は達成できない:
WorkingPrecisionを特定の値に設定するときは,Wolfram言語における数値操作のための各関数がPrecisionGoalAccuracyGoalに特定のデフォルト設定を使っていなければならない.その典型的な例はNDSolveである.そのデフォルト設定はWorkingPrecisionにおける設定値の半分になっている.
目標精度と目標確度の両方が返される最終結果とそれらのさまざまなノルムや誤差推定に適用される.Wolfram言語における数値操作の関数は通常指定の目標精度あるいは目標確度のどちらか一方に達した段階で結果を返す.どちらかの設定値がInfinityの場合はそうではない方だけが考慮される.
N[expr,n]で通常の数値評価を行う場合,Wolfram言語は結果が n 桁精度に達するように自動的に内部計算を調整する.しかし関数の数値操作を行う場合,実際にはWorkingPrecisionPrecisionGoalをもっと明示的に指定する必要があるのが普通である.
アルゴリズムのモニターと選択
Wolfram言語の関数は内部がどのような仕組みになっているのかを知る必要がないように注意深く設定されている.しかし,特に反復アルゴリズムを使用する数値計算の場合には,アルゴリズムの内部過程がモニターできると便利なことがある.
StepMonitor
ステップが成功した場合に常に評価される式
EvaluationMonitor
入力からの関数が評価された場合に常に評価される式
数値関数の過程のモニター
これはステップが取られる度にxの値を出力する:
option->expr ではなく option:>expr を使うのが重要であることに注意されたい.expr が規則が与えられたときだけではなく,使われる度に評価されるためには遅延型の規則:>が必要である.
ReapSowは取るステップのリストを作る便利な方法を提供する:
これでステップを数える:
解へ向けて着実にステップを重ねるために,反復的な数値アルゴリズムが与えられた関数を数回評価しなければならないことがある.これは例えば各ステップが関数の値の差分によって導関数を推定しなければならないからだったり,ステップが成功するためにはいくつかの試みが必要だったりするからである.
これは解に到達するための有効なステップを示す:
これは関数が評価されたすべての場合を示す:
Wolfram言語のアルゴリズムによる評価パターンは非常に複雑なことがある:
Method->Automatic
自動的にメソッドを選択する(デフォルト)
Method->"name"
明示的に使用メソッドを指定する
Method->{"name",{"par1"->val1,}}
メソッドをより詳細に指定する
Methodオプション
特定のタイプの数値計算のため複数の異なるメソッドが知られていることがある.そのような場合にWolfram言語は普通文献で説明されているもの,説明されていないものの中で一般に最も成功率が高いものをサポートする.特定の問題に対し,最良のメソッドを自動的に選択するのには多大な努力が必要である.しかし,問題をよく知っていれば,あるいは数値メソッドについて研究しているのであれば,使うべきメソッドをWolfram言語に明示的に与えてみてもよいだろう.関数レファレンスページにはWolfram言語に組込まれているメソッドのいくつかが載っている.その他のメソッドについては「数値および関連関数」あるいは拡張ドキュメントで説明してある.
これはメソッド 使って微分方程式を解き,必要なステップと評価を返す:
自動選択されたメソッドの場合,これは必要なステップと評価の数になる:
これは他のいくつかのメソッドではどうなるかを示している.自動的に選択されたアダムス(Adams)法が最も速い:
これは差分次数のパラメータが変更された場合に陽的ルンゲ・クッタ(RungeKutta)法を使ったらどうなるかを示している:
関数の入力への過剰依存性
簡単な代数式で与えられる関数は,入力成分が少し変われば出力成分も少し変わる,という性質をよく持つ.しかし,実行手続型の関数には入力成分の変化に過剰に反応するような関数もある.これは,関数で使われる手続が入力の持つ有効数字を累進的に「削っていって」しまうからである.
反復手続に入力値0.1111を与え反復処理を何回か行う:
値を0.1112に変えて同じ処理を行う.0.1111で見られた結果から累進的に外れていくのが分かる:
FractionalPart[2x]の動作は,数 x のバイナリ表記における桁数を考えれば分かりやすい.最初の桁が落とされ,他の桁が左にシフトされる.この操作を何回か繰り返すと,より右寄りの桁に対して結果が敏感に反応してもおかしくない.右寄りの桁が x のもとの値にほとんど影響をおよぼさないのである.
FractionalPart[2x]で行われるシフト操作を再現する.x の最初の8バイナリ桁を見てみる:
特定の精度で入力すると,事実上桁数が限定されてしまう.1度,桁が「削られ」てしまうと正確な答は求まらない.精度を上げるためには,もとの入力の数字がもっと分かっていなけらばならないからである.任意精度の数を使っていれば,Wolfram言語は自動的にこのような精度の劣化を見張り,「任意精度の数」で説明してあるように,0.×10e によって有効数字が残らないようにした数を示している.
反復処理を繰り返すたびに,累進的に精度が悪化し,ついには桁精度ゼロに陥る:
各値の桁精度を確認してみる.ゼロ精度は有効桁がないことを示す:
厳密に計算すると,答は周期系列になる:
どのような形の近似数でも,それを上記の例のように使うといずれ有効数字がなくなってしまう.任意精度の数を使えば,各ステップの精度が表示されるので少なくとも精度がどう悪化したかが確認できる.しかし,機械精度の数を使うと桁精度が管理できないため,求まった答が意味あるものかどうか分からなくなってしまう.
機械精度の数を使うと桁精度の管理ができない.このため,どう悪化したか確認できない:
FractionalPart[2x]の操作を繰り返すたびに,直前の値から有効なバイナリ桁が抽出される.これらの桁の数字がランダム(例えば, の桁)なら,答もそれに対応してランダムになる.一方,桁の数字が単純なパターンを持つ(例えば,有理数)と,答もそれに対応して単純な形を持つ.
FractionalPart[3/2x]のような操作を繰り返すと,はじめが単純な数であっても,ランダムな数の系列が求まってしまうことがある.この結果は,入力成分への過剰依存の話とは直接関係ないが,実はStephen Wolframが1980年代中頃に発見した極めて一般的な現象である.
簡単な入力値だが,一見ランダム的な系列が生成される:
各値が厳密に求まったなら,今度は,安全に数値近似ができる:
厳密数を使い1000回反復し,最後の5回の値を見てみる:
機械精度で同じ処理をすると,完全に間違った答が求まってしまう:
反復処理を行う手続きに基づく関数は入力に対して過剰な依存性を示す.似たような状況が微分方程式の解にも言える.微分方程式の独立パラメータを変化させると,反復処理におけるあるステップから次のステップに移行するときの状況と同じことが起る.
ダッフィング(Duffing)の方程式を解く.初期条件は1とする:
求まった解をプロットする:
今度は初期値を1.001にして解いてみる:
解が前の値から累進的に外れていくのが分かる: