monad-bayes 1.0.0 → 1.1.0
raw patch · 42 files changed
+319/−240 lines, 42 filesdep ~brick
Dependency ranges changed: brick
Files
- CHANGELOG.md +1/−1
- README.md +70/−0
- benchmark/Single.hs +2/−2
- benchmark/Speed.hs +2/−2
- models/BetaBin.hs +7/−7
- models/ConjugatePriors.hs +7/−7
- models/Dice.hs +7/−7
- models/HMM.hs +11/−11
- models/LDA.hs +6/−6
- models/LogReg.hs +4/−4
- models/NonlinearSSM.hs +5/−5
- models/Sprinkler.hs +2/−2
- monad-bayes.cabal +10/−5
- src/Control/Monad/Bayes/Class.hs +43/−42
- src/Control/Monad/Bayes/Density/Free.hs +5/−5
- src/Control/Monad/Bayes/Density/State.hs +2/−2
- src/Control/Monad/Bayes/Enumerator.hs +7/−7
- src/Control/Monad/Bayes/Inference/MCMC.hs +11/−6
- src/Control/Monad/Bayes/Inference/PMMH.hs +4/−4
- src/Control/Monad/Bayes/Inference/RMSMC.hs +4/−4
- src/Control/Monad/Bayes/Inference/SMC.hs +3/−3
- src/Control/Monad/Bayes/Inference/SMC2.hs +7/−7
- src/Control/Monad/Bayes/Inference/TUI.hs +7/−9
- src/Control/Monad/Bayes/Integrator.hs +3/−3
- src/Control/Monad/Bayes/Population.hs +13/−13
- src/Control/Monad/Bayes/Sampler/Lazy.hs +2/−2
- src/Control/Monad/Bayes/Sampler/Strict.hs +4/−4
- src/Control/Monad/Bayes/Sequential/Coroutine.hs +6/−6
- src/Control/Monad/Bayes/Traced/Basic.hs +8/−8
- src/Control/Monad/Bayes/Traced/Common.hs +5/−5
- src/Control/Monad/Bayes/Traced/Dynamic.hs +8/−8
- src/Control/Monad/Bayes/Traced/Static.hs +8/−8
- src/Control/Monad/Bayes/Weighted.hs +9/−9
- test/TestAdvanced.hs +1/−1
- test/TestDistribution.hs +1/−1
- test/TestEnumerator.hs +3/−3
- test/TestInference.hs +2/−2
- test/TestIntegrator.hs +5/−5
- test/TestPopulation.hs +3/−3
- test/TestSampler.hs +1/−1
- test/TestSequential.hs +6/−6
- test/TestWeighted.hs +4/−4
CHANGELOG.md view
@@ -22,7 +22,7 @@ Addition of new helper functions, plotting tools, tests, and Integrator monad. - helpers include: `toEmpirical` (list of samples to empirical distribution) and `toBins` (simple histogramming)-- `Integrator` is an instance of `MonadSample` for numerical integration+- `Integrator` is an instance of `MonadDistribution` for numerical integration - `notebooks` now contains working notebook-based tutorials and examples - new tests, including with conjugate distributions to compare analytic solution against inferred posterior - `models` directory is cleaned up. New sequential models using `pipes` package to represent monadic streams
+ README.md view
@@ -0,0 +1,70 @@+# [Monad-Bayes](https://monad-bayes-site.netlify.app/_site/about.html)++A library for probabilistic programming in Haskell. ++<!-- [](https://hackage.haskell.org/package/monad-bayes)+[](http://stackage.org/lts/package/monad-bayes)+[](http://packdeps.haskellers.com/reverse/monad-bayes)+[](https://buildkite.com/tweag-1/monad-bayes) -->++[See the website](https://monad-bayes-site.netlify.app/_site/about.html) for an overview of the documentation, library, tutorials, examples (and a link to this very source code). ++<!-- Monad-Bayes is a library for **probabilistic programming in Haskell**. The emphasis is on composition of inference algorithms, and is implemented in terms of monad transformers. -->++<!-- See the [documentation](https://monad-bayes.netlify.app/) for a quick-start user guide and a reference overview of how it all works. -->++Created by [Adam Scibior][adam-web] ([@adscib][adam-github]), documentation, website and newer features by [Reuben][reuben-web], maintained by [Tweag][tweagio].++## Project status++Now that `monad-bayes` has been released on Hackage, and the documentation and the API has been updated, we will focus on adding new features. See the Github issues to get a sense of what is being prepared, and please feel free to make requests.++## Background++The basis for the code in this repository is the ICFP 2018 paper [2]. For the+code associated with the Haskell2015 paper [1], see the [`haskell2015`+tag][haskell2015-tag].++[1] Adam M. Ścibior, Zoubin Ghahramani, and Andrew D. Gordon. 2015. [Practical+probabilistic programming with monads][haskell2015-doi]. In _Proceedings of the+2015 ACM SIGPLAN Symposium on Haskell_ (Haskell ’15), Association for Computing+Machinery, Vancouver, BC, Canada, 165–176.++[2] Adam M. Ścibior, Ohad Kammar, and Zoubin Ghahramani. 2018. [Functional+programming for modular Bayesian inference][icfp2018-doi]. In _Proceedings of+the ACM on Programming Languages_ Volume 2, ICFP (July 2018), 83:1–83:29.++[3] Adam M. Ścibior. 2019. [Formally justified and modular Bayesian inference+for probabilistic programs][thesis-doi]. Thesis. University of Cambridge.++## Hacking++1. Install `stack` by following [these instructions][stack-install].++2. Clone the repository using one of these URLs:+ ```+ git clone git@github.com:tweag/monad-bayes.git+ git clone https://github.com/tweag/monad-bayes.git+ ```++Now you can use `stack build`, `stack test` and `stack ghci`.++**To view the notebooks, go to the website**. To use the notebooks interactively:++1. Compile the source: `stack build`+2. If you do not have `nix` [install it](https://nixos.org/download.html).+3. Run `nix develop --system x86_64-darwin --extra-experimental-features nix-command --extra-experimental-features flakes` - this should open a nix shell. For Linux use `x86_64-linux` for `--system` option instead. +4. Run `jupyter-lab` from the nix shell to load the notebooks.++Your mileage may vary. ++[adam-github]: https://github.com/adscib+[adam-web]: https://www.cs.ubc.ca/~ascibior/+[reuben-web]: https://reubencohngordon.com/+[haskell2015-doi]: https://doi.org/10.1145/2804302.2804317+[haskell2015-tag]: https://github.com/tweag/monad-bayes/tree/haskell2015+[icfp2018-doi]: https://doi.org/10.1145/3236778+[models]: https://github.com/tweag/monad-bayes/tree/master/models+[stack-install]: https://docs.haskellstack.org/en/stable/install_and_upgrade/+[thesis-doi]: https://doi.org/10.17863/CAM.42233+[tweagio]: https://tweag.io
benchmark/Single.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE ImportQualifiedPost #-} -import Control.Monad.Bayes.Class (MonadInfer)+import Control.Monad.Bayes.Class (MonadMeasure) import Control.Monad.Bayes.Inference.MCMC (MCMCConfig (..), Proposal (SingleSiteMH)) import Control.Monad.Bayes.Inference.RMSMC (rmsmcBasic) import Control.Monad.Bayes.Inference.SMC@@ -42,7 +42,7 @@ 'L' : 'D' : 'A' : n -> Just $ LDA (5, read n) _ -> Nothing -getModel :: MonadInfer m => Model -> (Int, m String)+getModel :: MonadMeasure m => Model -> (Int, m String) getModel model = (size model, program model) where size (LR n) = n
benchmark/Speed.hs view
@@ -4,7 +4,7 @@ module Main (main) where -import Control.Monad.Bayes.Class (MonadInfer, MonadSample)+import Control.Monad.Bayes.Class (MonadDistribution, MonadMeasure) import Control.Monad.Bayes.Inference.MCMC (MCMCConfig (MCMCConfig, numBurnIn, numMCMCSteps, proposal), Proposal (SingleSiteMH)) import Control.Monad.Bayes.Inference.RMSMC (rmsmcDynamic) import Control.Monad.Bayes.Inference.SMC (SMCConfig (SMCConfig, numParticles, numSteps, resampler), smc)@@ -39,7 +39,7 @@ show (HMM xs) = "HMM" ++ show (length xs) show (LDA xs) = "LDA" ++ show (length $ head xs) -buildModel :: MonadInfer m => Model -> m String+buildModel :: MonadMeasure m => Model -> m String buildModel (LR dataset) = show <$> LogReg.logisticRegression dataset buildModel (HMM dataset) = show <$> HMM.hmm dataset buildModel (LDA dataset) = show <$> LDA.lda dataset
models/BetaBin.hs view
@@ -8,8 +8,8 @@ -- The two formulations should be exactly equivalent, but only urn works with Dist. import Control.Monad (replicateM) import Control.Monad.Bayes.Class- ( MonadInfer,- MonadSample (bernoulli, uniform),+ ( MonadDistribution (bernoulli, uniform),+ MonadMeasure, condition, ) import Control.Monad.State.Lazy (evalStateT, get, put)@@ -17,14 +17,14 @@ import Pipes.Prelude qualified as P hiding (show) -- | Beta-binomial model as an i.i.d. sequence conditionally on weight.-latent :: MonadSample m => Int -> m [Bool]+latent :: MonadDistribution m => Int -> m [Bool] latent n = do weight <- uniform 0 1 replicateM n (bernoulli weight) -- | Beta-binomial as a random process. -- Equivalent to the above by De Finetti's theorem.-urn :: MonadSample m => Int -> m [Bool]+urn :: MonadDistribution m => Int -> m [Bool] urn n = flip evalStateT (1, 1) $ do replicateM n do (a, b) <- get@@ -36,7 +36,7 @@ -- | Beta-binomial as a random process. -- This time using the Pipes library, for a more pure functional style-urnP :: MonadSample m => Int -> m [Bool]+urnP :: MonadDistribution m => Int -> m [Bool] urnP n = P.toListM $ P.take n <-< P.unfoldr toss (1, 1) where toss (a, b) = do@@ -47,7 +47,7 @@ -- | A beta-binomial model where the first three states are True,True,False. -- The resulting distribution is on the remaining outcomes.-cond :: MonadInfer m => m [Bool] -> m [Bool]+cond :: MonadMeasure m => m [Bool] -> m [Bool] cond d = do ~(first : second : third : rest) <- d condition first@@ -56,7 +56,7 @@ return rest -- | The final conditional model, abstracting the representation.-model :: MonadInfer m => (Int -> m [Bool]) -> Int -> m Int+model :: MonadMeasure m => (Int -> m [Bool]) -> Int -> m Int model repr n = fmap count $ cond $ repr (n + 3) where -- Post-processing by counting the number of True values.
models/ConjugatePriors.hs view
@@ -7,7 +7,7 @@ import Control.Applicative (Applicative (liftA2)) import Control.Foldl (fold) import Control.Foldl qualified as F-import Control.Monad.Bayes.Class (Bayesian (..), MonadInfer, MonadSample (bernoulli, beta, gamma, normal), normalPdf)+import Control.Monad.Bayes.Class (Bayesian (..), MonadDistribution (bernoulli, beta, gamma, normal), MonadMeasure, normalPdf) import Numeric.Log (Log (Exp)) import Prelude @@ -19,7 +19,7 @@ -- | Posterior on the precision of the normal after the points are observed gammaNormalAnalytic ::- (MonadInfer m, Foldable t, Functor t) =>+ (MonadMeasure m, Foldable t, Functor t) => GammaParams -> t Double -> m Double@@ -34,7 +34,7 @@ b' = b + sum (fmap (** 2) points) / 2 -- | Posterior on beta after the bernoulli sample-betaBernoulliAnalytic :: (MonadInfer m, Foldable t) => BetaParams -> t Bool -> m Double+betaBernoulliAnalytic :: (MonadMeasure m, Foldable t) => BetaParams -> t Bool -> m Double betaBernoulliAnalytic (a, b) points = beta a' b' where (n, s) = fold (liftA2 (,) F.length (F.premap (\case True -> 1; False -> 0) F.sum)) points@@ -44,17 +44,17 @@ bernoulliPdf :: Floating a => a -> Bool -> Log a bernoulliPdf p x = let numBool = if x then 1.0 else 0 in Exp $ log (p ** numBool * (1 - p) ** (1 - numBool)) -betaBernoulli' :: MonadInfer m => (Double, Double) -> Bayesian m Double Bool+betaBernoulli' :: MonadMeasure m => (Double, Double) -> Bayesian m Double Bool betaBernoulli' (a, b) = Bayesian (beta a b) bernoulli bernoulliPdf -normalNormal' :: MonadInfer m => Double -> (Double, Double) -> Bayesian m Double Double+normalNormal' :: MonadMeasure m => Double -> (Double, Double) -> Bayesian m Double Double normalNormal' var (mu0, var0) = Bayesian (normal mu0 (sqrt var0)) (`normal` (sqrt var)) (`normalPdf` (sqrt var)) -gammaNormal' :: MonadInfer m => (Double, Double) -> Bayesian m Double Double+gammaNormal' :: MonadMeasure m => (Double, Double) -> Bayesian m Double Double gammaNormal' (a, b) = Bayesian (gamma a (recip b)) (normal 0 . sqrt . recip) (normalPdf 0 . sqrt . recip) normalNormalAnalytic ::- (MonadInfer m, Foldable t) =>+ (MonadMeasure m, Foldable t) => Double -> NormalParams -> t Double ->
models/Dice.hs view
@@ -5,30 +5,30 @@ import Control.Applicative (liftA2) import Control.Monad.Bayes.Class- ( MonadCond (score),- MonadInfer,- MonadSample (uniformD),+ ( MonadDistribution (uniformD),+ MonadFactor (score),+ MonadMeasure, condition, ) -- | A toss of a six-sided die.-die :: MonadSample m => m Int+die :: MonadDistribution m => m Int die = uniformD [1 .. 6] -- | A sum of outcomes of n independent tosses of six-sided dice.-dice :: MonadSample m => Int -> m Int+dice :: MonadDistribution m => Int -> m Int dice 1 = die dice n = liftA2 (+) die (dice (n - 1)) -- | Toss of two dice where the output is greater than 4.-diceHard :: MonadInfer m => m Int+diceHard :: MonadMeasure m => m Int diceHard = do result <- dice 2 condition (result > 4) return result -- | Toss of two dice with an artificial soft constraint.-diceSoft :: MonadInfer m => m Int+diceSoft :: MonadMeasure m => m Int diceSoft = do result <- dice 2 score (1 / fromIntegral result)
models/HMM.hs view
@@ -4,9 +4,9 @@ import Control.Monad (replicateM, when) import Control.Monad.Bayes.Class- ( MonadCond,- MonadInfer,- MonadSample (categorical, normal, uniformD),+ ( MonadDistribution (categorical, normal, uniformD),+ MonadFactor,+ MonadMeasure, factor, normalPdf, )@@ -39,7 +39,7 @@ ] -- | The transition model.-trans :: MonadSample m => Int -> m Int+trans :: MonadDistribution m => Int -> m Int trans 0 = categorical $ fromList [0.1, 0.4, 0.5] trans 1 = categorical $ fromList [0.2, 0.6, 0.2] trans 2 = categorical $ fromList [0.15, 0.7, 0.15]@@ -53,11 +53,11 @@ emissionMean _ = error "unreachable" -- | Initial state distribution-start :: MonadSample m => m Int+start :: MonadDistribution m => m Int start = uniformD [0, 1, 2] -- | Example HMM from http://dl.acm.org/citation.cfm?id=2804317-hmm :: (MonadInfer m) => [Double] -> m [Int]+hmm :: (MonadMeasure m) => [Double] -> m [Int] hmm dataset = f dataset (const . return) where expand x y = do@@ -67,7 +67,7 @@ f [] k = start >>= k [] f (y : ys) k = f ys (\xs x -> expand x y >>= k (x : xs)) -syntheticData :: MonadSample m => Int -> m [Double]+syntheticData :: MonadDistribution m => Int -> m [Double] syntheticData n = replicateM n syntheticPoint where syntheticPoint = uniformD [0, 1, 2]@@ -75,7 +75,7 @@ -- | Equivalent model, but using pipes for simplicity -- | Prior expressed as a stream-hmmPrior :: MonadSample m => Producer Int m b+hmmPrior :: MonadDistribution m => Producer Int m b hmmPrior = do x <- lift start yield x@@ -86,19 +86,19 @@ hmmObservations dataset = each (Nothing : (Just <$> reverse dataset)) -- | Posterior expressed as a stream-hmmPosterior :: (MonadInfer m) => [Double] -> Producer Int m ()+hmmPosterior :: (MonadMeasure m) => [Double] -> Producer Int m () hmmPosterior dataset = zipWithM hmmLikelihood hmmPrior (hmmObservations dataset) where- hmmLikelihood :: MonadCond f => (Int, Maybe Double) -> f ()+ hmmLikelihood :: MonadFactor f => (Int, Maybe Double) -> f () hmmLikelihood (l, o) = when (isJust o) (factor $ normalPdf (emissionMean l) 1 (fromJust o)) zipWithM f p1 p2 = Pipes.zip p1 p2 >-> Pipes.chain f >-> Pipes.map fst -hmmPosteriorPredictive :: MonadSample m => [Double] -> Producer Double m ()+hmmPosteriorPredictive :: MonadDistribution m => [Double] -> Producer Double m () hmmPosteriorPredictive dataset = Pipes.hoist enumerateToDistribution (hmmPosterior dataset) >-> Pipes.mapM (\x -> normal (emissionMean x) 1)
models/LDA.hs view
@@ -11,8 +11,8 @@ import Control.Monad qualified as List (replicateM) import Control.Monad.Bayes.Class- ( MonadInfer,- MonadSample (categorical, dirichlet, uniformD),+ ( MonadDistribution (categorical, dirichlet, uniformD),+ MonadMeasure, factor, ) import Control.Monad.Bayes.Sampler.Strict (sampleIO, sampleIOfixed)@@ -43,17 +43,17 @@ words "bear wolf bear python bear wolf bear wolf bear wolf" ] -wordDistPrior :: MonadSample m => m (V.Vector Double)+wordDistPrior :: MonadDistribution m => m (V.Vector Double) wordDistPrior = dirichlet $ V.replicate (length vocabulary) 1 -topicDistPrior :: MonadSample m => m (V.Vector Double)+topicDistPrior :: MonadDistribution m => m (V.Vector Double) topicDistPrior = dirichlet $ V.replicate (length topics) 1 wordIndex :: Map.Map Text Int wordIndex = Map.fromList $ zip vocabulary [0 ..] lda ::- MonadInfer m =>+ MonadMeasure m => Documents -> m (Map.Map Text (V.Vector (Text, Double)), [(Text, V.Vector (Text, Double))]) lda docs = do@@ -73,7 +73,7 @@ zip (fmap (foldr1 (\x y -> x <> " " <> y)) docs) (fmap (V.zip $ V.fromList ["topic1", "topic2"]) td) ) -syntheticData :: MonadSample m => Int -> Int -> m [[Text]]+syntheticData :: MonadDistribution m => Int -> Int -> m [[Text]] syntheticData d w = List.replicateM d (List.replicateM w syntheticWord) where syntheticWord = uniformD vocabulary
models/LogReg.hs view
@@ -7,13 +7,13 @@ import Control.Monad (replicateM) import Control.Monad.Bayes.Class- ( MonadInfer,- MonadSample (bernoulli, gamma, normal, uniform),+ ( MonadDistribution (bernoulli, gamma, normal, uniform),+ MonadMeasure, factor, ) import Numeric.Log (Log (Exp)) -logisticRegression :: MonadInfer m => [(Double, Bool)] -> m Double+logisticRegression :: MonadMeasure m => [(Double, Bool)] -> m Double logisticRegression dat = do m <- normal 0 1 b <- normal 0 1@@ -27,7 +27,7 @@ sigmoid 8 -- make a synthetic dataset by randomly choosing input-label pairs-syntheticData :: MonadSample m => Int -> m [(Double, Bool)]+syntheticData :: MonadDistribution m => Int -> m [(Double, Bool)] syntheticData n = replicateM n do x <- uniform (-1) 1 label <- bernoulli 0.5
models/NonlinearSSM.hs view
@@ -1,13 +1,13 @@ module NonlinearSSM where import Control.Monad.Bayes.Class- ( MonadInfer,- MonadSample (gamma, normal),+ ( MonadDistribution (gamma, normal),+ MonadMeasure, factor, normalPdf, ) -param :: MonadSample m => m (Double, Double)+param :: MonadDistribution m => m (Double, Double) param = do let a = 0.01 let b = 0.01@@ -23,7 +23,7 @@ -- | A nonlinear series model from Doucet et al. (2000) -- "On sequential Monte Carlo sampling methods" section VI.B model ::- (MonadInfer m) =>+ (MonadMeasure m) => -- | observed data [Double] -> -- | prior on the parameters@@ -43,7 +43,7 @@ return $ reverse xs generateData ::- MonadSample m =>+ MonadDistribution m => -- | T Int -> -- | list of latent and observable states from t=1
models/Sprinkler.hs view
@@ -3,7 +3,7 @@ import Control.Monad (when) import Control.Monad.Bayes.Class -hard :: MonadInfer m => m Bool+hard :: MonadMeasure m => m Bool hard = do rain <- bernoulli 0.3 sprinkler <- bernoulli $ if rain then 0.1 else 0.4@@ -15,7 +15,7 @@ condition (not wet) return rain -soft :: MonadInfer m => m Bool+soft :: MonadMeasure m => m Bool soft = do rain <- bernoulli 0.3 when rain (factor 0.2)
monad-bayes.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.0 name: monad-bayes-version: 1.0.0+version: 1.1.0 license: MIT license-file: LICENSE.md copyright: 2015-2020 Adam Scibior@@ -15,10 +15,15 @@ A library for probabilistic programming using probability monads. The emphasis is on composition of inference algorithms implemented in terms of monad transformers.+ Please refer to the [documentation](https://monad-bayes.netlify.app/)+ for a quick-start user guide and a reference overview of how it all+ works" and the included [README](#readme). category: Statistics build-type: Simple-extra-source-files: CHANGELOG.md+extra-source-files:+ CHANGELOG.md+ README.md source-repository head type: git@@ -60,7 +65,7 @@ default-language: Haskell2010 build-depends: base >=4.11 && <4.17- , brick+ , brick >=1.0 && <2.0 , containers >=0.5.10 && <0.7 , foldl , free >=5.0.2 && <5.2@@ -97,7 +102,7 @@ if flag(dev) ghc-options:- -O2 -Wall -Wno-missing-local-signatures -Wno-trustworthy-safe+ -Wall -Wno-missing-local-signatures -Wno-trustworthy-safe -Wno-missing-import-lists -Wno-implicit-prelude -Wno-monomorphism-restriction @@ -131,7 +136,7 @@ if flag(dev) ghc-options:- -O2 -Wall -Wcompat -Wincomplete-record-updates+ -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wnoncanonical-monad-instances else
src/Control/Monad/Bayes/Class.hs view
@@ -12,14 +12,14 @@ -- Stability : experimental -- Portability : GHC ----- This module defines 'MonadInfer', which can be used to represent any probabilistic program,+-- This module defines 'MonadMeasure', which can be used to represent any probabilistic program, -- such as the following: -- -- @ -- import Control.Monad (when) -- import Control.Monad.Bayes.Class ----- model :: MonadInfer m => m Bool+-- model :: MonadMeasure m => m Bool -- model = do -- rain <- bernoulli 0.3 -- sprinkler <-@@ -37,7 +37,7 @@ -- return rain -- @ module Control.Monad.Bayes.Class- ( MonadSample,+ ( MonadDistribution, random, uniform, normal,@@ -50,11 +50,11 @@ geometric, poisson, dirichlet,- MonadCond,+ MonadFactor, score, factor, condition,- MonadInfer,+ MonadMeasure, discrete, normalPdf, Bayesian (..),@@ -106,7 +106,7 @@ import Statistics.Distribution.Uniform (uniformDistr) -- | Monads that can draw random variables.-class Monad m => MonadSample m where+class Monad m => MonadDistribution m where -- | Draw from a uniform distribution. random :: -- | \(\sim \mathcal{U}(0, 1)\)@@ -220,12 +220,12 @@ -- | Draw from a continuous distribution using the inverse cumulative density -- function.-draw :: (ContDistr d, MonadSample m) => d -> m Double+draw :: (ContDistr d, MonadDistribution m) => d -> m Double draw d = fmap (quantile d) random -- | Draw from a discrete distribution using a sequence of draws from -- Bernoulli.-fromPMF :: MonadSample m => (Int -> Double) -> m Int+fromPMF :: MonadDistribution m => (Int -> Double) -> m Int fromPMF p = f 0 1 where f i r = do@@ -236,11 +236,11 @@ if b then pure i else f (i + 1) (r - q) -- | Draw from a discrete distributions using the probability mass function.-discrete :: (DiscreteDistr d, MonadSample m) => d -> m Int+discrete :: (DiscreteDistr d, MonadDistribution m) => d -> m Int discrete = fromPMF . probability -- | Monads that can score different execution paths.-class Monad m => MonadCond m where+class Monad m => MonadFactor m where -- | Record a likelihood. score :: -- | likelihood of the execution path@@ -249,7 +249,7 @@ -- | Synonym for 'score'. factor ::- MonadCond m =>+ MonadFactor m => -- | likelihood of the execution path Log Double -> m ()@@ -257,21 +257,21 @@ -- | synonym for pretty type signatures, but note that (A -> Distribution B) won't work as intended: for that, use Kernel -- Also note that the use of RankNTypes means performance may take a hit: really the main point of these signatures is didactic-type Distribution a = forall m. MonadSample m => m a+type Distribution a = forall m. MonadDistribution m => m a -type Measure a = forall m. MonadInfer m => m a+type Measure a = forall m. MonadMeasure m => m a -type Kernel a b = forall m. MonadInfer m => a -> m b+type Kernel a b = forall m. MonadMeasure m => a -> m b -- | Hard conditioning.-condition :: MonadCond m => Bool -> m ()+condition :: MonadFactor m => Bool -> m () condition b = score $ if b then 1 else 0 independent :: Applicative m => Int -> m a -> m [a] independent = replicateM -- | Monads that support both sampling and scoring.-class (MonadSample m, MonadCond m) => MonadInfer m+class (MonadDistribution m, MonadFactor m) => MonadMeasure m -- | Probability density function of the normal distribution. normalPdf ::@@ -286,7 +286,7 @@ normalPdf mu sigma x = Exp $ logDensity (normalDistr mu sigma) x -- | multivariate normal-mvNormal :: MonadSample m => V.Vector Double -> Matrix Double -> m (V.Vector Double)+mvNormal :: MonadDistribution m => V.Vector Double -> Matrix Double -> m (V.Vector Double) mvNormal mu bigSigma = do let n = length mu ss <- replicateM n (normal 0 1)@@ -296,12 +296,13 @@ -- | a useful datatype for expressing bayesian models data Bayesian m z o = Bayesian- { prior :: m z, -- prior over latent variable Z- generative :: z -> m o, -- distribution over observations given Z=z+ { prior :: m z, -- prior over latent variable Z; p(z)+ generative :: z -> m o, -- distribution over observations given Z=z; p(o|Z=z) likelihood :: z -> o -> Log Double -- p(o|z) } -posterior :: (MonadInfer m, Foldable f, Functor f) => Bayesian m z o -> f o -> m z+-- | p(z|o)+posterior :: (MonadMeasure m, Foldable f, Functor f) => Bayesian m z o -> f o -> m z posterior Bayesian {..} os = do z <- prior factor $ product $ fmap (likelihood z) os@@ -311,7 +312,7 @@ priorPredictive bm = prior bm >>= generative bm posteriorPredictive ::- (MonadInfer m, Foldable f, Functor f) =>+ (MonadMeasure m, Foldable f, Functor f) => Bayesian m a b -> f b -> m b@@ -337,68 +338,68 @@ ---------------------------------------------------------------------------- -- Instances that lift probabilistic effects to standard tranformers. -instance MonadSample m => MonadSample (IdentityT m) where+instance MonadDistribution m => MonadDistribution (IdentityT m) where random = lift random bernoulli = lift . bernoulli -instance MonadCond m => MonadCond (IdentityT m) where+instance MonadFactor m => MonadFactor (IdentityT m) where score = lift . score -instance MonadInfer m => MonadInfer (IdentityT m)+instance MonadMeasure m => MonadMeasure (IdentityT m) -instance MonadSample m => MonadSample (ExceptT e m) where+instance MonadDistribution m => MonadDistribution (ExceptT e m) where random = lift random uniformD = lift . uniformD -instance MonadCond m => MonadCond (ExceptT e m) where+instance MonadFactor m => MonadFactor (ExceptT e m) where score = lift . score -instance MonadInfer m => MonadInfer (ExceptT e m)+instance MonadMeasure m => MonadMeasure (ExceptT e m) -instance MonadSample m => MonadSample (ReaderT r m) where+instance MonadDistribution m => MonadDistribution (ReaderT r m) where random = lift random bernoulli = lift . bernoulli -instance MonadCond m => MonadCond (ReaderT r m) where+instance MonadFactor m => MonadFactor (ReaderT r m) where score = lift . score -instance MonadInfer m => MonadInfer (ReaderT r m)+instance MonadMeasure m => MonadMeasure (ReaderT r m) -instance (Monoid w, MonadSample m) => MonadSample (WriterT w m) where+instance (Monoid w, MonadDistribution m) => MonadDistribution (WriterT w m) where random = lift random bernoulli = lift . bernoulli categorical = lift . categorical -instance (Monoid w, MonadCond m) => MonadCond (WriterT w m) where+instance (Monoid w, MonadFactor m) => MonadFactor (WriterT w m) where score = lift . score -instance (Monoid w, MonadInfer m) => MonadInfer (WriterT w m)+instance (Monoid w, MonadMeasure m) => MonadMeasure (WriterT w m) -instance MonadSample m => MonadSample (StateT s m) where+instance MonadDistribution m => MonadDistribution (StateT s m) where random = lift random bernoulli = lift . bernoulli categorical = lift . categorical uniformD = lift . uniformD -instance MonadCond m => MonadCond (StateT s m) where+instance MonadFactor m => MonadFactor (StateT s m) where score = lift . score -instance MonadInfer m => MonadInfer (StateT s m)+instance MonadMeasure m => MonadMeasure (StateT s m) -instance MonadSample m => MonadSample (ListT m) where+instance MonadDistribution m => MonadDistribution (ListT m) where random = lift random bernoulli = lift . bernoulli categorical = lift . categorical -instance MonadCond m => MonadCond (ListT m) where+instance MonadFactor m => MonadFactor (ListT m) where score = lift . score -instance MonadInfer m => MonadInfer (ListT m)+instance MonadMeasure m => MonadMeasure (ListT m) -instance MonadSample m => MonadSample (ContT r m) where+instance MonadDistribution m => MonadDistribution (ContT r m) where random = lift random -instance MonadCond m => MonadCond (ContT r m) where+instance MonadFactor m => MonadFactor (ContT r m) where score = lift . score -instance MonadInfer m => MonadInfer (ContT r m)+instance MonadMeasure m => MonadMeasure (ContT r m)
src/Control/Monad/Bayes/Density/Free.hs view
@@ -23,7 +23,7 @@ ) where -import Control.Monad.Bayes.Class (MonadSample (random))+import Control.Monad.Bayes.Class (MonadDistribution (random)) import Control.Monad.RWS import Control.Monad.State (evalStateT) import Control.Monad.Trans.Free.Church (FT, MonadFree (..), hoistFT, iterT, iterTM, liftF)@@ -42,7 +42,7 @@ instance MonadFree SamF (Density m) where wrap = Density . wrap . fmap runDensity -instance Monad m => MonadSample (Density m) where+instance Monad m => MonadDistribution (Density m) where random = Density $ liftF (Random id) -- | Hoist 'Density' through a monad transform.@@ -50,7 +50,7 @@ hoist f (Density m) = Density (hoistFT f m) -- | Execute random sampling in the transformed monad.-interpret :: MonadSample m => Density m a -> m a+interpret :: MonadDistribution m => Density m a -> m a interpret (Density m) = iterT f m where f (Random k) = random >>= k@@ -68,7 +68,7 @@ -- | Execute computation with supplied values for a subset of random choices. -- Return the output value and a record of all random choices used, whether -- taken as input or drawn using the transformed monad.-density :: MonadSample m => [Double] -> Density m a -> m (a, [Double])+density :: MonadDistribution m => [Double] -> Density m a -> m (a, [Double]) density randomness (Density m) = runWriterT $ evalStateT (iterTM f $ hoistFT lift m) randomness where@@ -84,5 +84,5 @@ k x -- | Like 'density', but use an arbitrary sampling monad.-traced :: MonadSample m => [Double] -> Density Identity a -> m (a, [Double])+traced :: MonadDistribution m => [Double] -> Density Identity a -> m (a, [Double]) traced randomness m = density randomness $ hoist (return . runIdentity) m
src/Control/Monad/Bayes/Density/State.hs view
@@ -9,7 +9,7 @@ -- monad transformer techniques. module Control.Monad.Bayes.Density.State where -import Control.Monad.Bayes.Class (MonadSample (random))+import Control.Monad.Bayes.Class (MonadDistribution (random)) import Control.Monad.State (MonadState (get, put), StateT, evalStateT) import Control.Monad.Writer @@ -27,7 +27,7 @@ listen = Density . listen . runDensity pass = Density . pass . runDensity -instance MonadSample m => MonadSample (Density m) where+instance MonadDistribution m => MonadDistribution (Density m) where random = do trace <- get x <- case trace of
src/Control/Monad/Bayes/Enumerator.hs view
@@ -33,9 +33,9 @@ import Control.Applicative (Alternative) import Control.Arrow (second) import Control.Monad.Bayes.Class- ( MonadCond (..),- MonadInfer,- MonadSample (bernoulli, categorical, logCategorical, random),+ ( MonadDistribution (bernoulli, categorical, logCategorical, random),+ MonadFactor (..),+ MonadMeasure, ) import Control.Monad.Writer import Data.AEq (AEq, (===), (~==))@@ -52,15 +52,15 @@ newtype Enumerator a = Enumerator (WriterT (Product (Log Double)) [] a) deriving newtype (Functor, Applicative, Monad, Alternative, MonadPlus) -instance MonadSample Enumerator where+instance MonadDistribution Enumerator where random = error "Infinitely supported random variables not supported in Enumerator" bernoulli p = fromList [(True, (Exp . log) p), (False, (Exp . log) (1 - p))] categorical v = fromList $ zip [0 ..] $ map (Exp . log) (V.toList v) -instance MonadCond Enumerator where+instance MonadFactor Enumerator where score w = fromList [((), w)] -instance MonadInfer Enumerator+instance MonadMeasure Enumerator -- | Construct Enumerator from a list of values and associated weights. fromList :: [(a, Log Double)] -> Enumerator a@@ -129,7 +129,7 @@ toEmpiricalWeighted :: (Fractional b, Ord a, Ord b) => [(a, b)] -> [(a, b)] toEmpiricalWeighted = normalizeWeights . compact -enumerateToDistribution :: (MonadSample n) => Enumerator a -> n a+enumerateToDistribution :: (MonadDistribution n) => Enumerator a -> n a enumerateToDistribution model = do let samples = logExplicit model let (support, logprobs) = unzip samples
src/Control/Monad/Bayes/Inference/MCMC.hs view
@@ -11,12 +11,17 @@ -- Portability : GHC module Control.Monad.Bayes.Inference.MCMC where -import Control.Monad.Bayes.Class+import Control.Monad.Bayes.Class (MonadDistribution) import qualified Control.Monad.Bayes.Traced.Basic as Basic import Control.Monad.Bayes.Traced.Common+ ( MHResult (MHResult, trace),+ Trace (probDensity),+ burnIn,+ mhTransWithBool,+ ) import qualified Control.Monad.Bayes.Traced.Dynamic as Dynamic import qualified Control.Monad.Bayes.Traced.Static as Static-import Control.Monad.Bayes.Weighted+import Control.Monad.Bayes.Weighted (Weighted, unweighted) import Pipes ((>->)) import qualified Pipes as P import qualified Pipes.Prelude as P@@ -28,13 +33,13 @@ defaultMCMCConfig :: MCMCConfig defaultMCMCConfig = MCMCConfig {proposal = SingleSiteMH, numMCMCSteps = 1, numBurnIn = 0} -mcmc :: MonadSample m => MCMCConfig -> Static.Traced (Weighted m) a -> m [a]+mcmc :: MonadDistribution m => MCMCConfig -> Static.Traced (Weighted m) a -> m [a] mcmc (MCMCConfig {..}) m = burnIn numBurnIn $ unweighted $ Static.mh numMCMCSteps m -mcmcBasic :: MonadSample m => MCMCConfig -> Basic.Traced (Weighted m) a -> m [a]+mcmcBasic :: MonadDistribution m => MCMCConfig -> Basic.Traced (Weighted m) a -> m [a] mcmcBasic (MCMCConfig {..}) m = burnIn numBurnIn $ unweighted $ Basic.mh numMCMCSteps m -mcmcDynamic :: MonadSample m => MCMCConfig -> Dynamic.Traced (Weighted m) a -> m [a]+mcmcDynamic :: MonadDistribution m => MCMCConfig -> Dynamic.Traced (Weighted m) a -> m [a] mcmcDynamic (MCMCConfig {..}) m = burnIn numBurnIn $ unweighted $ Dynamic.mh numMCMCSteps m -- -- | draw iid samples until you get one that has non-zero likelihood@@ -45,7 +50,7 @@ >-> P.map (MHResult False) -- | convert a probabilistic program into a producer of samples-mcmcP :: MonadSample m => MCMCConfig -> Static.Traced m a -> P.Producer (MHResult a) m ()+mcmcP :: MonadDistribution m => MCMCConfig -> Static.Traced m a -> P.Producer (MHResult a) m () mcmcP MCMCConfig {..} m@(Static.Traced w _) = do initialValue <- independentSamples m >-> P.drain ( P.unfoldr (fmap (Right . (\k -> (k, trace k))) . mhTransWithBool w) initialValue
src/Control/Monad/Bayes/Inference/PMMH.hs view
@@ -18,7 +18,7 @@ ) where -import Control.Monad.Bayes.Class (Bayesian (generative), MonadInfer, MonadSample, prior)+import Control.Monad.Bayes.Class (Bayesian (generative), MonadDistribution, MonadMeasure, prior) import Control.Monad.Bayes.Inference.MCMC (MCMCConfig, mcmc) import Control.Monad.Bayes.Inference.SMC (SMCConfig (), smc) import Control.Monad.Bayes.Population as Pop@@ -35,7 +35,7 @@ -- | Particle Marginal Metropolis-Hastings sampling. pmmh ::- MonadSample m =>+ MonadDistribution m => MCMCConfig -> SMCConfig (Weighted m) -> Traced (Weighted m) a1 ->@@ -54,9 +54,9 @@ -- | Particle Marginal Metropolis-Hastings sampling from a Bayesian model pmmhBayesianModel ::- MonadInfer m =>+ MonadMeasure m => MCMCConfig -> SMCConfig (Weighted m) ->- (forall m'. MonadInfer m' => Bayesian m' a1 a2) ->+ (forall m'. MonadMeasure m' => Bayesian m' a1 a2) -> m [[(a2, Log Double)]] pmmhBayesianModel mcmcConf smcConf bm = pmmh mcmcConf smcConf (prior bm) (generative bm)
src/Control/Monad/Bayes/Inference/RMSMC.hs view
@@ -20,7 +20,7 @@ ) where -import Control.Monad.Bayes.Class (MonadSample)+import Control.Monad.Bayes.Class (MonadDistribution) import Control.Monad.Bayes.Inference.MCMC (MCMCConfig (..)) import Control.Monad.Bayes.Inference.SMC import Control.Monad.Bayes.Population@@ -42,7 +42,7 @@ -- | Resample-move Sequential Monte Carlo. rmsmc ::- MonadSample m =>+ MonadDistribution m => MCMCConfig -> SMCConfig m -> -- | model@@ -56,7 +56,7 @@ -- | Resample-move Sequential Monte Carlo with a more efficient -- tracing representation. rmsmcBasic ::- MonadSample m =>+ MonadDistribution m => MCMCConfig -> SMCConfig m -> -- | model@@ -71,7 +71,7 @@ -- where only random variables since last resampling are considered -- for rejuvenation. rmsmcDynamic ::- MonadSample m =>+ MonadDistribution m => MCMCConfig -> SMCConfig m -> -- | model
src/Control/Monad/Bayes/Inference/SMC.hs view
@@ -20,7 +20,7 @@ ) where -import Control.Monad.Bayes.Class (MonadInfer, MonadSample)+import Control.Monad.Bayes.Class (MonadDistribution, MonadMeasure) import Control.Monad.Bayes.Population ( Population, pushEvidence,@@ -37,7 +37,7 @@ -- | Sequential importance resampling. -- Basically an SMC template that takes a custom resampler. smc ::- MonadSample m =>+ MonadDistribution m => SMCConfig m -> Coroutine.Sequential (Population m) a -> Population m a@@ -49,5 +49,5 @@ -- Weights are normalized at each timestep and the total weight is pushed -- as a score into the transformed monad. smcPush ::- MonadInfer m => SMCConfig m -> Coroutine.Sequential (Population m) a -> Population m a+ MonadMeasure m => SMCConfig m -> Coroutine.Sequential (Population m) a -> Population m a smcPush config = smc config {resampler = (pushEvidence . resampler config)}
src/Control/Monad/Bayes/Inference/SMC2.hs view
@@ -20,9 +20,9 @@ where import Control.Monad.Bayes.Class- ( MonadCond (..),- MonadInfer,- MonadSample (random),+ ( MonadDistribution (random),+ MonadFactor (..),+ MonadMeasure, ) import Control.Monad.Bayes.Inference.MCMC import Control.Monad.Bayes.Inference.RMSMC (rmsmc)@@ -43,17 +43,17 @@ instance MonadTrans SMC2 where lift = SMC2 . lift . lift . lift -instance MonadSample m => MonadSample (SMC2 m) where+instance MonadDistribution m => MonadDistribution (SMC2 m) where random = lift random -instance Monad m => MonadCond (SMC2 m) where+instance Monad m => MonadFactor (SMC2 m) where score = SMC2 . score -instance MonadSample m => MonadInfer (SMC2 m)+instance MonadDistribution m => MonadMeasure (SMC2 m) -- | Sequential Monte Carlo squared. smc2 ::- MonadSample m =>+ MonadDistribution m => -- | number of time steps Int -> -- | number of inner particles
src/Control/Monad/Bayes/Inference/TUI.hs view
@@ -21,6 +21,7 @@ import Control.Monad.Bayes.Traced (Traced) import Control.Monad.Bayes.Traced.Common import Control.Monad.Bayes.Weighted+import Control.Monad.State.Class (put) import Data.Scientific (FPFormat (Exponent), formatScientific, fromFloatDigits) import Data.Text qualified as T import Data.Text.Lazy qualified as TL@@ -108,14 +109,11 @@ showVal = txt . T.pack . (\case [] -> ""; a -> show $ head a) -- | handler for events received by the TUI-appEvent :: s -> B.BrickEvent n1 s -> B.EventM n2 (B.Next s)-appEvent p (B.VtyEvent e) =- case e of- V.EvKey (V.KChar 'q') [] -> do- B.halt p- _ -> B.continue p-appEvent _ (B.AppEvent d) = B.continue d-appEvent _ _ = error "unknown event"+appEvent :: B.BrickEvent n s -> B.EventM n s ()+appEvent (B.VtyEvent (V.EvKey (V.KChar 'q') [])) = B.halt+appEvent (B.VtyEvent _) = pure ()+appEvent (B.AppEvent d) = put d+appEvent _ = error "unknown event" doneAttr, toDoAttr :: B.AttrName doneAttr = B.attrName "theBase" <> B.attrName "done"@@ -145,7 +143,7 @@ { B.appDraw = drawUI visualizer, B.appChooseCursor = B.showFirstCursor, B.appHandleEvent = appEvent,- B.appStartEvent = return,+ B.appStartEvent = return (), B.appAttrMap = const theMap } )
src/Control/Monad/Bayes/Integrator.hs view
@@ -8,7 +8,7 @@ -- | -- This is adapted from https://jtobin.io/giry-monad-implementation--- but brought into the monad-bayes framework (i.e. Integrator is an instance of MonadInfer)+-- 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@@ -34,7 +34,7 @@ import Control.Applicative (Applicative (..)) import Control.Foldl (Fold) import Control.Foldl qualified as Foldl-import Control.Monad.Bayes.Class (MonadSample (bernoulli, random, uniformD))+import Control.Monad.Bayes.Class (MonadDistribution (bernoulli, random, uniformD)) import Control.Monad.Bayes.Weighted (Weighted, weighted) import Control.Monad.Cont ( Cont,@@ -56,7 +56,7 @@ integrator f (Integrator a) = runCont a f runIntegrator = integrator -instance MonadSample Integrator where+instance MonadDistribution Integrator where random = fromDensityFunction $ Statistics.density $ Statistics.uniformDistr 0 1 bernoulli p = Integrator $ cont (\f -> p * f True + (1 - p) * f False) uniformD ls = fromMassFunction (const (1 / fromIntegral (length ls))) ls
src/Control/Monad/Bayes/Population.hs view
@@ -41,9 +41,9 @@ import Control.Arrow (second) import Control.Monad (replicateM) import Control.Monad.Bayes.Class- ( MonadCond,- MonadInfer,- MonadSample (categorical, logCategorical, random, uniform),+ ( MonadDistribution (categorical, logCategorical, random, uniform),+ MonadFactor,+ MonadMeasure, factor, ) import Control.Monad.Bayes.Weighted@@ -65,7 +65,7 @@ -- | A collection of weighted samples, or particles. newtype Population m a = Population (Weighted (ListT m) a)- deriving newtype (Functor, Applicative, Monad, MonadIO, MonadSample, MonadCond, MonadInfer)+ deriving newtype (Functor, Applicative, Monad, MonadIO, MonadDistribution, MonadFactor, MonadMeasure) instance MonadTrans Population where lift = Population . lift . lift@@ -97,7 +97,7 @@ withParticles n = (spawn n >>) resampleGeneric ::- MonadSample m =>+ MonadDistribution m => -- | resampler (V.Vector Double -> m [Int]) -> Population m a ->@@ -149,7 +149,7 @@ -- | Resample the population using the underlying monad and a systematic resampling scheme. -- The total weight is preserved. resampleSystematic ::- (MonadSample m) =>+ (MonadDistribution m) => Population m a -> Population m a resampleSystematic = resampleGeneric (\ps -> (`systematic` ps) <$> random)@@ -171,7 +171,7 @@ -- and \(w^{(k)}\) are the weights. -- -- The conditional variance of stratified sampling is always smaller than that of multinomial sampling and it is also unbiased - see [Comparison of Resampling Schemes for Particle Filtering](https://arxiv.org/abs/cs/0507025).-stratified :: MonadSample m => V.Vector Double -> m [Int]+stratified :: MonadDistribution m => V.Vector Double -> m [Int] stratified weights = do let bigN = V.length weights dithers <- V.replicateM bigN (uniform 0.0 1.0)@@ -191,7 +191,7 @@ -- | Resample the population using the underlying monad and a stratified resampling scheme. -- The total weight is preserved. resampleStratified ::- (MonadSample m) =>+ (MonadDistribution m) => Population m a -> Population m a resampleStratified = resampleGeneric stratified@@ -199,13 +199,13 @@ -- | Multinomial sampler. Sample from \(0, \ldots, n - 1\) \(n\) -- times drawn at random according to the weights where \(n\) is the -- length of vector of weights.-multinomial :: MonadSample m => V.Vector Double -> m [Int]+multinomial :: MonadDistribution m => V.Vector Double -> m [Int] multinomial ps = replicateM (V.length ps) (categorical ps) -- | Resample the population using the underlying monad and a multinomial resampling scheme. -- The total weight is preserved. resampleMultinomial ::- (MonadSample m) =>+ (MonadDistribution m) => Population m a -> Population m a resampleMultinomial = resampleGeneric multinomial@@ -227,7 +227,7 @@ -- | Push the evidence estimator as a score to the transformed monad. -- Weights are normalized after this operation. pushEvidence ::- MonadCond m =>+ MonadFactor m => Population m a -> Population m a pushEvidence = hoist applyWeight . extractEvidence@@ -235,7 +235,7 @@ -- | A properly weighted single sample, that is one picked at random according -- to the weights, with the sum of all weights. proper ::- (MonadSample m) =>+ (MonadDistribution m) => Population m a -> Weighted m a proper m = do@@ -254,7 +254,7 @@ -- This way a single sample can be selected from a population without -- introducing bias. collapse ::- (MonadInfer m) =>+ (MonadMeasure m) => Population m a -> m a collapse = applyWeight . proper
src/Control/Monad/Bayes/Sampler/Lazy.hs view
@@ -7,7 +7,7 @@ module Control.Monad.Bayes.Sampler.Lazy where import Control.Monad (ap, liftM)-import Control.Monad.Bayes.Class (MonadSample (random))+import Control.Monad.Bayes.Class (MonadDistribution (random)) import Control.Monad.Bayes.Weighted (Weighted, weighted) import Numeric.Log (Log (..)) import System.Random@@ -65,7 +65,7 @@ (Sampler m') = f (m g1) in m' g2 -instance MonadSample Sampler where+instance MonadDistribution Sampler where random = Sampler \(Tree r _) -> r sampler :: Sampler a -> IO a
src/Control/Monad/Bayes/Sampler/Strict.hs view
@@ -12,8 +12,8 @@ -- Stability : experimental -- Portability : GHC ----- 'SamplerIO' and 'SamplerST' are instances of 'MonadSample'. Apply a 'MonadCond'--- transformer to obtain a 'MonadInfer' that can execute probabilistic models.+-- 'SamplerIO' and 'SamplerST' are instances of 'MonadDistribution'. Apply a 'MonadFactor'+-- transformer to obtain a 'MonadMeasure' that can execute probabilistic models. module Control.Monad.Bayes.Sampler.Strict ( Sampler, SamplerIO,@@ -29,7 +29,7 @@ import Control.Foldl qualified as F hiding (random) import Control.Monad.Bayes.Class- ( MonadSample+ ( MonadDistribution ( bernoulli, beta, categorical,@@ -58,7 +58,7 @@ -- to particular pairs of monad and RNG type SamplerST s = Sampler (STGenM StdGen s) (ST s) -instance StatefulGen g m => MonadSample (Sampler g m) where+instance StatefulGen g m => MonadDistribution (Sampler g m) where random = Sampler (ReaderT uniformDouble01M) uniform a b = Sampler (ReaderT $ uniformRM (a, b))
src/Control/Monad/Bayes/Sequential/Coroutine.hs view
@@ -26,9 +26,9 @@ where import Control.Monad.Bayes.Class- ( MonadCond (..),- MonadInfer,- MonadSample (bernoulli, categorical, random),+ ( MonadDistribution (bernoulli, categorical, random),+ MonadFactor (..),+ MonadMeasure, ) import Control.Monad.Coroutine ( Coroutine (..),@@ -54,16 +54,16 @@ extract :: Await () a -> a extract (Await f) = f () -instance MonadSample m => MonadSample (Sequential m) where+instance MonadDistribution m => MonadDistribution (Sequential m) where random = lift random bernoulli = lift . bernoulli categorical = lift . categorical -- | Execution is 'suspend'ed after each 'score'.-instance MonadCond m => MonadCond (Sequential m) where+instance MonadFactor m => MonadFactor (Sequential m) where score w = lift (score w) >> suspend -instance MonadInfer m => MonadInfer (Sequential m)+instance MonadMeasure m => MonadMeasure (Sequential m) -- | A point where the computation is paused. suspend :: Monad m => Sequential m ()
src/Control/Monad/Bayes/Traced/Basic.hs view
@@ -19,9 +19,9 @@ import Control.Applicative (liftA2) import Control.Monad.Bayes.Class- ( MonadCond (..),- MonadInfer,- MonadSample (random),+ ( MonadDistribution (random),+ MonadFactor (..),+ MonadMeasure, ) import Control.Monad.Bayes.Density.Free (Density) import Control.Monad.Bayes.Traced.Common@@ -56,13 +56,13 @@ my = mx >>= model . f dy = dx `bind` (traceDist . f) -instance MonadSample m => MonadSample (Traced m) where+instance MonadDistribution m => MonadDistribution (Traced m) where random = Traced random (fmap singleton random) -instance MonadCond m => MonadCond (Traced m) where+instance MonadFactor m => MonadFactor (Traced m) where score w = Traced (score w) (score w >> pure (scored w)) -instance MonadInfer m => MonadInfer (Traced m)+instance MonadMeasure m => MonadMeasure (Traced m) hoist :: (forall x. m x -> m x) -> Traced m a -> Traced m a hoist f (Traced m d) = Traced m (f d)@@ -72,14 +72,14 @@ marginal (Traced _ d) = fmap output d -- | A single step of the Trace Metropolis-Hastings algorithm.-mhStep :: MonadSample m => Traced m a -> Traced m a+mhStep :: MonadDistribution m => Traced m a -> Traced m a mhStep (Traced m d) = Traced m d' where d' = d >>= mhTrans' m -- | Full run of the Trace Metropolis-Hastings algorithm with a specified -- number of steps.-mh :: MonadSample m => Int -> Traced m a -> m [a]+mh :: MonadDistribution m => Int -> Traced m a -> m [a] mh n (Traced m d) = fmap (map output . NE.toList) (f n) where f k
src/Control/Monad/Bayes/Traced/Common.hs view
@@ -21,7 +21,7 @@ where import Control.Monad.Bayes.Class- ( MonadSample (bernoulli, random),+ ( MonadDistribution (bernoulli, random), discrete, ) import qualified Control.Monad.Bayes.Density.Free as Free@@ -81,7 +81,7 @@ return $ t2 {variables = variables t1 ++ variables t2, probDensity = probDensity t1 * probDensity t2} -- | A single Metropolis-corrected transition of single-site Trace MCMC.-mhTrans :: MonadSample m => (Weighted (State.Density m)) a -> Trace a -> m (Trace a)+mhTrans :: MonadDistribution m => (Weighted (State.Density m)) a -> Trace a -> m (Trace a) mhTrans m t@Trace {variables = us, probDensity = p} = do let n = length us us' <- do@@ -95,11 +95,11 @@ accept <- bernoulli ratio return $ if accept then Trace vs b q else t -mhTransFree :: MonadSample m => Weighted (Free.Density m) a -> Trace a -> m (Trace a)+mhTransFree :: MonadDistribution m => Weighted (Free.Density m) a -> Trace a -> m (Trace a) mhTransFree m t = trace <$> mhTransWithBool m t -- | A single Metropolis-corrected transition of single-site Trace MCMC.-mhTransWithBool :: MonadSample m => Weighted (Free.Density m) a -> Trace a -> m (MHResult a)+mhTransWithBool :: MonadDistribution m => Weighted (Free.Density m) a -> Trace a -> m (MHResult a) mhTransWithBool m t@Trace {variables = us, probDensity = p} = do let n = length us us' <- do@@ -114,7 +114,7 @@ return if accept then MHResult True (Trace vs b q) else MHResult False t -- | A variant of 'mhTrans' with an external sampling monad.-mhTrans' :: MonadSample m => Weighted (Free.Density Identity) a -> Trace a -> m (Trace a)+mhTrans' :: MonadDistribution m => Weighted (Free.Density Identity) a -> Trace a -> m (Trace a) mhTrans' m = mhTransFree (Weighted.hoist (Free.hoist (return . runIdentity)) m) -- | burn in an MCMC chain for n steps (which amounts to dropping samples of the end of the list)
src/Control/Monad/Bayes/Traced/Dynamic.hs view
@@ -20,9 +20,9 @@ import Control.Monad (join) import Control.Monad.Bayes.Class- ( MonadCond (..),- MonadInfer,- MonadSample (random),+ ( MonadDistribution (random),+ MonadFactor (..),+ MonadMeasure, ) import Control.Monad.Bayes.Density.Free (Density) import Control.Monad.Bayes.Traced.Common@@ -67,13 +67,13 @@ instance MonadTrans Traced where lift m = Traced $ fmap ((,) (lift $ lift m) . pure) m -instance MonadSample m => MonadSample (Traced m) where+instance MonadDistribution m => MonadDistribution (Traced m) where random = Traced $ fmap ((,) random . singleton) random -instance MonadCond m => MonadCond (Traced m) where+instance MonadFactor m => MonadFactor (Traced m) where score w = Traced $ fmap (score w,) (score w >> pure (scored w)) -instance MonadInfer m => MonadInfer (Traced m)+instance MonadMeasure m => MonadMeasure (Traced m) hoist :: (forall x. m x -> m x) -> Traced m a -> Traced m a hoist f (Traced c) = Traced (f c)@@ -91,7 +91,7 @@ return (return x, pure x) -- | A single step of the Trace Metropolis-Hastings algorithm.-mhStep :: MonadSample m => Traced m a -> Traced m a+mhStep :: MonadDistribution m => Traced m a -> Traced m a mhStep (Traced c) = Traced $ do (m, t) <- c t' <- mhTransFree m t@@ -99,7 +99,7 @@ -- | Full run of the Trace Metropolis-Hastings algorithm with a specified -- number of steps.-mh :: MonadSample m => Int -> Traced m a -> m [a]+mh :: MonadDistribution m => Int -> Traced m a -> m [a] mh n (Traced c) = do (m, t) <- c let f k
src/Control/Monad/Bayes/Traced/Static.hs view
@@ -20,9 +20,9 @@ import Control.Applicative (liftA2) import Control.Monad.Bayes.Class- ( MonadCond (..),- MonadInfer,- MonadSample (random),+ ( MonadDistribution (random),+ MonadFactor (..),+ MonadMeasure, ) import Control.Monad.Bayes.Density.Free (Density) import Control.Monad.Bayes.Traced.Common@@ -61,13 +61,13 @@ instance MonadTrans Traced where lift m = Traced (lift $ lift m) (fmap pure m) -instance MonadSample m => MonadSample (Traced m) where+instance MonadDistribution m => MonadDistribution (Traced m) where random = Traced random (fmap singleton random) -instance MonadCond m => MonadCond (Traced m) where+instance MonadFactor m => MonadFactor (Traced m) where score w = Traced (score w) (score w >> pure (scored w)) -instance MonadInfer m => MonadInfer (Traced m)+instance MonadMeasure m => MonadMeasure (Traced m) hoist :: (forall x. m x -> m x) -> Traced m a -> Traced m a hoist f (Traced m d) = Traced m (f d)@@ -77,14 +77,14 @@ marginal (Traced _ d) = fmap output d -- | A single step of the Trace Metropolis-Hastings algorithm.-mhStep :: MonadSample m => Traced m a -> Traced m a+mhStep :: MonadDistribution m => Traced m a -> Traced m a mhStep (Traced m d) = Traced m d' where d' = d >>= mhTransFree m -- | Full run of the Trace Metropolis-Hastings algorithm with a specified -- number of steps. Newest samples are at the head of the list.-mh :: MonadSample m => Int -> Traced m a -> m [a]+mh :: MonadDistribution m => Int -> Traced m a -> m [a] mh n (Traced m d) = fmap (map output . NE.toList) (f n) where f k
src/Control/Monad/Bayes/Weighted.hs view
@@ -11,8 +11,8 @@ -- Stability : experimental -- Portability : GHC ----- 'Weighted' is an instance of 'MonadCond'. Apply a 'MonadSample' transformer to--- obtain a 'MonadInfer' that can execute probabilistic models.+-- 'Weighted' is an instance of 'MonadFactor'. Apply a 'MonadDistribution' transformer to+-- obtain a 'MonadMeasure' that can execute probabilistic models. module Control.Monad.Bayes.Weighted ( Weighted, withWeight,@@ -26,9 +26,9 @@ where import Control.Monad.Bayes.Class- ( MonadCond (..),- MonadInfer,- MonadSample,+ ( MonadDistribution,+ MonadFactor (..),+ MonadMeasure, factor, ) import Control.Monad.State (MonadIO, MonadTrans, StateT (..), lift, mapStateT, modify)@@ -37,12 +37,12 @@ -- | Execute the program using the prior distribution, while accumulating likelihood. newtype Weighted m a = Weighted (StateT (Log Double) m a) -- StateT is more efficient than WriterT- deriving newtype (Functor, Applicative, Monad, MonadIO, MonadTrans, MonadSample)+ deriving newtype (Functor, Applicative, Monad, MonadIO, MonadTrans, MonadDistribution) -instance Monad m => MonadCond (Weighted m) where+instance Monad m => MonadFactor (Weighted m) where score w = Weighted (modify (* w)) -instance MonadSample m => MonadInfer (Weighted m)+instance MonadDistribution m => MonadMeasure (Weighted m) -- | Obtain an explicit value of the likelihood for a given value. weighted, runWeighted :: Weighted m a -> m (a, Log Double)@@ -69,7 +69,7 @@ return x -- | Use the weight as a factor in the transformed monad.-applyWeight :: MonadCond m => Weighted m a -> m a+applyWeight :: MonadFactor m => Weighted m a -> m a applyWeight m = do (x, w) <- weighted m factor w
test/TestAdvanced.hs view
@@ -26,7 +26,7 @@ mcmcConfig :: MCMCConfig mcmcConfig = MCMCConfig {numMCMCSteps = 0, numBurnIn = 0, proposal = SingleSiteMH} -smcConfig :: MonadSample m => SMCConfig m+smcConfig :: MonadDistribution m => SMCConfig m smcConfig = SMCConfig {numSteps = 0, numParticles = 1000, resampler = resampleMultinomial} passed1, passed2, passed3, passed4, passed5, passed6, passed7 :: IO Bool
test/TestDistribution.hs view
@@ -9,7 +9,7 @@ where import Control.Monad (replicateM)-import Control.Monad.Bayes.Class (MonadSample, mvNormal)+import Control.Monad.Bayes.Class (MonadDistribution, mvNormal) import Control.Monad.Bayes.Sampler.Strict import Control.Monad.Identity (runIdentity) import Control.Monad.State (evalStateT)
test/TestEnumerator.hs view
@@ -3,7 +3,7 @@ module TestEnumerator (passed1, passed2, passed3, passed4) where import Control.Monad.Bayes.Class- ( MonadSample (categorical, uniformD),+ ( MonadDistribution (categorical, uniformD), ) import Control.Monad.Bayes.Enumerator ( enumerator,@@ -15,13 +15,13 @@ import Numeric.Log (Log (ln)) import Sprinkler (hard, soft) -unnorm :: MonadSample m => m Int+unnorm :: MonadDistribution m => m Int unnorm = categorical $ V.fromList [0.5, 0.8] passed1 :: Bool passed1 = (exp . ln) (evidence unnorm) ~== 1 -agg :: MonadSample m => m Int+agg :: MonadDistribution m => m Int agg = do x <- uniformD [0, 1] y <- uniformD [2, 1]
test/TestInference.hs view
@@ -14,7 +14,7 @@ normalNormalAnalytic, ) import Control.Monad (replicateM)-import Control.Monad.Bayes.Class (MonadInfer, posterior)+import Control.Monad.Bayes.Class (MonadMeasure, posterior) import Control.Monad.Bayes.Enumerator (enumerator) import Control.Monad.Bayes.Inference.SMC import Control.Monad.Bayes.Integrator (normalize)@@ -30,7 +30,7 @@ import Sprinkler (soft) import System.Random.Stateful (IOGenM, StdGen, mkStdGen, newIOGenM) -sprinkler :: MonadInfer m => m Bool+sprinkler :: MonadMeasure m => m Bool sprinkler = Sprinkler.soft -- | Count the number of particles produced by SMC
test/TestIntegrator.hs view
@@ -4,9 +4,9 @@ import Control.Monad (replicateM) import Control.Monad.Bayes.Class- ( MonadCond (score),- MonadInfer,- MonadSample (bernoulli, gamma, normal, random, uniformD),+ ( MonadDistribution (bernoulli, gamma, normal, random, uniformD),+ MonadFactor (score),+ MonadMeasure, condition, factor, normalPdf,@@ -32,7 +32,7 @@ volumeIsOne :: [Double] -> Bool volumeIsOne = (~== 1.0) . volume . uniformD -agg :: MonadSample m => m Int+agg :: MonadDistribution m => m Int agg = do x <- uniformD [0, 1] y <- uniformD [2, 1]@@ -141,7 +141,7 @@ quadrature = expectation $ normalize $ model1 in abs (sample - quadrature) < 0.01 -model1 :: MonadInfer m => m Double+model1 :: MonadMeasure m => m Double model1 = do x <- random y <- random
test/TestPopulation.hs view
@@ -1,6 +1,6 @@ module TestPopulation (weightedSampleSize, popSize, manySize, sprinkler, sprinklerExact, transCheck1, transCheck2, resampleCheck, popAvgCheck) where -import Control.Monad.Bayes.Class (MonadInfer, MonadSample)+import Control.Monad.Bayes.Class (MonadDistribution, MonadMeasure) import Control.Monad.Bayes.Enumerator (enumerator, expectation) import Control.Monad.Bayes.Population as Population ( Population,@@ -16,7 +16,7 @@ import Sprinkler (soft) import System.Random.Stateful (mkStdGen, newIOGenM) -weightedSampleSize :: MonadSample m => Population m a -> m Int+weightedSampleSize :: MonadDistribution m => Population m a -> m Int weightedSampleSize = fmap length . population popSize :: IO Int@@ -27,7 +27,7 @@ manySize = sampleIOfixed (weightedSampleSize $ spawn 5 >> sprinkler >> spawn 3) -sprinkler :: MonadInfer m => m Bool+sprinkler :: MonadMeasure m => m Bool sprinkler = Sprinkler.soft sprinklerExact :: [(Bool, Double)]
test/TestSampler.hs view
@@ -2,7 +2,7 @@ import qualified Control.Foldl as Fold import Control.Monad (replicateM)-import Control.Monad.Bayes.Class (MonadSample (normal))+import Control.Monad.Bayes.Class (MonadDistribution (normal)) import Control.Monad.Bayes.Sampler.Strict (sampleSTfixed) import Control.Monad.ST (ST, runST)
test/TestSequential.hs view
@@ -1,8 +1,8 @@ module TestSequential (twoSync, finishedTwoSync, checkTwoSync, checkPreserve, pFinished, isFinished, checkSync) where import Control.Monad.Bayes.Class- ( MonadInfer,- MonadSample (uniformD),+ ( MonadDistribution (uniformD),+ MonadMeasure, factor, ) import Control.Monad.Bayes.Enumerator as Dist (enumerator, mass)@@ -10,7 +10,7 @@ import Data.AEq (AEq ((~==))) import Sprinkler (soft) -twoSync :: MonadInfer m => m Int+twoSync :: MonadMeasure m => m Int twoSync = do x <- uniformD [0, 1] factor (fromIntegral x)@@ -18,7 +18,7 @@ factor (fromIntegral y) return (x + y) -finishedTwoSync :: MonadInfer m => Int -> m Bool+finishedTwoSync :: MonadMeasure m => Int -> m Bool finishedTwoSync n = finished (run n twoSync) where run 0 d = d@@ -30,7 +30,7 @@ checkTwoSync 2 = mass (finishedTwoSync 2) True ~== 1 checkTwoSync _ = error "Unexpected argument" -sprinkler :: MonadInfer m => m Bool+sprinkler :: MonadMeasure m => m Bool sprinkler = Sprinkler.soft checkPreserve :: Bool@@ -42,7 +42,7 @@ pFinished 2 = 1 pFinished _ = error "Unexpected argument" -isFinished :: MonadInfer m => Int -> m Bool+isFinished :: MonadMeasure m => Int -> m Bool isFinished n = finished (run n sprinkler) where run 0 d = d
test/TestWeighted.hs view
@@ -3,8 +3,8 @@ module TestWeighted (check, passed, result, model) where import Control.Monad.Bayes.Class- ( MonadInfer,- MonadSample (normal, uniformD),+ ( MonadDistribution (normal, uniformD),+ MonadMeasure, factor, ) import Control.Monad.Bayes.Sampler.Strict (sampleIOfixed)@@ -15,7 +15,7 @@ import Numeric.Log (Log (Exp, ln)) import System.Random.Stateful (mkStdGen, newIOGenM) -model :: MonadInfer m => m (Int, Double)+model :: MonadMeasure m => m (Int, Double) model = do n <- uniformD [0, 1, 2] unless (n == 0) (factor 0.5)@@ -23,7 +23,7 @@ when (n == 2) (factor $ (Exp . log) (x * x)) return (n, x) -result :: MonadSample m => m ((Int, Double), Double)+result :: MonadDistribution m => m ((Int, Double), Double) result = second (exp . ln) <$> weighted model passed :: IO Bool