{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, OverloadedStrings #-}
-- |
-- Module    : Statistics.Distribution.DiscreteUniform
-- Copyright : (c) 2016 André Szabolcs Szelp
-- License   : BSD3
--
-- Maintainer  : a.sz.szelp@gmail.com
-- Stability   : experimental
-- Portability : portable
--
-- The discrete uniform distribution. There are two parametrizations of
-- this distribution. First is the probability distribution on an
-- inclusive interval {1, ..., n}. This is parametrized with n only,
-- where p_1, ..., p_n = 1/n. ('discreteUniform').
--
-- The second parametrization is the uniform distribution on {a, ..., b} with
-- probabilities p_a, ..., p_b = 1/(a-b+1). This is parametrized with
-- /a/ and /b/. ('discreteUniformAB')

module Statistics.Distribution.DiscreteUniform
    (
      DiscreteUniform
    -- * Constructors
    , discreteUniform
    , discreteUniformAB
    -- * Accessors
    , rangeFrom
    , rangeTo
    ) where

import Control.Applicative (empty)
import Data.Aeson   (FromJSON(..), ToJSON, Value(..), (.:))
import Data.Binary  (Binary(..))
import Data.Data    (Data, Typeable)
import System.Random.Stateful (uniformRM)
import GHC.Generics (Generic)

import qualified Statistics.Distribution as D
import Statistics.Internal



-- | The discrete uniform distribution.
data DiscreteUniform = U {
      DiscreteUniform -> Int
rangeFrom  :: {-# UNPACK #-} !Int
    -- ^ /a/, the lower bound of the support {a, ..., b}
    , DiscreteUniform -> Int
rangeTo    :: {-# UNPACK #-} !Int
    -- ^ /b/, the upper bound of the support {a, ..., b}
    } deriving (DiscreteUniform -> DiscreteUniform -> Bool
(DiscreteUniform -> DiscreteUniform -> Bool)
-> (DiscreteUniform -> DiscreteUniform -> Bool)
-> Eq DiscreteUniform
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DiscreteUniform -> DiscreteUniform -> Bool
== :: DiscreteUniform -> DiscreteUniform -> Bool
$c/= :: DiscreteUniform -> DiscreteUniform -> Bool
/= :: DiscreteUniform -> DiscreteUniform -> Bool
Eq, Typeable, Typeable DiscreteUniform
Typeable DiscreteUniform =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> DiscreteUniform -> c DiscreteUniform)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c DiscreteUniform)
-> (DiscreteUniform -> Constr)
-> (DiscreteUniform -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c DiscreteUniform))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c DiscreteUniform))
-> ((forall b. Data b => b -> b)
    -> DiscreteUniform -> DiscreteUniform)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> DiscreteUniform -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> DiscreteUniform -> r)
-> (forall u.
    (forall d. Data d => d -> u) -> DiscreteUniform -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> DiscreteUniform -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> DiscreteUniform -> m DiscreteUniform)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> DiscreteUniform -> m DiscreteUniform)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> DiscreteUniform -> m DiscreteUniform)
-> Data DiscreteUniform
DiscreteUniform -> Constr
DiscreteUniform -> DataType
(forall b. Data b => b -> b) -> DiscreteUniform -> DiscreteUniform
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u.
Int -> (forall d. Data d => d -> u) -> DiscreteUniform -> u
forall u. (forall d. Data d => d -> u) -> DiscreteUniform -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> DiscreteUniform -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> DiscreteUniform -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> DiscreteUniform -> m DiscreteUniform
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> DiscreteUniform -> m DiscreteUniform
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c DiscreteUniform
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> DiscreteUniform -> c DiscreteUniform
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c DiscreteUniform)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c DiscreteUniform)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> DiscreteUniform -> c DiscreteUniform
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> DiscreteUniform -> c DiscreteUniform
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c DiscreteUniform
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c DiscreteUniform
$ctoConstr :: DiscreteUniform -> Constr
toConstr :: DiscreteUniform -> Constr
$cdataTypeOf :: DiscreteUniform -> DataType
dataTypeOf :: DiscreteUniform -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c DiscreteUniform)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c DiscreteUniform)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c DiscreteUniform)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c DiscreteUniform)
$cgmapT :: (forall b. Data b => b -> b) -> DiscreteUniform -> DiscreteUniform
gmapT :: (forall b. Data b => b -> b) -> DiscreteUniform -> DiscreteUniform
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> DiscreteUniform -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> DiscreteUniform -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> DiscreteUniform -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> DiscreteUniform -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> DiscreteUniform -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> DiscreteUniform -> [u]
$cgmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> DiscreteUniform -> u
gmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> DiscreteUniform -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> DiscreteUniform -> m DiscreteUniform
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> DiscreteUniform -> m DiscreteUniform
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> DiscreteUniform -> m DiscreteUniform
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> DiscreteUniform -> m DiscreteUniform
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> DiscreteUniform -> m DiscreteUniform
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> DiscreteUniform -> m DiscreteUniform
Data, (forall x. DiscreteUniform -> Rep DiscreteUniform x)
-> (forall x. Rep DiscreteUniform x -> DiscreteUniform)
-> Generic DiscreteUniform
forall x. Rep DiscreteUniform x -> DiscreteUniform
forall x. DiscreteUniform -> Rep DiscreteUniform x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. DiscreteUniform -> Rep DiscreteUniform x
from :: forall x. DiscreteUniform -> Rep DiscreteUniform x
$cto :: forall x. Rep DiscreteUniform x -> DiscreteUniform
to :: forall x. Rep DiscreteUniform x -> DiscreteUniform
Generic)

