@graphty/algorithms 1.7.3 → 1.8.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.
- package/dist/algorithms.d.ts +2 -37
- package/dist/algorithms.js +736 -223
- package/dist/algorithms.js.map +1 -1
- package/dist/algorithms.standalone.js +24524 -0
- package/dist/algorithms.standalone.js.map +1 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts +16 -11
- package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +17 -0
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/core/graph.d.ts +10 -0
- package/dist/src/core/graph.d.ts.map +1 -1
- package/dist/src/core/graph.js +31 -2
- package/dist/src/core/graph.js.map +1 -1
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexed/accelerator.d.ts +161 -0
- package/dist/src/indexed/accelerator.d.ts.map +1 -0
- package/dist/src/indexed/accelerator.js +60 -0
- package/dist/src/indexed/accelerator.js.map +1 -0
- package/dist/src/indexed/bfs.d.ts +28 -0
- package/dist/src/indexed/bfs.d.ts.map +1 -0
- package/dist/src/indexed/bfs.js +39 -0
- package/dist/src/indexed/bfs.js.map +1 -0
- package/dist/src/indexed/common-neighbors.d.ts +17 -0
- package/dist/src/indexed/common-neighbors.d.ts.map +1 -0
- package/dist/src/indexed/common-neighbors.js +41 -0
- package/dist/src/indexed/common-neighbors.js.map +1 -0
- package/dist/src/indexed/components.d.ts +28 -0
- package/dist/src/indexed/components.d.ts.map +1 -0
- package/dist/src/indexed/components.js +58 -0
- package/dist/src/indexed/components.js.map +1 -0
- package/dist/src/indexed/dijkstra.d.ts +63 -0
- package/dist/src/indexed/dijkstra.d.ts.map +1 -0
- package/dist/src/indexed/dijkstra.js +98 -0
- package/dist/src/indexed/dijkstra.js.map +1 -0
- package/dist/src/indexed/index.d.ts +22 -0
- package/dist/src/indexed/index.d.ts.map +1 -0
- package/dist/src/indexed/index.js +22 -0
- package/dist/src/indexed/index.js.map +1 -0
- package/dist/src/indexed/mst.d.ts +26 -0
- package/dist/src/indexed/mst.d.ts.map +1 -0
- package/dist/src/indexed/mst.js +48 -0
- package/dist/src/indexed/mst.js.map +1 -0
- package/dist/src/indexed/pagerank.d.ts +30 -0
- package/dist/src/indexed/pagerank.d.ts.map +1 -0
- package/dist/src/indexed/pagerank.js +50 -0
- package/dist/src/indexed/pagerank.js.map +1 -0
- package/dist/src/indexed/structures/arc-source.d.ts +13 -0
- package/dist/src/indexed/structures/arc-source.d.ts.map +1 -0
- package/dist/src/indexed/structures/arc-source.js +25 -0
- package/dist/src/indexed/structures/arc-source.js.map +1 -0
- package/dist/src/indexed/structures/index.d.ts +9 -0
- package/dist/src/indexed/structures/index.d.ts.map +1 -0
- package/dist/src/indexed/structures/index.js +9 -0
- package/dist/src/indexed/structures/index.js.map +1 -0
- package/dist/src/indexed/structures/min-heap.d.ts +44 -0
- package/dist/src/indexed/structures/min-heap.d.ts.map +1 -0
- package/dist/src/indexed/structures/min-heap.js +112 -0
- package/dist/src/indexed/structures/min-heap.js.map +1 -0
- package/dist/src/indexed/structures/union-find.d.ts +39 -0
- package/dist/src/indexed/structures/union-find.d.ts.map +1 -0
- package/dist/src/indexed/structures/union-find.js +70 -0
- package/dist/src/indexed/structures/union-find.js.map +1 -0
- package/dist/src/indexed/to-snapshot.d.ts +38 -0
- package/dist/src/indexed/to-snapshot.d.ts.map +1 -0
- package/dist/src/indexed/to-snapshot.js +58 -0
- package/dist/src/indexed/to-snapshot.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -3
- package/src/algorithms/centrality/betweenness.ts +36 -11
- package/src/core/graph.ts +35 -2
- package/src/index.ts +46 -0
- package/src/indexed/accelerator.ts +225 -0
- package/src/indexed/bfs.ts +57 -0
- package/src/indexed/common-neighbors.ts +46 -0
- package/src/indexed/components.ts +78 -0
- package/src/indexed/dijkstra.ts +134 -0
- package/src/indexed/index.ts +28 -0
- package/src/indexed/mst.ts +62 -0
- package/src/indexed/pagerank.ts +73 -0
- package/src/indexed/structures/arc-source.ts +25 -0
- package/src/indexed/structures/index.ts +9 -0
- package/src/indexed/structures/min-heap.ts +122 -0
- package/src/indexed/structures/union-find.ts +74 -0
- package/src/indexed/to-snapshot.ts +78 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The source node of an arc, by binary search on `rowPtr`. `GraphSnapshot` exposes `arcSource(a)`
|
|
3
|
+
* (`graph-format/src/snapshot/graph-snapshot.ts:544`), but an `AdjacencyView` -- which is what the
|
|
4
|
+
* Port 1 and Port 2 signatures take, so that `reverse()` works as an input for free -- does not,
|
|
5
|
+
* so the predecessor walk carries its own.
|
|
6
|
+
* @param rowPtr - The view's nodeCount + 1 row offsets
|
|
7
|
+
* @param arc - An arc index in `[0, arcCount)`
|
|
8
|
+
* @returns The node index whose row contains the arc
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export function arcSourceIn(rowPtr, arc) {
|
|
12
|
+
let lo = 0;
|
|
13
|
+
let hi = rowPtr.length - 1; // nodeCount
|
|
14
|
+
while (lo < hi) {
|
|
15
|
+
const mid = (lo + hi) >> 1;
|
|
16
|
+
if (rowPtr[mid + 1] <= arc) {
|
|
17
|
+
lo = mid + 1;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
hi = mid;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return lo;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=arc-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arc-source.js","sourceRoot":"","sources":["../../../../src/indexed/structures/arc-source.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,MAAW,EAAE,GAAW;IAChD,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,IAAI,EAAE,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY;IACxC,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC;YACzB,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACJ,EAAE,GAAG,GAAG,CAAC;QACb,CAAC;IACL,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scratch structures for the index-based ports (graph-format design 14.2, section 14.6's
|
|
3
|
+
* helper-ownership sentence at `graph-format-design.md:4270`).
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
export { arcSourceIn } from "./arc-source.js";
|
|
7
|
+
export { IndexedMinHeap } from "./min-heap.js";
|
|
8
|
+
export { IntUnionFind } from "./union-find.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/indexed/structures/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scratch structures for the index-based ports (graph-format design 14.2, section 14.6's
|
|
3
|
+
* helper-ownership sentence at `graph-format-design.md:4270`).
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
export { arcSourceIn } from "./arc-source.js";
|
|
7
|
+
export { IndexedMinHeap } from "./min-heap.js";
|
|
8
|
+
export { IntUnionFind } from "./union-find.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/indexed/structures/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A binary min-heap over node indices with O(log n) decrease-key, keyed by `Float64Array` values
|
|
3
|
+
* (graph-format design 14.2, `graph-format-design.md:3771`). `pushOrDecrease` is the only operation
|
|
4
|
+
* Dijkstra's inner loop needs: it inserts an absent node and decreases a present one, so the heap
|
|
5
|
+
* never holds a stale duplicate and `pop()` needs no "is this entry current" check.
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export declare class IndexedMinHeap {
|
|
9
|
+
private readonly heap;
|
|
10
|
+
private readonly slot;
|
|
11
|
+
private readonly key;
|
|
12
|
+
private size;
|
|
13
|
+
/**
|
|
14
|
+
* Create an empty heap over node indices in `[0, capacity)`.
|
|
15
|
+
* @param capacity - The number of distinct node indices the heap may hold
|
|
16
|
+
*/
|
|
17
|
+
constructor(capacity: number);
|
|
18
|
+
/**
|
|
19
|
+
* Whether the heap holds no entries.
|
|
20
|
+
* @returns True when the heap holds no entries
|
|
21
|
+
*/
|
|
22
|
+
isEmpty(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Insert a node that is not in the heap.
|
|
25
|
+
* @param node - The node index
|
|
26
|
+
* @param key - Its key
|
|
27
|
+
*/
|
|
28
|
+
push(node: number, key: number): void;
|
|
29
|
+
/**
|
|
30
|
+
* Insert the node, or lower its key if it is already present and the new key is smaller.
|
|
31
|
+
* @param node - The node index
|
|
32
|
+
* @param key - Its candidate key
|
|
33
|
+
*/
|
|
34
|
+
pushOrDecrease(node: number, key: number): void;
|
|
35
|
+
/**
|
|
36
|
+
* Remove and return the node with the smallest key. Undefined behaviour on an empty heap;
|
|
37
|
+
* callers guard with `isEmpty()`.
|
|
38
|
+
* @returns The node index
|
|
39
|
+
*/
|
|
40
|
+
pop(): number;
|
|
41
|
+
private siftUp;
|
|
42
|
+
private siftDown;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=min-heap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"min-heap.d.ts","sourceRoot":"","sources":["../../../../src/indexed/structures/min-heap.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;IAC1B,OAAO,CAAC,IAAI,CAAK;IAEjB;;;OAGG;gBACS,QAAQ,EAAE,MAAM;IAM5B;;;OAGG;IACH,OAAO,IAAI,OAAO;IAIlB;;;;OAIG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAQrC;;;;OAIG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAY/C;;;;OAIG;IACH,GAAG,IAAI,MAAM;IAab,OAAO,CAAC,MAAM;IAkBd,OAAO,CAAC,QAAQ;CAsBnB"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { INVALID_INDEX } from "@graphty/graph-format";
|
|
2
|
+
/**
|
|
3
|
+
* A binary min-heap over node indices with O(log n) decrease-key, keyed by `Float64Array` values
|
|
4
|
+
* (graph-format design 14.2, `graph-format-design.md:3771`). `pushOrDecrease` is the only operation
|
|
5
|
+
* Dijkstra's inner loop needs: it inserts an absent node and decreases a present one, so the heap
|
|
6
|
+
* never holds a stale duplicate and `pop()` needs no "is this entry current" check.
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export class IndexedMinHeap {
|
|
10
|
+
/**
|
|
11
|
+
* Create an empty heap over node indices in `[0, capacity)`.
|
|
12
|
+
* @param capacity - The number of distinct node indices the heap may hold
|
|
13
|
+
*/
|
|
14
|
+
constructor(capacity) {
|
|
15
|
+
this.size = 0;
|
|
16
|
+
this.heap = new Uint32Array(capacity);
|
|
17
|
+
this.slot = new Uint32Array(capacity).fill(INVALID_INDEX);
|
|
18
|
+
this.key = new Float64Array(capacity);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Whether the heap holds no entries.
|
|
22
|
+
* @returns True when the heap holds no entries
|
|
23
|
+
*/
|
|
24
|
+
isEmpty() {
|
|
25
|
+
return this.size === 0;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Insert a node that is not in the heap.
|
|
29
|
+
* @param node - The node index
|
|
30
|
+
* @param key - Its key
|
|
31
|
+
*/
|
|
32
|
+
push(node, key) {
|
|
33
|
+
this.key[node] = key;
|
|
34
|
+
this.heap[this.size] = node;
|
|
35
|
+
this.slot[node] = this.size;
|
|
36
|
+
this.size++;
|
|
37
|
+
this.siftUp(this.size - 1);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Insert the node, or lower its key if it is already present and the new key is smaller.
|
|
41
|
+
* @param node - The node index
|
|
42
|
+
* @param key - Its candidate key
|
|
43
|
+
*/
|
|
44
|
+
pushOrDecrease(node, key) {
|
|
45
|
+
const at = this.slot[node];
|
|
46
|
+
if (at === INVALID_INDEX) {
|
|
47
|
+
this.push(node, key);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (key < this.key[node]) {
|
|
51
|
+
this.key[node] = key;
|
|
52
|
+
this.siftUp(at);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Remove and return the node with the smallest key. Undefined behaviour on an empty heap;
|
|
57
|
+
* callers guard with `isEmpty()`.
|
|
58
|
+
* @returns The node index
|
|
59
|
+
*/
|
|
60
|
+
pop() {
|
|
61
|
+
const top = this.heap[0];
|
|
62
|
+
this.slot[top] = INVALID_INDEX;
|
|
63
|
+
this.size--;
|
|
64
|
+
if (this.size > 0) {
|
|
65
|
+
const moved = this.heap[this.size];
|
|
66
|
+
this.heap[0] = moved;
|
|
67
|
+
this.slot[moved] = 0;
|
|
68
|
+
this.siftDown(0);
|
|
69
|
+
}
|
|
70
|
+
return top;
|
|
71
|
+
}
|
|
72
|
+
siftUp(from) {
|
|
73
|
+
let at = from;
|
|
74
|
+
const node = this.heap[at];
|
|
75
|
+
const key = this.key[node];
|
|
76
|
+
while (at > 0) {
|
|
77
|
+
const parent = (at - 1) >> 1;
|
|
78
|
+
const parentNode = this.heap[parent];
|
|
79
|
+
if (this.key[parentNode] <= key) {
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
this.heap[at] = parentNode;
|
|
83
|
+
this.slot[parentNode] = at;
|
|
84
|
+
at = parent;
|
|
85
|
+
}
|
|
86
|
+
this.heap[at] = node;
|
|
87
|
+
this.slot[node] = at;
|
|
88
|
+
}
|
|
89
|
+
siftDown(from) {
|
|
90
|
+
let at = from;
|
|
91
|
+
const node = this.heap[at];
|
|
92
|
+
const key = this.key[node];
|
|
93
|
+
for (;;) {
|
|
94
|
+
const left = 2 * at + 1;
|
|
95
|
+
if (left >= this.size) {
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
const right = left + 1;
|
|
99
|
+
const child = right < this.size && this.key[this.heap[right]] < this.key[this.heap[left]] ? right : left;
|
|
100
|
+
const childNode = this.heap[child];
|
|
101
|
+
if (key <= this.key[childNode]) {
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
this.heap[at] = childNode;
|
|
105
|
+
this.slot[childNode] = at;
|
|
106
|
+
at = child;
|
|
107
|
+
}
|
|
108
|
+
this.heap[at] = node;
|
|
109
|
+
this.slot[node] = at;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=min-heap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"min-heap.js","sourceRoot":"","sources":["../../../../src/indexed/structures/min-heap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type U32 } from "@graphty/graph-format";
|
|
2
|
+
/**
|
|
3
|
+
* Index-keyed union-find over `[0, size)` with union by rank and path halving. The legacy
|
|
4
|
+
* `UnionFind` (`src/data-structures/union-find.ts`) is NodeId-keyed and stays where it is.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export declare class IntUnionFind {
|
|
8
|
+
private readonly parent;
|
|
9
|
+
private readonly rank;
|
|
10
|
+
/**
|
|
11
|
+
* Create a union-find whose every element is a singleton set.
|
|
12
|
+
* @param size - The number of elements, each initially its own singleton set
|
|
13
|
+
*/
|
|
14
|
+
constructor(size: number);
|
|
15
|
+
/**
|
|
16
|
+
* Find the representative of an element's set, halving the path on the way up.
|
|
17
|
+
* @param x - An element index
|
|
18
|
+
* @returns The representative of x's set
|
|
19
|
+
*/
|
|
20
|
+
find(x: number): number;
|
|
21
|
+
/**
|
|
22
|
+
* Merge the sets of two elements, attaching the shallower tree under the deeper one.
|
|
23
|
+
* @param a - An element index
|
|
24
|
+
* @param b - An element index
|
|
25
|
+
* @returns True when the two sets were distinct and have now been merged
|
|
26
|
+
*/
|
|
27
|
+
union(a: number, b: number): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Dense labels in FIRST-SEEN order, which is what makes `groups()` identical to the legacy
|
|
30
|
+
* iteration order and identical to the GPU's after its own `renumberPartition` readback
|
|
31
|
+
* (design 9.7's connectedComponents row).
|
|
32
|
+
* @returns The labels and the number of distinct sets
|
|
33
|
+
*/
|
|
34
|
+
toLabels(): {
|
|
35
|
+
readonly labels: U32;
|
|
36
|
+
readonly count: number;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=union-find.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"union-find.d.ts","sourceRoot":"","sources":["../../../../src/indexed/structures/union-find.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAEpE;;;;GAIG;AACH,qBAAa,YAAY;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAM;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAM;IAE3B;;;OAGG;gBACS,IAAI,EAAE,MAAM;IAQxB;;;;OAIG;IACH,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IASvB;;;;;OAKG;IACH,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;IAiBpC;;;;;OAKG;IACH,QAAQ,IAAI;QAAE,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE;CAO/D"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { renumberPartition } from "@graphty/graph-format";
|
|
2
|
+
/**
|
|
3
|
+
* Index-keyed union-find over `[0, size)` with union by rank and path halving. The legacy
|
|
4
|
+
* `UnionFind` (`src/data-structures/union-find.ts`) is NodeId-keyed and stays where it is.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export class IntUnionFind {
|
|
8
|
+
/**
|
|
9
|
+
* Create a union-find whose every element is a singleton set.
|
|
10
|
+
* @param size - The number of elements, each initially its own singleton set
|
|
11
|
+
*/
|
|
12
|
+
constructor(size) {
|
|
13
|
+
this.parent = new Uint32Array(size);
|
|
14
|
+
this.rank = new Uint32Array(size);
|
|
15
|
+
for (let i = 0; i < size; i++) {
|
|
16
|
+
this.parent[i] = i;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Find the representative of an element's set, halving the path on the way up.
|
|
21
|
+
* @param x - An element index
|
|
22
|
+
* @returns The representative of x's set
|
|
23
|
+
*/
|
|
24
|
+
find(x) {
|
|
25
|
+
let node = x;
|
|
26
|
+
while (this.parent[node] !== node) {
|
|
27
|
+
this.parent[node] = this.parent[this.parent[node]]; // path halving
|
|
28
|
+
node = this.parent[node];
|
|
29
|
+
}
|
|
30
|
+
return node;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Merge the sets of two elements, attaching the shallower tree under the deeper one.
|
|
34
|
+
* @param a - An element index
|
|
35
|
+
* @param b - An element index
|
|
36
|
+
* @returns True when the two sets were distinct and have now been merged
|
|
37
|
+
*/
|
|
38
|
+
union(a, b) {
|
|
39
|
+
const ra = this.find(a);
|
|
40
|
+
const rb = this.find(b);
|
|
41
|
+
if (ra === rb) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (this.rank[ra] < this.rank[rb]) {
|
|
45
|
+
this.parent[ra] = rb;
|
|
46
|
+
}
|
|
47
|
+
else if (this.rank[ra] > this.rank[rb]) {
|
|
48
|
+
this.parent[rb] = ra;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
this.parent[rb] = ra;
|
|
52
|
+
this.rank[ra]++;
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Dense labels in FIRST-SEEN order, which is what makes `groups()` identical to the legacy
|
|
58
|
+
* iteration order and identical to the GPU's after its own `renumberPartition` readback
|
|
59
|
+
* (design 9.7's connectedComponents row).
|
|
60
|
+
* @returns The labels and the number of distinct sets
|
|
61
|
+
*/
|
|
62
|
+
toLabels() {
|
|
63
|
+
const roots = new Uint32Array(this.parent.length);
|
|
64
|
+
for (let i = 0; i < roots.length; i++) {
|
|
65
|
+
roots[i] = this.find(i);
|
|
66
|
+
}
|
|
67
|
+
return renumberPartition(roots);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=union-find.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"union-find.js","sourceRoot":"","sources":["../../../../src/indexed/structures/union-find.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAY,MAAM,uBAAuB,CAAC;AAEpE;;;;GAIG;AACH,MAAM,OAAO,YAAY;IAIrB;;;OAGG;IACH,YAAY,IAAY;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,CAAS;QACV,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YAChC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,eAAe;YACnE,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,CAAS,EAAE,CAAS;QACtB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;QACzB,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;QACzB,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACpB,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACH,QAAQ;QACJ,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;CACJ"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversion from the legacy `Graph` class to a frozen graph-format snapshot
|
|
3
|
+
* (graph-format design 14.1 rule 4, 14.6 row A1). This is the ONLY bridge between the legacy
|
|
4
|
+
* Map-of-Maps surface and `indexed.*`; nothing under `src/indexed/` other than this file imports
|
|
5
|
+
* `../core/graph.js`.
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { type GraphSnapshot } from "@graphty/graph-format";
|
|
9
|
+
import type { Graph } from "../core/graph.js";
|
|
10
|
+
/** Options of {@link toSnapshot}. @public */
|
|
11
|
+
export interface ToSnapshotOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Record FNV-1a checksums at freeze so a caller can assert `snapshot.validate({ checksum: true })`
|
|
14
|
+
* (graph-format design 14.2's first port rule: views are shared, so a port that writes into one
|
|
15
|
+
* has to fail a test rather than corrupt the next call). Default false; the test suites set it.
|
|
16
|
+
*/
|
|
17
|
+
readonly checksum?: boolean | undefined;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Freeze a legacy `Graph` into a `GraphSnapshot`, memoised on the graph's `mutationCount`.
|
|
21
|
+
*
|
|
22
|
+
* The builder is created with `weightDtype: "f64"` so a legacy graph's double weights survive
|
|
23
|
+
* exactly: at freeze, graph-format keeps the original values in an f64 edge column with role
|
|
24
|
+
* `weight` (the "shadow") whenever at least one of them is not f32-exact, and costs nothing when
|
|
25
|
+
* they all are (graph-format design section 3.7, `graph-format/src/builder/freeze.ts:332-360`).
|
|
26
|
+
* A weighted `indexed.*` port reproduces legacy f64 results by passing
|
|
27
|
+
* `expandEdges(s, shadow.data)` as its per-arc `weights` override.
|
|
28
|
+
*
|
|
29
|
+
* Every legacy edge carries a weight (`Graph.addEdge` defaults it to 1), so the builder's
|
|
30
|
+
* `weighted: "auto"` always allocates the arc weight array -- 4 bytes per arc. That is truthful
|
|
31
|
+
* rather than wasteful: the legacy graph really does store the value.
|
|
32
|
+
* @param graph - The legacy graph to convert
|
|
33
|
+
* @param options - Conversion options
|
|
34
|
+
* @returns A frozen snapshot of the graph's current topology and weights
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
export declare function toSnapshot(graph: Graph, options?: ToSnapshotOptions): GraphSnapshot;
|
|
38
|
+
//# sourceMappingURL=to-snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"to-snapshot.d.ts","sourceRoot":"","sources":["../../../src/indexed/to-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEzE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC3C;AAeD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,iBAAsB,GAAG,aAAa,CAwBvF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversion from the legacy `Graph` class to a frozen graph-format snapshot
|
|
3
|
+
* (graph-format design 14.1 rule 4, 14.6 row A1). This is the ONLY bridge between the legacy
|
|
4
|
+
* Map-of-Maps surface and `indexed.*`; nothing under `src/indexed/` other than this file imports
|
|
5
|
+
* `../core/graph.js`.
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { GraphBuilder } from "@graphty/graph-format";
|
|
9
|
+
/**
|
|
10
|
+
* One entry per graph, REPLACED rather than appended to on a mutation. The entry holds the
|
|
11
|
+
* mutationCount it was built at, which is what makes a stale hit impossible -- the bug the old
|
|
12
|
+
* `WeakMap<Graph, CSRGraph>` cache had (graph-format design 14.1 rule 4).
|
|
13
|
+
*/
|
|
14
|
+
const SNAPSHOT_CACHE = new WeakMap();
|
|
15
|
+
/**
|
|
16
|
+
* Freeze a legacy `Graph` into a `GraphSnapshot`, memoised on the graph's `mutationCount`.
|
|
17
|
+
*
|
|
18
|
+
* The builder is created with `weightDtype: "f64"` so a legacy graph's double weights survive
|
|
19
|
+
* exactly: at freeze, graph-format keeps the original values in an f64 edge column with role
|
|
20
|
+
* `weight` (the "shadow") whenever at least one of them is not f32-exact, and costs nothing when
|
|
21
|
+
* they all are (graph-format design section 3.7, `graph-format/src/builder/freeze.ts:332-360`).
|
|
22
|
+
* A weighted `indexed.*` port reproduces legacy f64 results by passing
|
|
23
|
+
* `expandEdges(s, shadow.data)` as its per-arc `weights` override.
|
|
24
|
+
*
|
|
25
|
+
* Every legacy edge carries a weight (`Graph.addEdge` defaults it to 1), so the builder's
|
|
26
|
+
* `weighted: "auto"` always allocates the arc weight array -- 4 bytes per arc. That is truthful
|
|
27
|
+
* rather than wasteful: the legacy graph really does store the value.
|
|
28
|
+
* @param graph - The legacy graph to convert
|
|
29
|
+
* @param options - Conversion options
|
|
30
|
+
* @returns A frozen snapshot of the graph's current topology and weights
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export function toSnapshot(graph, options = {}) {
|
|
34
|
+
const checksum = options.checksum === true;
|
|
35
|
+
const cached = SNAPSHOT_CACHE.get(graph);
|
|
36
|
+
// A checksummed snapshot answers a plain request; a plain one cannot answer a checksummed
|
|
37
|
+
// request -- validate({ checksum: true }) throws E_INVALID_SNAPSHOT ("no-checksum") when none
|
|
38
|
+
// were recorded (graph-format/src/types/snapshot.ts:401-405).
|
|
39
|
+
if (cached !== undefined && cached.mutationCount === graph.mutationCount && (cached.checksum || !checksum)) {
|
|
40
|
+
return cached.snapshot;
|
|
41
|
+
}
|
|
42
|
+
const builder = new GraphBuilder({
|
|
43
|
+
directed: graph.isDirected,
|
|
44
|
+
weightDtype: "f64",
|
|
45
|
+
expectedNodes: graph.nodeCount,
|
|
46
|
+
expectedEdges: graph.totalEdgeCount,
|
|
47
|
+
});
|
|
48
|
+
for (const node of graph.nodes()) {
|
|
49
|
+
builder.addNode(node.id);
|
|
50
|
+
}
|
|
51
|
+
for (const edge of graph.edges()) {
|
|
52
|
+
builder.addEdge(edge.source, edge.target, edge.weight);
|
|
53
|
+
}
|
|
54
|
+
const snapshot = builder.freeze({ label: "algorithms.toSnapshot", checksum });
|
|
55
|
+
SNAPSHOT_CACHE.set(graph, { mutationCount: graph.mutationCount, checksum, snapshot });
|
|
56
|
+
return snapshot;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=to-snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"to-snapshot.js","sourceRoot":"","sources":["../../../src/indexed/to-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAsB,MAAM,uBAAuB,CAAC;AAoBzE;;;;GAIG;AACH,MAAM,cAAc,GAAG,IAAI,OAAO,EAAqB,CAAC;AAExD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAY,EAAE,UAA6B,EAAE;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC;IAC3C,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACzC,0FAA0F;IAC1F,8FAA8F;IAC9F,8DAA8D;IAC9D,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,aAAa,KAAK,KAAK,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzG,OAAO,MAAM,CAAC,QAAQ,CAAC;IAC3B,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC;QAC7B,QAAQ,EAAE,KAAK,CAAC,UAAU;QAC1B,WAAW,EAAE,KAAK;QAClB,aAAa,EAAE,KAAK,CAAC,SAAS;QAC9B,aAAa,EAAE,KAAK,CAAC,cAAc;KACtC,CAAC,CAAC;IACH,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAC/B,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAC/B,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,uBAAuB,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC9E,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;IACtF,OAAO,QAAQ,CAAC;AACpB,CAAC"}
|