packages feed

generic-random-0.1.0.0: bench/binaryTree.hs

{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
module Main where

import Control.Applicative
import Control.Monad
import Control.Monad.Trans.Class
import Data.Bool
import Data.Data
import Data.Functor
import GHC.Generics
import Control.DeepSeq
import Criterion.Main
import Test.QuickCheck
import Test.QuickCheck.Gen
import Test.QuickCheck.Random
import Control.Exception ( evaluate )
import Data.Random.Generics
import Data.Random.Generics.Internal
import Data.Random.Generics.Internal.Types

data T = N T T | L
  deriving (Eq, Ord, Show, Data, Generic)

instance NFData T

gen1 :: Int -> Gen T
gen1 n = runRejectT (tolerance epsilon (n + 1)) gen'
  where
    gen' = incr >> lift arbitrary >>= bool (return L) (liftA2 N gen' gen')

gen2 :: Int -> Gen T
gen2 n = g
  where
    (minSize, maxSize) = tolerance epsilon (n + 1)
    g = gen' 0 (\m t -> if m < minSize then g else return t)
    gen' n k | n >= maxSize = g
    gen' n k =
      arbitrary >>= bool
        (k (n+1) L)
        (gen' (n+1) $ \m l -> gen' m $ \m r -> k m (N l r))

main = getGs >>= \gs -> defaultMain $ liftA2 (\n f -> f n gs)
  [4 ^ e | e <- [1 .. 5]]

  -- Singular rejection sampling
  [ bg "handwritten1" gen1
  , bg "handwritten2" gen2
  , bg "SR" generatorSR

  -- Sized rejection sampling
  , bg "R" generatorR'

  -- Sized rejection sampling, not memoizing oracle
  , bg' "R-recomp" generatorR'

  -- Pointed generator
  , bg "P" generatorP'

  -- Pointed generator with rejection sampling
  , bg "PR" generatorPR'

  -- Pointed generator, not memoizing oracle
  , bg' "P-recomp" generatorP'
  ]

bg, bg' :: String -> (Int -> Gen T) -> Int -> [QCGen] -> Benchmark
bg name gen n gs =
  bench (name ++ "_" ++ show n) $
    nf (fmap (\g -> unGen gg g 0)) gs
  where
    gg = gen n

bg' name gen n gs =
  bench (name ++ "_" ++ show n) $
    nf (fmap (\(n, g) -> unGen (gen n) g 0)) (fmap ((,) n) gs)

getGs :: IO [QCGen]
getGs = replicateM 100 newQCGen