Quivers¶
A functional probabilistic programming language for PyTorch.
Quivers is a functional probabilistic programming language for PyTorch. The syntax will look familiar if you have used Pyro, NumPyro, Stan, or PyMC, with a few distinguishing features:
- Programs are first-class composable typed values. A program has a domain, codomain, algebra, and effect signature (
Sample,Score,Marginal,Pure), checked at compile time. Programs compose with>>, parallel-compose with@, change base across algebras withchange_base, and marginalize discrete latents withmarginalize z : K <- ...followed by an indented body. - Shared substrate for inference, deduction, and structural compression. A CKY parser written as a
deductionblock, a transformer-as-encoder over asignatureblock, and a Bayesian regression all compile to the same underlying semantics, with the same composition operators, and can thus compose with each other. - Algebra-parametric semantics. Programs can be parameterized by eleven built-in or user-defined algebras. Homomorphisms between algebras are values along which models can be transported. The compiler checks their source and target types; the algebraic laws remain assumptions of each instance.
The probabilistic-programming surface also includes:
- An inference toolkit. More than forty distribution families. SVI with automatic guides from mean-field and full-rank multivariate normals through low-rank, mixture, structured, IAF, neural-spline flow, and AutoDAIS guides; seven objectives (ELBO, IWAE, Renyi, VR-IWAE, ChiVI, RWS, and DReGs); and reparameterized, score-function, sticking-the-landing, and DReG gradient estimators. NUTS and HMC use dual-averaging step-size adaptation and Welford mass-matrix adaptation.
- An analysis toolkit. Static introspection of compiled programs (per-step algebra, chain depth, intermediate shape, source mapping); algebra-aware, saturation-free initialization recipes that adapt to whichever value algebra a program is parameterized over; compile-time diagnostics flagging latents whose default initialization would saturate the active algebra.
- Diagnostics and model comparison. ArviZ ecosystem integration: posteriors from any inference method (NUTS, HMC, or SVI) export to ArviZ for trace plots, rank plots, ESS, and \(\hat R\). PSIS-LOO (Pareto-smoothed importance-sampling leave-one-out cross-validation) for ranking competing models; posterior-predictive checks against user-defined test statistics; LOO-PIT for calibration.
- A mixed-effect model API. A brms-style formula frontend for mixed-effect regression compiles formulas to typed QVR programs through a bidirectional lens, taking pandas / polars dataframes as input and using R-canonical conventions (orthogonal polynomials, R-style transforms in the formula evaluation namespace) as defaults. The emitted QVR is inspectable, so a formula-fitted model is a starting point you can hand-edit rather than a closed black box.
- Interactive tooling.
qvr replis a GHCi-style four-pane Textual TUI with live syntax highlighting, an environment browser, file-watcher reloads, a command palette, and meta-commands (:type,:info,:browse,:edit,:save,:watch, …).qvr-lspimplements LSP 3.17 features including hover, definition, references, document symbols, semantic tokens, completion, formatting, and live diagnostics for VS Code, Cursor, Zed, and Neovim. A Jupyter kernel (qvr-kernel install) drives the same elaborator from notebooks.
Quick start¶
object Item : FinSet 100
# Predictor `x` flows in as exogenous data via the observations
# dict; free variables in `let` expressions resolve from the
# conditioning data at trace time (host-data channel).
program regression : Item -> Item [effects=[Sample, Score]]
sample sigma <- HalfNormal(1.0)
sample beta_0 <- Normal(0.0, 5.0)
sample beta_1 <- Normal(0.0, 2.0)
let mu = beta_0 + beta_1 * x
observe y : Item <- Normal(mu, sigma)
return y
export regression
from quivers.dsl import load
from quivers.inference import AutoNormalGuide, ELBO, SVI
import torch
program = load("docs/examples/source/bayesian_regression.qvr")
model = program.morphism
guide = AutoNormalGuide(model, observed_names={"y"})
optim = torch.optim.Adam(guide.parameters(), lr=1e-2)
svi = SVI(model, guide, optim, ELBO())
# Training loop (illustrative shape; pass real x_data, y_data in practice).
The same regression also expresses through a brms-style formula frontend:
from quivers.formulas import fit
# Call shape: fit("y ~ x + (1 | g)", data=df, family="gaussian", method="nuts")
# returns a result with a `.dump_qvr(path)` method for inspecting the emitted QVR.
print(fit.__name__)
Where to start¶
- Installation for setup.
- Quickstart for a working model in five minutes.
- QVR tutorial for probabilistic-programming users: seven chapters from linear regression through hierarchical models, sequence models, and inference-algorithm choice, with Pyro / NumPyro / Stan equivalents side-by-side.
- Python API tutorial for library developers and category-theory-fluent users: seven chapters covering the typed categorical API.
- Examples gallery: 46 end-to-end models grouped by family.
- Conceptual guides for feature-area deep dives.
- API reference for the typed Python API.
- Denotational semantics for the formal meaning of every well-typed program.
Architecture¶
The DSL is a thin layer over a typed categorical API. If you want to extend the library, write a new distribution family, or prove anything about a model, the categorical layer is what you read. If you just want to fit models, you can ignore it.
The library decomposes into eight layers. Each is consumable in isolation; each builds on those below it:
flowchart TB
L8["Layer 8: QVR DSL<br/>.qvr files, tree-sitter grammar, panproto AST"]
L7["Layer 7: Structural compression<br/>signature, encoder, decoder, loss blocks"]
L6["Layer 6: Inference<br/>guides, objectives, MCMC kernels, hybrid samplers"]
L5["Layer 5: Continuous probabilistic programs<br/>MonadicProgram, distribution families, flows, plates"]
L4["Layer 4: Stochastic morphisms<br/>Markov kernels, Giry monad, chart deduction surface"]
L3["Layer 3: Monadic and enriched constructs<br/>monads, algebras, ends, coends, Kan, profunctors"]
L2["Layer 2: Categorical structure<br/>functors, naturals, adjunctions, monoidal, traced"]
L1["Layer 1: Core V-enriched algebra<br/>FinSet, Morphism, CompositionRule hierarchy, wiring"]
L8 --> L7 --> L6 --> L5 --> L4 --> L3 --> L2 --> L1
The central abstraction is a morphism between finite sets, parameterized by an algebra (a complete lattice with a monoidal product distributing over joins). A morphism f : A -> B is a PyTorch tensor of shape (|A|, |B|) whose entries take values in the algebra; composition f >> g contracts along the shared dimension under the algebra's tensor product and join. Different algebras give different composition semantics: Boolean composes by AND / OR (relational composition), ProductFuzzy by multiplication / noisy-OR, Real by sum-product, Markov by row-stochastic kernel composition, and so on.
The denotational semantics gives every well-typed QVR phrase a formal meaning in a \(\mathcal{V}\)-enriched symmetric monoidal closed category. The implementation rests on enriched category theory (Kelly, 1982), the categorical foundations of probability (Giry, 1982; Fritz, 2020), and the SVI / HMC inference substrate (Hoffman, Blei, Wang & Paisley, 2013; Neal, 2011; Hoffman & Gelman, 2014).
References¶
- Tobias Fritz. 2020. A synthetic approach to Markov kernels, conditional independence and theorems on sufficient statistics. Advances in Mathematics, 370:107239.
- Michèle Giry. 1982. A categorical approach to probability theory. In Bernhard Banaschewski, editor, Categorical Aspects of Topology and Analysis, volume 915 of Lecture Notes in Mathematics, pages 68–85. Springer, Berlin, Heidelberg.
- Matthew D. Hoffman and Andrew Gelman. 2014. The No-U-Turn Sampler: adaptively setting path lengths in Hamiltonian Monte Carlo. Journal of Machine Learning Research, 15(47):1593–1623.
- Matthew D. Hoffman, David M. Blei, Chong Wang, and John Paisley. 2013. Stochastic variational inference. Journal of Machine Learning Research, 14(40):1303–1347.
- Gregory M. Kelly. 1982. Basic Concepts of Enriched Category Theory. Cambridge University Press; reprinted as Reprints in Theory and Applications of Categories 10 (2005):1–136.
- Radford M. Neal. 2011. MCMC using Hamiltonian dynamics. In Steve Brooks, Andrew Gelman, Galin L. Jones, and Xiao-Li Meng, editors, Handbook of Markov Chain Monte Carlo, chapter 5. Chapman & Hall/CRC.