-
-
Notifications
You must be signed in to change notification settings - Fork 412
Added the implementation of the Edmond Karp algorithm along with test cases #252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
raklaptudirm
merged 12 commits into
TheAlgorithms:master
from
mapcrafter2048:algorithm/edmondkarp
Oct 16, 2024
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
9b477f1
Added the implementation for bijection method binary to decimal and e…
mapcrafter2048 a358ea6
Added the implementation of the edmondkarp along with tests
mapcrafter2048 b560c2e
Update graph/edmondkarp.ts
mapcrafter2048 13ba5a3
Update edmondkarp.ts
mapcrafter2048 ab770c3
Update graph/edmondkarp.ts
mapcrafter2048 6fed73d
Implement the furhter changes to make the algorithm more refined
mapcrafter2048 b5daf9f
Updated the test cases
mapcrafter2048 4b5f2b5
Updated the code and rewrite some functions
mapcrafter2048 76dd412
Implement the optimal stack queue implementation in the edmond karp a…
mapcrafter2048 2aa4555
Implement the optimal stack queue implementation in the edmond karp a…
mapcrafter2048 f97e200
removed the bisection_method.ts, decimal_convert.ts, euler_method.ts
mapcrafter2048 97adbc8
Revert changes to package.json and package-lock.json
mapcrafter2048 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { StackQueue } from '../data_structures/queue/stack_queue' | ||
|
||
/** | ||
* @function edmondsKarp | ||
* @description Compute the maximum flow from a source node to a sink node using the Edmonds-Karp algorithm. | ||
* @Complexity_Analysis | ||
* Time complexity: O(V * E^2) where V is the number of vertices and E is the number of edges. | ||
* Space Complexity: O(E) due to residual graph representation. | ||
* @param {[number, number][][]} graph - The graph in adjacency list form. | ||
* @param {number} source - The source node. | ||
* @param {number} sink - The sink node. | ||
* @return {number} - The maximum flow from the source node to the sink node. | ||
* @see https://en.wikipedia.org/wiki/Edmonds%E2%80%93Karp_algorithm | ||
*/ | ||
export default function edmondsKarp( | ||
graph: [number, number][][], | ||
source: number, | ||
sink: number | ||
): number { | ||
const n = graph.length | ||
|
||
// Initialize residual graph | ||
const residualGraph: [number, number][][] = Array.from( | ||
{ length: n }, | ||
() => [] | ||
) | ||
|
||
// Build residual graph from the original graph | ||
for (let u = 0; u < n; u++) { | ||
for (const [v, cap] of graph[u]) { | ||
if (cap > 0) { | ||
residualGraph[u].push([v, cap]) // Forward edge | ||
residualGraph[v].push([u, 0]) // Reverse edge with 0 capacity | ||
} | ||
} | ||
} | ||
|
||
const findAugmentingPath = (parent: (number | null)[]): number => { | ||
const visited = Array(n).fill(false) | ||
const queue = new StackQueue<number>() | ||
queue.enqueue(source) | ||
visited[source] = true | ||
parent[source] = null | ||
|
||
while (queue.length() > 0) { | ||
const u = queue.dequeue() | ||
for (const [v, cap] of residualGraph[u]) { | ||
if (!visited[v] && cap > 0) { | ||
parent[v] = u | ||
visited[v] = true | ||
if (v === sink) { | ||
// Return the bottleneck capacity along the path | ||
let pathFlow = Infinity | ||
let current = v | ||
while (parent[current] !== null) { | ||
const prev = parent[current]! | ||
const edgeCap = residualGraph[prev].find( | ||
([node]) => node === current | ||
)![1] | ||
pathFlow = Math.min(pathFlow, edgeCap) | ||
current = prev | ||
} | ||
return pathFlow | ||
} | ||
queue.enqueue(v) | ||
} | ||
} | ||
} | ||
return 0 | ||
} | ||
|
||
let maxFlow = 0 | ||
const parent = Array(n).fill(null) | ||
|
||
while (true) { | ||
const pathFlow = findAugmentingPath(parent) | ||
if (pathFlow === 0) break // No augmenting path found | ||
|
||
// Update the capacities and reverse capacities in the residual graph | ||
let v = sink | ||
while (parent[v] !== null) { | ||
const u = parent[v]! | ||
// Update capacity of the forward edge | ||
const forwardEdge = residualGraph[u].find(([node]) => node === v)! | ||
forwardEdge[1] -= pathFlow | ||
// Update capacity of the reverse edge | ||
const reverseEdge = residualGraph[v].find(([node]) => node === u)! | ||
reverseEdge[1] += pathFlow | ||
|
||
v = u | ||
} | ||
|
||
maxFlow += pathFlow | ||
} | ||
|
||
return maxFlow | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import edmondsKarp from '../edmonds_karp' | ||
|
||
describe('Edmonds-Karp Algorithm', () => { | ||
it('should find the maximum flow in a simple graph', () => { | ||
const graph: [number, number][][] = [ | ||
[ | ||
[1, 3], | ||
[2, 2] | ||
], // Node 0: Edges to node 1 (capacity 3), and node 2 (capacity 2) | ||
[[3, 2]], // Node 1: Edge to node 3 (capacity 2) | ||
[[3, 3]], // Node 2: Edge to node 3 (capacity 3) | ||
[] // Node 3: No outgoing edges | ||
] | ||
const source = 0 | ||
const sink = 3 | ||
const maxFlow = edmondsKarp(graph, source, sink) | ||
expect(maxFlow).toBe(4) | ||
}) | ||
|
||
it('should find the maximum flow in a more complex graph', () => { | ||
const graph: [number, number][][] = [ | ||
[ | ||
[1, 10], | ||
[2, 10] | ||
], // Node 0: Edges to node 1 and node 2 (both capacity 10) | ||
[ | ||
[3, 4], | ||
[4, 8] | ||
], // Node 1: Edges to node 3 (capacity 4), and node 4 (capacity 8) | ||
[[4, 9]], // Node 2: Edge to node 4 (capacity 9) | ||
[[5, 10]], // Node 3: Edge to node 5 (capacity 10) | ||
[[5, 10]], // Node 4: Edge to node 5 (capacity 10) | ||
[] // Node 5: No outgoing edges (sink) | ||
] | ||
const source = 0 | ||
const sink = 5 | ||
const maxFlow = edmondsKarp(graph, source, sink) | ||
expect(maxFlow).toBe(14) | ||
}) | ||
|
||
it('should return 0 when there is no path from source to sink', () => { | ||
const graph: [number, number][][] = [ | ||
[], // Node 0: No outgoing edges | ||
[], // Node 1: No outgoing edges | ||
[] // Node 2: No outgoing edges (sink) | ||
] | ||
const source = 0 | ||
const sink = 2 | ||
const maxFlow = edmondsKarp(graph, source, sink) | ||
expect(maxFlow).toBe(0) | ||
}) | ||
|
||
it('should handle graphs with no edges', () => { | ||
const graph: [number, number][][] = [ | ||
[], // Node 0: No outgoing edges | ||
[], // Node 1: No outgoing edges | ||
[] // Node 2: No outgoing edges | ||
] | ||
const source = 0 | ||
const sink = 2 | ||
const maxFlow = edmondsKarp(graph, source, sink) | ||
expect(maxFlow).toBe(0) | ||
}) | ||
|
||
it('should handle graphs with self-loops', () => { | ||
const graph: [number, number][][] = [ | ||
[ | ||
[0, 10], | ||
[1, 10] | ||
], // Node 0: Self-loop with capacity 10, and edge to node 1 (capacity 10) | ||
[ | ||
[1, 10], | ||
[2, 10] | ||
], // Node 1: Self-loop and edge to node 2 | ||
[] // Node 2: No outgoing edges (sink) | ||
] | ||
const source = 0 | ||
const sink = 2 | ||
const maxFlow = edmondsKarp(graph, source, sink) | ||
expect(maxFlow).toBe(10) | ||
}) | ||
}) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.