3.4 矩阵广义逆

文章目录

  • 定义
  • 算法
  • 举例
  • 齐次方程组通解
  • 非齐次方程组通解
  • Python实现

定义

  矩阵的一号逆,是对矩阵逆的推广。对于线性方程组 A x = b A\bold x=\bold b Ax=b来说,如果 A A A可逆,那么它的解就是 x = A − 1 b x=A^{-1}b x=A1b。然后对于不可逆的方程,可不可以找到一个矩阵 G G G,使得 G b G\bold b Gb是方程的解呢?对于相容方程组,答案是肯定的,这个矩阵 G G G就是矩阵的一号逆 1 − i n v e r s e 1-inverse 1inverse,也叫减号逆,或广义逆generalized inverse,记号为 A − A^- A。它的定义是:
A A − A = A AA^-A=A AAA=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.667100000.3331000001000
  再进行初等列变换:
( 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} 10010001020100011010.667100000.3331000001000
  所以得到了 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.667100.3331001 Q= 100201110
   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.66700.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 (EnAA)y,yRn
  公式中的 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 Ab+(EnAA)y,yRn
  同样,需要展开表示。

Python实现

  减号逆的实现,我用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

你可能感兴趣的:(线性代数【更新中】,矩阵,线性代数,人工智能)