我们希望对高斯消除进行编程,以计算基础(线性代数)作为我们自己的运动。这不是家庭作业。
我首先考虑[[Int]]
作为矩阵的结构。我当时认为我们可以按字典顺序对列表进行排序。但是我们必须用矩阵来计算。而且存在问题。有人可以给我们一些提示。
答案 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)
答案 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 = 0
和c = -7/5
。因此,为了解决所有我们需要的是每一行的第一个元素。这是一个找到c:
whatc :: Rational -> Rational -> Rational
whatc _ 0 = 0
whatc a b = - a / b
另外,正如其他人所说,使用列表来表示矩阵会给你带来更差的表现。但是,如果您只是想了解算法,列表应该没问题。