Metadata-Version: 2.5
Name: bayesmith
Version: 0.1.0
Summary: A graph of operators is a Bayesian model; its structure chooses the inference.
Project-URL: Repository, https://github.com/zzhang0123/bayesmith
Author: Zheng Zhang
License: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Mathematics
Requires-Python: >=3.11
Requires-Dist: equinox>=0.13
Requires-Dist: jax>=0.5
Requires-Dist: numpy
Requires-Dist: numpyro>=0.15
Description-Content-Type: text/markdown

# bayesmith

A Bayesian model is a graph of operators. Deterministic operators propagate
dependence; probabilistic operators contribute a conditional density. Together
they *are* the joint distribution.

bayesmith makes that graph **explicit and inspectable**, and then uses its
structure to choose how the model is fitted — an exact solve where the structure
permits one, NUTS where it does not.

```
block 0  {x}          Wiener exact        (linear_in checked, 3 scales)
block 1  {z}          enumerate 4 states
block 2  {sigma, nu}  NUTS (numpyro)      no exact structure found
```

The model tells you how it will be fitted, before it is fitted.

## What bayesmith is not

It is **not another probabilistic programming language**. Distributions, MCMC
kernels, variational inference and transforms all come from
[NumPyro](https://github.com/pyro-ppl/numpyro). bayesmith is the dispatch layer
above them, and every line in it must answer *"why can NumPyro not do this?"*

What it owns, because a trace-based PPL structurally cannot:

- **Structural exact inference** — conjugate / Wiener / GCR / GLS solves, and
  exact enumeration of discrete latents, selected per subgraph.
- **Streaming evidence** — square-root information factors combined exactly
  across datasets and observing epochs.
- **Diagnostics on the graph** — identifiability, prior sensitivity, and
  linearity checking of the declarations the dispatcher relies on.

Declarations such as `linear_in` are *claims about the model*, not hints, so
they are **checked rather than trusted**: a node declared linear is probed at
three scales before any exact solve is allowed to use it.

## Status

**0.1.0, the first release.** Published so other packages can depend on it by
name. Alpha in the classifier's sense: the API may still move.

Implemented and tested, 1163 tests: the graph core with plates and joint
log-density; the NumPyro bridge, so any graph is runnable through NUTS;
structural dispatch with the linear-Gaussian exact solves; exact enumeration of
discrete latents; streaming evidence as square-root information factors; and
graph diagnostics for identifiability, prior sensitivity and linearity.

**Two things the page above describes that 0.1.0 does not do yet.** Stated here
because a front page is a claim, and finding out afterwards is worse than
reading it now:

- **Enumeration is not dispatcher-selected.** `bayesmith.exact.discrete`
  computes the exact marginal and the posterior marginals over declared
  discrete latents, and reads the `Discrete(n)` support declaration to do it —
  but `classify` does not yet route a discrete subgraph to it. The
  `block 1  {z}  enumerate 4 states` line above is therefore a design sketch
  rather than a transcript; call the module directly.
- **Forward-backward is not implemented**, so a chain of `T` discrete latents
  costs `n ** T` by enumeration rather than `T * n**2`. Enumeration refuses
  past a budget rather than hanging, and names the count it would have visited.

## License

MIT
