Haskell中的矩阵划分

时间:2012-06-19 15:21:06

标签: haskell

有什么问题?该代码应该通过查找ab逆来进行矩阵除法。我试图了解它的错误是什么,但我没有看到如何链接它。

import List
import Ratio

inverse :: [[Rational]] -> [[Rational]]
inverse mat = sweep ([], zipWith (++) mat unit) where
    unit = map (take (length mat)) $ iterate (0 :) (1 : [0,0..])
    sweep (xss, []) = xss
    sweep (xss, yss) = sweep (xss' ++ [ws], filter (any (/= 0)) yss') where
        Just (x : xs) = find ((/= 0) . head) yss
        ws = map (/ x) xs
        [xss', yss'] = map (map f) [xss, yss]
        f (y : ys) = zipWith (\d e -> e - d * y) ws ys

如何将其与

链接
import Data.Array

mmult :: (Ix i, Num a) => Array (i, i) a -> Array (i, i) a -> Array (i, i) a 
mmult x y 
    | x1 /= y0 || x1' /= y0'  = error "range mismatch"
    | otherwise               = array ((x0, y1), (x0', y1')) l where
        ((x0, x1), (x0', x1')) = bounds x
        ((y0, y1), (y0', y1')) = bounds y
        ir = range (x0, x0')
        jr = range (y1, y1')
        kr = range (x1, x1')
        l  = [((i, j), sum [x ! (i, k) * y ! (k, j) | k <- kr

通过将ab相乘来进行矩阵除法。

1 个答案:

答案 0 :(得分:2)

这里似乎有几个问题。首先,lmmult的定义似乎不完整。你开始一个列表并开始一对,但从不关闭它们。也许你的意思是:

l = [((i, j), sum [x ! (i, k) * y ! (k, j) | k <- kr]) | i <- ir, j <- jr]

正如你所说,链接这两个模块所固有的另一个问题是,你在两个模块中使用不同类型的基质。第一个,您反转矩阵,将其视为列表列表。第二个是两个matricies的乘法,它使用数组。要将两者结合起来,您需要能够在表示之间进行转换。基本上,您需要两个操作:

fromListMatrix :: [[Rational]] -> Array (Int, Int) Rational
toListMatrix :: Array (Int, Int) Rational -> [[Rational]]

一旦有了这些,就可以很容易地实现矩阵划分。

divideMatrix :: Array (Int, Int) Rational -> Array (Int, Int) Rational -> Array (Int, Int) Rational
divideMatrix a b = mmult a (fromListMatrix (invert (toListMatrix b)))

在实施方面,让我们从toListMatrix开始,因为它更容易。

toListMatrix mat =

现在,我们需要数组的边界,所以

toListMatrix mat = let ((x0, x1), (x0', x1')) = bounds mat in

我们将逐行构建它:

toListMatrix mat = let ((x0, x1), (x0', x1')) = bounds mat in
    [row | rowNum <- range (x1, x1')]

每一行都只是具有固定行号的矩阵元素:

toListMatrix mat = let ((x0, x1), (x0', x1')) = bounds mat in
    [[mat ! (pos, rowNum) | pos <- range (x0, x0')] | rowNum <- range (x1, x1')]

转到fromlistMatrix

fromListMatrix mat =

我们希望将每个元素与一个位置相关联,然后将结果提供给array,所以:

fromListMatrix mat = array ((1, 1), (length (head mat), length mat)) indexedElems where
    indexedElems =

首先我们需要获得行号,所以:

fromListMatrix mat = array (length (head mat), length mat) indexedElems where
    indexedElems = someFunction (zip [1..] mat)

然后我们输入位置编号:

fromListMatrix mat = array (length (head mat), length mat) indexedElems where
    indexedElems = someFunction (map addPositions (zip [1..] mat))
    addPositions (rowNum, elems) = zip [(pos, rowNum) | pos <- [1..]] elems

现在我们有一个索引元素的行列表。我们需要将它连接成一个列表:

fromListMatrix mat = array (length (head mat), length mat) indexedElems where
    indexedElems = concat (map addPositions (zip [1..] mat))
    addPositions (rowNum, elems) = zip [(pos, rowNum) | pos <- [1..]] elems

最后,我们通过将map addPositions (zip [1..] mat)更改为包含zipWith的简单表单来清理代码:

fromListMatrix mat = array (length (head mat), length mat) indexedElems where
    indexedElems = concat (zipWith addPositions [1..] mat)
    addPositions rowNum elems = zip [(pos, rowNum) | pos <- [1..]] elems

你已经完成了!