Abstract
Schmelzer and Hastie showed that the solution path of the constrained LASSO and the path of Markowitz's Critical Line Algorithm (CLA) are the same curve. This note checks that identity numerically. It poses a constrained regression as a portfolio and hands it to a released CLA written for portfolios. On caps, signs, equality and inequality rows, monotone fits and zero sums, on simulated and real data, up to 500 predictors and on problems built to break a path algorithm, the paths reproduce LARS, an interior-point solver and three independent path algorithms, and meet the LASSO's optimality conditions to rounding, or to 10⁻⁹ where a path with more predictors than observations nears an interpolating fit. A design with two nearly identical columns is declined with an error rather than answered wrongly. With more predictors than observations the paths stay exact, where the path algorithms for general constraints add a ridge that moves the end of the path.
1 A constrained regression
Tibshirani (1996) introduced the LASSO as least squares with a single constraint, a budget on the norm of the coefficients: LARS (Efron et al., 2004) and the homotopy method (Osborne et al., 2000) compute the solution for every , or every , at once. The solution is piecewise linear in the parameter, so the whole path is a finite list of knots. scikit-learn’s lars_path (Pedregosa et al., 2011) takes , and one option, positive, for nonnegative coefficients. There is no place for any other constraint.
Many regressions need one. The diabetes data that LARS was introduced with (Efron et al., 2004) illustrate what a constraint can do: patients, ten standardised baseline variables and, as the response, a measure of disease progression a year later. Six of the variables are blood serum measurements, and three of them are closely related measures of cholesterol: total cholesterol (s1), LDL (s2) and HDL (s3). Least squares plays them off against each other. It gives total cholesterol a coefficient of and LDL one of : two large effects of opposite sign that mostly cancel. HDL gets , as if more of it made the disease progress faster. Low HDL is a risk factor for incident diabetes (Wilson et al., 2007); the response here is progression in patients who have the disease, so that finding suggests a negative sign but does not establish one. The LASSO path ends at the least-squares fit, so it gets there too. A cap on every coefficient, , stops the offsetting. We take , half the largest least-squares coefficient, a value chosen after seeing the fit. The example shows what a cap does to offsetting coefficients; it is not offered as a better model of the disease.
Figure 1 shows what the cap does. Without it the path passes the cap at ten of its 13 knots and ends with HDL positive. With it no coefficient passes the cap, and HDL stays negative along the whole path, although no sign is imposed. That does not hang on the choice of : every whole-number cap up to 637 keeps HDL negative along the whole path, and only looser caps let it turn positive. That is a property of these data, not a finding about HDL. The capped path has 13 knots.
lars_path computes; the coefficients that pass the cap are in orange. Right: every coefficient capped. Lines: the exact path, by the CLA in the penalty form. Circles: an interior-point solve at the midpoint of every segment. The horizontal axis is , decreasing to the right, on a symmetric-log scale: logarithmic above and linear below it, so that the end of the path at is shown.Both panels are exact paths. They come from the Critical Line Algorithm (CLA), which Markowitz (1956) wrote for portfolios, applied to one of the two encodings described below. The open-source package cvxcla (Schmelzer, 2026a) carries them out (Algorithm 1), and the right panel is one call:
from cvxcla import Lasso
knots = Lasso(X, y, lower=-u * np.ones(p), upper=u * np.ones(p)).path
The same call also takes signs (a bound of zero), equality rows a, b and inequality rows g, h, and picks the encoding that fits them.
What this note shows Schmelzer and Hastie (2026) prove that the CLA and the constrained LASSO (Gaines et al., 2018; James et al., 2020) trace the same curve; Table 1 gives the dictionary. Portfolio managers have always needed constraints, such as a budget, position limits and sector exposures, and Markowitz built them into the CLA from the start. So a CLA written for portfolios, with a thin layer that poses the regression as a portfolio, should give exact constrained-LASSO paths. This note shows that it does, or stops with an error where its arithmetic cannot be trusted, and checks every path against references that know nothing of portfolios. The layer is two encodings, Propositions 1 and 2. The propositions need nothing from Schmelzer & Hastie (2026) beyond the classical equivalence of the bound and penalty forms of the LASSO; that paper supplies the general identity of which they are instances. The checks also exposed two defects in the CLA that refused ordinary portfolio problems too, a tie for the largest expected return and a covariance of low rank. Both were fixed in cvxcla 2.6.0 (Schmelzer, 2026a). Drawing the hostile problems of Section 5.4 over more seeds exposed three more, on a design whose columns are nearly collinear: two in the check that a bound held along a segment is still optimal, which refused a correct path, and one in the plain LASSO homotopy, which lost the second of two events at the same . All three were fixed in 2.7.1, the release used here. Brodie et al. (2009) put an penalty on Markowitz portfolios to make them sparse, and a companion note (Schmelzer, 2026b) computes efficient frontiers with a LASSO solver. Both use regression to build portfolios. This note goes the other way. Section 2 recalls the CLA, Section 3 gives the two encodings, Section 4 says where the path starts and ends and collects them in Algorithm 1, Section 5 checks the paths, and Section 6 gives the limits.
| regression | portfolio |
|---|---|
| coefficient | position in asset |
| covariance of the asset returns | |
| expected returns (penalty form: a benchmark) | |
| gross exposure | |
| penalty | risk tolerance (penalty form) |
| bound | leverage cap , (budget form) |
| , | budget rows and position limits |
| knot of the LASSO path | turning point of the CLA |
The penalty form (Section 3.1) keeps as the parameter and takes bounds, equality rows and inequality rows ; it is the general form. The budget form (Section 3.2) keeps the budget, as Markowitz’s long-only, fully invested problem with a cash asset, and takes homogeneous constraints such as the zero sum of compositional data in one run.
Related work Exact paths of the constrained LASSO are not new. Gaines, Kim and Zhou (2018) derive a path algorithm from its optimality conditions that takes general linear rows. For alone, the Python package c-lasso (Simpson et al., 2021) has a path algorithm with a small ridge term added. For zero sums on blocks of coefficients, the comlasso algorithm of Jeon et al. (2020) traces the exact path, also with . None was derived with portfolios in mind, so Section 5 runs all three as independent checks. Hobson, Butcher and Lentati (2026) revisit Gaines et al. with CLASSO. The linear system of Gaines et al. is singular whenever a sign constraint binds on a zero coefficient, so CLASSO takes the direction from a small quadratic program instead. In the CLA a sign or a cap is a bound, not a row, so that singularity does not arise. CLASSO adds a ridge when , and its code had not been released when we wrote, so we do not run it. The CLA is an active-set method of the same kind, written for portfolios and used here as released. With the other path algorithms for general constraints add a ridge, which decides where their path ends; the CLA needs none (Section 4). Microbiome studies often have more taxa than samples, so this is the case a user of the zero-sum LASSO meets first. Table 6 collects what each accepts.
Notation The design is , with observations and predictors, and the response is . Write and . The constrained LASSO is with , and , infinite entries allowed, and a nonempty feasible set. A bound that excludes zero, such as with , is written as the row . With no rows and infinite bounds it is Tibshirani’s LASSO. We assume, as (Schmelzer & Hastie, 2026) does, that has a unique minimiser for every . Without constraints this holds when the columns of are in general position (R. J. Tibshirani, 2013), and with constraints when has full column rank (Hobson et al., 2026, Theorem 6). For constrained problems with we know of no such result. The checks of Section 5 test optimality, not uniqueness: where the minimiser is not unique, they confirm that the path is a path of minimisers.
2 The Critical Line Algorithm
The CLA starts with the portfolio of highest expected return and lowers the risk tolerance; between corners, the turning points or knots, the optimal portfolio moves along a straight line. Precisely, it solves the family of quadratic programs for every from down to , with . Markowitz’s algorithm (Markowitz, 1956) handles general linear constraints; we write them as equality rows, inequality rows and bounds, the form cvxcla takes. Here is the vector of holdings, the covariance, the expected returns and the risk tolerance. The term is a benchmark. With the objective is, up to a constant, the tracking variance against a portfolio less : the same CLA after the bounds and right-hand side are shifted by . With it is Markowitz’s problem.
Segments Write for the gradient of the Lagrangian. A point with multipliers and is optimal when on the free coordinates , where , and where . In addition , with on every row that is slack, . Call the coordinates at a bound blocked, , and the rows held tight active, . An active row is held as an equality. In the system below it is stacked under , with its right-hand side under and its multiplier under ; the slack rows take no part. To keep the display short, , and stand for these stacks. With , and fixed, and solve the bordered system so and are affine in . The gradient on the blocked coordinates is affine too, . One factorisation and two right-hand sides give the whole segment.
Events Lowering , the segment ends at the first of four events (Schmelzer & Hastie, 2026, Section 2.1): a free coordinate reaches a bound, a blocked coordinate’s gradient changes sign, a slack row becomes tight, or an active row’s multiplier falls to zero. Each is the root of an affine function of , such as . The coordinate or row concerned changes sides, (3) is solved again, and the walk continues; with no event left, the last segment runs to .
The start As the linear term dominates, and the path starts at a vertex maximising over the feasible set. A linear program finds it. Suppose the maximiser is unique, and as many of its coordinates lie strictly inside their bounds as there are equality rows and rows tight at it. Then the bordered matrix in (3) is nonsingular and the walk can begin. This is the nondegenerate case; cvxcla declines a degenerate start.
3 Two encodings
3.1 The penalty form
The first encoding reads the penalty as a cost: every unit of gross position, long or short, costs units of return. To make that a linear cost, each coefficient is split into a long and a short position, both nonnegative. The constraints on become constraints on the positions, unchanged in kind.
Formally, let have a column for every with and a column for every with , so that with . Let collect the matching bounds and . A coefficient whose bounds are both zero is fixed and can be dropped. Every then has at least one column, and has full row rank.
Proposition 1 (Penalty as cost). For , , where solves the CLA instance with Moreover lies in the range of , so the benchmark reading of Section 2 applies: the program tracks a least-squares fit and pays for every unit of gross position.
Proof. Up to the constant , the CLA objective at is . For a fixed feasible in (1), the smallest over with and is . The rows hold for every such , since they constrain only . It is attained by putting on the column of its sign, which respects because . The minimum of the CLA program over is therefore the minimum of over . At a minimiser no coordinate holds both signs, since lowering both by the same amount keeps and reduces the cost by times that amount. Hence minimises , and by uniqueness equals . For the range claim, lies in the range of , say . Since has full row rank, for some , and then , where is a least-squares fit. ◻
The covariance is singular when both signs of a coefficient are allowed, but (3) is not. For the proof keeps the two halves of a coefficient out of together. On the free coordinates is then positive definite on the null space of the active rows, the standing assumption of Schmelzer & Hastie (2026, Section 2). The halves come apart only at , which rounding can move to ; cvxcla treats an event whose parameter is round-off as one at .
Figure 2(a) shows the penalty form on the diabetes data (Efron et al., 2004), where there are no constraints and LARS can check every knot.

