2010-04-29 3 views
8

Я хотел бы эффективно манипулировать матрицами (полными или разреженными) с векторной библиотекой haskell.unboxing, (разреженные) матрицы и векторная библиотека 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 

Как вы можете видеть, матрица является вектором Unboxed векторов. Теперь я хотел бы сделать точечный продукт между вектором и матрицей. Это довольно просто сделать, объединив сумму, почтовый индекс и карту.

Но если я это сделаю, потому что я просматриваю строки матрицы, результатом является вектор в виде коробочки, хотя он может быть распакован.

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) 

Как я могу получить вектор unboxed как результат эффективно?

+1

Что такое defn of Field? –

ответ

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 операции.