@elarsaks/umap-wasm 0.1.0

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.
Files changed (41) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +349 -0
  3. package/dist/src/heap.d.ts +12 -0
  4. package/dist/src/heap.js +226 -0
  5. package/dist/src/index.d.ts +1 -0
  6. package/dist/src/index.js +5 -0
  7. package/dist/src/lib.d.ts +1 -0
  8. package/dist/src/lib.js +5 -0
  9. package/dist/src/matrix.d.ts +41 -0
  10. package/dist/src/matrix.js +360 -0
  11. package/dist/src/nn_descent.d.ts +17 -0
  12. package/dist/src/nn_descent.js +204 -0
  13. package/dist/src/tree.d.ts +16 -0
  14. package/dist/src/tree.js +320 -0
  15. package/dist/src/umap.d.ts +102 -0
  16. package/dist/src/umap.js +842 -0
  17. package/dist/src/utils.d.ts +16 -0
  18. package/dist/src/utils.js +137 -0
  19. package/dist/src/wasmBridge.d.ts +57 -0
  20. package/dist/src/wasmBridge.js +290 -0
  21. package/dist/test/matrix.test.d.ts +1 -0
  22. package/dist/test/matrix.test.js +169 -0
  23. package/dist/test/nn_descent.test.d.ts +1 -0
  24. package/dist/test/nn_descent.test.js +58 -0
  25. package/dist/test/test_data.d.ts +13 -0
  26. package/dist/test/test_data.js +1054 -0
  27. package/dist/test/tree.test.d.ts +1 -0
  28. package/dist/test/tree.test.js +60 -0
  29. package/dist/test/umap.test.d.ts +1 -0
  30. package/dist/test/umap.test.js +293 -0
  31. package/dist/test/utils.test.d.ts +1 -0
  32. package/dist/test/utils.test.js +128 -0
  33. package/dist/test/wasmDistance.test.d.ts +1 -0
  34. package/dist/test/wasmDistance.test.js +124 -0
  35. package/dist/test/wasmMatrix.test.d.ts +1 -0
  36. package/dist/test/wasmMatrix.test.js +389 -0
  37. package/dist/test/wasmTree.test.d.ts +1 -0
  38. package/dist/test/wasmTree.test.js +212 -0
  39. package/lib/umap-js.js +8657 -0
  40. package/lib/umap-js.min.js +1 -0
  41. package/package.json +58 -0