instance Show DiscreteUniform where
  showsPrec :: Int -> DiscreteUniform -> ShowS
showsPrec Int
i (U Int
a Int
b) = [Char] -> Int -> Int -> Int -> ShowS
forall a b. (Show a, Show b) => [Char] -> a -> b -> Int -> ShowS
defaultShow2 [Char]
"discreteUniformAB" Int
a Int
b Int
i
instance Read DiscreteUniform where
  readPrec :: ReadPrec DiscreteUniform
readPrec = [Char]
-> (Int -> Int -> Maybe DiscreteUniform)
-> ReadPrec DiscreteUniform
forall a b r.
(Read a, Read b) =>
[Char] -> (a -> b -> Maybe r) -> ReadPrec r
defaultReadPrecM2 [Char]
"discreteUniformAB" (\Int
a Int
b -> DiscreteUniform -> Maybe DiscreteUniform
forall a. a -> Maybe a
Just (Int -> Int -> DiscreteUniform
discreteUniformAB Int
a Int
b))

instance ToJSON   DiscreteUniform
instance FromJSON DiscreteUniform where
  parseJSON :: Value -> Parser DiscreteUniform
parseJSON (Object Object
v) = do
    Int
a <- Object
v Object -> Key -> Parser Int
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"uniformA"
    Int
b <- Object
v Object -> Key -> Parser Int
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"uniformB"
    DiscreteUniform -> Parser DiscreteUniform
forall a. a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return (DiscreteUniform -> Parser DiscreteUniform)
-> DiscreteUniform -> Parser DiscreteUniform
forall a b. (a -> b) -> a -> b
$ Int -> Int -> DiscreteUniform
discreteUniformAB Int
a Int
b
  parseJSON Value
_ = Parser DiscreteUniform
forall a. Parser a
forall (f :: * -> *) a. Alternative f => f a
empty

instance Binary DiscreteUniform where
  put :: DiscreteUniform -> Put
put (U Int
a Int
b) = Int -> Put
forall t. Binary t => t -> Put
put Int
a Put -> Put -> Put
forall a b. PutM a -> PutM b -> PutM b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> Put
forall t. Binary t => t -> Put
put Int
b
  get :: Get DiscreteUniform
get         = Int -> Int -> DiscreteUniform
discreteUniformAB (Int -> Int -> DiscreteUniform)
-> Get Int -> Get (Int -> DiscreteUniform)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get Int
forall t. Binary t => Get t
get Get (Int -> DiscreteUniform) -> Get Int -> Get DiscreteUniform
forall a b. Get (a -> b) -> Get a -> Get b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get Int
forall t. Binary t => Get t
get

instance D.Distribution DiscreteUniform where
  cumulative :: DiscreteUniform -> Double -> Double
cumulative (U Int
a Int
b) Double
x
    | Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
a = Double
0
    | Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
b = Double
1
    | Bool
otherwise = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor Double
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
b Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)

instance D.DiscreteDistr DiscreteUniform where
  probability :: DiscreteUniform -> Int -> Double
probability (U Int
a Int
b) Int
k
    | Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
a Bool -> Bool -> Bool
&& Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
b = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
b Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
    | Bool
otherwise        = Double
0

instance D.Mean DiscreteUniform where
  mean :: DiscreteUniform -> Double
mean (U Int
a Int
b) = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
aInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
b)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2

