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