主要内容

  • 矩阵定义
  • 解的唯一性
  • 顺序Gauss消去法
  • 全选主元Gauss消去法
  • LU分解
  • Cholesky分解
  • Gauss-Jordan消去法&求矩阵的逆
  • 三对角线方程组
  • Gauss-Seidel迭代&松弛迭代
  • 病态系统

一、引言

  • n个方程和n个未知数的方程组

数值方法No.4-求解联立线性代数方程 - 图1

  • 可以转化为矩阵的格式

数值方法No.4-求解联立线性代数方程 - 图2

  • 定义增广矩阵

数值方法No.4-求解联立线性代数方程 - 图3

  • 解线性方程的方法:
    • 直接求解:Gauss消元,LU分解,Cholesky分解,Thomas法,Gauss-Jordan法。
    • 迭代:Gauss-Seidel。

二、定义矩阵

  • 数值方法No.4-求解联立线性代数方程 - 图4
  • 对阵矩阵:数值方法No.4-求解联立线性代数方程 - 图5
  • 斜对称矩阵:数值方法No.4-求解联立线性代数方程 - 图6
  • 对角阵:主对角线存在非零元素的方正,其他都为0。
  • 上三角U:下半部分全0;下三角L:上半部分全0。
  • 稠密矩阵:没有任何0元素;稀疏矩阵:具有个别0元素。
  • 迹tr:方阵对角线的元素之和。
  • 非奇异矩阵:方阵的行列式不为0,从而有逆矩阵。
  • 当行列式很小,矩阵是病态的。
  • 秩:最大的非奇异的子方阵的阶数。

三、解的唯一性(以下默认系数A矩阵为n*n的方阵)

  • 当且仅当:增广矩阵数值方法No.4-求解联立线性代数方程 - 图7和系数矩阵 数值方法No.4-求解联立线性代数方程 - 图8的秩相同,方程组数值方法No.4-求解联立线性代数方程 - 图9有解;
  • 当且仅当:增广矩阵数值方法No.4-求解联立线性代数方程 - 图10和系数矩阵 数值方法No.4-求解联立线性代数方程 - 图11的秩相同,且=未知数的个数,方程组有唯一解;
  • 当且仅当:增广矩阵数值方法No.4-求解联立线性代数方程 - 图12和系数矩阵 数值方法No.4-求解联立线性代数方程 - 图13的秩相同,且<未知数的个数,方程组有无数解;
  • 齐次方程组:数值方法No.4-求解联立线性代数方程 - 图14——总有解为全0向量,这种解称为平凡解。如果系数矩阵奇异,那么齐次方程组存在无数解。

四、顺序Gauss消去法

1. 原理和算法

  • 将增广矩阵化简为上三角矩阵,从而向量数值方法No.4-求解联立线性代数方程 - 图15在此过程中被修改,最后解出向量数值方法No.4-求解联立线性代数方程 - 图16

消去。消去和回代步骤的公式如下:

  • 消去

数值方法No.4-求解联立线性代数方程 - 图17

  • 回代:从数值方法No.4-求解联立线性代数方程 - 图18计算到数值方法No.4-求解联立线性代数方程 - 图19

数值方法No.4-求解联立线性代数方程 - 图20

  • 缺陷:
    • 如果对角线上的主元素数值方法No.4-求解联立线性代数方程 - 图21=0的时候,那么消去公式的计算就会出现问题。
    • 当这个元素和其他元素比起来很小的时候,那么结果可能不准确。
    • 解决方法:交换系数矩阵的行和列,一边选择最大的主元素,称为全主元法;不时执行交换行或者列,而不是全部都交换,称为部分主元法。如果对角线选主元找不到非零元素,那么矩阵一定奇异。
  • 算法复杂度:
    • 消去和回代需要数值方法No.4-求解联立线性代数方程 - 图22次乘法和除法运算,以及数值方法No.4-求解联立线性代数方程 - 图23次加减运算。

2. 例子

  • 例子

数值方法No.4-求解联立线性代数方程 - 图24

首先,系数矩阵数值方法No.4-求解联立线性代数方程 - 图25和增广矩阵数值方法No.4-求解联立线性代数方程 - 图26分别为
数值方法No.4-求解联立线性代数方程 - 图27以及数值方法No.4-求解联立线性代数方程 - 图28

消去:根据公式,n=3, kij依次取数:
k=0, i=1,2, j=0,1,2,3;
k=1, i=2, j=1,2,3;
①k=0, i=1的时候,j=0~3
数值方法No.4-求解联立线性代数方程 - 图29
k=0, i=2的时候,j=0~3
数值方法No.4-求解联立线性代数方程 - 图30
因此,k=0的循环之后,结果为
数值方法No.4-求解联立线性代数方程 - 图31
②k=1, i=2的时候,j=1,2,3
数值方法No.4-求解联立线性代数方程 - 图32
因此,k=1的循环之后,结果为
数值方法No.4-求解联立线性代数方程 - 图33
接着进行回代:
数值方法No.4-求解联立线性代数方程 - 图34

