@elarsaks/umap-wasm 0.1.2 → 0.1.4

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 (52) hide show
  1. package/dist/{src/heap.d.ts → heap.d.ts} +1 -1
  2. package/dist/heap.js +184 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +2 -0
  5. package/dist/lib.d.ts +2 -0
  6. package/dist/lib.js +2 -0
  7. package/dist/matrix.js +257 -0
  8. package/dist/{src/nn_descent.d.ts → nn_descent.d.ts} +4 -4
  9. package/dist/nn_descent.js +127 -0
  10. package/dist/{src/tree.d.ts → tree.d.ts} +2 -2
  11. package/dist/tree.js +228 -0
  12. package/dist/{src/umap.d.ts → umap.d.ts} +1 -1
  13. package/dist/umap.js +700 -0
  14. package/dist/{src/utils.d.ts → utils.d.ts} +1 -1
  15. package/dist/utils.js +98 -0
  16. package/dist/wasmBridge.js +188 -0
  17. package/lib/umap-js.js +6842 -7490
  18. package/lib/umap-js.min.js +1 -1
  19. package/package.json +64 -63
  20. package/dist/src/heap.js +0 -226
  21. package/dist/src/index.d.ts +0 -2
  22. package/dist/src/index.js +0 -8
  23. package/dist/src/lib.d.ts +0 -1
  24. package/dist/src/lib.js +0 -5
  25. package/dist/src/matrix.js +0 -360
  26. package/dist/src/nn_descent.js +0 -204
  27. package/dist/src/tree.js +0 -320
  28. package/dist/src/umap.js +0 -842
  29. package/dist/src/utils.js +0 -137
  30. package/dist/src/wasmBridge.js +0 -290
  31. package/dist/test/matrix.test.d.ts +0 -1
  32. package/dist/test/matrix.test.js +0 -169
  33. package/dist/test/nn_descent.test.d.ts +0 -1
  34. package/dist/test/nn_descent.test.js +0 -58
  35. package/dist/test/smoke.playwright.test.d.ts +0 -1
  36. package/dist/test/smoke.playwright.test.js +0 -98
  37. package/dist/test/test_data.d.ts +0 -13
  38. package/dist/test/test_data.js +0 -1054
  39. package/dist/test/tree.test.d.ts +0 -1
  40. package/dist/test/tree.test.js +0 -60
  41. package/dist/test/umap.test.d.ts +0 -1
  42. package/dist/test/umap.test.js +0 -293
  43. package/dist/test/utils.test.d.ts +0 -1
  44. package/dist/test/utils.test.js +0 -128
  45. package/dist/test/wasmDistance.test.d.ts +0 -1
  46. package/dist/test/wasmDistance.test.js +0 -124
  47. package/dist/test/wasmMatrix.test.d.ts +0 -1
  48. package/dist/test/wasmMatrix.test.js +0 -389
  49. package/dist/test/wasmTree.test.d.ts +0 -1
  50. package/dist/test/wasmTree.test.js +0 -212
  51. /package/dist/{src/matrix.d.ts → matrix.d.ts} +0 -0
  52. /package/dist/{src/wasmBridge.d.ts → wasmBridge.d.ts} +0 -0
@@ -1,4 +1,4 @@
1
- import { RandomFn } from './umap';
1
+ import { RandomFn } from './umap.js';
2
2
  export type Heap = number[][][];
3
3
  export declare function makeHeap(nPoints: number, size: number): Heap;
4
4
  export declare function rejectionSample(nSamples: number, poolSize: number, random: RandomFn): number[];
