跳到主要内容

线性方程组数值解法

线性方程组 Ax=bAx = b 的求解是科学计算的核心问题。本章介绍直接法(有限步内获得精确解)和迭代法(逐步逼近解)两大类算法。


一、直接法

1.1 Gauss 消元法

基本思想:通过初等行变换将系数矩阵化为上三角矩阵,然后回代求解。

算法步骤

  1. 消元过程:对 k=1,2,,n1k = 1, 2, \ldots, n-1,计算 mik=aik(k)akk(k),i=k+1,,nm_{ik} = \frac{a_{ik}^{(k)}}{a_{kk}^{(k)}}, \quad i = k+1, \ldots, n aij(k+1)=aij(k)mikakj(k),bi(k+1)=bi(k)mikbk(k)a_{ij}^{(k+1)} = a_{ij}^{(k)} - m_{ik} a_{kj}^{(k)}, \quad b_i^{(k+1)} = b_i^{(k)} - m_{ik} b_k^{(k)}

  2. 回代过程xn=bn(n)ann(n)x_n = \frac{b_n^{(n)}}{a_{nn}^{(n)}} xi=bi(i)j=i+1naij(i)xjaii(i),i=n1,,1x_i = \frac{b_i^{(i)} - \sum_{j=i+1}^n a_{ij}^{(i)} x_j}{a_{ii}^{(i)}}, \quad i = n-1, \ldots, 1

运算量:约 23n3\frac{2}{3}n^3 次浮点运算。

1.2 列主元消元法

数值稳定性问题

当主元 akk(k)a_{kk}^{(k)} 很小时,消元过程会放大舍入误差。

解决方案:在第 kk 步消元前,选取列主元 aik,k(k)=maxkinai,k(k)|a_{i_k,k}^{(k)}| = \max_{k \leq i \leq n} |a_{i,k}^{(k)}| 然后交换第 kk 行与第 iki_k 行。

1.3 LU 分解

定理:若 AA 的各阶顺序主子式均非零,则 AA 可唯一分解为 A=LUA = LU,其中 LL 是单位下三角阵,UU 是上三角阵。

计算过程

  • Doolittle 分解:LL 为单位下三角阵,UU 为上三角阵
  • Crout 分解:LL 为下三角阵,UU 为单位上三角阵

求解步骤

  1. Ax=bL(Ux)=bAx = b \Rightarrow L(Ux) = b
  2. Ly=bLy = b(前代)
  3. Ux=yUx = y(回代)

1.4 Cholesky 分解(针对对称正定矩阵)

AA 对称正定,则存在唯一的对角元为正的下三角阵 LL,使得: A=LLTA = LL^T

计算公式ljj=ajjk=1j1ljk2l_{jj} = \sqrt{a_{jj} - \sum_{k=1}^{j-1} l_{jk}^2} lij=aijk=1j1likljkljj,i>jl_{ij} = \frac{a_{ij} - \sum_{k=1}^{j-1} l_{ik}l_{jk}}{l_{jj}}, \quad i > j

优点:运算量约为 LU 分解的一半,数值稳定性好。


二、迭代法

当矩阵规模很大且稀疏时,直接法运算量和存储量过大,迭代法是更好的选择。

2.1 迭代法的一般形式

AA 分裂为 A=MNA = M - N,则: Ax=bMx=Nx+bx=M1Nx+M1bAx = b \Rightarrow Mx = Nx + b \Rightarrow x = M^{-1}Nx + M^{-1}b

迭代格式:x(k+1)=Bx(k)+fx^{(k+1)} = Bx^{(k)} + f,其中 B=M1NB = M^{-1}N 为迭代矩阵。

收敛条件:迭代矩阵的谱半径 ρ(B)<1\rho(B) < 1

2.2 Jacobi 迭代

分裂A=DLUA = D - L - U,其中 DD 为对角阵,LL 为严格下三角阵,UU 为严格上三角阵。

迭代格式x(k+1)=D1(L+U)x(k)+D1bx^{(k+1)} = D^{-1}(L + U)x^{(k)} + D^{-1}b

分量形式xi(k+1)=1aii(bijiaijxj(k)),i=1,,nx_i^{(k+1)} = \frac{1}{a_{ii}}\left(b_i - \sum_{j \neq i} a_{ij}x_j^{(k)}\right), \quad i = 1, \ldots, n

2.3 Gauss-Seidel 迭代

改进:使用最新计算出的分量值。

迭代格式x(k+1)=(DL)1Ux(k)+(DL)1bx^{(k+1)} = (D - L)^{-1}Ux^{(k)} + (D - L)^{-1}b

分量形式xi(k+1)=1aii(bij<iaijxj(k+1)j>iaijxj(k))x_i^{(k+1)} = \frac{1}{a_{ii}}\left(b_i - \sum_{j < i} a_{ij}x_j^{(k+1)} - \sum_{j > i} a_{ij}x_j^{(k)}\right)

2.4 SOR (逐次超松弛) 迭代

思想:在 Gauss-Seidel 迭代基础上引入松弛因子 ω\omega

迭代格式xi(k+1)=(1ω)xi(k)+ωaii(bij<iaijxj(k+1)j>iaijxj(k))x_i^{(k+1)} = (1-\omega)x_i^{(k)} + \frac{\omega}{a_{ii}}\left(b_i - \sum_{j < i} a_{ij}x_j^{(k+1)} - \sum_{j > i} a_{ij}x_j^{(k)}\right)

  • ω=1\omega = 1:退化为 Gauss-Seidel
  • 0<ω<10 < \omega < 1:低松弛(用于非正定系统)
  • 1<ω<21 < \omega < 2:超松弛(加速收敛)
