2010-04-29 14 views
8

Chciałbym efektywnie manipulować macierzami (pełnymi lub rzadkimi) za pomocą biblioteki wektorowej Haskell.unboxing, (rzadkie) macierze i biblioteka wektorów haskell

Oto typu matryca

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 

Jak widać, matryca jest wektorem odpakowanych wektorów. Teraz chciałbym zrobić produkt punktowy między wektorem a matrycą. Jest to dość proste dzięki połączeniu sumy, suwaka i mapy.

Ale jeśli to zrobię, ponieważ mapuję przez rzędy macierzy, wynikiem jest wektor pudełkowy, mimo że można go rozpakować.

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) 

Jak skutecznie uzyskać rozpakowany wektor?

+1

co jest wadą Field? –

Odpowiedz

1

Nie wiem, jaki jest twój typ Field, więc nie do końca rozumiem drugi fragment.

Ale jeśli reprezentujesz swoją matrycę jako wektor zapakowany w pudełka, twoje wyniki pośrednie będą wektorem pola. Jeśli chcesz mieć nieprzypisany wynik, musisz przekonwertować typy jawnie za pomocą U.fromList . V.toList. To przykład dla swojej gęstej typu matrycy (pominąłem rzadki przypadek dla zwięzłość):

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) 

wyjściowa:

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

nie jestem pewien o wykonywaniu tego podejścia. Prawdopodobnie znacznie lepiej jest przechowywać całą macierz jako pojedynczy nieopakowany wektor i uzyskać dostęp do elementów według indeksu zgodnie z modelem przechowywania. W ten sposób nie potrzebujesz pudełkowych wektorów.

Zobacz również nową bibliotekę repa i jej index.