3. 代码

  1. #include<iostream>
  2. #include<math.h>
  3. using namespace std;
  4. class Gauss
  5. {
  6. private:
  7. int i,j,k,n;
  8. double eps, ratio, sum, *x, **a; //定义x是用来储存求解的结果向量,a是用来储存增广矩阵。
  9. public:
  10. void gauss_input();
  11. void gauss_elimination();
  12. void gauss_output();
  13. ~Gauss()
  14. {
  15. delete [] x; // 释放x向量空间
  16. // 释放a矩阵空间,需要先释放每个“元素”(每个元素是向量),再最后释放a。
  17. for(i=0; i<n; i++)
  18. {
  19. delete [] a[i];
  20. }
  21. delete [] a;
  22. }
  23. };
  24. void Gauss::gauss_input()
  25. {
  26. cout << "Enter the number of functions : " ;
  27. cin >> n;
  28. // 储存x向量
  29. x = new double [n];
  30. // 出错点:这里*不可少,储存a矩阵;注意定义矩阵的技巧。
  31. a = new double*[n];
  32. for(i=0; i<n; i++){
  33. a[i] = new double [n+1];
  34. }
  35. // 输入a(0:n-1, 0:n-1)的元素即为系数矩阵。
  36. for(i=0; i<n; i++)
  37. for(j=0; j<n; j++){
  38. cout << "Enter a[" << i << "][" << j << "]=";
  39. cin >> a[i][j];
  40. }
  41. // 输入a(0:n-1, n)的元素即为b
  42. for(i=0; i<n; i++){
  43. cout << "Enter b[" << i << "]=" ;
  44. cin >> a[i][n];
  45. }
  46. // 输入对角线最小的元素。
  47. cout << "Min of main element : ";
  48. cin >> eps;
  49. }
  50. void Gauss::gauss_elimination()
  51. {
  52. // 消去
  53. for(k=0; k<n-1; k++){
  54. int i_start=k+1;
  55. //如果对角线主元素太小,那么报错。
  56. if(fabs(a[k][k]) < eps){
  57. cout << "Main element is too small. Failure..." << endl;
  58. exit(0);
  59. }
  60. for(i=i_start; i<n; i++){
  61. ratio = a[i][k]/a[k][k];
  62. for(j=(k+1); j<n+1; j++){
  63. a[i][j] -= ratio * a[k][j];
  64. }
  65. }
  66. }
  67. // 回代
  68. x[n-1] = a[n-1][n] / a[n-1][n-1];
  69. for(i=n-2; i>=0; i--){
  70. sum = 0.0;
  71. for(j=i+1; j<n; j++){
  72. sum += a[i][j] * x[j];
  73. }
  74. x[i] = (a[i][n] - sum) / a[i][i];
  75. }
  76. }
  77. void Gauss::gauss_output()
  78. {
  79. cout << "Result is " << endl;
  80. for(i=0; i<n; i++){
  81. cout << "x[" << i << "]=" << x[i] << endl;
  82. }
  83. }
  84. int main()
  85. {
  86. Gauss g1;
  87. g1.gauss_input();
  88. g1.gauss_elimination();
  89. g1.gauss_output();
  90. return 0;
  91. }

ubuntu中运行

  1. danielshen@DESKTOP-VOSNAQJ:~/nr/chp2$ g++ c5.cpp -o c5 -std=c++11
  2. danielshen@DESKTOP-VOSNAQJ:~/nr/chp2$ ./c5
  3. Enter the number of functions : 3
  4. Enter a[0][0]=0.8
  5. Enter a[0][1]=0.02
  6. Enter a[0][2]=0.06
  7. Enter a[1][0]=0.1
  8. Enter a[1][1]=0.83
  9. Enter a[1][2]=0.12
  10. Enter a[2][0]=0.1
  11. Enter a[2][1]=0.15
  12. Enter a[2][2]=0.82
  13. Enter b[0]=50
  14. Enter b[1]=30
  15. Enter b[2]=20
  16. Min of main element : 0.001
  17. Result is
  18. x[0]=60.9226
  19. x[1]=27.0682
  20. x[2]=12.0091

4. 其他补充

  • 高斯消元法不适合奇异矩阵。
  • 行阶梯形矩阵(Row echelon form):每行的第一个非零元素(称为leading coefficient)为1;第i行的leading coefficient 位于第i+1行的leading coefficient的左上;全0的行位于具有非零行的下方。
  • 主要是进行行操作,从而将矩阵转化为上三角矩阵,变成行阶梯形矩阵;操作包括了“交换行”、“将行乘以非零常数”、“将一行加到另一行。”。
  • 算法:

    • 部分旋转:通过交换行,从而将具有最大绝对值的输入移动到轴的位置,保持计算的稳定性;
  • 代码


