You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Draft release notes for 0.2.0 (not a release) #128
Draft release notes for the next version, for the owner to review. Nothing is released and nothing is tagged by this issue.
Blocked on a tag first
v0.1.0 is registered in General (JuliaRegistries/General#163656, merged
2026-08-08) but the repository has no v0.1.0 tag and no GitHub Release.
TagBot last ran before the registry merge and has not fired since, so the
registered version names a revision nobody can check out, and #116 reports 121
unreleased commits on main.
That should be resolved before anything below ships, so 0.2.0 has a named
predecessor. It is an owner action.
Proposed version: 0.2.0
Breaking, which under Julia's pre-1.0 convention is a minor bump. Anyone
pinned to 0.1.0 is protected by the resolver. A patch bump would not protect
them, which is why the auto-generated 0.1.1 PR (#133) was closed.
Upgrading
Existing checkouts need Pkg.resolve() before anything will run. Several
dependencies changed this cycle (FlexiChains moved to [deps], ModifiedDistributions and LinearAlgebra were added), and a Manifest.toml
predating them fails with "does not appear in the manifest" or a silent
extension load failure. Manifest.toml is gitignored, so fresh clones are
unaffected. This bit four working trees during development, so it is worth
stating rather than leaving people to discover it.
Breaking changes
FlexiChains is now a hard dependency. It was a weak dependency behind a
package extension; it is now the storage format for inference output. The DistributionsInferenceFlexiChainsExt extension is collapsed into core, and
with it the "extension not loaded" error machinery, since that state can no
longer occur. The DynamicPPL/FlexiChains extension now triggers on DynamicPPL alone.
optimise_distribution's init now takes values on the constrained
scale, the units a caller thinks in, and transforms internally. Previously
it expected unconstrained values, which forced the package's own tutorial to
call to_unconstrained fully qualified to work around the export policy.
point_estimate, distribution_draws and distribution_params are
removed (refactor!: remove the superseded readback API #136). Replacements: distribution_draws(obj, chain) -> inference_to_distributions(obj, chain); point_estimate(obj, chain) -> inference_to_distribution(obj, chain, mean); point_estimate(obj, chain; summary = f) -> inference_to_distribution(obj, chain, f); distribution_params has no direct replacement — nothing in the codebase
depended on its NamedTuple-of-values output for anything but building point_estimate's reconstructed object.
New
Posterior output
inference_to_distribution(obj, chain) returns the equal-weight MixtureModel over draws: the Monte Carlo posterior predictive.
inference_to_distributions(obj, chain) returns one reconstructed
object per draw.
inference_to_distribution(obj, chain, summary) returns the marginal
plug-in. The reduction is positional and required, so the loss of
uncertainty is visible at the call site. Unlike the 2-argument form, this
one does not require reconstruct(obj, x) to return a Distribution
(refactor!: remove the superseded readback API #136): it summarises and reconstructs once, exactly what inference_to_distributions does once per draw, so it is generic in the
same way. Only the 2-argument MixtureModel form needs a Distribution
out, since mixing non-distributions is meaningless.
Aliases inference_to_dist and inference_to_dists.
A single draws keyword on all three, taking nothing, a range, an
index vector, or an Integer n meaning n draws sampled at random across the
pooled set (with an rng keyword). The Integer form exists because draws
pool chain-major, so a hand-written 1:200 on a four-chain run returns 200
draws from chain 1 alone.
inference_to_parameters(obj, chain) returns the estimated rows' draws
keyed by their dotted names, as a Tables.jl-compatible column table — a NamedTuple of equal-length vectors satisfies Tables.jl structurally, so DataFrame(result) works with no dependency added.
inference_to_parameter_distribution(obj, chain) fits an MvNormal to
those draws on the unconstrained scale, keeping the joint posterior's
correlations. The scale matters: a Gaussian fitted on the constrained scale
places mass on negative shapes and scales. Intended for Markov melding,
where a fitted posterior becomes a joint prior scored through extra_logprior rather than per-row priors, since per-row priors cannot
carry correlation.
Fitting
distribution_to_turing(obj, data, sampler, nsamples) returning a
chain, alongside the existing model-returning method, which is unchanged.
distribution_to_advancedmh(obj, data, sampler, nsamples), a second
engine proving the contract.
Public accessors template, observations and flat_priors on FitLogDensity, so an engine author never reads a struct field.
draws_to_chain public, for keying raw sampler draws into a chain.
The ModifiedDistributions extension is un-parked (feat: un-park the ModifiedDistributions extension #130), now that
ModifiedDistributions 0.1.0 is registered: the fit protocol works for a
standalone modifier distribution, not only as a leaf inside a composed tree.
Performance
Batch record scoring is roughly 7.6x faster (perf(engine): convert a NamedTuple-record batch once at FitLogDensity construction #132). A NamedTuple
batch previously allocated a fresh Vector{Union{Missing, Float64}} per
record per evaluation. The batch is now converted once at FitLogDensity
construction: 54.5 us -> 7.2 us on a 200-record batch, and about 5.6x under
a ForwardDiff gradient, with allocations down about 7.5x. The Missing-admitting element type is preserved, so the censored logpdf
specialisation is still selected.
Fixed
distribution_draws silently returned only the first chain's draws
(readback_draws silently drops every chain but the first #89). Two index ranges were built from the iteration count alone against a
column-major flattening of iterations by chains, so a four-chain run
returned a quarter of its draws with nothing reported. Summaries with
default arguments were unaffected; per-draw readback and filtered selection
were not. This shipped in the registered 0.1.0.
init containing a non-finite value raised an uncaught DomainError from
inside the transform rather than the intended named error, because the
finite check ran on the post-transform value.
An orphaned Mooncake extension declaration with no corresponding file,
reintroduced as a rebase artefact, which made every AD test item that loaded
Mooncake log an extension-load failure.
Both pooling implementations are pinned to the chain-major layout by tests
using disjoint per-chain values, so a transposed layout fails loudly rather
than producing plausible but wrong subsamples.
Known limitations to state in the notes
inference_to_distribution's quantile is O(K) per root-finding step and
costs roughly 13 ms at 8000 draws. mean, rand, pdf and cdf are
cheap. Callers wanting many quantiles should thin with draws. There is
deliberately no hidden default cap, because a hidden one would make results
depend on an invisible parameter.
inference_to_parameter_distribution refuses a covariance that is not
positive definite, which happens with fewer draws than parameters or with
parameters collinear on the unconstrained scale.
A ComposedDistributions centred pool cannot be fitted through distribution_to_turing or distribution_to_advancedmh (distribution_to_turing rejects a centred pool #109). Rows scored
via extra_logprior have no per-row prior, so there is neither a sampling
site nor a bijector to build. The log-density route covers the case.
point_estimate, distribution_params and distribution_draws are removed as of PR #136, so the "known limitation"/"still open" items below about them are resolved. Recording the final shape here rather than editing history into the sections below.
distribution_params(obj, chain): no direct replacement. Confirmed nothing in the codebase depended on its NamedTuple-of-values output for anything but building point_estimate's reconstructed object.
One more breaking-adjacent fix landed alongside it:inference_to_distribution(obj, chain, summary) (the 3-argument form) no longer requires reconstruct(obj, x) to return a Distribution. That requirement was an inconsistency inherited from the 2-argument MixtureModel form (which still requires it, correctly) rather than a real constraint on the 3-argument form's summarise-then-reconstruct-once operation. Without this, the point_estimate -> inference_to_distribution mapping above would not have held for non-Distribution fittable objects, which is most of this package's own fixtures and tutorials.
0.2.0 therefore ships without the readback trio, resolving the "decide whether 0.2.0 ships with them present or absent" question below in favour of absent.
This was posted by a bot. Please ping @seabbs for any questions.
Draft release notes for the next version, for the owner to review.
Nothing is released and nothing is tagged by this issue.
Blocked on a tag first
v0.1.0 is registered in General (JuliaRegistries/General#163656, merged
2026-08-08) but the repository has no
v0.1.0tag and no GitHub Release.TagBot last ran before the registry merge and has not fired since, so the
registered version names a revision nobody can check out, and #116 reports 121
unreleased commits on main.
That should be resolved before anything below ships, so 0.2.0 has a named
predecessor. It is an owner action.
Proposed version: 0.2.0
Breaking, which under Julia's pre-1.0 convention is a minor bump. Anyone
pinned to 0.1.0 is protected by the resolver. A patch bump would not protect
them, which is why the auto-generated 0.1.1 PR (#133) was closed.
Upgrading
Existing checkouts need
Pkg.resolve()before anything will run. Severaldependencies changed this cycle (
FlexiChainsmoved to[deps],ModifiedDistributionsandLinearAlgebrawere added), and aManifest.tomlpredating them fails with "does not appear in the manifest" or a silent
extension load failure.
Manifest.tomlis gitignored, so fresh clones areunaffected. This bit four working trees during development, so it is worth
stating rather than leaving people to discover it.
Breaking changes
package extension; it is now the storage format for inference output. The
DistributionsInferenceFlexiChainsExtextension is collapsed into core, andwith it the "extension not loaded" error machinery, since that state can no
longer occur. The
DynamicPPL/FlexiChainsextension now triggers onDynamicPPLalone.optimise_distribution'sinitnow takes values on the constrainedscale, the units a caller thinks in, and transforms internally. Previously
it expected unconstrained values, which forced the package's own tutorial to
call
to_unconstrainedfully qualified to work around the export policy.point_estimate,distribution_drawsanddistribution_paramsareremoved (refactor!: remove the superseded readback API #136). Replacements:
distribution_draws(obj, chain)->inference_to_distributions(obj, chain);point_estimate(obj, chain)->inference_to_distribution(obj, chain, mean);point_estimate(obj, chain; summary = f)->inference_to_distribution(obj, chain, f);distribution_paramshas no direct replacement — nothing in the codebasedepended on its
NamedTuple-of-values output for anything but buildingpoint_estimate's reconstructed object.New
Posterior output
inference_to_distribution(obj, chain)returns the equal-weightMixtureModelover draws: the Monte Carlo posterior predictive.inference_to_distributions(obj, chain)returns one reconstructedobject per draw.
inference_to_distribution(obj, chain, summary)returns the marginalplug-in. The reduction is positional and required, so the loss of
uncertainty is visible at the call site. Unlike the 2-argument form, this
one does not require
reconstruct(obj, x)to return aDistribution(refactor!: remove the superseded readback API #136): it summarises and reconstructs once, exactly what
inference_to_distributionsdoes once per draw, so it is generic in thesame way. Only the 2-argument
MixtureModelform needs aDistributionout, since mixing non-distributions is meaningless.
inference_to_distandinference_to_dists.drawskeyword on all three, takingnothing, a range, anindex vector, or an
Integern meaning n draws sampled at random across thepooled set (with an
rngkeyword). TheIntegerform exists because drawspool chain-major, so a hand-written
1:200on a four-chain run returns 200draws from chain 1 alone.
Parameter access (#134)
inference_to_parameters(obj, chain)returns the estimated rows' drawskeyed by their dotted names, as a Tables.jl-compatible column table — a
NamedTupleof equal-length vectors satisfies Tables.jl structurally, soDataFrame(result)works with no dependency added.inference_to_parameter_distribution(obj, chain)fits anMvNormaltothose draws on the unconstrained scale, keeping the joint posterior's
correlations. The scale matters: a Gaussian fitted on the constrained scale
places mass on negative shapes and scales. Intended for Markov melding,
where a fitted posterior becomes a joint prior scored through
extra_logpriorrather than per-row priors, since per-row priors cannotcarry correlation.
Fitting
distribution_to_turing(obj, data, sampler, nsamples)returning achain, alongside the existing model-returning method, which is unchanged.
distribution_to_advancedmh(obj, data, sampler, nsamples), a secondengine proving the contract.
distribution_to_objective(obj, data), completing the constrained roundtrip (Complete the constrained round trip: to_unconstrained, distribution_to_objective, objective_to_distribution #93).
template,observationsandflat_priorsonFitLogDensity, so an engine author never reads a struct field.draws_to_chainpublic, for keying raw sampler draws into a chain.ModifiedDistributionsextension is un-parked (feat: un-park the ModifiedDistributions extension #130), now thatModifiedDistributions 0.1.0 is registered: the fit protocol works for a
standalone modifier distribution, not only as a leaf inside a composed tree.
Performance
NamedTuplebatch previously allocated a fresh
Vector{Union{Missing, Float64}}perrecord per evaluation. The batch is now converted once at
FitLogDensityconstruction: 54.5 us -> 7.2 us on a 200-record batch, and about 5.6x under
a ForwardDiff gradient, with allocations down about 7.5x. The
Missing-admitting element type is preserved, so the censored logpdfspecialisation is still selected.
Fixed
distribution_drawssilently returned only the first chain's draws(readback_draws silently drops every chain but the first #89). Two index ranges were built from the iteration count alone against a
column-major flattening of iterations by chains, so a four-chain run
returned a quarter of its draws with nothing reported. Summaries with
default arguments were unaffected; per-draw readback and filtered selection
were not. This shipped in the registered 0.1.0.
initcontaining a non-finite value raised an uncaughtDomainErrorfrominside the transform rather than the intended named error, because the
finite check ran on the post-transform value.
Mooncakeextension declaration with no corresponding file,reintroduced as a rebase artefact, which made every AD test item that loaded
Mooncake log an extension-load failure.
Tests
tree fixture gives its leaves different prior families, so
flat_priorsisabstractly typed (The ComposedDistributions AD scenarios do not cover the abstract-prior path the Enzyme bug lived in #78).
using disjoint per-chain values, so a transposed layout fails loudly rather
than producing plausible but wrong subsamples.
Known limitations to state in the notes
inference_to_distribution'squantileis O(K) per root-finding step andcosts roughly 13 ms at 8000 draws.
mean,rand,pdfandcdfarecheap. Callers wanting many quantiles should thin with
draws. There isdeliberately no hidden default cap, because a hidden one would make results
depend on an invisible parameter.
inference_to_parameter_distributionrefuses a covariance that is notpositive definite, which happens with fewer draws than parameters or with
parameters collinear on the unconstrained scale.
side is covered by FlexiChains' own
FlexiChainsPigeonsExt; only theDynamicPPL compat wall blocks it.
ComposedDistributionscentred pool cannot be fitted throughdistribution_to_turingordistribution_to_advancedmh(distribution_to_turing rejects a centred pool #109). Rows scoredvia
extra_logpriorhave no per-row prior, so there is neither a samplingsite nor a bijector to build. The log-density route covers the case.
Still open before this ships
Remove the superseded readback API, or decide to keep it for oneDone: removed in refactor!: remove the superseded readback API #136.version.
Reverse the FlexiChains direction and take it off the readback path #91 and Settle the naming convention and the export policy before registration #92 need closing or re-scoping.Done: both closed.Define an inference-engine contract: distribution_to_trace(obj, data, engine) #94 is delivered by the engine verbs.Done: closed.This was posted by a bot. Please ping @seabbs for any questions.