Bullet_General.gif (3885 bytes) Matrix Inversion by Gauss-Jordan Elimination with maximization of pivot elements. (線上執行) (原始碼下載)

對於解決一般的矩陣求逆問題,傳統的 Matrix Inversion by Gauss-Jordan Elimination 就可應付,這部分上次已經介紹過了;但是如果遇到主對角線元素比其它元素小很多,或是主對角線元素等於零的線性聯立方程組,就必須用到 maximization of pivot elements 的技巧,因為主對角線元素很小將會產生嚴重的捨入誤差,導致計算結果錯誤的問題;主對角線元素為零,將會產生溢位的問題。

maximization of pivot elements 的演算法大致有三種 maximal column pivoting、scaled-column pivoting 以及 complete pivoting,以下要介紹的是 complete pivoting 應用於 Matrix Inversion by Gauss-Jordan Elimination 的演算法,complete pivoting 是三種方法中執行效率最差,但卻是可將捨入誤差降至最小的方法。(其實我對於 pivoting 並不很熟悉,如果說明有誤,請來信指正,謝謝!)

complete pivoting 演算法是將係數矩陣中絕對值最大的元素找出,稱此元素為 pivot element,一個 n×n 的係數矩陣必須找出 n 個 pivot element,每個 pivot element 不可同列或同行,因為若有兩個pivot element 同列或同行將無法進行 Gauss Jordan Elimination,以下以一個簡單的矩陣來說明 complete pivoting 應用於 Matrix Inversion by Gauss-Jordan Elimination 的演算法。左邊的 3×3 矩陣是欲求逆矩陣之矩陣,右邊的 3×3 矩陣是單位矩陣。

 

0	-1	3	1	0	0
1	0	-2	0	1	0
4	0	2	0	0	1
step1
0	-1	3	1	0	0
1	0	-2	0	1	0
1	0	1/2	0	0	1/4
step2
0	-1	3	1	0	0
0	0	-2/5	0	1	-1/4
1	0	1/2	0	0	1/4
step3
0	-1/3	1	1/3	0	0
0	0	-5/2	0	1	-1/4
1	0	1/2	0	0	1/4
step4
0	-1/3	1	1/3	0	0
0	-5/6	0	5/6	1	-1/4
1	1/6	0	-1/6	0	1/4
step5
0	-1/3	1	1/3	0	0
0	1	0	-1	-6/5	3/10
1	1/6	0	-1/6	0	1/4
step6
0	0	1	0	-2/5	1/10
0	1	0	-1	-6/5	3/10
1	0	0	0	1/5	1/5
step7
1	0	0	0	1/5	1/5
0	1	0	-1	-6/5	3/10
0	0	1	0	-2/5	1/10

 

step1:在左邊的 3×3 矩陣中絕對值最大的元素為 4,所以將第三列每個元素同除 4。

step2:執行消去法使得第一行的其餘元素為零。

step3:在左邊的 3×3 矩陣中絕對值最大的元素為 3,所以將第一列每個元素同除 3。

step4:執行消去法使得第三行的其餘元素為零。

step5:在左邊的 3×3 矩陣中絕對值最大的元素為 -5 / 6,所以將第二列每個元素同除 -5 / 6。

step6:執行消去法使得第二行的其餘元素為零。

step7:進行列對調使得左邊的 3×3 矩陣成為單位矩陣,則右邊的 3×3 矩陣即為逆矩陣。

副程式:

Public Sub MIMP(m() As Single, ReturnValue() As Single)
     Dim i As Long, j As Long, k As Long, n As Long
     Dim r() As Long, c() As Long, row As Long, temp() As Single
     Dim Pivot As Single, NoCompare As Boolean
     row = UBound(m, 1)
     If row <> UBound(m, 2) Then MsgBox "矩陣輸入有誤": Exit Sub
     ReDim r(1 To row), c(1 To row), temp(1 To row), ReturnValue(1 To row, 1 To row)
     For i = 1 To row
          ReturnValue(i, i) = 1
     Next
     For i = 1 To row
          Pivot = 0
          NoCompare = False
          For j = 1 To row
               For n = 1 To i - 1
                    NoCompare = (j = c(n))
                    If NoCompare Then Exit For
               Next n
               If Not NoCompare Then
                    For k = 1 To row
                         For n = 1 To i - 1
                              NoCompare = (k = r(n))
                              If NoCompare Then Exit For
                         Next n
                         If Not NoCompare Then
                              If Abs(m(k, j)) >= Pivot Then
                                   Pivot = Abs(m(k, j))
                                   r(i) = k: c(i) = j
                              End If
                         End If
                    Next k
               End If
          Next j
          Pivot = m(r(i), c(i))
          If Pivot <> 1 Then
               For k = 1 To row
                    m(r(i), k) = m(r(i), k) / Pivot
                    ReturnValue(r(i), k) = ReturnValue(r(i), k) / Pivot
               Next k
          End If
          For j = 1 To row
               Pivot = m(j, c(i))
               If j <> r(i) And Pivot <> 0 Then
                    For k = 1 To row
                         m(j, k) = m(j, k) - m(r(i), k) * Pivot
                         ReturnValue(j, k) = ReturnValue(j, k) - ReturnValue(r(i), k) * Pivot
                    Next
               End If
          Next j
     Next i
     For i = 1 To row - 1
          If r(i) <> c(i) Then
               For j = 1 To row
                    temp(j) = ReturnValue(r(i), j)
                    ReturnValue(r(i), j) = ReturnValue(c(i), j)
                    ReturnValue(c(i), j) = temp(j)
               Next
	       For j = i + 1 To row
                    If r(j) = c(i) Then r(j) = r(i): Exit For
               Next
               r(i) = c(i)
          End If
     Next
