feat: resolve reversion-driven polytomies in the optimize loop - #947
Merged
ivan-aksamentov merged 4 commits intoSep 3, 2026
Conversation
- Add a reversion-driven hoist: when a child edge reverts a substitution on the parent edge, insert a node grouping the child with its sibling subtree and lift the non-reverted substitutions above it, removing one mutation per reversion and adding none. Branch lengths split proportionally to preserve root-to-node distances; indels use an all-or-nothing distance-preserving rule. - Fold the shared-mutation merge, the hoist, and helper-node retirement into a single per-polytomy routine driven to a fixpoint by a monotone (mutation count, node count) potential. Run it every loop iteration, independent of the zero-optimal collapse, so reversions in the input and in polytomies formed by earlier iterations are resolved. - Relocate the two moved edges with reparent_edge to keep their keys and partition state; register the fresh node and edge in dense partitions.
- Require the polytomy node to keep at least two children before hoisting: moving the reverting child under the new node must leave a sibling behind, or the node becomes a childless stub (a spurious leaf). A node whose children all revert the same position merges to a single reverting child and is now left with its residual reversion rather than dissolved.
- Unit-test the hoist move on constructed trees: the untouched substitutions land once above the new node without duplication, chained positions compose onto both output edges, pure reversions drop one mutation, distances are preserved, and per-partition splits are independent. - Unit-test the indel rule for the cancelling, overlapping-fallback, and clean-hoist cases. - Integration-test the merge -> hoist -> retire routine end to end: the worked example reaches the parsimony optimum, incompatible splits stop at the greedy bound, helper retirement spares pre-existing internal nodes, and the root and reversion-free polytomies are left untouched. - Add a loop test proving the hoist fires through prune_and_merge_in_loop with no zero-optimal collapse. - Property-test that the potential never rises and strictly falls on any change, and that leaves, non-negative branch lengths, and the single-root tree shape are preserved. The committed regression seed pins the all-children-revert degenerate case.
6 tasks
ivan-aksamentov
deleted the
feat/optimize-polytomy-reversion-resolution
branch
September 3, 2026 06:28
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolve:
Create:
Update:
A polytomy resolution can place a substitution on a parent edge and revert it on a child -- two mutations where one suffices. These reversions persisted. This adds a reversion hoist that removes them, run together with merge and helper-node cleanup as one fixpoint routine every iteration.
Work items
reparent_edge[src]merge_single_polytomytopub(crate)for reuse by the routine [src]Possible improvements