雅可比迭代法
雅可比迭代法(Jacobi iteration)把线性方程组中每个未知量由对应的一行解出,并在下一轮统一使用上一轮的数值更新。它实现简单,所有分量可以并行计算;收敛却需要检查矩阵结构或迭代矩阵,非零对角元本身不足以保证成功。
同时更新两个未知量
考虑 、。由每行解出对应变量,得到 从 出发,第一轮为 ;第二轮必须仍同时读取第一轮的旧值,得到 ;第三轮为 。精确解为 。
第二轮若在算出 后,马上把它用于同一轮的 ,就不再是 Jacobi,而是高斯—赛德尔迭代法。是否保存旧向量是算法定义的一部分,并非一个无关的编程优化。
矩阵分裂与收敛判据
设 ,其中 是对角部分, 分别为严格下、上三角部分,且所有 。Jacobi 更新写成 若精确解为 ,误差满足 。对所有初值收敛的充要条件是谱半径 :此时矩阵幂趋零;若有模至少一的特征值,便存在不衰减的相应模式。非对角化情形仍可用 Jordan 块证明,小于一的指数衰减压过块中有限次数的多项式因子。Netlib 给出 Jacobi 分裂及标准收敛条件。[1]
主例 ,特征值为 ,谱半径约为 ,故收敛。各分量可换号或起伏,不要求每个坐标单调接近解。
严格对角占优的直接证明
若逐行满足 ,令 任意误差向量满足 取最大值得 。严格占优也保证 非奇异:若 且取绝对值最大的非零分量 ,该行便要求 ,与严格不等式矛盾。于是唯一解和收敛都由同一个条件得到。
还可给出后验停止界。记相邻差 ,同样有 。从当前点到极限的尾和满足 这比只凭相邻两次数字看起来相同更明确,但前提是有可信的收缩常数。主例可取 ,虽比实际谱半径保守,仍给出有效保证。
可复算反例与实现
有解变式取 、,每行没有其他未知量,一轮即到 。反例取 、。矩阵可逆、解为 ,但从零开始的迭代为 ,因为迭代矩阵有模为二的特征值。
下面程序限定在严格行对角占优的有限实矩阵,以便给出收敛保证;其他矩阵即使可能收敛也不在此接口范围内。它从零开始,以实际残差最大范数验收,返回近似及轮数,不修改输入。稠密每轮 时间、额外向量 空间;稀疏矩阵可只遍历非零元。
import math
def jacobi(A, b, tol=1e-12, maxiter=1000):
A, b = [list(map(float, row)) for row in A], list(map(float, b)); n = len(b)
if not n or len(A) != n or any(len(row) != n for row in A):
raise ValueError("square matrix matching b required")
if not all(math.isfinite(v) for row in A for v in row) or not all(math.isfinite(v) for v in b):
raise ValueError("finite input required")
if any(abs(A[i][i]) <= sum(abs(A[i][j]) for j in range(n) if j != i) for i in range(n)):
raise ValueError("this implementation requires strict row diagonal dominance")
if not math.isfinite(tol) or tol <= 0 or not isinstance(maxiter, int) or maxiter < 0:
raise ValueError("positive tolerance and nonnegative integer iteration limit required")
x = [0.0]*n; target = tol*max(1.0, max(map(abs, b)))
for k in range(maxiter+1):
residual = [b[i]-sum(a*v for a, v in zip(A[i], x)) for i in range(n)]
if max(map(abs, residual)) <= target:
return x, k
if k == maxiter:
break
new = [(b[i]-sum(A[i][j]*x[j] for j in range(n) if j != i))/A[i][i]
for i in range(n)]
if not all(math.isfinite(v) for v in new):
raise ArithmeticError("nonfinite Jacobi iterate")
x = new
raise RuntimeError("true residual did not reach tolerance")
print(jacobi([[4, 1], [2, 3]], [1, 2])) # near ([0.1, 0.6], iteration count)加权 Jacobi 另用 ,在多重网格中常用作平滑器。改变 会改变谱与稳定性条件,不能只因更新便于并行就不再检查收敛。
参考资料
- ↑ Richard Barrett et al. Templates for the Solution of Linear Systems,Jacobi Method。