rhine-bayes-0.9: src/Data/MonadicStreamFunction/Bayes.hs
module Data.MonadicStreamFunction.Bayes where
-- base
import Control.Arrow
import Data.Functor (($>))
import Data.Tuple (swap)
-- transformers
-- log-domain
import Numeric.Log hiding (sum)
-- monad-bayes
import Control.Monad.Bayes.Population
-- dunai
import Data.MonadicStreamFunction
import Data.MonadicStreamFunction.InternalCore (MSF (..))
-- | Run the Sequential Monte Carlo algorithm continuously on an 'MSF'
runPopulationS ::
forall m a b.
Monad m =>
-- | Number of particles
Int ->
-- | Resampler
(forall x. Population m x -> Population m x) ->
MSF (Population m) a b ->
-- FIXME Why not MSF m a (Population b)
MSF m a [(b, Log Double)]
runPopulationS nParticles resampler = runPopulationsS resampler . (spawn nParticles $>)
-- | Run the Sequential Monte Carlo algorithm continuously on a 'Population' of 'MSF's
runPopulationsS ::
Monad m =>
-- | Resampler
(forall x. Population m x -> Population m x) ->
Population m (MSF (Population m) a b) ->
MSF m a [(b, Log Double)]
runPopulationsS resampler = go
where
go msfs = MSF $ \a -> do
-- TODO This is quite different than the dunai version now. Maybe it's right nevertheless.
-- FIXME This normalizes, which introduces bias, whatever that means
bAndMSFs <- runPopulation $ normalize $ resampler $ flip unMSF a =<< msfs
return $
second (go . fromWeightedList . return) $
unzip $
(swap . fmap fst &&& swap . fmap snd) . swap <$> bAndMSFs
-- FIXME see PR re-adding this to monad-bayes
normalize :: Monad m => Population m a -> Population m a
normalize = fromWeightedList . fmap (\particles -> second (/ (sum $ snd <$> particles)) <$> particles) . runPopulation