@graphty/algorithms 1.3.1 → 1.4.2
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/README.md +358 -413
- package/dist/algorithms.js +564 -261
- package/dist/algorithms.js.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.d.ts +10 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +27 -6
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/algorithms/centrality/closeness.d.ts +11 -2
- package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/closeness.js +17 -3
- package/dist/src/algorithms/centrality/closeness.js.map +1 -1
- package/dist/src/algorithms/centrality/degree.d.ts +7 -0
- package/dist/src/algorithms/centrality/degree.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/degree.js +9 -6
- package/dist/src/algorithms/centrality/degree.js.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts +21 -3
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js +25 -7
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts +28 -2
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank.js +30 -4
- package/dist/src/algorithms/centrality/delta-pagerank.js.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.d.ts +10 -3
- package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.js +11 -4
- package/dist/src/algorithms/centrality/eigenvector.js.map +1 -1
- package/dist/src/algorithms/centrality/hits.d.ts +10 -3
- package/dist/src/algorithms/centrality/hits.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/hits.js +11 -4
- package/dist/src/algorithms/centrality/hits.js.map +1 -1
- package/dist/src/algorithms/centrality/index.d.ts +1 -1
- package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/index.js +1 -1
- package/dist/src/algorithms/centrality/index.js.map +1 -1
- package/dist/src/algorithms/centrality/katz.d.ts +10 -3
- package/dist/src/algorithms/centrality/katz.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/katz.js +13 -8
- package/dist/src/algorithms/centrality/katz.js.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.d.ts +14 -0
- package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.js +16 -1
- package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.d.ts +2 -3
- package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.js +21 -4
- package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
- package/dist/src/algorithms/community/index.d.ts.map +1 -1
- package/dist/src/algorithms/community/index.js.map +1 -1
- package/dist/src/algorithms/community/label-propagation.d.ts +0 -3
- package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -1
- package/dist/src/algorithms/community/label-propagation.js +13 -6
- package/dist/src/algorithms/community/label-propagation.js.map +1 -1
- package/dist/src/algorithms/community/leiden.d.ts +0 -1
- package/dist/src/algorithms/community/leiden.d.ts.map +1 -1
- package/dist/src/algorithms/community/leiden.js +37 -6
- package/dist/src/algorithms/community/leiden.js.map +1 -1
- package/dist/src/algorithms/community/louvain-optimized.d.ts +37 -0
- package/dist/src/algorithms/community/louvain-optimized.d.ts.map +1 -1
- package/dist/src/algorithms/community/louvain-optimized.js +42 -7
- package/dist/src/algorithms/community/louvain-optimized.js.map +1 -1
- package/dist/src/algorithms/community/louvain.d.ts +2 -3
- package/dist/src/algorithms/community/louvain.d.ts.map +1 -1
- package/dist/src/algorithms/community/louvain.js +19 -6
- package/dist/src/algorithms/community/louvain.js.map +1 -1
- package/dist/src/algorithms/community/modularity-utils.d.ts +0 -4
- package/dist/src/algorithms/community/modularity-utils.d.ts.map +1 -1
- package/dist/src/algorithms/community/modularity-utils.js +1 -5
- package/dist/src/algorithms/community/modularity-utils.js.map +1 -1
- package/dist/src/algorithms/components/connected.d.ts +23 -0
- package/dist/src/algorithms/components/connected.d.ts.map +1 -1
- package/dist/src/algorithms/components/connected.js +29 -3
- package/dist/src/algorithms/components/connected.js.map +1 -1
- package/dist/src/algorithms/matching/bipartite.d.ts +10 -0
- package/dist/src/algorithms/matching/bipartite.d.ts.map +1 -1
- package/dist/src/algorithms/matching/bipartite.js +10 -0
- package/dist/src/algorithms/matching/bipartite.js.map +1 -1
- package/dist/src/algorithms/matching/index.d.ts.map +1 -1
- package/dist/src/algorithms/matching/index.js.map +1 -1
- package/dist/src/algorithms/matching/isomorphism.d.ts +8 -0
- package/dist/src/algorithms/matching/isomorphism.d.ts.map +1 -1
- package/dist/src/algorithms/matching/isomorphism.js +36 -2
- package/dist/src/algorithms/matching/isomorphism.js.map +1 -1
- package/dist/src/algorithms/mst/index.d.ts.map +1 -1
- package/dist/src/algorithms/mst/index.js.map +1 -1
- package/dist/src/algorithms/mst/kruskal.d.ts +14 -0
- package/dist/src/algorithms/mst/kruskal.d.ts.map +1 -1
- package/dist/src/algorithms/mst/kruskal.js +17 -3
- package/dist/src/algorithms/mst/kruskal.js.map +1 -1
- package/dist/src/algorithms/mst/prim.d.ts +9 -0
- package/dist/src/algorithms/mst/prim.d.ts.map +1 -1
- package/dist/src/algorithms/mst/prim.js +9 -0
- package/dist/src/algorithms/mst/prim.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.d.ts +10 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.js +10 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts +11 -4
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +18 -16
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts +15 -0
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js +15 -0
- package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts +17 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/floyd-warshall.js +17 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.js.map +1 -1
- package/dist/src/algorithms/shortest-path/index.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/index.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs-unified.d.ts +13 -0
- package/dist/src/algorithms/traversal/bfs-unified.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs-unified.js +37 -0
- package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs-variants.d.ts +23 -0
- package/dist/src/algorithms/traversal/bfs-variants.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs-variants.js +34 -0
- package/dist/src/algorithms/traversal/bfs-variants.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs.d.ts +1 -1
- package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs.js +1 -1
- package/dist/src/algorithms/traversal/bfs.js.map +1 -1
- package/dist/src/algorithms/traversal/dfs.d.ts +10 -0
- package/dist/src/algorithms/traversal/dfs.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/dfs.js +48 -0
- package/dist/src/algorithms/traversal/dfs.js.map +1 -1
- package/dist/src/algorithms/traversal/index.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/index.js.map +1 -1
- package/dist/src/benchmark-all-algorithms.d.ts +2 -0
- package/dist/src/benchmark-all-algorithms.d.ts.map +1 -1
- package/dist/src/benchmark-all-algorithms.js +32 -3
- package/dist/src/benchmark-all-algorithms.js.map +1 -1
- package/dist/src/clustering/hierarchical.d.ts +8 -1
- package/dist/src/clustering/hierarchical.d.ts.map +1 -1
- package/dist/src/clustering/hierarchical.js +22 -6
- package/dist/src/clustering/hierarchical.js.map +1 -1
- package/dist/src/clustering/index.d.ts.map +1 -1
- package/dist/src/clustering/index.js.map +1 -1
- package/dist/src/clustering/k-core.d.ts +2 -5
- package/dist/src/clustering/k-core.d.ts.map +1 -1
- package/dist/src/clustering/k-core.js +14 -12
- package/dist/src/clustering/k-core.js.map +1 -1
- package/dist/src/clustering/mcl.d.ts +6 -0
- package/dist/src/clustering/mcl.d.ts.map +1 -1
- package/dist/src/clustering/mcl.js +34 -3
- package/dist/src/clustering/mcl.js.map +1 -1
- package/dist/src/clustering/spectral.d.ts +4 -1
- package/dist/src/clustering/spectral.d.ts.map +1 -1
- package/dist/src/clustering/spectral.js +61 -28
- package/dist/src/clustering/spectral.js.map +1 -1
- package/dist/src/core/graph.d.ts +45 -0
- package/dist/src/core/graph.d.ts.map +1 -1
- package/dist/src/core/graph.js +45 -1
- package/dist/src/core/graph.js.map +1 -1
- package/dist/src/data-structures/index.d.ts.map +1 -1
- package/dist/src/data-structures/index.js.map +1 -1
- package/dist/src/data-structures/priority-queue.d.ts +18 -1
- package/dist/src/data-structures/priority-queue.d.ts.map +1 -1
- package/dist/src/data-structures/priority-queue.js +26 -5
- package/dist/src/data-structures/priority-queue.js.map +1 -1
- package/dist/src/data-structures/union-find.d.ts +21 -0
- package/dist/src/data-structures/union-find.d.ts.map +1 -1
- package/dist/src/data-structures/union-find.js +21 -0
- package/dist/src/data-structures/union-find.js.map +1 -1
- package/dist/src/flow/ford-fulkerson.d.ts +4 -2
- package/dist/src/flow/ford-fulkerson.d.ts.map +1 -1
- package/dist/src/flow/ford-fulkerson.js +31 -2
- package/dist/src/flow/ford-fulkerson.js.map +1 -1
- package/dist/src/flow/min-cut.d.ts +0 -3
- package/dist/src/flow/min-cut.d.ts.map +1 -1
- package/dist/src/flow/min-cut.js +17 -4
- package/dist/src/flow/min-cut.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/link-prediction/adamic-adar.d.ts +26 -0
- package/dist/src/link-prediction/adamic-adar.d.ts.map +1 -1
- package/dist/src/link-prediction/adamic-adar.js +36 -10
- package/dist/src/link-prediction/adamic-adar.js.map +1 -1
- package/dist/src/link-prediction/common-neighbors.d.ts +21 -0
- package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -1
- package/dist/src/link-prediction/common-neighbors.js +27 -6
- package/dist/src/link-prediction/common-neighbors.js.map +1 -1
- package/dist/src/link-prediction/index.d.ts.map +1 -1
- package/dist/src/optimized/bit-packed.d.ts +103 -53
- package/dist/src/optimized/bit-packed.d.ts.map +1 -1
- package/dist/src/optimized/bit-packed.js +104 -54
- package/dist/src/optimized/bit-packed.js.map +1 -1
- package/dist/src/optimized/csr-graph.d.ts +87 -24
- package/dist/src/optimized/csr-graph.d.ts.map +1 -1
- package/dist/src/optimized/csr-graph.js +87 -24
- package/dist/src/optimized/csr-graph.js.map +1 -1
- package/dist/src/optimized/direction-optimized-bfs.d.ts +37 -16
- package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -1
- package/dist/src/optimized/direction-optimized-bfs.js +39 -20
- package/dist/src/optimized/direction-optimized-bfs.js.map +1 -1
- package/dist/src/optimized/graph-adapter.d.ts +58 -9
- package/dist/src/optimized/graph-adapter.d.ts.map +1 -1
- package/dist/src/optimized/graph-adapter.js +58 -10
- package/dist/src/optimized/graph-adapter.js.map +1 -1
- package/dist/src/optimized/index.d.ts +1 -1
- package/dist/src/optimized/index.d.ts.map +1 -1
- package/dist/src/optimized/index.js +3 -1
- package/dist/src/optimized/index.js.map +1 -1
- package/dist/src/pathfinding/astar.d.ts +25 -9
- package/dist/src/pathfinding/astar.d.ts.map +1 -1
- package/dist/src/pathfinding/astar.js +25 -10
- package/dist/src/pathfinding/astar.js.map +1 -1
- package/dist/src/pathfinding/utils.d.ts +15 -6
- package/dist/src/pathfinding/utils.d.ts.map +1 -1
- package/dist/src/pathfinding/utils.js +19 -7
- package/dist/src/pathfinding/utils.js.map +1 -1
- package/dist/src/research/grsbm.d.ts +0 -1
- package/dist/src/research/grsbm.d.ts.map +1 -1
- package/dist/src/research/grsbm.js +22 -9
- package/dist/src/research/grsbm.js.map +1 -1
- package/dist/src/research/index.d.ts.map +1 -1
- package/dist/src/research/index.js.map +1 -1
- package/dist/src/research/sync.d.ts +0 -1
- package/dist/src/research/sync.d.ts.map +1 -1
- package/dist/src/research/sync.js +28 -7
- package/dist/src/research/sync.js.map +1 -1
- package/dist/src/research/terahac.d.ts +0 -1
- package/dist/src/research/terahac.d.ts.map +1 -1
- package/dist/src/research/terahac.js +32 -4
- package/dist/src/research/terahac.js.map +1 -1
- package/dist/src/utils/graph-converters.d.ts +31 -0
- package/dist/src/utils/graph-converters.d.ts.map +1 -1
- package/dist/src/utils/graph-converters.js +31 -0
- package/dist/src/utils/graph-converters.js.map +1 -1
- package/dist/src/utils/graph-utilities.d.ts.map +1 -1
- package/dist/src/utils/graph-utilities.js.map +1 -1
- package/dist/src/utils/math-utilities.d.ts +11 -0
- package/dist/src/utils/math-utilities.d.ts.map +1 -1
- package/dist/src/utils/math-utilities.js +14 -5
- package/dist/src/utils/math-utilities.js.map +1 -1
- package/dist/src/utils/optimization-helpers.d.ts +9 -0
- package/dist/src/utils/optimization-helpers.d.ts.map +1 -1
- package/dist/src/utils/optimization-helpers.js +12 -0
- package/dist/src/utils/optimization-helpers.js.map +1 -1
- package/dist/src/utils/priorityQueue.d.ts +24 -0
- package/dist/src/utils/priorityQueue.d.ts.map +1 -1
- package/dist/src/utils/priorityQueue.js +34 -4
- package/dist/src/utils/priorityQueue.js.map +1 -1
- package/package.json +49 -45
- package/src/algorithms/centrality/betweenness.ts +34 -17
- package/src/algorithms/centrality/closeness.ts +34 -17
- package/src/algorithms/centrality/degree.ts +15 -19
- package/src/algorithms/centrality/delta-pagerank-simple.ts +36 -28
- package/src/algorithms/centrality/delta-pagerank.ts +34 -11
- package/src/algorithms/centrality/eigenvector.ts +14 -15
- package/src/algorithms/centrality/hits.ts +17 -17
- package/src/algorithms/centrality/index.ts +20 -15
- package/src/algorithms/centrality/katz.ts +17 -25
- package/src/algorithms/centrality/pagerank.ts +26 -17
- package/src/algorithms/community/girvan-newman.ts +39 -28
- package/src/algorithms/community/index.ts +6 -7
- package/src/algorithms/community/label-propagation.ts +20 -28
- package/src/algorithms/community/leiden.ts +61 -37
- package/src/algorithms/community/louvain-optimized.ts +49 -20
- package/src/algorithms/community/louvain.ts +35 -25
- package/src/algorithms/community/modularity-utils.ts +5 -17
- package/src/algorithms/components/connected.ts +40 -17
- package/src/algorithms/matching/bipartite.ts +17 -10
- package/src/algorithms/matching/index.ts +4 -4
- package/src/algorithms/matching/isomorphism.ts +53 -23
- package/src/algorithms/mst/index.ts +3 -4
- package/src/algorithms/mst/kruskal.ts +21 -6
- package/src/algorithms/mst/prim.ts +13 -4
- package/src/algorithms/shortest-path/bellman-ford.ts +16 -15
- package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +28 -28
- package/src/algorithms/shortest-path/dijkstra.ts +23 -17
- package/src/algorithms/shortest-path/floyd-warshall.ts +21 -4
- package/src/algorithms/shortest-path/index.ts +5 -5
- package/src/algorithms/traversal/bfs-unified.ts +64 -60
- package/src/algorithms/traversal/bfs-variants.ts +61 -37
- package/src/algorithms/traversal/bfs.ts +1 -7
- package/src/algorithms/traversal/dfs.ts +61 -42
- package/src/algorithms/traversal/index.ts +3 -3
- package/src/benchmark-all-algorithms.ts +57 -25
- package/src/clustering/hierarchical.ts +40 -34
- package/src/clustering/index.ts +8 -8
- package/src/clustering/k-core.ts +26 -42
- package/src/clustering/mcl.ts +53 -23
- package/src/clustering/spectral.ts +91 -57
- package/src/core/graph.ts +54 -14
- package/src/data-structures/index.ts +2 -2
- package/src/data-structures/priority-queue.ts +36 -11
- package/src/data-structures/union-find.ts +22 -1
- package/src/flow/ford-fulkerson.ts +62 -35
- package/src/flow/min-cut.ts +43 -45
- package/src/index.ts +3 -2
- package/src/link-prediction/adamic-adar.ts +65 -51
- package/src/link-prediction/common-neighbors.ts +45 -36
- package/src/link-prediction/index.ts +1 -1
- package/src/optimized/bit-packed.ts +106 -56
- package/src/optimized/csr-graph.ts +93 -30
- package/src/optimized/direction-optimized-bfs.ts +44 -25
- package/src/optimized/graph-adapter.ts +64 -16
- package/src/optimized/index.ts +7 -9
- package/src/pathfinding/astar.ts +40 -25
- package/src/pathfinding/utils.ts +20 -13
- package/src/research/grsbm.ts +30 -24
- package/src/research/index.ts +4 -4
- package/src/research/sync.ts +39 -23
- package/src/research/terahac.ts +54 -20
- package/src/utils/graph-converters.ts +42 -14
- package/src/utils/graph-utilities.ts +11 -37
- package/src/utils/math-utilities.ts +17 -8
- package/src/utils/optimization-helpers.ts +27 -21
- package/src/utils/priorityQueue.ts +40 -6
|
@@ -10,7 +10,7 @@ export {
|
|
|
10
10
|
evaluateAdamicAdar,
|
|
11
11
|
getTopAdamicAdarCandidatesForNode,
|
|
12
12
|
} from "./adamic-adar.js";
|
|
13
|
-
export type {LinkPredictionOptions, LinkPredictionScore} from "./common-neighbors.js";
|
|
13
|
+
export type { LinkPredictionOptions, LinkPredictionScore } from "./common-neighbors.js";
|
|
14
14
|
export {
|
|
15
15
|
commonNeighborsForPairs,
|
|
16
16
|
commonNeighborsPrediction,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {TypedFastBitSet} from "typedfastbitset";
|
|
1
|
+
import { TypedFastBitSet } from "typedfastbitset";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Wrapper around TypedFastBitSet with graph-specific optimizations
|
|
@@ -10,6 +10,10 @@ export class GraphBitSet {
|
|
|
10
10
|
private bitset: TypedFastBitSet;
|
|
11
11
|
private _cardinality = 0;
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Creates a new GraphBitSet with optional pre-allocated capacity.
|
|
15
|
+
* @param capacity - The initial capacity to pre-allocate for the bitset
|
|
16
|
+
*/
|
|
13
17
|
constructor(capacity?: number) {
|
|
14
18
|
this.bitset = new TypedFastBitSet();
|
|
15
19
|
if (capacity) {
|
|
@@ -19,8 +23,9 @@ export class GraphBitSet {
|
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
* Add a single element to the set.
|
|
27
|
+
* @param index - The element index to add
|
|
28
|
+
*/
|
|
24
29
|
add(index: number): void {
|
|
25
30
|
if (!this.bitset.has(index)) {
|
|
26
31
|
this.bitset.add(index);
|
|
@@ -29,8 +34,9 @@ export class GraphBitSet {
|
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
/**
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
* Remove a single element from the set.
|
|
38
|
+
* @param index - The element index to remove
|
|
39
|
+
*/
|
|
34
40
|
remove(index: number): void {
|
|
35
41
|
if (this.bitset.has(index)) {
|
|
36
42
|
this.bitset.remove(index);
|
|
@@ -39,30 +45,35 @@ export class GraphBitSet {
|
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
/**
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
* Check if an element exists in the set.
|
|
49
|
+
* @param index - The element index to check
|
|
50
|
+
* @returns True if the element exists, false otherwise
|
|
51
|
+
*/
|
|
44
52
|
has(index: number): boolean {
|
|
45
53
|
return this.bitset.has(index);
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
/**
|
|
49
|
-
|
|
50
|
-
|
|
57
|
+
* Clear all elements
|
|
58
|
+
*/
|
|
51
59
|
clear(): void {
|
|
52
60
|
this.bitset.clear();
|
|
53
61
|
this._cardinality = 0;
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
/**
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
* Check if the set is empty.
|
|
66
|
+
* @returns True if the set contains no elements, false otherwise
|
|
67
|
+
*/
|
|
59
68
|
isEmpty(): boolean {
|
|
60
69
|
return this._cardinality === 0;
|
|
61
70
|
}
|
|
62
71
|
|
|
63
72
|
/**
|
|
64
|
-
|
|
65
|
-
|
|
73
|
+
* Optimized for graph algorithms - add a range of indices.
|
|
74
|
+
* @param start - The starting index (inclusive)
|
|
75
|
+
* @param end - The ending index (exclusive)
|
|
76
|
+
*/
|
|
66
77
|
addRange(start: number, end: number): void {
|
|
67
78
|
for (let i = start; i < end; i++) {
|
|
68
79
|
if (!this.bitset.has(i)) {
|
|
@@ -73,31 +84,35 @@ export class GraphBitSet {
|
|
|
73
84
|
}
|
|
74
85
|
|
|
75
86
|
/**
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
* Fast cardinality tracking - get the number of elements in the set.
|
|
88
|
+
* @returns The number of elements in the set
|
|
89
|
+
*/
|
|
78
90
|
size(): number {
|
|
79
91
|
return this._cardinality;
|
|
80
92
|
}
|
|
81
93
|
|
|
82
94
|
/**
|
|
83
|
-
|
|
84
|
-
|
|
95
|
+
* Batch operations for frontier management - swap contents with another GraphBitSet.
|
|
96
|
+
* @param other - The GraphBitSet to swap contents with
|
|
97
|
+
*/
|
|
85
98
|
swap(other: GraphBitSet): void {
|
|
86
99
|
[this.bitset, other.bitset] = [other.bitset, this.bitset];
|
|
87
100
|
[this._cardinality, other._cardinality] = [other._cardinality, this._cardinality];
|
|
88
101
|
}
|
|
89
102
|
|
|
90
103
|
/**
|
|
91
|
-
|
|
92
|
-
|
|
104
|
+
* Efficient iteration over all elements in the set.
|
|
105
|
+
* @yields The indices of elements in the set
|
|
106
|
+
*/
|
|
93
107
|
*[Symbol.iterator](): Generator<number> {
|
|
94
|
-
|
|
108
|
+
// Use TypedFastBitSet's optimized iteration
|
|
95
109
|
yield* this.bitset;
|
|
96
110
|
}
|
|
97
111
|
|
|
98
112
|
/**
|
|
99
|
-
|
|
100
|
-
|
|
113
|
+
* Perform union operation with another GraphBitSet, updating this set in place.
|
|
114
|
+
* @param other - The GraphBitSet to union with
|
|
115
|
+
*/
|
|
101
116
|
union(other: GraphBitSet): void {
|
|
102
117
|
const result = this.bitset.union(other.bitset);
|
|
103
118
|
this.bitset = result;
|
|
@@ -106,6 +121,10 @@ export class GraphBitSet {
|
|
|
106
121
|
this._cardinality = size;
|
|
107
122
|
}
|
|
108
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Perform intersection operation with another GraphBitSet, updating this set in place.
|
|
126
|
+
* @param other - The GraphBitSet to intersect with
|
|
127
|
+
*/
|
|
109
128
|
intersection(other: GraphBitSet): void {
|
|
110
129
|
const result = this.bitset.intersection(other.bitset);
|
|
111
130
|
this.bitset = result;
|
|
@@ -114,6 +133,10 @@ export class GraphBitSet {
|
|
|
114
133
|
this._cardinality = size;
|
|
115
134
|
}
|
|
116
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Perform difference operation with another GraphBitSet, updating this set in place.
|
|
138
|
+
* @param other - The GraphBitSet to subtract from this set
|
|
139
|
+
*/
|
|
117
140
|
difference(other: GraphBitSet): void {
|
|
118
141
|
const result = this.bitset.difference(other.bitset);
|
|
119
142
|
this.bitset = result;
|
|
@@ -123,8 +146,9 @@ export class GraphBitSet {
|
|
|
123
146
|
}
|
|
124
147
|
|
|
125
148
|
/**
|
|
126
|
-
|
|
127
|
-
|
|
149
|
+
* Clone the bitset.
|
|
150
|
+
* @returns A new GraphBitSet with the same elements
|
|
151
|
+
*/
|
|
128
152
|
clone(): GraphBitSet {
|
|
129
153
|
const cloned = new GraphBitSet();
|
|
130
154
|
cloned.bitset = this.bitset.clone();
|
|
@@ -145,6 +169,10 @@ export class VisitedBitArray {
|
|
|
145
169
|
private wordCount: number;
|
|
146
170
|
private _size: number;
|
|
147
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Creates a new VisitedBitArray with the specified size.
|
|
174
|
+
* @param size - The number of bits to allocate
|
|
175
|
+
*/
|
|
148
176
|
constructor(size: number) {
|
|
149
177
|
this._size = size;
|
|
150
178
|
this.wordCount = Math.ceil(size / 32);
|
|
@@ -152,8 +180,9 @@ export class VisitedBitArray {
|
|
|
152
180
|
}
|
|
153
181
|
|
|
154
182
|
/**
|
|
155
|
-
|
|
156
|
-
|
|
183
|
+
* Set bit at the specified index.
|
|
184
|
+
* @param index - The bit index to set
|
|
185
|
+
*/
|
|
157
186
|
set(index: number): void {
|
|
158
187
|
if (index < 0 || index >= this._size) {
|
|
159
188
|
throw new Error(`Index ${String(index)} out of bounds [0, ${String(this._size)})`);
|
|
@@ -168,8 +197,10 @@ export class VisitedBitArray {
|
|
|
168
197
|
}
|
|
169
198
|
|
|
170
199
|
/**
|
|
171
|
-
|
|
172
|
-
|
|
200
|
+
* Get bit value at the specified index.
|
|
201
|
+
* @param index - The bit index to get
|
|
202
|
+
* @returns True if the bit is set, false otherwise
|
|
203
|
+
*/
|
|
173
204
|
get(index: number): boolean {
|
|
174
205
|
if (index < 0 || index >= this._size) {
|
|
175
206
|
return false;
|
|
@@ -182,15 +213,16 @@ export class VisitedBitArray {
|
|
|
182
213
|
}
|
|
183
214
|
|
|
184
215
|
/**
|
|
185
|
-
|
|
186
|
-
|
|
216
|
+
* Clear all bits
|
|
217
|
+
*/
|
|
187
218
|
clear(): void {
|
|
188
219
|
this.words.fill(0);
|
|
189
220
|
}
|
|
190
221
|
|
|
191
222
|
/**
|
|
192
|
-
|
|
193
|
-
|
|
223
|
+
* Toggle bit at the specified index.
|
|
224
|
+
* @param index - The bit index to toggle
|
|
225
|
+
*/
|
|
194
226
|
toggle(index: number): void {
|
|
195
227
|
if (index < 0 || index >= this._size) {
|
|
196
228
|
throw new Error(`Index ${String(index)} out of bounds [0, ${String(this._size)})`);
|
|
@@ -205,8 +237,9 @@ export class VisitedBitArray {
|
|
|
205
237
|
}
|
|
206
238
|
|
|
207
239
|
/**
|
|
208
|
-
|
|
209
|
-
|
|
240
|
+
* Population count for statistics - count the number of set bits.
|
|
241
|
+
* @returns The number of bits set to 1
|
|
242
|
+
*/
|
|
210
243
|
popcount(): number {
|
|
211
244
|
let count = 0;
|
|
212
245
|
for (let i = 0; i < this.wordCount; i++) {
|
|
@@ -219,26 +252,30 @@ export class VisitedBitArray {
|
|
|
219
252
|
}
|
|
220
253
|
|
|
221
254
|
/**
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
255
|
+
* Efficient population count for a single word.
|
|
256
|
+
* Uses bit manipulation tricks for fast counting.
|
|
257
|
+
* @param n - The 32-bit word to count
|
|
258
|
+
* @returns The number of bits set to 1 in the word
|
|
259
|
+
*/
|
|
225
260
|
private popcountWord(n: number): number {
|
|
226
261
|
let x = n;
|
|
227
262
|
x = x - ((x >>> 1) & 0x55555555);
|
|
228
263
|
x = (x & 0x33333333) + ((x >>> 2) & 0x33333333);
|
|
229
|
-
return (((x + (x >>> 4)) &
|
|
264
|
+
return (((x + (x >>> 4)) & 0xf0f0f0f) * 0x1010101) >>> 24;
|
|
230
265
|
}
|
|
231
266
|
|
|
232
267
|
/**
|
|
233
|
-
|
|
234
|
-
|
|
268
|
+
* Get size of the bit array.
|
|
269
|
+
* @returns The total number of bits in the array
|
|
270
|
+
*/
|
|
235
271
|
size(): number {
|
|
236
272
|
return this._size;
|
|
237
273
|
}
|
|
238
274
|
|
|
239
275
|
/**
|
|
240
|
-
|
|
241
|
-
|
|
276
|
+
* Check if all bits are zero.
|
|
277
|
+
* @returns True if no bits are set, false otherwise
|
|
278
|
+
*/
|
|
242
279
|
isEmpty(): boolean {
|
|
243
280
|
for (let i = 0; i < this.wordCount; i++) {
|
|
244
281
|
if (this.words[i] !== 0) {
|
|
@@ -249,8 +286,9 @@ export class VisitedBitArray {
|
|
|
249
286
|
}
|
|
250
287
|
|
|
251
288
|
/**
|
|
252
|
-
|
|
253
|
-
|
|
289
|
+
* Set multiple bits from an array of indices.
|
|
290
|
+
* @param indices - Array of bit indices to set
|
|
291
|
+
*/
|
|
254
292
|
setMultiple(indices: number[]): void {
|
|
255
293
|
for (const index of indices) {
|
|
256
294
|
this.set(index);
|
|
@@ -258,8 +296,9 @@ export class VisitedBitArray {
|
|
|
258
296
|
}
|
|
259
297
|
|
|
260
298
|
/**
|
|
261
|
-
|
|
262
|
-
|
|
299
|
+
* Get indices of all set bits.
|
|
300
|
+
* @returns Array containing the indices of all bits that are set to 1
|
|
301
|
+
*/
|
|
263
302
|
getSetIndices(): number[] {
|
|
264
303
|
const indices: number[] = [];
|
|
265
304
|
for (let wordIndex = 0; wordIndex < this.wordCount; wordIndex++) {
|
|
@@ -292,6 +331,10 @@ export class CompactDistanceArray {
|
|
|
292
331
|
private _size: number;
|
|
293
332
|
private static readonly INFINITY = 65535;
|
|
294
333
|
|
|
334
|
+
/**
|
|
335
|
+
* Creates a new CompactDistanceArray with the specified size.
|
|
336
|
+
* @param size - The number of distance values to store
|
|
337
|
+
*/
|
|
295
338
|
constructor(size: number) {
|
|
296
339
|
this._size = size;
|
|
297
340
|
this.data = new Uint16Array(size);
|
|
@@ -299,8 +342,10 @@ export class CompactDistanceArray {
|
|
|
299
342
|
}
|
|
300
343
|
|
|
301
344
|
/**
|
|
302
|
-
|
|
303
|
-
|
|
345
|
+
* Set distance at the specified index.
|
|
346
|
+
* @param index - The node index to set the distance for
|
|
347
|
+
* @param distance - The distance value to set
|
|
348
|
+
*/
|
|
304
349
|
set(index: number, distance: number): void {
|
|
305
350
|
if (distance >= CompactDistanceArray.INFINITY) {
|
|
306
351
|
throw new Error(`Distance exceeds maximum value (${String(CompactDistanceArray.INFINITY - 1)})`);
|
|
@@ -310,30 +355,35 @@ export class CompactDistanceArray {
|
|
|
310
355
|
}
|
|
311
356
|
|
|
312
357
|
/**
|
|
313
|
-
|
|
314
|
-
|
|
358
|
+
* Get distance at the specified index.
|
|
359
|
+
* @param index - The node index to get the distance for
|
|
360
|
+
* @returns The distance value, or INFINITY if not set
|
|
361
|
+
*/
|
|
315
362
|
get(index: number): number {
|
|
316
363
|
const value = this.data[index];
|
|
317
364
|
return value ?? CompactDistanceArray.INFINITY; // Default to unvisited
|
|
318
365
|
}
|
|
319
366
|
|
|
320
367
|
/**
|
|
321
|
-
|
|
322
|
-
|
|
368
|
+
* Check if a node has been visited (has a valid distance).
|
|
369
|
+
* @param index - The node index to check
|
|
370
|
+
* @returns True if the node has been visited, false otherwise
|
|
371
|
+
*/
|
|
323
372
|
isVisited(index: number): boolean {
|
|
324
373
|
return this.data[index] !== CompactDistanceArray.INFINITY;
|
|
325
374
|
}
|
|
326
375
|
|
|
327
376
|
/**
|
|
328
|
-
|
|
329
|
-
|
|
377
|
+
* Reset all distances to unvisited state.
|
|
378
|
+
*/
|
|
330
379
|
clear(): void {
|
|
331
380
|
this.data.fill(CompactDistanceArray.INFINITY);
|
|
332
381
|
}
|
|
333
382
|
|
|
334
383
|
/**
|
|
335
|
-
|
|
336
|
-
|
|
384
|
+
* Get the size of the distance array.
|
|
385
|
+
* @returns The number of elements in the array
|
|
386
|
+
*/
|
|
337
387
|
size(): number {
|
|
338
388
|
return this._size;
|
|
339
389
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {NodeId} from "../types/index.js";
|
|
1
|
+
import type { NodeId } from "../types/index.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Interface for read-only graph operations
|
|
@@ -44,19 +44,29 @@ interface CSRGraphData<TNodeId> {
|
|
|
44
44
|
export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
45
45
|
private data: CSRGraphData<TNodeId>;
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Creates a new CSRGraph from an adjacency list representation.
|
|
49
|
+
* @param adjacencyList - Map of node IDs to arrays of neighbor node IDs
|
|
50
|
+
* @param weights - Optional map of edge weights keyed by "source-target" strings
|
|
51
|
+
* @param buildReverse - Whether to build reverse edges for bottom-up BFS (default true)
|
|
52
|
+
*/
|
|
47
53
|
constructor(adjacencyList: Map<TNodeId, TNodeId[]>, weights?: Map<string, number>, buildReverse = true) {
|
|
48
54
|
this.data = this.buildCSR(adjacencyList, weights, buildReverse);
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
/**
|
|
52
|
-
|
|
53
|
-
|
|
58
|
+
* Build CSR structure from adjacency list.
|
|
59
|
+
* @param adjacencyList - Map of node IDs to arrays of neighbor node IDs
|
|
60
|
+
* @param weights - Optional map of edge weights keyed by "source-target" strings
|
|
61
|
+
* @param buildReverse - Whether to build reverse edges for bottom-up BFS
|
|
62
|
+
* @returns The constructed CSR graph data structure
|
|
63
|
+
*/
|
|
54
64
|
private buildCSR(
|
|
55
65
|
adjacencyList: Map<TNodeId, TNodeId[]>,
|
|
56
66
|
weights?: Map<string, number>,
|
|
57
67
|
buildReverse = true,
|
|
58
68
|
): CSRGraphData<TNodeId> {
|
|
59
|
-
|
|
69
|
+
// Collect all unique nodes (both sources and targets)
|
|
60
70
|
const allNodes = new Set<TNodeId>();
|
|
61
71
|
for (const [source, neighbors] of adjacencyList) {
|
|
62
72
|
allNodes.add(source);
|
|
@@ -115,7 +125,7 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
115
125
|
throw new Error(`Node ${String(n)} not found in nodeIdToIndex map`);
|
|
116
126
|
}
|
|
117
127
|
|
|
118
|
-
return {id: n, index};
|
|
128
|
+
return { id: n, index };
|
|
119
129
|
})
|
|
120
130
|
.sort((a, b) => a.index - b.index);
|
|
121
131
|
|
|
@@ -193,18 +203,37 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
193
203
|
}
|
|
194
204
|
|
|
195
205
|
// Core API methods
|
|
206
|
+
/**
|
|
207
|
+
* Get the total number of nodes in the graph.
|
|
208
|
+
* @returns The number of nodes
|
|
209
|
+
*/
|
|
196
210
|
nodeCount(): number {
|
|
197
211
|
return this.data.indexToNodeId.length;
|
|
198
212
|
}
|
|
199
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Get the total number of edges in the graph.
|
|
216
|
+
* @returns The number of edges
|
|
217
|
+
*/
|
|
200
218
|
edgeCount(): number {
|
|
201
219
|
return this.data.columnIndices.length;
|
|
202
220
|
}
|
|
203
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Check if a node exists in the graph.
|
|
224
|
+
* @param nodeId - The node ID to check
|
|
225
|
+
* @returns True if the node exists, false otherwise
|
|
226
|
+
*/
|
|
204
227
|
hasNode(nodeId: TNodeId): boolean {
|
|
205
228
|
return this.data.nodeIdToIndex.has(nodeId);
|
|
206
229
|
}
|
|
207
230
|
|
|
231
|
+
/**
|
|
232
|
+
* Check if an edge exists between two nodes.
|
|
233
|
+
* @param source - The source node ID
|
|
234
|
+
* @param target - The target node ID
|
|
235
|
+
* @returns True if the edge exists, false otherwise
|
|
236
|
+
*/
|
|
208
237
|
hasEdge(source: TNodeId, target: TNodeId): boolean {
|
|
209
238
|
const sourceIndex = this.data.nodeIdToIndex.get(source);
|
|
210
239
|
const targetIndex = this.data.nodeIdToIndex.get(target);
|
|
@@ -225,8 +254,10 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
225
254
|
}
|
|
226
255
|
|
|
227
256
|
/**
|
|
228
|
-
|
|
229
|
-
|
|
257
|
+
* Get neighbors of a node as node IDs.
|
|
258
|
+
* @param nodeId - The node ID to get neighbors for
|
|
259
|
+
* @returns An iterator over neighbor node IDs
|
|
260
|
+
*/
|
|
230
261
|
neighbors(nodeId: TNodeId): IterableIterator<TNodeId> {
|
|
231
262
|
const nodeIndex = this.data.nodeIdToIndex.get(nodeId);
|
|
232
263
|
if (nodeIndex === undefined) {
|
|
@@ -236,7 +267,7 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
236
267
|
const start = this.data.rowPointers[nodeIndex];
|
|
237
268
|
const end = this.data.rowPointers[nodeIndex + 1];
|
|
238
269
|
|
|
239
|
-
const {columnIndices, indexToNodeId} = this.data;
|
|
270
|
+
const { columnIndices, indexToNodeId } = this.data;
|
|
240
271
|
function* generateNeighbors(): Generator<TNodeId> {
|
|
241
272
|
if (start !== undefined && end !== undefined) {
|
|
242
273
|
for (let i = start; i < end; i++) {
|
|
@@ -255,15 +286,18 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
255
286
|
}
|
|
256
287
|
|
|
257
288
|
/**
|
|
258
|
-
|
|
259
|
-
|
|
289
|
+
* Get all nodes in the graph.
|
|
290
|
+
* @returns An iterator over all node IDs
|
|
291
|
+
*/
|
|
260
292
|
nodes(): IterableIterator<TNodeId> {
|
|
261
293
|
return this.data.indexToNodeId.values();
|
|
262
294
|
}
|
|
263
295
|
|
|
264
296
|
/**
|
|
265
|
-
|
|
266
|
-
|
|
297
|
+
* Get neighbors as indices (internal use).
|
|
298
|
+
* @param nodeIndex - The internal index of the node
|
|
299
|
+
* @returns Array of neighbor indices
|
|
300
|
+
*/
|
|
267
301
|
getNeighborIndices(nodeIndex: number): number[] {
|
|
268
302
|
if (nodeIndex < 0 || nodeIndex >= this.data.indexToNodeId.length) {
|
|
269
303
|
return [];
|
|
@@ -278,6 +312,11 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
278
312
|
return Array.from(this.data.columnIndices.subarray(start, end));
|
|
279
313
|
}
|
|
280
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Get the out-degree (number of outgoing edges) of a node.
|
|
317
|
+
* @param nodeId - The node ID to get the out-degree for
|
|
318
|
+
* @returns The number of outgoing edges from the node
|
|
319
|
+
*/
|
|
281
320
|
outDegree(nodeId: TNodeId): number {
|
|
282
321
|
const nodeIndex = this.data.nodeIdToIndex.get(nodeId);
|
|
283
322
|
if (nodeIndex === undefined) {
|
|
@@ -288,8 +327,10 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
288
327
|
}
|
|
289
328
|
|
|
290
329
|
/**
|
|
291
|
-
|
|
292
|
-
|
|
330
|
+
* Get out-degree by index (internal use).
|
|
331
|
+
* @param nodeIndex - The internal index of the node
|
|
332
|
+
* @returns The number of outgoing edges from the node
|
|
333
|
+
*/
|
|
293
334
|
outDegreeByIndex(nodeIndex: number): number {
|
|
294
335
|
const start = this.data.rowPointers[nodeIndex];
|
|
295
336
|
const end = this.data.rowPointers[nodeIndex + 1];
|
|
@@ -301,8 +342,10 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
301
342
|
}
|
|
302
343
|
|
|
303
344
|
/**
|
|
304
|
-
|
|
305
|
-
|
|
345
|
+
* Iterator support for neighbor indices.
|
|
346
|
+
* @param nodeIndex - The internal index of the node
|
|
347
|
+
* @yields The indices of neighboring nodes
|
|
348
|
+
*/
|
|
306
349
|
*iterateNeighborIndices(nodeIndex: number): Generator<number> {
|
|
307
350
|
const start = this.data.rowPointers[nodeIndex];
|
|
308
351
|
const end = this.data.rowPointers[nodeIndex + 1];
|
|
@@ -318,8 +361,10 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
318
361
|
}
|
|
319
362
|
|
|
320
363
|
/**
|
|
321
|
-
|
|
322
|
-
|
|
364
|
+
* Iterator support for incoming neighbor indices (for bottom-up BFS).
|
|
365
|
+
* @param nodeIndex - The internal index of the node
|
|
366
|
+
* @yields The indices of nodes with edges pointing to this node
|
|
367
|
+
*/
|
|
323
368
|
*iterateIncomingNeighborIndices(nodeIndex: number): Generator<number> {
|
|
324
369
|
if (!this.data.reverseRowPointers || !this.data.reverseColumnIndices) {
|
|
325
370
|
return;
|
|
@@ -339,8 +384,10 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
339
384
|
}
|
|
340
385
|
|
|
341
386
|
/**
|
|
342
|
-
|
|
343
|
-
|
|
387
|
+
* Convert node ID to internal index.
|
|
388
|
+
* @param nodeId - The node ID to convert
|
|
389
|
+
* @returns The internal index for the node
|
|
390
|
+
*/
|
|
344
391
|
nodeToIndex(nodeId: TNodeId): number {
|
|
345
392
|
const index = this.data.nodeIdToIndex.get(nodeId);
|
|
346
393
|
if (index === undefined) {
|
|
@@ -351,8 +398,10 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
351
398
|
}
|
|
352
399
|
|
|
353
400
|
/**
|
|
354
|
-
|
|
355
|
-
|
|
401
|
+
* Convert internal index to node ID.
|
|
402
|
+
* @param index - The internal index to convert
|
|
403
|
+
* @returns The node ID for the given index
|
|
404
|
+
*/
|
|
356
405
|
indexToNodeId(index: number): TNodeId {
|
|
357
406
|
const nodeId = this.data.indexToNodeId[index];
|
|
358
407
|
if (nodeId === undefined) {
|
|
@@ -363,8 +412,11 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
363
412
|
}
|
|
364
413
|
|
|
365
414
|
/**
|
|
366
|
-
|
|
367
|
-
|
|
415
|
+
* Get edge weight between two nodes.
|
|
416
|
+
* @param source - The source node ID
|
|
417
|
+
* @param target - The target node ID
|
|
418
|
+
* @returns The edge weight, or undefined if the edge doesn't exist or has no weight
|
|
419
|
+
*/
|
|
368
420
|
getEdgeWeight(source: TNodeId, target: TNodeId): number | undefined {
|
|
369
421
|
if (!this.data.edgeWeights) {
|
|
370
422
|
return undefined;
|
|
@@ -393,8 +445,13 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
393
445
|
}
|
|
394
446
|
|
|
395
447
|
/**
|
|
396
|
-
|
|
397
|
-
|
|
448
|
+
* Binary search for target in sorted array.
|
|
449
|
+
* @param arr - The typed array to search in
|
|
450
|
+
* @param target - The value to search for
|
|
451
|
+
* @param start - The starting index (inclusive)
|
|
452
|
+
* @param end - The ending index (exclusive)
|
|
453
|
+
* @returns The index of the target, or -1 if not found
|
|
454
|
+
*/
|
|
398
455
|
private binarySearch(arr: Uint32Array, target: number, start: number, end: number): number {
|
|
399
456
|
let left = start;
|
|
400
457
|
let right = end - 1;
|
|
@@ -422,13 +479,19 @@ export class CSRGraph<TNodeId = NodeId> implements ReadonlyGraph<TNodeId> {
|
|
|
422
479
|
}
|
|
423
480
|
|
|
424
481
|
/**
|
|
425
|
-
|
|
426
|
-
|
|
482
|
+
* Create CSR graph from standard Graph interface.
|
|
483
|
+
* @param graph - The graph object to convert, must implement nodes, neighbors, hasNode, and optionally getEdge
|
|
484
|
+
* @param graph.nodes - Function that returns an iterator over node objects with id property
|
|
485
|
+
* @param graph.neighbors - Function that returns an iterator over neighbor node IDs
|
|
486
|
+
* @param graph.hasNode - Function that checks if a node exists in the graph
|
|
487
|
+
* @param graph.getEdge - Optional function that returns edge data including weight
|
|
488
|
+
* @returns A new CSRGraph instance
|
|
489
|
+
*/
|
|
427
490
|
static fromGraph<TNodeId = NodeId>(graph: {
|
|
428
|
-
nodes(): IterableIterator<{id: TNodeId}>;
|
|
491
|
+
nodes(): IterableIterator<{ id: TNodeId }>;
|
|
429
492
|
neighbors(nodeId: TNodeId): IterableIterator<TNodeId>;
|
|
430
493
|
hasNode(nodeId: TNodeId): boolean;
|
|
431
|
-
getEdge?(source: TNodeId, target: TNodeId): {weight?: number} | undefined;
|
|
494
|
+
getEdge?(source: TNodeId, target: TNodeId): { weight?: number } | undefined;
|
|
432
495
|
}): CSRGraph<TNodeId> {
|
|
433
496
|
const adjacencyList = new Map<TNodeId, TNodeId[]>();
|
|
434
497
|
const weights = new Map<string, number>();
|