哈斯克尔的矩阵部门 [英] Matrix division in Haskell
问题描述
有什么不对?此代码应该通过查找 a
次 b
inverse来进行矩阵分解。
导入列表
导入比率
inverse :: [[Rational]] - > [[Rational]]
inverse mat = sweep([],zipWith(++)mat单元)其中
unit = map(take(length mat))$ iterate(0 :)(1: (xs,yss)= sweep(xss'++ [ws],filter(any(/ = 0))[0,0 ..])
sweep(xss,[])= xss
sweep yss')其中
Just(x:xs)= find((/ = 0)。 map(map f)[xss,yss]
f(y:ys)= zipWith(\ de - > 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'=错误范围不匹配
| (x0,x1'))=边界x
((y0, y1',y0',y1'))=边界y
ir =范围(x0,x0')
jr =范围(y1,y1')
kr =范围(x1, x1')
l = [((i,j),sum [x!(i,k)* y!(k,j)| k < - kr
通过乘以 a
和 b
'inverse。
这里似乎有一些问题,首先,定义 l
in mmult
似乎是不完整的,你开始一个列表并开始一个列表,但是从不关闭它们。
$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ )| k <-kr])| i <-ir,j <-jr]
正如你所说的,链接这两个模块的另一个问题是,你正在使用不同类型的matri cies在两个模块中,第一个是反转矩阵的地方,将它当作列表的列表。第二个乘以两个矩阵,使用数组。要组合这两者,您需要能够在表示之间进行转换。实质上,您需要两个操作:
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 ab = mmult a(fromListMatrix(invert(toListMatrix b)))
在实现方面,让我们从到ListMatrix
开始,因为它更容易。
toListMatrix mat =
现在,我们将需要数组,所以
toListMatrix mat = let((x0,x1),(x0',x1'))=边界垫in
我们将逐行构建它:
toListMatrix mat = let((x0,x1),(x0',x1'))=边界在
中[ rowNum < - range(x1,x1')]
每行只是矩阵的元素使用固定的行号:
toListMatrix mat = let((x0,x1),(x0',x1'))=在
[[垫! (pos,rowNum)| pos < - range(x0,x0')] | rowNum < - range(x1,x1')]
转到 fromlistMatrix
:
fromListMatrix mat =
我们希望将每个元素与一个位置相关联,然后将结果提供给 array
,所以:(),(长度(头垫),长度垫))indexedElems其中
indexedElems =
首先,我们需要获取行数,所以:
fromListMatrix mat = array(length(head mat),length mat)indexedElems其中
indexedElems = someFunction(zip [1 ..] mat)
然后我们输入仓位数字:
fromListMatrix mat = array(length(head mat),length mat)indexedElems其中
indexedElems = someFunction(map addPositions(zip [1 ..] mat))
addPositions(rowNum,elems)= zip [(pos,rowNum)| pos< - [1 ..]] elems
现在我们有一个索引行的列表元素。我们需要将它连接成一个列表:
pre $ 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其中
indexedElems = concat(zipWith addPositions [1 ..] mat)
addPositions rowNum elems = zip [(pos,rowNum)| pos< - [1 ..]] elems
完成!
What is wrong? This code is supposed to do matrix division by finding a
times b
inverse. I try to understand what its errors are but I fail to see how to link it.
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
How can I link it with
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
to do matrix division by multiplying a
and b
's inverse.
There seem to be a couple problems here. First of all, the definition of l
in mmult
seems to be incomplete. You start a list and start a pair, but never close them. Perhaps you meant:
l = [((i, j), sum [x ! (i, k) * y ! (k, j) | k <- kr]) | i <- ir, j <- jr]
The other problem that is inherent in, as you put it, linking those two modules, is that you are using different types for matricies in the two modules. The first one, where you invert a matrix, treats it as a list of lists. The second one, which multiplies two matricies, uses arrays. To combine the two, you need to be able to convert between the representations. Essentially, you need two operations:
fromListMatrix :: [[Rational]] -> Array (Int, Int) Rational
toListMatrix :: Array (Int, Int) Rational -> [[Rational]]
Once you have these, you can implement matrix division pretty easily.
divideMatrix :: Array (Int, Int) Rational -> Array (Int, Int) Rational -> Array (Int, Int) Rational
divideMatrix a b = mmult a (fromListMatrix (invert (toListMatrix b)))
On the implementation front, let's start with toListMatrix
, as it is easier.
toListMatrix mat =
Now, we're going to need the bounds of the array, so
toListMatrix mat = let ((x0, x1), (x0', x1')) = bounds mat in
We will construct it row by row:
toListMatrix mat = let ((x0, x1), (x0', x1')) = bounds mat in
[row | rowNum <- range (x1, x1')]
Each row is simply the elements of the matrix with a fixed row number:
toListMatrix mat = let ((x0, x1), (x0', x1')) = bounds mat in
[[mat ! (pos, rowNum) | pos <- range (x0, x0')] | rowNum <- range (x1, x1')]
Moving on to fromlistMatrix
:
fromListMatrix mat =
We want to associate each element with a position, and then feed the result to array
, so:
fromListMatrix mat = array ((1, 1), (length (head mat), length mat)) indexedElems where
indexedElems =
First we need to get the row numbers in place, so:
fromListMatrix mat = array (length (head mat), length mat) indexedElems where
indexedElems = someFunction (zip [1..] mat)
Then we put in the position numbers:
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
Now we have a list of rows of the indexed elements. We need to concatenate this into a single list:
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
Finally, we clean up the code by changing map addPositions (zip [1..] mat)
into a simpler form with 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
You're done!
这篇关于哈斯克尔的矩阵部门的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!