10. 非線形最適化 (多次元)
注 – 例題ワークシートをダウンロードすることができます. 1. 例題ワークシートの入手と使用方法 をご覧ください.
多次元の非線形最適化問題の XLPack による解き方, すなわち, 一般の多変数非線形関数 f(x1, x2, …, xn) の最小点の求め方の例を説明します.
例題
次の関数の最小点を求める.
f(x1, x2) = 100(x2 - x12)2 + (1 - x1)2
関数の形は次のようになります(縦軸は対数値で表しています).
この関数は, Rosenbrock の関数と呼ばれ, (-1.2, 1) を出発点として, 最小点 (1, 1) を求めるテスト問題としてよく使用されます. 深い曲がった谷の中に最小点があり, 最小点に到達するのが難しいとされています.
VBA プログラムを使用した解き方 (1)
VBA サブルーチン Optif0 を使ったプログラム例を示します.
Sub F(N As Long, X() As Double, Fval As Double)
Fval = 100 * (X(1) - X(0) ^ 2) ^ 2 + (1 - X(0)) ^ 2
End Sub
Sub Start()
Const NMax = 10, Ndata = 5
Dim N As Long, X(NMax) As Double, Xpls(NMax) As Double, Fpls As Double
Dim Info As Long, I As Long
N = 2
For I = 0 To Ndata - 1
'--- Input data
X(0) = Cells(6 + I, 1): X(1) = Cells(6 + I, 2)
'--- Find min point of equation
Call Optif0(N, X(), AddressOf F, Xpls(), Fpls, Info)
'--- Output result
Cells(6 + I, 3) = Xpls(0): Cells(6 + I, 4) = Xpls(1): Cells(6 + I, 5) = Info
Next
End Sub
目的関数を外部サブルーチンとして用意し, 初期値を指定して Optif0 を呼び出します. Optif0 は, 初期値として与えられた近似解を出発点に反復計算を行い, その近傍の最小点を求めます. ここでは, 5 つの異なる初期値を与えたときにどのような解が得られるかを見るプログラムとしています.
初期値としては, (-1.2, 1) の他に (-1, 1), (-1, -1), (0, 1), (0, 0) を試してみます.
このプログラムを実行すると, 次の結果が得られました.
(-1, 1) のように初期値によっては収束しない場合がありました. 上の例はテスト問題のため, あえて収束しにくい初期値を与えていますが, 実際に使う際にはできるだけよい初期値を与えるべきです. 問題によっては局所的な最小点をいくつも持つものがあり, 目的の解以外の局所最小点に収束してしまうことがあります.
VBA プログラムを使用した解き方 (2)
リバースコミュニケーション版の VBA サブルーチン Optif0_r を使ったプログラム例を示します.
Sub Start()
Const NMax = 10, Ndata = 5
Dim N As Long, X(NMax) As Double, Xpls(NMax) As Double, Fpls As Double
Dim Info As Long, I As Long
Dim XX(NMax - 1) As Double, YY As Double, IRev As Long
N = 2
For I = 0 To Ndata - 1
'--- Input data
X(0) = Cells(6 + I, 1): X(1) = Cells(6 + I, 2)
'--- Find min point of equation
IRev = 0
Do
Call Optif0_r(N, X(), Xpls(), Fpls, Info, XX(), YY, IRev)
If IRev = 1 Then YY = 100 * (XX(1) - XX(0) ^ 2) ^ 2 + (1 - XX(0)) ^ 2
Loop While IRev <> 0
'--- Output result
Cells(6 + I, 3) = Xpls(0): Cells(6 + I, 4) = Xpls(1): Cells(6 + I, 5) = Info
Next
End Sub
目的関数を外部関数として与えるのではなく, IRev = 1 のときに XX() の値を使って関数値を計算し YY に入れて再度 Optif0_r を呼び出します. リバースコミュニケーション版の詳細については こちら を参照してください.
このプログラムを実行すると上と同じ結果が得られます.
ソルバーを使用した解き方
XLPackソルバーアドインの「多変数非線形最適化」を使って解くこともできます. B9セルに数式 (=100*(C8-B8^2)^2+(1-B8)^2) が入力されています.
ソルバーについては こちら も参照ください.