{-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver -fplugin=GHC.TypeLits.Normalise -fconstraint-solver-iterations=10 #-}
{-# LANGUAGE UndecidableInstances #-}

-- | 'Statistical' models where the observations depend on known conditions.
module Goal.Probability.Conditional
    ( SampleMap
    -- ** Markov Kernels
    , (>.>*)
    , (>$>*)
    , (*<.<)
    , (*<$<)
    -- ** Conditional Distributions
    , conditionalLogLikelihood
    , conditionalLogLikelihoodDifferential
    , conditionalDataMap
    , kFoldMap
    , kFoldMap'
    --, mapToConditionalData
    , mapConditionalLogLikelihood
    , mapConditionalLogLikelihoodDifferential
    , parMapConditionalLogLikelihood
    , parMapConditionalLogLikelihoodDifferential
    ) where


--- Imports  ---


-- Goal --

import Goal.Core
import Goal.Geometry

import Goal.Probability.Statistical
import Goal.Probability.ExponentialFamily

import qualified Data.Map.Strict as M
import qualified Data.List as L

import Control.Parallel.Strategies


--- Generic ---


-- | Evalutes the given conditional distribution at a 'SamplePoint'.
(>.>*) :: (Map Natural f y x, ExponentialFamily x)
       => Natural # f y x
       -> SamplePoint x
       -> Natural # y
>.>* :: (Natural # f y x) -> SamplePoint x -> Natural # y
(>.>*) Natural # f y x
p SamplePoint x
x = Natural # f y x
p (Natural # f y x) -> (Natural #* x) -> Natural # y
forall c (f :: Type -> Type -> Type) y x.
Map c f y x =>
(c # f y x) -> (c #* x) -> c # y
>.> SamplePoint x -> Mean # x
forall x. ExponentialFamily x => SamplePoint x -> Mean # x
sufficientStatistic SamplePoint x
x

-- | Mapped application of conditional distributions on a 'Sample'.
(>$>*) :: (Map Natural f y x, ExponentialFamily x)
       => Natural # f y x
       -> Sample x
       -> [Natural # y]
>$>* :: (Natural # f y x) -> Sample x -> [Natural # y]
(>$>*) Natural # f y x
p Sample x
xs = Natural # f y x
p (Natural # f y x) -> [Natural #* x] -> [Natural # y]
forall c (f :: Type -> Type -> Type) y x.
Map c f y x =>
(c # f y x) -> [c #* x] -> [c # y]
>$> (SamplePoint x -> Mean # x
forall x. ExponentialFamily x => SamplePoint x -> Mean # x
sufficientStatistic (SamplePoint x -> Mean # x) -> Sample x -> [Mean # x]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Sample x
xs)

infix 8 >.>*
infix 8 >$>*

-- | Applies the transpose of a 'Bilinear' 'Map' to a 'SamplePoint'.
(*<.<) :: (Map Natural f x y, Bilinear f y x, ExponentialFamily y)
       => SamplePoint y
       -> Natural # f y x
       -> Natural # x
*<.< :: SamplePoint y -> (Natural # f y x) -> Natural # x
(*<.<) SamplePoint y
x Natural # f y x
p = SamplePoint y -> Mean # y
forall x. ExponentialFamily x => SamplePoint x -> Mean # x
sufficientStatistic SamplePoint y
x Point (Dual Natural) y -> (Natural # f y x) -> Natural # x
forall c (f :: Type -> Type -> Type) x y.
(Map c f x y, Bilinear f y x) =>
(c #* y) -> (c # f y x) -> c # x
<.< Natural # f y x
p

-- | Mapped transpose application on a 'Sample'.
(*<$<) :: (Map Natural f x y, Bilinear f y x, ExponentialFamily y)
       => Sample y
       -> Natural # f y x
       -> [Natural # x]
*<$< :: Sample y -> (Natural # f y x) -> [Natural # x]
(*<$<) Sample y
xs Natural # f y x
p = (SamplePoint y -> Mean # y
forall x. ExponentialFamily x => SamplePoint x -> Mean # x
sufficientStatistic (SamplePoint y -> Mean # y) -> Sample y -> [Mean # y]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Sample y
xs) [Point (Dual Natural) y] -> (Natural # f y x) -> [Natural # x]
forall c (f :: Type -> Type -> Type) x y.
(Map c f x y, Bilinear f y x) =>
[c #* y] -> (c # f y x) -> [c # x]
<$< Natural # f y x
p

infix 8 *<.<
infix 8 *<$<


-- | A synonym for Maps from Inputs to Outputs that matches the confusing,
-- backwards style of Goal.
type SampleMap z x = M.Map (SamplePoint x) (Sample z)


dependantLogLikelihood
    :: (LogLikelihood Natural y s, Map Natural f y x)
    => [([s], Mean # x)] -> Natural # f y x -> Double
dependantLogLikelihood :: [([s], Mean # x)] -> (Natural # f y x) -> Double
dependantLogLikelihood [([s], Mean # x)]
ysxs Natural # f y x
chrm =
    let ([[s]]
yss,[Mean # x]
xs) = [([s], Mean # x)] -> ([[s]], [Mean # x])
forall a b. [(a, b)] -> ([a], [b])
unzip [([s], Mean # x)]
ysxs
     in [Double] -> Double
forall (f :: Type -> Type) x.
(Foldable f, Fractional x) =>
f x -> x
average ([Double] -> Double)
-> ([Natural # y] -> [Double]) -> [Natural # y] -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([s] -> (Natural # y) -> Double)
-> [[s]] -> [Natural # y] -> [Double]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith [s] -> (Natural # y) -> Double
forall c x s. LogLikelihood c x s => [s] -> (c # x) -> Double
logLikelihood [[s]]
yss ([Natural # y] -> Double) -> [Natural # y] -> Double
forall a b. (a -> b) -> a -> b
$ Natural # f y x
chrm (Natural # f y x) -> [Natural #* x] -> [Natural # y]
forall c (f :: Type -> Type -> Type) y x.
Map c f y x =>
(c # f y x) -> [c #* x] -> [c # y]
>$> [Natural #* x]
[Mean # x]
xs

dependantLogLikelihoodDifferential
    :: (LogLikelihood Natural y s, Propagate Natural f y x)
    => [([s], Mean # x)] -> Natural # f y x -> Mean # f y x
dependantLogLikelihoodDifferential :: [([s], Mean # x)] -> (Natural # f y x) -> Mean # f y x
dependantLogLikelihoodDifferential [([s], Mean # x)]
ysxs Natural # f y x
chrm =
    let ([[s]]
yss,[Mean # x]
xs) = [([s], Mean # x)] -> ([[s]], [Mean # x])
forall a b. [(a, b)] -> ([a], [b])
unzip [([s], Mean # x)]
ysxs
        (Mean # f y x
df,[Natural # y]
yhts) = [Natural #* y]
-> [Natural #* x]
-> (Natural # f y x)
-> (Natural #* f y x, [Natural # y])
forall c (f :: Type -> Type -> Type) y x.
Propagate c f y x =>
[c #* y] -> [c #* x] -> (c # f y x) -> (c #* f y x, [c # y])
propagate [Natural #* y]
[Point Mean y]
mys [Natural #* x]
[Mean # x]
xs Natural # f y x
chrm
        mys :: [Point Mean y]
mys = ([s] -> (Natural # y) -> Point Mean y)
-> [[s]] -> [Natural # y] -> [Point Mean y]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith [s] -> (Natural # y) -> Point Mean y
forall c x s. LogLikelihood c x s => [s] -> (c # x) -> c #* x
logLikelihoodDifferential [[s]]
yss [Natural # y]
yhts
     in Mean # f y x
df

dependantLogLikelihoodPar
    :: (LogLikelihood Natural y s, Map Natural f y x)
    => [([s], Mean # x)] -> Natural # f y x -> Double
dependantLogLikelihoodPar :: [([s], Mean # x)] -> (Natural # f y x) -> Double
dependantLogLikelihoodPar [([s], Mean # x)]
ysxs Natural # f y x
chrm =
    let ([[s]]
yss,[Mean # x]
xs) = [([s], Mean # x)] -> ([[s]], [Mean # x])
forall a b. [(a, b)] -> ([a], [b])
unzip [([s], Mean # x)]
ysxs
     in [Double] -> Double
forall (f :: Type -> Type) x.
(Foldable f, Fractional x) =>
f x -> x
average ([Double] -> Double)
-> ([Natural # y] -> [Double]) -> [Natural # y] -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Strategy Double
-> (([s], Natural # y) -> Double)
-> [([s], Natural # y)]
-> [Double]
forall b a. Strategy b -> (a -> b) -> [a] -> [b]
parMap Strategy Double
forall a. NFData a => Strategy a
rdeepseq (([s] -> (Natural # y) -> Double) -> ([s], Natural # y) -> Double
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry [s] -> (Natural # y) -> Double
forall c x s. LogLikelihood c x s => [s] -> (c # x) -> Double
logLikelihood) ([([s], Natural # y)] -> [Double])
-> ([Natural # y] -> [([s], Natural # y)])
-> [Natural # y]
-> [Double]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[s]] -> [Natural # y] -> [([s], Natural # y)]
forall a b. [a] -> [b] -> [(a, b)]
zip [[s]]
yss ([Natural # y] -> Double) -> [Natural # y] -> Double
forall a b. (a -> b) -> a -> b
$ Natural # f y x
chrm (Natural # f y x) -> [Natural #* x] -> [Natural # y]
forall c (f :: Type -> Type -> Type) y x.
Map c f y x =>
(c # f y x) -> [c #* x] -> [c # y]
>$> [Natural #* x]
[Mean # x]
xs

dependantLogLikelihoodDifferentialPar
    :: (LogLikelihood Natural y s, Propagate Natural f y x)
    => [([s], Mean # x)] -> Natural # f y x -> Mean # f y x
dependantLogLikelihoodDifferentialPar :: [([s], Mean # x)] -> (Natural # f y x) -> Mean # f y x
dependantLogLikelihoodDifferentialPar [([s], Mean # x)]
ysxs Natural # f y x
chrm =
    let ([[s]]
yss,[Mean # x]
xs) = [([s], Mean # x)] -> ([[s]], [Mean # x])
forall a b. [(a, b)] -> ([a], [b])
unzip [([s], Mean # x)]
ysxs
        (Mean # f y x
df,[Natural # y]
yhts) = [Natural #* y]
-> [Natural #* x]
-> (Natural # f y x)
-> (Natural #* f y x, [Natural # y])
forall c (f :: Type -> Type -> Type) y x.
Propagate c f y x =>
[c #* y] -> [c #* x] -> (c # f y x) -> (c #* f y x, [c # y])
propagate [Natural #* y]
[Point Mean y]
mys [Natural #* x]
[Mean # x]
xs Natural # f y x
chrm
        mys :: [Point Mean y]
mys = Strategy (Point Mean y)
-> (([s], Natural # y) -> Point Mean y)
-> [([s], Natural # y)]
-> [Point Mean y]
forall b a. Strategy b -> (a -> b) -> [a] -> [b]
parMap Strategy (Point Mean y)
forall a. NFData a => Strategy a
rdeepseq (([s] -> (Natural # y) -> Point Mean y)
-> ([s], Natural # y) -> Point Mean y
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry [s] -> (Natural # y) -> Point Mean y
forall c x s. LogLikelihood c x s => [s] -> (c # x) -> c #* x
logLikelihoodDifferential) ([([s], Natural # y)] -> [Point Mean y])
-> [([s], Natural # y)] -> [Point Mean y]
forall a b. (a -> b) -> a -> b
$ [[s]] -> [Natural # y] -> [([s], Natural # y)]
forall a b. [a] -> [b] -> [(a, b)]
zip [[s]]
yss [Natural # y]
yhts
     in Mean # f y x
df

-- | Turns a list of input/output pairs into a Map, by collecting into lists the
-- different outputs to each particular input.
conditionalDataMap
    :: Ord x
    => [(t, x)] -- ^ Output/Input Pairs
    -> M.Map x [t] -- ^ Input Output map
conditionalDataMap :: [(t, x)] -> Map x [t]
conditionalDataMap = (Map x [t] -> (t, x) -> Map x [t])
-> Map x [t] -> [(t, x)] -> Map x [t]
forall (t :: Type -> Type) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Map x [t] -> (t, x) -> Map x [t]
forall k a. Ord k => Map k [a] -> (a, k) -> Map k [a]
folder Map x [t]
forall k a. Map k a
M.empty
    where folder :: Map k [a] -> (a, k) -> Map k [a]
folder Map k [a]
mp (a
t,k
x) =
            let ts :: Maybe [a]
ts = k -> Map k [a] -> Maybe [a]
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup k
x Map k [a]
mp
                ts' :: [a]
ts' = [a] -> ([a] -> [a]) -> Maybe [a] -> [a]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [a
t] (a
ta -> [a] -> [a]
forall a. a -> [a] -> [a]
:) Maybe [a]
ts
             in k -> [a] -> Map k [a] -> Map k [a]
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert k
x [a]
ts' Map k [a]
mp
    --M.fromListWith (++) [(x, [y]) | (y, x) <- yxs]

-- | Partition a conditional dataset into k > 1 (training,validation) pairs,
-- where each dataset condition is partitioned to match its size.
kFoldMap
    :: Ord x => Int -> M.Map x [y] -> [(M.Map x [y], M.Map x [y])]
kFoldMap :: Int -> Map x [y] -> [(Map x [y], Map x [y])]
kFoldMap Int
k Map x [y]
ixzmp =
    let ixzmps :: Map x [([y], [y])]
ixzmps = Int -> [y] -> [([y], [y])]
forall x. Int -> [x] -> [([x], [x])]
kFold Int
k ([y] -> [([y], [y])]) -> Map x [y] -> Map x [([y], [y])]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Map x [y]
ixzmp
        ixs :: [x]
ixs = Map x [y] -> [x]
forall k a. Map k a -> [k]
M.keys Map x [y]
ixzmp
        tvzss :: [[([y], [y])]]
tvzss = Map x [([y], [y])] -> [[([y], [y])]]
forall k a. Map k a -> [a]
M.elems Map x [([y], [y])]
ixzmps
        tvxzmps :: [Map x ([y], [y])]
tvxzmps = [(x, ([y], [y]))] -> Map x ([y], [y])
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(x, ([y], [y]))] -> Map x ([y], [y]))
-> ([([y], [y])] -> [(x, ([y], [y]))])
-> [([y], [y])]
-> Map x ([y], [y])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [x] -> [([y], [y])] -> [(x, ([y], [y]))]
forall a b. [a] -> [b] -> [(a, b)]
zip [x]
ixs ([([y], [y])] -> Map x ([y], [y]))
-> [[([y], [y])]] -> [Map x ([y], [y])]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> [[([y], [y])]] -> [[([y], [y])]]
forall a. [[a]] -> [[a]]
L.transpose [[([y], [y])]]
tvzss
     in [Map x [y]] -> [Map x [y]] -> [(Map x [y], Map x [y])]
forall a b. [a] -> [b] -> [(a, b)]
zip ((([y], [y]) -> [y]) -> Map x ([y], [y]) -> Map x [y]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap ([y], [y]) -> [y]
forall a b. (a, b) -> a
fst (Map x ([y], [y]) -> Map x [y])
-> [Map x ([y], [y])] -> [Map x [y]]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> [Map x ([y], [y])]
tvxzmps) ((([y], [y]) -> [y]) -> Map x ([y], [y]) -> Map x [y]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap ([y], [y]) -> [y]
forall a b. (a, b) -> b
snd (Map x ([y], [y]) -> Map x [y])
-> [Map x ([y], [y])] -> [Map x [y]]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> [Map x ([y], [y])]
tvxzmps)

-- | Partition a conditional dataset into k > 2 (training,test,validation) triplets,
-- where each dataset condition is partitioned to match its size.
kFoldMap'
    :: Ord x => Int -> M.Map x [y] -> [(M.Map x [y], M.Map x [y], M.Map x [y])]
kFoldMap' :: Int -> Map x [y] -> [(Map x [y], Map x [y], Map x [y])]
kFoldMap' Int
k Map x [y]
ixzmp =
    let ixzmps :: Map x [([y], [y], [y])]
ixzmps = Int -> [y] -> [([y], [y], [y])]
forall x. Int -> [x] -> [([x], [x], [x])]
kFold' Int
k ([y] -> [([y], [y], [y])]) -> Map x [y] -> Map x [([y], [y], [y])]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Map x [y]
ixzmp
        ixs :: [x]
ixs = Map x [y] -> [x]
forall k a. Map k a -> [k]
M.keys Map x [y]
ixzmp
        tvzss :: [[([y], [y], [y])]]
tvzss = Map x [([y], [y], [y])] -> [[([y], [y], [y])]]
forall k a. Map k a -> [a]
M.elems Map x [([y], [y], [y])]
ixzmps
        tvxzmps :: [Map x ([y], [y], [y])]
tvxzmps = [(x, ([y], [y], [y]))] -> Map x ([y], [y], [y])
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(x, ([y], [y], [y]))] -> Map x ([y], [y], [y]))
-> ([([y], [y], [y])] -> [(x, ([y], [y], [y]))])
-> [([y], [y], [y])]
-> Map x ([y], [y], [y])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [x] -> [([y], [y], [y])] -> [(x, ([y], [y], [y]))]
forall a b. [a] -> [b] -> [(a, b)]
zip [x]
ixs ([([y], [y], [y])] -> Map x ([y], [y], [y]))
-> [[([y], [y], [y])]] -> [Map x ([y], [y], [y])]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> [[([y], [y], [y])]] -> [[([y], [y], [y])]]
forall a. [[a]] -> [[a]]
L.transpose [[([y], [y], [y])]]
tvzss
     in [Map x [y]]
-> [Map x [y]]
-> [Map x [y]]
-> [(Map x [y], Map x [y], Map x [y])]
forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 ((([y], [y], [y]) -> [y]) -> Map x ([y], [y], [y]) -> Map x [y]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (\([y]
x,[y]
_,[y]
_) -> [y]
x) (Map x ([y], [y], [y]) -> Map x [y])
-> [Map x ([y], [y], [y])] -> [Map x [y]]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> [Map x ([y], [y], [y])]
tvxzmps)
             ((([y], [y], [y]) -> [y]) -> Map x ([y], [y], [y]) -> Map x [y]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (\([y]
_,[y]
x,[y]
_) -> [y]
x) (Map x ([y], [y], [y]) -> Map x [y])
-> [Map x ([y], [y], [y])] -> [Map x [y]]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> [Map x ([y], [y], [y])]
tvxzmps)
             ((([y], [y], [y]) -> [y]) -> Map x ([y], [y], [y]) -> Map x [y]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (\([y]
_,[y]
_,[y]
x) -> [y]
x) (Map x ([y], [y], [y]) -> Map x [y])
-> [Map x ([y], [y], [y])] -> [Map x [y]]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> [Map x ([y], [y], [y])]
tvxzmps)

--mapToConditionalData :: M.Map x [y] -> [(y,x)]
--mapToConditionalData mp =
--    let (xs,zss) = unzip $ M.toAscList mp
--     in concat $ zipWith (\x zs -> zip zs $ repeat x) xs zss


-- | The conditional 'logLikelihood' for a conditional distribution.
conditionalLogLikelihood
    :: (ExponentialFamily x, Map Natural f y x, LogLikelihood Natural y t)
    => [(t, SamplePoint x)] -- ^ Output/Input Pairs
    -> Natural # f y x -- ^ Function
    -> Double -- ^ conditional cross entropy estimate
conditionalLogLikelihood :: [(t, SamplePoint x)] -> (Natural # f y x) -> Double
conditionalLogLikelihood [(t, SamplePoint x)]
yxs Natural # f y x
f =
    let ysxs :: [([t], Mean # x)]
ysxs = [ ([t
y],SamplePoint x -> Mean # x
forall x. ExponentialFamily x => SamplePoint x -> Mean # x
sufficientStatistic SamplePoint x
x) | (t
y,SamplePoint x
x) <- [(t, SamplePoint x)]
yxs ]
     in [([t], Mean # x)] -> (Natural # f y x) -> Double
forall y s (f :: Type -> Type -> Type) x.
(LogLikelihood Natural y s, Map Natural f y x) =>
[([s], Mean # x)] -> (Natural # f y x) -> Double
dependantLogLikelihood [([t], Mean # x)]
ysxs Natural # f y x
f

-- | The conditional 'logLikelihoodDifferential' for a conditional distribution.
conditionalLogLikelihoodDifferential
    :: ( ExponentialFamily x, LogLikelihood Natural y t, Propagate Natural f y x )
    => [(t, SamplePoint x)] -- ^ Output/Input Pairs
    -> Natural # f y x -- ^ Function
    -> Mean # f y x -- ^ Differential
conditionalLogLikelihoodDifferential :: [(t, SamplePoint x)] -> (Natural # f y x) -> Mean # f y x
conditionalLogLikelihoodDifferential [(t, SamplePoint x)]
yxs Natural # f y x
f =
    let ysxs :: [([t], Mean # x)]
ysxs = [ ([t
y],SamplePoint x -> Mean # x
forall x. ExponentialFamily x => SamplePoint x -> Mean # x
sufficientStatistic SamplePoint x
x) | (t
y,SamplePoint x
x) <- [(t, SamplePoint x)]
yxs ]
     in [([t], Mean # x)] -> (Natural # f y x) -> Mean # f y x
forall y s (f :: Type -> Type -> Type) x.
(LogLikelihood Natural y s, Propagate Natural f y x) =>
[([s], Mean # x)] -> (Natural # f y x) -> Mean # f y x
dependantLogLikelihoodDifferential [([t], Mean # x)]
ysxs Natural # f y x
f

-- | The conditional 'logLikelihood' for a conditional distribution, where
-- redundant conditions/inputs are combined. This can dramatically increase performance when
-- the number of distinct conditions/inputs is small.
mapConditionalLogLikelihood
    :: ( ExponentialFamily x, Map Natural f y x, LogLikelihood Natural y t )
    => M.Map (SamplePoint x) [t] -- ^ Output/Input Pairs
    -> Natural # f y x -- ^ Function
    -> Double -- ^ conditional cross entropy estimate
mapConditionalLogLikelihood :: Map (SamplePoint x) [t] -> (Natural # f y x) -> Double
mapConditionalLogLikelihood Map (SamplePoint x) [t]
xtsmp =
     [([t], Mean # x)] -> (Natural # f y x) -> Double
forall y s (f :: Type -> Type -> Type) x.
(LogLikelihood Natural y s, Map Natural f y x) =>
[([s], Mean # x)] -> (Natural # f y x) -> Double
dependantLogLikelihood [ ([t]
ts, SamplePoint x -> Mean # x
forall x. ExponentialFamily x => SamplePoint x -> Mean # x
sufficientStatistic SamplePoint x
x) | (SamplePoint x
x,[t]
ts) <- Map (SamplePoint x) [t] -> [(SamplePoint x, [t])]
forall k a. Map k a -> [(k, a)]
M.toList Map (SamplePoint x) [t]
xtsmp]

-- | The conditional 'logLikelihoodDifferential', where redundant conditions are
-- combined. This can dramatically increase performance when the number of
-- distinct conditions is small.
mapConditionalLogLikelihoodDifferential
    :: ( ExponentialFamily x, LogLikelihood Natural y t
       , Propagate Natural f y x, Ord (SamplePoint x) )
    => M.Map (SamplePoint x) [t] -- ^ Output/Input Pairs
    -> Natural # f y x -- ^ Function
    -> Mean # f y x -- ^ Differential
mapConditionalLogLikelihoodDifferential :: Map (SamplePoint x) [t] -> (Natural # f y x) -> Mean # f y x
mapConditionalLogLikelihoodDifferential Map (SamplePoint x) [t]
xtsmp =
     [([t], Mean # x)] -> (Natural # f y x) -> Mean # f y x
forall y s (f :: Type -> Type -> Type) x.
(LogLikelihood Natural y s, Propagate Natural f y x) =>
[([s], Mean # x)] -> (Natural # f y x) -> Mean # f y x
dependantLogLikelihoodDifferential [ ([t]
ts, SamplePoint x -> Mean # x
forall x. ExponentialFamily x => SamplePoint x -> Mean # x
sufficientStatistic SamplePoint x
x) | (SamplePoint x
x,[t]
ts) <- Map (SamplePoint x) [t] -> [(SamplePoint x, [t])]
forall k a. Map k a -> [(k, a)]
M.toList Map (SamplePoint x) [t]
xtsmp]

-- | The conditional 'logLikelihood' for a conditional distribution, where
-- redundant conditions/inputs are combined. This can dramatically increase performance when
-- the number of distinct conditions/inputs is small.
parMapConditionalLogLikelihood
    :: ( ExponentialFamily x, Map Natural f y x, LogLikelihood Natural y t )
    => M.Map (SamplePoint x) [t] -- ^ Output/Input Pairs
    -> Natural # f y x -- ^ Function
    -> Double -- ^ conditional cross entropy estimate
parMapConditionalLogLikelihood :: Map (SamplePoint x) [t] -> (Natural # f y x) -> Double
parMapConditionalLogLikelihood Map (SamplePoint x) [t]
xtsmp =
     [([t], Mean # x)] -> (Natural # f y x) -> Double
forall y s (f :: Type -> Type -> Type) x.
(LogLikelihood Natural y s, Map Natural f y x) =>
[([s], Mean # x)] -> (Natural # f y x) -> Double
dependantLogLikelihoodPar [ ([t]
ts, SamplePoint x -> Mean # x
forall x. ExponentialFamily x => SamplePoint x -> Mean # x
sufficientStatistic SamplePoint x
x) | (SamplePoint x
x,[t]
ts) <- Map (SamplePoint x) [t] -> [(SamplePoint x, [t])]
forall k a. Map k a -> [(k, a)]
M.toList Map (SamplePoint x) [t]
xtsmp]

-- | The conditional 'logLikelihoodDifferential', where redundant conditions are
-- combined. This can dramatically increase performance when the number of
-- distinct conditions is small.
parMapConditionalLogLikelihoodDifferential
    :: ( ExponentialFamily x, LogLikelihood Natural y t
       , Propagate Natural f y x, Ord (SamplePoint x) )
    => M.Map (SamplePoint x) [t] -- ^ Output/Input Pairs
    -> Natural # f y x -- ^ Function
    -> Mean # f y x -- ^ Differential
parMapConditionalLogLikelihoodDifferential :: Map (SamplePoint x) [t] -> (Natural # f y x) -> Mean # f y x
parMapConditionalLogLikelihoodDifferential Map (SamplePoint x) [t]
xtsmp =
     [([t], Mean # x)] -> (Natural # f y x) -> Mean # f y x
forall y s (f :: Type -> Type -> Type) x.
(LogLikelihood Natural y s, Propagate Natural f y x) =>
[([s], Mean # x)] -> (Natural # f y x) -> Mean # f y x
dependantLogLikelihoodDifferentialPar [ ([t]
ts, SamplePoint x -> Mean # x
forall x. ExponentialFamily x => SamplePoint x -> Mean # x
sufficientStatistic SamplePoint x
x) | (SamplePoint x
x,[t]
ts) <- Map (SamplePoint x) [t] -> [(SamplePoint x, [t])]
forall k a. Map k a -> [(k, a)]
M.toList Map (SamplePoint x) [t]
xtsmp]