欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

线性代数组织(III)确定特征值和特征向量

最编程 2024-03-03 09:19:47
...

线性代数整理(二)

行列式

行列式是方阵的一个属性

矩阵可以表示一组向量,方阵表示n个n维向量,用一个数字表示这些向量组的不同?

比方说在二维平面中,这里有三组二维向量,每组都有两个向量,那么每组向量的面积就可以表示它们的不同。当然这里说面积是针对二维平面来说的,在三维空间中,就是体积;在更高维度中,可能就是一个体,但这个体比较抽象

行列式描述的就是n个n维向量所组成的这样一个体的属性。我们从二维空间入手,来看一看行列式是怎么计算的

像这样的两个向量所组成的行列式,我们记作

,这里我们可以看到,这两个向量,在行列式中,我们是按行来排列的。但其实按行排列还是按列排列都是可以的,是无所谓的。对于行列式,也可以表示成

,而求它的值,实际上就是求上图中平行四边形的面积。

通过做绿色的辅助线,可得这个平行四边形的面积=(a + c)(b + d) - 2bc - cd - ab = ad - bc

对于二阶方阵来说,它的行列式的值为主对角线上的乘积减去非主对角线上的乘积。

反过来,则

,由此,我们可以看出

行列式表示向量组在空间中形成的有向体积

对于二维空间,我们往往是先从x轴看向y轴,则对于上面的u和v两个向量来说,从u到v的逆时针方向上,我们就认为它的行列式就是正的。而从u到v的顺时针方向上,我们就认为它的行列式是负的。

但是在三维或以上的空间中,体积的方向将变得极其复杂。简单说,在行列式中,向量排列的顺序是有意义的。在n阶行列式中,任意交换两行,则行列式的值取反。

行列式的基本性质

  1. 单位矩阵的行列式等于1,即det I = 1
  2. 交换行列式的两行,则行列式的值取反。
  3. 方阵的某一行乘以一个数k,则其对应的行列式也缩放了k倍,即

,比如

(a,b)这个向量扩展了两倍,则这个平行四边形的面积也扩展了两倍。这里需要注意的是,是其中的某一行,而不是所有行,这和矩阵的数量乘法是不一样的。

(其中A为方阵);而正确的写法为

,,其中n是指A为n阶方阵。

  1. 方阵中的某一行加上一行数,则有:

,它其实表示的是一个向量相加,当然我们也可以直接代进公式,左边 = (a + a')d - (b + b')c = ad + a'd - bc - b'c。右边= ad - bc + a'd - b'c,说明左边=右边

这里的第4和第3条是行列式的加法和数量乘法,这是非常有意义的两种基本运算。

行列式和矩阵的逆

性质一:如果行列式的两行相同,则行列式的值为0。

证明: 假设方阵A交换两行后为A'

