{-# 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