packages feed

goal-core-0.20: benchmarks/outer-products.hs

{-# LANGUAGE DataKinds,ScopedTypeVariables,FlexibleContexts #-}

import Goal.Core
import qualified Goal.Core.Vector.Generic as G
import qualified Goal.Core.Vector.Storable as S
import qualified Goal.Core.Vector.Boxed as B

import qualified Numeric.LinearAlgebra as H
import qualified Criterion.Main as C
import qualified System.Random.MWC.Probability as P


--- Globals ---


type Rows = 1000
type Columns = 1000

n :: Int
n = 20

addMatrices :: (KnownNat n, KnownNat k) => S.Matrix n k Double -> S.Matrix n k Double -> S.Matrix n k Double
addMatrices (G.Matrix mtx1) (G.Matrix mtx2) = G.Matrix $ S.add mtx1 mtx2


--- Function ---


averageOuterProduct2 v12s =
    let ln = fromIntegral $ length v12s
     in S.withMatrix (S.scale ln) $ foldr foldfun (G.Matrix $ S.replicate 0) v12s
    where foldfun (v1,v2) mtx = addMatrices mtx $ S.outerProduct v1 v2

averageWeightedOuterProduct2 wv12s =
    foldr foldfun (G.Matrix $ S.replicate 0) wv12s
        where foldfun (w,v1,v2) mtx = addMatrices mtx . S.outerProduct v1 $ S.scale w v2


--- Main ---


main :: IO ()
main = do

    let rnd :: P.Prob IO Double
        rnd = P.uniformR (-1,1)

    v1s :: [S.Vector Rows Double]
        <- P.withSystemRandom . P.sample . replicateM n $ S.replicateM rnd
    v2s :: [S.Vector Columns Double]
        <- P.withSystemRandom . P.sample . replicateM n $ S.replicateM rnd

    let ws :: [Double]
        ws0 = [1..fromIntegral n]
        ws = (/sum ws0) <$> ws0

    let v12s = zip v1s v2s
        wv12s = zip3 ws v1s v2s
    let v11s = zip v1s v1s
        wv11s = zip3 ws v1s v1s

    C.defaultMain
       [ C.bench "average-outer-product" $ C.nf averageOuterProduct2 v12s
       , C.bench "bulk-outer-product" $ C.nf S.averageOuterProduct v12s
       , C.bench "average-weighted-outer-product" $ C.nf averageWeightedOuterProduct2 wv12s
       , C.bench "bulk-weighted-outer-product" $ C.nf S.weightedAverageOuterProduct wv12s
       , C.bench "average-outer-product0" $ C.nf averageOuterProduct2 v11s
       , C.bench "bulk-outer-product0" $ C.nf S.averageOuterProduct v11s
       , C.bench "average-weighted-outer-product0" $ C.nf averageWeightedOuterProduct2 wv11s
       , C.bench "bulk-weighted-outer-product0" $ C.nf S.weightedAverageOuterProduct wv11s
       , C.bench "triangular-weighted-outer-product0" $ C.nf (S.lowerTriangular . S.weightedAverageOuterProduct) wv11s ]