2010-04-29 61 views
8

我想用haskell的矢量庫有效地處理矩陣(完全或稀疏)。拆箱,(稀疏)矩陣和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 

正如你可以看到,基體是裝箱向量的向量。現在,我想在矢量和矩陣之間做點積。通過合併金額,郵編和地圖來做相當簡單。

但如果我這樣做,因爲我通過矩陣的行映射,結果是盒裝的載體,即使它可能被拆箱。

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) 

如何有效地得到一個取消裝箱的向量?

+1

Field的定義是什麼? – 2010-04-30 19:49:20

回答

1

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

但是,如果您將矩陣表示爲盒裝矢量,則您的中間結果將爲盒裝矢量。如果你想有一個unboxed結果,你需要明確地將類型轉換爲U.fromList . V.toList。這對你的密集矩陣型爲例(我略去了稀疏的情況下):

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

-- assuming row-major order 
data Matrix a = Full (V.Vector (U.Vector a)) 

type Vector a = U.Vector a 

-- matrix to vector dot product 
dot :: (U.Unbox a, Num a) => (Matrix a) -> (Vector a) -> (Vector a) 
(Full rows) `dot` x = 
    let mx = V.map (vdot x) rows 
    in U.fromList . V.toList $ mx -- unboxing, O(n) 

-- vector to vector dot product 
vdot :: (U.Unbox a, Num a) => Vector a -> Vector a -> a 
vdot x y = U.sum $ U.zipWith (*) x y 

instance (Show a, U.Unbox a) => Show (Matrix a) where 
    show (Full rows) = show $ V.toList $ V.map U.toList rows 

showV = show . U.toList 

main = 
    let m = Full $ V.fromList $ map U.fromList ([[1,2],[3,4]] :: [[Int]]) 
     x = U.fromList ([5,6] :: [Int]) 
     mx = m `dot` x 
    in putStrLn $ (show m) ++ " × " ++ (showV x) ++ " = " ++ (showV mx) 

輸出:

[[1,2],[3,4]] × [5,6] = [17,39] 

我不知道這種方法的性能。可能將整個矩陣存儲爲單個未裝箱的向量並根據存儲模型按索引訪問元素要好得多。這樣你就不需要盒裝矢量。

看看也是在新的repa庫及其index操作。