jacobian迭代, guassion-seidel迭代,multigrid预条件,conjugate gradient迭代, preconditioner conjugate gradient, biconjugate gradient, GMRES, biconjugate gradient stablized
动机
迭代法解线性方程组,在稀疏矩阵时比直接法快几十倍,所以自己实现一下迭代法,加深理解
并行化:迭代法相对直接法,并行化更直观
速度:迭代法中途有很多乘法计算在矩阵稀疏时乘以0,所以矩阵稀疏时计算起来会非常快(几十倍)
相对直接法中间过程都会变成dense矩阵,所以稀疏和不稀疏计算时间一样
误差:直接法只有浮点误差,迭代法是近似收敛法,会有收敛误差
不收敛:迭代法对矩阵本身的性质:对称正定(SPD),对称,矩阵稳定性(最大特征值/最小特征值)有要求,矩阵性质不好时会很难收敛
代码还是都在 https://github.com/mrzhuzhe/riven/solver 这个目录下
https://github.com/mrzhuzhe/riven 现在在这个repos项目中增加了Eigen作为子项目
Clone 时需要 --recursive
其中第一个参数:"32"是矩阵大小,可以从外部传入默认是64
其中第二个参数:1 是柏松矩阵 2 是稠密对称矩阵 0 是随机稠密矩阵
后面都保持这个约定
jacobian 有个小trick就是计算时,因为都是根据对角线来,如果矩阵是基于对角线的带状矩阵,可以把一行的计算简化成几个固定乘法的计算
高斯赛德二和jacobian都需要矩阵近似对称正定,且收敛需要的步数较多,但是好处是非常容易并行化
你只需要写一个f2c和c2f函数
再 16 - 8 - 4 - 8 - 16 每个尺度上跑几个iteration 给下一个尺度当初始条件就可以了
根据painless conjugate gradient文档共轭梯度就是向梯度方向前进,但是不是垂直于梯度方向(sgd),而是共轭于自己上一次的迭代方向,每次迭代的方向都是已经确定的,每次只需计算步长即可
共轭梯度为krylov子空间法,虽然共轭梯度也需要正定,但是似乎比jacobian等迭代法有更好的泛化性能
双共轭梯度泛化性比共轭梯度更好一些,但是需要额外再计算一个residuel和方向
还有一个计算量更大但数值更稳定的bicg-stablized 在 solver/inc/bicg_stab.h
预条件法改变了优化的目标residuel,且在迭代过程中要解一个子线性方程,但是会让迭代收敛大幅加快
GMRES在计算过程中需要求特征值
1. 共轭梯度为什么时候会fail , fail和不收敛有关系吗?
Fail是因为共轭梯度计算alpha和beta时有除法,判断到分母为0时算法就会当作异常
2. 为什么迭代法都是针对一列b和x计算的,多列x和b如何处理?
后面会根据实际使用时遇到的问题来持续优化
还是研究具体场景