{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}
module Statistics.Distribution
    (
      
      Distribution(..)
    , DiscreteDistr(..)
    , ContDistr(..)
      
    , MaybeMean(..)
    , Mean(..)
    , MaybeVariance(..)
    , Variance(..)
    , MaybeEntropy(..)
    , Entropy(..)
    , FromSample(..)
      
    , ContGen(..)
    , DiscreteGen(..)
    , genContinuous
      
    , findRoot
    , sumProbabilities
    ) where
import Prelude hiding (sum)
import Statistics.Function        (square)
import Statistics.Sample.Internal (sum)
import System.Random.Stateful     (StatefulGen, uniformDouble01M)
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Generic as G
class Distribution d where
    
    
    
    
    
    
    
    cumulative :: d -> Double -> Double
    cumulative d
d Double
x = Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- d -> Double -> Double
forall d. Distribution d => d -> Double -> Double
complCumulative d
d Double
x
    
    
    
    
    
    
    
    
    complCumulative :: d -> Double -> Double
    complCumulative d
d Double
x = Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- d -> Double -> Double
forall d. Distribution d => d -> Double -> Double
cumulative d
d Double
x
    {-# MINIMAL (cumulative | complCumulative) #-}
class Distribution  d => DiscreteDistr d where
    
    probability :: d -> Int -> Double
    probability d
d = Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double) -> (Int -> Double) -> Int -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. d -> Int -> Double
forall d. DiscreteDistr d => d -> Int -> Double
logProbability d
d
    
    logProbability :: d -> Int -> Double
    logProbability d
d = Double -> Double
forall a. Floating a => a -> a
log (Double -> Double) -> (Int -> Double) -> Int -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. d -> Int -> Double
forall d. DiscreteDistr d => d -> Int -> Double
probability d
d
    {-# MINIMAL (probability | logProbability) #-}
class Distribution d => ContDistr d where
    
    
    
    density :: d -> Double -> Double
    density d
d = Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double) -> (Double -> Double) -> Double -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. d -> Double -> Double
forall d. ContDistr d => d -> Double -> Double
logDensity d
d
    
    logDensity :: d -> Double -> Double
    logDensity d
d = Double -> Double
forall a. Floating a => a -> a
log (Double -> Double) -> (Double -> Double) -> Double -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. d -> Double -> Double
forall d. ContDistr d => d -> Double -> Double
density d
d
    
    
    
    quantile :: d -> Double -> Double
    quantile d
d Double
x = d -> Double -> Double
forall d. ContDistr d => d -> Double -> Double
complQuantile d
d (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
x)
    
    
    
    complQuantile :: d -> Double -> Double
    complQuantile d
