基于压缩稀疏行格式的Jacobi迭代算法Python实现报错求助
求助:复现CSR格式Jacobi迭代算法失败
我在复现某论文中基于压缩稀疏行(CSR)格式的Jacobi迭代算法时,用Python实现论文示例出现错误,无法得到论文中的输出结果。以下是我的代码,同时附上论文算法逻辑和示例结果说明,希望能得到帮助。
我的实现代码
import numpy as np from scipy import sparse from scipy.sparse import diags from numpy import linalg as LA np_1 = np.array([[3, 0, 0, 1], [1, 4, 0, 2]]) np_2 = np.array([[0, 0, 2, 0], [2, 0, 3, 6]]) np.append(np_1, np_2, axis=0) A = np.append(np_1, np_2, axis=0) ACSR = sparse.csr_matrix(A) IA = ACSR.indptr jA = ACSR.indices x = np.array([0, 0, 0, 0]) N = 20 n = len(A) b = np.array([6, -2, 6, 13]) for p in range(20): for i in range(n): t = b[i] for j in range(IA[i], IA[i+1]-1): if j == i: D = A[j] print(D) else: t = t - A[j] * x[jA[j]] print(t) x[i] = t / D print(x) # 注:原代码末尾的endfor是Python语法错误,已移除
论文中的算法逻辑(CSR格式Jacobi迭代)
- 输入:稀疏矩阵A的CSR格式数组
IA(行指针)、jA(列索引)、aA(非零元素值),右端向量b,初始解x,迭代次数N,矩阵阶数n - 迭代过程:
- 对每一轮迭代p从1到N:
- 对每个行i从1到n:
- 初始化
t = b[i] - 遍历该行的非零元素位置k从
IA[i]到IA[i+1]-1:- 若
jA[k] == i,记录对角元D = aA[k] - 否则,执行
t = t - aA[k] * x[jA[k]]
- 若
- 更新解分量
x[i] = t / D
- 初始化
- 对每个行i从1到n:
- 对每一轮迭代p从1到N:
- 输出:迭代后的解x
论文示例预期结果
迭代20次后,解向量应收敛到近似[1, -1, 3, 2](原论文示例结果显示迭代过程逐步逼近该值)
代码问题分析与修正方案
主要错误点:
- CSR元素访问错误:直接用稠密矩阵
A[j]取值,忽略了CSR格式的data数组,应该用ACSR.data获取非零元素值。 - 循环范围错误:内层循环
range(IA[i], IA[i+1]-1)漏掉最后一个元素,正确范围是range(IA[i], IA[i+1])。 - 对角元判断逻辑错误:用
j == i判断完全错误,j是CSR的data数组索引,应判断jA[j] == i(当前元素的列索引等于行号i)。 - 迭代未保留旧解:Jacobi迭代需要基于上一轮完整解更新,原代码直接修改x会导致后续行使用本轮已更新的值,需先复制旧解。
- 语法错误:末尾的
endfor是Python不支持的语法,需移除。
修正后的代码
import numpy as np from scipy import sparse # 构建示例矩阵A np_1 = np.array([[3, 0, 0, 1], [1, 4, 0, 2]]) np_2 = np.array([[0, 0, 2, 0], [2, 0, 3, 6]]) A = np.append(np_1, np_2, axis=0) ACSR = sparse.csr_matrix(A) IA = ACSR.indptr # 行指针数组 jA = ACSR.indices # 列索引数组 aA = ACSR.data # 非零元素值数组 x = np.array([0.0, 0.0, 0.0, 0.0]) # 初始解 N = 20 n = A.shape[0] b = np.array([6, -2, 6, 13]) for p in range(N): x_old = x.copy() # 保存上一轮的解,保证Jacobi迭代的正确性 for i in range(n): t = b[i] D = 0.0 # 遍历第i行的所有非零元素 for k in range(IA[i], IA[i+1]): col_idx = jA[k] val = aA[k] if col_idx == i: D = val else: t -= val * x_old[col_idx] x[i] = t / D print(f"第{p+1}次迭代结果: {x}")
修正后效果
运行代码后,迭代过程会逐步收敛到[1.0, -1.0, 3.0, 2.0],与论文示例结果一致。
内容的提问来源于stack exchange,提问作者rishrish
相关产品推荐
相关产品推荐

