MIT licensed by LazyPPL team
Maintained by [email protected]
This version can be pinned in stack with:lazyppl-1.1.0@sha256:f72644c2b0f88ef71ca55bdd93e85bab20753197131681d1939fbe1af328b4f4,6486

LazyPPL

LazyPPL is a Haskell library for Bayesian probabilistic programming, drawing on the fact that lazy data structures are a natural idiom for programming with infinite-dimensional Bayesian methods such as Poisson/Gaussian/Dirichlet processes.

The crucial semantic idea, inspired by developments in synthetic probability theory, is to work with two separate monads: an affine monad of probability, which supports laziness, and a commutative, non-affine monad of measures, which does not. This gives a Metropolis-Hastings implementation that works with lazy programs.

The main LazyPPL modules are on Hackage and Stackage. Various worked examples in literate Haskell are at https://lazyppl-team.github.io.

Laziness lets us specify non-parametric models cleanly: processes or infinite-dimensional functions only have their finite explored portion materialised. We have first-class

  • stochastic memoization: memoize :: (a -> Prob b) -> Prob (a -> b)
  • Gaussian processes: wiener :: Prob (Double -> Double)
  • point processes: poissonPP :: Double -> Double -> Prob [Double] (in the example demos)
  • Dirichlet processes: dp :: Double -> Prob a -> Prob (Prob a)

Examples

  • WienerDemo (lhs) is a simple implementation of regression using a Wiener process. Via maintaining a hidden table of previous calls, it appears to be a bona fide random function $R\to R$ constructed lazily. Some values are sampled during simulation, others during plotting.

Wiener process regression

  • RegressionDemo (lhs) demonstrates piecewise linear regression. The change points are drawn from a lazy Poisson process.

Poisson-split piecewise linear regression

  • Clustering (lhs) contains some simple clustering examples, where the number of clusters is unknown. Stick-breaking is lazy, and we use stochastic memoization.

Dirichlet process clustering

  • ProgramInduction (lhs) is a simple example of program induction over an arithmetic language. Random expressions are represented as an infinite forest with a finite path through it.

Program induction

Library

  • LazyPPL.hs provides the core monads and inference. Prob is an affine monad of probability measures. Meas is a non-affine monad of unnormalised measures with sample and score. The Metropolis-Hastings algorithm mh takes a probability p of changing any given site of the rose tree of random seeds. Setting p=1/num_sites approximates single-site MH and p=1 recovers multi-site MH. We can’t compute the number of active sites without forcing more of the lazy tree, so we use this p-parameterised form. A second algorithm, mh1 in lazyppl-singlesite, implements a single-site proposal kernel by inspecting the Haskell heap.
  • LazyPPL/Distributions.hs and LazyPPL/Distributions/* provide common distributions and abstract types capturing exchangeability. For example, newCustomer :: Restaurant -> Prob Table for the Chinese Restaurant Process (DirichletP.hs) and Restaurant -> Prob [Dish] for the Indian Buffet Process (IBP.hs).

Installation

Build with Cabal: install GHCup for GHC 9.14.1 and Cabal 3.18.2.0, then cabal update and cabal build in the repo root. First build takes a few minutes.

Run a demo: cabal run -fdemos wiener-exe (or regression-exe, clustering-exe, etc.), or explore in the REPL with cabal repl lib:lazyppl.

The library is pure Haskell and needs no LAPACK or BLAS installation. The plotting demos use the matplotlib Haskell wrapper, which calls into Python: sudo apt-get install -y --no-install-recommends python3-matplotlib python3-numpy python3-scipy python-is-python3.

To try lazyppl in your browser without installing anything, click Open in GitHub Codespaces. This opens a ready-to-use VS Code environment with GHC and Cabal already in place.

Writing your own probabilistic models

Under executables: in examples/package.yaml, add a stanza and run hpack examples (0.39.6) to regenerate examples/lazyppl-examples.cabal:

executables:
  # ...
  mymodel-exe:
    main:                MyModel.hs
    source-dirs:         models
    ghc-options:
    - -threaded
    - -rtsopts
    - -with-rtsopts=-N
    - -main-is MyModel
    dependencies:
    - lazyppl

Run with cabal run mymodel-exe, or open in the REPL: cabal repl exe:mymodel-exe.

Changes

Changelog for lazyppl

1.1.0

Added

  • lazyppl-examples: separate examples and plotting package
  • Playground: interactive browser models
  • Example pages: locally served fonts and icons

Changed

  • Build: Cabal and GHC 9.6.7, 9.12.4, 9.14.1
  • gp, wiener: pure Haskell without LAPACK
  • mh, mhirreducible: lower stream memory retention
  • memrec: Ord keys without Show
  • Integer memoize: restricted to Prob
  • Distributions: validate inputs and parameter domains
  • beta, dirichlet: reject unsupported shape parameters
  • Random labels and acceptance draws: open interval (0,1)
  • mh, mhirreducible, weightedsamples, wis: separate generator per run
  • superuniformbounded: bounded graph angle sampling

Fixed

  • wis: resample from all weighted samples
  • Integer memoize: return values at their own indices
  • mh, mhirreducible, wis: zero and invalid weights
  • mh1: reject proposals without reverse sites
  • beta, dirichlet: sampling at numerical boundaries
  • beta, dirichlet: reject unsupported custom tree labels
  • categorical: rounding with finite and infinite streams
  • categorical: accept finite probabilities with a rounding-sized shortfall
  • Dirichlet processes: small-stick accumulation
  • poisson: sampling at extreme labels
  • ibp: first customer’s dish count
  • gp: initial and conditional distributions
  • wiener: variance at extreme times
  • normalLogPdf, betaLogPdf, dirichletLogPdf: extreme-input accuracy
  • binomialLogPmf: large-count accuracy
  • gammaLogPdf, poissonLogPmf: extreme-input accuracy
  • Memoization, Gaussian processes and counters: concurrent state
  • uniformbounded, uniformBoundedLogPdf: overflowing bound differences
  • Playground: retry failed WebAssembly downloads
  • Playground: validate results before plotting
  • Mondrian playground: reject overlaps and duplicate identifiers
  • GraphDemo: graph probabilities and figure edges
  • Example pages: correct maximum-likelihood sample labels
  • Example pages: syntax colours in dark mode
  • Website generation: preserve prior site on build failure

Removed

  • LazyPPL.SingleSite: moved to lazyppl-singlesite
  • lazyppl: hmatrix, LAPACK and plotting dependencies

1.0.1

  • Add support for GHC 9.8 and 9.10
  • Drop upper bounds on dependencies (except base)
  • Add log-density / log-PMF functions: normalLogPdf, gammaLogPdf, etc.
  • Export scoreLog and scoreProductLog (already defined in 1.0, now visible)
  • Remove monad-extras dependency

1.0

  • Initial Hackage release