Probabilistic Programming environment on the BEAM with NX, inspired by PyMC

I am looking for reviews by practitioners: GitHub - borodark/exmc: Probabilistic programming in BEAM

A Probabilistic Programming environment on the BEAM, inspired by PyMC. Exmc is a from-scratch Elixir implementation of PyMC’s architecture: declarative model specification, automatic constraint transforms, NUTS sampling, and Bayesian diagnostics — all on Nx tensors with optional EXLA acceleration.

With deep respect: this project builds on the ideas, rigor, and ergonomics pioneered by the PyMC community. The goal is not to replace PyMC. The goal is to preserve correctness and usability while exploring what changes when the runtime is the BEAM.

Why A New PPL Environment?

PyMC established a high bar for statistical correctness, extensibility, and user experience. Exmc asks a focused question:

What happens if that architecture runs on a fault-tolerant, massively concurrent runtime?

The BEAM gives us lightweight processes, isolation, and message passing. That changes how we think about multi-chain sampling, streaming diagnostics, and observability. Exmc keeps PyMC’s model semantics and diagnostics philosophy, while rethinking execution.

What We Preserve From PyMC

  • Model semantics and ergonomics: declarative RVs, clear constraints, sensible defaults.
  • Statistical correctness: NUTS with Stan-style warmup, ESS/R-hat, WAIC/LOO.
  • Composable diagnostics: traces, energy, autocorrelation, and predictive checks.

What The BEAM Enables

  • True multi-chain concurrency with one compiled model.
  • Live streaming diagnostics without polling.
  • A live posterior state that can be updated online during sampling.
  • Isolated failure domains so one chain can fail without killing the run.
7 Likes

Very cool! I suggest you look at using deftransform for your Math module, for example. Should speed up things a bit when using EXLA as a compiler.

Also EMLX should also be useful for Mac users :slight_smile:

Edit: also use defn for your dist functions. NxSignal should be an easy example to follow :slight_smile:

Edit 2: Instead of relying on BEAM RNG, you can use Nx.Random for tensor-compatible stateless RNG

4 Likes