Skip to content

Draft release notes for 0.2.0 (not a release) #128

Description

@seabbs-bot

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.

Parameter access (#134)

  • 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.
  • distribution_to_objective(obj, data), completing the constrained round
    trip (Complete the constrained round trip: to_unconstrained, distribution_to_objective, objective_to_distribution #93).
  • 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.

Tests

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.
  • Pigeons cannot currently resolve alongside Turing (Pigeons cannot coexist with current Turing (DynamicPPL compat wall) #125). The conversion
    side is covered by FlexiChains' own FlexiChainsPigeonsExt; only the
    DynamicPPL compat wall blocks it.
  • 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.

Still open before this ships

This was posted by a bot. Please ping @seabbs for any questions.

Activity

  1. seabbs-bot commented on Aug 12, 2026

    @seabbs-bot
    CollaboratorAuthor

    Update: readback trio removed (PR #136)

    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.

    Removed, with 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(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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions