2010-04-29 15 views
8

Matrisleri (tam veya seyrek) haskell'in vektör kütüphanesi ile verimli bir şekilde işlemek istiyorum. İşte (unchand), (seyrek) matrisler ve haskell vektörel kütüphanesi

Gördüğünüz gibi, matris kutusuz vektörlerin bir vektör olan bir matris tipi

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 

olduğunu. Şimdi, bir vektör ile matris arasında nokta ürünü yapmak istiyorum. Bir toplam, fermuar ve haritayı birleştirerek yapmak oldukça basit.

Ama eğer bunu yaparsam, matrisin satırları üzerinden eşleme yapıyorum çünkü sonuç, kutulanmamış olsa bile kutulu bir vektördür.

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) 

Kutusuz bir vektörü verimli bir şekilde nasıl alabilirim?

+1

Saha Tanımı Nedir? –

cevap

1

Field türünüzün ne olduğunu bilmiyorum, bu yüzden ikinci snippet'i tam olarak anlamadım.

Ancak matrisinizi kutulu bir vektör olarak temsil ediyorsanız, ara sonuçlarınız kutulu vektörler olacaktır. Kutusuz bir sonuca sahip olmak istiyorsanız, türleri U.fromList . V.toList ile açıkça dönüştürmeniz gerekir. Bu yoğun matris türü için bir örnek (I kısalık için seyrek durumda atlanmıştır):

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) 

Çıktı:

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

Ben bu yaklaşımın performansı hakkında emin değilim. Muhtemelen, tüm matrisin tek kutudan çıkarılmamış bir vektör olarak saklanması ve depolama modeline göre indeksle erişim elemanlarının bulunması daha iyidir. Bu şekilde kutulu vektörlere ihtiyacınız yoktur.

Yeni repa kitaplığına ve index işlemine de bakın.