8

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

ご覧のとおり、行列はボックス化されていないベクトルのベクトルです。今、ベクトルと行列の間で内積をしたいと思います。sum、zip、および map を組み合わせることで、かなり簡単に実行できます。

しかし、これを行うと、行列の行を介してマッピングしているため、ボックス化されていない場合でも、結果はボックス化されたベクトルになります。

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)

ボックス化されていないベクトルを結果として効率的に取得するにはどうすればよいですか?

4

1 に答える 1

1

あなたのFieldタイプがわからないので、2番目のスニペットがよくわかりません。

ただし、行列をボックス化されたベクトルとして表すと、中間結果はボックス化されたベクトルになります。ボックス化されていない結果が必要な場合は、型を明示的に変換する必要があります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操作も見てください。

于 2010-05-04T17:49:45.370 に答える