Fast Combinatorial Non-negative Least Squares.
As described in the publication by Van Benthem and Keenan (10.1002/cem.889), which is in turn based on the active-set method algorithm previously published by Lawson and Hanson. The basic active-set method is implemented in the nnls repository.
Given the matrices
https://en.wikipedia.org/wiki/Non-negative_least_squares
npm i ml-fcnnls- Single
$y$ , using arrays as inputs.
import{fcnnlsVector}from'ml-fcnnls';constX=[[1,1,2],[10,11,-9],[-1,0,0],[-5,6,-7],];consty=[-1,11,0,1];constk=fcnnlsVector(X,y).K.to1DArray();/* k = [0.4610, 0.5611, 0] */- Multiple RHS, using
Matrixinstances as inputs.
import{fcnnls}from'ml-fcnnls';import{Matrix}from'ml-matrix';//npm i ml-matrix// Example with multiple RHSconstX=newMatrix([[1,1,2],[10,11,-9],[-1,0,0],[-5,6,-7],]);// Y can either be a Matrix or an array of arraysconstY=newMatrix([[-1,0,0,9],[11,-20,103,5],[0,0,0,0],[1,2,3,4],]);constK=fcnnls(X,Y).K;// `K.to2DArray()` converts the matrix to array./*K = Matrix([ [0.4610, 0, 4.9714, 0], [0.5611, 0, 4.7362, 2.2404], [0, 1.2388, 0, 1.9136],])*/- Using the options
const{ K, info }=fcnnls(X,Y,{info: true,// returns the error/iteration.maxIterations: 5,gradientTolerance: 0,});/* K is the same result as in 2 *//* info = { rse: [[...], [...], [...]], iterations: 3 } */Both fcnnls and fcnnlsVector accept the same options.
| Option | Type | Default | Description |
|---|---|---|---|
maxIterations | number | 3 * X.columns | Maximum number of iterations of the active-set loop. |
gradientTolerance | number | 1e-5 | Larger values (like 1e-4) can help when the iteration limit is exceeded. |
info | boolean | false | When true, also returns info with the root squared error per column of Y and the iteration count. |
interceptAtZero | boolean | true | Set to false to add a column of ones to the left of X, fitting an intercept. |
K is always a Matrix of non-negative coefficients. When info: true, the result also carries info.rse (root squared error, one row per computation of K) and info.iterations.