收敛性定理

AA 对称正定,则:

  • Jacobi 迭代收敛的充要条件是 2DA2D - A 也正定
  • Gauss-Seidel 迭代一定收敛
  • SOR 迭代当 0<ω<20 < \omega < 2 时收敛

三、典型例题

例题 1:用 LU 分解求解

求解: (211433879)(x1x2x3)=(41026)\begin{pmatrix} 2 & 1 & 1 \\ 4 & 3 & 3 \\ 8 & 7 & 9 \end{pmatrix} \begin{pmatrix} x_1 \\ x_2 \\ x_3 \end{pmatrix} = \begin{pmatrix} 4 \\ 10 \\ 26 \end{pmatrix}

解析

进行 Doolittle 分解 A=LUA = LUL=(100210431),U=(211011002)L = \begin{pmatrix} 1 & 0 & 0 \\ 2 & 1 & 0 \\ 4 & 3 & 1 \end{pmatrix}, \quad U = \begin{pmatrix} 2 & 1 & 1 \\ 0 & 1 & 1 \\ 0 & 0 & 2 \end{pmatrix}

Ly=bLy = b

  • y1=4y_1 = 4
  • y2=102×4=2y_2 = 10 - 2 \times 4 = 2
  • y3=264×43×2=4y_3 = 26 - 4 \times 4 - 3 \times 2 = 4

Ux=yUx = y

  • x3=4/2=2x_3 = 4 / 2 = 2
  • x2=(22)/1=0x_2 = (2 - 2) / 1 = 0
  • x1=(402)/2=1x_1 = (4 - 0 - 2) / 2 = 1

答案x=(1,0,2)Tx = (1, 0, 2)^T

例题 2:迭代法收敛性分析

A=(410141014)A = \begin{pmatrix} 4 & 1 & 0 \\ 1 & 4 & 1 \\ 0 & 1 & 4 \end{pmatrix},分析 Jacobi 和 Gauss-Seidel 迭代的收敛性。

解析

Jacobi 迭代矩阵: BJ=D1(L+U)=(01/401/401/401/40)B_J = D^{-1}(L+U) = \begin{pmatrix} 0 & -1/4 & 0 \\ -1/4 & 0 & -1/4 \\ 0 & -1/4 & 0 \end{pmatrix}

计算特征值:det(BJλI)=λ(λ21/8)=0\det(B_J - \lambda I) = -\lambda(\lambda^2 - 1/8) = 0

特征值为 0,±1/80, \pm 1/\sqrt{8},故 ρ(BJ)=1/80.354<1\rho(B_J) = 1/\sqrt{8} \approx 0.354 < 1,Jacobi 收敛。

Gauss-Seidel 迭代矩阵:BGS=(DL)1UB_{GS} = (D-L)^{-1}U

对于对称正定矩阵,Gauss-Seidel 一定收敛,且收敛速度通常比 Jacobi 快约一倍。


四、计算验证:C++ 实现

点击查看 C++ Jacobi 迭代实现
#include <iostream>
#include <vector>
#include <cmath>
#include <iomanip>

using namespace std;
using Matrix = vector<vector<double>>;
using Vector = vector<double>;

// Jacobi 迭代求解 Ax = b
Vector jacobi(const Matrix& A, const Vector& b, int max_iter = 1000, double tol = 1e-10) {
int n = A.size();
Vector x(n, 0.0), x_new(n, 0.0);

for (int iter = 0; iter < max_iter; ++iter) {
for (int i = 0; i < n; ++i) {
double sum = b[i];
for (int j = 0; j < n; ++j) {
if (i != j) sum -= A[i][j] * x[j];
}
x_new[i] = sum / A[i][i];
}

// 计算误差
double error = 0.0;
for (int i = 0; i < n; ++i) {
error += abs(x_new[i] - x[i]);
x[i] = x_new[i];
}

if (error < tol) {
cout << "收敛于第 " << iter + 1 << " 次迭代" << endl;
return x;
}
}

cout << "达到最大迭代次数" << endl;
return x;
}

int main() {
// 测试:对称正定矩阵
Matrix A = {
{4, 1, 0},
{1, 4, 1},
{0, 1, 4}
};
Vector b = {5, 6, 7};

cout << fixed << setprecision(10);
Vector x = jacobi(A, b);

cout << "解向量:";
for (double xi : x) cout << xi << " ";
cout << endl;

// 验证残差
cout << "\n残差 Ax - b:";
for (int i = 0; i < 3; ++i) {
double sum = 0;
for (int j = 0; j < 3; ++j) sum += A[i][j] * x[j];
cout << sum - b[i] << " ";
}
cout << endl;

return 0;
}

五、方法选择指南

方法类型适用场景优点缺点
Gauss 消元中小规模稠密矩阵通用、稳定O(n3)O(n^3) 运算量
LU 分解多个右端项分解一次多次求解需要存储 L 和 U
Cholesky对称正定矩阵运算量减半、稳定仅适用于 SPD 矩阵
Jacobi大规模稀疏矩阵并行性好、简单收敛可能较慢
Gauss-Seidel大规模稀疏矩阵收敛通常更快不易并行
SOR需要加速收敛可调节松弛因子需选择最优 ω\omega

学习要点
  1. 直接法适用于中小规模问题,注意数值稳定性(选主元)。
  2. 迭代法适用于大规模稀疏问题,关键是保证收敛性。
  3. 对称正定矩阵优先使用 Cholesky 分解或 Gauss-Seidel 迭代。
  4. 实际工程中常使用预条件共轭梯度法 (PCG) 等高级算法。

本章节是数值代数的基础,掌握这些算法对于理解更高级的数值方法(如有限元、优化算法)至关重要。