packages feed

random-extras 0.16 → 0.17

raw patch · 4 files changed

+91/−12 lines, 4 files

Files

+ Data/Random/Distribution/Uniform/Exclusive.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE FlexibleContexts #-}++{- |+Module       : Data.Random.Extras+Copyright    : 2010 Aristid Breitkreuz+License      : BSD3+Stability    : experimental+Portability  : portable++An uniform distribution that excludes the first parameter.+-}++module Data.Random.Distribution.Uniform.Exclusive+(+  Excludable(..)+, uniformExclusiveDist+, uniformExclusive+)+where+  +import Data.Random.RVar+import Data.Random.Distribution+import Data.Random.Distribution.Uniform+import Data.Random.Internal.Fixed+import Data.Int+import Data.Word+import Data.Fixed++-- | A class for excluding discrete values. No change for floating point+-- values.+-- +-- /Note:/ 'Uniform' is exclusive on the second argument for floating point+--         values, so 'Excludable' does not need to exclude anything for them.+class Excludable a where+    smaller :: a -> a+    bigger :: a -> a++-- | A uniform distribution that excludes the first parameter+-- , but includes the second.+-- +-- /Note:/ 'Uniform' behaves the opposite way for floating point values.+uniformExclusiveDist :: (Excludable a, Ord a) => a -> a -> Uniform a+uniformExclusiveDist a b | c == EQ   = error "Invalid exclusive uniform distribution"+                         | c == LT   = Uniform b (bigger a)+                         | otherwise = Uniform (smaller a) b+    where c = compare a b++-- | A uniformly distributed random value that excludes the first parameter.+uniformExclusive :: (Distribution Uniform a, Excludable a, Ord a) => a -> a -> RVar a+uniformExclusive a b = rvar $ uniformExclusiveDist a b++instance Excludable Int where { smaller = pred; bigger = succ }+instance Excludable Int8 where { smaller = pred; bigger = succ }+instance Excludable Int16 where { smaller = pred; bigger = succ }+instance Excludable Int32 where { smaller = pred; bigger = succ }+instance Excludable Int64 where { smaller = pred; bigger = succ }+instance Excludable Word where { smaller = pred; bigger = succ }+instance Excludable Word8 where { smaller = pred; bigger = succ }+instance Excludable Word16 where { smaller = pred; bigger = succ }+instance Excludable Word32 where { smaller = pred; bigger = succ }+instance Excludable Word64 where { smaller = pred; bigger = succ }+instance Excludable Integer where { smaller = pred; bigger = succ }++instance Excludable Float where { smaller = id; bigger = id }+instance Excludable Double where { smaller = id; bigger = id }++instance Excludable Bool where { smaller = not; bigger = not }++instance HasResolution r => Excludable (Fixed r) where+    smaller = mkFixed . pred . unMkFixed+    bigger = mkFixed . succ . unMkFixed
Data/Random/Shuffle/Weighted.hs view
@@ -50,37 +50,42 @@ import Data.Random.RVar import Data.Random.Distribution import Data.Random.Distribution.Uniform+import Data.Random.Distribution.Uniform.Exclusive import qualified Data.Map as M  moduleError :: String -> String -> a moduleError n s = error $ "Data.Random.Shuffle.Weighted." ++ n ++ ": " ++ s  -- | Randomly shuffle a CDF map according to its weights.-weightedShuffleCDF :: (Num w, Ord w, Distribution Uniform w) => M.Map w a -> RVar [a]+weightedShuffleCDF :: (Num w, Ord w, Distribution Uniform w, Excludable w) => M.Map w a -> RVar [a] weightedShuffleCDF m | M.null m  = return []                      | otherwise = weightedChoiceExtractCDF m >>= \(m', a) -> (a:) <$> weightedShuffleCDF m'  -- | Randomly shuffle a weighted list according to its weights.-weightedShuffle :: (Num w, Ord w, Distribution Uniform w) => [(w, a)] -> RVar [a]+weightedShuffle :: (Num w, Ord w, Distribution Uniform w, Excludable w) => [(w, a)] -> RVar [a] weightedShuffle = weightedShuffleCDF . cdfMapFromList  -- | Randomly draw /n/ elements from a CDF map according to its weights.-weightedSampleCDF :: (Num w, Ord w, Distribution Uniform w) => Int -> M.Map w a -> RVar [a]+weightedSampleCDF :: (Num w, Ord w, Distribution Uniform w, Excludable w) => Int -> M.Map w a -> RVar [a] weightedSampleCDF n m | M.null m || n <= 0 = return []                       | otherwise          = weightedChoiceExtractCDF m >>= \(m', a) -> (a:) <$> weightedSampleCDF (n - 1) m'  -- | Randomly draw /n/ elements from a weighted list according to its weights.-weightedSample :: (Num w, Ord w, Distribution Uniform w) => Int -> [(w, a)] -> RVar [a]+weightedSample :: (Num w, Ord w, Distribution Uniform w, Excludable w) => Int -> [(w, a)] -> RVar [a] weightedSample n = weightedSampleCDF n . cdfMapFromList  -- | Randomly extract an element from a CDF map according to its weights. The -- element is removed and the resulting "weight gap" closed.-weightedChoiceExtractCDF :: (Num w, Ord w, Distribution Uniform w) => M.Map w a -> RVar (M.Map w a, a)-weightedChoiceExtractCDF m | M.null m  = moduleError "weightedChoiceExtractCDF" "empty map"-                           | otherwise = extract <$> uniform 0 wmax-    where Just ((wmax, _), _) = M.maxViewWithKey m+weightedChoiceExtractCDF :: (Num w, Ord w, Distribution Uniform w, Excludable w) => M.Map w a -> RVar (M.Map w a, a)+weightedChoiceExtractCDF m | M.null m         = moduleError "weightedChoiceExtractCDF" "empty map"+                           | M.null exceptMax = return (exceptMax, maxE)+                           | otherwise        = extract <$> uniformExclusive 0 wmax+    where Just ((wmax, maxE), exceptMax) = M.maxViewWithKey m           extract w = (a `M.union` M.mapKeysMonotonic (subtract gap) c, b)-              where (a, r) = M.split w m+              where (a, e, r') = M.splitLookup w m+                    r = case e of+                          Nothing -> r'+                          Just ex -> M.insert w ex r'                     Just ((k, b), c) = M.minViewWithKey r                     gap = case M.minViewWithKey c of                             Nothing -> 0@@ -88,4 +93,6 @@  -- | Generate a CDF map from a weighted list. cdfMapFromList :: Num w => [(w, a)] -> M.Map w a-cdfMapFromList = M.fromAscList . scanl1 (\(w1, _) (w2, x) -> (w1 + w2, x))+cdfMapFromList = M.fromAscListWith (const id) +                 . scanl1 (\(w1, _) (w2, x) -> (w1 + w2, x)) +                 . dropWhile ((==0) . fst)
README view
@@ -1,4 +1,4 @@-Random-extras 0.16+Random-extras 0.17 ------------------  This package contains additional monadic functions for random values.
random-extras.cabal view
@@ -1,7 +1,7 @@ Name:                random-extras  -- http://www.haskell.org/haskellwiki/Package_versioning_policy-Version:             0.16+Version:             0.17 Synopsis:            Additional functions for random values. Description:         Additional functions for random values, based on random-fu. Inspired by random-shuffle. Homepage:            http://github.com/aristidb/random-extras@@ -17,6 +17,7 @@  Library   Exposed-modules:+        Data.Random.Distribution.Uniform.Exclusive,         Data.Random.Dovetail,         Data.Random.Extras,         Data.Random.Shuffle.Weighted