/ / unboxing, (розрізнені) матриці та векторна бібліотека haskell - масиви, haskell, вектор, unboxing

розпаковані (рідкі) матриці та векторна бібліотека Haskell - масиви, маскування, вектор, розпакування

Я хотів би ефективно маніпулювати матрицями (повними або розрідженими) за допомогою векторної бібліотеки 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

Як бачимо, матриця є вектором незміщених векторів. Тепер я хотів би зробити точковий продукт між вектором та матрицею. Зробити це досить просто, поєднуючи суму, поштовий індекс та карту.

Але якщо я це роблю, оскільки я картографую через рядки матриці, результат - вектор в коробці, навіть якщо він може бути без коробки.

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 для відповіді № 1

Я не знаю, що ваше Field тип є, тому я не розумію другий фрагмент.

Але якщо ви представляєте свою матрицю як коробковий вектор, вашими проміжними результатами будуть коробчасті вектори. Якщо ви хочете отримати некомплектний результат, вам потрібно явно перетворити типи 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]

Я не впевнений у виконанні такого підходу. Напевно, набагато краще зберігати всю матрицю як єдиний неосмислений вектор та елементи доступу за індексом відповідно до моделі зберігання. Таким чином, вам не потрібні бокси.

Погляньте також на нове ремонт бібліотека та її index операції.