使用scipy.sparse.linalg.eigsh时遇ARPACK错误-9999的解决咨询
解决方案
1. 确保M算子满足对称正定要求
eigsh要求广义特征值问题中的M算子是对称正定的(实数域场景),否则ARPACK的默认求解逻辑会失效:
- 定义
LinearOperator时显式指定is_hermitian=True(实数场景等价于对称),让Scipy明确算子的对称性,避免内部校验出错。 - 验证M算子的正定性:对随机向量
x,计算x.T @ Mop.matvec(x),结果需为正(浮点误差范围内)。
2. 调整eigsh的求解参数
默认的which='LM'(最大模特征值)在广义问题下可能难以收敛,尝试切换目标特征值类型并指定求解模式:
- 使用
which='LA'(最大代数特征值)或which='SA'(最小代数特征值),搭配mode='normal'。 - 若需中间特征值,可结合shift-invert模式,无需精确猜测sigma:比如用
sigma=0搭配which='LM',此时求解的是最小广义特征值(等价于找$M^{-1}A$的最大模特征值)。
3. 验证LinearOperator的实现正确性
手动校验Aop和Mop的矩阵向量乘法是否符合预期:
- 生成小维度的稠密矩阵
A_dense、M_dense,对应你的算子逻辑。 - 对比
Aop.matvec(x)与A_dense @ x、Mop.matvec(x)与M_dense @ x的结果,确保完全一致(浮点误差内)。
4. 增加迭代次数或调整ARPACK参数
如果是迭代次数不足导致的分解失败,显式设置maxiter参数(默认值可能偏小):
vals, vecs = eigsh(Aop, k=5, M=Mop, which='LA', mode='normal', maxiter=2000)
示例修正代码
import numpy as np from scipy.sparse.linalg import LinearOperator, eigsh # 示例对称正定M算子的matvec实现 def M_matvec(x): return x + 0.3 * np.roll(x, 1) + 0.3 * np.roll(x, -1) # 示例对称A算子的matvec实现 def A_matvec(x): return 2 * x + np.roll(x, 1) + np.roll(x, -1) n = 100 # 显式指定is_hermitian=True Aop = LinearOperator((n, n), matvec=A_matvec, is_hermitian=True) Mop = LinearOperator((n, n), matvec=M_matvec, is_hermitian=True) # 调整参数后的调用 vals, vecs = eigsh(Aop, k=5, M=Mop, which='LA', mode='normal', maxiter=1000) print("特征值:", vals)
内容的提问来源于stack exchange,提问作者donionn74
相关产品推荐
相关产品推荐

