@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,3 +1,5 @@
|
|
|
1
|
+
import { louvainOptimized } from "./louvain-optimized.js";
|
|
2
|
+
import { calculateModularity, getNeighborCommunities, getNodeDegree, getTotalEdgeWeight } from "./modularity-utils.js";
|
|
1
3
|
/**
|
|
2
4
|
* Louvain community detection algorithm
|
|
3
5
|
*
|
|
@@ -6,9 +8,8 @@
|
|
|
6
8
|
*
|
|
7
9
|
* References:
|
|
8
10
|
* - Blondel, V. D., Guillaume, J. L., Lambiotte, R., & Lefebvre, E. (2008).
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
11
|
+
* Fast unfolding of communities in large networks.
|
|
12
|
+
* Journal of statistical mechanics: theory and experiment, 2008(10), P10008.
|
|
12
13
|
* @param graph - The input graph
|
|
13
14
|
* @param options - Algorithm options
|
|
14
15
|
* @returns Community detection result with communities, modularity, and iterations
|
|
@@ -17,6 +18,21 @@ export function louvain(graph, options = {}) {
|
|
|
17
18
|
const resolution = options.resolution ?? 1.0;
|
|
18
19
|
const maxIterations = options.maxIterations ?? 100;
|
|
19
20
|
const tolerance = options.tolerance ?? 1e-6;
|
|
21
|
+
// Use optimized version by default for larger graphs
|
|
22
|
+
// Only disable if explicitly requested or graph is very small
|
|
23
|
+
const shouldUseOptimized = options.useOptimized !== false && graph.nodeCount > 50;
|
|
24
|
+
if (shouldUseOptimized) {
|
|
25
|
+
return louvainOptimized(graph, {
|
|
26
|
+
resolution,
|
|
27
|
+
maxIterations,
|
|
28
|
+
tolerance,
|
|
29
|
+
// Enable all optimizations by default
|
|
30
|
+
pruneLeaves: true,
|
|
31
|
+
importanceOrdering: true,
|
|
32
|
+
thresholdCycling: true,
|
|
33
|
+
pruningThreshold: 0.01,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
20
36
|
// Initialize: each node in its own community
|
|
21
37
|
const communities = initializeCommunities(graph);
|
|
22
38
|
let modularity = calculateModularity(graph, communities, resolution);
|
|
@@ -28,7 +44,7 @@ export function louvain(graph, options = {}) {
|
|
|
28
44
|
if (improved) {
|
|
29
45
|
const newModularity = calculateModularity(graph, communities, resolution);
|
|
30
46
|
// Check for convergence
|
|
31
|
-
if (
|
|
47
|
+
if (newModularity - modularity < tolerance) {
|
|
32
48
|
break;
|
|
33
49
|
}
|
|
34
50
|
modularity = newModularity;
|
|
@@ -43,6 +59,8 @@ export function louvain(graph, options = {}) {
|
|
|
43
59
|
}
|
|
44
60
|
/**
|
|
45
61
|
* Initialize communities: each node in its own community
|
|
62
|
+
* @param graph - The input graph
|
|
63
|
+
* @returns Map of node IDs to their initial community IDs
|
|
46
64
|
*/
|
|
47
65
|
function initializeCommunities(graph) {
|
|
48
66
|
const communities = new Map();
|
|
@@ -56,6 +74,10 @@ function initializeCommunities(graph) {
|
|
|
56
74
|
* Phase 1 of Louvain algorithm: Local optimization
|
|
57
75
|
* For each node, try moving to neighboring communities and keep the move
|
|
58
76
|
* that provides the best modularity gain.
|
|
77
|
+
* @param graph - The input graph
|
|
78
|
+
* @param communities - Map of node IDs to community IDs
|
|
79
|
+
* @param resolution - Resolution parameter for modularity calculation
|
|
80
|
+
* @returns True if any improvement was made, false otherwise
|
|
59
81
|
*/
|
|
60
82
|
function louvainPhase1(graph, communities, resolution) {
|
|
61
83
|
let globalImprovement = false;
|
|
@@ -96,6 +118,12 @@ function louvainPhase1(graph, communities, resolution) {
|
|
|
96
118
|
}
|
|
97
119
|
/**
|
|
98
120
|
* Calculate modularity contribution of a node to a specific community
|
|
121
|
+
* @param graph - The input graph
|
|
122
|
+
* @param nodeId - The node ID to evaluate
|
|
123
|
+
* @param community - The community to measure contribution to
|
|
124
|
+
* @param communities - Map of all node IDs to community IDs
|
|
125
|
+
* @param resolution - Resolution parameter for modularity calculation
|
|
126
|
+
* @returns The modularity contribution of the node to the specified community
|
|
99
127
|
*/
|
|
100
128
|
function nodeModularityContribution(graph, nodeId, community, communities, resolution) {
|
|
101
129
|
const totalEdgeWeight = getTotalEdgeWeight(graph);
|
|
@@ -121,66 +149,13 @@ function nodeModularityContribution(graph, nodeId, community, communities, resol
|
|
|
121
149
|
}
|
|
122
150
|
}
|
|
123
151
|
// Modularity formula: Q = (1/2m) * Σ[A_ij - (k_i * k_j)/(2m)] * δ(c_i, c_j)
|
|
124
|
-
const modularityIncrease = (internalLinks - (
|
|
152
|
+
const modularityIncrease = (internalLinks - (resolution * nodeDegree * communityDegree) / (2 * totalEdgeWeight)) / totalEdgeWeight;
|
|
125
153
|
return modularityIncrease;
|
|
126
154
|
}
|
|
127
|
-
/**
|
|
128
|
-
* Get communities of neighboring nodes
|
|
129
|
-
*/
|
|
130
|
-
function getNeighborCommunities(graph, nodeId, communities) {
|
|
131
|
-
const neighborCommunities = new Set();
|
|
132
|
-
for (const neighbor of graph.neighbors(nodeId)) {
|
|
133
|
-
const community = communities.get(neighbor);
|
|
134
|
-
if (community !== undefined) {
|
|
135
|
-
neighborCommunities.add(community);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return neighborCommunities;
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Calculate total modularity of the current community assignment
|
|
142
|
-
*/
|
|
143
|
-
function calculateModularity(graph, communities, resolution) {
|
|
144
|
-
const totalEdgeWeight = getTotalEdgeWeight(graph);
|
|
145
|
-
if (totalEdgeWeight === 0) {
|
|
146
|
-
return 0;
|
|
147
|
-
}
|
|
148
|
-
let modularity = 0;
|
|
149
|
-
// For undirected graphs, we need to be careful not to double-count edges
|
|
150
|
-
const countedEdges = new Set();
|
|
151
|
-
// Calculate modularity: Q = (1/2m) * Σ[A_ij - γ(k_i * k_j)/(2m)] * δ(c_i, c_j)
|
|
152
|
-
for (const nodeI of graph.nodes()) {
|
|
153
|
-
for (const nodeJ of graph.nodes()) {
|
|
154
|
-
// Skip if already counted this pair in undirected graph
|
|
155
|
-
if (!graph.isDirected) {
|
|
156
|
-
const nodeIStr = String(nodeI.id);
|
|
157
|
-
const nodeJStr = String(nodeJ.id);
|
|
158
|
-
const edgeKey = nodeIStr <= nodeJStr ? `${nodeIStr}-${nodeJStr}` : `${nodeJStr}-${nodeIStr}`;
|
|
159
|
-
if (countedEdges.has(edgeKey)) {
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
countedEdges.add(edgeKey);
|
|
163
|
-
}
|
|
164
|
-
if (communities.get(nodeI.id) === communities.get(nodeJ.id)) {
|
|
165
|
-
const edge = graph.getEdge(nodeI.id, nodeJ.id);
|
|
166
|
-
const reverseEdge = !graph.isDirected ? graph.getEdge(nodeJ.id, nodeI.id) : null;
|
|
167
|
-
let edgeWeight = 0;
|
|
168
|
-
if (edge) {
|
|
169
|
-
edgeWeight += edge.weight ?? 1;
|
|
170
|
-
}
|
|
171
|
-
if (reverseEdge && nodeI.id !== nodeJ.id) {
|
|
172
|
-
edgeWeight += reverseEdge.weight ?? 1;
|
|
173
|
-
}
|
|
174
|
-
const degreeI = getNodeDegree(graph, nodeI.id);
|
|
175
|
-
const degreeJ = getNodeDegree(graph, nodeJ.id);
|
|
176
|
-
modularity += edgeWeight - ((resolution * degreeI * degreeJ) / (2 * totalEdgeWeight));
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return modularity / (2 * totalEdgeWeight);
|
|
181
|
-
}
|
|
182
155
|
/**
|
|
183
156
|
* Extract final community structure
|
|
157
|
+
* @param communities - Map of node IDs to community IDs
|
|
158
|
+
* @returns Array of communities (each is an array of node IDs)
|
|
184
159
|
*/
|
|
185
160
|
function extractCommunities(communities) {
|
|
186
161
|
const communityMap = new Map();
|
|
@@ -195,25 +170,4 @@ function extractCommunities(communities) {
|
|
|
195
170
|
}
|
|
196
171
|
return Array.from(communityMap.values());
|
|
197
172
|
}
|
|
198
|
-
/**
|
|
199
|
-
* Calculate total edge weight in the graph
|
|
200
|
-
*/
|
|
201
|
-
function getTotalEdgeWeight(graph) {
|
|
202
|
-
let totalWeight = 0;
|
|
203
|
-
for (const edge of graph.edges()) {
|
|
204
|
-
totalWeight += edge.weight ?? 1;
|
|
205
|
-
}
|
|
206
|
-
return totalWeight;
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Get the total degree (sum of edge weights) for a node
|
|
210
|
-
*/
|
|
211
|
-
function getNodeDegree(graph, nodeId) {
|
|
212
|
-
let degree = 0;
|
|
213
|
-
for (const neighbor of graph.neighbors(nodeId)) {
|
|
214
|
-
const edge = graph.getEdge(nodeId, neighbor);
|
|
215
|
-
degree += edge?.weight ?? 1;
|
|
216
|
-
}
|
|
217
|
-
return degree;
|
|
218
|
-
}
|
|
219
173
|
//# sourceMappingURL=louvain.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"louvain.js","sourceRoot":"","sources":["../../../../src/algorithms/community/louvain.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"louvain.js","sourceRoot":"","sources":["../../../../src/algorithms/community/louvain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared modularity calculation utilities for community detection algorithms
|
|
3
|
+
*
|
|
4
|
+
* Used by: Louvain, Leiden, Girvan-Newman
|
|
5
|
+
*/
|
|
6
|
+
import type { Graph } from "../../core/graph.js";
|
|
7
|
+
import type { NodeId } from "../../types/index.js";
|
|
8
|
+
/**
|
|
9
|
+
* Calculate total edge weight in the graph
|
|
10
|
+
*
|
|
11
|
+
* For undirected graphs, each edge is counted once.
|
|
12
|
+
* For directed graphs, each directed edge is counted once.
|
|
13
|
+
* @param graph - The input graph
|
|
14
|
+
* @returns Total sum of edge weights (default weight is 1)
|
|
15
|
+
*/
|
|
16
|
+
export declare function getTotalEdgeWeight(graph: Graph): number;
|
|
17
|
+
/**
|
|
18
|
+
* Get the total degree (sum of edge weights) for a node
|
|
19
|
+
*
|
|
20
|
+
* Computes the weighted degree by summing all edge weights incident to the node.
|
|
21
|
+
* @param graph - The input graph
|
|
22
|
+
* @param nodeId - The node ID to compute degree for
|
|
23
|
+
* @returns The weighted degree of the node
|
|
24
|
+
*/
|
|
25
|
+
export declare function getNodeDegree(graph: Graph, nodeId: NodeId): number;
|
|
26
|
+
/**
|
|
27
|
+
* Get communities of neighboring nodes
|
|
28
|
+
*
|
|
29
|
+
* Returns the set of community IDs that neighbors of the given node belong to.
|
|
30
|
+
* @param graph - The input graph
|
|
31
|
+
* @param nodeId - The node to get neighbor communities for
|
|
32
|
+
* @param communities - Map from node IDs to community IDs
|
|
33
|
+
* @returns Set of community IDs that neighbors belong to
|
|
34
|
+
*/
|
|
35
|
+
export declare function getNeighborCommunities(graph: Graph, nodeId: NodeId, communities: Map<NodeId, number>): Set<number>;
|
|
36
|
+
/**
|
|
37
|
+
* Calculate modularity of a partition
|
|
38
|
+
*
|
|
39
|
+
* Modularity measures the quality of a community partition. It compares the
|
|
40
|
+
* number of edges within communities to what would be expected in a random graph.
|
|
41
|
+
*
|
|
42
|
+
* Formula: Q = (1/2m) * Σ[A_ij - γ(k_i * k_j)/(2m)] * δ(c_i, c_j)
|
|
43
|
+
* where:
|
|
44
|
+
* - m = total edge weight
|
|
45
|
+
* - A_ij = adjacency matrix entry (edge weight between i and j)
|
|
46
|
+
* - k_i, k_j = degrees of nodes i and j
|
|
47
|
+
* - γ = resolution parameter (higher values favor smaller communities)
|
|
48
|
+
* - δ = Kronecker delta (1 if same community, 0 otherwise)
|
|
49
|
+
* @param graph - The input graph
|
|
50
|
+
* @param communities - Map from node IDs to community IDs
|
|
51
|
+
* @param resolution - Resolution parameter (default: 1.0)
|
|
52
|
+
* @returns Modularity score (range typically -0.5 to 1.0)
|
|
53
|
+
*/
|
|
54
|
+
export declare function calculateModularity(graph: Graph, communities: Map<NodeId, number>, resolution?: number): number;
|
|
55
|
+
//# sourceMappingURL=modularity-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modularity-utils.d.ts","sourceRoot":"","sources":["../../../../src/algorithms/community/modularity-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAQvD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CASlE;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAWlH;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,SAAM,GAAG,MAAM,CAgD5G"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate total edge weight in the graph
|
|
3
|
+
*
|
|
4
|
+
* For undirected graphs, each edge is counted once.
|
|
5
|
+
* For directed graphs, each directed edge is counted once.
|
|
6
|
+
* @param graph - The input graph
|
|
7
|
+
* @returns Total sum of edge weights (default weight is 1)
|
|
8
|
+
*/
|
|
9
|
+
export function getTotalEdgeWeight(graph) {
|
|
10
|
+
let totalWeight = 0;
|
|
11
|
+
for (const edge of graph.edges()) {
|
|
12
|
+
totalWeight += edge.weight ?? 1;
|
|
13
|
+
}
|
|
14
|
+
return totalWeight;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get the total degree (sum of edge weights) for a node
|
|
18
|
+
*
|
|
19
|
+
* Computes the weighted degree by summing all edge weights incident to the node.
|
|
20
|
+
* @param graph - The input graph
|
|
21
|
+
* @param nodeId - The node ID to compute degree for
|
|
22
|
+
* @returns The weighted degree of the node
|
|
23
|
+
*/
|
|
24
|
+
export function getNodeDegree(graph, nodeId) {
|
|
25
|
+
let degree = 0;
|
|
26
|
+
for (const neighbor of graph.neighbors(nodeId)) {
|
|
27
|
+
const edge = graph.getEdge(nodeId, neighbor);
|
|
28
|
+
degree += edge?.weight ?? 1;
|
|
29
|
+
}
|
|
30
|
+
return degree;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get communities of neighboring nodes
|
|
34
|
+
*
|
|
35
|
+
* Returns the set of community IDs that neighbors of the given node belong to.
|
|
36
|
+
* @param graph - The input graph
|
|
37
|
+
* @param nodeId - The node to get neighbor communities for
|
|
38
|
+
* @param communities - Map from node IDs to community IDs
|
|
39
|
+
* @returns Set of community IDs that neighbors belong to
|
|
40
|
+
*/
|
|
41
|
+
export function getNeighborCommunities(graph, nodeId, communities) {
|
|
42
|
+
const neighborCommunities = new Set();
|
|
43
|
+
for (const neighbor of graph.neighbors(nodeId)) {
|
|
44
|
+
const community = communities.get(neighbor);
|
|
45
|
+
if (community !== undefined) {
|
|
46
|
+
neighborCommunities.add(community);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return neighborCommunities;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Calculate modularity of a partition
|
|
53
|
+
*
|
|
54
|
+
* Modularity measures the quality of a community partition. It compares the
|
|
55
|
+
* number of edges within communities to what would be expected in a random graph.
|
|
56
|
+
*
|
|
57
|
+
* Formula: Q = (1/2m) * Σ[A_ij - γ(k_i * k_j)/(2m)] * δ(c_i, c_j)
|
|
58
|
+
* where:
|
|
59
|
+
* - m = total edge weight
|
|
60
|
+
* - A_ij = adjacency matrix entry (edge weight between i and j)
|
|
61
|
+
* - k_i, k_j = degrees of nodes i and j
|
|
62
|
+
* - γ = resolution parameter (higher values favor smaller communities)
|
|
63
|
+
* - δ = Kronecker delta (1 if same community, 0 otherwise)
|
|
64
|
+
* @param graph - The input graph
|
|
65
|
+
* @param communities - Map from node IDs to community IDs
|
|
66
|
+
* @param resolution - Resolution parameter (default: 1.0)
|
|
67
|
+
* @returns Modularity score (range typically -0.5 to 1.0)
|
|
68
|
+
*/
|
|
69
|
+
export function calculateModularity(graph, communities, resolution = 1.0) {
|
|
70
|
+
const totalEdgeWeight = getTotalEdgeWeight(graph);
|
|
71
|
+
if (totalEdgeWeight === 0) {
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
let modularity = 0;
|
|
75
|
+
// For undirected graphs, we need to be careful not to double-count edges
|
|
76
|
+
const countedEdges = new Set();
|
|
77
|
+
// Calculate modularity: Q = (1/2m) * Σ[A_ij - γ(k_i * k_j)/(2m)] * δ(c_i, c_j)
|
|
78
|
+
for (const nodeI of graph.nodes()) {
|
|
79
|
+
for (const nodeJ of graph.nodes()) {
|
|
80
|
+
// Skip if already counted this pair in undirected graph
|
|
81
|
+
if (!graph.isDirected) {
|
|
82
|
+
const nodeIStr = String(nodeI.id);
|
|
83
|
+
const nodeJStr = String(nodeJ.id);
|
|
84
|
+
const edgeKey = nodeIStr <= nodeJStr ? `${nodeIStr}-${nodeJStr}` : `${nodeJStr}-${nodeIStr}`;
|
|
85
|
+
if (countedEdges.has(edgeKey)) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
countedEdges.add(edgeKey);
|
|
89
|
+
}
|
|
90
|
+
if (communities.get(nodeI.id) === communities.get(nodeJ.id)) {
|
|
91
|
+
const edge = graph.getEdge(nodeI.id, nodeJ.id);
|
|
92
|
+
const reverseEdge = !graph.isDirected ? graph.getEdge(nodeJ.id, nodeI.id) : null;
|
|
93
|
+
let edgeWeight = 0;
|
|
94
|
+
if (edge) {
|
|
95
|
+
edgeWeight += edge.weight ?? 1;
|
|
96
|
+
}
|
|
97
|
+
if (reverseEdge && nodeI.id !== nodeJ.id) {
|
|
98
|
+
edgeWeight += reverseEdge.weight ?? 1;
|
|
99
|
+
}
|
|
100
|
+
const degreeI = getNodeDegree(graph, nodeI.id);
|
|
101
|
+
const degreeJ = getNodeDegree(graph, nodeJ.id);
|
|
102
|
+
modularity += edgeWeight - (resolution * degreeI * degreeJ) / (2 * totalEdgeWeight);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return modularity / (2 * totalEdgeWeight);
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=modularity-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modularity-utils.js","sourceRoot":"","sources":["../../../../src/algorithms/community/modularity-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,47 +8,70 @@ import type { NodeId } from "../../types/index.js";
|
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
10
|
* Find connected components in an undirected graph using Union-Find
|
|
11
|
+
* @param graph - The input graph (must be undirected)
|
|
12
|
+
* @returns Array of connected components, each containing an array of node IDs
|
|
11
13
|
*/
|
|
12
14
|
export declare function connectedComponents(graph: Graph): NodeId[][];
|
|
13
15
|
/**
|
|
14
16
|
* Find connected components using DFS (alternative implementation)
|
|
17
|
+
* @param graph - The input graph (must be undirected)
|
|
18
|
+
* @returns Array of connected components, each containing an array of node IDs
|
|
15
19
|
*/
|
|
16
20
|
export declare function connectedComponentsDFS(graph: Graph): NodeId[][];
|
|
17
21
|
/**
|
|
18
22
|
* Find the number of connected components
|
|
23
|
+
* @param graph - The input graph (must be undirected)
|
|
24
|
+
* @returns The number of connected components in the graph
|
|
19
25
|
*/
|
|
20
26
|
export declare function numberOfConnectedComponents(graph: Graph): number;
|
|
21
27
|
/**
|
|
22
28
|
* Check if the graph is connected (has exactly one connected component)
|
|
29
|
+
* @param graph - The input graph (must be undirected)
|
|
30
|
+
* @returns True if the graph is connected, false otherwise
|
|
23
31
|
*/
|
|
24
32
|
export declare function isConnected(graph: Graph): boolean;
|
|
25
33
|
/**
|
|
26
34
|
* Find the largest connected component
|
|
35
|
+
* @param graph - The input graph (must be undirected)
|
|
36
|
+
* @returns Array of node IDs in the largest connected component
|
|
27
37
|
*/
|
|
28
38
|
export declare function largestConnectedComponent(graph: Graph): NodeId[];
|
|
29
39
|
/**
|
|
30
40
|
* Get the connected component containing a specific node
|
|
41
|
+
* @param graph - The input graph (must be undirected)
|
|
42
|
+
* @param nodeId - The node ID to find the component for
|
|
43
|
+
* @returns Array of node IDs in the same component as the specified node
|
|
31
44
|
*/
|
|
32
45
|
export declare function getConnectedComponent(graph: Graph, nodeId: NodeId): NodeId[];
|
|
33
46
|
/**
|
|
34
47
|
* Find strongly connected components using Tarjan's algorithm
|
|
48
|
+
* @param graph - The input graph (must be directed)
|
|
49
|
+
* @returns Array of strongly connected components, each containing an array of node IDs
|
|
35
50
|
*/
|
|
36
51
|
export declare function stronglyConnectedComponents(graph: Graph): NodeId[][];
|
|
37
52
|
/**
|
|
38
53
|
* Check if a directed graph is strongly connected
|
|
54
|
+
* @param graph - The input graph (must be directed)
|
|
55
|
+
* @returns True if the graph is strongly connected, false otherwise
|
|
39
56
|
*/
|
|
40
57
|
export declare function isStronglyConnected(graph: Graph): boolean;
|
|
41
58
|
/**
|
|
42
59
|
* Find weakly connected components in a directed graph
|
|
43
60
|
* (treat the graph as undirected for connectivity)
|
|
61
|
+
* @param graph - The input graph (must be directed)
|
|
62
|
+
* @returns Array of weakly connected components, each containing an array of node IDs
|
|
44
63
|
*/
|
|
45
64
|
export declare function weaklyConnectedComponents(graph: Graph): NodeId[][];
|
|
46
65
|
/**
|
|
47
66
|
* Check if a directed graph is weakly connected
|
|
67
|
+
* @param graph - The input graph (must be directed)
|
|
68
|
+
* @returns True if the graph is weakly connected, false otherwise
|
|
48
69
|
*/
|
|
49
70
|
export declare function isWeaklyConnected(graph: Graph): boolean;
|
|
50
71
|
/**
|
|
51
72
|
* Find condensation graph (quotient graph of strongly connected components)
|
|
73
|
+
* @param graph - The input graph (must be directed)
|
|
74
|
+
* @returns Object containing the condensed graph, component map, and component arrays
|
|
52
75
|
*/
|
|
53
76
|
export declare function condensationGraph(graph: Graph): {
|
|
54
77
|
condensedGraph: Graph;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connected.d.ts","sourceRoot":"","sources":["../../../../src/algorithms/components/connected.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"connected.d.ts","sourceRoot":"","sources":["../../../../src/algorithms/components/connected.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD;;;;;GAKG;AAEH;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,EAAE,CAqB5D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,EAAE,CAiB/D;AAoBD;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAEhE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,CAQhE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAe5E;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,EAAE,CAoEpE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAOzD;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,EAAE,CAqBlE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAMvD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG;IAC7C,cAAc,EAAE,KAAK,CAAC;IACtB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC;CAC1B,CA2CA"}
|
|
@@ -7,6 +7,8 @@ import { UnionFind } from "../../data-structures/union-find.js";
|
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
9
|
* Find connected components in an undirected graph using Union-Find
|
|
10
|
+
* @param graph - The input graph (must be undirected)
|
|
11
|
+
* @returns Array of connected components, each containing an array of node IDs
|
|
10
12
|
*/
|
|
11
13
|
export function connectedComponents(graph) {
|
|
12
14
|
if (graph.isDirected) {
|
|
@@ -25,6 +27,8 @@ export function connectedComponents(graph) {
|
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
29
|
* Find connected components using DFS (alternative implementation)
|
|
30
|
+
* @param graph - The input graph (must be undirected)
|
|
31
|
+
* @returns Array of connected components, each containing an array of node IDs
|
|
28
32
|
*/
|
|
29
33
|
export function connectedComponentsDFS(graph) {
|
|
30
34
|
if (graph.isDirected) {
|
|
@@ -43,6 +47,10 @@ export function connectedComponentsDFS(graph) {
|
|
|
43
47
|
}
|
|
44
48
|
/**
|
|
45
49
|
* DFS helper for connected components
|
|
50
|
+
* @param graph - The input graph
|
|
51
|
+
* @param nodeId - The starting node ID
|
|
52
|
+
* @param visited - Set of already visited node IDs
|
|
53
|
+
* @param component - Array to accumulate component members
|
|
46
54
|
*/
|
|
47
55
|
function dfsComponent(graph, nodeId, visited, component) {
|
|
48
56
|
visited.add(nodeId);
|
|
@@ -55,28 +63,37 @@ function dfsComponent(graph, nodeId, visited, component) {
|
|
|
55
63
|
}
|
|
56
64
|
/**
|
|
57
65
|
* Find the number of connected components
|
|
66
|
+
* @param graph - The input graph (must be undirected)
|
|
67
|
+
* @returns The number of connected components in the graph
|
|
58
68
|
*/
|
|
59
69
|
export function numberOfConnectedComponents(graph) {
|
|
60
70
|
return connectedComponents(graph).length;
|
|
61
71
|
}
|
|
62
72
|
/**
|
|
63
73
|
* Check if the graph is connected (has exactly one connected component)
|
|
74
|
+
* @param graph - The input graph (must be undirected)
|
|
75
|
+
* @returns True if the graph is connected, false otherwise
|
|
64
76
|
*/
|
|
65
77
|
export function isConnected(graph) {
|
|
66
78
|
return numberOfConnectedComponents(graph) <= 1;
|
|
67
79
|
}
|
|
68
80
|
/**
|
|
69
81
|
* Find the largest connected component
|
|
82
|
+
* @param graph - The input graph (must be undirected)
|
|
83
|
+
* @returns Array of node IDs in the largest connected component
|
|
70
84
|
*/
|
|
71
85
|
export function largestConnectedComponent(graph) {
|
|
72
86
|
const components = connectedComponents(graph);
|
|
73
87
|
if (components.length === 0) {
|
|
74
88
|
return [];
|
|
75
89
|
}
|
|
76
|
-
return components.reduce((largest, current) => current.length > largest.length ? current : largest);
|
|
90
|
+
return components.reduce((largest, current) => (current.length > largest.length ? current : largest));
|
|
77
91
|
}
|
|
78
92
|
/**
|
|
79
93
|
* Get the connected component containing a specific node
|
|
94
|
+
* @param graph - The input graph (must be undirected)
|
|
95
|
+
* @param nodeId - The node ID to find the component for
|
|
96
|
+
* @returns Array of node IDs in the same component as the specified node
|
|
80
97
|
*/
|
|
81
98
|
export function getConnectedComponent(graph, nodeId) {
|
|
82
99
|
if (!graph.hasNode(nodeId)) {
|
|
@@ -92,6 +109,8 @@ export function getConnectedComponent(graph, nodeId) {
|
|
|
92
109
|
}
|
|
93
110
|
/**
|
|
94
111
|
* Find strongly connected components using Tarjan's algorithm
|
|
112
|
+
* @param graph - The input graph (must be directed)
|
|
113
|
+
* @returns Array of strongly connected components, each containing an array of node IDs
|
|
95
114
|
*/
|
|
96
115
|
export function stronglyConnectedComponents(graph) {
|
|
97
116
|
if (!graph.isDirected) {
|
|
@@ -154,6 +173,8 @@ export function stronglyConnectedComponents(graph) {
|
|
|
154
173
|
}
|
|
155
174
|
/**
|
|
156
175
|
* Check if a directed graph is strongly connected
|
|
176
|
+
* @param graph - The input graph (must be directed)
|
|
177
|
+
* @returns True if the graph is strongly connected, false otherwise
|
|
157
178
|
*/
|
|
158
179
|
export function isStronglyConnected(graph) {
|
|
159
180
|
if (!graph.isDirected) {
|
|
@@ -165,6 +186,8 @@ export function isStronglyConnected(graph) {
|
|
|
165
186
|
/**
|
|
166
187
|
* Find weakly connected components in a directed graph
|
|
167
188
|
* (treat the graph as undirected for connectivity)
|
|
189
|
+
* @param graph - The input graph (must be directed)
|
|
190
|
+
* @returns Array of weakly connected components, each containing an array of node IDs
|
|
168
191
|
*/
|
|
169
192
|
export function weaklyConnectedComponents(graph) {
|
|
170
193
|
if (!graph.isDirected) {
|
|
@@ -183,6 +206,8 @@ export function weaklyConnectedComponents(graph) {
|
|
|
183
206
|
}
|
|
184
207
|
/**
|
|
185
208
|
* Check if a directed graph is weakly connected
|
|
209
|
+
* @param graph - The input graph (must be directed)
|
|
210
|
+
* @returns True if the graph is weakly connected, false otherwise
|
|
186
211
|
*/
|
|
187
212
|
export function isWeaklyConnected(graph) {
|
|
188
213
|
if (!graph.isDirected) {
|
|
@@ -192,6 +217,8 @@ export function isWeaklyConnected(graph) {
|
|
|
192
217
|
}
|
|
193
218
|
/**
|
|
194
219
|
* Find condensation graph (quotient graph of strongly connected components)
|
|
220
|
+
* @param graph - The input graph (must be directed)
|
|
221
|
+
* @returns Object containing the condensed graph, component map, and component arrays
|
|
195
222
|
*/
|
|
196
223
|
export function condensationGraph(graph) {
|
|
197
224
|
if (!graph.isDirected) {
|
|
@@ -216,8 +243,7 @@ export function condensationGraph(graph) {
|
|
|
216
243
|
for (const edge of Array.from(graph.edges())) {
|
|
217
244
|
const sourceComponent = componentMap.get(edge.source);
|
|
218
245
|
const targetComponent = componentMap.get(edge.target);
|
|
219
|
-
if (sourceComponent !== undefined && targetComponent !== undefined &&
|
|
220
|
-
sourceComponent !== targetComponent) {
|
|
246
|
+
if (sourceComponent !== undefined && targetComponent !== undefined && sourceComponent !== targetComponent) {
|
|
221
247
|
const edgeKey = `${String(sourceComponent)}-${String(targetComponent)}`;
|
|
222
248
|
if (!addedEdges.has(edgeKey)) {
|
|
223
249
|
condensedGraph.addEdge(sourceComponent, targetComponent);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connected.js","sourceRoot":"","sources":["../../../../src/algorithms/components/connected.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"connected.js","sourceRoot":"","sources":["../../../../src/algorithms/components/connected.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,10 +20,16 @@ export interface BipartiteMatchingOptions {
|
|
|
20
20
|
/**
|
|
21
21
|
* Find maximum matching in a bipartite graph using augmenting path algorithm
|
|
22
22
|
* (simplified implementation that's more reliable than Hopcroft-Karp for this context)
|
|
23
|
+
* @param graph - The bipartite graph to find maximum matching for
|
|
24
|
+
* @param options - Optional configuration including left and right node partitions
|
|
25
|
+
* @returns The maximum matching as a map from left nodes to right nodes and the matching size
|
|
26
|
+
* @throws Error if the graph is not bipartite
|
|
23
27
|
*/
|
|
24
28
|
export declare function maximumBipartiteMatching(graph: Graph, options?: BipartiteMatchingOptions): BipartiteMatchingResult;
|
|
25
29
|
/**
|
|
26
30
|
* Check if graph is bipartite and return the partition
|
|
31
|
+
* @param graph - The graph to check for bipartiteness
|
|
32
|
+
* @returns An object with left and right node sets if bipartite, or null if not bipartite
|
|
27
33
|
*/
|
|
28
34
|
export declare function bipartitePartition(graph: Graph): {
|
|
29
35
|
left: Set<NodeId>;
|
|
@@ -32,6 +38,10 @@ export declare function bipartitePartition(graph: Graph): {
|
|
|
32
38
|
/**
|
|
33
39
|
* Simple greedy bipartite matching algorithm
|
|
34
40
|
* Useful for comparison or when Hopcroft-Karp is overkill
|
|
41
|
+
* @param graph - The bipartite graph to find matching for
|
|
42
|
+
* @param options - Optional configuration including left and right node partitions
|
|
43
|
+
* @returns The matching as a map from left nodes to right nodes and the matching size
|
|
44
|
+
* @throws Error if the graph is not bipartite
|
|
35
45
|
*/
|
|
36
46
|
export declare function greedyBipartiteMatching(graph: Graph, options?: BipartiteMatchingOptions): BipartiteMatchingResult;
|
|
37
47
|
//# sourceMappingURL=bipartite.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bipartite.d.ts","sourceRoot":"","sources":["../../../../src/algorithms/matching/bipartite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"bipartite.d.ts","sourceRoot":"","sources":["../../../../src/algorithms/matching/bipartite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGnD;;;;;;;;GAQG;AAEH,MAAM,WAAW,uBAAuB;IACpC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACrC,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACpC,KAAK,EAAE,KAAK,EACZ,OAAO,GAAE,wBAA6B,GACvC,uBAAuB,CAsDzB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG;IAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,CAWjG;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,wBAA6B,GAAG,uBAAuB,CAgCrH"}
|