@@ -0,0 +1,842 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __generator = (this && this.__generator) || function (thisArg, body) {
45
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
46
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
47
+ function verb(n) { return function (v) { return step([n, v]); }; }
48
+ function step(op) {
49
+ if (f) throw new TypeError("Generator is already executing.");
50
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
51
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
52
+ if (y = 0, t) op = [op[0] & 2, t.value];
53
+ switch (op[0]) {
54
+ case 0: case 1: t = op; break;
55
+ case 4: _.label++; return { value: op[1], done: false };
56
+ case 5: _.label++; y = op[1]; op = [0]; continue;
57
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
58
+ default:
59
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
60
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
61
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
62
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
63
+ if (t[2]) _.ops.pop();
64
+ _.trys.pop(); continue;
65
+ }
66
+ op = body.call(thisArg, _);
67
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
68
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
69
+ }
70
+ };
71
+ var __read = (this && this.__read) || function (o, n) {
72
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
73
+ if (!m) return o;
74
+ var i = m.call(o), r, ar = [], e;
75
+ try {
76
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
77
+ }
78
+ catch (error) { e = { error: error }; }
79
+ finally {
80
+ try {
81
+ if (r && !r.done && (m = i["return"])) m.call(i);
82
+ }
83
+ finally { if (e) throw e.error; }
84
+ }
85
+ return ar;
86
+ };
87
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
88
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
89
+ if (ar || !(i in from)) {
90
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
91
+ ar[i] = from[i];
92
+ }
93
+ }
94
+ return to.concat(ar || Array.prototype.slice.call(from));
95
+ };
96
+ var __importDefault = (this && this.__importDefault) || function (mod) {
97
+ return (mod && mod.__esModule) ? mod : { "default": mod };
98
+ };
99
+ Object.defineProperty(exports, "__esModule", { value: true });
100
+ exports.UMAP = void 0;
101
+ exports.euclidean = euclidean;
102
+ exports.cosine = cosine;
103
+ exports.findABParams = findABParams;
104
+ exports.fastIntersection = fastIntersection;
105
+ exports.resetLocalConnectivity = resetLocalConnectivity;
106
+ exports.initTransform = initTransform;
107
+ var heap = __importStar(require("./heap"));
108
+ var matrix = __importStar(require("./matrix"));
109
+ var nnDescent = __importStar(require("./nn_descent"));
110
+ var tree = __importStar(require("./tree"));
111
+ var utils = __importStar(require("./utils"));
112
+ var ml_levenberg_marquardt_1 = __importDefault(require("ml-levenberg-marquardt"));
113
+ var wasmBridge = __importStar(require("./wasmBridge"));
114
+ var SMOOTH_K_TOLERANCE = 1e-5;
115
+ var MIN_K_DIST_SCALE = 1e-3;
116
+ var UMAP = (function () {
117
+ function UMAP(params) {
118
+ if (params === void 0) { params = {}; }
119
+ var _this = this;
120
+ this.learningRate = 1.0;
121
+ this.localConnectivity = 1.0;
122
+ this.minDist = 0.1;
123
+ this.nComponents = 2;
124
+ this.nEpochs = 0;
125
+ this.nNeighbors = 15;
126
+ this.negativeSampleRate = 5;
127
+ this.random = Math.random;
128
+ this.repulsionStrength = 1.0;
129
+ this.setOpMixRatio = 1.0;
130
+ this.spread = 1.0;
131
+ this.transformQueueSize = 4.0;
132
+ this.targetMetric = "categorical";
133
+ this.targetWeight = 0.5;
134
+ this.targetNNeighbors = this.nNeighbors;
135
+ this.distanceFn = euclidean;
136
+ this.useWasmDistance = false;
137
+ this.useWasmMatrix = false;
138
+ this.useWasmTree = false;
139
+ this.isInitialized = false;
140
+ this.rpForest = [];
141
+ this.embedding = [];
142
+ this.optimizationState = new OptimizationState();
143
+ var setParam = function (key) {
144
+ if (params[key] !== undefined)
145
+ _this[key] = params[key];
146
+ };
147
+ setParam('distanceFn');
148
+ setParam('useWasmDistance');
149
+ setParam('useWasmMatrix');
150
+ setParam('useWasmTree');
151
+ setParam('learningRate');
152
+ setParam('localConnectivity');
153
+ setParam('minDist');
154
+ setParam('nComponents');
155
+ setParam('nEpochs');
156
+ setParam('nNeighbors');
157
+ setParam('negativeSampleRate');
158
+ setParam('random');
159
+ setParam('repulsionStrength');
160
+ setParam('setOpMixRatio');
161
+ setParam('spread');
162
+ setParam('transformQueueSize');
163
+ }
164
+ UMAP.prototype.fit = function (X) {
165
+ this.initializeFit(X);
166
+ this.optimizeLayout();
167
+ return this.embedding;
168
+ };
169
+ UMAP.prototype.fitAsync = function (X_1) {
170
+ return __awaiter(this, arguments, void 0, function (X, callback) {
171
+ if (callback === void 0) { callback = function () { return true; }; }
172
+ return __generator(this, function (_a) {
173
+ switch (_a.label) {
174
+ case 0:
175
+ this.initializeFit(X);
176
+ return [4, this.optimizeLayoutAsync(callback)];
177
+ case 1:
178
+ _a.sent();
179
+ return [2, this.embedding];
180
+ }
181
+ });
182
+ });
183
+ };
184
+ UMAP.prototype.setSupervisedProjection = function (Y, params) {
185
+ if (params === void 0) { params = {}; }
186
+ this.Y = Y;
187
+ this.targetMetric = params.targetMetric || this.targetMetric;
188
+ this.targetWeight = params.targetWeight || this.targetWeight;
189
+ this.targetNNeighbors = params.targetNNeighbors || this.targetNNeighbors;
190
+ };
191
+ UMAP.prototype.setPrecomputedKNN = function (knnIndices, knnDistances) {
192
+ this.knnIndices = knnIndices;
193
+ this.knnDistances = knnDistances;
194
+ };
195
+ UMAP.prototype.initializeFit = function (X) {
196
+ if (X.length <= this.nNeighbors) {
197
+ throw new Error("Not enough data points (".concat(X.length, ") to create nNeighbors: ").concat(this.nNeighbors, ". Add more data points or adjust the configuration."));
198
+ }
199
+ if (this.X === X && this.isInitialized) {
200
+ return this.getNEpochs();
201
+ }
202
+ this.X = X;
203
+ if (!this.knnIndices && !this.knnDistances) {
204
+ var knnResults = this.nearestNeighbors(X);
205
+ this.knnIndices = knnResults.knnIndices;
206
+ this.knnDistances = knnResults.knnDistances;
207
+ }
208
+ this.graph = this.fuzzySimplicialSet(X, this.nNeighbors, this.setOpMixRatio);
209
+ this.makeSearchFns();
210
+ this.searchGraph = this.makeSearchGraph(X);
211
+ this.processGraphForSupervisedProjection();
212
+ var _a = this.initializeSimplicialSetEmbedding(), head = _a.head, tail = _a.tail, epochsPerSample = _a.epochsPerSample;
213
+ this.optimizationState.head = head;
214
+ this.optimizationState.tail = tail;
215
+ this.optimizationState.epochsPerSample = epochsPerSample;
216
+ this.initializeOptimization();
217
+ this.prepareForOptimizationLoop();
218
+ this.isInitialized = true;
219
+ return this.getNEpochs();
220
+ };
221
+ UMAP.prototype.makeSearchFns = function () {
222
+ var _this = this;
223
+ var distanceWrapper = function (a, b) {
224
+ if (_this.useWasmDistance) {
225
+ if (!wasmBridge.isWasmAvailable()) {
226
+ throw new Error('WASM distance requested via `useWasmDistance: true` but the wasm module is not initialized or available. ' +
227
+ 'Call `await wasmBridge.initWasm()` before using UMAP with wasm distances or build the wasm package.');
228
+ }
229
+ return wasmBridge.euclideanWasm(a, b);
230
+ }
231
+ return _this.distanceFn(a, b);
232
+ };
233
+ var _a = nnDescent.makeInitializations(distanceWrapper), initFromTree = _a.initFromTree, initFromRandom = _a.initFromRandom;
234
+ this.initFromTree = initFromTree;
235
+ this.initFromRandom = initFromRandom;
236
+ this.search = nnDescent.makeInitializedNNSearch(distanceWrapper);
237
+ };
238
+ UMAP.prototype.computeDistance = function (a, b) {
239
+ if (this.useWasmDistance) {
240
+ if (!wasmBridge.isWasmAvailable()) {
241
+ throw new Error('WASM distance requested via `useWasmDistance: true` but the wasm module is not initialized or available. ' +
242
+ 'Call `await wasmBridge.initWasm()` before using UMAP with wasm distances or build the wasm package.');
243
+ }
244
+ return wasmBridge.euclideanWasm(a, b);
245
+ }
246
+ return this.distanceFn(a, b);
247
+ };
248
+ UMAP.prototype.makeSearchGraph = function (X) {
249
+ var knnIndices = this.knnIndices;
250
+ var knnDistances = this.knnDistances;
251
+ var dims = [X.length, X.length];
252
+ var searchGraph = new matrix.SparseMatrix([], [], [], dims);
253
+ for (var i = 0; i < knnIndices.length; i++) {
254
+ var knn = knnIndices[i];
255
+ var distances = knnDistances[i];
256
+ for (var j = 0; j < knn.length; j++) {
257
+ var neighbor = knn[j];
258
+ var distance = distances[j];
259
+ if (distance > 0) {
260
+ searchGraph.set(i, neighbor, distance);
261
+ }
262
+ }
263
+ }
264
+ var transpose = matrix.transpose(searchGraph);
265
+ return matrix.maximum(searchGraph, transpose);
266
+ };
267
+ UMAP.prototype.transform = function (toTransform) {
268
+ var _this = this;
269
+ var rawData = this.X;
270
+ if (rawData === undefined || rawData.length === 0) {
271
+ throw new Error('No data has been fit.');
272
+ }
273
+ var nNeighbors = Math.floor(this.nNeighbors * this.transformQueueSize);
274
+ nNeighbors = Math.min(rawData.length, nNeighbors);
275
+ var init = nnDescent.initializeSearch(this.rpForest, rawData, toTransform, nNeighbors, this.initFromRandom, this.initFromTree, this.random);
276
+ var result = this.search(rawData, this.searchGraph, init, toTransform);
277
+ var _a = heap.deheapSort(result), indices = _a.indices, distances = _a.weights;
278
+ indices = indices.map(function (x) { return x.slice(0, _this.nNeighbors); });
279
+ distances = distances.map(function (x) { return x.slice(0, _this.nNeighbors); });
280
+ var adjustedLocalConnectivity = Math.max(0, this.localConnectivity - 1);
281
+ var _b = this.smoothKNNDistance(distances, this.nNeighbors, adjustedLocalConnectivity), sigmas = _b.sigmas, rhos = _b.rhos;
282
+ var _c = this.computeMembershipStrengths(indices, distances, sigmas, rhos), rows = _c.rows, cols = _c.cols, vals = _c.vals;
283
+ var size = [toTransform.length, rawData.length];
284
+ var graph = new matrix.SparseMatrix(rows, cols, vals, size);
285
+ var normed = matrix.normalize(graph, "l1");
286
+ var csrMatrix = matrix.getCSR(normed);
287
+ var nPoints = toTransform.length;
288
+ var eIndices = utils.reshape2d(csrMatrix.indices, nPoints, this.nNeighbors);
289
+ var eWeights = utils.reshape2d(csrMatrix.values, nPoints, this.nNeighbors);
290
+ var embedding = initTransform(eIndices, eWeights, this.embedding);
291
+ var nEpochs = this.nEpochs
292
+ ? this.nEpochs / 3
293
+ : graph.nRows <= 10000
294
+ ? 100
295
+ : 30;
296
+ var graphMax = graph
297
+ .getValues()
298
+ .reduce(function (max, val) { return (val > max ? val : max); }, 0);
299
+ graph = graph.map(function (value) { return (value < graphMax / nEpochs ? 0 : value); });
300
+ graph = matrix.eliminateZeros(graph);
301
+ var epochsPerSample = this.makeEpochsPerSample(graph.getValues(), nEpochs);
302
+ var head = graph.getRows();
303
+ var tail = graph.getCols();
304
+ this.assignOptimizationStateParameters({
305
+ headEmbedding: embedding,
306
+ tailEmbedding: this.embedding,
307
+ head: head,
308
+ tail: tail,
309
+ currentEpoch: 0,
310
+ nEpochs: nEpochs,
311
+ nVertices: graph.getDims()[1],
312
+ epochsPerSample: epochsPerSample,
313
+ });
314
+ this.prepareForOptimizationLoop();
315
+ return this.optimizeLayout();
316
+ };
317
+ UMAP.prototype.processGraphForSupervisedProjection = function () {
318
+ var _a = this, Y = _a.Y, X = _a.X;
319
+ if (Y) {
320
+ if (Y.length !== X.length) {
321
+ throw new Error('Length of X and y must be equal');
322
+ }
323
+ if (this.targetMetric === "categorical") {
324
+ var lt = this.targetWeight < 1.0;
325
+ var farDist = lt ? 2.5 * (1.0 / (1.0 - this.targetWeight)) : 1.0e12;
326
+ this.graph = this.categoricalSimplicialSetIntersection(this.graph, Y, farDist);
327
+ }
328
+ }
329
+ };
330
+ UMAP.prototype.step = function () {
331
+ var currentEpoch = this.optimizationState.currentEpoch;
332
+ if (currentEpoch < this.getNEpochs()) {
333
+ this.optimizeLayoutStep(currentEpoch);
334
+ }
335
+ return this.optimizationState.currentEpoch;
336
+ };
337
+ UMAP.prototype.getEmbedding = function () {
338
+ return this.embedding;
339
+ };
340
+ UMAP.prototype.nearestNeighbors = function (X) {
341
+ var _a = this, distanceFn = _a.distanceFn, nNeighbors = _a.nNeighbors;
342
+ var log2 = function (n) { return Math.log(n) / Math.log(2); };
343
+ var metricNNDescent = nnDescent.makeNNDescent(distanceFn, this.random);
344
+ var round = function (n) {
345
+ return n === 0.5 ? 0 : Math.round(n);
346
+ };
347
+ var nTrees = 5 + Math.floor(round(Math.pow(X.length, 0.5) / 20.0));
348
+ var nIters = Math.max(5, Math.floor(Math.round(log2(X.length))));
349
+ this.rpForest = tree.makeForest(X, nNeighbors, nTrees, this.random, this.useWasmTree);
350
+ var leafArray = tree.makeLeafArray(this.rpForest);
351
+ var _b = metricNNDescent(X, leafArray, nNeighbors, nIters), indices = _b.indices, weights = _b.weights;
352
+ return { knnIndices: indices, knnDistances: weights };
353
+ };
354
+ UMAP.prototype.fuzzySimplicialSet = function (X, nNeighbors, setOpMixRatio) {
355
+ if (setOpMixRatio === void 0) { setOpMixRatio = 1.0; }
356
+ var _a = this, _b = _a.knnIndices, knnIndices = _b === void 0 ? [] : _b, _c = _a.knnDistances, knnDistances = _c === void 0 ? [] : _c, localConnectivity = _a.localConnectivity;
357
+ var _d = this.smoothKNNDistance(knnDistances, nNeighbors, localConnectivity), sigmas = _d.sigmas, rhos = _d.rhos;
358
+ var _e = this.computeMembershipStrengths(knnIndices, knnDistances, sigmas, rhos), rows = _e.rows, cols = _e.cols, vals = _e.vals;
359
+ var size = [X.length, X.length];
360
+ if (this.useWasmMatrix && wasmBridge.isWasmAvailable()) {
361
+ var wasmMat = wasmBridge.createSparseMatrixWasm(rows, cols, vals, size[0], size[1]);
362
+ var transpose_1 = wasmBridge.sparseTransposeWasm(wasmMat);
363
+ var prodMatrix_1 = wasmBridge.sparsePairwiseMultiplyWasm(wasmMat, transpose_1);
364
+ var added = wasmBridge.sparseAddWasm(wasmMat, transpose_1);
365
+ var a_1 = wasmBridge.sparseSubtractWasm(added, prodMatrix_1);
366
+ var b_1 = wasmBridge.sparseMultiplyScalarWasm(a_1, setOpMixRatio);
367
+ var c_1 = wasmBridge.sparseMultiplyScalarWasm(prodMatrix_1, 1.0 - setOpMixRatio);
368
+ var resultWasm = wasmBridge.sparseAddWasm(b_1, c_1);
369
+ var entries = wasmBridge.wasmSparseMatrixGetAll(resultWasm);
370
+ var jsRows = entries.map(function (e) { return e.row; });
371
+ var jsCols = entries.map(function (e) { return e.col; });
372
+ var jsVals = entries.map(function (e) { return e.value; });
373
+ return new matrix.SparseMatrix(jsRows, jsCols, jsVals, size);
374
+ }
375
+ if (this.useWasmMatrix && wasmBridge.isWasmAvailable()) {
376
+ var wasmMat = wasmBridge.createSparseMatrixWasm(rows, cols, vals, size[0], size[1]);
377
+ var transpose_2 = wasmBridge.sparseTransposeWasm(wasmMat);
378
+ var prodMatrix_2 = wasmBridge.sparsePairwiseMultiplyWasm(wasmMat, transpose_2);
379
+ var added = wasmBridge.sparseAddWasm(wasmMat, transpose_2);
380
+ var a_2 = wasmBridge.sparseSubtractWasm(added, prodMatrix_2);
381
+ var b_2 = wasmBridge.sparseMultiplyScalarWasm(a_2, setOpMixRatio);
382
+ var c_2 = wasmBridge.sparseMultiplyScalarWasm(prodMatrix_2, 1.0 - setOpMixRatio);
383
+ var resultWasm = wasmBridge.sparseAddWasm(b_2, c_2);
384
+ var entries = wasmBridge.wasmSparseMatrixGetAll(resultWasm);
385
+ var jsRows = entries.map(function (e) { return e.row; });
386
+ var jsCols = entries.map(function (e) { return e.col; });
387
+ var jsVals = entries.map(function (e) { return e.value; });
388
+ return new matrix.SparseMatrix(jsRows, jsCols, jsVals, size);
389
+ }
390
+ var sparseMatrix = new matrix.SparseMatrix(rows, cols, vals, size);
391
+ var transpose = matrix.transpose(sparseMatrix);
392
+ var prodMatrix = matrix.pairwiseMultiply(sparseMatrix, transpose);
393
+ var a = matrix.subtract(matrix.add(sparseMatrix, transpose), prodMatrix);
394
+ var b = matrix.multiplyScalar(a, setOpMixRatio);
395
+ var c = matrix.multiplyScalar(prodMatrix, 1.0 - setOpMixRatio);
396
+ var result = matrix.add(b, c);
397
+ return result;
398
+ };
399
+ UMAP.prototype.categoricalSimplicialSetIntersection = function (simplicialSet, target, farDist, unknownDist) {
400
+ if (unknownDist === void 0) { unknownDist = 1.0; }
401
+ var intersection = fastIntersection(simplicialSet, target, unknownDist, farDist);
402
+ intersection = matrix.eliminateZeros(intersection);
403
+ return resetLocalConnectivity(intersection);
404
+ };
405
+ UMAP.prototype.smoothKNNDistance = function (distances, k, localConnectivity, nIter, bandwidth) {
406
+ if (localConnectivity === void 0) { localConnectivity = 1.0; }
407
+ if (nIter === void 0) { nIter = 64; }
408
+ if (bandwidth === void 0) { bandwidth = 1.0; }
409
+ var target = (Math.log(k) / Math.log(2)) * bandwidth;
410
+ var rho = utils.zeros(distances.length);
411
+ var result = utils.zeros(distances.length);
412
+ for (var i = 0; i < distances.length; i++) {
413
+ var lo = 0.0;
414
+ var hi = Infinity;
415
+ var mid = 1.0;
416
+ var ithDistances = distances[i];
417
+ var nonZeroDists = ithDistances.filter(function (d) { return d > 0.0; });
418
+ if (nonZeroDists.length >= localConnectivity) {
419
+ var index = Math.floor(localConnectivity);
420
+ var interpolation = localConnectivity - index;
421
+ if (index > 0) {
422
+ rho[i] = nonZeroDists[index - 1];
423
+ if (interpolation > SMOOTH_K_TOLERANCE) {
424
+ rho[i] +=
425
+ interpolation * (nonZeroDists[index] - nonZeroDists[index - 1]);
426
+ }
427
+ }
428
+ else {
429
+ rho[i] = interpolation * nonZeroDists[0];
430
+ }
431
+ }
432
+ else if (nonZeroDists.length > 0) {
433
+ rho[i] = utils.max(nonZeroDists);
434
+ }
435
+ for (var n = 0; n < nIter; n++) {
436
+ var psum = 0.0;
437
+ for (var j = 1; j < distances[i].length; j++) {
438
+ var d = distances[i][j] - rho[i];
439
+ if (d > 0) {
440
+ psum += Math.exp(-(d / mid));
441
+ }
442
+ else {
443
+ psum += 1.0;
444
+ }
445
+ }
446
+ if (Math.abs(psum - target) < SMOOTH_K_TOLERANCE) {
447
+ break;
448
+ }
449
+ if (psum > target) {
450
+ hi = mid;
451
+ mid = (lo + hi) / 2.0;
452
+ }
453
+ else {
454
+ lo = mid;
455
+ if (hi === Infinity) {
456
+ mid *= 2;
457
+ }
458
+ else {
459
+ mid = (lo + hi) / 2.0;
460
+ }
461
+ }
462
+ }
463
+ result[i] = mid;
464
+ if (rho[i] > 0.0) {
465
+ var meanIthDistances = utils.mean(ithDistances);
466
+ if (result[i] < MIN_K_DIST_SCALE * meanIthDistances) {
467
+ result[i] = MIN_K_DIST_SCALE * meanIthDistances;
468
+ }
469
+ }
470
+ else {
471
+ var meanDistances = utils.mean(distances.map(utils.mean));
472
+ if (result[i] < MIN_K_DIST_SCALE * meanDistances) {
473
+ result[i] = MIN_K_DIST_SCALE * meanDistances;
474
+ }
475
+ }
476
+ }
477
+ return { sigmas: result, rhos: rho };
478
+ };
479
+ UMAP.prototype.computeMembershipStrengths = function (knnIndices, knnDistances, sigmas, rhos) {
480
+ var nSamples = knnIndices.length;
481
+ var nNeighbors = knnIndices[0].length;
482
+ var rows = utils.zeros(nSamples * nNeighbors);
483
+ var cols = utils.zeros(nSamples * nNeighbors);
484
+ var vals = utils.zeros(nSamples * nNeighbors);
485
+ for (var i = 0; i < nSamples; i++) {
486
+ for (var j = 0; j < nNeighbors; j++) {
487
+ var val = 0;
488
+ if (knnIndices[i][j] === -1) {
489
+ continue;
490
+ }
491
+ if (knnIndices[i][j] === i) {
492
+ val = 0.0;
493
+ }
494
+ else if (knnDistances[i][j] - rhos[i] <= 0.0) {
495
+ val = 1.0;
496
+ }
497
+ else {
498
+ val = Math.exp(-((knnDistances[i][j] - rhos[i]) / sigmas[i]));
499
+ }
500
+ rows[i * nNeighbors + j] = i;
501
+ cols[i * nNeighbors + j] = knnIndices[i][j];
502
+ vals[i * nNeighbors + j] = val;
503
+ }
504
+ }
505
+ return { rows: rows, cols: cols, vals: vals };
506
+ };
507
+ UMAP.prototype.initializeSimplicialSetEmbedding = function () {
508
+ var _this = this;
509
+ var nEpochs = this.getNEpochs();
510
+ var nComponents = this.nComponents;
511
+ var graphValues = this.graph.getValues();
512
+ var graphMax = 0;
513
+ for (var i = 0; i < graphValues.length; i++) {
514
+ var value = graphValues[i];
515
+ if (graphMax < graphValues[i]) {
516
+ graphMax = value;
517
+ }
518
+ }
519
+ var graph = this.graph.map(function (value) {
520
+ if (value < graphMax / nEpochs) {
521
+ return 0;
522
+ }
523
+ else {
524
+ return value;
525
+ }
526
+ });
527
+ this.embedding = utils.zeros(graph.nRows).map(function () {
528
+ return utils.zeros(nComponents).map(function () {
529
+ return utils.tauRand(_this.random) * 20 + -10;
530
+ });
531
+ });
532
+ var weights = [];
533
+ var head = [];
534
+ var tail = [];
535
+ var rowColValues = graph.getAll();
536
+ for (var i = 0; i < rowColValues.length; i++) {
537
+ var entry = rowColValues[i];
538
+ if (entry.value) {
539
+ weights.push(entry.value);
540
+ tail.push(entry.row);
541
+ head.push(entry.col);
542
+ }
543
+ }
544
+ var epochsPerSample = this.makeEpochsPerSample(weights, nEpochs);
545
+ return { head: head, tail: tail, epochsPerSample: epochsPerSample };
546
+ };
547
+ UMAP.prototype.makeEpochsPerSample = function (weights, nEpochs) {
548
+ var result = utils.filled(weights.length, -1.0);
549
+ var max = utils.max(weights);
550
+ var nSamples = weights.map(function (w) { return (w / max) * nEpochs; });
551
+ nSamples.forEach(function (n, i) {
552
+ if (n > 0)
553
+ result[i] = nEpochs / nSamples[i];
554
+ });
555
+ return result;
556
+ };
557
+ UMAP.prototype.assignOptimizationStateParameters = function (state) {
558
+ Object.assign(this.optimizationState, state);
559
+ };
560
+ UMAP.prototype.prepareForOptimizationLoop = function () {
561
+ var _a = this, repulsionStrength = _a.repulsionStrength, learningRate = _a.learningRate, negativeSampleRate = _a.negativeSampleRate;
562
+ var _b = this.optimizationState, epochsPerSample = _b.epochsPerSample, headEmbedding = _b.headEmbedding, tailEmbedding = _b.tailEmbedding;
563
+ var dim = headEmbedding[0].length;
564
+ var moveOther = headEmbedding.length === tailEmbedding.length;
565
+ var epochsPerNegativeSample = epochsPerSample.map(function (e) { return e / negativeSampleRate; });
566
+ var epochOfNextNegativeSample = __spreadArray([], __read(epochsPerNegativeSample), false);
567
+ var epochOfNextSample = __spreadArray([], __read(epochsPerSample), false);
568
+ this.assignOptimizationStateParameters({
569
+ epochOfNextSample: epochOfNextSample,
570
+ epochOfNextNegativeSample: epochOfNextNegativeSample,
571
+ epochsPerNegativeSample: epochsPerNegativeSample,
572
+ moveOther: moveOther,
573
+ initialAlpha: learningRate,
574
+ alpha: learningRate,
575
+ gamma: repulsionStrength,
576
+ dim: dim,
577
+ });
578
+ };
579
+ UMAP.prototype.initializeOptimization = function () {
580
+ var headEmbedding = this.embedding;
581
+ var tailEmbedding = this.embedding;
582
+ var _a = this.optimizationState, head = _a.head, tail = _a.tail, epochsPerSample = _a.epochsPerSample;
583
+ var nEpochs = this.getNEpochs();
584
+ var nVertices = this.graph.nCols;
585
+ var _b = findABParams(this.spread, this.minDist), a = _b.a, b = _b.b;
586
+ this.assignOptimizationStateParameters({
587
+ headEmbedding: headEmbedding,
588
+ tailEmbedding: tailEmbedding,
589
+ head: head,
590
+ tail: tail,
591
+ epochsPerSample: epochsPerSample,
592
+ a: a,
593
+ b: b,
594
+ nEpochs: nEpochs,
595
+ nVertices: nVertices,
596
+ });
597
+ };
598
+ UMAP.prototype.optimizeLayoutStep = function (n) {
599
+ var optimizationState = this.optimizationState;
600
+ var head = optimizationState.head, tail = optimizationState.tail, headEmbedding = optimizationState.headEmbedding, tailEmbedding = optimizationState.tailEmbedding, epochsPerSample = optimizationState.epochsPerSample, epochOfNextSample = optimizationState.epochOfNextSample, epochOfNextNegativeSample = optimizationState.epochOfNextNegativeSample, epochsPerNegativeSample = optimizationState.epochsPerNegativeSample, moveOther = optimizationState.moveOther, initialAlpha = optimizationState.initialAlpha, alpha = optimizationState.alpha, gamma = optimizationState.gamma, a = optimizationState.a, b = optimizationState.b, dim = optimizationState.dim, nEpochs = optimizationState.nEpochs, nVertices = optimizationState.nVertices;
601
+ var clipValue = 4.0;
602
+ for (var i = 0; i < epochsPerSample.length; i++) {
603
+ if (epochOfNextSample[i] > n) {
604
+ continue;
605
+ }
606
+ var j = head[i];
607
+ var k = tail[i];
608
+ var current = headEmbedding[j];
609
+ var other = tailEmbedding[k];
610
+ var distSquared = rDist(current, other);
611
+ var gradCoeff = 0;
612
+ if (distSquared > 0) {
613
+ gradCoeff = -2.0 * a * b * Math.pow(distSquared, b - 1.0);
614
+ gradCoeff /= a * Math.pow(distSquared, b) + 1.0;
615
+ }
616
+ for (var d = 0; d < dim; d++) {
617
+ var gradD = clip(gradCoeff * (current[d] - other[d]), clipValue);
618
+ current[d] += gradD * alpha;
619
+ if (moveOther) {
620
+ other[d] += -gradD * alpha;
621
+ }
622
+ }
623
+ epochOfNextSample[i] += epochsPerSample[i];
624
+ var nNegSamples = Math.floor((n - epochOfNextNegativeSample[i]) / epochsPerNegativeSample[i]);
625
+ for (var p = 0; p < nNegSamples; p++) {
626
+ var k_1 = utils.tauRandInt(nVertices, this.random);
627
+ var other_1 = tailEmbedding[k_1];
628
+ var distSquared_1 = rDist(current, other_1);
629
+ var gradCoeff_1 = 0.0;
630
+ if (distSquared_1 > 0.0) {
631
+ gradCoeff_1 = 2.0 * gamma * b;
632
+ gradCoeff_1 /=
633
+ (0.001 + distSquared_1) * (a * Math.pow(distSquared_1, b) + 1);
634
+ }
635
+ else if (j === k_1) {
636
+ continue;
637
+ }
638
+ for (var d = 0; d < dim; d++) {
639
+ var gradD = 4.0;
640
+ if (gradCoeff_1 > 0.0) {
641
+ gradD = clip(gradCoeff_1 * (current[d] - other_1[d]), clipValue);
642
+ }
643
+ current[d] += gradD * alpha;
644
+ }
645
+ }
646
+ epochOfNextNegativeSample[i] += nNegSamples * epochsPerNegativeSample[i];
647
+ }
648
+ optimizationState.alpha = initialAlpha * (1.0 - n / nEpochs);
649
+ optimizationState.currentEpoch += 1;
650
+ return headEmbedding;
651
+ };
652
+ UMAP.prototype.optimizeLayoutAsync = function (epochCallback) {
653
+ var _this = this;
654
+ if (epochCallback === void 0) { epochCallback = function () { return true; }; }
655
+ return new Promise(function (resolve, reject) {
656
+ var step = function () { return __awaiter(_this, void 0, void 0, function () {
657
+ var _a, nEpochs, currentEpoch, epochCompleted, shouldStop, isFinished;
658
+ return __generator(this, function (_b) {
659
+ try {
660
+ _a = this.optimizationState, nEpochs = _a.nEpochs, currentEpoch = _a.currentEpoch;
661
+ this.embedding = this.optimizeLayoutStep(currentEpoch);
662
+ epochCompleted = this.optimizationState.currentEpoch;
663
+ shouldStop = epochCallback(epochCompleted) === false;
664
+ isFinished = epochCompleted === nEpochs;
665
+ if (!shouldStop && !isFinished) {
666
+ setTimeout(function () { return step(); }, 0);
667
+ }
668
+ else {
669
+ return [2, resolve(isFinished)];
670
+ }
671
+ }
672
+ catch (err) {
673
+ reject(err);
674
+ }
675
+ return [2];
676
+ });
677
+ }); };
678
+ setTimeout(function () { return step(); }, 0);
679
+ });
680
+ };
681
+ UMAP.prototype.optimizeLayout = function (epochCallback) {
682
+ if (epochCallback === void 0) { epochCallback = function () { return true; }; }
683
+ var isFinished = false;
684
+ var embedding = [];
685
+ while (!isFinished) {
686
+ var _a = this.optimizationState, nEpochs = _a.nEpochs, currentEpoch = _a.currentEpoch;
687
+ embedding = this.optimizeLayoutStep(currentEpoch);
688
+ var epochCompleted = this.optimizationState.currentEpoch;
689
+ var shouldStop = epochCallback(epochCompleted) === false;
690
+ isFinished = epochCompleted === nEpochs || shouldStop;
691
+ }
692
+ return embedding;
693
+ };
694
+ UMAP.prototype.getNEpochs = function () {
695
+ var graph = this.graph;
696
+ if (this.nEpochs > 0) {
697
+ return this.nEpochs;
698
+ }
699
+ var length = graph.nRows;
700
+ if (length <= 2500) {
701
+ return 500;
702
+ }
703
+ else if (length <= 5000) {
704
+ return 400;
705
+ }
706
+ else if (length <= 7500) {
707
+ return 300;
708
+ }
709
+ else {
710
+ return 200;
711
+ }
712
+ };
713
+ return UMAP;
714
+ }());
715
+ exports.UMAP = UMAP;
716
+ function euclidean(x, y) {
717
+ var result = 0;
718
+ for (var i = 0; i < x.length; i++) {
719
+ result += Math.pow((x[i] - y[i]), 2);
720
+ }
721
+ return Math.sqrt(result);
722
+ }
723
+ function cosine(x, y) {
724
+ var result = 0.0;
725
+ var normX = 0.0;
726
+ var normY = 0.0;
727
+ for (var i = 0; i < x.length; i++) {
728
+ result += x[i] * y[i];
729
+ normX += Math.pow(x[i], 2);
730
+ normY += Math.pow(y[i], 2);
731
+ }
732
+ if (normX === 0 && normY === 0) {
733
+ return 0;
734
+ }
735
+ else if (normX === 0 || normY === 0) {
736
+ return 1.0;
737
+ }
738
+ else {
739
+ return 1.0 - result / Math.sqrt(normX * normY);
740
+ }
741
+ }
742
+ var OptimizationState = (function () {
743
+ function OptimizationState() {
744
+ this.currentEpoch = 0;
745
+ this.headEmbedding = [];
746
+ this.tailEmbedding = [];
747
+ this.head = [];
748
+ this.tail = [];
749
+ this.epochsPerSample = [];
750
+ this.epochOfNextSample = [];
751
+ this.epochOfNextNegativeSample = [];
752
+ this.epochsPerNegativeSample = [];
753
+ this.moveOther = true;
754
+ this.initialAlpha = 1.0;
755
+ this.alpha = 1.0;
756
+ this.gamma = 1.0;
757
+ this.a = 1.5769434603113077;
758
+ this.b = 0.8950608779109733;
759
+ this.dim = 2;
760
+ this.nEpochs = 500;
761
+ this.nVertices = 0;
762
+ }
763
+ return OptimizationState;
764
+ }());
765
+ function clip(x, clipValue) {
766
+ if (x > clipValue)
767
+ return clipValue;
768
+ else if (x < -clipValue)
769
+ return -clipValue;
770
+ else
771
+ return x;
772
+ }
773
+ function rDist(x, y) {
774
+ var result = 0.0;
775
+ for (var i = 0; i < x.length; i++) {
776
+ result += Math.pow(x[i] - y[i], 2);
777
+ }
778
+ return result;
779
+ }
780
+ function findABParams(spread, minDist) {
781
+ var curve = function (_a) {
782
+ var _b = __read(_a, 2), a = _b[0], b = _b[1];
783
+ return function (x) {
784
+ return 1.0 / (1.0 + a * Math.pow(x, (2 * b)));
785
+ };
786
+ };
787
+ var xv = utils
788
+ .linear(0, spread * 3, 300)
789
+ .map(function (val) { return (val < minDist ? 1.0 : val); });
790
+ var yv = utils.zeros(xv.length).map(function (val, index) {
791
+ var gte = xv[index] >= minDist;
792
+ return gte ? Math.exp(-(xv[index] - minDist) / spread) : val;
793
+ });
794
+ var initialValues = [0.5, 0.5];
795
+ var data = { x: xv, y: yv };
796
+ var options = {
797
+ damping: 1.5,
798
+ initialValues: initialValues,
799
+ gradientDifference: 10e-2,
800
+ maxIterations: 100,
801
+ errorTolerance: 10e-3,
802
+ };
803
+ var parameterValues = (0, ml_levenberg_marquardt_1.default)(data, curve, options).parameterValues;
804
+ var _a = __read(parameterValues, 2), a = _a[0], b = _a[1];
805
+ return { a: a, b: b };
806
+ }
807
+ function fastIntersection(graph, target, unknownDist, farDist) {
808
+ if (unknownDist === void 0) { unknownDist = 1.0; }
809
+ if (farDist === void 0) { farDist = 5.0; }
810
+ return graph.map(function (value, row, col) {
811
+ if (target[row] === -1 || target[col] === -1) {
812
+ return value * Math.exp(-unknownDist);
813
+ }
814
+ else if (target[row] !== target[col]) {
815
+ return value * Math.exp(-farDist);
816
+ }
817
+ else {
818
+ return value;
819
+ }
820
+ });
821
+ }
822
+ function resetLocalConnectivity(simplicialSet) {
823
+ simplicialSet = matrix.normalize(simplicialSet, "max");
824
+ var transpose = matrix.transpose(simplicialSet);
825
+ var prodMatrix = matrix.pairwiseMultiply(transpose, simplicialSet);
826
+ simplicialSet = matrix.add(simplicialSet, matrix.subtract(transpose, prodMatrix));
827
+ return matrix.eliminateZeros(simplicialSet);
828
+ }
829
+ function initTransform(indices, weights, embedding) {
830
+ var result = utils
831
+ .zeros(indices.length)
832
+ .map(function (z) { return utils.zeros(embedding[0].length); });
833
+ for (var i = 0; i < indices.length; i++) {
834
+ for (var j = 0; j < indices[0].length; j++) {
835
+ for (var d = 0; d < embedding[0].length; d++) {
836
+ var a = indices[i][j];
837
+ result[i][d] += weights[i][j] * embedding[a][d];
838
+ }
839
+ }
840
+ }
841
+ return result;
842
+ }