|
|
◆ Lmder1_r()
| Sub Lmder1_r |
( |
M As |
Long, |
|
|
N As |
Long, |
|
|
X() As |
Double, |
|
|
Fvec() As |
Double, |
|
|
Fjac() As |
Double, |
|
|
Tol As |
Double, |
|
|
Ipvt() As |
Long, |
|
|
Info As |
Long, |
|
|
XX() As |
Double, |
|
|
YY() As |
Double, |
|
|
IRev As |
Long, |
|
|
Optional Info2 As |
Long |
|
) |
| |
非線形最小二乗法 (レーベンバーグ・マルカート法) (シンプルドライバ) (リバースコミュニケーション版)
- 目的
- 本ルーチンはM個のN変数非線形関数の二乗和の最小点をレーベンバーグ・マルカート法により求める.
min Σfi(x1, x2, ..., xn)^2 (ただし, Σは i = 1 〜 M)
IRevに従って関数値およびヤコビ行列をユーザーが与える必要がある.
Lmder1_rは, FTol = Tol, XTol = Tol, GTol = 0, Maxfev = 100*(n+1), Mode = 1, Factor = 100, Nprint = 0 としてLmder_rを呼び出すのに相当する.
- 引数
-
| [in] | M | 関数の数. (M > 0) |
| [in] | N | 変数の数. (0 < N <= M) |
| [in,out] | X() | 配列 X(LX - 1) (LX >= N)
[in] 初期近似解
[out] IRev = 0: 求められた最終近似解.
IRev = 2: ヤコビ行列を求める点. |
| [out] | Fvec() | 配列 Fvec(LFvec - 1) (LFvec >= M)
IRev = 0: 求められた解ベクトルX()における関数値. |
| [in,out] | Fjac() | 配列 Fjac(LFjac1 - 1, LFjac2 - 1) (LFjac1 >= M, LFjac2 >= N)
[in] IRev = 2: 再呼び出し時にX()におけるヤコビ行列(∂fi/∂xj)を与えること.
[out] IRev = 0: 上部の N×N 部分に, 対角要素の絶対値が昇順になるように並べ替えを行った上三角行列 R が入る.
P^T * (J^T * J)*P = R^T * R
ここで, P は並べ替えを表す置換行列, J は最終的に求められたヤコビ行列である. |
| [in] | Tol | 二乗和および解の相対誤差の許容値. (Tol >= 0) |
| [out] | Ipvt() | 配列 Ipvt(LIpvt - 1) (LIpvt >= N)
置換行列を定義するピボット情報. |
| [out] | Info | = 0: 正常終了. (サブコードをInfo2に返す)
= -1: パラメータ M の誤り. (M < N)
= -2: パラメータ N の誤り. (N <= 0)
= -3: パラメータ X() の誤り. (配列X()の大きさが不足)
= -4: パラメータ Fvec() の誤り. (配列Fvec()の大きさが不足)
= -5: パラメータ Fjac() の誤り. (配列Fjac()の大きさが不足)
= -6: パラメータ Tol の誤り. (Tol < 0)
= -7: パラメータ Ipiv() の誤り. (配列Ipiv()の大きさが不足)
= -9: パラメータ XX() の誤り. (配列XX()の大きさが不足)
= -10: パラメータ YY() の誤り. (配列YY()の大きさが不足)
= 1: 関数評価回数(IRev=1で戻る回数)がMaxfevを超えた.
= 2: 残差二乗和が改善されなくなった. (FTolが小さすぎる)
= 3: 解が改善されなくなった. (XTolが小さすぎる)
= 4: Fvecとヤコビ行列の列が計算機イプシロン内で直交した. (GTolが小さすぎる) |
| [out] | XX() | 配列 XX(LXX - 1) (LXX >= N)
IRev = 1の場合, 関数値を求めるべき点を返す. |
| [in] | YY() | 配列 YY(LYY - 1) (LYY >= M)
IRev = 1の場合, 再呼び出し時に関数値fi(XX()) (i = 1〜M)を与えること. |
| [in,out] | IRev | リバースコミュニケーションの制御変数.
[in] 最初の呼び出し時に 0 に設定しておくこと. 2回目以降の呼び出し時には値を変更してはならない.
[out] 0 以外の時には下記処理を行ってから再び本ルーチンを呼び出すこと.
= 0: 処理終了. 正常終了かどうかはInfoをチェックすること.
= 1: XX()における関数値を求めYY()に設定すること. YY()以外の変数を変更してはならない.
= 2: X()におけるヤコビ行列を求め Fjac()に設定すること. Fjac()以外の変数を変更してはならない. |
| [out] | Info2 | (省略可)
Info = 0 で戻ったときのサブコード.
= 1: 二乗和の相対減少値およびその予測値の両方がFTol以下になった
= 2: 連続する2回の反復の相対誤差がXTol以下になった
= 3: 上の2つ共満たした |
- 出典
- netlib/minpack
- 使用例
- 次のデータをモデル関数 f(x) = c1*(1 - exp(-c2*x)) で近似する. 2つのパラメータc1, c2は非線形最小二乗法により定める.
f(x) x
10.07 77.6
29.61 239.9
50.76 434.8
81.78 760.0
初期値は, c1 = 500, c2 = 0.0001 とする. Sub FLmder(M As Long, N As Long, X() As Double, Fvec() As Double, Fjac() As Double, IFlag As Long)
Dim Xdata(3) As Double, Ydata(3) As Double, I As Long
Ydata(0) = 10.07: Xdata(0) = 77.6
Ydata(1) = 29.61: Xdata(1) = 239.9
Ydata(2) = 50.76: Xdata(2) = 434.8
Ydata(3) = 81.78: Xdata(3) = 760
If IFlag = 1 Then
For I = 0 To M - 1
Fvec(I) = Ydata(I) - X(0) * (1 - Exp(-Xdata(I) * X(1)))
Next
ElseIf IFlag = 2 Then
For I = 0 To M - 1
Fjac(I, 0) = Exp(-Xdata(I) * X(1)) - 1
Fjac(I, 1) = -Xdata(I) * X(0) * Exp(-X(1) * Xdata(I))
Next
End If
End Sub
Sub Ex_Lmder1_r()
Const M = 4, N = 2
Dim X(N - 1) As Double, Fvec(M - 1) As Double, Fjac(M - 1, N - 1) As Double
Dim Tol As Double, Ipvt(N - 1) As Long, Info As Long
Dim XX(N - 1) As Double, YY(M - 1) As Double, IRev As Long, IFlag As Long
Tol = 0.00000001 '1.0e-8
X(0) = 500: X(1) = 0.0001
IRev = 0
Do
Call Lmder1_r(M, N, X(), Fvec(), Fjac(), Tol, Ipvt(), Info, XX(), YY(), IRev)
If IRev = 1 Or IRev = 2 Then
IFlag = IRev
Call FLmder(M, N, XX(), YY(), Fjac(), IFlag)
End If
Loop While IRev <> 0
Debug.Print "C1, C2 =", X(0), X(1)
Debug.Print "Info =", Info
End Sub
Sub Lmder1_r(M As Long, N As Long, X() As Double, Fvec() As Double, Fjac() As Double, Tol As Double, Ipvt() As Long, Info As Long, XX() As Double, YY() As Double, IRev As Long, Optional Info2 As Long) 非線形最小二乗法 (レーベンバーグ・マルカート法) (シンプルドライバ) (リバースコミュニケーション版)
- 実行結果
C1, C2 = 241.084896089973 5.44942234119956E-04
Info = 0
|