package/dist/heap.js ADDED
@@ -0,0 +1,184 @@
1
+ import * as utils from './utils.js';
2
+ export function makeHeap(nPoints, size) {
3
+ const makeArrays = (fillValue) => {
4
+ return utils.empty(nPoints).map(() => {
5
+ return utils.filled(size, fillValue);
6
+ });
7
+ };
8
+ const heap = [];
9
+ heap.push(makeArrays(-1));
10
+ heap.push(makeArrays(Infinity));
11
+ heap.push(makeArrays(0));
12
+ return heap;
13
+ }
14
+ export function rejectionSample(nSamples, poolSize, random) {
15
+ const result = utils.zeros(nSamples);
16
+ for (let i = 0; i < nSamples; i++) {
17
+ let rejectSample = true;
18
+ let j = 0;
19
+ while (rejectSample) {
20
+ j = utils.tauRandInt(poolSize, random);
21
+ let broken = false;
22
+ for (let k = 0; k < i; k++) {
23
+ if (j === result[k]) {
24
+ broken = true;
25
+ break;
26
+ }
27
+ }
28
+ if (!broken)
29
+ rejectSample = false;
30
+ }
31
+ result[i] = j;
32
+ }
33
+ return result;
34
+ }
35
+ export function heapPush(heap, row, weight, index, flag) {
36
+ row = Math.floor(row);
37
+ const indices = heap[0][row];
38
+ const weights = heap[1][row];
39
+ const isNew = heap[2][row];
40
+ if (weight >= weights[0]) {
41
+ return 0;
42
+ }
43
+ for (let i = 0; i < indices.length; i++) {
44
+ if (index === indices[i]) {
45
+ return 0;
46
+ }
47
+ }
48
+ return uncheckedHeapPush(heap, row, weight, index, flag);
49
+ }
50
+ export function uncheckedHeapPush(heap, row, weight, index, flag) {
51
+ const indices = heap[0][row];
52
+ const weights = heap[1][row];
53
+ const isNew = heap[2][row];
54
+ if (weight >= weights[0]) {
55
+ return 0;
56
+ }
57
+ weights[0] = weight;
58
+ indices[0] = index;
59
+ isNew[0] = flag;
60
+ let i = 0;
61
+ let iSwap = 0;
62
+ while (true) {
63
+ const ic1 = 2 * i + 1;
64
+ const ic2 = ic1 + 1;
65
+ const heapShape2 = heap[0][0].length;
66
+ if (ic1 >= heapShape2) {
67
+ break;
68
+ }
69
+ else if (ic2 >= heapShape2) {
70
+ if (weights[ic1] > weight) {
71
+ iSwap = ic1;
72
+ }
73
+ else {
74
+ break;
75
+ }
76
+ }
77
+ else if (weights[ic1] >= weights[ic2]) {
78
+ if (weight < weights[ic1]) {
79
+ iSwap = ic1;
80
+ }
81
+ else {
82
+ break;
83
+ }
84
+ }
85
+ else {
86
+ if (weight < weights[ic2]) {
87
+ iSwap = ic2;
88
+ }
89
+ else {
90
+ break;
91
+ }
92
+ }
93
+ weights[i] = weights[iSwap];
94
+ indices[i] = indices[iSwap];
95
+ isNew[i] = isNew[iSwap];
96
+ i = iSwap;
97
+ }
98
+ weights[i] = weight;
99
+ indices[i] = index;
100
+ isNew[i] = flag;
101
+ return 1;
102
+ }
103
+ export function buildCandidates(currentGraph, nVertices, nNeighbors, maxCandidates, random) {
104
+ const candidateNeighbors = makeHeap(nVertices, maxCandidates);
105
+ for (let i = 0; i < nVertices; i++) {
106
+ for (let j = 0; j < nNeighbors; j++) {
107
+ if (currentGraph[0][i][j] < 0) {
108
+ continue;
109
+ }
110
+ const idx = currentGraph[0][i][j];
111
+ const isn = currentGraph[2][i][j];
112
+ const d = utils.tauRand(random);
113
+ heapPush(candidateNeighbors, i, d, idx, isn);
114
+ heapPush(candidateNeighbors, idx, d, i, isn);
115
+ currentGraph[2][i][j] = 0;
116
+ }
117
+ }
118
+ return candidateNeighbors;
119
+ }
120
+ export function deheapSort(heap) {
121
+ const indices = heap[0];
122
+ const weights = heap[1];
123
+ for (let i = 0; i < indices.length; i++) {
124
+ const indHeap = indices[i];
125
+ const distHeap = weights[i];
126
+ for (let j = 0; j < indHeap.length - 1; j++) {
127
+ const indHeapIndex = indHeap.length - j - 1;
128
+ const distHeapIndex = distHeap.length - j - 1;
129
+ const temp1 = indHeap[0];
130
+ indHeap[0] = indHeap[indHeapIndex];
131
+ indHeap[indHeapIndex] = temp1;
132
+ const temp2 = distHeap[0];
133
+ distHeap[0] = distHeap[distHeapIndex];
134
+ distHeap[distHeapIndex] = temp2;
135
+ siftDown(distHeap, indHeap, distHeapIndex, 0);
136
+ }
137
+ }
138
+ return { indices, weights };
139
+ }
140
+ function siftDown(heap1, heap2, ceiling, elt) {
141
+ while (elt * 2 + 1 < ceiling) {
142
+ const leftChild = elt * 2 + 1;
143
+ const rightChild = leftChild + 1;
144
+ let swap = elt;
145
+ if (heap1[swap] < heap1[leftChild]) {
146
+ swap = leftChild;
147
+ }
148
+ if (rightChild < ceiling && heap1[swap] < heap1[rightChild]) {
149
+ swap = rightChild;
150
+ }
151
+ if (swap === elt) {
152
+ break;
153
+ }
154
+ else {
155
+ const temp1 = heap1[elt];
156
+ heap1[elt] = heap1[swap];
157
+ heap1[swap] = temp1;
158
+ const temp2 = heap2[elt];
159
+ heap2[elt] = heap2[swap];
160
+ heap2[swap] = temp2;
161
+ elt = swap;
162
+ }
163
+ }
164
+ }
165
+ export function smallestFlagged(heap, row) {
166
+ const ind = heap[0][row];
167
+ const dist = heap[1][row];
168
+ const flag = heap[2][row];
169
+ let minDist = Infinity;
170
+ let resultIndex = -1;
171
+ for (let i = 0; i > ind.length; i++) {
172
+ if (flag[i] === 1 && dist[i] < minDist) {
173
+ minDist = dist[i];
174
+ resultIndex = i;
175
+ }
176
+ }
177
+ if (resultIndex >= 0) {
178
+ flag[resultIndex] = 0;
179
+ return Math.floor(ind[resultIndex]);
180
+ }
181
+ else {
182
+ return -1;
183
+ }
184
+ }
@@ -0,0 +1,2 @@
1
+ export { UMAP, UMAPParameters } from './umap.js';
2
+ export { initWasm, isWasmAvailable } from './wasmBridge.js';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { UMAP } from './umap.js';
2
+ export { initWasm, isWasmAvailable } from './wasmBridge.js';
package/dist/lib.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { UMAP } from './umap.js';
2
+ export { initWasm, isWasmAvailable } from './wasmBridge.js';
package/dist/lib.js ADDED
@@ -0,0 +1,2 @@
1
+ export { UMAP } from './umap.js';
2
+ export { initWasm, isWasmAvailable } from './wasmBridge.js';
package/dist/matrix.js ADDED
@@ -0,0 +1,257 @@
1
+ import * as utils from './utils.js';
2
+ export class SparseMatrix {
3
+ constructor(rows, cols, values, dims) {
4
+ this.entries = new Map();
5
+ this.nRows = 0;
6
+ this.nCols = 0;
7
+ if (rows.length !== cols.length || rows.length !== values.length) {
8
+ throw new Error('rows, cols and values arrays must all have the same length');
9
+ }
10
+ this.nRows = dims[0];
11
+ this.nCols = dims[1];
12
+ for (let i = 0; i < values.length; i++) {
13
+ const row = rows[i];
14
+ const col = cols[i];
15
+ this.checkDims(row, col);
16
+ const key = this.makeKey(row, col);
17
+ this.entries.set(key, { value: values[i], row, col });
18
+ }
19
+ }
20
+ makeKey(row, col) {
21
+ return `${row}:${col}`;
22
+ }
23
+ checkDims(row, col) {
24
+ const withinBounds = row < this.nRows && col < this.nCols;
25
+ if (!withinBounds) {
26
+ throw new Error('row and/or col specified outside of matrix dimensions');
27
+ }
28
+ }
29
+ set(row, col, value) {
30
+ this.checkDims(row, col);
31
+ const key = this.makeKey(row, col);
32
+ if (!this.entries.has(key)) {
33
+ this.entries.set(key, { value, row, col });
34
+ }
35
+ else {
36
+ this.entries.get(key).value = value;
37
+ }
38
+ }
39
+ get(row, col, defaultValue = 0) {
40
+ this.checkDims(row, col);
41
+ const key = this.makeKey(row, col);
42
+ if (this.entries.has(key)) {
43
+ return this.entries.get(key).value;
44
+ }
45
+ else {
46
+ return defaultValue;
47
+ }
48
+ }
49
+ getAll(ordered = true) {
50
+ const rowColValues = [];
51
+ this.entries.forEach(value => {
52
+ rowColValues.push(value);
53
+ });
54
+ if (ordered) {
55
+ rowColValues.sort((a, b) => {
56
+ if (a.row === b.row) {
57
+ return a.col - b.col;
58
+ }
59
+ else {
60
+ return a.row - b.row;
61
+ }
62
+ });
63
+ }
64
+ return rowColValues;
65
+ }
66
+ getDims() {
67
+ return [this.nRows, this.nCols];
68
+ }
69
+ getRows() {
70
+ return Array.from(this.entries, ([key, value]) => value.row);
71
+ }
72
+ getCols() {
73
+ return Array.from(this.entries, ([key, value]) => value.col);
74
+ }
75
+ getValues() {
76
+ return Array.from(this.entries, ([key, value]) => value.value);
77
+ }
78
+ forEach(fn) {
79
+ this.entries.forEach(value => fn(value.value, value.row, value.col));
80
+ }
81
+ map(fn) {
82
+ let vals = [];
83
+ this.entries.forEach(value => {
84
+ vals.push(fn(value.value, value.row, value.col));
85
+ });
86
+ const dims = [this.nRows, this.nCols];
87
+ return new SparseMatrix(this.getRows(), this.getCols(), vals, dims);
88
+ }
89
+ toArray() {
90
+ const rows = utils.empty(this.nRows);
91
+ const output = rows.map(() => {
92
+ return utils.zeros(this.nCols);
93
+ });
94
+ this.entries.forEach(value => {
95
+ output[value.row][value.col] = value.value;
96
+ });
97
+ return output;
98
+ }
99
+ }
100
+ export function transpose(matrix) {
101
+ const cols = [];
102
+ const rows = [];
103
+ const vals = [];
104
+ matrix.forEach((value, row, col) => {
105
+ cols.push(row);
106
+ rows.push(col);
107
+ vals.push(value);
108
+ });
109
+ const dims = [matrix.nCols, matrix.nRows];
110
+ return new SparseMatrix(rows, cols, vals, dims);
111
+ }
112
+ export function identity(size) {
113
+ const [rows] = size;
114
+ const matrix = new SparseMatrix([], [], [], size);
115
+ for (let i = 0; i < rows; i++) {
116
+ matrix.set(i, i, 1);
117
+ }
118
+ return matrix;
119
+ }
120
+ export function pairwiseMultiply(a, b) {
121
+ return elementWise(a, b, (x, y) => x * y);
122
+ }
123
+ export function add(a, b) {
124
+ return elementWise(a, b, (x, y) => x + y);
125
+ }
126
+ export function subtract(a, b) {
127
+ return elementWise(a, b, (x, y) => x - y);
128
+ }
129
+ export function maximum(a, b) {
130
+ return elementWise(a, b, (x, y) => (x > y ? x : y));
131
+ }
132
+ export function multiplyScalar(a, scalar) {
133
+ return a.map((value) => {
134
+ return value * scalar;
135
+ });
136
+ }
137
+ export function eliminateZeros(m) {
138
+ const zeroIndices = new Set();
139
+ const values = m.getValues();
140
+ const rows = m.getRows();
141
+ const cols = m.getCols();
142
+ for (let i = 0; i < values.length; i++) {
143
+ if (values[i] === 0) {
144
+ zeroIndices.add(i);
145
+ }
146
+ }
147
+ const removeByZeroIndex = (_, index) => !zeroIndices.has(index);
148
+ const nextValues = values.filter(removeByZeroIndex);
149
+ const nextRows = rows.filter(removeByZeroIndex);
150
+ const nextCols = cols.filter(removeByZeroIndex);
151
+ return new SparseMatrix(nextRows, nextCols, nextValues, m.getDims());
152
+ }
153
+ export function normalize(m, normType = "l2") {
154
+ const normFn = normFns[normType];
155
+ const colsByRow = new Map();
156
+ m.forEach((_, row, col) => {
157
+ const cols = colsByRow.get(row) || [];
158
+ cols.push(col);
159
+ colsByRow.set(row, cols);
160
+ });
161
+ const nextMatrix = new SparseMatrix([], [], [], m.getDims());
162
+ for (let row of colsByRow.keys()) {
163
+ const cols = colsByRow.get(row).sort();
164
+ const vals = cols.map(col => m.get(row, col));
165
+ const norm = normFn(vals);
166
+ for (let i = 0; i < norm.length; i++) {
167
+ nextMatrix.set(row, cols[i], norm[i]);
168
+ }
169
+ }
170
+ return nextMatrix;
171
+ }
172
+ const normFns = {
173
+ ["max"]: (xs) => {
174
+ let max = -Infinity;
175
+ for (let i = 0; i < xs.length; i++) {
176
+ max = xs[i] > max ? xs[i] : max;
177
+ }
178
+ return xs.map(x => x / max);
179
+ },
180
+ ["l1"]: (xs) => {
181
+ let sum = 0;
182
+ for (let i = 0; i < xs.length; i++) {
183
+ sum += xs[i];
184
+ }
185
+ return xs.map(x => x / sum);
186
+ },
187
+ ["l2"]: (xs) => {
188
+ let sum = 0;
189
+ for (let i = 0; i < xs.length; i++) {
190
+ sum += xs[i] ** 2;
191
+ }
192
+ return xs.map(x => Math.sqrt(x ** 2 / sum));
193
+ },
194
+ };
195
+ function elementWise(a, b, op) {
196
+ const visited = new Set();
197
+ const rows = [];
198
+ const cols = [];
199
+ const vals = [];
200
+ const operate = (row, col) => {
201
+ rows.push(row);
202
+ cols.push(col);
203
+ const nextValue = op(a.get(row, col), b.get(row, col));
204
+ vals.push(nextValue);
205
+ };
206
+ const valuesA = a.getValues();
207
+ const rowsA = a.getRows();
208
+ const colsA = a.getCols();
209
+ for (let i = 0; i < valuesA.length; i++) {
210
+ const row = rowsA[i];
211
+ const col = colsA[i];
212
+ const key = `${row}:${col}`;
213
+ visited.add(key);
214
+ operate(row, col);
215
+ }
216
+ const valuesB = b.getValues();
217
+ const rowsB = b.getRows();
218
+ const colsB = b.getCols();
219
+ for (let i = 0; i < valuesB.length; i++) {
220
+ const row = rowsB[i];
221
+ const col = colsB[i];
222
+ const key = `${row}:${col}`;
223
+ if (visited.has(key))
224
+ continue;
225
+ operate(row, col);
226
+ }
227
+ const dims = [a.nRows, a.nCols];
228
+ return new SparseMatrix(rows, cols, vals, dims);
229
+ }
230
+ export function getCSR(x) {
231
+ const entries = [];
232
+ x.forEach((value, row, col) => {
233
+ entries.push({ value, row, col });
234
+ });
235
+ entries.sort((a, b) => {
236
+ if (a.row === b.row) {
237
+ return a.col - b.col;
238
+ }
239
+ else {
240
+ return a.row - b.row;
241
+ }
242
+ });
243
+ const indices = [];
244
+ const values = [];
245
+ const indptr = [];
246
+ let currentRow = -1;
247
+ for (let i = 0; i < entries.length; i++) {
248
+ const { row, col, value } = entries[i];
249
+ if (row !== currentRow) {
250
+ currentRow = row;
251
+ indptr.push(i);
252
+ }
253
+ indices.push(col);
254
+ values.push(value);
255
+ }
256
+ return { indices, values, indptr };
257
+ }
@@ -1,7 +1,7 @@
1
- import * as heap from './heap';
2
- import * as matrix from './matrix';
3
- import * as tree from './tree';
4
- import { RandomFn, Vectors, DistanceFn } from './umap';
1
+ import * as heap from './heap.js';
2
+ import * as matrix from './matrix.js';
3
+ import * as tree from './tree.js';
4
+ import { RandomFn, Vectors, DistanceFn } from './umap.js';
5
5
  export declare function makeNNDescent(distanceFn: DistanceFn, random: RandomFn): (data: Vectors, leafArray: Vectors, nNeighbors: number, nIters?: number, maxCandidates?: number, delta?: number, rho?: number, rpTreeInit?: boolean) => {
6
6
  indices: number[][];
7
7
  weights: number[][];
@@ -0,0 +1,127 @@
1
+ import * as heap from './heap.js';
2
+ import * as matrix from './matrix.js';
3
+ import * as tree from './tree.js';
4
+ import * as utils from './utils.js';
5
+ export function makeNNDescent(distanceFn, random) {
6
+ return function nNDescent(data, leafArray, nNeighbors, nIters = 10, maxCandidates = 50, delta = 0.001, rho = 0.5, rpTreeInit = true) {
7
+ const nVertices = data.length;
8
+ const currentGraph = heap.makeHeap(data.length, nNeighbors);
9
+ for (let i = 0; i < data.length; i++) {
10
+ const indices = heap.rejectionSample(nNeighbors, data.length, random);
11
+ for (let j = 0; j < indices.length; j++) {
12
+ const d = distanceFn(data[i], data[indices[j]]);
13
+ heap.heapPush(currentGraph, i, d, indices[j], 1);
14
+ heap.heapPush(currentGraph, indices[j], d, i, 1);
15
+ }
16
+ }
17
+ if (rpTreeInit) {
18
+ for (let n = 0; n < leafArray.length; n++) {
19
+ for (let i = 0; i < leafArray[n].length; i++) {
20
+ if (leafArray[n][i] < 0) {
21
+ break;
22
+ }
23
+ for (let j = i + 1; j < leafArray[n].length; j++) {
24
+ if (leafArray[n][j] < 0) {
25
+ break;
26
+ }
27
+ const d = distanceFn(data[leafArray[n][i]], data[leafArray[n][j]]);
28
+ heap.heapPush(currentGraph, leafArray[n][i], d, leafArray[n][j], 1);
29
+ heap.heapPush(currentGraph, leafArray[n][j], d, leafArray[n][i], 1);
30
+ }
31
+ }
32
+ }
33
+ }
34
+ for (let n = 0; n < nIters; n++) {
35
+ const candidateNeighbors = heap.buildCandidates(currentGraph, nVertices, nNeighbors, maxCandidates, random);
36
+ let c = 0;
37
+ for (let i = 0; i < nVertices; i++) {
38
+ for (let j = 0; j < maxCandidates; j++) {
39
+ let p = Math.floor(candidateNeighbors[0][i][j]);
40
+ if (p < 0 || utils.tauRand(random) < rho) {
41
+ continue;
42
+ }
43
+ for (let k = 0; k < maxCandidates; k++) {
44
+ const q = Math.floor(candidateNeighbors[0][i][k]);
45
+ const cj = candidateNeighbors[2][i][j];
46
+ const ck = candidateNeighbors[2][i][k];
47
+ if (q < 0 || (!cj && !ck)) {
48
+ continue;
49
+ }
50
+ const d = distanceFn(data[p], data[q]);
51
+ c += heap.heapPush(currentGraph, p, d, q, 1);
52
+ c += heap.heapPush(currentGraph, q, d, p, 1);
53
+ }
54
+ }
55
+ }
56
+ if (c <= delta * nNeighbors * data.length) {
57
+ break;
58
+ }
59
+ }
60
+ const sorted = heap.deheapSort(currentGraph);
61
+ return sorted;
62
+ };
63
+ }
64
+ export function makeInitializations(distanceFn) {
65
+ function initFromRandom(nNeighbors, data, queryPoints, _heap, random) {
66
+ for (let i = 0; i < queryPoints.length; i++) {
67
+ const indices = utils.rejectionSample(nNeighbors, data.length, random);
68
+ for (let j = 0; j < indices.length; j++) {
69
+ if (indices[j] < 0) {
70
+ continue;
71
+ }
72
+ const d = distanceFn(data[indices[j]], queryPoints[i]);
73
+ heap.heapPush(_heap, i, d, indices[j], 1);
74
+ }
75
+ }
76
+ }
77
+ function initFromTree(_tree, data, queryPoints, _heap, random) {
78
+ for (let i = 0; i < queryPoints.length; i++) {
79
+ const indices = tree.searchFlatTree(queryPoints[i], _tree, random);
80
+ for (let j = 0; j < indices.length; j++) {
81
+ if (indices[j] < 0) {
82
+ return;
83
+ }
84
+ const d = distanceFn(data[indices[j]], queryPoints[i]);
85
+ heap.heapPush(_heap, i, d, indices[j], 1);
86
+ }
87
+ }
88
+ return;
89
+ }
90
+ return { initFromRandom, initFromTree };
91
+ }
92
+ export function makeInitializedNNSearch(distanceFn) {
93
+ return function nnSearchFn(data, graph, initialization, queryPoints) {
94
+ const { indices, indptr } = matrix.getCSR(graph);
95
+ for (let i = 0; i < queryPoints.length; i++) {
96
+ const tried = new Set(initialization[0][i]);
97
+ while (true) {
98
+ const vertex = heap.smallestFlagged(initialization, i);
99
+ if (vertex === -1) {
100
+ break;
101
+ }
102
+ const candidates = indices.slice(indptr[vertex], indptr[vertex + 1]);
103
+ for (const candidate of candidates) {
104
+ if (candidate === vertex ||
105
+ candidate === -1 ||
106
+ tried.has(candidate)) {
107
+ continue;
108
+ }
109
+ const d = distanceFn(data[candidate], queryPoints[i]);
110
+ heap.uncheckedHeapPush(initialization, i, d, candidate, 1);
111
+ tried.add(candidate);
112
+ }
113
+ }
114
+ }
115
+ return initialization;
116
+ };
117
+ }
118
+ export function initializeSearch(forest, data, queryPoints, nNeighbors, initFromRandom, initFromTree, random) {
119
+ const results = heap.makeHeap(queryPoints.length, nNeighbors);
120
+ initFromRandom(nNeighbors, data, queryPoints, results, random);
121
+ if (forest) {
122
+ for (let tree of forest) {
123
+ initFromTree(tree, data, queryPoints, results, random);
124
+ }
125
+ }
126
+ return results;
127
+ }
@@ -1,5 +1,5 @@
1
- import { RandomFn, Vector, Vectors } from './umap';
2
- import { WasmFlatTree } from './wasmBridge';
1
+ import { RandomFn, Vector, Vectors } from './umap.js';
2
+ import { WasmFlatTree } from './wasmBridge.js';
3
3
  export declare class FlatTree {
4
4
  hyperplanes: number[][];
5
5
  offsets: number[];