What is skoro?
A library for writing a probabilistic model once and running any inference algorithm on it, built for models that live over time.
Skoro is a Rust library for writing probabilistic models once, generatively, and running different inference algorithms on the same model. This page says what that means, who it is for, and the ideas the rest of the library follows from. The argument for each of them is in the charter.
One model, written generatively#
A model is written the way it is thought of: each uncertain quantity, and the conditional distribution it has given the quantities it depends on. Consider a range measurement between a vehicle at and a target at :
That one statement serves three situations. The vehicle and the target can be estimated jointly from ; the vehicle alone can be estimated from when the target is known; and can be simulated from given and . In skoro these are not three models. The model holds the joint distribution, and which quantities are observed is part of each question asked of it, so the same model answers all three, from different threads at once.
Factor-graph libraries, by contrast, describe a model by the residuals of one particular posterior. Each of the three situations needs a different set of factors, and the third, simulation, cannot be expressed at all.
Inference reads the model#
The library records a model’s structure as the model is built, much as automatic differentiation records a computation: which quantities depend on which, what each density term scores, which of its parts are a residual or a whitening factor, which operations can be differentiated to second order. An inference algorithm reads what it needs from that record. If the model meets the algorithm’s assumptions, the algorithm runs; if not, it refuses before it starts and names what is missing and where. The user never describes the model a second time for the algorithm’s benefit.
Models that live over time#
Skoro is built for sequential estimation, where a model is never finished:
- It grows. Each tick appends new states and measurements, and each kind of measurement can be different.
- It forgets. States that stop mattering are marginalized onto what remains and retired.
- It branches. When it is uncertain which target a measurement came from, the model is held under several hypotheses at once, as cheap branches of one another, and an algorithm weighs them.
- It is shared. One writer builds while estimators run on immutable snapshots of the model, without waiting for each other.
Sub-models are ordinary functions of quantities, placed under namespaces by the code that calls them, so the model of one tick is written once and reused for every tick.
Who it is for#
- People developing inference algorithms. Skoro’s first purpose is to make new algorithms easy to write against real models: what an algorithm can discover about a model matters as much as how a model is built.
- People building real-time estimators for robots and autonomous systems, on CPU or GPU, from Rust, often under several hypotheses at once.
- People doing Bayesian inference with quantities that live on manifolds, such as rotations and poses, or that need second-order derivatives.
What it is not#
- Not a general probabilistic programming language. Each model has a fixed structure, built forward. Structure that is itself random is handled one level up, over a family of models, rather than by programs whose shape changes as they run, as in Gen.jl.
- Not a replacement for mature solvers. It does not compete with GTSAM or Ceres on the maturity of its least-squares solvers, nor with Stan or NumPyro on the breadth of its distributions. What it offers is the combination: one generative model, a structure algorithms can read, manifold-aware derivatives of second order, and a model that lives across threads and over time.
The ideas everything follows from#
The charter argues each of these in full:
- Conditioning belongs to the query, never to the model.
- Derivatives come from composition. A few primitive operations carry hand-written derivatives, and everything else, distributions and manifold retractions included, is built from them; each operation reports the order of derivative it supports.
- Static at the edges, dynamic inside. Models are written with typed handles the compiler checks, while everything stored inside is nameable, so models can be serialized and driven from other languages.
- Randomness is explicit. Every random draw comes from a key, so one seed reproduces a run.
- Precision belongs to the query. A model commits to no float precision; each estimator chooses its own, and the solves where conditioning matters run on the host in double precision.
How this came to be
The development behind this page, newest first:
- What skoro is Done The library's charter: what skoro is for, who it serves, and the positions on which everything else in it rests. It was written when the repository started over, from an interrogation of the design that came before (kept on the archive branch), so that each later entry has a stated purpose to build towards and to be measured against. It settled skoro's purpose and its users, and twelve positions on the shape of its core; the home page and What is skoro? were written from it.