det(A) = -det(A'),因为两行相同,所以A = A'

det(A) = -det(A) 则det(A) = 0,得证

从直观上考虑:二维空间中,两个向量共线,面积为0;在三维空间中,两个向量共线,形成一个平面,体积为0;n维空间中,两个向量共线,则退化成一个n-1维的体,它的n维的体积为0。

性质二:如果行列式的一行是另一行的k倍,则行列式的值为0.

证明:

这一条跟上面一条在直观上理解是一样的,因为它们共线。

性质三:如果行列式有一行为0,则行列式的值为0。

证明:

在直观上理解,就是一个n维体中,有一个零向量,则这个n维体退化成了n-1维体,它的n维的体积为0

性质四:如果行列式的一行是其他行的线性组合,则行列式的值为0。

证明:

这是根据行列式的加法以及性质二来证明的。从n维空间的角度考虑,如果有两行线性相关,则无法构成n维空间的一组基,就算其他行都线性无关,也退化成n-1维空间,它的n维空间的体积为0.

行列式形成一个向量组,如果这组向量线性相关,则行列式的值为0,det(A)=0

矩阵不可逆

如果这组向量线性无关,则行列式的值不为0,det(A)≠0

矩阵可逆

现在对于方阵A的等价命题又可以增加一条

  1. 对于方阵A,矩阵A可逆,A是非奇异矩阵
  2. 线性系统Ax=0(齐次线性方程组)只有唯一解,x=0
  3. 矩阵的行最简形式rref(A)=I
  4. A可以表示成一系列初等矩阵的乘积
  5. Ax=b只有唯一解
  6. 方阵A的列向量线性无关
  7. 方阵A的列向量可以生成n维空间
  8. 方阵A的列向量是n维空间的基
  9. 方阵A为满秩矩阵(秩=n)
  10. 方阵A的行秩为n
  11. 方阵A的列秩为n
  12. 方阵A的行空间为
  1. 方阵A的列空间为
  1. 方阵A的零空间为{O},维度为0
  2. det(A)≠0

计算行列式的算法

如果一个行列式的一行加(减)另一行的k倍,行列式的值不变。

证明:

这条性质是计算行列式的值的基础。

一个方阵行列式的值

  1. 等于其进行高斯消元法后的结果

上三角矩阵U

  1. 等于其进行高斯-约旦消元法后的结果

对角矩阵D(只有主对角线上的元素为非零元素,其他位置上的元素都为0)

但是这个高斯-约旦消元法跟之前讲线性系统时候的有所不同,它不能进行归一化操作。因为一旦进行归一化操作,行列式的值就发生了变化,这跟矩阵的性质是不一样的,归一化的本质就是某一行乘以了某个常数k,行列式的值就扩大了k倍。并且进行行置换和列置换需要改变行列式的正负号,因为任意交换两行,行列式的值取反。如果消元结果有零行,行列式的值为0。

对角矩阵的行列式

上三角矩阵的行列式

其实上三角矩阵的行列式跟对角矩阵的行列式的值是相同的,也是

,这是因为在进行约旦消元法的过程中,将主元列上面的数减去主元值乘以一个系数,全部化成0,也就变成了对角矩阵,而主元列的主元值都不变。

下三角矩阵的行列式

跟上三角矩阵的求法类似,进行高斯消元法就好,最后依然是一个对角矩阵,而主元列的主元值不变,依然为

所以上面的计算行列式的值不需要进行约旦消元法,只需要进行高斯消元法即可。

简单用2阶行列式进行验证

新增一个接口Formula

public interface Formula<T extends Number> {
    /**
     * 求行列式的值
     * @return
     */
    T result(Addr<T> addr);
}

行列式实现类

@ToString
public class Determinant<T extends Number> implements Formula<T> {
    //原始方阵
    private Ranks<T> source;
    //高斯消元法后的方阵
    private Ranks<T> matrix;

    @SuppressWarnings("unchecked")
    public Determinant(Ranks<T> matrix) throws CloneNotSupportedException {
        if (matrix.rowNum() != matrix.colNum()) {
            throw new IllegalArgumentException("矩阵必须为方阵");
        }
        this.source = matrix;
        this.matrix = ((Matrix) matrix).clone();
    }

    @Override
    public T result(Addr<T> addr) {
        T res = addr.one();
        int times = forword(addr);
        for (int i = 0; i < matrix.rowNum(); i++) {
            res = addr.mul(res,matrix.get(new int[]{i,i}));
        }
        //交换次数为奇数,结果取负
        if ((times & 1) == 1) {
            return addr.neg(res);
        }
        return res;
    }

    /**
     * 高斯消元,此处不可做归一化处理
     * @param addr
     * @return
     */
    @SuppressWarnings("unchecked")
    private int forword(Addr<T> addr) {
        int i = 0;
        int k = 0;
        //交换位置的次数
        int times = 0;
        while (i < matrix.rowNum() && k < matrix.colNum()) {
            int maxRow = maxRow(i, k, matrix.rowNum(), addr);
            T[] temp = (T[]) new Number[matrix.colNum()];
            if (maxRow != i) {
                times++;
            }
            //每一行无论是否有主元,都与主元最大值所在行进行交换
            for (int j = 0; j < matrix.colNum(); j++) {
                temp[j] = matrix.get(new int[]{i, j});
                matrix.set(new int[]{i, j}, matrix.get(new int[]{maxRow, j}));
                matrix.set(new int[]{maxRow, j}, temp[j]);
            }
            if (addr.equals(matrix.get(new int[]{i,k}),addr.zero())) {
                k++;
            }else {
                //将主元所在行以下的行的所有非主元数据全部变成0
                for (int m = i + 1; m < matrix.rowNum(); m++) {
                    T u1 = matrix.get(new int[]{m, k});
                    for (int l = 0; l < matrix.colNum(); l++) {
                        matrix.set(new int[]{m, l}, addr.sub(matrix.get(new int[]{m, l}),
                                addr.mul(matrix.get(new int[]{i, l}),
                                        addr.div(u1,matrix.get(new int[]{i,k})))));
                    }
                }
                i++;
            }
        }
        return times;
    }

    /**
     * 获取主元最大值所在的行
     * @param addr
     * @return
     */
    private int maxRow(int indexI,int indexJ,int n,Addr<T> addr) {
        T best = matrix.get(new int[]{indexI,indexJ});
        int ret = indexI;
        for (int i = indexI + 1; i < n; i++) {
            if (addr.compair(matrix.get(new int[]{i,indexJ}),best) == 1) {
                best = matrix.get(new int[]{i,indexJ});
                ret = i;
            }
        }
        return ret;
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        Addr<Double> addr = new Addr<Double>() {
            @Override
            public Double zero() {
                return 0.0;
            }

            @Override
            public Double one() {
                return 1.0;
            }

            @Override
            public Double add(Double lhs, Double rhs) {
                return lhs + rhs;
            }

            @Override
            public Double sub(Double lhs, Double rhs) {
                return lhs - rhs;
            }

            @Override
            public Double mul(Double k, Double hs) {
                return k * hs;
            }

            @Override
            public Double square(Double hs) {
                return hs * hs;
            }

            @Override
            public double prescription(Double hs) {
                return Math.sqrt(hs);
            }

            @Override
            public double div(Double hs, double nhs) {
                return hs / nhs;
            }

            @Override
            public Double div(Double hs, Double nhs) {
                return hs / nhs;
            }

            @Override
            public double acos(double hs) {
                return Math.acos(hs);
            }
            @Override
            public double toDegree(double hs) {
                return Math.toDegrees(hs);
            }

            @Override
            public int compair(Double lhs, Double rhs) {
                if (lhs - rhs > 0) {
                    return 1;
                }else if (lhs - rhs < 0) {
                    return -1;
                }else {
                    return 0;
                }
            }

            @Override
            public boolean equals(Double lhs, Double rhs) {
                double dis = 1e-8;
                if (Math.abs(lhs - rhs) < dis) {
                    return true;
                }
                return false;
            }

            @Override
            public Double neg(Double hs) {
                return -hs;
            }
        };
        Ranks<Double> matrix = new Matrix<>(new Double[][]{{7.0,3.0},{2.0,5.0}});
        Formula<Double> determinant = new Determinant<>(matrix);
        System.out.println(determinant.result(addr));
        System.out.println(determinant);
    }
}

运行结果

29.000000000000004
Determinant(source=Matrix{values=[[7.0, 3.0],[2.0, 5.0]]}, matrix=Matrix{values=[[7.0, 3.0],[0.0, 4.142857142857143]]})

Python代码

from ._global import is_zero
from .Matrix import Matrix

class Determinant:

    def __init__(self, matrix):
        assert matrix.row_num() == matrix.col_num(), "矩阵必须为方阵"
        self._source = matrix
        self._matrix = [matrix.row_vector(i) for i in range(matrix.row_num())]

    def result(self):
        # 求行列式的值
        res = 1
        times = self._forword()
        for i in range(len(self._matrix)):
            res *= self._matrix[i][i]
        if times % 2 == 1:
            return -res
        return res

    def _forword(self):
        # 高斯消元,此处不可做归一化处理
        i, k, times = 0, 0, 0
        while i < len(self._matrix) and k < len(self._matrix[0]):
            # 看matrix[i][k]位置是否可以为主元
            max_row = self._max_row(i, k, len(self._matrix))
            if max_row != i:
                times += 1
            self._matrix[i], self._matrix[max_row] = self._matrix[max_row], self._matrix[i]
            if is_zero(self._matrix[i][k]):
                k += 1
            else:
                for j in range(i + 1, len(self._matrix)):
                    self._matrix[j] = self._matrix[j] - self._matrix[j][k] * (self._matrix[i] / self._matrix[i][k])
                i += 1
        return times

    def _max_row(self, index_i, index_j, n):
        # 主元最大值所在的行
        best, ret = self._matrix[index_i][index_j], index_i
        for i in range(index_i + 1, n):
            if self._matrix[i][index_j] > best:
                best, ret = self._matrix[i][index_j], i
        return ret

    def __repr__(self):
        return "Determinant({},{})".format(self._source, Matrix(self._matrix))

    __str__ = __repr__
from playLA.Determinant import Determinant
from playLA.Matrix import Matrix

if __name__ == "__main__":
    matrix = Matrix([[7, 3], [2, 5]])
    determinant = Determinant(matrix)
    print(determinant.result())
    print(determinant)

运行结果

29.000000000000004
Determinant(Matrix([[7, 3], [2, 5]]),Matrix([[7, 3], [0.0, 4.142857142857143]]))

初等矩阵与行列式

之前我们讲的性质都可以从几何方面来进行理解,但是对于这个性质对于几何来讲就没什么用了,因为对于两个空间体体积的乘积,在几何上的意义就不那么明确了。所以我们要从纯代数的角度出发,来进行证明。

首先,如果A或者B中的某一行和其他行线性相关,则

,假设A中某一行和其他行线性相关,则

的结果矩阵中依然会保持线性相关性。

,所以在这种情况下,等式的两边成立。

现在我们来看A和B中的所有行都线性无关,从方阵的等价命题中

  1. 对于方阵A,矩阵A可逆,A是非奇异矩阵
  2. 线性系统Ax=0(齐次线性方程组)只有唯一解,x=0
  3. 矩阵的行最简形式rref(A)=I
  4. A可以表示成一系列初等矩阵的乘积
  5. Ax=b只有唯一解
  6. 方阵A的列向量线性无关
  7. 方阵A的列向量可以生成n维空间
  8. 方阵A的列向量是n维空间的基
  9. 方阵A为满秩矩阵(秩=n)
  10. 方阵A的行秩为n
  11. 方阵A的列秩为n
  12. 方阵A的行空间为
  1. 方阵A的列空间为
  1. 方阵A的零空间为{O},维度为0
  2. det(A)≠0

我们可以看到第4条,这表示A或者B都能表示为一系列初等矩阵的乘积。而初等矩阵是对单位矩阵进行初等变换(行操作),则我们把A拆解成一系列初等矩阵

,进而我们需要研究一下初等矩阵的行列式

初等矩阵的变换一共有三种形式

  1. 如果E是单位矩阵的某一行乘以k,很明显 det(E) = k
  2. 如果E是单位矩阵的某两行交换位置,很明显 det(E) = -1
  3. 如果E是单位矩阵的某行加(减)另一行的k倍 det(E) = 1

现在我们需要先证明这个命题

现在我们依然分三种情况来证明

  1. 如果E是单位矩阵的某一行乘以k,方阵EB是B中的某一行乘以k,则

,而等式右边

,左右相等,在该种情况下得证。

  1. 如果E是单位矩阵的某两行交换位置,方阵EB是B中某两行交换位置,

,等式右边

,左右相等,在该种情况下得证。

  1. 如果E是单位矩阵的某行加(减)另一行的k倍,方阵EB是B中的某行加(减)另一行的k倍,

,等式右边

,左右相等,在该种情况下得证。

从而,下面的式子就可以进行转化

将A拆成一系列的初等矩阵的乘积,就有

而A本身的行列式为

最终得到

得证

我们将B替换成A的逆,则有

这里可以计算A的逆的行列式的值,而A的行列式的值由于在分母的位置,所以它不能为0,换句话说,如果A的行列式的值为0,A的逆的行列式的值不存在,进而A的逆不存在。这进而说明了方阵A的等价命题中A若存在逆,det(A)≠0。

矩阵的LDU分解,PLU分解,PLUP分解

  • LDU分解

之前我们讲过矩阵的LU分解,将一个矩阵分解成了一个单位下三角矩阵L和一个上三角矩阵U

在不做归一化处理的高斯消元法中,将矩阵A化成一个上三角矩阵U,同时产生一个初等矩阵的逆矩阵L。现在如果我们想把U也化成一个单位上三角矩阵的话,L不变,等于我们进行高斯消元法的时候进行归一化处理,此时也相当于进行了一系列的初等矩阵的变换,我们同样要获取这些初等矩阵的逆矩阵D

我们可以看到D是一个对角矩阵。此时

  • PLU分解

我们再来看一个矩阵的高斯消元的过程

此时它的这两步操作的初等矩阵的逆矩阵L为

,当我们要对第二行的主元进行消元的时候,我们发现,第二行第二列的元素为0,如果按照正常的高斯消元法,我们会替换第二行和第三行。

但同时会产生一个交换操作,之前的初等矩阵的逆矩阵L

也要交换位置,此时这个矩阵将不再是单位下三角矩阵。在不动L的情况下,我们需要新产生一个初等矩阵的逆矩阵

,我们称这个矩阵为置换矩阵P,虽然有了矩阵P,但由于我们还是交换了位置,矩阵L也就变成了

最终得到

  • PLUP分解

PLU分解并不能解决所有的矩阵的问题,比如

我们在进行高斯消元的过程中,第1列1下面两个0,这个没有问题,但是在对第二列进行消元的过程中,第二行和第三行的值都是0,即便进行行交换也没有用。则PLU分解的方法就失效了。为了继续高斯消元,需要交换矩阵的两列。但是初等矩阵中没有交换矩阵两列的初等变换,只能交换矩阵的两行。例如

要交换矩阵的两列,需要右乘以置换矩阵,比如

所以A需要去右乘一个置换矩阵,完成列交换,而这个置换矩阵我们称之为P',再根据之前的PLU分解,最后可得

这里的A可以是任意矩阵。

行式就是列式

对于一个方阵,无论它其中的向量是行排列还是列排列,它们的行列式的值相等。

即为

之前我们讲解了任意A可以分解成PLUP'四个矩阵,其中P是一个行变换矩阵,P'是一个列变换矩阵,则

在这里,L、U的行列式的值和它们转置的行列式的值肯定是相等的,因为L是下三角矩阵,U是上三角矩阵,它们的行列式都等于对角矩阵的行列式的值,而L转置后是一个上三角矩阵,U转置后是一个下三角矩阵,它们的行列式同样等于对角矩阵的行列式的值。

P和P'是单位矩阵经过几次交换位置的初等变换的初等矩阵的结果,所以我们可以先证明这个命题

如果E表示单位矩阵两行交换位置det(E) = -1,而一个单位矩阵的两行交换了位置之后再进行转置,转置的结果还是两行交换了位置,它的行列式的值同样为-1,得证。

由于P和P'和它们的转置后的行交换的次数是一样的,所以P和P'的行列式的值和它们转置后的行列式的值是相等的,

得证。

我们之前讲的所有性质,都是基于行的。换成列一样存在。

  1. 交换行列式的两列,则行列式的值取反。
  2. 方阵的某一列乘以一个数k,则其对应的行列式也缩放了k倍,即
  1. 方阵中的某一列加上一列数,则有:
  1. 如果行列式的两列相同,则行列式的值为0。
  2. 如果行列式的一列是另一列的k倍,则行列式的值为0。
  3. 如果行列式的一列是其他列的线形组合,则行列式的值为0。
  4. 如果一个方阵加(减)另一列的k倍,行列式的值不变。

特征值和特征向量

特征值和特征向量也是方阵的一个属性,描述的是方阵的"特征",把方阵当作变换的时候的一个"特征"

我们之前已经知道矩阵看作变换,可以把空间中的一个向量(一个点)转换成另外一个向量(一个点)

图中就是把(1,4)这个蓝色的向量转换到了(-4,5)这个绿色的向量。当然它也是一个基变换,从(4,1)、(-2,1)组成的一组基到标准基的变换。

我们再来看一组转换

在这组转换里面,转换后的向量和转换前的向量在方向上并没有发生改变,只不过变成了原来的向量的某一个常数倍,满足

这里

称为A的特征值(eigenvalue)

称为A对应于

的特征向量(eigenvector)

求解特征值和特征向量

这里需要注意的是,零向量肯定满足。是平凡解。既然是A的特征,零向量自然无法反映A的特征。如果是零向量就跟A无关了,A可以任意取。所以,特征向量不考虑零向量。但

=0并不平凡,此时等式就变成了

,由于

不能为零向量,该方程变成了一个齐次线性方程组。

根据方阵的等价命题中

  1. 对于方阵A,矩阵A可逆,A是非奇异矩阵
  2. 线性系统Ax=0(齐次线性方程组)只有唯一解,x=0
  3. 矩阵的行最简形式rref(A)=I
  4. A可以表示成一系列初等矩阵的乘积
  5. Ax=b只有唯一解
  6. 方阵A的列向量线性无关
  7. 方阵A的列向量可以生成n维空间
  8. 方阵A的列向量是n维空间的基
  9. 方阵A为满秩矩阵(秩=n)
  10. 方阵A的行秩为n
  11. 方阵A的列秩为n
  12. 方阵A的行空间为
  1. 方阵A的列空间为
  1. 方阵A的零空间为{O},维度为0
  2. det(A)≠0

的第2条,我们知道,A可逆的话,

只能为零向量,所以A一定不可逆。

所以这里特征值可以为0

我们再对这个等式进行一系列的变形(由于矩阵不能与常数相减,所以将常数乘以一个单位矩阵,等式两边依然成立)

我们其实是希望

这个齐次线性方程组有非零解,根据方阵的等价命题中的2和15可知,其实就是

不可逆,必然

的行列式等于0,即

,我们称该方程为特征方程

我们依然以

为例来说明该行列式的计算过程

这里A是二阶方阵,所以I为二阶单位矩阵,根据矩阵的加减法,代入得

由于我们知道了

可以为2或者3,依次代入齐次线性方程组,就可以求出相应的特征向量

经过高斯消元,它们都有零行,u是一个二维向量,表示未知数的个数为2,而系数矩阵的非零行为1,小于未知数个数,表示它们都有无数解,这里的s表示可以取任意的实数。可以理解成(1,1)、(2,1)都是一维空间的基,它们所生成的一维空间的所有的向量都是该齐次线性方程组的解。

特征值和特征向量的相关概念

如果u是A对应于

的一个特征向量,则ku也是一个特征向量。这里的k≠0。

这里的k其实就等于上面的s,它可以取任意值,这里我们也来证明一下。

它同样满足

的基本式,所以得证

该命题同样也说明了

有无数解

特征向量组成了

这个方阵的零空间。当然这里要刨除零向量。

准确的说这个零空间

称为

对应的特征空间

特征方程

是一个关于

的n次方程,

有n个解(这个范围是一个复数范围,而不仅仅是实数内)

之前我们例子中的

它就是一个二次方程的两个解,我们称为简单特征值

但也有可能

这个二次方程的两个解相同,我们称为多重特征值,它的重数为2

这个二次方程的两个解为复数,我们称为复数特征值,不过复数特征值和多重特征值我们讨论的比较少,而应用最多的依然是简单特征值

特征值和特征向量的性质

之前我们已经介绍过,如果特征值为0,A一定不可逆,则现在我们可以为方阵A的等价命题再增加一条

  1. 对于方阵A,矩阵A可逆,A是非奇异矩阵
  2. 线性系统Ax=0(齐次线性方程组)只有唯一解,x=0
  3. 矩阵的行最简形式rref(A)=I
  4. A可以表示成一系列初等矩阵的乘积
  5. Ax=b只有唯一解
  6. 方阵A的列向量线性无关
  7. 方阵A的列向量可以生成n维空间
  8. 方阵A的列向量是n维空间的基
  9. 方阵A为满秩矩阵(秩=n)
  10. 方阵A的行秩为n
  11. 方阵A的列秩为n
  12. 方阵A的行空间为
  1. 方阵A的列空间为
  1. 方阵A的零空间为{O},维度为0
  2. det(A)≠0
  3. 0不是A的特征值

根据特征值和特征向量的定义和特征方程

如果A是一个对角矩阵,它的行列式为

那么

的行列式为

由此可见,对角矩阵的特征值是其对角线上的元素

同理,如果A是一个上三角矩阵,它的行列式为

那么

的行列式为

则上三角矩阵的特征值是其对角线上的元素

同理,如果A是一个下三角矩阵,它的行列式为

那么

的行列式为

则下三角矩阵的特征值是其对角线上的元素

是A的特征值,则

的特征值

这里我们可以采用数学归纳法来证明

当m=1时,