ml-matrix 6.1.2 → 6.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/History.md +36 -0
- package/README.md +6 -6
- package/matrix.d.ts +106 -70
- package/matrix.js +822 -668
- package/matrix.umd.js +1 -0
- package/package.json +21 -12
- package/src/correlation.js +17 -7
- package/src/covariance.js +10 -6
- package/src/dc/cholesky.js +20 -16
- package/src/dc/evd.js +45 -45
- package/src/dc/lu.js +32 -32
- package/src/dc/nipals.js +135 -0
- package/src/dc/qr.js +24 -24
- package/src/dc/svd.js +48 -48
- package/src/dc/util.js +1 -1
- package/src/determinant.js +2 -2
- package/src/index.js +4 -3
- package/src/inspect.js +2 -2
- package/src/linearDependencies.js +14 -14
- package/src/mathOperations.js +147 -147
- package/src/matrix.js +234 -233
- package/src/pseudoInverse.js +5 -5
- package/src/stat.js +33 -33
- package/src/util.js +8 -8
- package/src/views/selection.js +28 -28
- package/src/views/sub.js +28 -28
- package/src/wrap/WrapperMatrix1D.js +2 -2
package/src/dc/nipals.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import WrapperMatrix2D from '../wrap/WrapperMatrix2D';
|
|
2
|
+
import Matrix from '../matrix';
|
|
3
|
+
|
|
4
|
+
export default class nipals {
|
|
5
|
+
constructor(X, options = {}) {
|
|
6
|
+
X = WrapperMatrix2D.checkMatrix(X);
|
|
7
|
+
let { Y } = options;
|
|
8
|
+
const {
|
|
9
|
+
scaleScores = false,
|
|
10
|
+
maxIterations = 1000,
|
|
11
|
+
terminationCriteria = 1e-10,
|
|
12
|
+
} = options;
|
|
13
|
+
|
|
14
|
+
let u;
|
|
15
|
+
if (Y) {
|
|
16
|
+
if (Array.isArray(Y) && typeof Y[0] === 'number') {
|
|
17
|
+
Y = Matrix.columnVector(Y);
|
|
18
|
+
} else {
|
|
19
|
+
Y = WrapperMatrix2D.checkMatrix(Y);
|
|
20
|
+
}
|
|
21
|
+
if (!Y.isColumnVector() || Y.rows !== X.rows) {
|
|
22
|
+
throw new Error('Y must be a column vector of length X.rows');
|
|
23
|
+
}
|
|
24
|
+
u = Y;
|
|
25
|
+
} else {
|
|
26
|
+
u = X.getColumnVector(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let diff = 1;
|
|
30
|
+
let t, q, w, tOld;
|
|
31
|
+
|
|
32
|
+
for (
|
|
33
|
+
let counter = 0;
|
|
34
|
+
counter < maxIterations && diff > terminationCriteria;
|
|
35
|
+
counter++
|
|
36
|
+
) {
|
|
37
|
+
w = X.transpose()
|
|
38
|
+
.mmul(u)
|
|
39
|
+
.div(
|
|
40
|
+
u
|
|
41
|
+
.transpose()
|
|
42
|
+
.mmul(u)
|
|
43
|
+
.get(0, 0),
|
|
44
|
+
);
|
|
45
|
+
w = w.div(w.norm());
|
|
46
|
+
|
|
47
|
+
t = X.mmul(w).div(
|
|
48
|
+
w
|
|
49
|
+
.transpose()
|
|
50
|
+
.mmul(w)
|
|
51
|
+
.get(0, 0),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
if (counter > 0) {
|
|
55
|
+
diff = t
|
|
56
|
+
.clone()
|
|
57
|
+
.sub(tOld)
|
|
58
|
+
.pow(2)
|
|
59
|
+
.sum();
|
|
60
|
+
}
|
|
61
|
+
tOld = t.clone();
|
|
62
|
+
|
|
63
|
+
if (Y) {
|
|
64
|
+
q = Y.transpose()
|
|
65
|
+
.mmul(t)
|
|
66
|
+
.div(
|
|
67
|
+
t
|
|
68
|
+
.transpose()
|
|
69
|
+
.mmul(t)
|
|
70
|
+
.get(0, 0),
|
|
71
|
+
);
|
|
72
|
+
q = q.div(q.norm());
|
|
73
|
+
|
|
74
|
+
u = Y.mmul(q).div(
|
|
75
|
+
q
|
|
76
|
+
.transpose()
|
|
77
|
+
.mmul(q)
|
|
78
|
+
.get(0, 0),
|
|
79
|
+
);
|
|
80
|
+
} else {
|
|
81
|
+
u = t;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (Y) {
|
|
86
|
+
let p = X.transpose()
|
|
87
|
+
.mmul(t)
|
|
88
|
+
.div(
|
|
89
|
+
t
|
|
90
|
+
.transpose()
|
|
91
|
+
.mmul(t)
|
|
92
|
+
.get(0, 0),
|
|
93
|
+
);
|
|
94
|
+
p = p.div(p.norm());
|
|
95
|
+
let xResidual = X.clone().sub(t.clone().mmul(p.transpose()));
|
|
96
|
+
let residual = u
|
|
97
|
+
.transpose()
|
|
98
|
+
.mmul(t)
|
|
99
|
+
.div(
|
|
100
|
+
t
|
|
101
|
+
.transpose()
|
|
102
|
+
.mmul(t)
|
|
103
|
+
.get(0, 0),
|
|
104
|
+
);
|
|
105
|
+
let yResidual = Y.clone().sub(
|
|
106
|
+
t
|
|
107
|
+
.clone()
|
|
108
|
+
.mulS(residual.get(0, 0))
|
|
109
|
+
.mmul(q.transpose()),
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
this.t = t;
|
|
113
|
+
this.p = p.transpose();
|
|
114
|
+
this.w = w.transpose();
|
|
115
|
+
this.q = q;
|
|
116
|
+
this.u = u;
|
|
117
|
+
this.s = t.transpose().mmul(t);
|
|
118
|
+
this.xResidual = xResidual;
|
|
119
|
+
this.yResidual = yResidual;
|
|
120
|
+
this.betas = residual;
|
|
121
|
+
} else {
|
|
122
|
+
this.w = w.transpose();
|
|
123
|
+
this.s = t
|
|
124
|
+
.transpose()
|
|
125
|
+
.mmul(t)
|
|
126
|
+
.sqrt();
|
|
127
|
+
if (scaleScores) {
|
|
128
|
+
this.t = t.clone().div(this.s.get(0, 0));
|
|
129
|
+
} else {
|
|
130
|
+
this.t = t;
|
|
131
|
+
}
|
|
132
|
+
this.xResidual = X.sub(t.mmul(w.transpose()));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
package/src/dc/qr.js
CHANGED
|
@@ -7,14 +7,14 @@ export default class QrDecomposition {
|
|
|
7
7
|
constructor(value) {
|
|
8
8
|
value = WrapperMatrix2D.checkMatrix(value);
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
let qr = value.clone();
|
|
11
|
+
let m = value.rows;
|
|
12
|
+
let n = value.columns;
|
|
13
|
+
let rdiag = new Float64Array(n);
|
|
14
|
+
let i, j, k, s;
|
|
15
15
|
|
|
16
16
|
for (k = 0; k < n; k++) {
|
|
17
|
-
|
|
17
|
+
let nrm = 0;
|
|
18
18
|
for (i = k; i < m; i++) {
|
|
19
19
|
nrm = hypotenuse(nrm, qr.get(i, k));
|
|
20
20
|
}
|
|
@@ -47,8 +47,8 @@ export default class QrDecomposition {
|
|
|
47
47
|
solve(value) {
|
|
48
48
|
value = Matrix.checkMatrix(value);
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
let qr = this.QR;
|
|
51
|
+
let m = qr.rows;
|
|
52
52
|
|
|
53
53
|
if (value.rows !== m) {
|
|
54
54
|
throw new Error('Matrix row dimensions must agree');
|
|
@@ -57,10 +57,10 @@ export default class QrDecomposition {
|
|
|
57
57
|
throw new Error('Matrix is rank deficient');
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
let count = value.columns;
|
|
61
|
+
let X = value.clone();
|
|
62
|
+
let n = qr.columns;
|
|
63
|
+
let i, j, k, s;
|
|
64
64
|
|
|
65
65
|
for (k = 0; k < n; k++) {
|
|
66
66
|
for (j = 0; j < count; j++) {
|
|
@@ -89,8 +89,8 @@ export default class QrDecomposition {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
isFullRank() {
|
|
92
|
-
|
|
93
|
-
for (
|
|
92
|
+
let columns = this.QR.columns;
|
|
93
|
+
for (let i = 0; i < columns; i++) {
|
|
94
94
|
if (this.Rdiag[i] === 0) {
|
|
95
95
|
return false;
|
|
96
96
|
}
|
|
@@ -99,10 +99,10 @@ export default class QrDecomposition {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
get upperTriangularMatrix() {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
let qr = this.QR;
|
|
103
|
+
let n = qr.columns;
|
|
104
|
+
let X = new Matrix(n, n);
|
|
105
|
+
let i, j;
|
|
106
106
|
for (i = 0; i < n; i++) {
|
|
107
107
|
for (j = 0; j < n; j++) {
|
|
108
108
|
if (i < j) {
|
|
@@ -118,11 +118,11 @@ export default class QrDecomposition {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
get orthogonalMatrix() {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
let qr = this.QR;
|
|
122
|
+
let rows = qr.rows;
|
|
123
|
+
let columns = qr.columns;
|
|
124
|
+
let X = new Matrix(rows, columns);
|
|
125
|
+
let i, j, k, s;
|
|
126
126
|
|
|
127
127
|
for (k = columns - 1; k >= 0; k--) {
|
|
128
128
|
for (i = 0; i < rows; i++) {
|
|
@@ -136,7 +136,7 @@ export default class QrDecomposition {
|
|
|
136
136
|
s += qr.get(i, k) * X.get(i, j);
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
s = -s / qr
|
|
139
|
+
s = -s / qr.get(k, k);
|
|
140
140
|
|
|
141
141
|
for (i = k; i < rows; i++) {
|
|
142
142
|
X.set(i, j, X.get(i, j) + s * qr.get(i, k));
|
package/src/dc/svd.js
CHANGED
|
@@ -7,33 +7,33 @@ export default class SingularValueDecomposition {
|
|
|
7
7
|
constructor(value, options = {}) {
|
|
8
8
|
value = WrapperMatrix2D.checkMatrix(value);
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
let m = value.rows;
|
|
11
|
+
let n = value.columns;
|
|
12
12
|
|
|
13
13
|
const {
|
|
14
14
|
computeLeftSingularVectors = true,
|
|
15
15
|
computeRightSingularVectors = true,
|
|
16
|
-
autoTranspose = false
|
|
16
|
+
autoTranspose = false,
|
|
17
17
|
} = options;
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
let wantu = Boolean(computeLeftSingularVectors);
|
|
20
|
+
let wantv = Boolean(computeRightSingularVectors);
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
let swapped = false;
|
|
23
|
+
let a;
|
|
24
24
|
if (m < n) {
|
|
25
25
|
if (!autoTranspose) {
|
|
26
26
|
a = value.clone();
|
|
27
27
|
// eslint-disable-next-line no-console
|
|
28
28
|
console.warn(
|
|
29
|
-
'Computing SVD on a matrix with more columns than rows. Consider enabling autoTranspose'
|
|
29
|
+
'Computing SVD on a matrix with more columns than rows. Consider enabling autoTranspose',
|
|
30
30
|
);
|
|
31
31
|
} else {
|
|
32
32
|
a = value.transpose();
|
|
33
33
|
m = a.rows;
|
|
34
34
|
n = a.columns;
|
|
35
35
|
swapped = true;
|
|
36
|
-
|
|
36
|
+
let aux = wantu;
|
|
37
37
|
wantu = wantv;
|
|
38
38
|
wantv = aux;
|
|
39
39
|
}
|
|
@@ -41,21 +41,21 @@ export default class SingularValueDecomposition {
|
|
|
41
41
|
a = value.clone();
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
let nu = Math.min(m, n);
|
|
45
|
+
let ni = Math.min(m + 1, n);
|
|
46
|
+
let s = new Float64Array(ni);
|
|
47
|
+
let U = new Matrix(m, nu);
|
|
48
|
+
let V = new Matrix(n, n);
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
let e = new Float64Array(n);
|
|
51
|
+
let work = new Float64Array(m);
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
let si = new Float64Array(ni);
|
|
54
54
|
for (let i = 0; i < ni; i++) si[i] = i;
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
let nct = Math.min(m - 1, n);
|
|
57
|
+
let nrt = Math.max(0, Math.min(n - 2, m));
|
|
58
|
+
let mrc = Math.max(nct, nrt);
|
|
59
59
|
|
|
60
60
|
for (let k = 0; k < mrc; k++) {
|
|
61
61
|
if (k < nct) {
|
|
@@ -202,9 +202,9 @@ export default class SingularValueDecomposition {
|
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
205
|
+
let pp = p - 1;
|
|
206
|
+
let iter = 0;
|
|
207
|
+
let eps = Number.EPSILON;
|
|
208
208
|
while (p > 0) {
|
|
209
209
|
let k, kase;
|
|
210
210
|
for (k = p - 2; k >= -1; k--) {
|
|
@@ -295,7 +295,7 @@ export default class SingularValueDecomposition {
|
|
|
295
295
|
Math.abs(s[p - 2]),
|
|
296
296
|
Math.abs(e[p - 2]),
|
|
297
297
|
Math.abs(s[k]),
|
|
298
|
-
Math.abs(e[k])
|
|
298
|
+
Math.abs(e[k]),
|
|
299
299
|
);
|
|
300
300
|
const sp = s[p - 1] / scale;
|
|
301
301
|
const spm1 = s[p - 2] / scale;
|
|
@@ -396,7 +396,7 @@ export default class SingularValueDecomposition {
|
|
|
396
396
|
}
|
|
397
397
|
|
|
398
398
|
if (swapped) {
|
|
399
|
-
|
|
399
|
+
let tmp = V;
|
|
400
400
|
V = U;
|
|
401
401
|
U = tmp;
|
|
402
402
|
}
|
|
@@ -409,10 +409,10 @@ export default class SingularValueDecomposition {
|
|
|
409
409
|
}
|
|
410
410
|
|
|
411
411
|
solve(value) {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
412
|
+
let Y = value;
|
|
413
|
+
let e = this.threshold;
|
|
414
|
+
let scols = this.s.length;
|
|
415
|
+
let Ls = Matrix.zeros(scols, scols);
|
|
416
416
|
|
|
417
417
|
for (let i = 0; i < scols; i++) {
|
|
418
418
|
if (Math.abs(this.s[i]) <= e) {
|
|
@@ -422,13 +422,13 @@ export default class SingularValueDecomposition {
|
|
|
422
422
|
}
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
|
|
426
|
-
|
|
425
|
+
let U = this.U;
|
|
426
|
+
let V = this.rightSingularVectors;
|
|
427
427
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
428
|
+
let VL = V.mmul(Ls);
|
|
429
|
+
let vrows = V.rows;
|
|
430
|
+
let urows = U.rows;
|
|
431
|
+
let VLU = Matrix.zeros(vrows, urows);
|
|
432
432
|
|
|
433
433
|
for (let i = 0; i < vrows; i++) {
|
|
434
434
|
for (let j = 0; j < urows; j++) {
|
|
@@ -448,11 +448,11 @@ export default class SingularValueDecomposition {
|
|
|
448
448
|
}
|
|
449
449
|
|
|
450
450
|
inverse() {
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
451
|
+
let V = this.V;
|
|
452
|
+
let e = this.threshold;
|
|
453
|
+
let vrows = V.rows;
|
|
454
|
+
let vcols = V.columns;
|
|
455
|
+
let X = new Matrix(vrows, this.s.length);
|
|
456
456
|
|
|
457
457
|
for (let i = 0; i < vrows; i++) {
|
|
458
458
|
for (let j = 0; j < vcols; j++) {
|
|
@@ -462,11 +462,11 @@ export default class SingularValueDecomposition {
|
|
|
462
462
|
}
|
|
463
463
|
}
|
|
464
464
|
|
|
465
|
-
|
|
465
|
+
let U = this.U;
|
|
466
466
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
467
|
+
let urows = U.rows;
|
|
468
|
+
let ucols = U.columns;
|
|
469
|
+
let Y = new Matrix(vrows, urows);
|
|
470
470
|
|
|
471
471
|
for (let i = 0; i < vrows; i++) {
|
|
472
472
|
for (let j = 0; j < urows; j++) {
|
|
@@ -490,10 +490,10 @@ export default class SingularValueDecomposition {
|
|
|
490
490
|
}
|
|
491
491
|
|
|
492
492
|
get rank() {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
for (
|
|
493
|
+
let tol = Math.max(this.m, this.n) * this.s[0] * Number.EPSILON;
|
|
494
|
+
let r = 0;
|
|
495
|
+
let s = this.s;
|
|
496
|
+
for (let i = 0, ii = s.length; i < ii; i++) {
|
|
497
497
|
if (s[i] > tol) {
|
|
498
498
|
r++;
|
|
499
499
|
}
|
package/src/dc/util.js
CHANGED
package/src/determinant.js
CHANGED
|
@@ -5,7 +5,7 @@ import MatrixSelectionView from './views/selection';
|
|
|
5
5
|
export function determinant(matrix) {
|
|
6
6
|
matrix = Matrix.checkMatrix(matrix);
|
|
7
7
|
if (matrix.isSquare()) {
|
|
8
|
-
|
|
8
|
+
let a, b, c, d;
|
|
9
9
|
if (matrix.columns === 2) {
|
|
10
10
|
// 2 x 2 matrix
|
|
11
11
|
a = matrix.get(0, 0);
|
|
@@ -16,7 +16,7 @@ export function determinant(matrix) {
|
|
|
16
16
|
return a * d - b * c;
|
|
17
17
|
} else if (matrix.columns === 3) {
|
|
18
18
|
// 3 x 3 matrix
|
|
19
|
-
|
|
19
|
+
let subMatrix0, subMatrix1, subMatrix2;
|
|
20
20
|
subMatrix0 = new MatrixSelectionView(matrix, [1, 2], [1, 2]);
|
|
21
21
|
subMatrix1 = new MatrixSelectionView(matrix, [1, 2], [0, 2]);
|
|
22
22
|
subMatrix2 = new MatrixSelectionView(matrix, [1, 2], [0, 1]);
|
package/src/index.js
CHANGED
|
@@ -14,15 +14,16 @@ export { correlation } from './correlation';
|
|
|
14
14
|
|
|
15
15
|
export {
|
|
16
16
|
default as SingularValueDecomposition,
|
|
17
|
-
default as SVD
|
|
17
|
+
default as SVD,
|
|
18
18
|
} from './dc/svd.js';
|
|
19
19
|
export {
|
|
20
20
|
default as EigenvalueDecomposition,
|
|
21
|
-
default as EVD
|
|
21
|
+
default as EVD,
|
|
22
22
|
} from './dc/evd.js';
|
|
23
23
|
export {
|
|
24
24
|
default as CholeskyDecomposition,
|
|
25
|
-
default as CHO
|
|
25
|
+
default as CHO,
|
|
26
26
|
} from './dc/cholesky.js';
|
|
27
27
|
export { default as LuDecomposition, default as LU } from './dc/lu.js';
|
|
28
28
|
export { default as QrDecomposition, default as QR } from './dc/qr.js';
|
|
29
|
+
export { default as Nipals, default as NIPALS } from './dc/nipals.js';
|
package/src/inspect.js
CHANGED
|
@@ -19,9 +19,9 @@ function inspectData(matrix, indent) {
|
|
|
19
19
|
const maxI = Math.min(rows, maxRows);
|
|
20
20
|
const maxJ = Math.min(columns, maxColumns);
|
|
21
21
|
const result = [];
|
|
22
|
-
for (
|
|
22
|
+
for (let i = 0; i < maxI; i++) {
|
|
23
23
|
let line = [];
|
|
24
|
-
for (
|
|
24
|
+
for (let j = 0; j < maxJ; j++) {
|
|
25
25
|
line.push(formatNumber(matrix.get(i, j)));
|
|
26
26
|
}
|
|
27
27
|
result.push(`${line.join(' ')}`);
|
|
@@ -2,8 +2,8 @@ import Matrix from './matrix';
|
|
|
2
2
|
import SingularValueDecomposition from './dc/svd';
|
|
3
3
|
|
|
4
4
|
function xrange(n, exception) {
|
|
5
|
-
|
|
6
|
-
for (
|
|
5
|
+
let range = [];
|
|
6
|
+
for (let i = 0; i < n; i++) {
|
|
7
7
|
if (i !== exception) {
|
|
8
8
|
range.push(i);
|
|
9
9
|
}
|
|
@@ -16,13 +16,13 @@ function dependenciesOneRow(
|
|
|
16
16
|
matrix,
|
|
17
17
|
index,
|
|
18
18
|
thresholdValue = 10e-10,
|
|
19
|
-
thresholdError = 10e-10
|
|
19
|
+
thresholdError = 10e-10,
|
|
20
20
|
) {
|
|
21
21
|
if (error > thresholdError) {
|
|
22
22
|
return new Array(matrix.rows + 1).fill(0);
|
|
23
23
|
} else {
|
|
24
|
-
|
|
25
|
-
for (
|
|
24
|
+
let returnArray = matrix.addRow(index, [0]);
|
|
25
|
+
for (let i = 0; i < returnArray.rows; i++) {
|
|
26
26
|
if (Math.abs(returnArray.get(i, 0)) < thresholdValue) {
|
|
27
27
|
returnArray.set(i, 0, 0);
|
|
28
28
|
}
|
|
@@ -35,20 +35,20 @@ export function linearDependencies(matrix, options = {}) {
|
|
|
35
35
|
const { thresholdValue = 10e-10, thresholdError = 10e-10 } = options;
|
|
36
36
|
matrix = Matrix.checkMatrix(matrix);
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
let n = matrix.rows;
|
|
39
|
+
let results = new Matrix(n, n);
|
|
40
40
|
|
|
41
|
-
for (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
for (let i = 0; i < n; i++) {
|
|
42
|
+
let b = Matrix.columnVector(matrix.getRow(i));
|
|
43
|
+
let Abis = matrix.subMatrixRow(xrange(n, i)).transpose();
|
|
44
|
+
let svd = new SingularValueDecomposition(Abis);
|
|
45
|
+
let x = svd.solve(b);
|
|
46
|
+
let error = Matrix.sub(b, Abis.mmul(x))
|
|
47
47
|
.abs()
|
|
48
48
|
.max();
|
|
49
49
|
results.setRow(
|
|
50
50
|
i,
|
|
51
|
-
dependenciesOneRow(error, x, i, thresholdValue, thresholdError)
|
|
51
|
+
dependenciesOneRow(error, x, i, thresholdValue, thresholdError),
|
|
52
52
|
);
|
|
53
53
|
}
|
|
54
54
|
return results;
|