@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
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {CentralityOptions, CentralityResult} from "../../types/index.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { CentralityOptions, CentralityResult } from "../../types/index.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Eigenvector centrality implementation
|
|
@@ -19,19 +19,14 @@ export interface EigenvectorCentralityOptions extends CentralityOptions {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* Calculate eigenvector centrality for all nodes in the graph
|
|
23
|
-
* Uses the power iteration method to find the dominant eigenvector
|
|
22
|
+
* Calculate eigenvector centrality for all nodes in the graph.
|
|
23
|
+
* Uses the power iteration method to find the dominant eigenvector.
|
|
24
|
+
* @param graph - The graph to compute eigenvector centrality on
|
|
25
|
+
* @param options - Configuration options for the computation
|
|
26
|
+
* @returns Object mapping node IDs to their eigenvector centrality scores
|
|
24
27
|
*/
|
|
25
|
-
export function eigenvectorCentrality(
|
|
26
|
-
|
|
27
|
-
options: EigenvectorCentralityOptions = {},
|
|
28
|
-
): CentralityResult {
|
|
29
|
-
const {
|
|
30
|
-
maxIterations = 100,
|
|
31
|
-
tolerance = 1e-6,
|
|
32
|
-
normalized = true,
|
|
33
|
-
startVector,
|
|
34
|
-
} = options;
|
|
28
|
+
export function eigenvectorCentrality(graph: Graph, options: EigenvectorCentralityOptions = {}): CentralityResult {
|
|
29
|
+
const { maxIterations = 100, tolerance = 1e-6, normalized = true, startVector } = options;
|
|
35
30
|
|
|
36
31
|
const centrality: CentralityResult = {};
|
|
37
32
|
const nodes = Array.from(graph.nodes());
|
|
@@ -146,7 +141,11 @@ export function eigenvectorCentrality(
|
|
|
146
141
|
}
|
|
147
142
|
|
|
148
143
|
/**
|
|
149
|
-
* Calculate eigenvector centrality for a specific node
|
|
144
|
+
* Calculate eigenvector centrality for a specific node.
|
|
145
|
+
* @param graph - The graph to compute eigenvector centrality on
|
|
146
|
+
* @param nodeId - The ID of the node to calculate centrality for
|
|
147
|
+
* @param options - Configuration options for the computation
|
|
148
|
+
* @returns The eigenvector centrality score for the specified node
|
|
150
149
|
*/
|
|
151
150
|
export function nodeEigenvectorCentrality(
|
|
152
151
|
graph: Graph,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {CentralityOptions} from "../../types/index.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { CentralityOptions } from "../../types/index.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* HITS (Hyperlink-Induced Topic Search) algorithm implementation
|
|
@@ -25,18 +25,14 @@ export interface HITSOptions extends CentralityOptions {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* Calculate HITS hub and authority scores for all nodes in the graph
|
|
29
|
-
* Uses iterative method with normalization
|
|
28
|
+
* Calculate HITS hub and authority scores for all nodes in the graph.
|
|
29
|
+
* Uses iterative method with normalization.
|
|
30
|
+
* @param graph - The graph to compute HITS scores on
|
|
31
|
+
* @param options - Configuration options for the computation
|
|
32
|
+
* @returns Object containing hub and authority scores for all nodes
|
|
30
33
|
*/
|
|
31
|
-
export function hits(
|
|
32
|
-
|
|
33
|
-
options: HITSOptions = {},
|
|
34
|
-
): HITSResult {
|
|
35
|
-
const {
|
|
36
|
-
maxIterations = 100,
|
|
37
|
-
tolerance = 1e-6,
|
|
38
|
-
normalized = true,
|
|
39
|
-
} = options;
|
|
34
|
+
export function hits(graph: Graph, options: HITSOptions = {}): HITSResult {
|
|
35
|
+
const { maxIterations = 100, tolerance = 1e-6, normalized = true } = options;
|
|
40
36
|
|
|
41
37
|
const hubs: Record<string, number> = {};
|
|
42
38
|
const authorities: Record<string, number> = {};
|
|
@@ -45,7 +41,7 @@ export function hits(
|
|
|
45
41
|
const nodeIds = nodes.map((node) => node.id);
|
|
46
42
|
|
|
47
43
|
if (nodeIds.length === 0) {
|
|
48
|
-
return {hubs, authorities};
|
|
44
|
+
return { hubs, authorities };
|
|
49
45
|
}
|
|
50
46
|
|
|
51
47
|
// Initialize scores
|
|
@@ -185,17 +181,21 @@ export function hits(
|
|
|
185
181
|
}
|
|
186
182
|
}
|
|
187
183
|
|
|
188
|
-
return {hubs, authorities};
|
|
184
|
+
return { hubs, authorities };
|
|
189
185
|
}
|
|
190
186
|
|
|
191
187
|
/**
|
|
192
|
-
* Calculate HITS scores for a specific node
|
|
188
|
+
* Calculate HITS scores for a specific node.
|
|
189
|
+
* @param graph - The graph to compute HITS scores on
|
|
190
|
+
* @param nodeId - The ID of the node to calculate scores for
|
|
191
|
+
* @param options - Configuration options for the computation
|
|
192
|
+
* @returns Object containing hub and authority scores for the specified node
|
|
193
193
|
*/
|
|
194
194
|
export function nodeHITS(
|
|
195
195
|
graph: Graph,
|
|
196
196
|
nodeId: string | number,
|
|
197
197
|
options: HITSOptions = {},
|
|
198
|
-
): {hub: number
|
|
198
|
+
): { hub: number; authority: number } {
|
|
199
199
|
if (!graph.hasNode(nodeId)) {
|
|
200
200
|
throw new Error(`Node ${String(nodeId)} not found in graph`);
|
|
201
201
|
}
|
|
@@ -2,18 +2,23 @@
|
|
|
2
2
|
* Centrality algorithms
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export type {BetweennessCentralityOptions} from "./betweenness.js";
|
|
6
|
-
export {betweennessCentrality, edgeBetweennessCentrality, nodeBetweennessCentrality} from "./betweenness.js";
|
|
7
|
-
export type {ClosenessCentralityOptions} from "./closeness.js";
|
|
8
|
-
export {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export
|
|
15
|
-
export {
|
|
16
|
-
export
|
|
17
|
-
export {
|
|
18
|
-
export
|
|
19
|
-
export {
|
|
5
|
+
export type { BetweennessCentralityOptions } from "./betweenness.js";
|
|
6
|
+
export { betweennessCentrality, edgeBetweennessCentrality, nodeBetweennessCentrality } from "./betweenness.js";
|
|
7
|
+
export type { ClosenessCentralityOptions } from "./closeness.js";
|
|
8
|
+
export {
|
|
9
|
+
closenessCentrality,
|
|
10
|
+
nodeClosenessCentrality,
|
|
11
|
+
nodeWeightedClosenessCentrality,
|
|
12
|
+
weightedClosenessCentrality,
|
|
13
|
+
} from "./closeness.js";
|
|
14
|
+
export { degreeCentrality, nodeDegreeCentrality } from "./degree.js";
|
|
15
|
+
export type { DeltaPageRankOptions } from "./delta-pagerank.js";
|
|
16
|
+
export { DeltaPageRank, PriorityDeltaPageRank } from "./delta-pagerank.js";
|
|
17
|
+
export type { EigenvectorCentralityOptions } from "./eigenvector.js";
|
|
18
|
+
export { eigenvectorCentrality, nodeEigenvectorCentrality } from "./eigenvector.js";
|
|
19
|
+
export type { HITSOptions, HITSResult } from "./hits.js";
|
|
20
|
+
export { hits, nodeHITS } from "./hits.js";
|
|
21
|
+
export type { KatzCentralityOptions } from "./katz.js";
|
|
22
|
+
export { katzCentrality, nodeKatzCentrality } from "./katz.js";
|
|
23
|
+
export type { PageRankOptions, PageRankResult } from "./pagerank.js";
|
|
24
|
+
export { pageRank, pageRankCentrality, personalizedPageRank, topPageRankNodes } from "./pagerank.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {CentralityOptions, CentralityResult} from "../../types/index.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { CentralityOptions, CentralityResult } from "../../types/index.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Katz centrality implementation
|
|
@@ -22,20 +22,14 @@ export interface KatzCentralityOptions extends CentralityOptions {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* Calculate Katz centrality for all nodes in the graph
|
|
26
|
-
* Uses iterative method to compute centrality scores
|
|
25
|
+
* Calculate Katz centrality for all nodes in the graph.
|
|
26
|
+
* Uses iterative method to compute centrality scores.
|
|
27
|
+
* @param graph - The graph to compute Katz centrality on
|
|
28
|
+
* @param options - Configuration options for the computation
|
|
29
|
+
* @returns Object mapping node IDs to their Katz centrality scores
|
|
27
30
|
*/
|
|
28
|
-
export function katzCentrality(
|
|
29
|
-
|
|
30
|
-
options: KatzCentralityOptions = {},
|
|
31
|
-
): CentralityResult {
|
|
32
|
-
const {
|
|
33
|
-
alpha = 0.1,
|
|
34
|
-
beta = 1.0,
|
|
35
|
-
maxIterations = 100,
|
|
36
|
-
tolerance = 1e-6,
|
|
37
|
-
normalized = true,
|
|
38
|
-
} = options;
|
|
31
|
+
export function katzCentrality(graph: Graph, options: KatzCentralityOptions = {}): CentralityResult {
|
|
32
|
+
const { alpha = 0.1, beta = 1.0, maxIterations = 100, tolerance = 1e-6, normalized = true } = options;
|
|
39
33
|
|
|
40
34
|
const centrality: CentralityResult = {};
|
|
41
35
|
const nodes = Array.from(graph.nodes());
|
|
@@ -68,16 +62,14 @@ export function katzCentrality(
|
|
|
68
62
|
|
|
69
63
|
// For directed graphs, use in-neighbors
|
|
70
64
|
// For undirected graphs, use all neighbors
|
|
71
|
-
const neighbors = graph.isDirected ?
|
|
72
|
-
Array.from(graph.inNeighbors(nodeId)) :
|
|
73
|
-
graph.neighbors(nodeId);
|
|
65
|
+
const neighbors = graph.isDirected ? Array.from(graph.inNeighbors(nodeId)) : graph.neighbors(nodeId);
|
|
74
66
|
|
|
75
67
|
for (const neighbor of neighbors) {
|
|
76
68
|
const neighborKey = neighbor.toString();
|
|
77
69
|
sum += previousScores.get(neighborKey) ?? 0;
|
|
78
70
|
}
|
|
79
71
|
|
|
80
|
-
currentScores.set(nodeId.toString(),
|
|
72
|
+
currentScores.set(nodeId.toString(), alpha * sum + beta);
|
|
81
73
|
}
|
|
82
74
|
|
|
83
75
|
// Check for convergence
|
|
@@ -123,13 +115,13 @@ export function katzCentrality(
|
|
|
123
115
|
}
|
|
124
116
|
|
|
125
117
|
/**
|
|
126
|
-
* Calculate Katz centrality for a specific node
|
|
118
|
+
* Calculate Katz centrality for a specific node.
|
|
119
|
+
* @param graph - The graph to compute Katz centrality on
|
|
120
|
+
* @param nodeId - The ID of the node to calculate centrality for
|
|
121
|
+
* @param options - Configuration options for the computation
|
|
122
|
+
* @returns The Katz centrality score for the specified node
|
|
127
123
|
*/
|
|
128
|
-
export function nodeKatzCentrality(
|
|
129
|
-
graph: Graph,
|
|
130
|
-
nodeId: string | number,
|
|
131
|
-
options: KatzCentralityOptions = {},
|
|
132
|
-
): number {
|
|
124
|
+
export function nodeKatzCentrality(graph: Graph, nodeId: string | number, options: KatzCentralityOptions = {}): number {
|
|
133
125
|
if (!graph.hasNode(nodeId)) {
|
|
134
126
|
throw new Error(`Node ${String(nodeId)} not found in graph`);
|
|
135
127
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {NodeId} from "../../types/index.js";
|
|
3
|
-
import {SimpleDeltaPageRank} from "./delta-pagerank-simple.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { NodeId } from "../../types/index.js";
|
|
3
|
+
import { SimpleDeltaPageRank } from "./delta-pagerank-simple.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* PageRank algorithm implementation
|
|
@@ -76,11 +76,11 @@ export interface PageRankResult {
|
|
|
76
76
|
*
|
|
77
77
|
* For initial computation on small-medium graphs, standard algorithm may be faster
|
|
78
78
|
* due to lower overhead.
|
|
79
|
+
* @param graph - The directed input graph to analyze
|
|
80
|
+
* @param options - Algorithm configuration options
|
|
81
|
+
* @returns PageRank result containing ranks, iteration count, and convergence status
|
|
79
82
|
*/
|
|
80
|
-
export function pageRank(
|
|
81
|
-
graph: Graph,
|
|
82
|
-
options: PageRankOptions = {},
|
|
83
|
-
): PageRankResult {
|
|
83
|
+
export function pageRank(graph: Graph, options: PageRankOptions = {}): PageRankResult {
|
|
84
84
|
const {
|
|
85
85
|
dampingFactor = 0.85,
|
|
86
86
|
maxIterations = 100,
|
|
@@ -102,7 +102,7 @@ export function pageRank(
|
|
|
102
102
|
const n = nodes.length;
|
|
103
103
|
|
|
104
104
|
if (n === 0) {
|
|
105
|
-
return {ranks: {}, iterations: 0, converged: true};
|
|
105
|
+
return { ranks: {}, iterations: 0, converged: true };
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
// Use delta-based optimization by default for larger graphs
|
|
@@ -221,7 +221,7 @@ export function pageRank(
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
if (danglingSum > 0) {
|
|
224
|
-
const danglingContribution = dampingFactor * danglingSum / n;
|
|
224
|
+
const danglingContribution = (dampingFactor * danglingSum) / n;
|
|
225
225
|
for (const nodeId of nodes) {
|
|
226
226
|
const currentRank = newRanks.get(nodeId) ?? 0;
|
|
227
227
|
if (personalVector) {
|
|
@@ -284,6 +284,10 @@ export function pageRank(
|
|
|
284
284
|
|
|
285
285
|
/**
|
|
286
286
|
* Calculate Personalized PageRank for a specific set of source nodes
|
|
287
|
+
* @param graph - The directed input graph to analyze
|
|
288
|
+
* @param personalNodes - Nodes to personalize the PageRank towards
|
|
289
|
+
* @param options - Algorithm configuration options
|
|
290
|
+
* @returns PageRank result containing ranks, iteration count, and convergence status
|
|
287
291
|
*/
|
|
288
292
|
export function personalizedPageRank(
|
|
289
293
|
graph: Graph,
|
|
@@ -314,35 +318,39 @@ export function personalizedPageRank(
|
|
|
314
318
|
}
|
|
315
319
|
|
|
316
320
|
return pageRank(graph, {
|
|
317
|
-
...
|
|
321
|
+
...options,
|
|
318
322
|
personalization,
|
|
319
323
|
});
|
|
320
324
|
}
|
|
321
325
|
|
|
322
326
|
/**
|
|
323
327
|
* Calculate PageRank centrality (normalized PageRank scores)
|
|
328
|
+
* @param graph - The directed input graph to analyze
|
|
329
|
+
* @param options - Algorithm configuration options
|
|
330
|
+
* @returns PageRank scores for each node keyed by node ID
|
|
324
331
|
*/
|
|
325
|
-
export function pageRankCentrality(
|
|
326
|
-
graph: Graph,
|
|
327
|
-
options: PageRankOptions = {},
|
|
328
|
-
): Record<string, number> {
|
|
332
|
+
export function pageRankCentrality(graph: Graph, options: PageRankOptions = {}): Record<string, number> {
|
|
329
333
|
const result = pageRank(graph, options);
|
|
330
334
|
return result.ranks;
|
|
331
335
|
}
|
|
332
336
|
|
|
333
337
|
/**
|
|
334
338
|
* Get the top-k nodes by PageRank score
|
|
339
|
+
* @param graph - The directed input graph to analyze
|
|
340
|
+
* @param k - Number of top nodes to return
|
|
341
|
+
* @param options - Algorithm configuration options
|
|
342
|
+
* @returns Array of top-k nodes with their PageRank scores, sorted descending
|
|
335
343
|
*/
|
|
336
344
|
export function topPageRankNodes(
|
|
337
345
|
graph: Graph,
|
|
338
346
|
k: number,
|
|
339
347
|
options: PageRankOptions = {},
|
|
340
|
-
): {node: NodeId
|
|
348
|
+
): { node: NodeId; rank: number }[] {
|
|
341
349
|
const result = pageRank(graph, options);
|
|
342
350
|
|
|
343
|
-
const nodeRanks: {node: NodeId
|
|
351
|
+
const nodeRanks: { node: NodeId; rank: number }[] = [];
|
|
344
352
|
for (const [nodeStr, rank] of Object.entries(result.ranks)) {
|
|
345
|
-
nodeRanks.push({node: nodeStr as NodeId, rank});
|
|
353
|
+
nodeRanks.push({ node: nodeStr as NodeId, rank });
|
|
346
354
|
}
|
|
347
355
|
|
|
348
356
|
// Sort by rank in descending order
|
|
@@ -353,6 +361,7 @@ export function topPageRankNodes(
|
|
|
353
361
|
|
|
354
362
|
/**
|
|
355
363
|
* Normalize ranks so they sum to 1
|
|
364
|
+
* @param ranks - The ranks map to normalize in place
|
|
356
365
|
*/
|
|
357
366
|
function normalizeRanks(ranks: Map<NodeId, number>): void {
|
|
358
367
|
let sum = 0;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {CommunityResult, ComponentResult, GirvanNewmanOptions, NodeId} from "../../types/index.js";
|
|
3
|
-
import {connectedComponents} from "../components/connected.js";
|
|
1
|
+
import { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { CommunityResult, ComponentResult, GirvanNewmanOptions, NodeId } from "../../types/index.js";
|
|
3
|
+
import { connectedComponents } from "../components/connected.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Girvan-Newman community detection algorithm
|
|
@@ -14,18 +14,14 @@ import {connectedComponents} from "../components/connected.js";
|
|
|
14
14
|
*
|
|
15
15
|
* References:
|
|
16
16
|
* - Girvan, M., & Newman, M. E. J. (2002). Community structure in social
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* and biological networks. Proceedings of the National Academy of Sciences,
|
|
18
|
+
* 99(12), 7821-7826.
|
|
20
19
|
* @param graph - The input graph
|
|
21
20
|
* @param options - Algorithm options
|
|
22
21
|
* @returns Array of community detection results representing the dendrogram
|
|
23
22
|
*/
|
|
24
|
-
export function girvanNewman(
|
|
25
|
-
|
|
26
|
-
options: GirvanNewmanOptions = {},
|
|
27
|
-
): CommunityResult[] {
|
|
28
|
-
const {maxCommunities} = options;
|
|
23
|
+
export function girvanNewman(graph: Graph, options: GirvanNewmanOptions = {}): CommunityResult[] {
|
|
24
|
+
const { maxCommunities } = options;
|
|
29
25
|
const minCommunitySize = options.minCommunitySize ?? 1;
|
|
30
26
|
const maxIterations = options.maxIterations ?? 100; // Prevent infinite loops
|
|
31
27
|
|
|
@@ -50,20 +46,20 @@ export function girvanNewman(
|
|
|
50
46
|
}
|
|
51
47
|
|
|
52
48
|
// Find edges with maximum betweenness
|
|
53
|
-
const maxBetweenness = Math.max(...
|
|
54
|
-
const edgesToRemove: {source: NodeId
|
|
49
|
+
const maxBetweenness = Math.max(...edgeBetweenness.values());
|
|
50
|
+
const edgesToRemove: { source: NodeId; target: NodeId }[] = [];
|
|
55
51
|
|
|
56
52
|
for (const [edgeKey, centrality] of edgeBetweenness) {
|
|
57
53
|
if (Math.abs(centrality - maxBetweenness) < 1e-10) {
|
|
58
54
|
const [source, target] = edgeKey.split("|");
|
|
59
55
|
if (source && target) {
|
|
60
|
-
edgesToRemove.push({source, target});
|
|
56
|
+
edgesToRemove.push({ source, target });
|
|
61
57
|
}
|
|
62
58
|
}
|
|
63
59
|
}
|
|
64
60
|
|
|
65
61
|
// Remove edges with highest betweenness
|
|
66
|
-
for (const {source, target} of edgesToRemove) {
|
|
62
|
+
for (const { source, target } of edgesToRemove) {
|
|
67
63
|
workingGraph.removeEdge(source, target);
|
|
68
64
|
}
|
|
69
65
|
|
|
@@ -71,9 +67,7 @@ export function girvanNewman(
|
|
|
71
67
|
components = getConnectedComponentsResult(workingGraph);
|
|
72
68
|
|
|
73
69
|
// Filter communities by minimum size
|
|
74
|
-
const validCommunities = components.components.filter(
|
|
75
|
-
(community) => community.length >= minCommunitySize,
|
|
76
|
-
);
|
|
70
|
+
const validCommunities = components.components.filter((community) => community.length >= minCommunitySize);
|
|
77
71
|
|
|
78
72
|
// Calculate modularity for the new community structure
|
|
79
73
|
const modularity = calculateModularity(graph, components.componentMap);
|
|
@@ -102,6 +96,8 @@ export function girvanNewman(
|
|
|
102
96
|
*
|
|
103
97
|
* Edge betweenness is the fraction of shortest paths that pass through the edge.
|
|
104
98
|
* We adapt node betweenness centrality calculation to work with edges.
|
|
99
|
+
* @param graph - The input graph to analyze
|
|
100
|
+
* @returns Map of edge keys to their betweenness centrality values
|
|
105
101
|
*/
|
|
106
102
|
function calculateEdgeBetweenness(graph: Graph): Map<string, number> {
|
|
107
103
|
const edgeBetweenness = new Map<string, number>();
|
|
@@ -117,7 +113,7 @@ function calculateEdgeBetweenness(graph: Graph): Map<string, number> {
|
|
|
117
113
|
const source = sourceNode.id;
|
|
118
114
|
|
|
119
115
|
// Run BFS to find all shortest paths from source
|
|
120
|
-
const {distances, predecessors, pathCounts} = findAllShortestPaths(graph, source);
|
|
116
|
+
const { distances, predecessors, pathCounts } = findAllShortestPaths(graph, source);
|
|
121
117
|
|
|
122
118
|
// Calculate dependency for each node and accumulate edge betweenness
|
|
123
119
|
const dependency = new Map<NodeId, number>();
|
|
@@ -191,8 +187,14 @@ function calculateEdgeBetweenness(graph: Graph): Map<string, number> {
|
|
|
191
187
|
|
|
192
188
|
/**
|
|
193
189
|
* Find all shortest paths from a source node using optimized BFS
|
|
190
|
+
* @param graph - The input graph to search
|
|
191
|
+
* @param source - The source node to compute shortest paths from
|
|
192
|
+
* @returns Object containing distances, predecessors, and path counts
|
|
194
193
|
*/
|
|
195
|
-
function findAllShortestPaths(
|
|
194
|
+
function findAllShortestPaths(
|
|
195
|
+
graph: Graph,
|
|
196
|
+
source: NodeId,
|
|
197
|
+
): {
|
|
196
198
|
distances: Map<NodeId, number>;
|
|
197
199
|
predecessors: Map<NodeId, NodeId[]>;
|
|
198
200
|
pathCounts: Map<NodeId, number>;
|
|
@@ -262,11 +264,14 @@ function findAllShortestPaths(graph: Graph, source: NodeId): {
|
|
|
262
264
|
}
|
|
263
265
|
}
|
|
264
266
|
|
|
265
|
-
return {distances, predecessors, pathCounts};
|
|
267
|
+
return { distances, predecessors, pathCounts };
|
|
266
268
|
}
|
|
267
269
|
|
|
268
270
|
/**
|
|
269
271
|
* Generate a consistent edge key for undirected graphs
|
|
272
|
+
* @param source - The source node ID
|
|
273
|
+
* @param target - The target node ID
|
|
274
|
+
* @returns A consistent string key for the edge (ordered alphabetically)
|
|
270
275
|
*/
|
|
271
276
|
function getEdgeKey(source: NodeId, target: NodeId): string {
|
|
272
277
|
// For undirected graphs, ensure consistent ordering
|
|
@@ -282,11 +287,11 @@ function getEdgeKey(source: NodeId, target: NodeId): string {
|
|
|
282
287
|
|
|
283
288
|
/**
|
|
284
289
|
* Calculate modularity for a given community structure - optimized version
|
|
290
|
+
* @param graph - The original graph
|
|
291
|
+
* @param communityMap - Map from node IDs to community indices
|
|
292
|
+
* @returns The modularity score of the partition
|
|
285
293
|
*/
|
|
286
|
-
function calculateModularity(
|
|
287
|
-
graph: Graph,
|
|
288
|
-
communityMap: Map<NodeId, number>,
|
|
289
|
-
): number {
|
|
294
|
+
function calculateModularity(graph: Graph, communityMap: Map<NodeId, number>): number {
|
|
290
295
|
const totalEdgeWeight = getTotalEdgeWeight(graph);
|
|
291
296
|
if (totalEdgeWeight === 0) {
|
|
292
297
|
return 0;
|
|
@@ -313,7 +318,7 @@ function calculateModularity(
|
|
|
313
318
|
continue;
|
|
314
319
|
}
|
|
315
320
|
|
|
316
|
-
modularity += edgeWeight - (
|
|
321
|
+
modularity += edgeWeight - (degreeI * degreeJ) / (2 * totalEdgeWeight);
|
|
317
322
|
}
|
|
318
323
|
}
|
|
319
324
|
|
|
@@ -322,6 +327,8 @@ function calculateModularity(
|
|
|
322
327
|
|
|
323
328
|
/**
|
|
324
329
|
* Calculate total edge weight in the graph
|
|
330
|
+
* @param graph - The input graph
|
|
331
|
+
* @returns Total sum of all edge weights
|
|
325
332
|
*/
|
|
326
333
|
function getTotalEdgeWeight(graph: Graph): number {
|
|
327
334
|
let totalWeight = 0;
|
|
@@ -335,6 +342,9 @@ function getTotalEdgeWeight(graph: Graph): number {
|
|
|
335
342
|
|
|
336
343
|
/**
|
|
337
344
|
* Get the total degree (sum of edge weights) for a node
|
|
345
|
+
* @param graph - The input graph
|
|
346
|
+
* @param nodeId - The node ID to compute degree for
|
|
347
|
+
* @returns The weighted degree of the node
|
|
338
348
|
*/
|
|
339
349
|
function getNodeDegree(graph: Graph, nodeId: NodeId): number {
|
|
340
350
|
let degree = 0;
|
|
@@ -349,6 +359,8 @@ function getNodeDegree(graph: Graph, nodeId: NodeId): number {
|
|
|
349
359
|
|
|
350
360
|
/**
|
|
351
361
|
* Convert connected components result to ComponentResult format
|
|
362
|
+
* @param graph - The input graph
|
|
363
|
+
* @returns Object containing components array and node-to-component map
|
|
352
364
|
*/
|
|
353
365
|
function getConnectedComponentsResult(graph: Graph): ComponentResult {
|
|
354
366
|
const components = connectedComponents(graph);
|
|
@@ -360,6 +372,5 @@ function getConnectedComponentsResult(graph: Graph): ComponentResult {
|
|
|
360
372
|
});
|
|
361
373
|
});
|
|
362
374
|
|
|
363
|
-
return {components, componentMap};
|
|
375
|
+
return { components, componentMap };
|
|
364
376
|
}
|
|
365
|
-
|
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
* than with the rest of the network.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
export {girvanNewman} from "./girvan-newman.js";
|
|
10
|
-
export type {LabelPropagationOptions, LabelPropagationResult} from "./label-propagation.js";
|
|
11
|
-
export {labelPropagation, labelPropagationAsync, labelPropagationSemiSupervised} from "./label-propagation.js";
|
|
12
|
-
export type {LeidenOptions, LeidenResult} from "./leiden.js";
|
|
13
|
-
export {leiden} from "./leiden.js";
|
|
14
|
-
export {louvain} from "./louvain.js";
|
|
15
|
-
|
|
9
|
+
export { girvanNewman } from "./girvan-newman.js";
|
|
10
|
+
export type { LabelPropagationOptions, LabelPropagationResult } from "./label-propagation.js";
|
|
11
|
+
export { labelPropagation, labelPropagationAsync, labelPropagationSemiSupervised } from "./label-propagation.js";
|
|
12
|
+
export type { LeidenOptions, LeidenResult } from "./leiden.js";
|
|
13
|
+
export { leiden } from "./leiden.js";
|
|
14
|
+
export { louvain } from "./louvain.js";
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
* detect community structures in large-scale networks"
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import type {Graph} from "../../core/graph.js";
|
|
13
|
-
import {graphToMap} from "../../utils/graph-converters.js";
|
|
14
|
-
import {SeededRandom, shuffle} from "../../utils/math-utilities.js";
|
|
12
|
+
import type { Graph } from "../../core/graph.js";
|
|
13
|
+
import { graphToMap } from "../../utils/graph-converters.js";
|
|
14
|
+
import { SeededRandom, shuffle } from "../../utils/math-utilities.js";
|
|
15
15
|
|
|
16
16
|
export interface LabelPropagationOptions {
|
|
17
17
|
maxIterations?: number;
|
|
@@ -26,15 +26,15 @@ export interface LabelPropagationResult {
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Internal implementation of Label Propagation Algorithm
|
|
29
|
+
* @param graph - Map representation of the graph (node to neighbors with weights)
|
|
30
|
+
* @param options - Algorithm configuration options
|
|
31
|
+
* @returns Community assignments, iteration count, and convergence status
|
|
29
32
|
*/
|
|
30
33
|
function labelPropagationImpl(
|
|
31
34
|
graph: Map<string, Map<string, number>>,
|
|
32
35
|
options: LabelPropagationOptions = {},
|
|
33
36
|
): LabelPropagationResult {
|
|
34
|
-
const {
|
|
35
|
-
maxIterations = 100,
|
|
36
|
-
randomSeed = 42,
|
|
37
|
-
} = options;
|
|
37
|
+
const { maxIterations = 100, randomSeed = 42 } = options;
|
|
38
38
|
|
|
39
39
|
if (graph.size === 0) {
|
|
40
40
|
return {
|
|
@@ -61,7 +61,7 @@ function labelPropagationImpl(
|
|
|
61
61
|
converged = true;
|
|
62
62
|
|
|
63
63
|
// Create random order for node updates
|
|
64
|
-
const nodeOrder = [...
|
|
64
|
+
const nodeOrder = [...nodes];
|
|
65
65
|
shuffle(nodeOrder, random);
|
|
66
66
|
|
|
67
67
|
// Update each node's label
|
|
@@ -151,14 +151,15 @@ function labelPropagationImpl(
|
|
|
151
151
|
/**
|
|
152
152
|
* Internal implementation of Asynchronous Label Propagation
|
|
153
153
|
* Updates all nodes simultaneously (can lead to oscillations)
|
|
154
|
+
* @param graph - Map representation of the graph (node to neighbors with weights)
|
|
155
|
+
* @param options - Algorithm configuration options
|
|
156
|
+
* @returns Community assignments, iteration count, and convergence status
|
|
154
157
|
*/
|
|
155
158
|
function labelPropagationAsyncImpl(
|
|
156
159
|
graph: Map<string, Map<string, number>>,
|
|
157
160
|
options: LabelPropagationOptions = {},
|
|
158
161
|
): LabelPropagationResult {
|
|
159
|
-
const {
|
|
160
|
-
maxIterations = 100,
|
|
161
|
-
} = options;
|
|
162
|
+
const { maxIterations = 100 } = options;
|
|
162
163
|
|
|
163
164
|
if (graph.size === 0) {
|
|
164
165
|
return {
|
|
@@ -261,16 +262,17 @@ function labelPropagationAsyncImpl(
|
|
|
261
262
|
/**
|
|
262
263
|
* Internal implementation of Semi-supervised Label Propagation
|
|
263
264
|
* Some nodes have fixed labels that don't change
|
|
265
|
+
* @param graph - Map representation of the graph (node to neighbors with weights)
|
|
266
|
+
* @param seedLabels - Map of node IDs to their fixed community labels
|
|
267
|
+
* @param options - Algorithm configuration options
|
|
268
|
+
* @returns Community assignments, iteration count, and convergence status
|
|
264
269
|
*/
|
|
265
270
|
function labelPropagationSemiSupervisedImpl(
|
|
266
271
|
graph: Map<string, Map<string, number>>,
|
|
267
272
|
seedLabels: Map<string, number>,
|
|
268
273
|
options: LabelPropagationOptions = {},
|
|
269
274
|
): LabelPropagationResult {
|
|
270
|
-
const {
|
|
271
|
-
maxIterations = 100,
|
|
272
|
-
randomSeed = 42,
|
|
273
|
-
} = options;
|
|
275
|
+
const { maxIterations = 100, randomSeed = 42 } = options;
|
|
274
276
|
|
|
275
277
|
// Initialize random number generator
|
|
276
278
|
const random = SeededRandom.createGenerator(randomSeed);
|
|
@@ -278,7 +280,7 @@ function labelPropagationSemiSupervisedImpl(
|
|
|
278
280
|
// Initialize labels
|
|
279
281
|
const labels = new Map<string, number>();
|
|
280
282
|
const nodes = Array.from(graph.keys());
|
|
281
|
-
let labelCounter = Math.max(...
|
|
283
|
+
let labelCounter = Math.max(...Array.from(seedLabels.values())) + 1;
|
|
282
284
|
|
|
283
285
|
for (const node of nodes) {
|
|
284
286
|
if (seedLabels.has(node)) {
|
|
@@ -366,7 +368,6 @@ function labelPropagationSemiSupervisedImpl(
|
|
|
366
368
|
/**
|
|
367
369
|
* Label Propagation Algorithm
|
|
368
370
|
* Each node adopts the most frequent label among its neighbors
|
|
369
|
-
*
|
|
370
371
|
* @param graph - Undirected graph (can be weighted)
|
|
371
372
|
* @param options - Algorithm options
|
|
372
373
|
* @returns Community assignments
|
|
@@ -374,10 +375,7 @@ function labelPropagationSemiSupervisedImpl(
|
|
|
374
375
|
* Time Complexity: O(m) per iteration, typically O(km) for k iterations
|
|
375
376
|
* Space Complexity: O(n)
|
|
376
377
|
*/
|
|
377
|
-
export function labelPropagation(
|
|
378
|
-
graph: Graph,
|
|
379
|
-
options: LabelPropagationOptions = {},
|
|
380
|
-
): LabelPropagationResult {
|
|
378
|
+
export function labelPropagation(graph: Graph, options: LabelPropagationOptions = {}): LabelPropagationResult {
|
|
381
379
|
// Convert Graph to Map representation
|
|
382
380
|
const graphMap = graphToMap(graph);
|
|
383
381
|
return labelPropagationImpl(graphMap, options);
|
|
@@ -386,15 +384,11 @@ export function labelPropagation(
|
|
|
386
384
|
/**
|
|
387
385
|
* Asynchronous Label Propagation
|
|
388
386
|
* Updates all nodes simultaneously (can lead to oscillations)
|
|
389
|
-
*
|
|
390
387
|
* @param graph - Undirected graph (can be weighted)
|
|
391
388
|
* @param options - Algorithm options
|
|
392
389
|
* @returns Community assignments
|
|
393
390
|
*/
|
|
394
|
-
export function labelPropagationAsync(
|
|
395
|
-
graph: Graph,
|
|
396
|
-
options: LabelPropagationOptions = {},
|
|
397
|
-
): LabelPropagationResult {
|
|
391
|
+
export function labelPropagationAsync(graph: Graph, options: LabelPropagationOptions = {}): LabelPropagationResult {
|
|
398
392
|
// Convert Graph to Map representation
|
|
399
393
|
const graphMap = graphToMap(graph);
|
|
400
394
|
return labelPropagationAsyncImpl(graphMap, options);
|
|
@@ -403,7 +397,6 @@ export function labelPropagationAsync(
|
|
|
403
397
|
/**
|
|
404
398
|
* Semi-supervised Label Propagation
|
|
405
399
|
* Some nodes have fixed labels that don't change
|
|
406
|
-
*
|
|
407
400
|
* @param graph - Undirected graph (can be weighted)
|
|
408
401
|
* @param seedLabels - Initial fixed labels for some nodes
|
|
409
402
|
* @param options - Algorithm options
|
|
@@ -418,4 +411,3 @@ export function labelPropagationSemiSupervised(
|
|
|
418
411
|
const graphMap = graphToMap(graph);
|
|
419
412
|
return labelPropagationSemiSupervisedImpl(graphMap, seedLabels, options);
|
|
420
413
|
}
|
|
421
|
-
|