Skip to content

constrained_lasso: restructure, the JRS review fixes, and a comlasso check in CI - #68

Merged
tschm merged 7 commits into
mainfrom
constrained-lasso-restructure
Oct 24, 2026
Merged

tschm merged 7 commits into
mainfrom
constrained-lasso-restructure

Conversation

@tschm

@tschm tschm commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Restructures the constrained-LASSO note for readability, addresses every point of an editor's review for the Journal of Reproducible Statistics, and adds a CI workflow for the R step. (#67 is merged; this is based on main.)

Section 1: a result, not a walked-back prediction

"What this note checks" said the CLA "should return the knots … with no change to its code", then that this "was not quite met, in two ways". It is now "What this note shows": a CLA written for portfolios, with a thin layer (two encodings and a relaxation), gives exact constrained-LASSO paths, and with p > n it does so with no ridge, which the other open path algorithms for general constraints don't. The two CLA defects are still stated and point to Appendix C.

Section 6: four parts instead of ten special cases

  1. Degenerate starts, and the relaxation that resolves them.
  2. Starts that need no relaxation: rows slack at β = 0, flat starts, rows that exclude β = 0.
  3. More predictors than observations (unchanged).
  4. What stays out of reach: numerically singular free blocks, and a relaxation that no retry certifies.

Appendices

  • A. The monotone fit: the knots move linearly in ε.
  • B. One encoding or two, with the encodings table.
  • C. What the checks did for the CLA, with the portfolio table.
  • D. The detail on Gaines et al.: the port, the started problems, and why its shipped start is off the path. Section 5 now summarises it in one paragraph.

No text was dropped; everything moved is in an appendix.

Hand-typed numbers now from the script

Wide's 53 knots; where lars_path's positive mode really ends (λ = 30.65) and its KKT violation at λ = 0 (3.2e-2); Figure 2's 13 knots, 2.3e-13 and ‖β(0)‖₁ = 3460. They go to figures/evidence_numbers.tex, and test_lars_positive_end checks the claim.

Review fixes

  1. Inequality rows in the CLA (Section 2). Problem (2) now has Cx ≤ h, which Proposition 1, the code and the evidence already passed. Active rows join the bordered system as equalities. A slack row joins when its slack reaches zero; an active row leaves when its multiplier does.

  2. The relaxation, specified (Section 6). Lemma 1 states when the ε/2ε extrapolation is exact (both runs take the same sequence of active sets) and proves it; the certificate is what the result rests on. The parameters are as cvxcla runs them: ε = ρ‖c‖∞ / max G_jj with ρ = 1e-6, then 1e-7 and 1e-8; d from a fixed seed with signs the bounds allow, scaled so C_r d ≤ ½; acceptance at 1e-9 relative. Appendix A is now an illustration, not a proof.

  3. comlasso, run (Section 5). R/comlasso_check.R fetches comlasso 0.2 from jenjong/ComLasso at a pinned commit, checks its SHA-256, and loads the package's code unchanged (R 4 won't install a package built for R 3.2). It traces the same knots as the CLA on Zero-sum, sCD14 and Wide, zero-sum (3 seeds):

    problem gap (relative to the largest coefficient)
    Zero-sum, sCD14 ≤ 4.1e-15
    Wide, zero-sum (p > n) ≤ 5.8e-12

    On two Wide seeds comlasso steps to λ ≈ 1e-11 before recording λ = 0; cvxcla counts that as λ = 0. The script fails on a gap above 1e-9 or a knot mismatch.

    make figures now runs R checks marked # run: after figures. compile.yml installs R 4.6.1 and the packages a check names on # needs: (Ubuntu libraries on # apt:) from the CRAN snapshot r-check.yml already pins. This is the first CI run of that step; actionlint wasn't available locally.

Minor review points (4–12)

  • Abstract: now mentions the relaxation layer, the agreement with comlasso, and the one declined problem.
  • Numbers from the script:
    • Pinned's first knot (4053), the largest interior-point gap of Table 2, and the p = 500 cross-check in Scale are now macros.
    • The cost ratios are said to be measured once by timings.
  • Uniqueness: stated as an assumption when there are constraints or p > n; the checks test optimality, not uniqueness.
  • Table 6: the caption names its seed.
  • Figure 3: the 8 largest genera are in colour and the rest in grey, with interior-point checks at every third midpoint.
  • Layout:
    • Appendix tables sit with their text; Gaines comes before the portfolio defects.
    • The bibliography is ragged-right, and the build has no LaTeX warnings.
  • Related work follows the encodings list, under its own heading.

CI: comlasso-check

