Skip to content

Bound Rogue SPR candidates with parent dual prices - #215

Merged
ms609 merged 7 commits into
mainfrom
claude/project-thread-dwoyrq
Oct 14, 2026
Merged

ms609 merged 7 commits into
mainfrom
claude/project-thread-dwoyrq

Conversation

@ms609

@ms609 ms609 commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Before: for almost every candidate leaf, SPRDist(method = "Rogue") solves a full LAP, and 89% of those LAPs end below the running minimum. The LAP accounts for 52% of runtime at 80 leaves and 66% at 150.

After: the parent pair's LAP is solved once, lazily, on the first candidate that passes the row bound. Each candidate's splits are then priced with the parent's column duals.

  • For any prices v, LB(v) = Σ_j v_j + Σ_i min_j (c_ij − v_j) is at most the optimal assignment cost. The bound is therefore exact in int64, and the prices affect only speed.
  • The bound rejects 82–88% of the LAPs that would otherwise only reject.
  • The remaining LAPs warm-start JV from v (src/lap_warm.cpp, kept in its own translation unit so that lap()'s codegen is untouched).

Wall-clock (prototype, eager prices; minimum over interleaved runs):

Workload Baseline (s) This PR (s) Change
30 leaves, random 0.423 0.343 −19%
80 leaves, random 4.00 1.94 −51%
150 leaves, random 18.2 6.40 −65%
150 leaves, 30 moves apart 1.31 1.00 −23%
Near-identical pairs no change (noise)

Verification:

  • SPRDist() output was identical on 345 pair runs.
  • Across 650,676 candidate scores the largest difference was 7e-15, and the argmin sets were identical.
  • After this rebase onto main, SPRDist() matches the R path on 40 random pairs of 8–60 leaves.
  • Local covr on the SPR tests leaves no new line uncovered. The unreachable guards are marked #nocov.

The research write-up and scripts are in dev/rogue_mci_bound_findings.md and dev/rogue_bound/, which .Rbuildignore excludes from the package build.

🤖 Generated with Claude Code

https://claude.ai/code/session_014CDmnvPhnKFWMrQgqPKVY7

Solve the parent pair's assignment once per spr_rogue_scores() call and
price each candidate's splits with the parent column duals.  The bound
sum(v) + sum_i min_j(c_ij - v_j) is valid for any prices, so it is exact
in int64; candidates it rejects skip the LAP, and the rest warm-start JV
from the same prices (lap_warm.cpp).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014CDmnvPhnKFWMrQgqPKVY7
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014CDmnvPhnKFWMrQgqPKVY7
Benchmarks, workloads, offline LAP-bound analyzer and patches behind
dev/rogue_mci_bound_findings.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014CDmnvPhnKFWMrQgqPKVY7
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014CDmnvPhnKFWMrQgqPKVY7
Skip the parent LAP when the row bound rejects every candidate, as on
near-identical pairs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014CDmnvPhnKFWMrQgqPKVY7
@ms609
ms609 marked this pull request as ready for review October 14, 2026 10:28
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014CDmnvPhnKFWMrQgqPKVY7
spr_rogue_scores() requires binary trees (reduce_trees() overflows on a
star, flagged by ASan); the empty-split guard it covered is unreachable
from SPRDist() and is marked #nocov.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014CDmnvPhnKFWMrQgqPKVY7
@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown

Performance benchmark results

Call Status Change Time (ms)
ClusteringInfoDistance(tr280) ⚪ NSD 0.19% 9.29, 9.26 →
9.27, 9.22
ClusteringInfoDistance(tr50) ⚪ NSD -0.69% 6.64, 6.63 →
6.73, 6.66
LAPJV(test2000) ⚪ NSD -0.1% 95.3, 95.1 →
94.9, 95.3
LAPJV(test40) ⚪ NSD -1.93% 0.0176, 0.0178 →
0.018, 0.0181
LAPJV(test400) ⚪ NSD -0.91% 3.2, 3.21 →
3.23, 3.24
MutualClusteringInfo(tr280) ⚪ NSD -1.21% 17.9, 18.2 →
18.1, 18.4
MutualClusteringInfo(tr50) ⚪ NSD -0.19% 17.3, 17.2 →
17.8, 17.1
NNIMaxStep(2000, normalize = TRUE) ⚪ NSD 0.25% 0.215, 0.216 →
0.214, 0.216
NNIMaxStep(300, normalize = TRUE) ⚪ NSD 0% 0.0315, 0.0316 →
0.0317, 0.0315
NNIMaxStep(300) ⚪ NSD -0.35% 0.0087, 0.00889 →
0.00886, 0.0088
PathDist(postTrees) ⚪ NSD -0.27% 2.39, 2.38 →
2.39, 2.4
PhylogeneticInfoDistance(tr180) ⚪ NSD 1.01% 59, 57.9 →
58.3, 58.2
PhylogeneticInfoDistance(tr50) ⚪ NSD 0.3% 44.9, 43.5 →
43.7, 44.2
RobinsonFoulds(tr280) ⚪ NSD 0.21% 4.76, 4.75 →
4.75, 4.74
RobinsonFoulds(tr280) ⚪ NSD 0.11% 4.57, 4.57 →
4.6, 4.56
RobinsonFoulds(tr50) ⚪ NSD -0.98% 4.57, 4.56 →
4.61, 4.59

@codecov

codecov Bot commented Oct 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.57%. Comparing base (64e9127) to head (2095b68).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #215      +/-   ##
==========================================
+ Coverage   97.44%   97.57%   +0.12%     
==========================================
  Files          59       60       +1     
  Lines        5762     6065     +303     
==========================================
+ Hits         5615     5918     +303     
  Misses        147      147              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ms609
ms609 merged commit 00d2b8f into main Oct 14, 2026
21 checks passed
@ms609
ms609 deleted the claude/project-thread-dwoyrq branch October 14, 2026 12:43
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