Python收敛图绘制报错(列表索引需为整数/切片而非元组)的解决方法
问题解决:Jacobi/Gauss-Seidel迭代范数绘图报错处理
错误原因
报错'list indices must be integers or slices, not tuple'出现在第46、47行的res_jacobi[:,k]和res_gauss_seidel[:,k],因为res_jacobi是Python列表(结构为[分量1迭代列表, 分量2迭代列表, ...]),而非numpy数组,不支持二维数组的[:,k]索引语法。
修正后的完整代码
import numpy as np import matplotlib.pyplot as plt def jacobi(A, b, x0, tol=1e-10, max_iter=100): n = len(A) x = x0.copy() res = [[] for _ in range(n)] for k in range(max_iter): x_new = np.zeros_like(x) for i in range(n): s = 0 for j in range(n): if i != j: # 取标量值计算,避免维度不匹配 s += A[i][j] * x[j, 0] x_new[i, 0] = (b[i, 0] - s) / A[i][i] res[i].append(x_new[i, 0]) if np.linalg.norm(x_new - x) < tol: return x_new, np.array(res).T # 转置为(迭代步数, 分量数)的数组 x = x_new.copy() return None, np.array(res).T def gauss_seidel(A, b, x0, tol=1e-10, max_iter=100): n = len(A) x = x0.copy() res = [[] for _ in range(n)] for k in range(max_iter): x_old = x.copy() for i in range(n): s = 0 for j in range(n): if i != j: s += A[i][j] * x[j, 0] x[i, 0] = (b[i, 0] - s) / A[i][i] res[i].append(x[i, 0]) # 统一收敛判断条件,和Jacobi保持一致 if np.linalg.norm(x - x_old) < tol: return x, np.array(res).T return None, np.array(res).T A = np.random.normal(0, 1, size=(4,4)) + 10000 * np.identity(4) b = np.random.normal(0, 1, size=(4,1)) x_exact = np.linalg.solve(A, b) x0_jacobi = np.random.normal(0, 1, size=(4,1)) x0_gauss_seidel = np.random.normal(0, 1, size=(4,1)) x_jacobi, res_jacobi = jacobi(A, b, x0_jacobi) x_gauss_seidel, res_gauss_seidel = gauss_seidel(A, b, x0_gauss_seidel) # 计算每一步的范数,res_jacobi现在是(迭代步数,4)的数组,转置后和x_exact匹配 jacobi_norms = [np.linalg.norm(x_exact - res_jacobi[k].reshape(4,1)) for k in range(len(res_jacobi))] gauss_seidel_norms = [np.linalg.norm(x_exact - res_gauss_seidel[k].reshape(4,1)) for k in range(len(res_gauss_seidel))] plt.plot(range(len(jacobi_norms)), jacobi_norms, label='Jacobi') plt.plot(range(len(gauss_seidel_norms)), gauss_seidel_norms, label='Gauss-Seidel') plt.xlabel('迭代步数k') plt.ylabel('||x - xk||') plt.legend() plt.show()
关键修改说明
- 结果列表转numpy数组并转置:在两个迭代函数的返回语句中,将
res转为numpy数组后执行.T转置,得到(迭代步数, 分量数)的结构,方便按步数提取完整迭代解。 - 维度匹配处理:
- 迭代计算时,将列向量的元素取标量值(如
x[j,0]),避免数组运算导致维度错误; - 计算范数时,将每一步的迭代解
res_jacobi[k]reshape为列向量,和x_exact的维度对齐。
- 迭代计算时,将列向量的元素取标量值(如
- 统一收敛判断条件:Gauss-Seidel函数中改用
np.linalg.norm(x - x_old)判断收敛,和Jacobi逻辑保持一致,避免因残差计算方式不同导致的迭代次数差异。
内容的提问来源于stack exchange,提问作者CrustyCrab
相关产品推荐
相关产品推荐

