Skip to content

fix: fit coalescent prior on final node times#862

Draft
ivan-aksamentov wants to merge 1 commit into
rustfrom
fix/timetree-coalescent-fit-final-node-times
Draft

fix: fit coalescent prior on final node times#862
ivan-aksamentov wants to merge 1 commit into
rustfrom
fix/timetree-coalescent-fit-final-node-times

Conversation

@ivan-aksamentov

Copy link
Copy Markdown
Member

fix/timetree-coalescent-fit-final-node-times -> rust

Update:

The coalescent (constant or skyline) prior was estimated once before the optimization loop, on the first, pre-reroot node times, and the in-loop re-estimation was gated by i >= 2. Combined with early convergence, a run could keep that pre-loop prior for the whole run, so the reported prior disagreed with the node times the run outputs, and it was fit before the final reroot changed those times.

This re-fits the prior every optimization round on the current node times, and after the loop and any final marginal pass re-fits once more on the final node times. The fit is exposed as TimetreeOutput.coalescent_tc [src], so the reported prior is the maximum-likelihood prior of the tree that is written out.

Under the Kingman coalescent the constant-$T_c$ log-likelihood $\log \mathcal{L}(T_c) = -M\ln T_c - I/T_c$ is strictly unimodal, so the maximum-likelihood $T_c$ of the final tree is unique. Fitting on the final node times makes the reported prior that maximum, and restores v0's intent of conditioning the final node times on the coalescent prior rather than on a first, least-refined tree.

Work items

  • Re-fit the coalescent prior every optimization round on the current node times [src]
  • Re-fit on the output node times after the loop and final marginal pass [src]
  • Expose the fitted prior as TimetreeOutput.coalescent_tc [src]
  • Add a pipeline test asserting the reported $T_c$ maximizes the output tree's coalescent likelihood [src]

Possible improvements

The coalescent/skyline prior was fit once before the optimization loop, on the first, pre-reroot node times, and the in-loop re-estimation was gated by i >= 2. Combined with early convergence, a run could keep the pre-loop prior, so the reported prior disagreed with the output node times (B1) and was fit before the final reroot (N5).

Re-fit the prior every optimization round on the current node times, and after the loop and any final marginal pass re-fit once more on the final node times. Expose that fit as TimetreeOutput.coalescent_tc so the reported prior is the maximum-likelihood prior of the tree written out. A pipeline test asserts the reported constant Tc maximizes the output tree's coalescent likelihood.
@rneher

rneher commented Jul 23, 2026

Copy link
Copy Markdown
Member

yes, refitting every cycle makes sense. The previous schedule and conditioning was not necessary. We can fit the skyline at every iteration, no longer a need to do constant first and then skyline at the end.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants