在Haskell中实现Gauss-Jordan消除

时间:2011-12-11 11:35:38

标签: math haskell linear-algebra

我们希望对高斯消除进行编程,以计算基础(线性代数)作为我们自己的运动。这不是家庭作业。

我首先考虑[[Int]]作为矩阵的结构。我当时认为我们可以按字典顺序对列表进行排序。但是我们必须用矩阵来计算。而且存在问题。有人可以给我们一些提示。

2 个答案:

答案 0 :(得分:4)

考虑使用hmatrix包中的矩阵。在其模块中,您可以找到快速implementation of a matrix和大量linear algebra algorithms。浏览他们的消息来源可能会帮助您解决疑虑。

这是一个通过将矩阵分割成行来将一行添加到另一行的简单示例。

import Numeric.Container
import Data.Packed.Matrix

addRow :: Container Vector t => Int -> Int -> Matrix t -> Matrix t
addRow from to m = let rows = toRows m in
  fromRows $ take to rows ++
             [(rows !! from) `add` (rows !! to)] ++
             drop (to + 1) rows

另一个例子,这次使用矩阵乘法。

addRow :: (Product e, Container Vector e) =>
          Int -> Int -> Matrix e -> Matrix e
addRow from to m = m `add` (e <> m)
  where
    nrows = rows m
    e = buildMatrix nrows nrows
        (\(r,c) -> if (r,c) /= (to,from) then 0 else 1)

比照。 ContainerVectorProduct

答案 1 :(得分:1)

如果您使用[[Rational]]而不是[[Int]],那将更容易,因为您获得了很好的分工。

您可能希望从实现基本行操作开始。

swap :: Int -> Int -> [[Rational]] -> [[Rational]
swap r1 r2 m = --a matrix with r1 and r2 swapped

scale :: Int -> Rational -> [[Rational]] -> [[Rational]]
scale r c m = --a matrix with row r multiplied by c

addrow :: Int -> Int -> Rational -> [[Rational]] -> [[Rational]]
addrow r1 r2 c m = --a matrix with (c * r1) added to r2

为了实际执行guassian消除,您需要一种方法来决定将一行中的多个行添加到另一行以获得零。所以给了两行..

5 4 3 2 1
7 6 5 4 3

我们想要将第1行添加c到第2行,以便7变为零。所以7 + c * 5 = 0c = -7/5。因此,为了解决所有我们需要的是每一行的第一个元素。这是一个找到c:

的函数
whatc :: Rational -> Rational -> Rational
whatc _ 0 = 0
whatc a b = - a / b

另外,正如其他人所说,使用列表来表示矩阵会给你带来更差的表现。但是,如果您只是想了解算法,列表应该没问题。