packages feed

random-variates 0.1.1.0 → 0.1.3.0

raw patch · 7 files changed

+224/−74 lines, 7 filesdep +binarydep +bytestringdep ~basenew-component:exe:GenPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: binary, bytestring

Dependency ranges changed: base

API changes (from Hackage documentation)

- Stochastic.Distributions.Continuous: instance Stochastic.Generator.Generator Stochastic.Distributions.Continuous.Dist
- Stochastic.Distributions.Continuous: instance Stochastic.Generator.Generator Stochastic.Distributions.UniformBase
- Stochastic.Distributions.Discrete: instance Stochastic.Generator.Generator Stochastic.Distributions.Discrete.Dist
- Stochastic.Generator: class Generator g where type family From g nextN 0 = state $ \ g0 -> ([], g0) nextN n = do { x <- nextG; xs <- nextN (n - 1); return (x : xs) }
- Stochastic.Generator: foldWhile :: Generator g => (From g -> a -> a) -> a -> (a -> Bool) -> State g [From g]
- Stochastic.Generator: instance Stochastic.Generator.Generator [a]
- Stochastic.Generator: nextG :: Generator g => State g (From g)
- Stochastic.Generator: nextN :: Generator g => Int -> State g [(From g)]
- Stochastic.Generator: while :: Generator g => ((From g) -> Bool) -> State g [From g]
+ Stochastic.Distributions: seededBase :: IO UniformBase
+ Stochastic.Generator: IOGen :: (g -> (a, g)) -> (MVar g) -> IOGen g a
+ Stochastic.Generator: data IOGen g a
+ Stochastic.Generator: dropGen :: (g -> (a, g)) -> Integer -> g -> g
+ Stochastic.Generator: dropIO :: IOGen g a -> Integer -> IO ()
+ Stochastic.Generator: foldGenWhile :: (g -> (a, g)) -> (b -> a -> b) -> b -> (b -> Bool) -> (g -> ([a], g))
+ Stochastic.Generator: genTake :: (g -> (a, g)) -> Integer -> (g -> ([a], g))
+ Stochastic.Generator: genWhile :: (g -> (a, g)) -> (a -> Bool) -> (g -> ([a], g))
+ Stochastic.Generator: liftGen :: (g -> (a, g)) -> g -> IO (IOGen g a)
+ Stochastic.Generator: nextIO :: IOGen g a -> IO a
+ Stochastic.Generator: type Gen g a = g -> (a, g)
+ Stochastic.Uniform: class RandomGen g
+ Stochastic.Uniform: data UniformRandom
+ Stochastic.Uniform: genRange :: RandomGen g => g -> (Int, Int)
+ Stochastic.Uniform: instance GHC.Classes.Eq Stochastic.Uniform.EntropyExhausted
+ Stochastic.Uniform: instance GHC.Exception.Exception Stochastic.Uniform.EntropyExhausted
+ Stochastic.Uniform: instance GHC.Show.Show Stochastic.Uniform.EntropyExhausted
+ Stochastic.Uniform: instance System.Random.RandomGen Stochastic.Uniform.UniformRandom
+ Stochastic.Uniform: nWayAllocate :: Integer -> Integer -> UniformRandom -> ([UniformRandom], UniformRandom)
+ Stochastic.Uniform: next :: RandomGen g => g -> (Int, g)
+ Stochastic.Uniform: split :: RandomGen g => g -> (g, g)
+ Stochastic.Uniform: splitAllocate :: Integer -> UniformRandom -> (UniformRandom, UniformRandom)
+ Stochastic.Uniform: xorshift128plus :: Integer -> UniformRandom
- Stochastic.Distributions: stdBase :: Int -> UniformBase
+ Stochastic.Distributions: stdBase :: Integer -> UniformBase

Files