d Double
x = d -> Double -> Double
forall d. ContDistr d => d -> Double -> Double
quantile d
d (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
x)
    {-# MINIMAL (density | logDensity), (quantile | complQuantile) #-}
class Distribution d => MaybeMean d where
    maybeMean :: d -> Maybe Double
class MaybeMean d => Mean d where
    mean :: d -> Double
class MaybeMean d => MaybeVariance d where
    maybeVariance :: d -> Maybe Double
    maybeVariance = (Double -> Double) -> Maybe Double -> Maybe Double
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Double -> Double
square (Maybe Double -> Maybe Double)
-> (d -> Maybe Double) -> d -> Maybe Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. d -> Maybe Double
forall d. MaybeVariance d => d -> Maybe Double
maybeStdDev
    maybeStdDev   :: d -> Maybe Double
    maybeStdDev   = (Double -> Double) -> Maybe Double -> Maybe Double
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Double -> Double
forall a. Floating a => a -> a
sqrt (Maybe Double -> Maybe Double)
-> (d -> Maybe Double) -> d -> Maybe Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. d -> Maybe Double
forall d. MaybeVariance d => d -> Maybe Double
maybeVariance
    {-# MINIMAL (maybeVariance | maybeStdDev) #-}
class (Mean d, MaybeVariance d) => Variance d where
    variance :: d -> Double
    variance d
d = Double -> Double
square (d -> Double
forall d. Variance d => d -> Double
stdDev d
d)
    stdDev   :: d -> Double
    stdDev = Double -> Double
forall a. Floating a => a -> a
sqrt (Double -> Double) -> (d -> Double) -> d -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. d -> Double
forall d. Variance d => d -> Double
variance
    {-# MINIMAL (variance | stdDev) #-}
class (Distribution d) => MaybeEntropy d where
  
  maybeEntropy :: d -> Maybe Double
class (MaybeEntropy d) => Entropy d where
  
  entropy :: d -> Double
class Distribution d => ContGen d where
  genContVar :: (StatefulGen g m) => d -> g -> m Double
class (DiscreteDistr d, ContGen d) => DiscreteGen d where
  genDiscreteVar :: (StatefulGen g m) => d -> g -> m Int
class FromSample d a where
  
  
  
  
  fromSample :: G.Vector v a => v a -> Maybe d
genContinuous :: (ContDistr d, StatefulGen g m) => d -> g -> m Double
genContinuous :: forall d g (m :: * -> *).
(ContDistr d, StatefulGen g m) =>
d -> g -> m Double
genContinuous d
d g
gen = do
  Double
x <- g -> m Double
forall g (m :: * -> *). StatefulGen g m => g -> m Double
uniformDouble01M g
gen
  Double -> m Double
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double -> m Double) -> Double -> m Double
forall a b. (a -> b) -> a -> b
$! d -> Double -> Double
forall d. ContDistr d => d -> Double -> Double
quantile d
d Double
x
data P = P {-# UNPACK #-} !Double {-# UNPACK #-} !Double
findRoot :: ContDistr d =>
            d                   
         -> Double              
         -> Double              
         -> Double              
         -> Double              
         -> Double
findRoot :: forall d.
ContDistr d =>
d -> Double -> Double -> Double -> Double -> Double
findRoot d
d Double
prob = Int -> Double -> Double -> Double -> Double -> Double
loop Int
0 Double
1
  where
    loop :: Int -> Double -> Double -> Double -> Double -> Double
loop !(Int
i::Int) !Double
dx !Double
x !Double
lo !Double
hi
      | Double -> Double
forall a. Num a => a -> a
abs Double
dx Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
accuracy Bool -> Bool -> Bool
|| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
maxIters = Double
x
      | Bool
otherwise                           = Int -> Double -> Double -> Double -> Double -> Double
loop (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Double
dx'' Double
x'' Double
lo' Double
hi'
      where
        err :: Double
err                   = d -> Double -> Double
forall d. Distribution d => d -> Double -> Double
cumulative d
d Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
prob
        P Double
lo' Double
hi' | Double
err Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0   = Double -> Double -> P
P Double
x Double
hi
                  | Bool
otherwise = Double -> Double -> P
P Double
lo Double
x
        pdf :: Double
pdf                   = d -> Double -> Double
forall d. ContDistr d => d -> Double -> Double
density d
d Double
x
        P Double
dx' Double
x' | Double
pdf Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
/= Double
0   = Double -> Double -> P
P (Double
err Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
pdf) (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
dx)
                 | Bool
otherwise  = Double -> Double -> P
P Double
dx Double
x
        P Double
dx'' Double
x''
            | Double
x' Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
lo' Bool -> Bool -> Bool
|| Double
x' Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
hi' Bool -> Bool -> Bool
|| Double
pdf Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0 = let y :: Double
y = (Double
lo' Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
hi') Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2
                                                 in  Double -> Double -> P
P (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
x) Double
y
            | Bool
otherwise                        = Double -> Double -> P
P Double
dx' Double
x'
    accuracy :: Double
accuracy = Double
1e-15
    maxIters :: Int
maxIters = Int
150
sumProbabilities :: DiscreteDistr d => d -> Int -> Int -> Double
sumProbabilities :: forall d. DiscreteDistr d => d -> Int -> Int -> Double
sumProbabilities d
d Int
low Int
hi =
  
  
  Double -> Double -> Double
forall a. Ord a => a -> a -> a
min Double
1 (Double -> Double)
-> (Vector Int -> Double) -> Vector Int -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Double -> Double
forall (v :: * -> *). Vector v Double => v Double -> Double
sum (Vector Double -> Double)
-> (Vector Int -> Vector Double) -> Vector Int -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Double) -> Vector Int -> Vector Double
forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
U.map (d -> Int -> Double
forall d. DiscreteDistr d => d -> Int -> Double
probability d
d) (Vector Int -> Double) -> Vector Int -> Double
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Vector Int
forall a. (Unbox a, Enum a) => a -> a -> Vector a
U.enumFromTo Int
low Int
hi