{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
-- |
-- Module    : Statistics.Distribution.Lognormal
-- Copyright : (c) 2020 Ximin Luo
-- License   : BSD3
--
-- Maintainer  : infinity0@pwned.gg
-- Stability   : experimental
-- Portability : portable
--
-- The Weibull distribution.  This is a continuous probability
-- distribution that describes the occurrence of a single event whose
-- probability changes over time, controlled by the shape parameter.

module Statistics.Distribution.Weibull
    (
      WeibullDistribution
      -- * Constructors
    , weibullDistr
    , weibullDistrErr
    , weibullStandard
    , weibullDistrApproxMeanStddevErr
    ) where

import Control.Applicative
import Data.Aeson            (FromJSON(..), ToJSON, Value(..), (.:))
import Data.Binary           (Binary(..))
import Data.Data             (Data, Typeable)
import GHC.Generics          (Generic)
import Numeric.MathFunctions.Constants (m_eulerMascheroni)
import Numeric.SpecFunctions (expm1, log1p, logGamma)
import qualified Data.Vector.Generic as G

import qualified Statistics.Distribution as D
import qualified Statistics.Sample as S
import Statistics.Internal


-- | The Weibull distribution.
data WeibullDistribution = WD {
      WeibullDistribution -> Double
wdShape  :: {-# UNPACK #-} !Double
    , WeibullDistribution -> Double
wdLambda :: {-# UNPACK #-} !Double
    } deriving (WeibullDistribution -> WeibullDistribution -> Bool
(WeibullDistribution -> WeibullDistribution -> Bool)
-> (WeibullDistribution -> WeibullDistribution -> Bool)
-> Eq WeibullDistribution
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: WeibullDistribution -> WeibullDistribution -> Bool
$c/= :: WeibullDistribution -> WeibullDistribution -> Bool
== :: WeibullDistribution -> WeibullDistribution -> Bool
$c== :: WeibullDistribution -> WeibullDistribution -> Bool
Eq, Typeable, Typeable WeibullDistribution
DataType
Constr
Typeable WeibullDistribution
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g)
    -> WeibullDistribution
    -> c WeibullDistribution)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c WeibullDistribution)
-> (WeibullDistribution -> Constr)
-> (WeibullDistribution -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c WeibullDistribution))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c WeibullDistribution))
-> ((forall b. Data b => b -> b)
    -> WeibullDistribution -> WeibullDistribution)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> WeibullDistribution -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> WeibullDistribution -> r)
-> (forall u.
    (forall d. Data d => d -> u) -> WeibullDistribution -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> WeibullDistribution -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> WeibullDistribution -> m WeibullDistribution)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> WeibullDistribution -> m WeibullDistribution)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> WeibullDistribution -> m WeibullDistribution)
-> Data WeibullDistribution
WeibullDistribution -> DataType
WeibullDistribution -> Constr
(forall b. Data b => b -> b)
-> WeibullDistribution -> WeibullDistribution
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> WeibullDistribution
-> c WeibullDistribution
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c WeibullDistribution
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) -> WeibullDistribution -> u
forall u.
(forall d. Data d => d -> u) -> WeibullDistribution -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> WeibullDistribution -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> WeibullDistribution -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> WeibullDistribution -> m WeibullDistribution
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> WeibullDistribution -> m WeibullDistribution
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c WeibullDistribution
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> WeibullDistribution
-> c WeibullDistribution
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c WeibullDistribution)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c WeibullDistribution)
$cWD :: Constr
$tWeibullDistribution :: DataType
gmapMo :: (forall d. Data d => d -> m d)
-> WeibullDistribution -> m WeibullDistribution
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> WeibullDistribution -> m WeibullDistribution
gmapMp :: (forall d. Data d => d -> m d)
-> WeibullDistribution -> m WeibullDistribution
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d)
-> WeibullDistribution -> m WeibullDistribution
gmapM :: (forall d. Data d => d -> m d)
-> WeibullDistribution -> m WeibullDistribution
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d)
-> WeibullDistribution -> m WeibullDistribution
gmapQi :: Int -> (forall d. Data d => d -> u) -> WeibullDistribution -> u
$cgmapQi :: forall u.
Int -> (forall d. Data d => d -> u) -> WeibullDistribution -> u
gmapQ :: (forall d. Data d => d -> u) -> WeibullDistribution -> [u]
$cgmapQ :: forall u.
(forall d. Data d => d -> u) -> WeibullDistribution -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> WeibullDistribution -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> WeibullDistribution -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> WeibullDistribution -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> WeibullDistribution -> r
gmapT :: (forall b. Data b => b -> b)
-> WeibullDistribution -> WeibullDistribution
$cgmapT :: (forall b. Data b => b -> b)
-> WeibullDistribution -> WeibullDistribution
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c WeibullDistribution)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c WeibullDistribution)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c WeibullDistribution)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c WeibullDistribution)
dataTypeOf :: WeibullDistribution -> DataType
$cdataTypeOf :: WeibullDistribution -> DataType
toConstr :: WeibullDistribution -> Constr
$ctoConstr :: WeibullDistribution -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c WeibullDistribution
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c WeibullDistribution
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> WeibullDistribution
-> c WeibullDistribution
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g)
-> WeibullDistribution
-> c WeibullDistribution
$cp1Data :: Typeable WeibullDistribution
Data, (forall x. WeibullDistribution -> Rep WeibullDistribution x)
-> (forall x. Rep WeibullDistribution x -> WeibullDistribution)
-> Generic WeibullDistribution
forall x. Rep WeibullDistribution x -> WeibullDistribution
forall x. WeibullDistribution -> Rep WeibullDistribution x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep WeibullDistribution x -> WeibullDistribution
$cfrom :: forall x. WeibullDistribution -> Rep WeibullDistribution x
Generic)

