{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# OPTIONS_GHC -Wno-type-defaults #-}
{-# OPTIONS_GHC -Wno-unused-top-binds #-}

-- |
-- This is adapted from https://jtobin.io/giry-monad-implementation
-- but brought into the monad-bayes framework (i.e. Integrator is an instance of MonadMeasure)
-- It's largely for debugging other inference methods and didactic use,
-- because brute force integration of measures is
-- only practical for small programs
module Control.Monad.Bayes.Integrator
  ( probability,
    variance,
    expectation,
    cdf,
    empirical,
    enumeratorWith,
    histogram,
    plotCdf,
    volume,
    normalize,
    Integrator,
    momentGeneratingFunction,
    cumulantGeneratingFunction,
    integrator,
    runIntegrator,
  )
where

import Control.Applicative (Applicative (..))
import Control.Foldl (Fold)
import Control.Foldl qualified as Foldl
import Control.Monad.Bayes.Class (MonadDistribution (bernoulli, random, uniformD))
import Control.Monad.Bayes.Weighted (WeightedT, runWeightedT)
import Control.Monad.Cont
  ( Cont,
    ContT (ContT),
    cont,
    runCont,
  )
import Data.Foldable (Foldable (foldl'))
import Data.Set (Set, elems)
import Numeric.Integration.TanhSinh (Result (result), trap)
import Numeric.Log (Log (ln))
import Statistics.Distribution qualified as Statistics
import Statistics.Distribution.Uniform qualified as Statistics
-- Prelude exports liftA2 from GHC 9.6 on, see https://github.com/haskell/core-libraries-committee/blob/main/guides/export-lifta2-prelude.md
-- import Control.Applicative further up can be removed once we don't support GHC <= 9.4 anymore

import Prelude hiding (Applicative (..))

newtype Integrator a = Integrator {forall a. Integrator a -> Cont Double a
getIntegrator :: Cont Double a}
  deriving newtype ((forall a b. (a -> b) -> Integrator a -> Integrator b)
-> (forall a b. a -> Integrator b -> Integrator a)
-> Functor Integrator
forall a b. a -> Integrator b -> Integrator a
forall a b. (a -> b) -> Integrator a -> Integrator b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> Integrator a -> Integrator b
fmap :: forall a b. (a -> b) -> Integrator a -> Integrator b
$c<$ :: forall a b. a -> Integrator b -> Integrator a
<$ :: forall a b. a -> Integrator b -> Integrator a
Functor, Functor Integrator
Functor Integrator =>
(forall a. a -> Integrator a)
-> (forall a b.
    Integrator (a -> b) -> Integrator a -> Integrator b)
-> (forall a b c.
    (a -> b -> c) -> Integrator a -> Integrator b -> Integrator c)
-> (forall a b. Integrator a -> Integrator b -> Integrator b)
-> (forall a b. Integrator a -> Integrator b -> Integrator a)
-> Applicative Integrator
forall a. a -> Integrator a
forall a b. Integrator a -> Integrator b -> Integrator a
forall a b. Integrator a -> Integrator b -> Integrator b
forall a b. Integrator (a -> b) -> Integrator a -> Integrator b
forall a b c.
(a -> b -> c) -> Integrator a -> Integrator b -> Integrator c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall a. a -> Integrator a
pure :: forall a. a -> Integrator a
$c<*> :: forall a b. Integrator (a -> b) -> Integrator a -> Integrator b
<*> :: forall a b. Integrator (a -> b) -> Integrator a -> Integrator b
$cliftA2 :: forall a b c.
(a -> b -> c) -> Integrator a -> Integrator b -> Integrator c
liftA2 :: forall a b c.
(a -> b -> c) -> Integrator a -> Integrator b -> Integrator c
$c*> :: forall a b. Integrator a -> Integrator b -> Integrator b
*> :: forall a b. Integrator a -> Integrator b -> Integrator b
$c<* :: forall a b. Integrator a -> Integrator b -> Integrator a
<* :: forall a b. Integrator a -> Integrator b -> Integrator a
Applicative, Applicative Integrator
Applicative Integrator =>
(forall a b. Integrator a -> (a -> Integrator b) -> Integrator b)
-> (forall a b. Integrator a -> Integrator b -> Integrator b)
-> (forall a. a -> Integrator a)
-> Monad Integrator
forall a. a -> Integrator a
forall a b. Integrator a -> Integrator b -> Integrator b
forall a b. Integrator a -> (a -> Integrator b) -> Integrator b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall a b. Integrator a -> (a -> Integrator b) -> Integrator b
>>= :: forall a b. Integrator a -> (a -> Integrator b) -> Integrator b
$c>> :: forall a b. Integrator a -> Integrator b -> Integrator b
>> :: forall a b. Integrator a -> Integrator b -> Integrator b
$creturn :: forall a. a -> Integrator a
return :: forall a. a -> Integrator a
Monad)

runIntegrator :: (a -> Double) -> Integrator a -> Double
runIntegrator :: forall a. (a -> Double) -> Integrator a -> Double
runIntegrator a -> Double
f (Integrator Cont Double a
a) = Cont Double a -> (a -> Double) -> Double
forall r a. Cont r a -> (a -> r) -> r
runCont Cont Double a
a a -> Double
f

integrator :: ((a -> Double) -> Double) -> Integrator a
integrator :: forall a. ((a -> Double) -> Double) -> Integrator a
integrator = Cont Double a -> Integrator a
forall a. Cont Double a -> Integrator a
Integrator (Cont Double a -> Integrator a)
-> (((a -> Double) -> Double) -> Cont Double a)
-> ((a -> Double) -> Double)
-> Integrator a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a -> Double) -> Double) -> Cont Double a
forall a r. ((a -> r) -> r) -> Cont r a
cont

instance MonadDistribution Integrator where
  random :: Integrator Double
random = (Double -> Double) -> Integrator Double
fromDensityFunction ((Double -> Double) -> Integrator Double)
-> (Double -> Double) -> Integrator Double
forall a b. (a -> b) -> a -> b
$ UniformDistribution -> Double -> Double
forall d. ContDistr d => d -> Double -> Double
Statistics.density (UniformDistribution -> Double -> Double)
-> UniformDistribution -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double -> Double -> UniformDistribution
Statistics.uniformDistr Double
0 Double
1
  bernoulli :: Double -> Integrator Bool
bernoulli Double
p = Cont Double Bool -> Integrator Bool
forall a. Cont Double a -> Integrator a
Integrator (Cont Double Bool -> Integrator Bool)
-> Cont Double Bool -> Integrator Bool
forall a b. (a -> b) -> a -> b
$ ((Bool -> Double) -> Double) -> Cont Double Bool
forall a r. ((a -> r) -> r) -> Cont r a
cont (\Bool -> Double
f -> Double
p Double -> Double -> Double
forall a. Num a => a -> a -> a
* Bool -> Double
f Bool
True Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
p) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Bool -> Double
f Bool
False)
  uniformD :: forall a. [a] -> Integrator a
uniformD [a]
ls = (a -> Double) -> [a] -> Integrator a
forall (f :: * -> *) a.
Foldable f =>
(a -> Double) -> f a -> Integrator a
fromMassFunction (Double -> a -> Double
forall a b. a -> b -> a
const (Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
ls))) [a]
ls

