矩阵的一号逆,是对矩阵逆的推广。对于线性方程组 A x = b A\bold x=\bold b Ax=b来说,如果 A A A可逆,那么它的解就是 x = A − 1 b x=A^{-1}b x=A−1b。然后对于不可逆的方程,可不可以找到一个矩阵 G G G,使得 G b G\bold b Gb是方程的解呢?对于相容方程组,答案是肯定的,这个矩阵 G G G就是矩阵的一号逆 1 − i n v e r s e 1-inverse 1−inverse,也叫减号逆,或广义逆generalized inverse,记号为 A − A^- A−。它的定义是:
A A − A = A AA^-A=A AA−A=A
符合这个定义的所有矩阵都是矩阵的减号逆,对于可逆矩阵来说,减号逆只有一个,对于不可逆矩阵来说,减号逆存在多个。
根据定义是很难求出减号逆的。求减号逆的办法是将矩阵先扩充变成一个方阵,变成下面这个样子:
( A m × n E m × m E n × n 0 ) \begin{pmatrix} A_{m \times n} &E_{m \times m}\\ E_{n \times n} & 0 \end{pmatrix} (Am×nEn×nEm×m0)
通过填充把矩阵变成了 ( m + n ) × ( m + n ) (m+n) \times (m+n) (m+n)×(m+n)的矩阵,再进行初等行变换与初等列变换,将左上角变成单位矩阵 E r E_r Er,其中 r r r是矩阵的秩,这样这个扩充的矩阵就变成这个样子:
( E r P Q 0 ) \begin{pmatrix} E_{r} & P\\ Q & 0 \end{pmatrix} (ErQP0)
最后的减号逆就是一个矩阵乘法就出来了:
A − = Q ( E r ∗ ∗ ∗ ) n × m P A^{-}=Q\begin{pmatrix} E_{r} & \ast\\ \ast & \ast \end{pmatrix}_{n \times m}P A−=Q(Er∗∗∗)n×mP
这里的 ∗ \ast ∗表示放什么数字都可以了。为了计算方便,可以全部取0。
以下是矩阵:
A = ( 1 1 2 2 2 1 3 3 3 ) A=\begin{pmatrix}1 & 1 & 2\\ 2 & 2 & 1\\ 3 & 3 & 3\\ \end{pmatrix} A= 123123213
扩展成大矩阵:
( 1 1 2 1 0 0 2 2 1 0 1 0 3 3 3 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 ) \begin{pmatrix}1 & 1 & 2 & 1 & 0 & 0\\ 2 & 2 & 1 & 0 & 1 & 0\\ 3 & 3 & 3 & 0 & 0 & 1\\ 1 & 0 & 0 & 0 & 0 & 0\\ 0 & 1 & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 & 0\\ \end{pmatrix} 123100123010213001100000010000001000
先初等行变换:
( 1 1 2 1 0 0 0 0 1 0.667 − 0.333 0 0 0 0 − 1 − 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 ) \begin{pmatrix}1 & 1 & 2 & 1 & 0 & 0\\ 0 & 0 & 1 & 0.667 & -0.333 & 0\\ 0 & 0 & 0 & -1 & -1 & 1\\ 1 & 0 & 0 & 0 & 0 & 0\\ 0 & 1 & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 & 0\\ \end{pmatrix} 10010010001021000110.667−10000−0.333−1000001000
再进行初等列变换:
( 1 0 0 1 0 0 0 1 0 0.667 − 0.333 0 0 0 0 − 1 − 1 1 1 − 2 − 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 ) \begin{pmatrix}1 & 0 & 0 & 1 & 0 & 0\\ 0 & 1 & 0 & 0.667 & -0.333 & 0\\ 0 & 0 & 0 & -1 & -1 & 1\\ 1 & -2 & -1 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0 & 0 & 0\\ \end{pmatrix} 100100010−201000−11010.667−10000−0.333−1000001000
所以得到了 P , Q P,Q P,Q,以下就是:
P = ( 1 0 0 0.667 − 0.333 0 − 1 − 1 1 ) Q = ( 1 − 2 − 1 0 0 1 0 1 0 ) P=\begin{pmatrix}1 & 0 & 0\\ 0.667 & -0.333 & 0\\ -1 & -1 & 1\\ \end{pmatrix}\\ Q=\begin{pmatrix}1 & -2 & -1\\ 0 & 0 & 1\\ 0 & 1 & 0\\ \end{pmatrix} P= 10.667−10−0.333−1001 Q= 100−201−110
E r E_r Er剩余部位全为0的减号逆为:
A − = Q ( E r 0 0 0 ) n × m P = ( − 0.333 0.667 0 0 0 0 0.667 − 0.333 0 ) A^-=Q\begin{pmatrix} E_{r} & 0\\ 0 & 0 \end{pmatrix}_{n \times m}P=\begin{pmatrix}-0.333 & 0.667 & 0\\ 0 & 0 & 0\\ 0.667 & -0.333 & 0\\ \end{pmatrix} A−=Q(Er000)n×mP= −0.33300.6670.6670−0.333000
通过矩阵的减号逆,可以获取齐次方程组的所有解。虽然之前说过求齐次方程组通解的办法。但是这里给出另外一种办法,这种办法就是利用矩阵的减号逆,齐次方程组 A x = 0 A\bold x=\bold 0 Ax=0的通解是:
( E n − A − A ) y , y ∈ R n (E_n-A^-A)\bold y,\bold y \in R^n (En−A−A)y,y∈Rn
公式中的 y y y是任意变量,不过这种形式表示通解不太方便。因为还需要继续展开计算,才可以变成自由变量与基的线性组合。
同样非齐次方程组的解也可以用减号逆表示,我们知道非齐次方程组的解就是特解加上齐次方程组的通解,所以对于 A x = b A\bold x=\bold b Ax=b,所有的解就是:
A − b + ( E n − A − A ) y , y ∈ R n A^-\bold b+(E_n-A^-A)\bold y,\bold y \in R^n A−b+(En−A−A)y,y∈Rn
同样,需要展开表示。
减号逆的实现,我用python实现了一下,只贴了部分代码:
# 减号逆
def one_inverse(self):
form, echelons = self.to_p_q_form()
# 再获取Q矩阵,P矩阵
m = len(self.__vectors[0])
n = len(self.__vectors)
p_array = [[0 for _ in range(m)] for _ in range(m)]
for column in range(n, m + n):
for line in range(0, m):
p_array[column - n][line] = form.__vectors[column][line]
q_array = [[0 for _ in range(n)] for _ in range(n)]
for column in range(0, n):
for line in range(m, m + n):
q_array[column][line - m] = form.__vectors[column][line]
er_array = [[0 for _ in range(n)] for _ in range(m)]
for i, echelon in enumerate(echelons):
if echelon[0] >= n:
break
er_array[i][i] = 1
q = Matrix(q_array)
er = Matrix(er_array)
p = Matrix(p_array)
return (q * er )* p
# pq型
def to_p_q_form(self):
m = len(self.__vectors[0])
n = len(self.__vectors)
new_matrix = self.expand_q_r_form(m, n)
new_matrix = new_matrix.to_upper_triangle(last_line=m)
# 变成阶梯形后,每一行除于自己的主元系数
echelons = new_matrix.get_echelons()
vectors = new_matrix.__vectors
for line, echelon in enumerate(echelons):
column = echelon[0]
if column >= n:
break
matrix_utils.row_times(vectors, line, 1 / vectors[column][line])
# 循环阶梯进行初等列变换,将右面都变成0
for line, echelon in enumerate(echelons):
# 把右边全变成0
main_column = echelon[0]
pivot = vectors[main_column][line]
for column in range(main_column + 1, n):
line_pivot = -vectors[column][line] / pivot
matrix_utils.column_times_add(vectors, main_column, line_pivot, column)
# 再进行初等列变换,将主元列移动到前面
for line, echelon in enumerate(echelons):
main_column = echelon[0]
if main_column >= n:
break
matrix_utils.column_swap(vectors, main_column, line)
return new_matrix, echelons
def expand_q_r_form(self, m, n):
# 组建一个新矩阵
vectors = [[0 for _ in range(m + n)] for _ in range(m + n)]
# 先将矩阵复制进去
for i, vector in enumerate(self.__vectors):
for j, e in enumerate(vector):
vectors[i][j] = e
# 右边放一个
for column in range(n, m + n):
vectors[column][column - n] = 1
# 下面放一个
for row in range(m, m + n):
vectors[row - m][row] = 1
# 行变换到阶梯形
new_matrix = Matrix(vectors)
return new_matrix