如何获取Scipy隐式重启Arnoldi方法的迭代次数?
解决ARPACK求解特征值时的迭代次数获取问题
你的问题出在手动计数逻辑与ARPACK内部迭代计数逻辑不匹配,同时误用了非对称求解器处理Hermitian矩阵。以下是修正方案和解释:
核心问题分析
- 求解器误用:你的矩阵是Hermitian(自共轭)类型,应使用
_SymmetricArpackParams而非_UnsymmetricArpackParams,后者针对非对称矩阵,会造成不必要的开销和计数偏差。 - 手动计数错误:ARPACK的
maxiter是允许的最大迭代次数,当达到该次数后,ARPACK会停止迭代,但你的循环仍会重复调用params.iterate(),此时该方法不会执行实际迭代,但计数器i仍会递增,导致i超过maxiter。 - 无需手动计数:ARPACK内部已记录真实迭代次数,直接读取对应属性即可。
修正后的代码
import numpy as np import scipy.sparse.linalg._eigen.arpack as bark def ct(v): return np.conj(v.T) def eigsb(A, k=6, M=None, sigma=None, which='LM', v0=None, ncv=None, maxiter=None, tol=0, return_eigenvectors=True, Minv=None, OPinv=None, OPpart=None): n = A.shape[0] mode = 1 M_matvec = None Minv_matvec = None matvec = bark._aslinearoperator_with_dtype(A).matvec # 针对Hermitian矩阵使用对称ARPACK求解器 params = bark._SymmetricArpackParams(n, k, A.dtype.char, matvec, mode, M_matvec, Minv_matvec, sigma, ncv, v0, maxiter, which, tol) try: while not params.converged: params.iterate() except RuntimeError as e: # 捕获达到maxiter未收敛的错误 if "maximum number of iterations" in str(e): pass else: raise # 直接读取ARPACK内部记录的迭代次数 actual_iter = params.iter return actual_iter, params.extract(return_eigenvectors) # 生成Hermitian矩阵 d = 50 mat = np.random.rand(d,d) + 1j * np.random.rand(d,d) mat = mat - (np.random.rand(d,d) + 1j * np.random.rand(d,d)) mat = mat + ct(mat) # 调用函数获取迭代次数和特征值 iter_count, (vals, vecs) = eigsb(mat, k=1, which='SR', ncv=6, maxiter=50) print(f"实际迭代次数: {iter_count}")
关键说明
params.iter:这是ARPACK内部维护的迭代次数计数器,记录了实际执行的迭代次数,不会出现超过maxiter的情况——当达到maxiter时,ARPACK会抛出RuntimeError,此时params.iter就是执行到最后的迭代次数。- 异常捕获:添加异常捕获是为了处理达到
maxiter仍未收敛的场景,避免程序崩溃,同时保留已有的计算结果。 - 对称求解器:Hermitian矩阵使用
_SymmetricArpackParams能大幅提升求解效率,且计数更准确。
内容的提问来源于stack exchange,提问作者AProjans
相关产品推荐
相关产品推荐

