9. 実装イメージ
9
Sub get_x(vector_Y, matrix_A)
For Row = 0 To matrix_Aのサイズ
' Step 1
‘ vector_Yもmatrix_AもRow行をmatrix_A(Row)(Row)で割る
' Step 2
For row2 = 0 To matrix_Aのサイズ
If Row <> row2 Then
For col = Row To matrix_Aのサイズ
‘ matrix_A(row2)(col)からmatrix_A(Row2)(Row) * matrix_A(Row)(col) を引く
‘ vector_Yも同様に処理する
Next col
End If
Next row2 Next Row
End Sub
@VBA
ループで全行処理
For row=0 to m-1
全ての行から引くので、
全体のループの中に
ループのある2重ルー
プ構造が必要と分かる。
𝑎𝑎𝑖𝑖𝑖𝑖で割る
正方行列を仮定
1次元ベクトルを仮定
10. 掃き出し法 実装例1
10
Function get_x_0(vector_Y_, matrix_A_)
' 掃き出し法により解を求める
vector_Y = vector_Y_ ' Variant型ならDeep copyされる
matrix_A = matrix_A_
For Row = 0 To UBound(vector_Y)
' row行の係数を(row行, row列)の係数で割る
coef = matrix_A(Row)(Row)
vector_Y(Row) = vector_Y(Row) / coef
For col = Row To UBound(vector_Y)
matrix_A(Row)(col) = matrix_A(Row)(col) / coef
Next col
' row行に(row2行, row列)の係数を掛けたものをrow2行から引く。ただしrow=row2は除く。
For row2 = 0 To UBound(vector_Y)
If Row <> row2 Then
coef = matrix_A(row2)(Row)
vector_Y(row2) = vector_Y(row2) - vector_Y(Row) * coef
For col = Row To UBound(vector_Y)
matrix_A(row2)(col) = matrix_A(row2)(col) - matrix_A(Row)(col) * coef
Next col
End If
Next row2
Next Row
get_x_0 = vector_Y
End Function
正方行列を仮定
1次元ベクトルを仮定
Step 1
Step2
@VBA
変数をDeep copyすることで、
引数への副作用を避けた
18. 行列の最終列にベクトルを
追加するコード例
18
𝑎𝑎11
𝑎𝑎21
𝑎𝑎31
⋮
𝑎𝑎 𝑚𝑚1
𝑎𝑎12
𝑎𝑎22
𝑎𝑎32
⋮
𝑎𝑎 𝑚𝑚2
⋯
𝑎𝑎1𝑛𝑛
𝑎𝑎2𝑛𝑛
𝑎𝑎3𝑛𝑛
⋮
𝑎𝑎 𝑚𝑚𝑚𝑚
Function matrix_append(matrix_A_, vector_Y_)
' 行列の最終列にvector_Y_の要素をコピーする。実用には要素数のチェックを入れたほうが良い。
new_matrix = matrix_A_
For i = 0 To UBound(new_matrix)
Dim row_data As Variant
row_data = new_matrix(i)
ReDim Preserve row_data(UBound(row_data) + 1) ' 内容保持したまま拡張
row_data(UBound(row_data)) = vector_Y_(i)
new_matrix(i) = row_data
Next i
matrix_append = new_matrix
End Function
@VBA
𝑎𝑎11
𝑎𝑎21
𝑎𝑎31
⋮
𝑎𝑎 𝑚𝑚1
𝑎𝑎12
𝑎𝑎22
𝑎𝑎32
⋮
𝑎𝑎 𝑚𝑚2
⋯
𝑎𝑎1𝑛𝑛
𝑎𝑎2𝑛𝑛
𝑎𝑎3𝑛𝑛
⋮
𝑎𝑎 𝑚𝑚𝑚𝑚
𝑦𝑦1
𝑦𝑦2
𝑦𝑦3
⋮
𝑦𝑦𝑚𝑚
𝑦𝑦1
𝑦𝑦2
𝑦𝑦3
⋮
𝑦𝑦𝑚𝑚
2つを結合し
て・・・と
19. 掃き出し法 実装例2
19
Function get_x_1(vector_Y_, matrix_A_)
' 掃き出し法により解を求める
matrix_data = matrix_append(matrix_A_, vector_Y_)
For Row = 0 To UBound(matrix_data)
' row行の係数を(row行, row列)の係数で割る
coef = matrix_data(Row)(Row)
For col = Row To UBound(matrix_data(0))
matrix_data(Row)(col) = matrix_data(Row)(col) / coef
Next col
' row行に(row2行, row列)の係数を掛けたものをrow2行から引く。ただしrow=row2は除く。
For row2 = 0 To UBound(matrix_data)
If Row <> row2 Then
coef = matrix_data(row2)(Row)
For col = Row To UBound(matrix_data(0))
matrix_data(row2)(col) = matrix_data(row2)(col) - matrix_data(Row)(col) * coef
Next col
End If
Next row2
Next Row
' 解を取り出す(なんて面倒なんだ)
Dim ans As Variant
ans = Array()
ReDim ans(UBound(matrix_data))
For i = 0 To UBound(matrix_data)
ans(i) = matrix_data(i)(UBound(matrix_data(0)))
Next i
get_x_1 = ans
End Function
matrix_dataはn行n+1列の2次元配列
Step 1
Step2
@VBA
*VBAでは行数が増えたが、
VBA以外ではシンプルになって
計算速度も上がる。
**逆行列計算での利用を視野に
入れると関数を整理した方が良
いが、ここでは考慮しない。
23. 23
Function get_x_2(vector_Y_, matrix_A_)
' 掃き出し法により解を求める
matrix_data = matrix_append(matrix_A_, vector_Y_)
For Row = 0 To UBound(matrix_data)
’最大係数となる行を探して、row行と入れ替える
switch_row_index = search_max_coef(Row, matrix_data)
matrix_data = switch_row(Row, switch_row_index, matrix_data)
' row行の係数を(row行, row列)の係数で割る
coef = matrix_data(Row)(Row)
For col = Row To UBound(matrix_data(0))
matrix_data(Row)(col) = matrix_data(Row)(col) / coef
Next col
' row行に(row2行, row列)の係数を掛けたものをrow2行から引く。ただしrow=row2は除く。
For row2 = 0 To UBound(matrix_data)
If Row <> row2 Then
coef = matrix_data(row2)(Row)
For col = Row To UBound(matrix_data(0))
matrix_data(row2)(col) = matrix_data(row2)(col) - matrix_data(Row)(col) * coef
Next col
End If
Next row2
Next Row
' 解を取り出す(なんて面倒なんだ)
Dim ans As Variant
ans = Array()
ReDim ans(UBound(matrix_data))
For i = 0 To UBound(matrix_data)
ans(i) = matrix_data(i)(UBound(matrix_data(0)))
Next i
get_x_2 = ans
End Function
掃き出し法 実装例3
係数値最大の行を探して、
row行と入れ替えている。
エラー対策のコードも仕込
めば、実用的に使える。
@VBA