Option Explicit
Public Function drda(x As Double, a As Double, b As Double, c As Double) As Double
drda = b * x ^ (1 + c) / (1 + a * x ^ c) ^ 2
End Function
Public Function drdb(x As Double, a As Double, b As Double, c As Double) As Double
drdb = -x / (1 + a * x ^ c)
End Function
Public Function drdc(x As Double, a As Double, b As Double, c As Double) As Double
drdc = b * a * x ^ (1 + c) * Log(x) / (1 + a * x ^ c) ^ 2
End Function
Public Function f(x As Double, a As Double, b As Double, c As Double)
f = b * x / (1 + a * x ^ c)
End Function
Public Function r(ff As Double, x As Double, a As Double, b As Double, c As Double)
r = ff - f(x, a, b, c)
End Function
Public Sub newton(a As Double, b As Double, c As Double)
Dim aa(1 To 3, 1 To 3) As Double
Dim x As Variant
Dim y(1 To 3, 1 To 1) As Double
Dim xd As Variant, yd As Variant
Dim mi As Integer
Dim i As Integer, j As Integer
Dim dn As Integer
xd = Array(1.6, 4.52, 6.8, 8.16, 11.5, 12.7, 18.2, 29, 38.9, 57.3)
yd = Array(171, 228, 258, 284, 321, 335, 378, 401, 410, 429)
For mi = 1 To 100
For i = 1 To 3
For j = 1 To 3
aa(i, j) = 0
Next
y(i, 1) = 0
Next
For dn = 1 To 10
aa(1, 1) = aa(1, 1) + drda(CDbl(xd(dn - 1)), a, b, c) * drda(CDbl(xd(dn - 1)), a, b, c)
aa(2, 1) = aa(2, 1) + drda(CDbl(xd(dn - 1)), a, b, c) * drdb(CDbl(xd(dn - 1)), a, b, c)
aa(3, 1) = aa(3, 1) + drda(CDbl(xd(dn - 1)), a, b, c) * drdc(CDbl(xd(dn - 1)), a, b, c)
aa(1, 2) = aa(1, 2) + drdb(CDbl(xd(dn - 1)), a, b, c) * drda(CDbl(xd(dn - 1)), a, b, c)
aa(2, 2) = aa(2, 2) + drdb(CDbl(xd(dn - 1)), a, b, c) * drdb(CDbl(xd(dn - 1)), a, b, c)
aa(3, 2) = aa(3, 2) + drdb(CDbl(xd(dn - 1)), a, b, c) * drdc(CDbl(xd(dn - 1)), a, b, c)
aa(1, 3) = aa(1, 3) + drdc(CDbl(xd(dn - 1)), a, b, c) * drda(CDbl(xd(dn - 1)), a, b, c)
aa(2, 3) = aa(2, 3) + drdc(CDbl(xd(dn - 1)), a, b, c) * drdb(CDbl(xd(dn - 1)), a, b, c)
aa(3, 3) = aa(3, 3) + drdc(CDbl(xd(dn - 1)), a, b, c) * drdc(CDbl(xd(dn - 1)), a, b, c)
y(1, 1) = y(1, 1) + r(CDbl(yd(dn - 1)), CDbl(xd(dn - 1)), a, b, c) * drda(CDbl(xd(dn - 1)), a, b, c)
y(2, 1) = y(2, 1) + r(CDbl(yd(dn - 1)), CDbl(xd(dn - 1)), a, b, c) * drdb(CDbl(xd(dn - 1)), a, b, c)
y(3, 1) = y(3, 1) + r(CDbl(yd(dn - 1)), CDbl(xd(dn - 1)), a, b, c) * drdc(CDbl(xd(dn - 1)), a, b, c)
Next
x = WorksheetFunction.MMult(WorksheetFunction.MInverse(aa), y)
a = a - x(1, 1)
b = b - x(2, 1)
c = c - x(3, 1)
Debug.Print mi, a, b, c
Next
End Sub
Public Sub matrix()
Dim amin As Double, bmin As Double, cmin As Double
Dim ia As Double, ib As Double, ic As Double
Dim n As Integer
Dim ymin As Double
Dim y As Double
amin = 0
bmin = 150
cmin = 0
ymin = yy(amin, bmin, cmin)
For ia = 0 To 2 Step 0.1
For ib = 200 To 240
For ic = 0 To 2 Step 0.1
y = yy(ia, ib, ic)
If y < ymin Then
ymin = y
amin = ia
bmin = ib
cmin = ic
Debug.Print amin, bmin, cmin, y
End If
Next
Next
Next
Debug.Print amin, bmin, cmin
Call newton(amin, bmin, cmin)
End Sub
Public Function yy(a As Double, b As Double, c As Double) As Double
Dim xd As Variant, yd As Variant
Dim y As Double
Dim i As Integer
y = 0
xd = Array(1.6, 4.52, 6.8, 8.16, 11.5, 12.7, 18.2, 29, 38.9, 57.3)
yd = Array(171, 228, 258, 284, 321, 335, 378, 401, 410, 429)
For i = 1 To 10
y = y + r(CDbl(yd(i - 1)), CDbl(xd(i - 1)), a, b, c) ^ 2
Next
yy = y
End Function
|
まず関数rのa,b,cで偏微分した式を
定義しました。
求める関数fを定義しました
最小二乗法に使うrの式を定義しました。
この部分は、ニュートン法の関数の開始点です。
初期値をa,b,cを引数にしています。
行列に値の代入しています。
逆行列を算出して、Δa,Δb,Δcを求めるために行列の
積を計算しています
Δa,Δb,Δcの値が、xに現るので、
初期値のa,b,cを補正して、
新たな、初期値a,b,c,を求めました
一度の計算による、近似値の値の出力
収束しない場合等を考えて、
近似計算を100繰り返しています。
収束したら、プログラムをストップしたかったら
条件文等で、止めてもいいと思います。
今回の初期値を求めるために
a,b,cの取りうる値を推定して、
排^2が、最小値になる
求める解の近傍のa,b,cを求めています。
狽秩O2の関数です
|
|
|
|
|