instance Show WeibullDistribution where
  showsPrec :: Int -> WeibullDistribution -> ShowS
showsPrec Int
i (WD Double
k Double
l) = String -> Double -> Double -> Int -> ShowS
forall a b. (Show a, Show b) => String -> a -> b -> Int -> ShowS
defaultShow2 String
"weibullDistr" Double
k Double
l Int
i
instance Read WeibullDistribution where
  readPrec :: ReadPrec WeibullDistribution
readPrec = String
-> (Double -> Double -> Maybe WeibullDistribution)
-> ReadPrec WeibullDistribution
forall a b r.
(Read a, Read b) =>
String -> (a -> b -> Maybe r) -> ReadPrec r
defaultReadPrecM2 String
"weibullDistr" ((Double -> Double -> Maybe WeibullDistribution)
 -> ReadPrec WeibullDistribution)
-> (Double -> Double -> Maybe WeibullDistribution)
-> ReadPrec WeibullDistribution
forall a b. (a -> b) -> a -> b
$
    ((String -> Maybe WeibullDistribution)
-> (WeibullDistribution -> Maybe WeibullDistribution)
-> Either String WeibullDistribution
-> Maybe WeibullDistribution
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe WeibullDistribution -> String -> Maybe WeibullDistribution
forall a b. a -> b -> a
const Maybe WeibullDistribution
forall a. Maybe a
Nothing) WeibullDistribution -> Maybe WeibullDistribution
forall a. a -> Maybe a
Just (Either String WeibullDistribution -> Maybe WeibullDistribution)
-> (Double -> Either String WeibullDistribution)
-> Double
-> Maybe WeibullDistribution
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Double -> Either String WeibullDistribution)
 -> Double -> Maybe WeibullDistribution)
-> (Double -> Double -> Either String WeibullDistribution)
-> Double
-> Double
-> Maybe WeibullDistribution
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double -> Either String WeibullDistribution
weibullDistrErr

instance ToJSON WeibullDistribution
instance FromJSON WeibullDistribution where
  parseJSON :: Value -> Parser WeibullDistribution
parseJSON (Object Object
v) = do
    Double
k <- Object
v Object -> Key -> Parser Double
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"wdShape"
    Double
l <- Object
v Object -> Key -> Parser Double
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"wdLambda"
    (String -> Parser WeibullDistribution)
-> (WeibullDistribution -> Parser WeibullDistribution)
-> Either String WeibullDistribution
-> Parser WeibullDistribution
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Parser WeibullDistribution
forall (m :: * -> *) a. MonadFail m => String -> m a
fail WeibullDistribution -> Parser WeibullDistribution
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String WeibullDistribution -> Parser WeibullDistribution)
-> Either String WeibullDistribution -> Parser WeibullDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Either String WeibullDistribution
weibullDistrErr Double
k Double
l
  parseJSON Value
