packages feed

ttrie-0.1: benchmarks/BenchGen.hs

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module BenchGen where

import Control.Applicative
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Primitive
import Control.Monad.Trans.Class
import Control.Monad.Trans.State.Strict
import Data.Bifunctor
import Data.Set (Set)
import qualified Data.Set as Set
import qualified Data.Vector as V
import System.Random.MWC
import System.Random.MWC.CondensedTable

------------------------------------------------------------------------------

newtype Generator m k a = Generator { unG :: StateT (Gen (PrimState m), Set k) m a }
  deriving (Functor, Applicative, Monad)

instance MonadIO m => MonadIO (Generator m k) where
    liftIO = Generator . liftIO

runGenerator :: PrimMonad m => Gen (PrimState m) -> Generator m k a -> m a
runGenerator gen (Generator m) = evalStateT m (gen, Set.empty)

liftGen :: PrimMonad m => (Gen (PrimState m) -> m a) -> Generator m k a
liftGen f = Generator $ lift . f =<< gets fst

reuse :: (PrimMonad m, Ord k) => Generator m k k -> Generator m k k
reuse keygen = Generator $ do
    (gen,ks) <- get
    if Set.null ks
        then unG keygen
        else do
            i <- lift $ uniformR (0, Set.size ks - 1) gen
            return $ Set.elemAt i ks

remember :: (PrimMonad m, Ord k) => Generator m k k -> Generator m k k
remember keygen = Generator $ do
    k <- unG keygen
    modify (second $ Set.insert k)
    return k

forget :: (PrimMonad m, Ord k) => Generator m k k -> Generator m k k
forget keygen = Generator $ do
    k <- unG keygen
    modify (second $ Set.delete k)
    return k

------------------------------------------------------------------------------

data Config m op k = Config { operations :: CondensedTableV op
                            , keys :: op -> CondensedTableV (Generator m k k)
                            }

generateOperations :: (PrimMonad m, Ord k)
                   => Config m op k
                   -> Int
                   -> Generator m k [(op,k)]
generateOperations config n =
    replicateM n $ do
        op <- liftGen $ genFromTable (operations config)
        k <- join $ liftGen $ genFromTable $ (keys config) op
        return (op,k)

------------------------------------------------------------------------------

mkTable :: [(a,Double)] -> CondensedTableV a
mkTable = tableFromWeights . V.fromList