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';
const X = [
[1, 1, 2],
[10, 11, -9],
[-1, 0, 0],
[-5, 6, -7],
];
const y = [-1, 11, 0, 1];
const k = 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 RHS
const X = new Matrix([
[1, 1, 2],
[10, 11, -9],
[-1, 0, 0],
[-5, 6, -7],
]);
// Y can either be a Matrix or an array of arrays
const Y = new Matrix([
[-1, 0, 0, 9],
[11, -20, 103, 5],
[0, 0, 0, 0],
[1, 2, 3, 4],
]);
const K = 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.