_ = Parser WeibullDistribution
forall (f :: * -> *) a. Alternative f => f a
empty

instance Binary WeibullDistribution where
  put :: WeibullDistribution -> Put
put (WD Double
k Double
l) = Double -> Put
forall t. Binary t => t -> Put
put Double
k Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Double -> Put
forall t. Binary t => t -> Put
put Double
l
  get :: Get WeibullDistribution
get = do
    Double
k <- Get Double
forall t. Binary t => Get t
get
    Double
l <- Get Double
forall t. Binary t => Get t
get
    (String -> Get WeibullDistribution)
-> (WeibullDistribution -> Get WeibullDistribution)
-> Either String WeibullDistribution
-> Get WeibullDistribution
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Get WeibullDistribution
forall (m :: * -> *) a. MonadFail m => String -> m a
fail WeibullDistribution -> Get WeibullDistribution
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String WeibullDistribution -> Get WeibullDistribution)
-> Either String WeibullDistribution -> Get WeibullDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Either String WeibullDistribution
weibullDistrErr Double
k Double
l

instance D.Distribution WeibullDistribution where
  cumulative :: WeibullDistribution -> Double -> Double
cumulative      = WeibullDistribution -> Double -> Double
cumulative
  complCumulative :: WeibullDistribution -> Double -> Double
complCumulative = WeibullDistribution -> Double -> Double
complCumulative

instance D.ContDistr WeibullDistribution where
  logDensity :: WeibullDistribution -> Double -> Double
logDensity    = WeibullDistribution -> Double -> Double
logDensity
  quantile :: WeibullDistribution -> Double -> Double
quantile      = WeibullDistribution -> Double -> Double
quantile
  complQuantile :: WeibullDistribution -> Double -> Double
complQuantile = WeibullDistribution -> Double -> Double
complQuantile

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

instance D.Mean WeibullDistribution where
  mean :: WeibullDistribution -> Double
mean (WD Double
k Double
l) = Double
l Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double
logGamma (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
k))

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

instance D.Variance WeibullDistribution where
  variance :: WeibullDistribution -> Double
variance (WD Double
k Double
l) = Double
l Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
l Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double
logGamma (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
invk)) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
q Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
q)
   where
    invk :: Double
invk = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
k
    q :: Double
q    = Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double
logGamma (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
invk))

instance D.Entropy WeibullDistribution where
  entropy :: WeibullDistribution -> Double
entropy (WD Double
k Double
l) = Double
m_eulerMascheroni Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
k) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
forall a. Floating a => a -> a
log (Double
l Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
k) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1

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

instance D.ContGen WeibullDistribution where
  genContVar :: WeibullDistribution -> g -> m Double
genContVar WeibullDistribution
d = WeibullDistribution -> g -> m Double
forall d g (m :: * -> *).
(ContDistr d, StatefulGen g m) =>
d -> g -> m Double
D.genContinuous WeibullDistribution
d

-- | Standard Weibull distribution with scale factor (lambda) 1.
weibullStandard :: Double -> WeibullDistribution
weibullStandard :: Double -> WeibullDistribution
weibullStandard Double
k = Double -> Double -> WeibullDistribution
weibullDistr Double
k Double
1.0

-- | Create Weibull distribution from parameters.
--
-- If the shape (first) parameter is @1.0@, the distribution is equivalent to a
-- 'Statistics.Distribution.Exponential.ExponentialDistribution' with parameter
-- @1 / lambda@ the scale (second) parameter.
weibullDistr
  :: Double            -- ^ Shape
  -> Double            -- ^ Lambda (scale)
  -> WeibullDistribution
weibullDistr :: Double -> Double -> WeibullDistribution
weibullDistr Double
k Double
l = (String -> WeibullDistribution)
-> (WeibullDistribution -> WeibullDistribution)
-> Either String WeibullDistribution
-> WeibullDistribution
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> WeibullDistribution
forall a. HasCallStack => String -> a
error WeibullDistribution -> WeibullDistribution
forall a. a -> a
id (Either String WeibullDistribution -> WeibullDistribution)
-> Either String WeibullDistribution -> WeibullDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Either String WeibullDistribution
weibullDistrErr Double
k Double
l