random-variates.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                random-variates-version:             0.1.1.0+version:             0.1.3.0 synopsis:            "Uniform RNG => Non-Uniform RNGs" description:         "Collection of transforms uniform random number generators (RNGs) into any of a dozen common RNGs. Each presenting several common interfaces. Additionally Empirical distributions can be sampled from and tested (chi-squared) against theoretical distributions."    license:             MIT@@ -23,6 +23,7 @@ library   exposed-modules:                   Stochastic.Generator+                  Stochastic.Uniform                   Stochastic.Distribution.Continuous                   Stochastic.Distribution.Discrete                   Stochastic.Distributions@@ -33,16 +34,25 @@    other-modules:    build-depends:       -                         base >=4.6 && <5.0-                       , containers >= 0.5.7.0-                       , lens >=4.13-                       , random >=1.1-                       , reinterpret-cast >= 0.1.0-                       , mtl >= 2.2-                       , erf >= 2.0+                       base >=4.6 && <5.0+                     , containers >= 0.5.7.0+                     , lens >=4.13+                     , random >=1.1+                     , reinterpret-cast >= 0.1.0+                     , mtl >= 2.2+                     , erf >= 2.0+                     , bytestring >= 0.10+                     ,  binary    hs-source-dirs:      src   default-language:    Haskell2010+  default-extensions: DeriveGeneric,  DeriveDataTypeable +Executable Gen+  main-is: tests/gen.hs+  build-depends:       base+                     , random-variates >=0.1+  default-language:    Haskell2010+ Test-Suite vis   type:                exitcode-stdio-1.0   main-is:             tests/vis.hs@@ -60,4 +70,4 @@                      , random-variates >=0.1   default-language:    Haskell2010 -  +   
src/Stochastic/Distributions.hs view
@@ -2,28 +2,52 @@ module Stochastic.Distributions(   UniformBase(rDouble)   ,stdBase+  ,seededBase   ,Empirical(..)   ,mkEmpirical   ) where +import Stochastic.Uniform+import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Lazy as LBS+ import System.Random import Control.Monad.State.Lazy import Stochastic.Tools+import System.IO+import Data.Word+import Data.Binary.Get  data UniformBase = UniformBase {   rDouble :: (Double, UniformBase) }  -stdGen2Uni gen = UniformBase {-  rDouble = mapTuple-            (id)-            (stdGen2Uni)-            (randomR (0,1) gen)+readWord64 :: Handle -> IO Word64+readWord64 h = do+  w1 <- hGetChar h+  w2 <- hGetChar h+  w3 <- hGetChar h+  w4 <- hGetChar h+  w5 <- hGetChar h+  w6 <- hGetChar h+  w7 <- hGetChar h+  w8 <- hGetChar h+  let words = [w1,w2,w3,w4,w5,w6,w7,w8] :: String+  return $ runGet getWord64host $ LBS.fromStrict $ B.pack words++mk g = UniformBase {+  rDouble = mapTuple (id) (mk) (random g)   } -stdBase s = stdGen2Uni (mkStdGen s)+stdBase :: Integer -> UniformBase+stdBase s = mk $ xorshift128plus s +seededBase :: IO UniformBase+seededBase = do+  word <- withBinaryFile "/dev/random/" ReadMode (readWord64)+  let seed = toInteger word+  return $ stdBase seed  data Empirical = Empirical {   degreesOfFreedom :: Int,
src/Stochastic/Distributions/Continuous.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeFamilies #-} module Stochastic.Distributions.Continuous(   mkUniform   ,mkExp@@ -25,15 +23,6 @@   cdf  _ x = x   cdf' _ p = p   degreesOfFreedom _ = 0---instance Generator Dist where-  type (From Dist) = Double-  nextG = state $ \ g0 -> rand g0--instance Generator UniformBase where-  type (From UniformBase) = Double-  nextG = state $ \ g0 -> rDouble g0   data Dist =
src/Stochastic/Distributions/Discrete.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE TypeFamilies #-} module Stochastic.Distributions.Discrete(   mkBinomial   ,mkBernoulli@@ -12,15 +11,11 @@ import Data.Maybe import Control.Monad.State.Lazy import Stochastic.Tools-import Stochastic.Generator(Generator(..), foldWhile)+import Stochastic.Generator(foldGenWhile) import Stochastic.Distributions import Stochastic.Distribution.Discrete import qualified Stochastic.Distributions.Continuous as C -instance Generator Dist where-  type (From Dist) = Int-  nextG = state $ \ g0 -> rand g0- data Dist =   Uniform Int Int UniformBase   | Poisson C.Dist@@ -96,7 +91,7 @@     mapTuple     (\x -> length x)     (Poisson)-    (runState (foldWhile (+) 0.0 (<1.0)) g0)+    ((foldGenWhile (C.rand) (+) 0.0 (<1.0)) g0)   rand (Bernoulli p g0) =     mapTuple     (\x -> if (x >= p) then 1 else 0)@@ -132,12 +127,12 @@   cdf (Uniform a b _) x = toDbl (x-a) / toDbl (b-a)    cdf' g@(Poisson (C.Exponential y _)) x =-    sum . fst $ runState (fold) [1..]+    (sum . fst) (fold [1..])     where-      reduce :: Int -> Double -> Double-      reduce = (\y p -> (pmf g y) + p)-      fold :: State [Int] [From [Int]]-      fold = foldWhile (reduce) 0 (<x)+      reduce :: Double -> Int -> Double+      reduce = (\p y -> (pmf g y) + p)+      fold :: [Int] -> ([Int], [Int])+      fold = foldGenWhile (myUncons) (reduce) 0 (<x)   cdf' (Geometric p _) x =     ceiling $ (log (1-x)) / (log (1-p))   cdf' (Bernoulli p _) x@@ -166,6 +161,9 @@       (_, r, _) = head $ filter (\(w,_,_) -> (w==k)) cache   pmf (Uniform a b _) x = toDbl x/toDbl (b-a) ++myUncons :: [a] -> (a, [a])+myUncons (x:xs) = (x, xs)  toDbl = fromInteger . toInteger 
src/Stochastic/Generator.hs view
@@ -1,45 +1,61 @@-{-# LANGUAGE TypeFamilies #-} module Stochastic.Generator where-+import Control.Concurrent.MVar import Control.Monad.State.Lazy -class Generator g where-  type From g-  nextG   :: State g (From g)-  nextN  :: Int -> State g [(From g)]-  nextN 0 = state $ \g0 -> ([], g0)-  nextN n =-    do-      x  <- nextG-      xs <- nextN (n-1)-      return (x:xs)+type Gen g a = (g -> (a,g))+data IOGen g a = IOGen (g -> (a, g)) (MVar g) -instance Generator [a] where-  type From [a] = a-  nextG = state $ \ g0 -> (head g0, tail g0)+liftGen :: (g -> (a, g)) -> g -> IO (IOGen g a)+liftGen f g = do+  var <- newMVar g+  return $ IOGen f var -foldWhile :: Generator g-         => (From g -> a -> a)-         -> a-         -> (a -> Bool)-         -> State g [From g]-foldWhile f z p =-  do-   x  <- nextG-   let y = f x z-   xs <- if (p y)-         then foldWhile f y p -         else return []-   return (x:xs)+nextIO :: IOGen g a -> IO a+nextIO (IOGen f var) = do+  val <- takeMVar var+  let (x, g') = f val+  putMVar var g'+  return x -while :: Generator g => ((From g) -> Bool) -> State g [From g]-while p =-  do-   x  <- nextG-   xs <- if (p x)-         then while p-         else return []-   return (x:xs)+foldGenWhile :: (g -> (a,g))+          -> (b -> a -> b)+          -> b+          -> (b -> Bool)+          -> (g -> ([a], g))+foldGenWhile nxt f zz p = h zz+  where+    h z g0 +      | not (p z) = ([], g0)+      | otherwise = (x:xs, g2)+      where+        (xs, g2) = h (f z x) g1+        (x, g1)  = nxt g0 +genWhile :: (g -> (a, g)) -> (a -> Bool) -> (g -> ([a], g))+genWhile nxt p = h+  where+    h g0 = let (x, g1) = nxt g0 in+            let (xs, g2) = h g1 in+            if (p x) then (x:xs, g2) else ([], g1) +genTake :: (g -> (a,g)) -> Integer -> (g -> ([a], g))+genTake f 0 g0 = ([], g0)+genTake f n g0 = ((x:xs), g2)+  where+    (x, g1) = f g0+    (xs, g2) = genTake f (n-1) g1++dropGen :: (g -> (a,g)) -> Integer -> g -> g+dropGen f = d+  where+    d 0 g0 = g0+    d n g0 = d (n-1) $! (snd $ f g0)++++dropIO :: IOGen g a -> Integer -> IO ()+dropIO _ 0 = return ()+dropIO ioG n = do+  nextIO ioG+  dropIO ioG (n-1) 
+ src/Stochastic/Uniform.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE BangPatterns #-}+module Stochastic.Uniform(xorshift128plus,+                          UniformRandom,+                          nWayAllocate,+                          splitAllocate,+                          RandomGen(..)) where++import Stochastic.Generator+import Data.Word+import Data.Bits+import Data.Typeable+import Control.Exception(throw, Exception)+import System.Random(RandomGen(..))++data UniformRandom = XorShift128Plus Word64 Word64 Integer++data EntropyExhausted = EntropyExhausted+                      deriving(Eq, Typeable)++instance Exception EntropyExhausted where+instance Show EntropyExhausted where+  show e = "EntropyExhausted"++{- |+For information on the performance of the xorshift-128-plus PRNG, please see: <http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf Vigna et al.>+-}+xorshift128plus :: Integer -> UniformRandom+xorshift128plus seed = XorShift128Plus high low entropy+  where+    high = fromInteger seed+    low = fromInteger seed+    entropy = (2^127)++nWayAllocate :: Integer -> Integer -> UniformRandom -> ([UniformRandom], UniformRandom)+nWayAllocate _ 0 g0 = ([], g0)+nWayAllocate size n g0 = ((g1:gs), g3)+  where+    !(gs,g3) = nWayAllocate size (n-1) g2+    !(g1,g2) = splitAllocate size g0++splitAllocate :: Integer -> UniformRandom -> (UniformRandom, UniformRandom)+splitAllocate count g@(XorShift128Plus high low entropy) =+    ((XorShift128Plus high low count), g')+    where+      !g' = step (next) (count) g+++instance RandomGen UniformRandom where+  next (XorShift128Plus high low entropy) +    | entropy == 0 = throw EntropyExhausted+    | otherwise    = final +    where+      -- eagerly evaluate this function, retain no intermediaries or we might blow the stack+      final    = (ret, XorShift128Plus high' low' entropy')+      !ret     = fromInteger $ toInteger $ high' + high+      x        = low `xor` (low `shift` 23)+      high'    = x `xor` high `xor` (x `shift` (-17)) `xor` (high `shift` (-26))+      low'     = high+      entropy' = entropy - 1+  split g@(XorShift128Plus high low entropy) =+    ((XorShift128Plus high low entropy'), g')+    where+      !entropy' = (2^32)+      !g' = step (next) (entropy') g++step :: (g -> (a,g)) -> Integer -> g -> g+step f 0 g'' = g''+step f n g'' = step (f) (n-1) $! (snd $ f g'')+
+ tests/gen.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE BangPatterns #-}+module Main where++import Stochastic.Generator+import Stochastic.Uniform+import Stochastic.Distributions+import System.Environment+import System.IO+import Data.IORef++main :: IO ()+main = do+  [count] <- getArgs+  let n  = read count :: Integer+  let g  = xorshift128plus 42+  let g' = dropGen (next) n g+  iog <- liftGen (next) g'+  x <- nextIO iog+  putStrLn (show x)+--  ref <- newIORef g+--  invert $ step n (f ref)+  return ()+++myUncons (x:xs) = (x, xs)++step :: Integer -> IO Int -> [IO Int]+step 0 _  = []+step n io = (io:(step (n-1) io))++invert :: [IO a] -> IO [a]+invert [] = return []+invert (io:ios) = do+  x <- io+  xs <- invert ios+  return (x:xs)++f :: IORef UniformRandom -> IO Int+f ref = do+  g <- readIORef ref+  let (x, g') = next g+  writeIORef ref g'+  return x+