How to | 制約条件付き非線形最適化を行う方法
最適化問題の重要な部分に制約条件付き非線形最適化がある.この最適化は,関数が線形ではなく,パラメータ値が特定の範囲に限られているものである.Wolfram言語はこれらの最適化問題だけでなく,その他のさまざまな最適化問題も解くことができる.
簡単な最適化問題は,点
が原点の1単位内にある
の最大値を求めるというものである.Maximizeの第1引数はリストに入った関数と制約条件であり,第2引数は変数をリストする:
sol = Maximize[{y^2 - x, x^2 + y^2 ≤ 1}, {x, y}]この出力は,第1要素が見付かった値の中で最大の値であるリストである.第2要素sol[[2]]はその最大値を返す独立変数の値に対する規則のリストである.sol[[2]]という表記は,Part[sol,2]の簡略形である:
sol[[2]]もとの問題に解を当てはめてみることによって,この解が制約条件を満足するかどうかを検証することができる./.sol[[2]]をもとの問題の後に使って,これを行う./.は,ReplaceAllの簡略形である:
{y^2 - x, x^2 + y^2 ≤ 1} /. sol[[2]]Minimize[{Cos[x] + x / 2, 0 < x < 10}, x]この結果は,Nの小数近似として見ることができる:
N[%]求めたいものが数値結果である場合には,最初からその数値バージョンであるNMinimizeおよびNMaximize を使う方がより効率的である.NMinimizeおよびNMaximizeは数値アルゴリズムを使用し,大域的最適値ではない結果を返すことがあることに注意:
NMinimize[{Cos[x] + x / 2, 0 < x < 10}, x]Maximize および Minimize は照明された大域的最適値を返して記号的に最適化する式を解析する.記号的技法で解析できない式がある場合には,NMaximizeおよびNMinimizeの方がより便利で効率的である.
以下は,パラメータ
が数値ではない場合にNIntegrateが評価しないために,MaximizeおよびMinimizeがうまく使えない簡単な式の例である:
NIntegrate[Cos[q x] / q, {x, 0, 4Pi}]以下は,NMinimizeで使えるこの式に対する関数である.引数の?NumericQは,
が数値ではない場合に関数がNIntegrateを評価しないようにプロテクトする.?は,PatternTestの簡略表記である:
f[q_ ? NumericQ] := NIntegrate[Cos[q * x] / q, {x, 0, 4Pi}]NMinimizeおよびNMaximizeを使ってこの最適化を数値的に行うことができる.第2引数は勾配を求めるための2つの開始値を
に与える:
NMinimize[{f[q], q > 1}, {q, 1, 2}]NMinimize,NMaximize,Minimize,Maximizeは,大域的な最小値と最大値を求めようとする.ときにはより速いこともあるFindMinimumおよびFindMaximumは,極小値と極大値を求めようとする:
FindMaximum[{100 / ((x - 1)^2 + (y - 4)^2 + 1) + 200 / ((x + 1)^2 + (y + 2)^2 + 1) }, {{x, 2}, y}]NMaximize[{ 100 / ((x - 1)^2 + (y - 4)^2 + 1) + 200 / ((x + 1)^2 + (y + 2)^2 + 1) }, {{x, 1, 2}, y}]よくある最適化問題は,曲線とデータの間のエラーを最小化するパラメータを見付けるというものである.この例では,FindFitを呼び出してこれらのデータ点に対する二次フィットを求める:
dat = {{0, -1.144}, {1, -0.924}, {2, 3.70}, {3, 12.72}, {4, 26.14}, {5, 43.96}};FindFitの引数はデータ,式,そのパラメータのリスト,および変数である.以下でこの問題を解く:
fit1 = FindFit[dat,
a(x - b)(x - c),
{a, b, c},
x]制約条件を加えることができる.例えば,すべてのパラメータが正でなくてはならないとして,その制約条件を式と一緒にリストに置く:
fit2 = FindFit[dat,
{a(x - b)(x - c), a > 0, b > 0, c > 0},
{a, b, c},
x]以下は2つのフィットを比較する.
が小さいときを除いてこの2つは非常に似ている:
Plot[{a(x - b)(x - c) /. fit1, a(x - b)(x - c) /. fit2}, {x, 0, 5},
Epilog -> (Map[Point, dat]), PlotStyle -> {Red, Blue}]