fromDensityFunction :: (Double -> Double) -> Integrator Double
fromDensityFunction :: (Double -> Double) -> Integrator Double
fromDensityFunction Double -> Double
d = Cont Double Double -> Integrator Double
forall a. Cont Double a -> Integrator a
Integrator (Cont Double Double -> Integrator Double)
-> Cont Double Double -> Integrator Double
forall a b. (a -> b) -> a -> b
$
  ((Double -> Double) -> Double) -> Cont Double Double
forall a r. ((a -> r) -> r) -> Cont r a
cont (((Double -> Double) -> Double) -> Cont Double Double)
-> ((Double -> Double) -> Double) -> Cont Double Double
forall a b. (a -> b) -> a -> b
$ \Double -> Double
f ->
    (Double -> Double) -> Double
integralWithQuadrature (\Double
x -> Double -> Double
f Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
d Double
x)
  where
    integralWithQuadrature :: (Double -> Double) -> Double
integralWithQuadrature = Result -> Double
result (Result -> Double)
-> ((Double -> Double) -> Result) -> (Double -> Double) -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Result] -> Result
forall a. HasCallStack => [a] -> a
last ([Result] -> Result)
-> ((Double -> Double) -> [Result]) -> (Double -> Double) -> Result
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\Double -> Double
z -> (Double -> Double) -> Double -> Double -> [Result]
trap Double -> Double
z Double
0 Double
1)

