TuringLang / TuringLang/SSMProblems.jl

Ancestor Callbacks are type unstable

Open
#124 1 comment 0 reactions 1 assignee View on GitHub

@charlesknipp is already working on this.

Since Dec 2, 2025.

Dominant language
Julia
Stars
11
Forks
7
PR merge metrics
No merged PRs in 30d

Description

The title is a little misleading, but illustrates the crux of a very persistent issue. In #101, we establish that initial draws can be different than states generated from the dynamics; this implies that their types need not be the same. In cases like automatic differentiation where targeted parameters are left out of the state prior, we need disentanglement.

While #101 is merged, there are still remnants of this issue which exist uniquely in the callbacks. This was highlighted in a comment left by @THargreaves in https://github.com/TuringLang/SSMProblems.jl/issues/122#issuecomment-3585749254, where an aesthetic change to the prior results in error due to the types.

What Gives

To collect a path of ancestors, we require pre-populating a container with roots that begin at the initial draw. As the filter progresses, subsequent states need not be the same type as the roots. For the sparse ancestry storage, this should be a brief modification to the callback:

function (c::AncestorCallback)(
    model, filter, step, state, data, ::PostPredictCallback; kwargs...
)
    particles = state.particles
    if step == 1
        N = num_particles(filter)
        c.tree = ParticleTree(getfield.(particles, :state), floor(Int64, N * log(N)))
    else
        prune!(c.tree, getfield.(particles, :ancestor))
        insert!(c.tree, getfield.(particles, :state), getfield.(particles, :ancestor))
    end
    return nothing
end

The main issue here is that we no longer store the initial draw as part of this structure. Furthermore (even though resampling shouldn't occur), we also lose a potential change in ancestry from particles at time 0 to time 1. Subsequently, we would have to change the behavior of ref_traj to something like a custom object instead of an OffsetVector.

I think this may be an easy fix, but it requires some discussion as to how we go about defining trajectories and priors.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.