五、全选主元Gauss消去法

https://www.geeksforgeeks.org/program-for-gauss-jordan-elimination-method/

1. 介绍

  • 全选主元Gauss消去法更加robust。
  • 新增了两个数据成员pivrow和pivcol,用于储藏在执行过程中的主元元素的行和列,储存需要的信息。因为在“行列”交换的时候,x也需要进行交换行的位置,因此要用到pivcol中的信息。

2. 例子

例如,方程组数值方法No.4-求解联立线性代数方程 - 图35,直接求解的话,数值方法No.4-求解联立线性代数方程 - 图36数值方法No.4-求解联立线性代数方程 - 图37。原因是数值方法No.4-求解联立线性代数方程 - 图38太小了,导致在求解的时候数值方法No.4-求解联立线性代数方程 - 图39变得巨大。

那么这里考虑将上下进行交换位置,就能得到正确的解。
数值方法No.4-求解联立线性代数方程 - 图40数值方法No.4-求解联立线性代数方程 - 图41

因此,在进行高斯消去的时候,避免采用绝对值很小的元素数值方法No.4-求解联立线性代数方程 - 图42,保持数值方法No.4-求解联立线性代数方程 - 图43

3. 算法

  • 第一步
    • 选主元:在系数矩阵A中选出绝对值最大的元素作为主元素,确定坐标数值方法No.4-求解联立线性代数方程 - 图44,使得数值方法No.4-求解联立线性代数方程 - 图45
    • 交换行列式:
      • 数值方法No.4-求解联立线性代数方程 - 图46,交换增广矩阵数值方法No.4-求解联立线性代数方程 - 图47的第0行和第数值方法No.4-求解联立线性代数方程 - 图48行元素;
      • 数值方法No.4-求解联立线性代数方程 - 图49,交换增广矩阵数值方法No.4-求解联立线性代数方程 - 图50的第0列数值方法No.4-求解联立线性代数方程 - 图51列元素;
      • 注意调换数值方法No.4-求解联立线性代数方程 - 图52数值方法No.4-求解联立线性代数方程 - 图53,并记录。
    • 消元
      • 数值方法No.4-求解联立线性代数方程 - 图54
      • 数值方法No.4-求解联立线性代数方程 - 图55
  • 第k步:重复进行,假设已经完成了第1步~第k-1步,
  • 消去:对于数值方法No.4-求解联立线性代数方程 - 图56,从数值方法No.4-求解联立线性代数方程 - 图57数值方法No.4-求解联立线性代数方程 - 图58进行以下运算。
    • 全选主元:数值方法No.4-求解联立线性代数方程 - 图59
    • 通过行列交换,把绝对值最大的元素交换到主元位置上。
    • 系数矩阵归一化:

待完善

六、带有正向和反向代入的LU分解

1. 介绍

  • 如果,系数矩阵元素不变,但是右边的b向量变了,那么对系数矩阵的操作不必重复进行,可以节省大量的计算工作。
  • 因此,采用LU分解,L是下三角矩阵,U是上三角矩阵。从而系数矩阵能够表示为两个矩阵的乘积

数值方法No.4-求解联立线性代数方程 - 图60

  • 注意,下三角矩阵L对角线元素是1,从而使用前向和后向扫描得到了向量数值方法No.4-求解联立线性代数方程 - 图61,定义新的向量数值方法No.4-求解联立线性代数方程 - 图62,那么有

数值方法No.4-求解联立线性代数方程 - 图63
利用数值方法No.4-求解联立线性代数方程 - 图64进行前向扫描,得到数值方法No.4-求解联立线性代数方程 - 图65,利用数值方法No.4-求解联立线性代数方程 - 图66进行后向扫描得到数值方法No.4-求解联立线性代数方程 - 图67

2. 算法

  • 步骤1:设数值方法No.4-求解联立线性代数方程 - 图68
  • 步骤2:对于数值方法No.4-求解联立线性代数方程 - 图69,执行
    • 数值方法No.4-求解联立线性代数方程 - 图70
    • 数值方法No.4-求解联立线性代数方程 - 图71
  • 系数矩阵A中的每个元素只使用1次,因此数值方法No.4-求解联立线性代数方程 - 图72可以储存在A的对应位置上,从而分解为

数值方法No.4-求解联立线性代数方程 - 图73

  • 前向代入

数值方法No.4-求解联立线性代数方程 - 图74

  • 后向带入

数值方法No.4-求解联立线性代数方程 - 图75
元素数值方法No.4-求解联立线性代数方程 - 图76不需要储存。

1. 例子