2010-04-29 8 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 

이다. 자, 저는 벡터와 행렬 사이에 내적 (dot product)을 만들고 싶습니다. 합계, 우편 번호 및지도를 결합하여 처리하는 것이 매우 간단합니다.

그러나 행렬의 행을 통해 매핑하기 때문에 상자에 넣을 수는 있지만 결과는 박스형 벡터입니다.

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의 정의는 무엇입니까? –

답변

1

귀하의 Field 유형이 무엇인지 모르겠으므로 두 번째 발췌 문장을 잘 이해하지 못합니다.

그러나 행렬을 박스형 벡터로 나타내면 중간 결과는 박스형 벡터가됩니다. unboxed 결과를 원한다면, 명시 적으로 타입을 U.fromList . V.toList으로 변환해야합니다. 이 당신의 조밀 한 매트릭스 유형에 대한 예 (I는 간결을위한 스파 스 케이스를 생략) :

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 작동을 살펴보십시오.