fromMassFunction :: (Foldable f) => (a -> Double) -> f a -> Integrator a
fromMassFunction :: forall (f :: * -> *) a.
Foldable f =>
(a -> Double) -> f a -> Integrator a
fromMassFunction a -> Double
f f a
support = Cont Double a -> Integrator a
forall a. Cont Double a -> Integrator a
Integrator (Cont Double a -> Integrator a) -> Cont Double a -> Integrator a
forall a b. (a -> b) -> a -> b
$ ((a -> Double) -> Double) -> Cont Double a
forall a r. ((a -> r) -> r) -> Cont r a
cont \a -> Double
g ->
  (Double -> a -> Double) -> Double -> f a -> Double
forall b a. (b -> a -> b) -> b -> f a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Double
acc a
x -> Double
acc Double -> Double -> Double
forall a. Num a => a -> a -> a
+ a -> Double
f a
x Double -> Double -> Double
forall a. Num a => a -> a -> a
* a -> Double
g a
x) Double
0 f a
support

empirical :: (Foldable f) => f a -> Integrator a
empirical :: forall (f :: * -> *) a. Foldable f => f a -> Integrator a
empirical = Cont Double a -> Integrator a
forall a. Cont Double a -> Integrator a
Integrator (Cont Double a -> Integrator a)
-> (f a -> Cont Double a) -> f a -> Integrator a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a -> Double) -> Double) -> Cont Double a
forall a r. ((a -> r) -> r) -> Cont r a
cont (((a -> Double) -> Double) -> Cont Double a)
-> (f a -> (a -> Double) -> Double) -> f a -> Cont Double a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a -> Double) -> f a -> Double) -> f a -> (a -> Double) -> Double
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> Double) -> f a -> Double
forall (f :: * -> *) r a.
(Foldable f, Fractional r) =>
(a -> r) -> f a -> r
weightedAverage
  where
    weightedAverage :: (Foldable f, Fractional r) => (a -> r) -> f a -> r
    weightedAverage :: forall (f :: * -> *) r a.
(Foldable f, Fractional r) =>
(a -> r) -> f a -> r
weightedAverage a -> r
f = Fold a r -> f a -> r
forall (f :: * -> *) a b. Foldable f => Fold a b -> f a -> b
Foldl.fold ((a -> r) -> Fold a r
forall r a. Fractional r => (a -> r) -> Fold a r
weightedAverageFold a -> r
f)

    weightedAverageFold :: (Fractional r) => (a -> r) -> Fold a r
    weightedAverageFold :: forall r a. Fractional r => (a -> r) -> Fold a r
weightedAverageFold a -> r
f = (a -> r) -> Fold r r -> Fold a r
forall a b r. (a -> b) -> Fold b r -> Fold a r
Foldl.premap a -> r
f Fold r r
forall a. Fractional a => Fold a a
averageFold

    averageFold :: (Fractional a) => Fold a a
    averageFold :: forall a. Fractional a => Fold a a
