splitmix-distributions 0.3.0.0 → 0.4.0.0
raw patch · 3 files changed
+80/−7 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ System.Random.SplitMix.Distributions: categorical :: (Monad m, Foldable t) => t Double -> GenT m (Maybe Int)
+ System.Random.SplitMix.Distributions: discrete :: (Monad m, Foldable t) => t (Double, b) -> GenT m (Maybe b)
+ System.Random.SplitMix.Distributions: samples :: Int -> Word64 -> Gen a -> [a]
+ System.Random.SplitMix.Distributions: samplesT :: Monad m => Int -> Word64 -> GenT m a -> m [a]
+ System.Random.SplitMix.Distributions: zipf :: (Monad m, Integral i) => Double -> GenT m i
Files
- ChangeLog.md +4/−0
- splitmix-distributions.cabal +1/−1
- src/System/Random/SplitMix/Distributions.hs +75/−6
ChangeLog.md view
@@ -1,3 +1,7 @@+0.4 :++- add Discrete, Categorical, Zipf-Mandelbrot distributions+ 0.3 : - type signatures of all generators are now parametrized over some Monad m rather than Identity. This allows for more flexibility on the use site.
splitmix-distributions.cabal view
@@ -1,5 +1,5 @@ name: splitmix-distributions-version: 0.3.0.0+version: 0.4.0.0 description: Random samplers for some common distributions, as well as a convenient interface for composing them, based on splitmix. Please see the README on GitHub at <https://github.com/ocramz/splitmix-distributions#readme> homepage: https://github.com/ocramz/splitmix-distributions#readme bug-reports: https://github.com/ocramz/splitmix-distributions/issues
src/System/Random/SplitMix/Distributions.hs view
@@ -45,11 +45,14 @@ -- ** Discrete bernoulli, fairCoin, multinomial,+ categorical,+ discrete,+ zipf, -- * PRNG -- ** Pure- Gen, sample,+ Gen, sample, samples, -- ** Monadic- GenT, sampleT,+ GenT, sampleT, samplesT, withGen ) where @@ -80,18 +83,33 @@ -- | Pure random generation type Gen = GenT Identity --- | Monadic evaluation+-- | Sample in a monadic context sampleT :: Monad m =>- Word64 -- ^ random seed- -> GenT m a -> m a+ Word64 -- ^ random seed+ -> GenT m a+ -> m a sampleT seed gg = evalStateT (unGen gg) (mkSMGen seed) --- | Pure evaluation+-- | Sample a batch+samplesT :: Monad m =>+ Int -- ^ size of sample+ -> Word64 -- ^ random seed+ -> GenT m a+ -> m [a]+samplesT n seed gg = sampleT seed (replicateM n gg)++-- | Pure sampling sample :: Word64 -- ^ random seed -> Gen a -> a sample seed gg = evalState (unGen gg) (mkSMGen seed) +-- | Sample a batch+samples :: Int -- ^ sample size+ -> Word64 -- ^ random seed+ -> Gen a+ -> [a]+samples n seed gg = sample seed (replicateM n gg) -- | Bernoulli trial bernoulli :: Monad m =>@@ -123,6 +141,57 @@ runningTotals xs = let adds = scanl1 (+) xs in (adds, sum xs) {-# INLINABLE multinomial #-} ++-- | Categorical distribution+--+-- Picks one index out of a discrete set with probability proportional to those supplied as input parameter vector+categorical :: (Monad m, Foldable t) =>+ t Double -- ^ probability vector \( p_i \gt 0 , \forall i \) (does not need to be normalized)+ -> GenT m (Maybe Int)+categorical ps = do+ xs <- multinomial 1 ps+ case xs of+ Just [x] -> pure $ Just x+ _ -> pure Nothing+++-- | The Zipf-Mandelbrot distribution.+--+-- Note that values of the parameter close to 1 are very computationally intensive.+--+-- >>> samples 10 1234 (zipf 1.1)+-- [3170051793,2,668775891,146169301649651,23,36,5,6586194257347,21,37911]+--+-- >>> samples 10 1234 (zipf 1.5)+-- [79,1,58,680,3,1,2,1,366,1]+zipf :: (Monad m, Integral i) =>+ Double -- ^ \( \alpha \gt 1 \)+ -> GenT m i+zipf a = do+ let+ b = 2 ** (a - 1)+ go = do+ u <- stdUniform+ v <- stdUniform+ let xInt = floor (u ** (- 1 / (a - 1)))+ x = fromIntegral xInt+ t = (1 + 1 / x) ** (a - 1)+ if v * x * (t - 1) / (b - 1) <= t / b+ then return xInt+ else go+ go+{-# INLINABLE zipf #-}++-- | Discrete distribution+--+-- Pick one item with probability proportional to those supplied as input parameter vector+discrete :: (Monad m, Foldable t) =>+ t (Double, b) -- ^ (probability, item) vector \( p_i \gt 0 , \forall i \) (does not need to be normalized)+ -> GenT m (Maybe b)+discrete d = do+ let (ps, xs) = unzip (toList d)+ midx <- categorical ps+ pure $ (xs !!) <$> midx -- | Uniform between two values uniformR :: Monad m =>