Repository navigation
fix: use shuffled child order for leaf labels in queue_shuffle - #225
Merged
Merged
Conversation
With shuffle_cherries = true, child_order can be [c2, c1], but the leaf label mapping still assigned c2 to new_pair.1 and c1 to new_pair.0. When the children were swapped, this wrote the wrong child (sometimes an internal node index) into label_mapping, so the returned mapping was not a permutation of the leaves or did not match v_qs (~92% of calls for n = 5..20). Read the labels from child_order, matching how internal nodes are queued and coded. Add a regression test checking that, with shuffle_cherries, v_qs is ordered, the mapping is a permutation, and the cophenetic distances of v_qs match those of v under the mapping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neclow
self-requested a review
November 2, 2026 10:25
The assert could not detect the shuffle_cherries bug: the bad mappings held unique (internal node) indices, so the check passed. With the fix it cannot fire, and it built a HashSet on every call in release builds. test_queue_shuffle_shuffle_cherries now checks the stronger properties (mapping is a permutation of the leaves, same tree under the mapping). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Check that the new vector is ordered, the mapping is a permutation of the leaves, and the tree is unchanged under the mapping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cover both values of shuffle_cherries: the new vector is ordered, the mapping is a permutation of the leaves, and the tree is unchanged under the mapping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neclow
reviewed
Nov 2, 2026
Collaborator
There was a problem hiding this comment.
Thanks for the PR! Pushed three commits on top:
refactor: removed thelabel_mappinguniqueness assert inqueue_shuffle. It couldn't catch this bug (the bad mappings held unique internal-node indices, so it passed), and with the fix it can't fire, so it was just building aHashSeton every call.test(py):shuffle_cherries=Truetest intest_reorder.py.test(r):queue_shuffletest intest_utils.R(there was none), covering both values ofshuffle_cherries.
| use crate::vector::base::sample_vector; | ||
| use crate::vector::graph::cophenetic_distances; | ||
|
|
||
| for _ in 0..100 { |
Collaborator
There was a problem hiding this comment.
We don't usually use loops for the tests here in Rust, we let Python/R have multiple tests.
Collaborator
There was a problem hiding this comment.
Done in ff5c66b (one sample per case, n = 5, 10, 50, 100).
Rust tests sample one tree per case; repeated random trials are left to the Python and R suites. Use n_leaves = 5, 10, 50, 100 like the other sampled tests in this module. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Problem
queue_shuffle(v, shuffle_cherries=True)returns an invalid label mapping most of the time. Whenchild_orderis swapped to[c2, c1], the leaf-label step still writesc2tonew_pair.1andc1tonew_pair.0:So the wrong child is written whenever the children were swapped. Sometimes that child is an internal node index. The mapping then either isn't a permutation of the leaves or doesn't match
v_qs.Repro (phylo2vec 1.3.1, random
vwith n = 5–20): 925 of 1,000 calls returned an invalid mapping.shuffle_cherries=Falseis unaffected, which is the only case the existing tests cover.Fix
Read the leaf labels from
child_order, the same way internal nodes are queued and coded a few lines above.Tests
New
test_queue_shuffle_shuffle_cherries(n = 3, 10, 50, 100 random vectors each) checks that, withshuffle_cherries = true:v_qsis orderedcophenetic_distances(v_qs)[i][j] == cophenetic_distances(v)[map[i]][map[j]]The test fails on
mainand passes with this change.cargo test -p phylo2vecpasses (340 unit tests and 43 doc tests).cargo fmt --checkand clippy are clean.🤖 Generated with Claude Code