Skip to main content

sabc

ci version

Simulated Annealing ABC in MLX

sabc performs likelihood-free Bayesian inference (Approximate Bayesian Computation) via Simulated Annealing. The annealing loop — empirical-CDF distance transform, importance resampling, epsilon schedule, and a Differential-Evolution MCMC kernel — runs in a compiled nanobind extension (sabc._core), while models, priors, and the entry point live in Python and exchange mlx.core.arrays with the C++ core zero-copy via DLPack.

Quickstart

All you provide is a prior, the observed data, and a distance function f_dist(theta, observed). The distance function is yours to write — it folds simulation, summary statistics, and the metric into one place — and it returns either one distance per particle (scalar) or one per summary statistic (vector). Here we infer the location of a 2-D model observed at [1, -1]:

import mlx.core as mx

import sabc
from sabc import distributions as dist

observed = mx.array([1.0, -1.0])

prior = dist.JointDistributionNamed(
    dict(theta=dist.Normal(mx.zeros(2), mx.ones(2) * 3.0))
)


def f_dist(theta, observed):
    # theta: (n_particles, n_para). Simulate, then return the distance(s).
    y = theta + mx.random.normal(theta.shape) * 0.1
    return mx.abs(y - observed)              # per-dimension (vector) distance


posterior = sabc.run(
    f_dist,
    prior=prior,
    observed=observed,
    n_particles=2000,
    n_simulation=200_000,
    schedule=sabc.SingleEps(v=1.0),
    key=mx.random.key(0),
)

print(posterior.samples.mean(axis=0))      # ~ [1, -1]

sabc.run returns a Posterior with samples, u, rho, and the epsilon_history / u_history traces.

Scalar vs vector distances, single vs multiple epsilon

The shape of what f_dist returns chooses the inference flavour, independently of the epsilon schedule:

  • return (n_particles,) / (n_particles, 1) for a single scalar distance,
  • return (n_particles, n_stats) to keep one distance per summary statistic.

A per-statistic distance pairs naturally with MultiEps, which anneals one temperature per statistic (SingleEps uses one shared temperature):

def f_dist(theta, observed):
    y = simulate(theta)
    return mx.abs(summary(y) - observed)    # (n_particles, n_stats)

posterior = sabc.run(
    f_dist, prior=prior, observed=observed,
    schedule=sabc.MultiEps(v=1.0),          # one epsilon per statistic
)

Priors

Priors are built from MLX-native, TFP-style distributions:

prior = dist.JointDistributionNamed(dict(
    a=dist.Normal(mx.zeros(1), mx.ones(1)),
    b=lambda a: dist.Normal(a, mx.ones(1)),   # p(b | a)
))

Examples

Self-contained examples are in examples.

Installation

sabc targets Apple Silicon (Metal); Linux support is experimental. It requires Python ≥ 3.11. Install the released package from PyPI:

pip install sabc

For a development checkout, use uv:

git clone https://github.com/dirmeier/sabc && cd sabc
uv sync --all-extras

Development

The project uses uv, scikit-build-core (CMake/C++23), ruff for Python, and clang-format + cpplint for C++. The Makefile wraps the common tasks:

make check    # cpp checks
make tests    # run the tests
make format   # autoformat
make lints    # lint

Install the git hooks once (the commit-msg type is needed for gitlint):

uv run pre-commit install --hook-type pre-commit --hook-type commit-msg

The hooks then run automatically on changed files at commit time. To run every hook against the whole repository (useful after adding a hook or before a PR):

uv run pre-commit run --all-files

Linux build (Docker)

The CI builds the C++/MLX extension under gcc on Linux. Apple clang accepts some MLX overloads that gcc rejects, so a dev container is provided to reproduce and verify the Linux build locally without GitHub Actions:

docker build -t sabc-linux -f .devcontainer/Dockerfile .
docker run --rm -v "$PWD":/work -w /work sabc-linux \
  bash -lc "uv sync --all-extras && make tests"

Citing SABC

If you find this package relevant to your research, please consider citing:

@article{albert2025simulated,
  title={Simulated Annealing ABC with multiple summary statistics},
  author={Albert, Carlo and Ulzega, Simone and Dirmeier, Simon and Scheidegger, Andreas and Bassi, Alberto and Mira, Antonietta},
  journal={arXiv preprint arXiv:2505.23261},
  year={2025}
}

Metadata

Release files for sabc 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sabc 0.3.0
File Size Uploaded Provenance
sabc-0.3.0.tar.gz 131.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for sabc 0.3.0
File Interpreter ABI Platform
sabc-0.3.0-cp313-cp313-macosx_26_0_arm64.whl CPython 3.13 CPython 3.13 macOS 26.0+ ARM64 Details

Total release size: 234.9 kB

Release files / sabc-0.3.0.tar.gz

Download URL sabc-0.3.0.tar.gz
Size 131.5 kB
Tags Source
SHA-256 checksum
How to use checksums
884f8a86e0ddf8dc6a239b25cd1f119bbe50629970b91f4597eca25f1060fef2
BLAKE2b-256 checksum
How to use checksums
579ab1eb0e7c074c08e3e3505ba7b67e4829f0ef9f456080db98ba0c4f21ecf8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / sabc-0.3.0-cp313-cp313-macosx_26_0_arm64.whl

Download URL sabc-0.3.0-cp313-cp313-macosx_26_0_arm64.whl
Size 103.4 kB
Tags CPython 3.13 macOS 26.0+ ARM64
SHA-256 checksum
How to use checksums
fc89da0de314f4e03cb4798ca55aa36f26e19534a4daeffd8257f1e12c9e189e
BLAKE2b-256 checksum
How to use checksums
e872b9237526a5bbf3ee981f755496eb2b384e24f7328fe783bd50c163d6ca9d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for sabc 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page