{-# 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 forall a. Num a => a -> a -> a
- forall d. Distribution d => d -> Double -> Double
complCumulative d
d Double
x
complCumulative :: d -> Double -> Double
complCumulative d
d Double
x = Double
1 forall a. Num a => a -> a -> a
- 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 = forall a. Floating a => a -> a
exp forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall d. DiscreteDistr d => d -> Int -> Double
logProbability d
d
logProbability :: d -> Int -> Double
logProbability d
d = forall a. Floating a => a -> a
log forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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 = forall a. Floating a => a -> a
exp forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall d. ContDistr d => d -> Double -> Double
logDensity d
d
logDensity :: d -> Double -> Double
logDensity d
d = forall a. Floating a => a -> a
log forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall d. ContDistr d => d -> Double -> Double
density d
d
quantile :: d -> Double -> Double
quantile d
d Double
x = forall d. ContDistr d => d -> Double -> Double
complQuantile d
d (Double
1 forall a. Num a => a -> a -> a
- Double
x)
complQuantile :: d -> Double -> Double
complQuantile d
d Double
x = forall d. ContDistr d => d -> Double -> Double
quantile d
d (Double
1 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 = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Double -> Double
square forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall d. MaybeVariance d => d -> Maybe Double
maybeStdDev
maybeStdDev :: d -> Maybe Double
maybeStdDev = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Floating a => a -> a
sqrt forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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 (forall d. Variance d => d -> Double
stdDev d
d)
stdDev :: d -> Double
stdDev = forall a. Floating a => a -> a
sqrt forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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 <- forall g (m :: * -> *). StatefulGen g m => g -> m Double
uniformDouble01M g
gen
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! 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
| forall a. Num a => a -> a
abs Double
dx forall a. Ord a => a -> a -> Bool
<= Double
accuracy Bool -> Bool -> Bool
|| Int
i forall a. Ord a => a -> a -> Bool
>= Int
maxIters = Double
x
| Bool
otherwise = Int -> Double -> Double -> Double -> Double -> Double
loop (Int
iforall a. Num a => a -> a -> a
+Int
1) Double
dx'' Double
x'' Double
lo' Double
hi'
where
err :: Double
err = forall d. Distribution d => d -> Double -> Double
cumulative d
d Double
x forall a. Num a => a -> a -> a
- Double
prob
P Double
lo' Double
hi' | Double
err 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 = forall d. ContDistr d => d -> Double -> Double
density d
d Double
x
P Double
dx' Double
x' | Double
pdf forall a. Eq a => a -> a -> Bool
/= Double
0 = Double -> Double -> P
P (Double
err forall a. Fractional a => a -> a -> a
/ Double
pdf) (Double
x 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' forall a. Ord a => a -> a -> Bool
< Double
lo' Bool -> Bool -> Bool
|| Double
x' forall a. Ord a => a -> a -> Bool
> Double
hi' Bool -> Bool -> Bool
|| Double
pdf forall a. Eq a => a -> a -> Bool
== Double
0 = let y :: Double
y = (Double
lo' forall a. Num a => a -> a -> a
+ Double
hi') forall a. Fractional a => a -> a -> a
/ Double
2
in Double -> Double -> P
P (Double
yforall 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 =
forall a. Ord a => a -> a -> a
min Double
1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (v :: * -> *). Vector v Double => v Double -> Double
sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
U.map (forall d. DiscreteDistr d => d -> Int -> Double
probability d
d) forall a b. (a -> b) -> a -> b
$ forall a. (Unbox a, Enum a) => a -> a -> Vector a
U.enumFromTo Int
low Int
hi