module Pareto
( controlLimit
, entropy
, ratio
, pareto
, causeEffect
, causesMaxConcentration
, effectsMaxConcentration
) where
import Data.List (sort)
controlLimit x = 1 * majority minority
where
factor = x / 5
majority = 0.6 * (logBase 2 (0.6 / factor))
minority = 0.4 * (logBase 2 (0.4 / (4 * factor)))
entropy numbers = foldl (\acc x -> acc subtrahend x) 0 numbers
where
s = sum numbers
subtrahend x = x * logBase 2 x
ratio numbers = etr / cl
where
etr = roundTo 6 $ entropy numbers
cl = roundTo 6 $ controlLimit $ fromIntegral $ length numbers
pareto numbers = ratio numbers <= 1
effects causes numbers = last $ take halt eff
where
caus = makeCauses $ fromIntegral $ length numbers
eff = makeEffects numbers
halt = l (fromIntegral $ length $ dropWhile (<= causes) caus)
l :: Num a => a
l = fromIntegral $ length numbers
causes effects numbers = last $ take halt caus
where
caus = makeCauses $ fromIntegral $ length numbers
eff = makeEffects numbers
halt = fromIntegral $ length $ takeWhile (<= effects) eff
l :: Num a => a
l = fromIntegral $ length numbers
makeCauses :: (Fractional b, Enum b) => b -> [b]
makeCauses l = map (/l) [1..l]
makeEffects numbers = map (roundTo 3 . (/s)) cumsum
where
s = sum numbers
sorted = reverse $ sort numbers
cumsum = scanl1 (+) sorted
causesMaxConcentration :: [Float] -> Float
causesMaxConcentration numbers = ordinal / (fromIntegral $ length numbers)
where
concentration = makeConcentration numbers
peak = maximum concentration
equalMax = map (peak ==) concentration
ordinal = fromIntegral $ (length $ takeWhile (== False) equalMax) + 1
effectsMaxConcentration :: Num a => [Float] -> Float
effectsMaxConcentration numbers = effects (causesMaxConcentration numbers) numbers
causeEffect :: (RealFrac a1, Fractional b, Fractional a, Enum a) => [a1] -> [(a, b)]
causeEffect numbers = zip caus eff
where
caus = makeCauses l
eff = makeEffects numbers
l = fromIntegral $ length numbers
makeConcentration numbers = zipWith (*) [1..l] sorted
where
sorted = reverse $ sort numbers
l = fromIntegral $ length numbers
roundTo decimals number = fromIntegral (round $ number * 10^decimals) / 10^decimals