End Sub

參數說明:

  • m:欲求逆矩陣之矩陣。
  • ReturnValue:傳回計算後之逆矩陣。

範例:

1.由鍵盤輸入矩陣元素:

Private Sub Command1_Click()
     Dim Keyin As String, m() As Single, x() As Single
     Keyin = InputBox("請輸入方陣,以分號"";""來分隔列元素,以空白來分隔欄元素。" _
               & vbNewLine & "例如有一3×3的方陣:" & vbNewLine & "1 2 3 " & vbNewLine & _
               "4 5 6 " & vbNewLine & "7 8 9 " & vbNewLine & "則輸入: 1 2 3;4 5 6;7 8 9 ")
     If SepStrToMatrix(Keyin, ";", " ", m) Then
          Call MIMP(m, x)
          Call PrintMatrix(x)
     Else
          MsgBox "方陣輸入有誤,請重新輸入。"
     End If
End Sub

其中 SepStrToMatrix 和 PrintMatrix這兩個副程式,請參閱本站的 將字串拆解成陣列

若有一矩陣如下:

0	-1	3	
1	0	-2	
4	0	2	

以上矩陣若沒有使用 maximization of pivot elements 的技巧來求逆矩陣的話,一定會出現溢位的問題。

執行 Command1 之後,在 VB5 的即時運算視窗可得此矩陣之逆矩陣。

0  0.2  0.2 
-1 -1.2  0.3 
 0 -0.4  9.999999E-02 

 

2.由檔案讀入矩陣元素:

Private Sub Command2_Click()
     Dim FileNo As Long, Keyin As String, temp As String, m() As Single, x() As Single
     FileNo = FreeFile
     Open "c:\main.txt" For Input As #FileNo
     Do While Not EOF(FileNo)
          Line Input #FileNo, temp
          If Trim(temp) <> "" Then Keyin = Keyin & temp & ";"
     Loop
     Close #FileNo
     Keyin = Mid(Keyin, 1, Len(Keyin) - 1)
     If SepStrToMatrix(Keyin, ";", " ", m) Then
          Call MIMP(m, x)
          Call PrintMatrix(x)
     Else
          MsgBox "方陣輸入有誤,請重新輸入。"
     End If
End Sub

其中 SepStrToMatrix 和 PrintMatrix這兩個副程式,請參閱本站的 將字串拆解成陣列

若有一矩陣儲存在"C:\main.txt"

-1 1 16 2
0 0 1 4
0 0 1 6
0 1 1 -3

以上矩陣若沒有使用 maximization of pivot elements 的技巧來求逆矩陣的話,一定會出現溢位的問題。

執行 Command2 之後,在 VB5 的即時運算視窗可得此矩陣之逆矩陣。

-1  42.5 -27.5  1 
 0 -4.5  3.5  0.9999999 
 0  3 -2  0 
 0 -0.5  0.4999999  0 

 

MIMP 副程式中的 " If Pivot <> 1 Then ",是為了略去除數為 1 的除法運算,還有 " If j<>r(i) And Pivot <> 0 Then ",是為了略去乘數為 0 的乘法運算,最終目的都是為了提昇執行速度。

如果是奇異矩陣求逆之問題,使用 MIMP 副程式將會出現溢位之問題,或是算出數值很大之逆矩陣,但是這個逆矩陣是錯誤的結果,你可以將原矩陣和算出之逆矩陣相乘,看看是否為單位矩陣,以確保計算結果之正確性,這點要非常注意。

另外,AX=B 之線性方程組也可以用逆矩陣的方式解出 X,X=A-1B,但是並不建議使用這種方式做,因為逆矩陣的計算效率比較差。

 


[ 上一個 | 首頁 | 數值分析 | 下一個 ]

This page was written by Jaric on Nov. 8 , 1998. All rights reserved.

Revised : Apr. 20 , 1999 .

Total pageview since 4/6/1999.