Audit: pin MLS2PLM neg-loglik & gradient to canonical equation#114
Conversation
Audit of the numeric core (linear_predictor / neg_loglik_and_grad in objective.py, the Rust neg_loglik_and_grad, and the Wright-Masters item-fit statistics) found all published formulas implemented correctly, and every performance refactor (einsum distance, one-hot grad_theta matmul, 2D grad_xi/grad_zeta rewrite, np.vdot penalty) mathematically equivalent to the original. The one gap: the Python objective's absolute NLL and gradient values were only guarded by finite-difference self-consistency and Rust-vs-NumPy parity, not pinned to the source equation. A future "optimization" that drifts both the forward and backward pass identically could slip through. Adds two source-grounded pins in tests/test_objective.py: - test_neg_loglik_matches_closed_form_single_entry: hand-computed scalar case. - test_neg_loglik_and_grad_matches_independent_reference: 3x4, 2-trait, 2-D latent case with default penalty, checked against a pure-Python closed-form reference derived directly from the MLS2PLM equations. Documents the canonical equations and source DOIs (Jeon et al. 2021; Molenaar & Jeon 2026; Kang & Jeon 2025) in docs/papers/mls2plm-canonical-equations.md. PDFs are cited by DOI, not redistributed (sources are not open-access). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RTAMs4bpSZS77Xe3RQjv9P
OpenCode Review Overview
Pull request overviewOpenCode reviewed the current-head bounded evidence and found no blocking issues. FindingsNo blocking findings. SummaryApproval sufficiency: bounded evidence supplied affirmative approval evidence for changed files, coverage/docstring posture, risk surfaces, and current-head verification; approval is not based merely on the absence of known blockers.
Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Docs: mls2plm-canonical-equations.md"]
S1 --> I1["operator or user guidance"]
I1 --> R1["Review risk: Docs: mls2plm-canonical-equations.md"]
R1 --> V1["docs review"]
Evidence --> S2["Test: test_objective.py"]
S2 --> I2["regression suite"]
I2 --> R2["Review risk: Test: test_objective.py"]
R2 --> V2["targeted test run"]
|
There was a problem hiding this comment.
Pull request overview
OpenCode reviewed the current-head bounded evidence and found no blocking issues.
Findings
No blocking findings.
Summary
Approval sufficiency: bounded evidence supplied affirmative approval evidence for changed files, coverage/docstring posture, risk surfaces, and current-head verification; approval is not based merely on the absence of known blockers.
Verification posture: CodeGraph evidence was initialized and bounded current-head evidence reviewed for changed-file evidence including docs/papers/mls2plm-canonical-equations.md, tests/test_objective.py.
Linter/static: workflow/static review evidence is bounded by the current-head GitHub Checks gate and changed-file evidence.
TDD/regression: coverage execution evidence and focused changed hunks were reviewed from bounded-review-evidence.md.
Coverage: coverage execution evidence reports supported repository test suites passed.
Docstring coverage: coverage execution evidence reports configured repository docstring gates passed or docstring coverage was advisory.
DAG: CodeGraph/source-backed behavior map connects docs/papers/mls2plm-canonical-equations.md to the affected review, runtime, or workflow path and required checks.
PoC/execution: coverage-evidence job executed on the current head and reported PASS.
DDD/domain: workflow and repository-governance invariants were reviewed against changed files in bounded evidence.
CDD/context: CodeGraph evidence, changed-file history, and focused hunks were reviewed from bounded-review-evidence.md.
Similar issues: changed-file history evidence was reviewed for comparable local precedents.
Claim/concept check: bounded evidence, repository source, current-head workflow evidence, and, where numeric, scientific, statistical, or literature-backed claims are affected, original-paper/formula evidence and parameter-recovery expectations were used for claims.
Standards search: standards and external-source checks are delegated to configured OpenCode web_search/Context7/DeepWiki sources when applicable; no evidence-backed standards blocker is present in bounded evidence.
Compatibility/convention: changed workflow/script conventions, object naming, and reserved-word safety for schema/API/config/code surfaces were checked in bounded evidence.
Breaking-change/backcompat: deployment evidence and changed-file history were checked for backward-compatibility risk.
Performance: changed surfaces were checked for performance risk in bounded evidence.
Developer experience: changed automation, review, test, setup, and maintenance surfaces were checked for helpful or obstructive DX impact in bounded evidence.
User experience: connected user, operator, API, CLI, documentation, review-comment, status-check, rendering, and workflow-reader behavior was checked for contradictions against code, docs, and tests in bounded evidence.
Visual/DOM: Playwright visual, DOM locator, ARIA snapshot, console, and responsive evidence were checked when a web UI surface was present; for non-web surfaces, API/CLI/log/docs/workflow interaction evidence was reviewed instead.
Accessibility/i18n: accessibility, localization, and human-readable text surfaces were checked where UI, CLI, API message, docs, logs, or review text changed.
Supply-chain/license: dependency, package, model, container, and external-tool changes were checked in bounded evidence.
Packaging: package, build, test, lint, and security contracts were checked in bounded evidence.
Security/privacy: workflow-token, review-gate, and repository-automation security/privacy boundaries were checked in bounded evidence.
- Result: APPROVE
- Reason: Mathematical formulas verified and tests pass with high coverage
- Head SHA:
d2470d8af35b933070186bcb0d99e706446d768f - Workflow run: 29083429148
- Workflow attempt: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Docs: mls2plm-canonical-equations.md"]
S1 --> I1["operator or user guidance"]
I1 --> R1["Review risk: Docs: mls2plm-canonical-equations.md"]
R1 --> V1["docs review"]
Evidence --> S2["Test: test_objective.py"]
S2 --> I2["regression suite"]
I2 --> R2["Review risk: Test: test_objective.py"]
R2 --> V2["targeted test run"]
|
Current-head verification for this loop:
|
Mathematical formula integrity audit
Audited the numeric core of
fast-mlsirm— the MLS2PLM regularized-JMLlikelihood/gradient and the item-fit statistics — against the published source
equations, with special attention to the recent performance refactors.
Formulas checked (all verified correct)
eta = exp(alpha)*theta + b - exp(tau)*rand regularizedEuclidean distance
r = sqrt(||xi - zeta||^2 + eps)— matches the LSIRM /MLS2PLM model (Jeon et al. 2021; Kang & Jeon 2025) under the simple-structure
restriction (see
docs/pr25_formula_review.md).softplus(eta) - y*eta(stable binarycross-entropy) + L2 penalty (Molenaar & Jeon 2026 regularized JML).
theta,alpha,b,xi,zeta,tau), including theexp()chain-rule factors onalpha/tau.neg_loglik_and_grad— kept at parity with the NumPy path.AIC/BIC/deviance, and Procrustes recovery alignment.
Performance refactors verified mathematically equivalent (kept as-is)
einsum('ij,ij->i', ...)+ Gram-matrix distance (replaces 3-D broadcast).grad_theta(replaces per-dimension loop).grad_xi/grad_zeta(replaces 3-D diff tensor).np.vdotpenalty accumulation (replacesnp.sum(x*x)).Damage found
None. No formula was restored because none was broken — every optimization
preserved the exact equation.
Added (regression guard)
docs/papers/mls2plm-canonical-equations.md— canonical equations, gradientderivation, and source DOIs (PDFs cited, not redistributed; sources are not
open-access).
tests/test_objective.pythat check the absoluteNLL and every gradient block against a pure-Python closed-form reference
derived from the equation (independent of the vectorized production path),
closing the gap left by the prior finite-difference-only coverage.
Full suite green: 133 Python tests + 4 Rust
mlsirm-coretests pass.🤖 Generated with Claude Code