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 1step1
→ 0 -1 3 1 0 0 1 0 -2 0 1 0 1 0 1/2 0 0 1/4step2
→ 0 -1 3 1 0 0 0 0 -2/5 0 1 -1/4 1 0 1/2 0 0 1/4step3
→ 0 -1/3 1 1/3 0 0 0 0 -5/2 0 1 -1/4 1 0 1/2 0 0 1/4step4
→ 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/4step5
→ 0 -1/3 1 1/3 0 0 0 1 0 -1 -6/5 3/10 1 1/6 0 -1/6 0 1/4step6
→ 0 0 1 0 -2/5 1/10 0 1 0 -1 -6/5 3/10 1 0 0 0 1/5 1/5step7
→ 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.