@graphty/algorithms 1.2.0 → 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 +375 -276
- package/dist/algorithms.d.ts +42 -2
- package/dist/algorithms.js +11402 -2
- package/dist/algorithms.js.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.d.ts +14 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +144 -169
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/algorithms/centrality/closeness.d.ts +35 -1
- package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/closeness.js +70 -149
- 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 +12 -9
- package/dist/src/algorithms/centrality/degree.js.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts +57 -0
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js +304 -0
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js.map +1 -0
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts +106 -0
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/delta-pagerank.js +320 -0
- package/dist/src/algorithms/centrality/delta-pagerank.js.map +1 -0
- 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 +3 -1
- package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/index.js +2 -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 +31 -0
- package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.js +61 -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 +67 -57
- package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
- package/dist/src/algorithms/community/index.d.ts +2 -0
- 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 +11 -4
- package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -1
- package/dist/src/algorithms/community/label-propagation.js +60 -38
- package/dist/src/algorithms/community/label-propagation.js.map +1 -1
- package/dist/src/algorithms/community/leiden.d.ts +3 -3
- package/dist/src/algorithms/community/leiden.d.ts.map +1 -1
- package/dist/src/algorithms/community/leiden.js +70 -44
- package/dist/src/algorithms/community/leiden.js.map +1 -1
- package/dist/src/algorithms/community/louvain-optimized.d.ts +149 -0
- package/dist/src/algorithms/community/louvain-optimized.d.ts.map +1 -0
- package/dist/src/algorithms/community/louvain-optimized.js +338 -0
- package/dist/src/algorithms/community/louvain-optimized.js.map +1 -0
- 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 +35 -81
- package/dist/src/algorithms/community/louvain.js.map +1 -1
- package/dist/src/algorithms/community/modularity-utils.d.ts +55 -0
- package/dist/src/algorithms/community/modularity-utils.d.ts.map +1 -0
- package/dist/src/algorithms/community/modularity-utils.js +108 -0
- package/dist/src/algorithms/community/modularity-utils.js.map +1 -0
- 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 +18 -40
- 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 +11 -12
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts +44 -0
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts.map +1 -0
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +195 -0
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -0
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts +20 -2
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js +30 -14
- 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 +42 -0
- package/dist/src/algorithms/traversal/bfs-unified.d.ts.map +1 -0
- package/dist/src/algorithms/traversal/bfs-unified.js +370 -0
- package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -0
- package/dist/src/algorithms/traversal/bfs-variants.d.ts +77 -0
- package/dist/src/algorithms/traversal/bfs-variants.d.ts.map +1 -0
- package/dist/src/algorithms/traversal/bfs-variants.js +402 -0
- package/dist/src/algorithms/traversal/bfs-variants.js.map +1 -0
- package/dist/src/algorithms/traversal/bfs.d.ts +4 -18
- package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs.js +5 -182
- 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 +25 -0
- package/dist/src/benchmark-all-algorithms.d.ts.map +1 -0
- package/dist/src/benchmark-all-algorithms.js +491 -0
- package/dist/src/benchmark-all-algorithms.js.map +1 -0
- package/dist/src/clustering/hierarchical.d.ts +23 -15
- package/dist/src/clustering/hierarchical.d.ts.map +1 -1
- package/dist/src/clustering/hierarchical.js +226 -224
- package/dist/src/clustering/hierarchical.js.map +1 -1
- package/dist/src/clustering/index.d.ts +4 -2
- package/dist/src/clustering/index.d.ts.map +1 -1
- package/dist/src/clustering/index.js +2 -2
- package/dist/src/clustering/index.js.map +1 -1
- package/dist/src/clustering/k-core.d.ts +17 -19
- package/dist/src/clustering/k-core.d.ts.map +1 -1
- package/dist/src/clustering/k-core.js +68 -30
- 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 +11 -0
- package/dist/src/clustering/spectral.d.ts.map +1 -1
- package/dist/src/clustering/spectral.js +99 -47
- 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 +49 -5
- 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 +20 -12
- package/dist/src/flow/ford-fulkerson.d.ts.map +1 -1
- package/dist/src/flow/ford-fulkerson.js +170 -217
- package/dist/src/flow/ford-fulkerson.js.map +1 -1
- package/dist/src/flow/min-cut.d.ts +6 -8
- package/dist/src/flow/min-cut.d.ts.map +1 -1
- package/dist/src/flow/min-cut.js +34 -12
- package/dist/src/flow/min-cut.js.map +1 -1
- package/dist/src/index.d.ts +3 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -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 +47 -30
- 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 +31 -14
- 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 +193 -0
- package/dist/src/optimized/bit-packed.d.ts.map +1 -0
- package/dist/src/optimized/bit-packed.js +342 -0
- package/dist/src/optimized/bit-packed.js.map +1 -0
- package/dist/src/optimized/csr-graph.d.ts +149 -0
- package/dist/src/optimized/csr-graph.d.ts.map +1 -0
- package/dist/src/optimized/csr-graph.js +404 -0
- package/dist/src/optimized/csr-graph.js.map +1 -0
- package/dist/src/optimized/direction-optimized-bfs.d.ts +95 -0
- package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -0
- package/dist/src/optimized/direction-optimized-bfs.js +242 -0
- package/dist/src/optimized/direction-optimized-bfs.js.map +1 -0
- package/dist/src/optimized/graph-adapter.d.ts +111 -0
- package/dist/src/optimized/graph-adapter.d.ts.map +1 -0
- package/dist/src/optimized/graph-adapter.js +194 -0
- package/dist/src/optimized/graph-adapter.js.map +1 -0
- package/dist/src/optimized/index.d.ts +14 -0
- package/dist/src/optimized/index.d.ts.map +1 -0
- package/dist/src/optimized/index.js +30 -0
- package/dist/src/optimized/index.js.map +1 -0
- 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 +28 -23
- 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 +31 -36
- package/dist/src/research/sync.js.map +1 -1
- package/dist/src/research/terahac.d.ts +2 -1
- package/dist/src/research/terahac.d.ts.map +1 -1
- package/dist/src/research/terahac.js +39 -7
- package/dist/src/research/terahac.js.map +1 -1
- package/dist/src/types/index.d.ts +8 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/utils/algorithm-utilities.d.ts +2 -0
- package/dist/src/utils/algorithm-utilities.d.ts.map +1 -0
- package/dist/src/utils/algorithm-utilities.js +2 -0
- package/dist/src/utils/algorithm-utilities.js.map +1 -0
- package/dist/src/utils/graph-converters.d.ts +110 -0
- package/dist/src/utils/graph-converters.d.ts.map +1 -0
- package/dist/src/utils/graph-converters.js +227 -0
- package/dist/src/utils/graph-converters.js.map +1 -0
- package/dist/src/utils/graph-utilities.d.ts +62 -0
- package/dist/src/utils/graph-utilities.d.ts.map +1 -0
- package/dist/src/utils/graph-utilities.js +148 -0
- package/dist/src/utils/graph-utilities.js.map +1 -0
- package/dist/src/utils/index.d.ts +5 -0
- package/dist/src/utils/index.d.ts.map +1 -0
- package/dist/src/utils/index.js +5 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/math-utilities.d.ts +63 -0
- package/dist/src/utils/math-utilities.d.ts.map +1 -0
- package/dist/src/utils/math-utilities.js +132 -0
- package/dist/src/utils/math-utilities.js.map +1 -0
- package/dist/src/utils/matrix-utilities.d.ts +2 -0
- package/dist/src/utils/matrix-utilities.d.ts.map +1 -0
- package/dist/src/utils/matrix-utilities.js +2 -0
- package/dist/src/utils/matrix-utilities.js.map +1 -0
- package/dist/src/utils/optimization-helpers.d.ts +42 -0
- package/dist/src/utils/optimization-helpers.d.ts.map +1 -0
- package/dist/src/utils/optimization-helpers.js +59 -0
- package/dist/src/utils/optimization-helpers.js.map +1 -0
- 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 +58 -39
- package/src/algorithms/centrality/betweenness.ts +185 -200
- package/src/algorithms/centrality/closeness.ts +93 -194
- package/src/algorithms/centrality/degree.ts +18 -22
- package/src/algorithms/centrality/delta-pagerank-simple.ts +374 -0
- package/src/algorithms/centrality/delta-pagerank.ts +458 -0
- package/src/algorithms/centrality/eigenvector.ts +14 -15
- package/src/algorithms/centrality/hits.ts +17 -17
- package/src/algorithms/centrality/index.ts +20 -13
- package/src/algorithms/centrality/katz.ts +17 -25
- package/src/algorithms/centrality/pagerank.ts +91 -16
- package/src/algorithms/community/girvan-newman.ts +90 -86
- package/src/algorithms/community/index.ts +6 -5
- package/src/algorithms/community/label-propagation.ts +69 -48
- package/src/algorithms/community/leiden.ts +88 -65
- package/src/algorithms/community/louvain-optimized.ts +474 -0
- package/src/algorithms/community/louvain.ts +52 -122
- package/src/algorithms/community/modularity-utils.ts +134 -0
- package/src/algorithms/components/connected.ts +40 -17
- package/src/algorithms/matching/bipartite.ts +24 -53
- 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 -28
- package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +248 -0
- package/src/algorithms/shortest-path/dijkstra.ts +38 -30
- 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 +437 -0
- package/src/algorithms/traversal/bfs-variants.ts +520 -0
- package/src/algorithms/traversal/bfs.ts +5 -229
- package/src/algorithms/traversal/dfs.ts +61 -42
- package/src/algorithms/traversal/index.ts +3 -3
- package/src/benchmark-all-algorithms.ts +580 -0
- package/src/clustering/hierarchical.ts +268 -272
- package/src/clustering/index.ts +8 -6
- package/src/clustering/k-core.ts +93 -61
- package/src/clustering/mcl.ts +53 -23
- package/src/clustering/spectral.ts +130 -72
- package/src/core/graph.ts +58 -18
- 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 +221 -262
- package/src/flow/min-cut.ts +59 -51
- package/src/index.ts +9 -2
- package/src/link-prediction/adamic-adar.ts +75 -74
- package/src/link-prediction/common-neighbors.ts +49 -49
- package/src/link-prediction/index.ts +1 -1
- package/src/optimized/bit-packed.ts +390 -0
- package/src/optimized/csr-graph.ts +518 -0
- package/src/optimized/direction-optimized-bfs.ts +310 -0
- package/src/optimized/graph-adapter.ts +248 -0
- package/src/optimized/index.ts +34 -0
- package/src/pathfinding/astar.ts +40 -25
- package/src/pathfinding/utils.ts +20 -13
- package/src/research/grsbm.ts +36 -39
- package/src/research/index.ts +4 -4
- package/src/research/sync.ts +41 -54
- package/src/research/terahac.ts +63 -21
- package/src/types/index.ts +8 -0
- package/src/utils/algorithm-utilities.ts +2 -0
- package/src/utils/graph-converters.ts +269 -0
- package/src/utils/graph-utilities.ts +173 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/math-utilities.ts +149 -0
- package/src/utils/matrix-utilities.ts +2 -0
- package/src/utils/optimization-helpers.ts +87 -0
- package/src/utils/priorityQueue.ts +40 -6
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {Graph} from "../core/graph.js";
|
|
2
|
-
import type {NodeId} from "../types/index.js";
|
|
1
|
+
import type { Graph } from "../core/graph.js";
|
|
2
|
+
import type { NodeId } from "../types/index.js";
|
|
3
|
+
import { getCommonNeighbors, getIntermediateNodes } from "../utils/graph-utilities.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Common Neighbors link prediction implementation
|
|
@@ -26,6 +27,11 @@ export interface LinkPredictionOptions {
|
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Calculate common neighbors score for a pair of nodes
|
|
30
|
+
* @param graph - The input graph
|
|
31
|
+
* @param source - The source node ID
|
|
32
|
+
* @param target - The target node ID
|
|
33
|
+
* @param options - Link prediction options
|
|
34
|
+
* @returns The number of common neighbors
|
|
29
35
|
*/
|
|
30
36
|
export function commonNeighborsScore(
|
|
31
37
|
graph: Graph,
|
|
@@ -37,39 +43,25 @@ export function commonNeighborsScore(
|
|
|
37
43
|
return 0;
|
|
38
44
|
}
|
|
39
45
|
|
|
40
|
-
const {directed = false} = options;
|
|
41
|
-
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
directed ? Array.from(graph.inNeighbors(target)) : Array.from(graph.neighbors(target)),
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
// Count common neighbors
|
|
51
|
-
let commonCount = 0;
|
|
52
|
-
for (const neighbor of sourceNeighbors) {
|
|
53
|
-
if (targetNeighbors.has(neighbor)) {
|
|
54
|
-
commonCount++;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
46
|
+
const { directed = false } = options;
|
|
47
|
+
|
|
48
|
+
// Use utility function to get common neighbors
|
|
49
|
+
// For directed graphs, we want intermediate nodes that form paths source->X->target
|
|
50
|
+
const commonNeighborsSet = directed
|
|
51
|
+
? getIntermediateNodes(graph, source, target)
|
|
52
|
+
: getCommonNeighbors(graph, source, target, false);
|
|
57
53
|
|
|
58
|
-
return
|
|
54
|
+
return commonNeighborsSet.size;
|
|
59
55
|
}
|
|
60
56
|
|
|
61
57
|
/**
|
|
62
58
|
* Calculate common neighbors scores for all possible node pairs
|
|
59
|
+
* @param graph - The input graph
|
|
60
|
+
* @param options - Link prediction options
|
|
61
|
+
* @returns Array of link prediction scores sorted by score descending
|
|
63
62
|
*/
|
|
64
|
-
export function commonNeighborsPrediction(
|
|
65
|
-
|
|
66
|
-
options: LinkPredictionOptions = {},
|
|
67
|
-
): LinkPredictionScore[] {
|
|
68
|
-
const {
|
|
69
|
-
directed = false,
|
|
70
|
-
includeExisting = false,
|
|
71
|
-
topK,
|
|
72
|
-
} = options;
|
|
63
|
+
export function commonNeighborsPrediction(graph: Graph, options: LinkPredictionOptions = {}): LinkPredictionScore[] {
|
|
64
|
+
const { directed = false, includeExisting = false, topK } = options;
|
|
73
65
|
|
|
74
66
|
const scores: LinkPredictionScore[] = [];
|
|
75
67
|
const nodes = Array.from(graph.nodes()).map((n) => n.id);
|
|
@@ -88,14 +80,14 @@ export function commonNeighborsPrediction(
|
|
|
88
80
|
continue;
|
|
89
81
|
}
|
|
90
82
|
|
|
91
|
-
const score = commonNeighborsScore(graph, source, target, {directed});
|
|
83
|
+
const score = commonNeighborsScore(graph, source, target, { directed });
|
|
92
84
|
|
|
93
85
|
if (score > 0) {
|
|
94
|
-
scores.push({source, target, score});
|
|
86
|
+
scores.push({ source, target, score });
|
|
95
87
|
|
|
96
88
|
// For undirected graphs, also add the reverse pair
|
|
97
89
|
if (!directed && source !== target) {
|
|
98
|
-
scores.push({source: target, target: source, score});
|
|
90
|
+
scores.push({ source: target, target: source, score });
|
|
99
91
|
}
|
|
100
92
|
}
|
|
101
93
|
}
|
|
@@ -114,6 +106,10 @@ export function commonNeighborsPrediction(
|
|
|
114
106
|
|
|
115
107
|
/**
|
|
116
108
|
* Calculate common neighbors scores for specific node pairs
|
|
109
|
+
* @param graph - The input graph
|
|
110
|
+
* @param pairs - Array of node ID pairs to calculate scores for
|
|
111
|
+
* @param options - Link prediction options
|
|
112
|
+
* @returns Array of link prediction scores for the specified pairs
|
|
117
113
|
*/
|
|
118
114
|
export function commonNeighborsForPairs(
|
|
119
115
|
graph: Graph,
|
|
@@ -129,22 +125,21 @@ export function commonNeighborsForPairs(
|
|
|
129
125
|
|
|
130
126
|
/**
|
|
131
127
|
* Get top candidates for link prediction for a specific node
|
|
128
|
+
* @param graph - The input graph
|
|
129
|
+
* @param node - The node ID to get candidates for
|
|
130
|
+
* @param options - Link prediction options with optional candidate list
|
|
131
|
+
* @returns Array of top link prediction candidates sorted by score descending
|
|
132
132
|
*/
|
|
133
133
|
export function getTopCandidatesForNode(
|
|
134
134
|
graph: Graph,
|
|
135
135
|
node: NodeId,
|
|
136
|
-
options: LinkPredictionOptions & {candidates?: NodeId[]} = {},
|
|
136
|
+
options: LinkPredictionOptions & { candidates?: NodeId[] } = {},
|
|
137
137
|
): LinkPredictionScore[] {
|
|
138
138
|
if (!graph.hasNode(node)) {
|
|
139
139
|
return [];
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
const {
|
|
143
|
-
directed = false,
|
|
144
|
-
includeExisting = false,
|
|
145
|
-
topK = 10,
|
|
146
|
-
candidates,
|
|
147
|
-
} = options;
|
|
142
|
+
const { directed = false, includeExisting = false, topK = 10, candidates } = options;
|
|
148
143
|
|
|
149
144
|
const scores: LinkPredictionScore[] = [];
|
|
150
145
|
const targetNodes = candidates ?? Array.from(graph.nodes()).map((n) => n.id);
|
|
@@ -159,10 +154,10 @@ export function getTopCandidatesForNode(
|
|
|
159
154
|
continue;
|
|
160
155
|
}
|
|
161
156
|
|
|
162
|
-
const score = commonNeighborsScore(graph, node, target, {directed});
|
|
157
|
+
const score = commonNeighborsScore(graph, node, target, { directed });
|
|
163
158
|
|
|
164
159
|
if (score > 0) {
|
|
165
|
-
scores.push({source: node, target, score});
|
|
160
|
+
scores.push({ source: node, target, score });
|
|
166
161
|
}
|
|
167
162
|
}
|
|
168
163
|
|
|
@@ -174,6 +169,11 @@ export function getTopCandidatesForNode(
|
|
|
174
169
|
|
|
175
170
|
/**
|
|
176
171
|
* Calculate precision and recall for link prediction evaluation
|
|
172
|
+
* @param trainingGraph - The training graph without test edges
|
|
173
|
+
* @param testEdges - Array of node pairs that are actual edges
|
|
174
|
+
* @param nonEdges - Array of node pairs that are not edges
|
|
175
|
+
* @param options - Link prediction options
|
|
176
|
+
* @returns Evaluation metrics including precision, recall, F1 score, and AUC
|
|
177
177
|
*/
|
|
178
178
|
export function evaluateCommonNeighbors(
|
|
179
179
|
trainingGraph: Graph,
|
|
@@ -181,19 +181,19 @@ export function evaluateCommonNeighbors(
|
|
|
181
181
|
nonEdges: [NodeId, NodeId][],
|
|
182
182
|
options: LinkPredictionOptions = {},
|
|
183
183
|
): {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
184
|
+
precision: number;
|
|
185
|
+
recall: number;
|
|
186
|
+
f1Score: number;
|
|
187
|
+
auc: number;
|
|
188
|
+
} {
|
|
189
189
|
// Get scores for test edges and non-edges
|
|
190
190
|
const testScores = commonNeighborsForPairs(trainingGraph, testEdges, options);
|
|
191
191
|
const nonEdgeScores = commonNeighborsForPairs(trainingGraph, nonEdges, options);
|
|
192
192
|
|
|
193
193
|
// Combine and sort all scores
|
|
194
194
|
const allScores = [
|
|
195
|
-
...
|
|
196
|
-
...
|
|
195
|
+
...testScores.map((s) => ({ ...s, isActualEdge: true })),
|
|
196
|
+
...nonEdgeScores.map((s) => ({ ...s, isActualEdge: false })),
|
|
197
197
|
].sort((a, b) => b.score - a.score);
|
|
198
198
|
|
|
199
199
|
// Calculate precision and recall at different thresholds
|
|
@@ -214,7 +214,7 @@ export function evaluateCommonNeighbors(
|
|
|
214
214
|
|
|
215
215
|
const precision = truePositives / (truePositives + falsePositives);
|
|
216
216
|
const recall = truePositives / totalPositives;
|
|
217
|
-
const f1 = precision + recall > 0 ? 2 * (precision * recall) / (precision + recall) : 0;
|
|
217
|
+
const f1 = precision + recall > 0 ? (2 * (precision * recall)) / (precision + recall) : 0;
|
|
218
218
|
|
|
219
219
|
if (f1 > bestF1) {
|
|
220
220
|
bestF1 = f1;
|
|
@@ -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,
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import { TypedFastBitSet } from "typedfastbitset";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wrapper around TypedFastBitSet with graph-specific optimizations
|
|
5
|
+
*
|
|
6
|
+
* Provides efficient bit-packed set operations optimized for graph algorithms
|
|
7
|
+
* with 8x memory reduction compared to standard JavaScript Set for boolean values.
|
|
8
|
+
*/
|
|
9
|
+
export class GraphBitSet {
|
|
10
|
+
private bitset: TypedFastBitSet;
|
|
11
|
+
private _cardinality = 0;
|
|
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
|
+
*/
|
|
17
|
+
constructor(capacity?: number) {
|
|
18
|
+
this.bitset = new TypedFastBitSet();
|
|
19
|
+
if (capacity) {
|
|
20
|
+
// Pre-allocate for known size
|
|
21
|
+
this.bitset.resize(capacity);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Add a single element to the set.
|
|
27
|
+
* @param index - The element index to add
|
|
28
|
+
*/
|
|
29
|
+
add(index: number): void {
|
|
30
|
+
if (!this.bitset.has(index)) {
|
|
31
|
+
this.bitset.add(index);
|
|
32
|
+
this._cardinality++;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Remove a single element from the set.
|
|
38
|
+
* @param index - The element index to remove
|
|
39
|
+
*/
|
|
40
|
+
remove(index: number): void {
|
|
41
|
+
if (this.bitset.has(index)) {
|
|
42
|
+
this.bitset.remove(index);
|
|
43
|
+
this._cardinality--;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
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
|
+
*/
|
|
52
|
+
has(index: number): boolean {
|
|
53
|
+
return this.bitset.has(index);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Clear all elements
|
|
58
|
+
*/
|
|
59
|
+
clear(): void {
|
|
60
|
+
this.bitset.clear();
|
|
61
|
+
this._cardinality = 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Check if the set is empty.
|
|
66
|
+
* @returns True if the set contains no elements, false otherwise
|
|
67
|
+
*/
|
|
68
|
+
isEmpty(): boolean {
|
|
69
|
+
return this._cardinality === 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
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
|
+
*/
|
|
77
|
+
addRange(start: number, end: number): void {
|
|
78
|
+
for (let i = start; i < end; i++) {
|
|
79
|
+
if (!this.bitset.has(i)) {
|
|
80
|
+
this.bitset.add(i);
|
|
81
|
+
this._cardinality++;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Fast cardinality tracking - get the number of elements in the set.
|
|
88
|
+
* @returns The number of elements in the set
|
|
89
|
+
*/
|
|
90
|
+
size(): number {
|
|
91
|
+
return this._cardinality;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Batch operations for frontier management - swap contents with another GraphBitSet.
|
|
96
|
+
* @param other - The GraphBitSet to swap contents with
|
|
97
|
+
*/
|
|
98
|
+
swap(other: GraphBitSet): void {
|
|
99
|
+
[this.bitset, other.bitset] = [other.bitset, this.bitset];
|
|
100
|
+
[this._cardinality, other._cardinality] = [other._cardinality, this._cardinality];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Efficient iteration over all elements in the set.
|
|
105
|
+
* @yields The indices of elements in the set
|
|
106
|
+
*/
|
|
107
|
+
*[Symbol.iterator](): Generator<number> {
|
|
108
|
+
// Use TypedFastBitSet's optimized iteration
|
|
109
|
+
yield* this.bitset;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Perform union operation with another GraphBitSet, updating this set in place.
|
|
114
|
+
* @param other - The GraphBitSet to union with
|
|
115
|
+
*/
|
|
116
|
+
union(other: GraphBitSet): void {
|
|
117
|
+
const result = this.bitset.union(other.bitset);
|
|
118
|
+
this.bitset = result;
|
|
119
|
+
|
|
120
|
+
const size = this.bitset.size();
|
|
121
|
+
this._cardinality = size;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Perform intersection operation with another GraphBitSet, updating this set in place.
|
|
126
|
+
* @param other - The GraphBitSet to intersect with
|
|
127
|
+
*/
|
|
128
|
+
intersection(other: GraphBitSet): void {
|
|
129
|
+
const result = this.bitset.intersection(other.bitset);
|
|
130
|
+
this.bitset = result;
|
|
131
|
+
|
|
132
|
+
const size = this.bitset.size();
|
|
133
|
+
this._cardinality = size;
|
|
134
|
+
}
|
|
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
|
+
*/
|
|
140
|
+
difference(other: GraphBitSet): void {
|
|
141
|
+
const result = this.bitset.difference(other.bitset);
|
|
142
|
+
this.bitset = result;
|
|
143
|
+
|
|
144
|
+
const size = this.bitset.size();
|
|
145
|
+
this._cardinality = size;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Clone the bitset.
|
|
150
|
+
* @returns A new GraphBitSet with the same elements
|
|
151
|
+
*/
|
|
152
|
+
clone(): GraphBitSet {
|
|
153
|
+
const cloned = new GraphBitSet();
|
|
154
|
+
cloned.bitset = this.bitset.clone();
|
|
155
|
+
|
|
156
|
+
cloned._cardinality = this._cardinality;
|
|
157
|
+
return cloned;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Specialized bit array for visited tracking
|
|
163
|
+
*
|
|
164
|
+
* More memory efficient than GraphBitSet for simple boolean arrays
|
|
165
|
+
* that don't need set operations.
|
|
166
|
+
*/
|
|
167
|
+
export class VisitedBitArray {
|
|
168
|
+
private words: Uint32Array;
|
|
169
|
+
private wordCount: number;
|
|
170
|
+
private _size: number;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Creates a new VisitedBitArray with the specified size.
|
|
174
|
+
* @param size - The number of bits to allocate
|
|
175
|
+
*/
|
|
176
|
+
constructor(size: number) {
|
|
177
|
+
this._size = size;
|
|
178
|
+
this.wordCount = Math.ceil(size / 32);
|
|
179
|
+
this.words = new Uint32Array(this.wordCount);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Set bit at the specified index.
|
|
184
|
+
* @param index - The bit index to set
|
|
185
|
+
*/
|
|
186
|
+
set(index: number): void {
|
|
187
|
+
if (index < 0 || index >= this._size) {
|
|
188
|
+
throw new Error(`Index ${String(index)} out of bounds [0, ${String(this._size)})`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const wordIndex = index >>> 5; // divide by 32
|
|
192
|
+
const bitIndex = index & 31; // modulo 32
|
|
193
|
+
const word = this.words[wordIndex];
|
|
194
|
+
if (word !== undefined) {
|
|
195
|
+
this.words[wordIndex] = word | (1 << bitIndex);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
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
|
+
*/
|
|
204
|
+
get(index: number): boolean {
|
|
205
|
+
if (index < 0 || index >= this._size) {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const wordIndex = index >>> 5;
|
|
210
|
+
const bitIndex = index & 31;
|
|
211
|
+
const word = this.words[wordIndex];
|
|
212
|
+
return word !== undefined && (word & (1 << bitIndex)) !== 0;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Clear all bits
|
|
217
|
+
*/
|
|
218
|
+
clear(): void {
|
|
219
|
+
this.words.fill(0);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Toggle bit at the specified index.
|
|
224
|
+
* @param index - The bit index to toggle
|
|
225
|
+
*/
|
|
226
|
+
toggle(index: number): void {
|
|
227
|
+
if (index < 0 || index >= this._size) {
|
|
228
|
+
throw new Error(`Index ${String(index)} out of bounds [0, ${String(this._size)})`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const wordIndex = index >>> 5;
|
|
232
|
+
const bitIndex = index & 31;
|
|
233
|
+
const word = this.words[wordIndex];
|
|
234
|
+
if (word !== undefined) {
|
|
235
|
+
this.words[wordIndex] = word ^ (1 << bitIndex);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Population count for statistics - count the number of set bits.
|
|
241
|
+
* @returns The number of bits set to 1
|
|
242
|
+
*/
|
|
243
|
+
popcount(): number {
|
|
244
|
+
let count = 0;
|
|
245
|
+
for (let i = 0; i < this.wordCount; i++) {
|
|
246
|
+
const word = this.words[i];
|
|
247
|
+
if (word !== undefined) {
|
|
248
|
+
count += this.popcountWord(word);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return count;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
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
|
+
*/
|
|
260
|
+
private popcountWord(n: number): number {
|
|
261
|
+
let x = n;
|
|
262
|
+
x = x - ((x >>> 1) & 0x55555555);
|
|
263
|
+
x = (x & 0x33333333) + ((x >>> 2) & 0x33333333);
|
|
264
|
+
return (((x + (x >>> 4)) & 0xf0f0f0f) * 0x1010101) >>> 24;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Get size of the bit array.
|
|
269
|
+
* @returns The total number of bits in the array
|
|
270
|
+
*/
|
|
271
|
+
size(): number {
|
|
272
|
+
return this._size;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Check if all bits are zero.
|
|
277
|
+
* @returns True if no bits are set, false otherwise
|
|
278
|
+
*/
|
|
279
|
+
isEmpty(): boolean {
|
|
280
|
+
for (let i = 0; i < this.wordCount; i++) {
|
|
281
|
+
if (this.words[i] !== 0) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Set multiple bits from an array of indices.
|
|
290
|
+
* @param indices - Array of bit indices to set
|
|
291
|
+
*/
|
|
292
|
+
setMultiple(indices: number[]): void {
|
|
293
|
+
for (const index of indices) {
|
|
294
|
+
this.set(index);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Get indices of all set bits.
|
|
300
|
+
* @returns Array containing the indices of all bits that are set to 1
|
|
301
|
+
*/
|
|
302
|
+
getSetIndices(): number[] {
|
|
303
|
+
const indices: number[] = [];
|
|
304
|
+
for (let wordIndex = 0; wordIndex < this.wordCount; wordIndex++) {
|
|
305
|
+
const word = this.words[wordIndex];
|
|
306
|
+
if (!word || word === 0) {
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
for (let bitIndex = 0; bitIndex < 32; bitIndex++) {
|
|
311
|
+
if (word & (1 << bitIndex)) {
|
|
312
|
+
const index = (wordIndex << 5) + bitIndex;
|
|
313
|
+
if (index < this._size) {
|
|
314
|
+
indices.push(index);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return indices;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Bit-packed distance array for BFS
|
|
325
|
+
*
|
|
326
|
+
* Optimized for storing distances using 16-bit integers (up to 65,535 levels)
|
|
327
|
+
* Still provides 2x memory savings compared to standard 32-bit numbers
|
|
328
|
+
*/
|
|
329
|
+
export class CompactDistanceArray {
|
|
330
|
+
private data: Uint16Array;
|
|
331
|
+
private _size: number;
|
|
332
|
+
private static readonly INFINITY = 65535;
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Creates a new CompactDistanceArray with the specified size.
|
|
336
|
+
* @param size - The number of distance values to store
|
|
337
|
+
*/
|
|
338
|
+
constructor(size: number) {
|
|
339
|
+
this._size = size;
|
|
340
|
+
this.data = new Uint16Array(size);
|
|
341
|
+
this.data.fill(CompactDistanceArray.INFINITY); // Initialize with max value (unvisited)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
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
|
+
*/
|
|
349
|
+
set(index: number, distance: number): void {
|
|
350
|
+
if (distance >= CompactDistanceArray.INFINITY) {
|
|
351
|
+
throw new Error(`Distance exceeds maximum value (${String(CompactDistanceArray.INFINITY - 1)})`);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
this.data[index] = distance;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
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
|
+
*/
|
|
362
|
+
get(index: number): number {
|
|
363
|
+
const value = this.data[index];
|
|
364
|
+
return value ?? CompactDistanceArray.INFINITY; // Default to unvisited
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
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
|
+
*/
|
|
372
|
+
isVisited(index: number): boolean {
|
|
373
|
+
return this.data[index] !== CompactDistanceArray.INFINITY;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Reset all distances to unvisited state.
|
|
378
|
+
*/
|
|
379
|
+
clear(): void {
|
|
380
|
+
this.data.fill(CompactDistanceArray.INFINITY);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Get the size of the distance array.
|
|
385
|
+
* @returns The number of elements in the array
|
|
386
|
+
*/
|
|
387
|
+
size(): number {
|
|
388
|
+
return this._size;
|
|
389
|
+
}
|
|
390
|
+
}
|