@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,7 @@
|
|
|
1
|
+
import { bfsAugmentingPath } from "../algorithms/traversal/bfs-variants.js";
|
|
2
|
+
import type { Graph } from "../core/graph.js";
|
|
3
|
+
import { graphToMap } from "../utils/graph-converters.js";
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* Ford-Fulkerson Algorithm for Maximum Flow
|
|
3
7
|
*
|
|
@@ -20,228 +24,15 @@ export interface FlowNetwork {
|
|
|
20
24
|
export interface MaxFlowResult {
|
|
21
25
|
maxFlow: number;
|
|
22
26
|
flowGraph: Map<string, Map<string, number>>;
|
|
23
|
-
minCut?: {source: Set<string
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Ford-Fulkerson algorithm using DFS for finding augmenting paths
|
|
28
|
-
*
|
|
29
|
-
* @param graph - Adjacency list representation with capacities
|
|
30
|
-
* @param source - Source node
|
|
31
|
-
* @param sink - Sink node
|
|
32
|
-
* @returns Maximum flow value and flow graph
|
|
33
|
-
*
|
|
34
|
-
* Time Complexity: O(E * f) where f is the maximum flow
|
|
35
|
-
* Space Complexity: O(V + E)
|
|
36
|
-
*/
|
|
37
|
-
export function fordFulkerson(
|
|
38
|
-
graph: Map<string, Map<string, number>>,
|
|
39
|
-
source: string,
|
|
40
|
-
sink: string,
|
|
41
|
-
): MaxFlowResult {
|
|
42
|
-
if (!graph.has(source) || !graph.has(sink)) {
|
|
43
|
-
return {maxFlow: 0, flowGraph: new Map()};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Create residual graph
|
|
47
|
-
const residualGraph = createResidualGraph(graph);
|
|
48
|
-
const flowGraph = new Map<string, Map<string, number>>();
|
|
49
|
-
|
|
50
|
-
// Initialize flow graph
|
|
51
|
-
for (const [u, neighbors] of graph) {
|
|
52
|
-
flowGraph.set(u, new Map());
|
|
53
|
-
for (const v of neighbors.keys()) {
|
|
54
|
-
const uFlowNeighbors = flowGraph.get(u);
|
|
55
|
-
if (uFlowNeighbors) {
|
|
56
|
-
uFlowNeighbors.set(v, 0);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
let maxFlow = 0;
|
|
62
|
-
let path = findAugmentingPath(residualGraph, source, sink);
|
|
63
|
-
|
|
64
|
-
while (path !== null) {
|
|
65
|
-
// Find minimum capacity along the path
|
|
66
|
-
let pathFlow = Infinity;
|
|
67
|
-
for (let i = 0; i < path.length - 1; i++) {
|
|
68
|
-
const u = path[i];
|
|
69
|
-
const v = path[i + 1];
|
|
70
|
-
if (!u || !v) {
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const uEdges = residualGraph.get(u);
|
|
75
|
-
if (!uEdges) {
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const capacity = uEdges.get(v);
|
|
80
|
-
if (capacity !== undefined) {
|
|
81
|
-
pathFlow = Math.min(pathFlow, capacity);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Update residual capacities
|
|
86
|
-
for (let i = 0; i < path.length - 1; i++) {
|
|
87
|
-
const u = path[i];
|
|
88
|
-
const v = path[i + 1];
|
|
89
|
-
if (!u || !v) {
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Update residual graph
|
|
94
|
-
const uEdges = residualGraph.get(u);
|
|
95
|
-
if (uEdges) {
|
|
96
|
-
const currentCapacity = uEdges.get(v);
|
|
97
|
-
if (currentCapacity !== undefined) {
|
|
98
|
-
uEdges.set(v, currentCapacity - pathFlow);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Add reverse edge
|
|
103
|
-
if (!residualGraph.has(v)) {
|
|
104
|
-
residualGraph.set(v, new Map());
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const vEdges = residualGraph.get(v);
|
|
108
|
-
if (vEdges) {
|
|
109
|
-
vEdges.set(u, (vEdges.get(u) ?? 0) + pathFlow);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Update flow graph
|
|
113
|
-
if (graph.get(u)?.has(v)) {
|
|
114
|
-
const uFlowEdges = flowGraph.get(u);
|
|
115
|
-
if (uFlowEdges) {
|
|
116
|
-
const currentFlow = uFlowEdges.get(v) ?? 0;
|
|
117
|
-
uFlowEdges.set(v, currentFlow + pathFlow);
|
|
118
|
-
}
|
|
119
|
-
} else if (graph.get(v)?.has(u)) {
|
|
120
|
-
// This is a reverse flow
|
|
121
|
-
const vFlowEdges = flowGraph.get(v);
|
|
122
|
-
if (vFlowEdges) {
|
|
123
|
-
const currentFlow = vFlowEdges.get(u) ?? 0;
|
|
124
|
-
vFlowEdges.set(u, currentFlow - pathFlow);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
maxFlow += pathFlow;
|
|
130
|
-
path = findAugmentingPath(residualGraph, source, sink);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Find minimum cut
|
|
134
|
-
const minCut = findMinCut(residualGraph, source);
|
|
135
|
-
|
|
136
|
-
return {maxFlow, flowGraph, minCut};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Edmonds-Karp algorithm (Ford-Fulkerson with BFS)
|
|
141
|
-
* More efficient implementation with better time complexity
|
|
142
|
-
*
|
|
143
|
-
* Time Complexity: O(V * E²)
|
|
144
|
-
*/
|
|
145
|
-
export function edmondsKarp(
|
|
146
|
-
graph: Map<string, Map<string, number>>,
|
|
147
|
-
source: string,
|
|
148
|
-
sink: string,
|
|
149
|
-
): MaxFlowResult {
|
|
150
|
-
if (!graph.has(source) || !graph.has(sink)) {
|
|
151
|
-
return {maxFlow: 0, flowGraph: new Map()};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const residualGraph = createResidualGraph(graph);
|
|
155
|
-
const flowGraph = new Map<string, Map<string, number>>();
|
|
156
|
-
|
|
157
|
-
// Initialize flow graph
|
|
158
|
-
for (const [u, neighbors] of graph) {
|
|
159
|
-
flowGraph.set(u, new Map());
|
|
160
|
-
for (const v of neighbors.keys()) {
|
|
161
|
-
const uFlowNeighbors = flowGraph.get(u);
|
|
162
|
-
if (uFlowNeighbors) {
|
|
163
|
-
uFlowNeighbors.set(v, 0);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
let maxFlow = 0;
|
|
169
|
-
let path = findAugmentingPathBFS(residualGraph, source, sink);
|
|
170
|
-
|
|
171
|
-
while (path !== null) {
|
|
172
|
-
let pathFlow = Infinity;
|
|
173
|
-
for (let i = 0; i < path.length - 1; i++) {
|
|
174
|
-
const u = path[i];
|
|
175
|
-
const v = path[i + 1];
|
|
176
|
-
if (!u || !v) {
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const uEdges = residualGraph.get(u);
|
|
181
|
-
if (!uEdges) {
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const capacity = uEdges.get(v);
|
|
186
|
-
if (capacity !== undefined) {
|
|
187
|
-
pathFlow = Math.min(pathFlow, capacity);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
for (let i = 0; i < path.length - 1; i++) {
|
|
192
|
-
const u = path[i];
|
|
193
|
-
const v = path[i + 1];
|
|
194
|
-
if (!u || !v) {
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const uEdges = residualGraph.get(u);
|
|
199
|
-
if (uEdges) {
|
|
200
|
-
const currentCapacity = uEdges.get(v);
|
|
201
|
-
if (currentCapacity !== undefined) {
|
|
202
|
-
uEdges.set(v, currentCapacity - pathFlow);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (!residualGraph.has(v)) {
|
|
207
|
-
residualGraph.set(v, new Map());
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const vEdges = residualGraph.get(v);
|
|
211
|
-
if (vEdges) {
|
|
212
|
-
vEdges.set(u, (vEdges.get(u) ?? 0) + pathFlow);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (graph.get(u)?.has(v)) {
|
|
216
|
-
const uFlowEdges = flowGraph.get(u);
|
|
217
|
-
if (uFlowEdges) {
|
|
218
|
-
const currentFlow = uFlowEdges.get(v) ?? 0;
|
|
219
|
-
uFlowEdges.set(v, currentFlow + pathFlow);
|
|
220
|
-
}
|
|
221
|
-
} else if (graph.get(v)?.has(u)) {
|
|
222
|
-
const vFlowEdges = flowGraph.get(v);
|
|
223
|
-
if (vFlowEdges) {
|
|
224
|
-
const currentFlow = vFlowEdges.get(u) ?? 0;
|
|
225
|
-
vFlowEdges.set(u, currentFlow - pathFlow);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
maxFlow += pathFlow;
|
|
231
|
-
path = findAugmentingPathBFS(residualGraph, source, sink);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const minCut = findMinCut(residualGraph, source);
|
|
235
|
-
|
|
236
|
-
return {maxFlow, flowGraph, minCut};
|
|
27
|
+
minCut?: { source: Set<string>; sink: Set<string>; edges: [string, string][] };
|
|
237
28
|
}
|
|
238
29
|
|
|
239
30
|
/**
|
|
240
31
|
* Create residual graph from original graph
|
|
32
|
+
* @param graph - The original graph with capacity values
|
|
33
|
+
* @returns A residual graph initialized with the original capacities
|
|
241
34
|
*/
|
|
242
|
-
function createResidualGraph(
|
|
243
|
-
graph: Map<string, Map<string, number>>,
|
|
244
|
-
): Map<string, Map<string, number>> {
|
|
35
|
+
function createResidualGraph(graph: Map<string, Map<string, number>>): Map<string, Map<string, number>> {
|
|
245
36
|
const residual = new Map<string, Map<string, number>>();
|
|
246
37
|
|
|
247
38
|
for (const [u, neighbors] of graph) {
|
|
@@ -259,8 +50,12 @@ function createResidualGraph(
|
|
|
259
50
|
|
|
260
51
|
/**
|
|
261
52
|
* Find augmenting path using DFS
|
|
53
|
+
* @param residualGraph - The residual graph with remaining capacities
|
|
54
|
+
* @param source - The source node
|
|
55
|
+
* @param sink - The sink node
|
|
56
|
+
* @returns An array of nodes forming the path, or null if no path exists
|
|
262
57
|
*/
|
|
263
|
-
function
|
|
58
|
+
function findAugmentingPathDFS(
|
|
264
59
|
residualGraph: Map<string, Map<string, number>>,
|
|
265
60
|
source: string,
|
|
266
61
|
sink: string,
|
|
@@ -300,64 +95,74 @@ function findAugmentingPath(
|
|
|
300
95
|
}
|
|
301
96
|
|
|
302
97
|
/**
|
|
303
|
-
*
|
|
98
|
+
* Update flow along an augmenting path
|
|
99
|
+
* @param residualGraph - The residual graph to update
|
|
100
|
+
* @param flowGraph - The flow graph to update with new flow values
|
|
101
|
+
* @param originalGraph - The original graph for edge direction reference
|
|
102
|
+
* @param path - The augmenting path to update flow along
|
|
103
|
+
* @param pathFlow - The amount of flow to push through the path
|
|
304
104
|
*/
|
|
305
|
-
function
|
|
105
|
+
function updateFlow(
|
|
306
106
|
residualGraph: Map<string, Map<string, number>>,
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const current = queue.shift();
|
|
317
|
-
if (!current) {
|
|
107
|
+
flowGraph: Map<string, Map<string, number>>,
|
|
108
|
+
originalGraph: Map<string, Map<string, number>>,
|
|
109
|
+
path: string[],
|
|
110
|
+
pathFlow: number,
|
|
111
|
+
): void {
|
|
112
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
113
|
+
const u = path[i];
|
|
114
|
+
const v = path[i + 1];
|
|
115
|
+
if (!u || !v) {
|
|
318
116
|
continue;
|
|
319
117
|
}
|
|
320
118
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
// Reconstruct path
|
|
330
|
-
const path: string[] = [];
|
|
331
|
-
let node = sink;
|
|
332
|
-
while (node !== source) {
|
|
333
|
-
path.unshift(node);
|
|
334
|
-
const parentNode = parent.get(node);
|
|
335
|
-
if (!parentNode) {
|
|
336
|
-
break;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
node = parentNode;
|
|
340
|
-
}
|
|
341
|
-
path.unshift(source);
|
|
342
|
-
return path;
|
|
343
|
-
}
|
|
119
|
+
// Update residual graph
|
|
120
|
+
const uEdges = residualGraph.get(u);
|
|
121
|
+
if (uEdges) {
|
|
122
|
+
const currentCapacity = uEdges.get(v);
|
|
123
|
+
if (currentCapacity !== undefined) {
|
|
124
|
+
uEdges.set(v, currentCapacity - pathFlow);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
344
127
|
|
|
345
|
-
|
|
346
|
-
|
|
128
|
+
// Add reverse edge
|
|
129
|
+
if (!residualGraph.has(v)) {
|
|
130
|
+
residualGraph.set(v, new Map());
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const vEdges = residualGraph.get(v);
|
|
134
|
+
if (vEdges) {
|
|
135
|
+
vEdges.set(u, (vEdges.get(u) ?? 0) + pathFlow);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Update flow graph
|
|
139
|
+
if (originalGraph.get(u)?.has(v)) {
|
|
140
|
+
const uFlowEdges = flowGraph.get(u);
|
|
141
|
+
if (uFlowEdges) {
|
|
142
|
+
const currentFlow = uFlowEdges.get(v) ?? 0;
|
|
143
|
+
uFlowEdges.set(v, currentFlow + pathFlow);
|
|
144
|
+
}
|
|
145
|
+
} else if (originalGraph.get(v)?.has(u)) {
|
|
146
|
+
// This is a reverse flow
|
|
147
|
+
const vFlowEdges = flowGraph.get(v);
|
|
148
|
+
if (vFlowEdges) {
|
|
149
|
+
const currentFlow = vFlowEdges.get(u) ?? 0;
|
|
150
|
+
vFlowEdges.set(u, currentFlow - pathFlow);
|
|
347
151
|
}
|
|
348
152
|
}
|
|
349
153
|
}
|
|
350
|
-
|
|
351
|
-
return null;
|
|
352
154
|
}
|
|
353
155
|
|
|
354
156
|
/**
|
|
355
157
|
* Find minimum cut from source side
|
|
158
|
+
* @param residualGraph - The residual graph after max flow computation
|
|
159
|
+
* @param source - The source node
|
|
160
|
+
* @returns The minimum cut partition with source and sink sets and cut edges
|
|
356
161
|
*/
|
|
357
162
|
function findMinCut(
|
|
358
163
|
residualGraph: Map<string, Map<string, number>>,
|
|
359
164
|
source: string,
|
|
360
|
-
): {source: Set<string
|
|
165
|
+
): { source: Set<string>; sink: Set<string>; edges: [string, string][] } {
|
|
361
166
|
// Find all reachable nodes from source in residual graph
|
|
362
167
|
const sourceSet = new Set<string>();
|
|
363
168
|
const queue = [source];
|
|
@@ -402,17 +207,136 @@ function findMinCut(
|
|
|
402
207
|
}
|
|
403
208
|
}
|
|
404
209
|
|
|
405
|
-
return {source: sourceSet, sink: sinkSet, edges: cutEdges};
|
|
210
|
+
return { source: sourceSet, sink: sinkSet, edges: cutEdges };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Core max flow algorithm implementation
|
|
215
|
+
* @param graph - The graph with capacity values
|
|
216
|
+
* @param source - The source node
|
|
217
|
+
* @param sink - The sink node
|
|
218
|
+
* @param findPath - Function to find an augmenting path in the residual graph
|
|
219
|
+
* @returns The maximum flow result including flow value, flow graph, and minimum cut
|
|
220
|
+
*/
|
|
221
|
+
function maxFlowCore(
|
|
222
|
+
graph: Map<string, Map<string, number>>,
|
|
223
|
+
source: string,
|
|
224
|
+
sink: string,
|
|
225
|
+
findPath: (
|
|
226
|
+
residual: Map<string, Map<string, number>>,
|
|
227
|
+
src: string,
|
|
228
|
+
snk: string,
|
|
229
|
+
) => { path: string[]; pathCapacity: number } | null,
|
|
230
|
+
): MaxFlowResult {
|
|
231
|
+
if (!graph.has(source) || !graph.has(sink)) {
|
|
232
|
+
return { maxFlow: 0, flowGraph: new Map() };
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Create residual graph
|
|
236
|
+
const residualGraph = createResidualGraph(graph);
|
|
237
|
+
const flowGraph = new Map<string, Map<string, number>>();
|
|
238
|
+
|
|
239
|
+
// Initialize flow graph
|
|
240
|
+
for (const [u, neighbors] of graph) {
|
|
241
|
+
flowGraph.set(u, new Map());
|
|
242
|
+
for (const v of neighbors.keys()) {
|
|
243
|
+
const uFlowNeighbors = flowGraph.get(u);
|
|
244
|
+
if (uFlowNeighbors) {
|
|
245
|
+
uFlowNeighbors.set(v, 0);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
let maxFlow = 0;
|
|
251
|
+
let pathResult = findPath(residualGraph, source, sink);
|
|
252
|
+
|
|
253
|
+
while (pathResult !== null) {
|
|
254
|
+
const { path, pathCapacity } = pathResult;
|
|
255
|
+
|
|
256
|
+
// Update flow
|
|
257
|
+
updateFlow(residualGraph, flowGraph, graph, path, pathCapacity);
|
|
258
|
+
maxFlow += pathCapacity;
|
|
259
|
+
|
|
260
|
+
// Find next path
|
|
261
|
+
pathResult = findPath(residualGraph, source, sink);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Find minimum cut
|
|
265
|
+
const minCut = findMinCut(residualGraph, source);
|
|
266
|
+
|
|
267
|
+
return { maxFlow, flowGraph, minCut };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Internal implementation of Ford-Fulkerson algorithm using DFS
|
|
272
|
+
* @param graph - The graph with capacity values
|
|
273
|
+
* @param source - The source node
|
|
274
|
+
* @param sink - The sink node
|
|
275
|
+
* @returns The maximum flow result
|
|
276
|
+
*/
|
|
277
|
+
function fordFulkersonImpl(graph: Map<string, Map<string, number>>, source: string, sink: string): MaxFlowResult {
|
|
278
|
+
// Adapter function for DFS path finding
|
|
279
|
+
const findPathDFS = (
|
|
280
|
+
residual: Map<string, Map<string, number>>,
|
|
281
|
+
src: string,
|
|
282
|
+
snk: string,
|
|
283
|
+
): { path: string[]; pathCapacity: number } | null => {
|
|
284
|
+
const path = findAugmentingPathDFS(residual, src, snk);
|
|
285
|
+
if (!path) {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Calculate path capacity
|
|
290
|
+
let pathCapacity = Infinity;
|
|
291
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
292
|
+
const u = path[i];
|
|
293
|
+
const v = path[i + 1];
|
|
294
|
+
if (u && v) {
|
|
295
|
+
const capacity = residual.get(u)?.get(v);
|
|
296
|
+
if (capacity !== undefined) {
|
|
297
|
+
pathCapacity = Math.min(pathCapacity, capacity);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return { path, pathCapacity };
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
return maxFlowCore(graph, source, sink, findPathDFS);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Internal implementation of Edmonds-Karp algorithm
|
|
310
|
+
* @param graph - The graph with capacity values
|
|
311
|
+
* @param source - The source node
|
|
312
|
+
* @param sink - The sink node
|
|
313
|
+
* @returns The maximum flow result
|
|
314
|
+
*/
|
|
315
|
+
function edmondsKarpImpl(graph: Map<string, Map<string, number>>, source: string, sink: string): MaxFlowResult {
|
|
316
|
+
// Use BFS variant for path finding
|
|
317
|
+
const findPathBFS = (
|
|
318
|
+
residual: Map<string, Map<string, number>>,
|
|
319
|
+
src: string,
|
|
320
|
+
snk: string,
|
|
321
|
+
): { path: string[]; pathCapacity: number } | null => {
|
|
322
|
+
return bfsAugmentingPath(residual, src, snk);
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
return maxFlowCore(graph, source, sink, findPathBFS);
|
|
406
326
|
}
|
|
407
327
|
|
|
408
328
|
/**
|
|
409
329
|
* Utility function to create a flow network for bipartite matching
|
|
330
|
+
* @param leftNodes - Array of left partition node identifiers
|
|
331
|
+
* @param rightNodes - Array of right partition node identifiers
|
|
332
|
+
* @param edges - Array of edges connecting left nodes to right nodes
|
|
333
|
+
* @returns The flow network graph with source and sink nodes
|
|
410
334
|
*/
|
|
411
335
|
export function createBipartiteFlowNetwork(
|
|
412
336
|
leftNodes: string[],
|
|
413
337
|
rightNodes: string[],
|
|
414
338
|
edges: [string, string][],
|
|
415
|
-
): {graph: Map<string, Map<string, number
|
|
339
|
+
): { graph: Map<string, Map<string, number>>; source: string; sink: string } {
|
|
416
340
|
const graph = new Map<string, Map<string, number>>();
|
|
417
341
|
const source = "__source__";
|
|
418
342
|
const sink = "__sink__";
|
|
@@ -454,6 +378,41 @@ export function createBipartiteFlowNetwork(
|
|
|
454
378
|
|
|
455
379
|
graph.set(sink, new Map());
|
|
456
380
|
|
|
457
|
-
return {graph, source, sink};
|
|
381
|
+
return { graph, source, sink };
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Ford-Fulkerson algorithm using DFS for finding augmenting paths
|
|
386
|
+
* @param graph - Adjacency list representation with capacities - accepts Graph class or Map
|
|
387
|
+
* @param source - Source node
|
|
388
|
+
* @param sink - Sink node
|
|
389
|
+
* @returns Maximum flow value and flow graph
|
|
390
|
+
*
|
|
391
|
+
* Time Complexity: O(E * f) where f is the maximum flow
|
|
392
|
+
* Space Complexity: O(V + E)
|
|
393
|
+
*/
|
|
394
|
+
export function fordFulkerson(graph: Graph, source: string, sink: string): MaxFlowResult {
|
|
395
|
+
// Convert Graph to Map representation
|
|
396
|
+
const graphMap = graphToMap(graph);
|
|
397
|
+
return fordFulkersonImpl(graphMap, source, sink);
|
|
458
398
|
}
|
|
459
399
|
|
|
400
|
+
/**
|
|
401
|
+
* Edmonds-Karp algorithm (Ford-Fulkerson with BFS)
|
|
402
|
+
* More efficient implementation with better time complexity
|
|
403
|
+
* @param graph - Adjacency list representation with capacities - accepts Graph class or Map
|
|
404
|
+
* @param source - Source node
|
|
405
|
+
* @param sink - Sink node
|
|
406
|
+
* @returns Maximum flow value and flow graph
|
|
407
|
+
*
|
|
408
|
+
* Time Complexity: O(V * E²)
|
|
409
|
+
*/
|
|
410
|
+
export function edmondsKarp(
|
|
411
|
+
graph: Graph | Map<string, Map<string, number>>,
|
|
412
|
+
source: string,
|
|
413
|
+
sink: string,
|
|
414
|
+
): MaxFlowResult {
|
|
415
|
+
// Convert Graph to Map representation if needed
|
|
416
|
+
const graphMap = graph instanceof Map ? graph : graphToMap(graph);
|
|
417
|
+
return edmondsKarpImpl(graphMap, source, sink);
|
|
418
|
+
}
|