上节课主要介绍了线性方程组的几种直接求解法,包括高斯消去法(主元消去)、高斯约当法(可以用来求解矩阵的逆)、LU分解法(高斯消去和Crout 方法),使用高斯消去法实现LU分解的原理可以通过一种拉格朗日形式来理解。本节课主要介绍线性方程组的几种迭代求解法,包括Jacobi法和高斯塞德尔法。
1. 使用MATLAB内置函数实现LU分解以及矩阵求逆
LU分解
MATLAB使用lu命令对矩阵进行LU分解,分解前对矩阵进行行变换,以满足主元消去的条件:
>> help lu
lu - lu 矩阵分解
此 MATLAB 函数 返回矩阵 Y,其中包含严格下三角矩阵 L(即不带其单位对角线)和上三角矩阵 U 作为子矩阵。也即,如果 [L,U,P] =
lu(A),Y = U+L-eye(size(A))。不会返回置换矩阵 P。
Y = lu(A)
[L,U] = lu(A)
[L,U,P] = lu(A)
[L,U,P,Q] = lu(A)
[L,U,P,Q,R] = lu(A)
[...] = lu(A,'vector')
[...] = lu(A,thresh)
[...] = lu(A,thresh,'vector')
另请参阅 cond, det, ilu, inv, qr, rref
lu 的参考页
名为 lu 的其他函数
>> A = [1 2 3;4 5 6;7 8 9]
A =
1 2 3
4 5 6
7 8 9
>> format long
>> det(A)
ans =
-9.516197353929915e-16
>> [l u p] = lu(A)
l =
1.000000000000000 0 0
0.142857142857143 1.000000000000000 0
0.571428571428571 0.500000000000000 1.000000000000000
u =
7.000000000000000 8.000000000000000 9.000000000000000
0 0.857142857142857 1.714285714285714
0 0 -0.000000000000000
p =
0 0 1
1 0 0
0 1 0
>> p*A
ans =
7 8 9
1 2 3
4 5 6
>> l*u
ans =
7 8 9
1 2 3
4 5 6
>> [l_1,u_1] = lu(A);
>> inv(p)*l == l_1
ans =
3×3 logical 数组
1 1 1
1 1 1
1 1 1
>> [l_2,u_2,p_2] = lu(p*A)
l_2 =
1.000000000000000 0 0
0.142857142857143 1.000000000000000 0
0.571428571428571 0.500000000000000 1.000000000000000
u_2 =
7.000000000000000 8.000000000000000 9.000000000000000
0 0.857142857142857 1.714285714285714
0 0 -0.000000000000000
p_2 =
1 0 0
0 1 0
0 0 1
矩阵求逆
MATLAB使用inv命令求矩阵的逆,但当矩阵的数量级很小时,inv求解会带来较大的舍入误差(Round-off error):
>> A = 10^(-4)*[1 2 3;4 5 6;7 8 9]
A =
1.0e-03 *
0.100000000000000 0.200000000000000 0.300000000000000
0.400000000000000 0.500000000000000 0.600000000000000
0.700000000000000 0.800000000000000 0.900000000000000
>> inv(A)
警告: 矩阵接近奇异值,或者缩放错误。结果可能不准确。RCOND = 1.317607e-17。
ans =
1.0e+19 *
-0.527049830677416 1.054099661354831 -0.527049830677416
1.054099661354831 -2.108199322709663 1.054099661354832
-0.527049830677415 1.054099661354831 -0.527049830677416
>> A*inv(A)
警告: 矩阵接近奇异值,或者缩放错误。结果可能不准确。RCOND = 1.317607e-17。
ans =
1.250000000000000 0 0
0.500000000000000 1.000000000000000 -0.500000000000000
1.000000000000000 0 0
2. Jacobi法求解线性方程组
Jacobi法是一种同步迭代求解法,考虑如下线性方程构成的系统: 简单运算,可推导出:
这一转换过程可以描述为如下矩阵形式: 其中矩阵和的元素为 Jacobi迭代法就是给出一个初始估计值,使用进行迭代求解,特点是每次迭代,同时更新的所有元素(同线性回归与逻辑回归中的梯度下降法): 通常初始值可以选择所有值为。
接下来,讨论该迭代法的收敛性条件。Jacobi迭代法收敛的一个充分条件为: 满足这一条件的矩阵称为对角占优的(diagonally dominant)。但是,不满足这一条件时,Jacobi迭代法也有可能会收敛,这只是一个充分条件。
Jacobi迭代法的停止准则采取估计值的相对误差来定义 其中是预先给定的一个精度。
3. 高斯-塞德尔法求解线性方程组
高斯塞德尔法与Jacobi法的推导过程是一致的,不同的是高斯塞德尔法使用异步迭代的方式进行迭代求解: 可以看到,第步的的值会使用步计算出来的的值以及步计算的值进行计算。高斯塞德尔的停止准则与Jacobi方法一致,一般情况下高斯塞德尔方法的收敛速度比Jacobi法快,且占用内存小。
例: MATLAB实现:
k = 1; x1 = 0; x2 = 0; x3 = 0; x4 = 0;
disp(' k x1 x2 x3 x4')
fprintf(' %2.0f %-8.5f %-8.5f %-8.5f %-8.5f \n', k, x1, x2, x3, x4)
for k=2 : 8
x1 = (54.5 - (-2*x2 + 3*x3 + 2*x4))/9;
x2 = (-14 - (2*x1 - 2*x3 + 3*x4))/8;
x3 = (12.5 - (-3*x1 + 2*x2 - 4*x4))/11;
x4 = (-21 - (-2*x1 + 3*x2 + 2*x3))/10;
fprintf(' %2.0f %-8.5f %-8.5f %-8.5f %-8.5f \n', k, x1, x2, x3, x4)
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>> Program4_8
k x1 x2 x3 x4
1 0.00000 0.00000 0.00000 0.00000
2 6.05556 -3.26389 3.38131 -0.58598
3 4.33336 -1.76827 2.42661 -1.18817
4 5.11778 -1.97723 2.45956 -0.97519
5 5.01303 -2.02267 2.51670 -0.99393
6 4.98805 -1.99511 2.49806 -1.00347
7 5.00250 -1.99981 2.49939 -0.99943
8 5.00012 -2.00040 2.50031 -0.99992
4. 三对角系统(Tridiagonal systems)与Thomas算法
三对角系统: 这样的系统可以通过高斯法,高斯约当法以及LU分解法求解,但基于系统矩阵的特殊结构(Sparse matrix, 稀疏矩阵),可以使用另一种更节省内存和时间的方法——Thomas算法。
Thomas算法将三角矩阵的对角线元素存储到一个向量中:,上对角元素存储到向量中:,下对角元素存储到向量中: ,上述三对角系统可以转换为: Thomas算法的第一步是将第一行元素规范化,得到: 其中,消去,得 其中,重复这一过程直到有 这样一个系统很容易可以通过回代法求解。
Thomas算法的步骤可以归结为:
- 定义 , , , ,
- 更新,:,
- 对:
- 使用回代法求解:,
MATLAB实现:
function x = Tridiagonal(A,B)
% The function solve a tridiagonal system of linear equations [a][x]=[b]
% using Thomas algorithm.
% Input variables:
% A The matrix of coefficients.
% B A column vector of constants.
% Output variable:
% x A colum vector with the solution.
[nR, nC] = size(A);
for i = 1:nR
d(i) = A(i,i);
end
for i = 1:nR-1
ad(i) = A(i,i+1);
end
for i = 2:nR
bd(i) = A(i,i-1);
end
ad(1) = ad(1)/d(1);
B(1) = B(1)/d(1);
for i = 2:nR-1
ad(i) = ad(i)/(d(i)-bd(i)*ad(i-1));
B(i)=(B(i)-bd(i)*B(i-1))/(d(i)-bd(i)*ad(i-1));
end
B(nR)=(B(nR)-bd(nR)*B(nR-1))/(d(nR)-bd(nR)*ad(nR-1));
x(nR,1) = B(nR);
for i = nR-1:-1:1
x(i,1) = B(i)-ad(i)*x(i+1);
end
5. 范数与条件数
5.1 向量范数
一般来说,向量范数需要满足一下三个条件:
- 正定性
- 齐次性
- 三角不等式
几种常见的向量范数:
- 1范数:
- 2范数:
- 范数:
5.2 矩阵范数
矩阵范数要比向量范数多一个条件:
矩阵范数中的范数均是由向量范数诱导而来:
- 1范数 证明:对任意,注意 因此 根据向量范数的三角不等式,可得 即 当时,能够取等号,因此
- 2范数 证明:假设的特征值为, 对应的单位特征向量为R^{n} 对,有 因此 当取最大特征值对应的单位特征向量时,等号成立,因此
- 范数 证明: 当时,有,因此 当时,等号成立
5.3 条件数与相对误差
对线性系统,假设其真实解为,数值解为,则真实误差为,一般真实解无法给出,因此,真实误差难以计算,但系统残差(residual)则可以通过下式给出:
例: 该系统的真实解为
- 若数值解为 真实误差为 系统残差为 系统残差与真实误差的数量级时一致的
- 若数值解为 真实误差为 系统残差为 此时,系统残差的数量级与真实误差的数量级差别很大,因此无法总是用残差来估计真实误差
一个好的想法是用范数来衡量估计误差,, ,注意 ,根据范数的三角不等式,有 进一步考虑相对误差和相对残差 有 注意 因此有 另一方面, 因此 同时 因此有 综上,有 就称作条件数(Condition number)。
例:考虑第3节的线性方程组 其真实解为 而使用第3节的高斯赛德尔法迭代6次后,得到的数值解为 因此真实误差为 系统残差为 现在以向量为例,检查一下上述不等式的真实性: 注意
病态系统(ill-conditioned):病态系统是指系统参数有很小的变化时都会引起解很大的变化的一类系统,且可以证明当条件数远大于时,系统是一个病态的。
6. 总结
本节课主要介绍了求解线性方程组的两种迭代数值求解法,包括Jacobi法和高斯塞德尔法,其中Jacobi法是同步更新,而高斯赛德尔法是异步更新。对于特殊的三对角矩阵,可以采用Thomas算法求解,相比高斯消去、LU分解法更节省内存和时间。最后,介绍了向量范数和矩阵范数的概念,并引入条件数来确定线性系统数值解的相对误差范围。