我已经编写了Gauss Seidel和Conjugate Gradient迭代算法来解决Haskell中的基质问题(但这个问题与方法有关,而不是与语言有关)。我的理解是这两种算法都应该具有相似的收敛特性,并且在大多数情况下CG方法应该更快。我已经对来自http://math.nist.gov/MatrixMarket/的对称正定矩阵进行了很多测试,我几乎无法得到CG算法。收敛,而GS几乎总是如此。我找不到任何带有右侧矢量的对称正定矩阵用于在线测试目的,所以我只是随意创建我自己的RHS(也许这是问题的一部分?)。如果我在Ax = b中使用(转置A)* A而不是A,我可以得到CG方法收敛,这只是迫使矩阵是对称的。我在这里包含了CG代码。它显然不会按原样编译。如果有人需要它起作用,我会发布所有内容。对于(Similar question)来自此(Pseudocode and example)的简单示例,它正常工作。关于共轭梯度与高斯赛德尔收敛标准,我有什么遗漏吗?谁能指出我正确的方向让这个工作?谢谢。
conjGrad :: (Floating a, Ord a, Show a) => a -> SpMCR a -> SpVCR a -> SpVCR a -> (SpVCR a, Int)
conjGrad tol mA b x0 = loop x0 r0 r0 rs0 1
where r0 = b - (mulMV mA x0)
rs0 = dot r0 r0
loop x r p rs i
| (varLog "residual = " $ sqrt rs') < tol = (x',i)
| otherwise = loop x' r' p' rs' (i+1)
where mAp = mulMV mA p
alpha = rs / (dot p mAp)
x' = x + (alpha .* p)
r' = r - (alpha .* mAp)
rs' = dot r' r'
beta = rs' / rs
p' = r' + (beta .* p)
(.*) :: (Num a) => a -> SpVCR a -> SpVCR a
(.*) s v = fmap (s *) v
编辑:果然,我没有考虑到MM文件格式只包含对称矩阵的下对角线这一事实。谢谢。现在算法收敛但似乎需要更多的迭代。我的理解是,当使用精确算术时,CG应该总是收敛少于矩阵次序的迭代次数。使用浮点(Double)的事实会产生如此大的差异(1.5 - 2 x矩阵顺序是合理收敛所需的迭代)吗?
跟进:对于任何可能偶然发现这一点的人来说,事实证明我的大多数问题都与我用于测试的矩阵有关。对于使用CG算法求解它们似乎相当恶劣。在某些情况下,简单的预处理有所帮助。
答案 0 :(得分:1)
你可以通过使用带有浮动的精确库来回答你的第二个问题,例如CReal:http://hackage.haskell.org/package/numbers或者去除你的日志记录(我认为这是引入浮动约束的东西)并且只使用来自的理由Data.Ratio。
这当然会非常缓慢。但它应该让你研究浮点近似对收敛的影响。