instance D.Variance DiscreteUniform where
  variance :: DiscreteUniform -> Double
variance (U Int
a Int
b) = (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
b Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)Double -> Int -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^(Int
2::Int) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
12

instance D.MaybeMean DiscreteUniform where
  maybeMean :: DiscreteUniform -> Maybe Double
maybeMean = Double -> Maybe Double
forall a. a -> Maybe a
Just (Double -> Maybe Double)
-> (DiscreteUniform -> Double) -> DiscreteUniform -> Maybe Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DiscreteUniform -> Double
forall d. Mean d => d -> Double
D.mean

instance D.MaybeVariance DiscreteUniform where
  maybeStdDev :: DiscreteUniform -> Maybe Double
maybeStdDev   = Double -> Maybe Double
forall a. a -> Maybe a
Just (Double -> Maybe Double)
-> (DiscreteUniform -> Double) -> DiscreteUniform -> Maybe Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DiscreteUniform -> Double
forall d. Variance d => d -> Double
D.stdDev
  maybeVariance :: DiscreteUniform -> Maybe Double
maybeVariance = Double -> Maybe Double
forall a. a -> Maybe a
Just (Double -> Maybe Double)
-> (DiscreteUniform -> Double) -> DiscreteUniform -> Maybe Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DiscreteUniform -> Double
forall d. Variance d => d -> Double
D.variance

instance D.Entropy DiscreteUniform where
  entropy :: DiscreteUniform -> Double
entropy (U Int
a Int
b) = Double -> Double
forall a. Floating a => a -> a
log (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Double) -> Int -> Double
forall a b. (a -> b) -> a -> b
$ Int
b Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1

instance D.MaybeEntropy DiscreteUniform where
  maybeEntropy :: DiscreteUniform -> Maybe Double
maybeEntropy = Double -> Maybe Double
forall a. a -> Maybe a
Just (Double -> Maybe Double)
-> (DiscreteUniform -> Double) -> DiscreteUniform -> Maybe Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DiscreteUniform -> Double
forall d. Entropy d => d -> Double
D.entropy

instance D.ContGen DiscreteUniform where
  genContVar :: forall g (m :: * -> *).
StatefulGen g m =>
DiscreteUniform -> g -> m Double
genContVar DiscreteUniform
d = (Int -> Double) -> m Int -> m Double
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (m Int -> m Double) -> (g -> m Int) -> g -> m Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DiscreteUniform -> g -> m Int
forall d g (m :: * -> *).
(DiscreteGen d, StatefulGen g m) =>
d -> g -> m Int
forall g (m :: * -> *).
StatefulGen g m =>
DiscreteUniform -> g -> m Int
D.genDiscreteVar DiscreteUniform
d

instance D.DiscreteGen DiscreteUniform where
  genDiscreteVar :: forall g (m :: * -> *).
StatefulGen g m =>
DiscreteUniform -> g -> m Int
genDiscreteVar (U Int
a Int
b) = (Int, Int) -> g -> m Int
forall a g (m :: * -> *).
(UniformRange a, StatefulGen g m) =>
(a, a) -> g -> m a
forall g (m :: * -> *). StatefulGen g m => (Int, Int) -> g -> m Int
uniformRM (Int
a,Int
b)

-- | Construct discrete uniform distribution on support {1, ..., n}.
--   Range /n/ must be >0.
discreteUniform :: Int             -- ^ Range
                -> DiscreteUniform
discreteUniform :: Int -> DiscreteUniform
discreteUniform Int
n
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1     = [Char] -> DiscreteUniform
forall a. HasCallStack => [Char] -> a
error ([Char] -> DiscreteUniform) -> [Char] -> DiscreteUniform
forall a b. (a -> b) -> a -> b
$ [Char]
msg [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char]
"range must be > 0. Got " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
n
  | Bool
otherwise = Int -> Int -> DiscreteUniform
U Int
1 Int
n
  where msg :: [Char]
msg = [Char]
"Statistics.Distribution.DiscreteUniform.discreteUniform: "

-- | Construct discrete uniform distribution on support {a, ..., b}.
discreteUniformAB :: Int             -- ^ Lower boundary (inclusive)
                  -> Int             -- ^ Upper boundary (inclusive)
                  -> DiscreteUniform
discreteUniformAB :: Int -> Int -> DiscreteUniform
discreteUniformAB Int
a Int
b
  | Int
b Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
a     = Int -> Int -> DiscreteUniform
U Int
b Int
a
  | Bool
otherwise = Int -> Int -> DiscreteUniform
U Int
a Int
b