-- | Create Weibull distribution from parameters.
--
-- If the shape (first) parameter is @1.0@, the distribution is equivalent to a
-- 'Statistics.Distribution.Exponential.ExponentialDistribution' with parameter
-- @1 / lambda@ the scale (second) parameter.
weibullDistrErr
  :: Double            -- ^ Shape
  -> Double            -- ^ Lambda (scale)
  -> Either String WeibullDistribution
weibullDistrErr :: Double -> Double -> Either String WeibullDistribution
weibullDistrErr Double
k Double
l | Double
k Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0     = String -> Either String WeibullDistribution
forall a b. a -> Either a b
Left (String -> Either String WeibullDistribution)
-> String -> Either String WeibullDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> String
errMsg Double
k Double
l
                    | Double
l Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0     = String -> Either String WeibullDistribution
forall a b. a -> Either a b
Left (String -> Either String WeibullDistribution)
-> String -> Either String WeibullDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> String
errMsg Double
k Double
l
                    | Bool
otherwise = WeibullDistribution -> Either String WeibullDistribution
forall a b. b -> Either a b
Right (WeibullDistribution -> Either String WeibullDistribution)
-> WeibullDistribution -> Either String WeibullDistribution
forall a b. (a -> b) -> a -> b
$ Double -> Double -> WeibullDistribution
WD Double
k Double
l

errMsg :: Double -> Double -> String
errMsg :: Double -> Double -> String
errMsg Double
k Double
l =
  String
"Statistics.Distribution.Weibull.weibullDistr: both shape and lambda must be positive. Got shape "
    String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
k
    String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" and lambda "
    String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
l

-- | Create Weibull distribution from mean and standard deviation.
--
-- The algorithm is from "Methods for Estimating Wind Speed Frequency
-- Distributions", C. G. Justus, W. R. Hargreaves, A. Mikhail, D. Graber, 1977.
-- Given the identity:
--
-- \[
-- (\frac{\sigma}{\mu})^2 = \frac{\Gamma(1+2/k)}{\Gamma(1+1/k)^2} - 1
-- \]
--
-- \(k\) can be approximated by
--
-- \[
-- k \approx (\frac{\sigma}{\mu})^{-1.086}
-- \]
--
-- \(\lambda\) is then calculated straightforwardly via the identity
--
-- \[
-- \lambda = \frac{\mu}{\Gamma(1+1/k)}
-- \]
--
-- Numerically speaking, the approximation for \(k\) is accurate only within a
-- certain range. We arbitrarily pick the range \(0.033 \le \frac{\sigma}{\mu} \le 1.45\)
-- where it is good to ~6%, and will refuse to create a distribution outside of
-- this range. The paper does not cover these details but it is straightforward
-- to check them numerically.
weibullDistrApproxMeanStddevErr
  :: Double            -- ^ Mean
  -> Double            -- ^ Stddev
  -> Either String WeibullDistribution
weibullDistrApproxMeanStddevErr :: Double -> Double -> Either String WeibullDistribution
weibullDistrApproxMeanStddevErr Double
m Double
s = if Double
r Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
1.45 Bool -> Bool -> Bool
|| Double
r Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0.033
    then String -> Either String WeibullDistribution
forall a b. a -> Either a b
Left String
msg
    else Double -> Double -> Either String WeibullDistribution
weibullDistrErr Double
k Double
l
  where r :: Double
r = Double
s Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
m
        k :: Double
k = (Double
s Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
m) Double -> Double -> Double
forall a. Floating a => a -> a -> a
** (-Double
1.086)
        l :: Double
l = Double
m Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double
logGamma (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
k))
        msg :: String
msg = String
"Statistics.Distribution.Weibull.weibullDistr: stddev-mean ratio "
          String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"outside approximation accuracy range [0.033, 1.45]. Got "
          String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"stddev " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
s String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" and mean " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
m

-- | Uses an approximation based on the mean and standard deviation in
--   'weibullDistrEstMeanStddevErr', with standard deviation estimated
--   using maximum likelihood method (unbiased estimation).
--
--   Returns @Nothing@ if sample contains less than one element or
--   variance is zero (all elements are equal), or if the estimated mean
--   and standard-deviation lies outside the range for which the
--   approximation is accurate.
instance D.FromSample WeibullDistribution Double where
  fromSample :: v Double -> Maybe WeibullDistribution
fromSample v Double
xs
    | v Double -> Int
forall (v :: * -> *) a. Vector v a => v a -> Int
G.length v Double
xs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1 = Maybe WeibullDistribution
forall a. Maybe a
Nothing
    | Double
v Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0           = Maybe WeibullDistribution
forall a. Maybe a
Nothing
    | Bool
otherwise        = (String -> Maybe WeibullDistribution)
-> (WeibullDistribution -> Maybe WeibullDistribution)
-> Either String WeibullDistribution
-> Maybe WeibullDistribution
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe WeibullDistribution -> String -> Maybe WeibullDistribution
forall a b. a -> b -> a
const Maybe WeibullDistribution
forall a. Maybe a
Nothing) WeibullDistribution -> Maybe WeibullDistribution
forall a. a -> Maybe a
Just (Either String WeibullDistribution -> Maybe WeibullDistribution)
-> Either String WeibullDistribution -> Maybe WeibullDistribution
forall a b. (a -> b) -> a -> b
$
      Double -> Double -> Either String WeibullDistribution
weibullDistrApproxMeanStddevErr Double
m (Double -> Double
forall a. Floating a => a -> a
sqrt Double
v)
    where
      (Double
m,Double
v) = v Double -> (Double, Double)
forall (v :: * -> *).
Vector v Double =>
v Double -> (Double, Double)
S.meanVarianceUnb v Double
xs

logDensity :: WeibullDistribution -> Double -> Double
logDensity :: WeibullDistribution -> Double -> Double
logDensity (WD Double
k Double
l) Double
x
  | Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0     = Double
0
  | Bool
otherwise = Double -> Double
forall a. Floating a => a -> a
log Double
k Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
k Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
log Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
k Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
log Double
l Double -> Double -> Double
forall a. Num a => a -> a -> a
- (Double
x Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
l) Double -> Double -> Double
forall a. Floating a => a -> a -> a
** Double
k

cumulative :: WeibullDistribution -> Double -> Double
cumulative :: WeibullDistribution -> Double -> Double
cumulative (WD Double
k Double
l) Double
x | Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0     = Double
0
                      | Bool
otherwise = -Double -> Double
forall a. Floating a => a -> a
expm1 (-(Double
x Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
l) Double -> Double -> Double
forall a. Floating a => a -> a -> a
** Double
k)

complCumulative :: WeibullDistribution -> Double -> Double
complCumulative :: WeibullDistribution -> Double -> Double
complCumulative (WD Double
k Double
l) Double
x | Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0     = Double
1
                           | Bool
otherwise = Double -> Double
forall a. Floating a => a -> a
exp (-(Double
x Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
l) Double -> Double -> Double
forall a. Floating a => a -> a -> a
** Double
k)

quantile :: WeibullDistribution -> Double -> Double
quantile :: WeibullDistribution -> Double -> Double
quantile (WD Double
k Double
l) Double
p
  | Double
p Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0         = Double
0
  | Double
p Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
1         = Double
inf
  | Double
p Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 Bool -> Bool -> Bool
&& Double
p Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1 = Double
l Double -> Double -> Double
forall a. Num a => a -> a -> a
* (-Double -> Double
forall a. Floating a => a -> a
log1p (-Double
p)) Double -> Double -> Double
forall a. Floating a => a -> a -> a
** (Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
k)
  | Bool
otherwise      =
    String -> Double
forall a. HasCallStack => String -> a
error (String -> Double) -> String -> Double
forall a b. (a -> b) -> a -> b
$ String
"Statistics.Distribution.Weibull.quantile: p must be in [0,1] range. Got: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
p
  where inf :: Double
inf = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
0

complQuantile :: WeibullDistribution -> Double -> Double
complQuantile :: WeibullDistribution -> Double -> Double
complQuantile (WD Double
k Double
l) Double
q
  | Double
q Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
0         = Double
inf
  | Double
q Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
1         = Double
0
  | Double
q Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 Bool -> Bool -> Bool
&& Double
q Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1 = Double
l Double -> Double -> Double
forall a. Num a => a -> a -> a
* (-Double -> Double
forall a. Floating a => a -> a
log Double
q) Double -> Double -> Double
forall a. Floating a => a -> a -> a
** (Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
k)
  | Bool
otherwise      =
    String -> Double
forall a. HasCallStack => String -> a
error (String -> Double) -> String -> Double
forall a b. (a -> b) -> a -> b
$ String
"Statistics.Distribution.Weibull.complQuantile: q must be in [0,1] range. Got: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Double -> String
forall a. Show a => a -> String
show Double
q
  where inf :: Double
inf = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
0