Conversation
The optimality-gap audit (#197) found the fitted v1 objective under-discriminative: on holdout songs the DP's fixed tie-break keeps 44.1% agreement with tab authors while the optimum set contains 55.5%. This opens the follow-up: measure that set exactly with chain DPs instead of an external solver, and learn a human-blind tie-break inside it. Pins, against brute force on exhaustive small families: - Chain::v1 mirrors the production objective path by path; - optimum_set: optimum, exact path count (saturating u64 with an exact natural log), and least / most / expected agreement with a reference among optimal paths, plus a most-agreeing optimal path — the achievable learning target; - lexicographic_path is primary- then secondary-optimal, reproduces the production DP path exactly with zero secondary weights, and with loss augmentation finds the least-agreeing optimal path; - path_features sums the per-note and per-transition secondary features; - train_secondary (averaged, loss-augmented structured perceptron over integer weights) converges on a separable tie-break, generalizes to held-out lines, is deterministic, and makes no update when the target is already chosen. All new functions are todo!() stubs (13 red); the existing 78 lab tests stay green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ie-break ties::Chain holds the v1 objective per line (candidates in production order, unary and pairwise costs). optimum_set solves forward and backward cost tables with path counts (saturating u64 plus an exact natural log via log-add), marks nodes and edges on optimal paths by f + g == optimum, and reads off: the optimal-path count; least and most reference agreement by min/max DPs over optimal edges, with a most-agreeing optimal path as the achievable learning target; and the expected agreement under a uniform draw from the optimum set (paths through a candidate / total, in log space). lexicographic_path minimizes (primary i64, secondary i128) with strict comparisons, so zero secondary weights reproduce the production DP path exactly; loss augmentation adds a margin per reference-matching note. train_secondary is an averaged structured perceptron over integer weights inside the primary optimum set, updating toward the achievable target and stopping after an epoch without updates. Contract suite green (13 ties + 78 existing); clippy clean at the crate's deny level (pedantic too_many_lines warnings only). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ties-check compares the exact optimum-set DPs with verified CP-SAT records (optimum and agreement ceiling per line). tiebreak reports the tie-break ladder for a v1 primary — floor, uniform over optima, production tie-break, learned tie-break, ceiling — plus optimal-path counts and unique-optimum lines; it trains the secondary on train songs with a song-level validation bucket for the margin and evaluates on holdout songs. Lines carry their holdout bucket, and the ladder counts lines where the learned tie-break changes the production path. First runs on the corrected corpus: the exact DPs agree with CP-SAT on all 1,954 holdout lines for v1 and v1-fit (optimum and ceiling). The learned tie-break changed 0 of 7,091 train lines — traced to the training setup, not the DP (fixed targets conflict across lines; margins far below the weight scale), addressed next. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The first tie-break run learned weights that changed 0 of 7,091 train lines. One cause is the fixed target: best_path breaks ties among the most-agreeing optimal paths by candidate index, so equally good targets disagree across similar lines and the perceptron chases conflicting updates. The standard remedy is a latent target — among the optimal paths that agree most with the tab author, the one cheapest under the current secondary weights. Pins latent_target against brute force: primary-optimal, most agreeing, then least secondary cost; equal to best_path under zero weights; refused for a reference of another length. Stub is todo!() (1 red). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
lexicographic_path and latent_target share one DP minimizing (primary, middle, secondary) with strict comparisons: Plain ignores the reference, Augment adds the margin to the secondary per matching note, Latent puts −matches in the middle so the most-agreeing optimal paths win before the secondary cost. Zero weights still reproduce the production path, and the latent target under zero weights equals best_path. train_secondary now updates toward the latent target under the current weights instead of a fixed best_path, removing conflicting targets across lines with equally good choices. Suite green (14 ties + 78 existing); clippy clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
With the latent target and margins up to 10,000, the learned tie-break still changed only 7 of 7,091 train lines. Diagnosis on train songs: where a most-agreeing optimal path differs from production, the tab author plays the same pitch one or two strings lower and higher up the neck (+1 string/+5 frets 50%, +1/+4 40%, +2/+9 7%) — yet in ~75% of lines the author agrees with production, so no global local-geometry weight separates the cases; 42.5% of the differing notes sit in repeated-pitch runs, where travel inside the line is free. The deciding information lies outside the line: the author's choice is closer to the fret of the last fretted event before the line in 63% of differing lines (production's in 33%). Pins that context as a measured feature: - TabLine::anchor_fret — the fret of the latest positioned, fretted note of the voice before the line (lowest fret at a chord onset; open strings and unpositioned notes skipped; None at a voice's start); - Chain::with_anchor / anchor and the anchor_distance secondary feature (|fret − anchor| per fretted note), primary cost unchanged; - brute-force secondary optimality with anchored chains, and a perceptron that learns an anchor-nearest tie-break on held-out lines. TabLine carries anchor_fret: None and with_anchor is todo!() here (4 red). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…feature tab_lines tracks, per voice, the lowest fretted position at the latest onset seen (chord notes included, open strings and unpositioned notes skipped) and stamps it on a line when its first note arrives: the fret the hand was at just before the line. Chain::with_anchor keeps the primary objective and feeds anchor_distance (|fret - anchor| per fretted note) to the secondary features. Suite green (30 fingering + 17 ties + 49 spike/optir); clippy clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…chor tiebreak now trains and reports two secondary variants per primary: local fingering-geometry features only, and the same plus anchor_distance to the line's hand anchor. Margins span 0 to 10^7 and training runs 20 epochs; the margin is chosen on the song-level validation bucket per variant, and the ladder reports lines whose path the learned tie-break changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Archives the optimum-set and learned tie-break results (aggregates only): exact DPs verified against CP-SAT optima and ceilings on 1,954 / 1,954 holdout lines; the tie-break ladder under v1-fit — floor 32.4%, uniform 42.9%, production 44.1%, learned local 44.0%, learned local + hand anchor 47.3%, ceiling 55.5%; tie structure and the v1 control; the diagnosis that tab authors' deviations are one-directional (lower string, higher fret) but context-dependent, with the preceding fretted event closer to the author's choice in 63% of differing lines; limitations (human-sourced anchor, linear non-convergent learner) and follow-ups. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
What
Follow-up to #197. Under the fitted
v1weights the production DP keeps 44.1% agreement with tab authors on holdout songs, while the set of cost-optimal fingerings contains 55.5%. That gap needs no new primary objective, only a better choice among ties. This PR measures the tie sets exactly, learns a human-blind lexicographic tie-break, and locates the information the authors used.Research tooling only (
lab/, not a workspace member); no production code changes.Built (red → green per commit)
lab/src/ties.rs:optimum_set— exact chain DPs: optimal-path count (saturatingu64+ exact ln), least / most / uniform-expected agreement among optimal paths, a most-agreeing optimal path;lexicographic_path— primary, then secondary; zero weights reproduce the production path exactly; optional loss augmentation;latent_target— cheapest most-agreeing optimal path under current weights;train_secondary— averaged, loss-augmented, latent-target perceptron on integer weights;anchor_distance.TabLine::anchor_fret— the fret of the latest fretted note before a line (lowest at a chord onset).fingering_gap ties-check(DPs vs verified CP-SAT records) andtiebreak(song-level fit/validation/test, margin chosen on validation, local vs local + anchor ablation).Results (holdout songs, primary v1-fit)
v1andv1-fit, both optimum and ceiling. The ceiling now costs milliseconds.v1weights the optimum is unique in 87% of lines, the whole ladder spans 35.7–36.2%, and the learned tie-break sits inside it at 36.1%.Full write-up:
docs/audit/2026-09-fingering-tie-break.md.Limitations
Checks
cd lab && cargo test: 96 tests green (17 ties, 30 fingering, 13 optir, 24 oracle spike, 12 propagate), including brute-force contracts and zero-secondary equality withinfer_positions.cargo fmt --checkclean; clippy clean at the crate's deny level.🤖 Generated with Claude Code