拆箱,(稀疏)矩阵和haskell矢量库

jiy*_*ori 8 arrays unboxing haskell vector

我想用haskell的向量库有效地操纵矩阵(完整或稀疏).

这是一种矩阵类型

import qualified Data.Vector.Unboxed as U
import qualified Data.Vector as V

data Link a = Full (V.Vector (U.Vector a))
    | Sparse (V.Vector (U.Vector (Int,a)))

type Vector a = U.Vector a
Run Code Online (Sandbox Code Playgroud)

如您所见,矩阵是未装箱矢量的矢量.现在,我想在矢量和矩阵之间做一个点积.通过组合sum,zip和map可以非常简单.

但是,如果我这样做,因为我正在映射矩阵的行,结果是一个盒装矢量,即使它可以是未装箱的.

propagateS output (Field src) (Full weights) = V.map (sum out) weights
    where out     = U.map output src
          sum s w = U.sum $ zipWithFull (*) w s

propagateS output (Field src) (Sparse weights) = V.map (sum out) weights
    where out     = U.map output src
          sum s w = U.sum $ zipWithSparse (*) w s

zipWithFull = U.zipWith

zipWithSparse f x y = U.map f' x
    where f' (i,v) = f v (y U.! i)
Run Code Online (Sandbox Code Playgroud)

如何有效地获得未装箱的矢量?

sas*_*nin 1

我不知道你的Field类型是什么,所以我不太明白第二个片段。

\n\n

但是,如果将矩阵表示为盒装向量,则中间结果将是盒装向量。如果您想要获得未装箱的结果,则需要使用 显式转换类型U.fromList . V.toList。这是密集矩阵类型的示例(为简洁起见,我省略了稀疏情况):

\n\n
import qualified Data.Vector.Unboxed as U\nimport qualified Data.Vector as V\n\n-- assuming row-major order\ndata Matrix a = Full (V.Vector (U.Vector a))\n\ntype Vector a = U.Vector a\n\n-- matrix to vector dot product\ndot :: (U.Unbox a, Num a) => (Matrix a) -> (Vector a) -> (Vector a)\n(Full rows) `dot` x =\n  let mx = V.map (vdot x) rows\n  in U.fromList . V.toList $ mx  -- unboxing, O(n)\n\n-- vector to vector dot product\nvdot :: (U.Unbox a, Num a) => Vector a -> Vector a -> a\nvdot x y = U.sum $ U.zipWith (*) x y\n\ninstance (Show a, U.Unbox a) => Show (Matrix a) where\n  show (Full rows) = show $ V.toList $ V.map U.toList rows\n\nshowV = show . U.toList\n\nmain =\n  let m = Full $ V.fromList $ map U.fromList ([[1,2],[3,4]] :: [[Int]])\n      x = U.fromList ([5,6] :: [Int])\n      mx = m `dot` x\n  in putStrLn $ (show m) ++ " \xc3\x97 " ++ (showV x) ++ " = " ++ (showV mx)\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
 [[1,2],[3,4]] \xc3\x97 [5,6] = [17,39]\n
Run Code Online (Sandbox Code Playgroud)\n\n

我不确定这种方法的性能。将整个矩阵存储为单个未装箱向量并根据存储模型通过索引访问元素可能会更好。这样你就不需要盒装向量。

\n\n

另请查看新的repa库及其index操作。

\n