lars_path returns (Pedregosa et al., 2011) (circles); all 13 agree to , relative. (b) The same path seen by the budget form as a portfolio: the long and short positions and the cash weight share a budget of one, against the leverage . Cash enters at , the end of the LASSO path; to its right the least-squares fit is diluted by cash.3.2 The budget form
With the penalty form starts degenerate (Section 4). The second encoding starts instead from the bound , a cap on the leverage, whose path is that of indexed by (Schmelzer & Hastie, 2026, Theorem 1), and divides by . The split coefficients then add up to at most one, which is Markowitz’s own setting. A cash asset with no risk and no return holds the rest.
Proposition 2 (Budget as simplex). Suppose and , so that every constraint is homogeneous. Write with , and add a riskless asset with . Then for the bound-form LASSO is the CLA instance with rows and and bounds . This is Markowitz’s long-only, fully invested problem with a cash asset of zero variance and zero return. If is the multiplier of the budget row and those of , then and the LASSO’s multipliers for are .
Proof. As in Proposition 1, is for the split , and is its slack. The constraint is unchanged by the scale , which is where homogeneity is needed. A nonzero right-hand side would become , a constraint that moves with the parameter. Substituting gives the objective plus a constant, and dividing by gives . For the multipliers, multiply the CLA’s stationarity row for a free coordinate, , by . This gives , the LASSO’s stationarity condition with penalty and constraint multipliers . The cash row reads while cash is held at zero. ◻
The two forms give the same knots unless the support’s sign vector lies in the span of the active constraint normals (Schmelzer & Hastie, 2026, Corollary 1 and Proposition 1). Under a zero sum that never happens: a nonzero that sums to zero has coefficients of both signs.
4 Where the path starts and ends
The two encodings differ most at the ends of the path. A nondegenerate start lets the walk begin at once; a degenerate one needs a relaxation.
Nondegenerate starts In the penalty form without equality rows the starting vertex is : all positions are closed, because each costs more than it can earn. The first event is the first entry, at over the allowed signs, which is LARS’s . Rows with are slack at , so they leave the start unchanged, and a row joins the active set when the path reaches it, like a bound. With equality rows, or a row with that leaves infeasible, the start is the linear program over , , : the point of smallest norm on the constraint set. For generic and it is a unique vertex with nonzeros, and the path holds still there, , until a second coefficient enters. In general, every constrained LASSO path is constant from some on, at a least-squares fit over the feasible points of smallest norm, and takes the place of (Schmelzer & Hastie, 2026, Proposition 3). That fit can take a quadratic program to find. Under the fully invested constraint of sparse portfolio regression (Brodie et al., 2009) every long-only in the simplex has , so the starting linear program is not unique; cvxcla starts on the tied face where its quadratic term is smallest, which is that fit.
In the budget form the start, at and , is the linear program over the simplex: put the whole budget on the best asset. Without equality rows that is the predictor most correlated with the response. It enters with the sign of its correlation and with , just as in LARS. Under it is one long and one short position of weight each, the most and the least correlated predictors, entering together. That is why two coefficients leave zero at once in Figure 3. Both starts are generically unique and nondegenerate.
Degenerate starts With the penalty form’s starting vertex is , with no free coordinates for rows. This is a degenerate vertex: the multipliers at the start are not determined by the active set, and (3) is singular. For homogeneous equality rows with signs the budget form is the remedy, because rescaling to the simplex moves the start off the origin. It cannot take rows or caps, which move with the parameter once rescaled (Proposition 2). Caps or inequality rows under a zero sum therefore leave only the penalty form, which starts degenerate there. So do homogeneous rows (), such as the ordering constraints of a monotone fit: all are tight at .
cvxcla resolves both by relaxation, an implementation device rather than part of the method. It traces the problem twice, with the homogeneous rows relaxed to and and a zero sum to and for a generic feasible point . In release 2.7.1, is times the scale of a coefficient, then and times it if needed. Both runs start nondegenerate. The relaxation enters only the right-hand side of (3), so where the two runs pass through the same active sets their knots are affine in , and is the knot at . That condition cannot be checked in advance. cvxcla therefore returns the extrapolated path only if a linear program finds multipliers that satisfy the optimality conditions of (1) at every knot and segment midpoint, to relative to . Otherwise it retries with the next and, after the last, declines. The extrapolation only proposes a path; the certificate is what guarantees the path returned. The paths it returns are checked again, like every other path, in Section 5.
The end of the path As the path ends at the least-squares fit of smallest norm under the constraints (Schmelzer & Hastie, 2026, Proposition 3). In the budget form this is where cash leaves its bound, its gradient reaching zero (Figure 2(b)), and the run stops there. With the end is an interpolating fit, and there that event wins a tie, since every correlation vanishes together with . is then singular, but the bordered system needs a positive definite Hessian only on the null space of the active rows, the standing assumption of Schmelzer & Hastie (2026), so the free set can outgrow the rank of . The other path algorithms for general constraints add a ridge: in Gaines et al. when , in c-lasso, and in CLASSO. At that ridge the authors of CLASSO report objectives up to , relative, above the unregularised ones (Hobson et al., 2026, Table 3). Each then traces a nearby problem whose path ends elsewhere.
Algorithm 1: the constrained LASSO path from a CLA.
Form , and the split of Section 3.1.
If there are equality rows and every constraint is homogeneous (, , no inequality rows), use the budget form of Proposition 2. Run the CLA from and stop when cash leaves zero. A turning point at with budget multiplier is the knot at .
Otherwise use the penalty form of Proposition 1 and run the CLA from to . A turning point at is the knot at . With , or a row with , the start is the feasible point of smallest norm.
If the start is degenerate, trace the penalty form twice, with the homogeneous rows relaxed by and , extrapolate the knots to , and return the path only if it passes the certificate.
Between two knots is affine in , so any other point on the path is an interpolation.
cvxcla.Lasso(X, y, a=A, b=b, g=C, h=h, lower=l, upper=u) (release 2.7.1) carries out steps 1–5 and returns the knots. With no constraint at all it traces the plain LASSO by a homotopy instead.
5 Numerical evidence
Each check tests a prediction of Schmelzer & Hastie (2026). Their Lemma 1 makes and the CLA one parametric quadratic program, so the penalty form should return the knots of : LARS tests this knot by knot where it applies, and the interior-point solver and the optimality conditions everywhere. Their Theorem 1 and Corollary 1 give the bound form the same knots, so the budget form should return them too: comlasso and c-lasso test this on the zero sums.
5.1 Test problems and checks
Table 2 lists the test problems and their constraints. The diabetes problems use the data of Section 1, with the response centred, and Box is the opening example. Nonnegative carries the one constraint lars_path accepts. In Cholesterol, is half the least-squares net effect of the three cholesterol measures, and the two rows bind at the end of the path. Pinned fits the first patient exactly, one nonhomogeneous equality row; its path holds still at its starting vertex until . Wide is a Gaussian design with 8 nonzero coefficients and noise of standard deviation . Zero-sum is a regression on compositional data in the style of Lin et al. (Lin et al., 2014), with the log-shares of parts as predictors. A composition is known only up to scale, so only a zero sum makes the fit independent of the units. Five parts have nonzero true coefficients. The signs of Zero-sum, signs fall on the even-numbered parts, which the truth meets. The caps of Zero-sum, caps are at half the largest zero-sum least-squares coefficient. Monotone is a Gaussian design with , and an ordered truth, under the rows . Sum to one predicts one unit’s outcomes over 40 periods from those of 20 donors with weights that sum to one. Unlike the classic synthetic control (Abadie et al., 2010), which also requires the weights to be nonnegative, the weights here may be negative; adding the signs would be one more bound. Floor, not in the table, is the diabetes LASSO with at least half its least-squares value, a row that leaves infeasible. Its path has 13 knots. It lies within of an interior-point solve at every midpoint and meets the optimality conditions to . sCD14 is the same model on real data from a study of the gut microbiome in HIV infection (Noguera-Julian et al., 2016), as distributed with the R package coda4microbiome (Calle et al., 2023). The predictors come from the counts of 60 bacterial genera in 151 stool samples, and the response is the level of sCD14, a marker of inflammation, in thousands. Each count gets a pseudocount of one, since a zero has no logarithm, and the predictors are the centred log-shares. Its path has 60 knots (Figure 3). Like the diabetes problems, sCD14 is a computational demonstration on real data. No biological inference is intended, and none should be drawn from its path.
Every path comes from cvxcla.Lasso 2.7.1. The bounds are passed even where they are infinite, so that the CLA computes it. Where LARS applies it is the reference, compared knot by knot in both and . Elsewhere the reference is an interior-point solve (Clarabel through CVXPY, tolerances ) at the midpoint of every segment. There the path is affine in , so it is known exactly from its two ends. This comparison is only as sharp as the solver. Its largest gap in Table 2 is , relative, on a path whose optimality conditions hold to rounding. The third check evaluates the optimality conditions of (1) directly at every knot and along every segment. Its unknowns are the multipliers of and of the active rows of . A linear program chooses them, under , to minimise one number : the largest violation of all the conditions below, taken jointly. Each condition, written as an inequality that is affine in the multipliers, becomes the row , and the program minimises . Its optimum is zero exactly when is optimal. The violation is then evaluated again, exactly, at the multipliers found, so the solver’s own tolerance cannot hide one. A small reported value therefore certifies optimality to that size, and a real violation cannot be masked: no choice of multipliers brings it below the optimum of the program. With the conditions are on the interior of the support; at zero, or only under and under ; at a cap and at a floor ; ; and primal feasibility. The check covers each segment whole, not only its midpoint, as Hobson et al. (2026) do. Which coefficients are zero, at a bound or free, and which rows are active, is read off the midpoint. With that fixed, and the multipliers taken affine between the two ends, every condition is affine in . It holds along the whole segment if it holds at both ends. A linear program finds multipliers at both ends under the midpoint’s pattern, and both ends must fit that pattern: inside a segment no coefficient may change sign or leave a bound, and no row may come loose. A path that is right at both ends of a segment and at its midpoint, but cuts across a knot, fails this check. The published tests include one (test_segment_check_sees_between_samples). With , and the cap , the path is zero down to , then up to the cap at . A single segment from to misses both knots, yet meets the path at its ends and at its midpoint, where the largest violation of the optimality conditions is 0. The segment check returns 0.25, relative to . The largest violation, relative to , is the last column of the table.
| problem | constraint | knots | ref. | gap | KKT | ||
|---|---|---|---|---|---|---|---|
| plain | none | 442 | 10 | 13 | LARS | ||
| nonnegative | 442 | 10 | 6 | LARS | |||
| wide | none, | 40 | 100 | 53 | LARS | ||
| box | 442 | 10 | 13 | IPM | |||
| cholesterol | 442 | 10 | 14 | IPM | |||
| pinned | 442 | 10 | 18 | IPM | |||
| zero-sum | 60 | 30 | 30 | IPM | |||
| zero-sum, signs | , | 60 | 30 | 21 | IPM | ||
| zero-sum, caps | , | 60 | 30 | 35 | IPM | ||
| monotone | 100 | 10 | 13 | IPM | |||
| sum to one | 40 | 20 | 19 | IPM | |||
| sCD14 | 151 | 60 | 60 | IPM |
5.2 Accuracy
The CLA returns LARS’s knots to , including on the wide design, where 53 knots carry the path to the interpolating fit. The KKT residuals are at the level of rounding throughout, including on the problems LARS cannot take. In positive mode lars_path labels as a point that is the path at , so the CLA’s last knot is compared with scipy.optimize.nnls (Lawson & Hanson, 1974) instead.
5.3 Scale and cost
Table 3 extends the test to simulated zero-sum problems of up to parts, each size drawn with three seeds. At that size a midpoint solve per segment would cost more than the path itself, so the table reports only the optimality conditions. They hold to rounding. A second check at the largest size comes from the other encoding. The penalty form, relaxed, returns the same 542 knots to , as it does on every zero-sum problem here (figures/encodings.tex). For a sense of cost, take a grid of 100 interior-point solves (Clarabel through CVXPY, compiled once with as a parameter). It costs about 90 times as much as the whole CLA path at , 340 times at , and 14 to 110 times on the constrained diabetes and zero-sum problems of Table 2. Each step was run once to warm up and then timed 11 times, 3 times at the sizes of Table 3, on an Apple M4 Pro. The ratios are of the medians; the ratio of any two paired runs stays within 8% of it. These are the only numbers the script does not write into the text. The grid also misses every knot between grid points.
| knots | KKT | ||
|---|---|---|---|
| 200 | 100 | 100–108 | |
| 400 | 200 | 208–224 | |
| 1000 | 500 | 538–542 |
5.4 Hostile problems
Table 4 adds problems chosen to make a path algorithm fail, each drawn with ten seeds (7 to 16), and reports the worst case. Correlated is a Gaussian design with and in which every pair of columns has correlation 0.99999. It is run alone, under a box and under a zero sum. Duplicate adds to the diabetes data an eleventh column, bmi plus noise of or times its spread, so that two columns nearly coincide; it is run alone and under the cap of Box. Wide, zero-sum puts a zero sum on Wide, where .
Every path that is traced meets the optimality conditions to or better. The gaps to the references grow with the conditioning. Against LARS the gap stays below times the machine epsilon, and LARS’s own KKT residual is at most : both paths are right. The same reading covers a minimiser that is not unique. LARS and the CLA may then trace different paths of minimisers, and a gap between them is no defect as long as both meet the optimality conditions; the certificate, not the agreement, is what each path is held to. Against the interior-point solver the gap reaches on Duplicate, where two nearly identical columns leave the minimiser all but unique: the solver can split the weight between the twins differently at almost the same objective. Even there the solver’s objective is never lower than the path’s by more than , relative, which is within its tolerance.
cvxcla declines Duplicate at without a cap for every seed, because both twins become free (Section 6). Under the cap it declines two of the ten seeds, for the same reason: on those draws both twins become free before the cap binds. On the others they never are both free, and the path is exact. Nothing else is declined. Wide, zero-sum, with near , is traced, with the largest residual in the table (Section 4).
| problem | knots | ref. | gap | KKT | |||
|---|---|---|---|---|---|---|---|
| correlated | 100 | 40 | 43–49 | LARS | |||
| correlated, box | 100 | 40 | 47–59 | IPM | |||
| correlated, zero-sum | 100 | 40 | 40–42 | IPM | |||
| duplicate | 442 | 11 | 14–16 | LARS | |||
| duplicate , box | 442 | 11 | 14–16 | IPM | |||
| duplicate | 442 | 11 | declined | ||||
| duplicate , box | 442 | 11 | 14 (2 declined) | IPM | |||
| wide, zero-sum | 40 | 100 | 50–78 | IPM | |||
5.5 More predictors than observations
A zero sum alone with is covered by comlasso (Jeon et al., 2020) too, so Table 5 puts on Wide (, , ten seeds) the constraints comlasso does not take. They are nonnegativity; a box at half the largest coefficient of the least-squares fit of smallest norm; two binding inequality rows that cap the net effect of three predictors, as in Cholesterol; the row of Pinned; and a zero sum with the signs of Zero-sum, signs or with the caps of the box. cvxcla declines none of them. Every path meets the optimality conditions to or better along every segment. The largest residuals come at the end of a path, near , where the fit almost interpolates; elsewhere they are at rounding. The largest is on one seed of Zero-sum, signs, with near . and the interior-point solver agrees to . Its objective is never lower than the path’s by more than , relative. That happens only near the end of a path, where the fit almost interpolates and the objective is small.
| Wide with | knots | gap | KKT |
|---|---|---|---|
| nonnegative | 48–100 | ||
| box | 92–315 | ||
| inequality rows | 50–78 | ||
| pinned | 51–73 | ||
| zero-sum, signs | 44–78 | ||
| zero-sum, caps | 88–389 |
5.6 Three independent path algorithms
Three path algorithms derived for the LASSO, with no reference to portfolios, can be run against the CLA. Started at the exact first knot, all three trace its path, up to the ridge two of them add.
comlasso (Jeon et al., 2020) traces the exact path under zero sums on blocks of coefficients, with no ridge and with , so it should agree with the CLA with no workaround. Its authors publish it as an R package built for R 3.2. We load it unchanged (Code availability) and run it on Zero-sum, sCD14 and Wide, zero-sum. It returns the CLA’s knots, to relative to the largest coefficient on the first two and to on Wide, zero-sum over the ten seeds.
The algorithm of Gaines et al. (2018) ships in MATLAB and in Julia. We ported the Julia package to Julia 1 without changing the algorithm (Code availability) and ran it on every problem of Table 2. Started at the exact first knot, where that is simple to state, it agrees with the CLA to on the five such problems with : box, cholesterol, plain, sCD14 and zero-sum. On Wide, where , its ridge keeps it away. As shipped, its own start puts it off the path on all 12 problems, by to relative to the largest coefficient. It takes the first knot from a linear program that does not involve , and calls a coefficient active above an absolute threshold of .
c-lasso (Simpson et al., 2021) has a path algorithm for alone, without bounds or signs, so it runs on Zero-sum, sCD14 and Wide, zero-sum. It adds a ridge term to , fixed in the package, and that term is the whole of its distance to the CLA. On the first two its 100 grid points lie up to from the CLA path as shipped, relative to the largest coefficient. With the ridge set to by hand they lie from it. With the same ridge is not small. On Wide, zero-sum, c-lasso as shipped lies 0.41 to 0.60 times the largest coefficient from the CLA over the ten seeds, and with the ridge at .
6 Limits and when to use it
When two columns nearly coincide and both become free, moving weight from one to the other barely changes the fit. Unless an active row forbids that move, (3) is then singular to working precision and cvxcla stops (Duplicate at , Table 4). This is the general-position assumption of Section 1, failing in floating point. Dropping or merging one of the two columns before tracing avoids it. A relaxation can also fail its certificate, when knots of the exact path lie closer together than the relaxation moves them; here none was declined. Finally, we do not prove that the walk terminates. The non-terminating examples of Hobson et al. (2026) need multipliers that are not unique, which a nonsingular (3) rules out, and every walk here ended.
When to use it cvxcla.Lasso is for LASSO paths under constraints lars_path does not take: caps, signs on some coefficients, equality and inequality rows and zero sums, also with . It returns the knots at less cost than a grid of interior-point solves (Section 5.3). For the plain or positive LASSO, lars_path is enough. Two nearly identical columns should be merged first. Table 6 lists what each path algorithm accepts.
lars_path |
c-lasso |
comlasso | Gaines et al. | CLASSO | cvxcla |
|
|---|---|---|---|---|---|---|
| caps | – | – | – | rows | rows | yes |
| per-coefficient signs | all | – | – | rows | rows | yes |
| equality rows | – | zero sums | yes | yes | yes | |
| inequality rows | – | – | – | yes | yes | yes |
| zero sums | – | yes | on blocks | yes | yes | yes |
| yes | yes | yes | yes | yes | yes | |
| without a ridge | yes | – | yes | – | – | yes |
We do not compare run times with comlasso, the algorithm of Gaines et al. or c-lasso. None runs here as its authors would run it today: comlasso is R code built for R 3.2 and read under R 4, the algorithm of Gaines et al. is our port of Julia 0.6 code, and c-lasso returns a grid of its own with a ridge. A timing across R, Julia and Python would measure the languages and the ports as much as the algorithms. A user choosing among them should first ask which constraints each accepts, and then time them on their own problem.
7 Conclusion
The checks here support the identity of Schmelzer and Hastie (2026) wherever the encodings reach. On every problem, a CLA written for portfolios returns the exact knots, or stops with an error where its arithmetic cannot be trusted. With the paths stay exact with no ridge, where the other path algorithms for general constraints trace a ridged problem that ends elsewhere.
Data and Code Availability
The software is in preprints/constrained_lasso/ of https://github.com/Jebel-Quant/lasso, under the MIT licence. Each script has a lockfile that fixes Python 3.12 and every package by version and hash. python/make_figures.py computes every path with cvxcla.Lasso 2.7.1 (Schmelzer, 2026a), runs every check, and writes every figure, table and number the text quotes. python/classo_check.py runs c-lasso 1.0.11. R/comlasso_check.R runs comlasso 0.2 under R 4.6.1, locally and in CI. The package was built for R 3.2, and R 4 refuses to install a package built before R 4.0, so the script does not install it. It fetches the package from its authors’ repository at a pinned commit, checks its SHA-256, and reads its functions from the package’s serialized code with lazyLoad, unchanged. comlasso is plain R, with no compiled code, so nothing in it depends on the R 3 build; its one dependency, Rglpk, comes from a dated CRAN snapshot. julia/classopath.jl ports ConstrainedLasso.jl, written for Julia 0.6, to Julia 1.12, with each departure marked; none changes the algorithm. julia/gaines_check.jl runs it in a pinned environment. The sCD14 data are not redistributed: python/fetch_scd14.py downloads coda4microbiome 0.2.4 from CRAN or, should CRAN drop it, from a dated snapshot of Posit Package Manager. It checks the SHA-256 of the tarball, and that of the data file inside it, which is the same byte for byte in both. make figures runs all five, in CI as well.
Every random design is drawn inside python/make_figures.py from a seed recorded there: seed 7 for the problems of Table 2, seeds 7 to 9 for Table 3, and seeds 7 to 16 for Tables 4 and 5. On a fixed platform the discrete results reproduce exactly: the knot counts, which problems are declined, and whether each path passes the certificate. A test runs the problems of Tables 3 and 4 twice and checks that they do. Only residuals near rounding vary, and only in their last digits.
The lockfiles fix the software, not the hardware: those residuals also differ in the last digits on another CPU, so the tests use tolerances between and , and costs are given only as ratios.
Competing interests The author works at Jebel Quant Research, which hosts the code, and maintains cvxcla, which computes every path. The checks are the author’s; the references they compare against are not. LARS, Clarabel, comlasso, ConstrainedLasso.jl and c-lasso were written by others, and the optimality conditions need no solver. There are no other competing interests.
Acknowledgements I thank Trevor Hastie for many helpful discussions.
References
- Abadie, A., Diamond, A., & Hainmueller, J. (2010). Synthetic Control Methods for Comparative Case Studies: Estimating the Effect of California’s Tobacco Control Program. Journal of the American Statistical Association, 105(490), 493–505. https://doi.org/10.1198/jasa.2009.ap08746 ↩
- Brodie, J., Daubechies, I., De Mol, C., Giannone, D., & Loris, I. (2009). Sparse and stable Markowitz portfolios. Proceedings of the National Academy of Sciences, 106(30), 12267–12272. https://doi.org/10.1073/pnas.0904287106 ↩ 1 2
- Calle, M. L., Pujolassos, M., & Susín, A. (2023). coda4microbiome: compositional data analysis for microbiome cross-sectional and longitudinal studies. BMC Bioinformatics, 24, 82. https://doi.org/10.1186/s12859-023-05205-3 ↩
- Efron, B., Hastie, T., Johnstone, I., & Tibshirani, R. (2004). Least angle regression. The Annals of Statistics, 32(2), 407–499. https://doi.org/10.1214/009053604000000067 ↩ 1 2 3 4
- Gaines, B. R., Kim, J., & Zhou, H. (2018). Algorithms for Fitting the Constrained Lasso. Journal of Computational and Graphical Statistics, 27(4), 861–871. https://doi.org/10.1080/10618600.2018.1473777 ↩ 1 2 3
- Hobson, M., Butcher, L., & Lentati, L. (2026). CLASSO: a practical primal path-following algorithm for the constrained LASSO. arXiv. https://doi.org/10.48550/ARXIV.2610.17024 ↩ 1 2 3 4 5 6
- James, G. M., Paulson, C., & Rusmevichientong, P. (2020). Penalized and Constrained Optimization: An Application to High-Dimensional Website Advertising. Journal of the American Statistical Association, 115(529), 107–122. https://doi.org/10.1080/01621459.2019.1609970 ↩
- Jeon, J.-J., Kim, Y., Won, S., & Choi, H. (2020). Primal path algorithm for compositional data analysis. Computational Statistics & Data Analysis, 148, 106958. https://doi.org/10.1016/j.csda.2020.106958 ↩ 1 2 3
- Lawson, C. L., & Hanson, R. J. (1974). Solving Least Squares Problems. Prentice-Hall. ↩
- Lin, W., Shi, P., Feng, R., & Li, H. (2014). Variable selection in regression with compositional covariates. Biometrika, 101(4), 785–797. https://doi.org/10.1093/biomet/asu031 ↩
- Markowitz, H. M. (1956). The optimization of a quadratic function subject to linear constraints. Naval Research Logistics Quarterly, 3(1–2), 111–133. https://doi.org/10.1002/nav.3800030110 ↩ 1 2
- Noguera-Julian, M., Rocafort, M., Guillén, Y., Rivera, J., Casadellà, M., Nowak, P., Hildebrand, F., Zeller, G., Parera, M., Bellido, R., Rodríguez, C., Carrillo, J., Mothe, B., Coll, J., Bravo, I., Estany, C., Herrero, C., Saz, J., Sirera, G., … Paredes, R. (2016). Gut Microbiota Linked to Sexual Preference and HIV Infection. EBioMedicine, 5, 135–146. https://doi.org/10.1016/j.ebiom.2016.01.032 ↩ 1 2
- Okabe, M., & Ito, K. (2008). Color universal design (CUD): how to make figures and presentations that are friendly to colorblind people. https://jfly.uni-koeln.de/color/ ↩
- Osborne, M. R., Presnell, B., & Turlach, B. A. (2000). A new approach to variable selection in least squares problems. IMA Journal of Numerical Analysis, 20(3), 389–403. https://doi.org/10.1093/imanum/20.3.389 ↩
- Pedregosa, F. et al. (2011). Scikit-learn: machine learning in Python. Journal of Machine Learning Research, 12, 2825–2830. ↩ 1 2
- Schmelzer, T. (2026b). cvxcla: The Critical Line Algorithm with an Operator Interface in Python. Elsevier BV. https://doi.org/10.2139/ssrn.7583179 ↩ 1 2 3
- Schmelzer, T. (2026a). The efficient frontier from a LASSO solver: a numerical check of the CLA–LASSO identity. Journal of Reproducible Statistics, 1. https://doi.org/10.68365/jrepstat.2026.7 ↩
- Schmelzer, T., & Hastie, T. (2026). The Critical Line Algorithm and the Constrained LASSO: One Curve, Two Literatures. arXiv. https://doi.org/10.48550/ARXIV.2609.25704 ↩ 1 2 3 4 5 6 7 8 9 10 11 12 13
- Simpson, L., Combettes, P. L., & Müller, C. L. (2021). c-lasso – a Python package for constrained sparse and robust regression and classification. Journal of Open Source Software, 6(57), 2844. https://doi.org/10.21105/joss.02844 ↩ 1 2
- Tibshirani, R. (1996). Regression Shrinkage and Selection Via the Lasso. Journal of the Royal Statistical Society Series B: Statistical Methodology, 58(1), 267–288. https://doi.org/10.1111/j.2517-6161.1996.tb02080.x ↩
- Tibshirani, R. J. (2013). The lasso problem and uniqueness. Electronic Journal of Statistics, 7, 1456–1490. https://doi.org/10.1214/13-EJS815 ↩
- Wilson, P. W. F., Meigs, J. B., Sullivan, L., et al. (2007). Prediction of incident diabetes mellitus in middle-aged adults: the Framingham Offspring Study. Archives of Internal Medicine, 167(10), 1068–1074. https://doi.org/10.1001/archinte.167.10.1068 ↩
Cite this article
Schmelzer, T. (2026). The Constrained LASSO is a Portfolio: A numerical check of the CLA–LASSO identity under constraints. Journal of Reproducible Statistics, 1, 10. https://doi.org/10.68365/jrepstat.2026.10
Schmelzer, Thomas. 2026. “The Constrained LASSO Is a Portfolio: A Numerical Check of the CLA–LASSO Identity Under Constraints.” Journal of Reproducible Statistics 1: 10. https://doi.org/10.68365/jrepstat.2026.10.
Schmelzer T. The Constrained LASSO is a Portfolio: A numerical check of the CLA–LASSO identity under constraints. Journal of Reproducible Statistics. 2026;1:10. doi:10.68365/jrepstat.2026.10
Schmelzer, T. (2026) “The Constrained LASSO is a Portfolio: A numerical check of the CLA–LASSO identity under constraints,” Journal of Reproducible Statistics, 1, p. 10. Available at: https://doi.org/10.68365/jrepstat.2026.10.
doi: https://doi.org/10.68365/jrepstat.2026.10
Downloads
https://doi.org/10.68365/jrepstat.2026.10 also supports content negotiation, so reference managers can fetch the citation from the DOI directly. The exports above work without it.