Add Luce Spectral Ranking (LSR / I-LSR) paired-comparison estimators - #292
Merged
Conversation
Implements choix 0.4.1's lsr.py dense pairwise path (source READ;
Maystre & Grossglauser 2015 NOT READ, cited as described by choix):
one-shot spectral estimate and iterative MLE from an n x n win-count
matrix. Rust core (mlsirm_core::scaling::{lsr_pairwise, ilsr_pairwise})
with Gaussian-elimination statdist guarded by positivity, sum, and
residual checks; overflow from huge counts/alpha raises instead of
returning NaN. I-LSR at alpha=0 reproduces the Bradley-Terry MLE
(cross-algorithm anchor vs bradley_terry_mm); alpha>0 regularization
semantics deliberately differ (chain-rate vs Dirichlet-MAP, per source).
Pins from an EXECUTED exact-Fraction/mpmath oracle cross-checked with
pip choix 0.4.1 (<= 2.2e-13). Six mutation kills EXECUTED (chain
transpose, dropped diagonal subtraction, dropped centering,
sum-n normalization via weights pins, denominator collapse via I-LSR
pins with the one-shot-unobservable limitation documented, tol*n vs tol
via a separating iteration-count fixture). MC-500 recovery test
(#[ignore]) passing. cargo 745 pass; pytest 273 pass.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
|
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: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
… rejection The relative pivot threshold in the stationary-distribution solve compared an O(1) sum-constraint pivot against an O(max count) global scale, falsely rejecting validly connected win matrices with globally huge counts (impl-review finding). Normalize the generator to unit max magnitude after the overflow guard; the stationary distribution is invariant under global rescaling of transition rates. Regression asserts: base vs base*1e20 params/weights equal to 1e-12; asymmetric 1e150 ILSR finite. The overflow fixture is now a genuinely overflowing n=4 matrix (row sums -> inf); the previous n=3 all-1e308 fixture never overflowed and is correctly accepted post-fix. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…atrix Mirror of the Rust-side fixture change in 343fc2f: the n=3 all-1e308 matrix never overflowed and is correctly accepted after the scale-invariance fix; use n=4 at 1.7e308 (row sums -> inf) and add a Python-side scale-invariance regression assert. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
3 tasks
Contributor
Author
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.
Implements Luce Spectral Ranking (LSR) and iterative LSR (I-LSR) for pairwise comparison data, following choix 0.4.1's
lsr.pydense path (source READ; Maystre & Grossglauser, 2015, Fast and Accurate Inference of Plackett-Luce Models, NIPS — NOT READ, cited as described by choix).Stacked on #291 (
seonghobae-bradley-terry) — review only the last commit.What
mlsirm_core::scaling::{lsr_pairwise, ilsr_pairwise}+LsrResult {params, weights, iterations}: LSR Markov chain (ratec/(w_i+w_j)on each loser->winner edge,alphaeverywhere as regularizer), stationary distribution via Gaussian elimination with partial pivoting (sum-constraint row replaces the redundant stationarity equation), scaled to sum n; params = centered logs.pi . chain ~ 0residual check — a custom elimination must prove stationarity, not just return something positive. Disconnected graphs at alpha=0 and overflow from huge counts/alpha raise errors instead of NaN (choix can emit NaN there).NormOfDifferenceTestsemantics (L1 <= tol*n, first check never fires, default max_iter=100). At alpha=0 the fixed point IS the Bradley-Terry MLE — verified againstbradley_terry_mmto 4e-19 on the oracle fixtures (cross-algorithm anchor). For alpha>0 the two regularization paths deliberately differ (chain-rate vs Dirichlet-MAP; both follow their sources, documented).fast_mlsirm.lsr_pairwise/ilsr_pairwisewith full input validation before casts.Spec-verify (BEFORE implementation)
Adversarial review of hand-derived spec + EXECUTED oracle: APPROVED-WITH-CHANGES; all 4 mandatory changes implemented (overflow tests for huge counts/alpha, statdist residual guard, alpha-diagonal equivalence documented, no-initial_params exposure documented).
Oracle (EXECUTED)
Exact-Fraction one-shot statdist + mpmath 50-digit I-LSR fixed points, cross-checked against pip choix 0.4.1 (<= 2.2e-13) and the shipped BT oracle (<= 4e-19). Exact pins e.g. fixture A statdist = [12/17, 45/34, 33/34]; iteration pins A=15 / C=17 at tol=1e-8.
Mutation kills (all EXECUTED, restore-verified)
Tests
#[ignore](all asserts read crate outputs); cargo 745 pass / 92 ignored.Adversarial impl-review outcome