definition design implementation
A Lenticulum factor is a parameterized statistical game in the sense of AutoBayes (Definition 27): a Bayesian lens — a forward kernel plus an approximate inversion — decorated with an energy and an entropy, all of which may depend on parameters ps. This is the one-line difference from Lux.jl:
and the lens is not stored but assembled on demand, once a polarity says which channels are observed. Lenticulum’s own departure from the paper is that the energy is vector-valued (Scalar and Multivariate Energy).
Sources: St Clere Smithe & Perin, AutoBayes (arXiv:2503.18608) Definitions 20, 22, 27–29, Theorem 23, Remarks 24, 26, 30 and the closing discussion; code:
lib/LenticulumCore.jl/src/statistical_game.jl,lens.jl,energy.jl,abstract_types.jl(statistical_game, energy, lens).Theory (CT-ML wiki): Statistical Game · Bayesian Lens · Variational Free Energy · Para Construction · Lax Functor · paper note
The four pieces, as four independent choices
| piece | in the paper | in Lenticulum | what varies |
|---|---|---|---|
| forward kernel | the model half of assemble(f, polarity, ps, st) | architecture | |
| inversion | an AbstractInversion: exact, amortised, solver, proximal, trivial | how the posterior is approximated (Inversions and Bayesian Lenses) | |
| energy | energy(f, …), a vector in energyspace(f) | NLL, residual, robust loss | |
| entropy | entropy(f, π, y, …), in the same energy space | Shannon, a KL, -weighted, zero |
and the loss is free_energy(f, π, y, ps, st) — a vector — collapsed by scalar_free_energy through the factor’s scalarisation. The type difference matters: the energy eats points (evaluated inside an expectation, cheap, no normalisation), the entropy eats a distribution. That is why they compose differently.
Composition: energies add, entropies chain
Definition 22 composes and by adding energies and chaining entropies, and Theorem 23 gives the free-energy chain rule . In Lenticulum:
compose(c, d; coupling)builds aComposedFactor;compose_energyreturns aGradedEnergy(the direct sum that replaces the paper’s ),compose_entropyandcompose_free_energyimplement the chain rule from samples of the downstream inversion, andchain_rule_defectreports the Jensen gap between the vector and scalar chain rules.TensorFactoris parallel composition — lax, with the defect the mutual information of the branches (Remark 26). Lenticulum’s rule is report the laxness, do not hide it.- On a graph, “downstream” is a property of the message schedule, not of the wiring, so Mycelium reports the order-free Bethe form instead (Bethe Free Energy).
The recursion is a fold with two sweeps — priors forward (pushforward), samples backward (inversions) — the same shape as forward/backward autodiff, except that the backward sweep is stochastic and the forward one carries distributions. The paper names the two expensive steps: pushforward priors (marginalisation — Mycelium’s job, by message passing) and expectations under the inversions (sampling or conjugacy).
Priors, data and losses are factors (Remark 24)
A pure game’s loss lacks the prior term of the free energy; AutoBayes fixes this by making the prior its own game with trivial inversion, energy and zero entropy. Lenticulum takes this literally: a prior is a PriorFactor, data is a DataFactor (a cup — a hard clamp), a loss is a LossFactor (a sink), and an optimiser is an OptimiserFactor on an exposed parameter variable. See Everything is a Factor.
Parameters, and the gradient the paper asks for
Any of the four pieces may depend on (Definition 27): a decoder, an amortised encoder, a learned loss or critic, a learned regulariser. The parameter tree is Lux’s — initialparameters returns a nested NamedTuple, which is the composite of Definition 28 with labels. The paper’s default semantics is descent with respect to the Fisher metric (the Bayesian learning rule); the multivariate energy is what makes a Gauss–Newton approximation of that metric available (Scalar and Multivariate Energy §6).
Definition 29 composes gradients block-diagonally and is therefore lax: it drops the terms where an upstream parameter moves the downstream pushforward prior and where a downstream parameter moves the sampling distribution of the upstream inversion — the reparametrisation/score-function terms. Lenticulum makes the choice explicit per edge, as an AbstractGradientCoupling:
| coupling | keeps | cost |
|---|---|---|
DiagonalCoupling() | block diagonal only (stop-gradient) | cheapest, biased |
PathwiseCoupling() | differentiates through the sampler | needs a reparametrisable inversion |
ScoreFunctionCoupling(baseline) | REINFORCE estimate of the dropped term | unbiased, high variance |
ExactCoupling() | everything | conjugate / analytic factors only |
These are the paper’s “different semantics functors” — different lax sections of the gradient fibration (Remark 30) — and The Type Discipline of a Factor Graph §4 observes that together they form an effect system with no composition rule yet.
The engineering agenda the paper leaves
- Pushforward by message passing — belief propagation / variational message passing approximates (Factor Graphs, Schedules).
- Expectations under inversions — sampling, or conjugacy where available (the linear-Gaussian fragment: The Linear Gaussian Chain).
- Conjugacy is not preserved by pushforward — moment-matching projections back into a family are needed, and they are again lax.
tab: Julia
**Docs:** [LenticulumCore API](https://mathstruct.org/Lenticulum.jl/dev/packages/lenticulumcore/) · [Lenticulum API](https://mathstruct.org/Lenticulum.jl/dev/packages/lenticulum/)
```julia
using Lenticulum, LenticulumCore, Mycelium, Random
f = GaussianFactor(1 => 1; noise = 0.25, channels = (:x, :y)) # y = A x + b + ε
ps, st = LenticulumCore.setup(Random.Xoshiro(0), f) # the Para parameter tree
keys(ps) # (:A, :b)
supported_polarities(f) # x → y and y → x
energyspace(f) # graded: (:fit, :complexity, :negentropy) — a vector energy
islinear(scalarisation(f)) # true: scalarising commutes with composition here
```