averageFold = a -> a -> a
forall a. Fractional a => a -> a -> a
(/) (a -> a -> a) -> Fold a a -> Fold a (a -> a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Fold a a
forall a. Num a => Fold a a
Foldl.sum Fold a (a -> a) -> Fold a a -> Fold a a
forall a b. Fold a (a -> b) -> Fold a a -> Fold a b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Fold a a
forall b a. Num b => Fold a b
Foldl.genericLength

expectation :: Integrator Double -> Double
expectation :: Integrator Double -> Double
expectation = (Double -> Double) -> Integrator Double -> Double
forall a. (a -> Double) -> Integrator a -> Double
runIntegrator Double -> Double
forall a. a -> a
id

variance :: Integrator Double -> Double
variance :: Integrator Double -> Double
variance Integrator Double
nu = (Double -> Double) -> Integrator Double -> Double
forall a. (a -> Double) -> Integrator a -> Double
runIntegrator (Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) Integrator Double
nu Double -> Double -> Double
forall a. Num a => a -> a -> a
- Integrator Double -> Double
expectation Integrator Double
nu Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2

momentGeneratingFunction :: Integrator Double -> Double -> Double
momentGeneratingFunction :: Integrator Double -> Double -> Double
momentGeneratingFunction Integrator Double
nu Double
t = (Double -> Double) -> Integrator Double -> Double
forall a. (a -> Double) -> Integrator a -> Double
runIntegrator (\Double
x -> Double -> Double
forall a. Floating a => a -> a
exp (Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x)) Integrator Double
nu

cumulantGeneratingFunction :: Integrator Double -> Double -> Double
cumulantGeneratingFunction :: Integrator Double -> Double -> Double
cumulantGeneratingFunction Integrator Double
nu = 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
. Integrator Double -> Double -> Double
momentGeneratingFunction Integrator Double
nu

normalize :: WeightedT Integrator a -> Integrator a
normalize :: forall a. WeightedT Integrator a -> Integrator a
normalize WeightedT Integrator a
m =
  let m' :: Integrator (a, Log Double)
m' = WeightedT Integrator a -> Integrator (a, Log Double)
forall (m :: * -> *) a. WeightedT m a -> m (a, Log Double)
runWeightedT WeightedT Integrator a
m
      z :: Double
z = ((a, Log Double) -> Double) -> Integrator (a, Log Double) -> Double
forall a. (a -> Double) -> Integrator a -> Double
runIntegrator (Log Double -> Double
forall a. Log a -> a
ln (Log Double -> Double)
-> ((a, Log Double) -> Log Double) -> (a, Log Double) -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Log Double -> Log Double
forall a. Floating a => a -> a
exp (Log Double -> Log Double)
-> ((a, Log Double) -> Log Double) -> (a, Log Double) -> Log Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, Log Double) -> Log Double
forall a b. (a, b) -> b
snd) Integrator (a, Log Double)
m'
   in do
        (a
x, Log Double
d) <- WeightedT Integrator a -> Integrator (a, Log Double)
forall (m :: * -> *) a. WeightedT m a -> m (a, Log Double)
runWeightedT WeightedT Integrator a
m
        Cont Double () -> Integrator ()
forall a. Cont Double a -> Integrator a
Integrator (Cont Double () -> Integrator ())
-> Cont Double () -> Integrator ()
forall a b. (a -> b) -> a -> b
$ ((() -> Double) -> Double) -> Cont Double ()
forall a r. ((a -> r) -> r) -> Cont r a
cont (((() -> Double) -> Double) -> Cont Double ())
-> ((() -> Double) -> Double) -> Cont Double ()
forall a b. (a -> b) -> a -> b
$ \() -> Double
f -> (() -> Double
f () Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Log Double -> Double
forall a. Log a -> a
ln (Log Double -> Double) -> Log Double -> Double
forall a b. (a -> b) -> a -> b
$ Log Double -> Log Double
forall a. Floating a => a -> a
exp Log Double
d)) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
z
        return a
x

cdf :: Integrator Double -> Double -> Double
cdf :: Integrator Double -> Double -> Double
cdf Integrator Double
nu Double
x = (Double -> Double) -> Integrator Double -> Double
forall a. (a -> Double) -> Integrator a -> Double
runIntegrator (Double
negativeInfinity Double -> Double -> Double -> Double
forall a. (Num a, Ord a) => a -> a -> a -> a
`to` Double
x) Integrator Double
nu
  where
    negativeInfinity :: Double
    negativeInfinity :: Double
negativeInfinity = Double -> Double
forall a. Num a => a -> a
negate (Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
0)

    to :: (Num a, Ord a) => a -> a -> a -> a
    to :: forall a. (Num a, Ord a) => a -> a -> a -> a
to a
a a
b a
k
      | a
k a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
a Bool -> Bool -> Bool
&& a
k a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
b = a
1
      | Bool
otherwise = a
0

volume :: Integrator Double -> Double
volume :: Integrator Double -> Double
volume = (Double -> Double) -> Integrator Double -> Double
forall a. (a -> Double) -> Integrator a -> Double
runIntegrator (Double -> Double -> Double
forall a b. a -> b -> a
const Double
1)

containing :: (Num a, Eq b) => [b] -> b -> a
containing :: forall a b. (Num a, Eq b) => [b] -> b -> a
containing [b]
xs b
x
  | b
x b -> [b] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [b]
xs = a
1
  | Bool
otherwise = a
0

instance (Num a) => Num (Integrator a) where
  + :: Integrator a -> Integrator a -> Integrator a
