列主元方法是一種用于求解矩陣逆的數值方法,特別適用于在計算機上實現。其基本思想是通過高斯消元法將矩陣轉換為上三角矩陣,然后通過回代求解矩陣的逆。以下是列主元方法求解矩陣 A A A 的逆的步驟:
[精確算法] 列主元高斯消元法
步驟 1:初始化
構造增廣矩陣 [ A ∣ I ] [A | I] [A∣I],其中 I I I 是 n n n 階單位矩陣。
步驟 2:列主元選擇
對于第 k k k 列( k = 1 , 2 , … , n k = 1, 2, \ldots, n k=1,2,…,n),找到列主元,即找到 i k i_k ik? 使得:
∣ a i k , k ∣ = max ? i ≥ k ∣ a i , k ∣ |a_{i_k,k}| = \max_{i \geq k} |a_{i,k}| ∣aik?,k?∣=i≥kmax?∣ai,k?∣
如果 i k ≠ k i_k \neq k ik?=k,則交換第 k k k 行和第 i k i_k ik? 行。
步驟 3:高斯消元
對于每一列 k k k( k = 1 , 2 , … , n ? 1 k = 1, 2, \ldots, n-1 k=1,2,…,n?1),進行以下操作:
- 歸一化第 k k k 行的列主元:
a k , k ← 1 a k , k a_{k,k} \leftarrow \frac{1}{a_{k,k}} ak,k?←ak,k?1? - 更新第 k k k 行的其他元素:
a k , j ← a k , j a k , k 對于所有? j ≠ k a_{k,j} \leftarrow \frac{a_{k,j}}{a_{k,k}} \quad \text{對于所有 } j \neq k ak,j?←ak,k?ak,j??對于所有?j=k - 消去下方所有行的第 k k k 列元素:
對于所有 i > k i > k i>k,計算:
m i , k = a i , k m_{i,k} = a_{i,k} mi,k?=ai,k?
然后更新第 i i i 行:
a i , j ← a i , j ? m i , k ? a k , j 對于所有? j a_{i,j} \leftarrow a_{i,j} - m_{i,k} \cdot a_{k,j} \quad \text{對于所有 } j ai,j?←ai,j??mi,k??ak,j?對于所有?j
步驟 4:回代求解
當矩陣 A A A 被轉換為上三角矩陣后,從最后一行開始回代:
對于每一行 k k k( k = n , n ? 1 , … , 1 k = n, n-1, \ldots, 1 k=n,n?1,…,1),進行以下操作: - 歸一化第 k k k 行的最后一個非零元素(即對角線元素):
a k , k ← 1 a k , k a_{k,k} \leftarrow \frac{1}{a_{k,k}} ak,k?←ak,k?1? - 更新第 k k k 行的其他元素:
a k , j ← a k , j a k , k 對于所有? j ≠ k a_{k,j} \leftarrow \frac{a_{k,j}}{a_{k,k}} \quad \text{對于所有 } j \neq k ak,j?←ak,k?ak,j??對于所有?j=k - 消去上方所有行的第 k k k 列元素:
對于所有 i < k i < k i<k,計算:
m i , k = a i , k m_{i,k} = a_{i,k} mi,k?=ai,k?
然后更新第 i i i 行:
a i , j ← a i , j ? m i , k ? a k , j 對于所有? j a_{i,j} \leftarrow a_{i,j} - m_{i,k} \cdot a_{k,j} \quad \text{對于所有 } j ai,j?←ai,j??mi,k??ak,j?對于所有?j
步驟 5:結果提取
經過上述步驟后,增廣矩陣的左側變為單位矩陣,而右側則變為了 A A A 的逆矩陣 A ? 1 A^{-1} A?1。提取右側的矩陣即為所求的逆矩陣。
需要注意的是,上述公式中的 a i , j a_{i,j} ai,j? 表示增廣矩陣中的元素,包括原矩陣 A A A 和單位矩陣 I I I 的部分。在實際計算中,這些操作會同時應用于 A A A 和 I I I,最終 I I I 的位置會被 A ? 1 A^{-1} A?1 所取代。
此外,如果在任何步驟中發現對角線上的元素 a k , k a_{k,k} ak,k? 為零或非常接近零,那么矩陣 A A A 可能是奇異矩陣,無法求逆。在這種情況下,算法應該停止并報錯。
Julia 代碼
美化數據格式
using DataFrames
function pm(A,b)m,n=size(A); z=[]for i=1:n st=iz=[z; "a:$st"]endfor i=1:nst=iz=[z;"b:$st"]endprintln(DataFrame([A b],z))
end
function luInv(A,par=false)n=size(A,1);T=typeof(A[1,1])A=copy(A); E = zeros(T,n,n); for i=1:n E[i,i]=1//1 endif par pm(A, E) endif par println("化為上三角") endfor i=1:n-1id=argmax(abs.(A[i:n,i])) # 尋找列主元 id=id-1A[i,i:n], A[i+id,i:n]= A[i+id,i:n],A[i,i:n]E[i,:], E[i+id,:] =E[i+id,:], E[i,:]for j=i+1:nc=A[j,i]/A[i,i]E[j,:]=E[j,:]-E[i,:]*cA[j,i:n]=A[j,i:n]-A[i,i:n]*cendif par pm(A, E) endendif par println("化為對角") endfor i=n:-1:2for j=1:i-1c=A[j,i]/A[i,i]E[j,:]=E[j,:]-E[i,:]*cA[j,1:i]=A[j,1:i]-A[i,1:i]*cendif par pm(A, E) endendIA=copy(E);for j=1:nIA[j,:] = E[j,:]/A[j,j]; A[j,j]=A[j,j]/A[j,j]endif par pm(A, IA) endreturn(IA)
end
舉例
n=3;
A=zeros(Rational,n,n)
for i=1:n-1A[i,i]=0;A[i,i+1]=11//1;A[i+1,i]=7//1;
end
A[n,n]=3//1;
IA=luInv(A,true)