A new workflow, modelled on r-check.yml, runs on PRs touching preprints/constrained_lasso/**, and can be started by hand. It:

  1. fetches sCD14;
  2. writes the saved paths with make_figures.py export, a new mode that takes about 1.5 s;
  3. installs R 4.6.1 and Rglpk 0.6.5.1 (pinned) from the CRAN snapshot;
  4. runs R/comlasso_check.R and uploads figures/comlasso.tex.

Its first run passed: the same knots on all five problems, gaps ≤ 2.5e-12. compile.yml also runs the check inside make figures, and passed with it.

Checks

  • make_figures.py test: 17 passed.
  • CI: compile (both preprints) and comlasso-check green.
  • R/comlasso_check.R: passes locally (R 4.6.1, Rglpk 0.6.5.1, GLPK 5.0).
  • Builds to 17 pages (main text about 12, then references and the appendices), with no overfull lines and no undefined references.

🤖 Generated with Claude Code

Base automatically changed from constrained-lasso-cvxcla-2.7 to main October 24, 2026 16:22
tschm and others added 2 commits October 24, 2026 18:23
…reframe Section 1

- Section 1: 'what this note shows' - a portfolio CLA plus a thin layer
  gives exact constrained-LASSO paths, including p > n with no ridge -
  instead of a prediction the note then walks back.
- Section 6: four parts (degenerate starts and the relaxation; starts
  that need no relaxation; p > n; what stays out of reach) instead of
  ten special cases.
- Appendices: the monotone-fit check (A), one encoding or two (B), the
  portfolio defects (C), and the detail on Gaines et al. (D), which
  Section 5 now summarises in one paragraph.
- Hand-typed numbers now come from the script: Wide's 53 knots, the end
  of lars_path's positive mode (lambda = 30.65, KKT 3.2e-2), and Figure 2's
  13 knots, 2.3e-13 and ||beta(0)||_1 = 3460. test_lars_positive_end.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cified with a lemma

Review points 1 and 2.

- Section 2: problem (2) now has rows Cx <= h, which Proposition 1, the
  code and the evidence pass to the CLA. Active rows join the bordered
  system as equalities; a slack row joins when its slack reaches zero, an
  active row leaves when its multiplier does. The nondegenerate start
  counts rows tight at it.
- Section 6: Lemma 1 states when the extrapolation is exact (both runs
  pass the same sequence of free sets, blocked sets and active rows) and
  proves it; the certificate is what the result rests on. The relaxation
  is now specified as cvxcla runs it: eps = rho ||c||_inf / max G_jj with
  rho = 1e-6, then 1e-7 and 1e-8; d from a fixed seed with signs the
  bounds allow, scaled so C_r d <= 1/2; acceptance at 1e-9 relative.
- Appendix A is an illustration of the lemma's hypothesis, not a proof.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tschm
tschm force-pushed the constrained-lasso-restructure branch from 6e30fc2 to df314d7 Compare October 24, 2026 16:27
tschm and others added 3 commits October 24, 2026 18:31
Review point 3. comlasso (Jeon et al., CSDA 2020) traces the exact
zero-sum path with p > n and no ridge, so it is the one independent
reference that should agree with no workaround. It does: the same knots
on Zero-sum, sCD14 and Wide, zero-sum (three seeds), to 4.1e-15 and, with
p > n, 5.8e-12, relative to the largest coefficient. On two Wide seeds it
steps to a lambda at rounding level before recording lambda = 0, which
cvxcla counts as lambda = 0.

- R/comlasso_check.R: fetches comlasso_0.2.zip from jenjong/ComLasso at
  a pinned commit, checks its SHA-256, and loads the package's code
  unchanged with lazyLoad (R 4 refuses packages built before R 4.0).
  Writes figures/comlasso.tex and fails if a gap exceeds 1e-9 or the
  knots differ.
- preprints/Makefile: an R/*.R marked '# run: after figures' runs last
  in make figures. The other note's R/long_short.R is unmarked.
- compile.yml: R 4.6.1 and the packages a check names on '# needs:'
  (and Ubuntu libraries on '# apt:'), from the CRAN snapshot r-check.yml
  pins; R/ joins the figure cache key.
- Section 5 has three independent path algorithms; Sections 1 and 6
  and the code availability section say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Abstract: the relaxation layer, comlasso, and the one declined
  problem.
- Numbers from the script: Pinned's first knot (4053), the largest
  interior-point gap of Table 2, and the second check at p = 500
  (encodings). The cost ratios are said to be measured once by timings,
  the one set of numbers not written by the script.
- Uniqueness with constraints and p > n is an assumption; the checks
  test optimality, not uniqueness.
- Table 6 says Wide, zero-sum is the first seed of Table 4.
- Scale cites the penalty form's agreement at p = 500.
- Figure 3: the eight genera largest at lambda = 0 in colour, the rest
  in grey, interior-point solves at every third midpoint for those eight.
- Layout: appendix tables placed with their text, Gaines before the
  portfolio defects, a ragged-right bibliography; 17 pages, no warnings.
- Related work follows the encodings list, under its own heading.
(Point 9, 'per unit' in Proposition 1's proof, was already fixed.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A workflow, modelled on r-check.yml, that runs R/comlasso_check.R on each
pull request touching preprints/constrained_lasso: fetch the sCD14 data,
export the zero-sum paths, install R 4.6.1 and Rglpk from the pinned
CRAN snapshot, run the check, and upload figures/comlasso.tex. compile.yml
still runs the script inside make figures; this is the check on its own,
fast and named.

make_figures.py gains an export mode that writes only
figures/zero_sum_paths.npz (about 1.5 s), for the checks that run c-lasso
and comlasso on it; main() calls the same function.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
if sys.argv[1:] == ["timings"]:
sys.exit(timings())
if sys.argv[1:] == ["export"]:
sys.exit(export_zero_sum_paths())
tschm and others added 2 commits October 24, 2026 20:45
…installs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tschm tschm changed the title constrained_lasso: restructure Section 6, move detail to appendices, reframe Section 1 constrained_lasso: restructure, the JRS review fixes, and a comlasso check in CI Oct 24, 2026
@tschm
tschm merged commit 5395f07 into main Oct 24, 2026
6 checks passed
@tschm
tschm deleted the constrained-lasso-restructure branch October 24, 2026 18:55
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.

1 participant