(+) = (a -> a -> a) -> Integrator a -> Integrator a -> Integrator a
forall a b c.
(a -> b -> c) -> Integrator a -> Integrator b -> Integrator c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 a -> a -> a
forall a. Num a => a -> a -> a
(+)
  (-) = (a -> a -> a) -> Integrator a -> Integrator a -> Integrator a
forall a b c.
(a -> b -> c) -> Integrator a -> Integrator b -> Integrator c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (-)
  * :: Integrator a -> Integrator a -> Integrator a
(*) = (a -> a -> a) -> Integrator a -> Integrator a -> Integrator a
forall a b c.
(a -> b -> c) -> Integrator a -> Integrator b -> Integrator c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 a -> a -> a
forall a. Num a => a -> a -> a
(*)
  abs :: Integrator a -> Integrator a
abs = (a -> a) -> Integrator a -> Integrator a
forall a b. (a -> b) -> Integrator a -> Integrator b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Num a => a -> a
abs
  signum :: Integrator a -> Integrator a
signum = (a -> a) -> Integrator a -> Integrator a
forall a b. (a -> b) -> Integrator a -> Integrator b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Num a => a -> a
signum
  fromInteger :: Integer -> Integrator a
fromInteger = a -> Integrator a
forall a. a -> Integrator a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> Integrator a) -> (Integer -> a) -> Integer -> Integrator a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> a
forall a. Num a => Integer -> a
fromInteger

probability :: (Ord a) => (a, a) -> Integrator a -> Double
probability :: forall a. Ord a => (a, a) -> Integrator a -> Double
probability (a
lower, a
upper) = (a -> Double) -> Integrator a -> Double
forall a. (a -> Double) -> Integrator a -> Double
runIntegrator (\a
x -> if a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
upper Bool -> Bool -> Bool
&& a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
lower then Double
1 else Double
0)

enumeratorWith :: (Ord a) => Set a -> Integrator a -> [(a, Double)]
enumeratorWith :: forall a. Ord a => Set a -> Integrator a -> [(a, Double)]
enumeratorWith Set a
ls Integrator a
meas =
  [ ( a
val,
      (a -> Double) -> Integrator a -> Double
forall a. (a -> Double) -> Integrator a -> Double
runIntegrator
        (\a
x -> if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
val then Double
1 else Double
0)
        Integrator a
meas
    )
    | a
val <- Set a -> [a]
forall a. Set a -> [a]
elems Set a
ls
  ]

histogram ::
  (Enum a, Ord a, Fractional a) =>
  Int ->
  a ->
  WeightedT Integrator a ->
  [(a, Double)]
histogram :: forall a.
(Enum a, Ord a, Fractional a) =>
Int -> a -> WeightedT Integrator a -> [(a, Double)]
histogram Int
nBins a
binSize WeightedT Integrator a
model = do
  a
x <- Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take Int
nBins [a
1 ..]
  let transform :: a -> a
transform a
k = (a
k a -> a -> a
forall a. Num a => a -> a -> a
- (Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
nBins a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
2)) a -> a -> a
forall a. Num a => a -> a -> a
* a
binSize
  return
    ( (forall a b. (a, b) -> a
fst)
        (a -> a
transform a
x, a -> a
transform (a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
1)),
      (a, a) -> Integrator a -> Double
forall a. Ord a => (a, a) -> Integrator a -> Double
probability (a -> a
transform a
x, a -> a
transform (a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
1)) (Integrator a -> Double) -> Integrator a -> Double
forall a b. (a -> b) -> a -> b
$ WeightedT Integrator a -> Integrator a
forall a. WeightedT Integrator a -> Integrator a
normalize WeightedT Integrator a
model
    )

plotCdf :: Int -> Double -> Double -> Integrator Double -> [(Double, Double)]
plotCdf :: Int -> Double -> Double -> Integrator Double -> [(Double, Double)]
plotCdf Int
nBins Double
binSize Double
middlePoint Integrator Double
model = do
  Double
x <- Int -> [Double] -> [Double]
forall a. Int -> [a] -> [a]
take Int
nBins [Double
1 ..]
  let transform :: Double -> Double
transform Double
k = (Double
k Double -> Double -> Double
forall a. Num a => a -> a -> a
- (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
nBins Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2)) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
binSize Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
middlePoint
  return (Double -> Double
transform Double
x, Integrator Double -> Double -> Double
cdf Integrator Double
model (Double -> Double
transform Double
x))