use crate::graph::traits::{GraphBase, GraphQuery};
use crate::graph::Graph;
use crate::node::NodeIndex;
use std::collections::{HashMap, VecDeque};
pub fn edmonds_karp<T, E, F>(
graph: &mut Graph<T, E>,
source: NodeIndex,
sink: NodeIndex,
mut capacity: F,
) -> f64
where
F: FnMut(NodeIndex, NodeIndex, &E) -> f64,
{
let n = graph.node_count();
if n == 0 {
return 0.0;
}
let node_indices: Vec<NodeIndex> = graph.nodes().map(|n| n.index()).collect();
let index_to_pos: HashMap<usize, usize> = node_indices
.iter()
.enumerate()
.map(|(i, ni)| (ni.index(), i))
.collect();
let mut adj: HashMap<usize, Vec<(usize, f64)>> = HashMap::with_capacity(n);
for edge in graph.edges() {
if let Ok((src, tgt)) = graph.edge_endpoints(edge.index()) {
if let Some(&u) = index_to_pos.get(&src.index()) {
if let Some(&v) = index_to_pos.get(&tgt.index()) {
let cap = capacity(src, tgt, edge.data());
if cap > 0.0 {
adj.entry(u).or_default().push((v, cap));
adj.entry(v).or_default().push((u, 0.0));
}
}
}
}
}
let mut max_flow = 0.0;
fn bfs(
adj: &HashMap<usize, Vec<(usize, f64)>>,
source_pos: usize,
sink_pos: usize,
n: usize,
parent: &mut [(isize, usize)], ) -> bool {
parent.fill((-1, 0));
let mut visited = vec![false; n];
let mut queue = VecDeque::new();
queue.push_back(source_pos);
visited[source_pos] = true;
while let Some(u) = queue.pop_front() {
if let Some(neighbors) = adj.get(&u) {
for (idx, (v, cap)) in neighbors.iter().enumerate() {
if !visited[*v] && *cap > 1e-9 {
visited[*v] = true;
parent[*v] = (u as isize, idx);
if *v == sink_pos {
return true;
}
queue.push_back(*v);
}
}
}
}
false
}
let source_pos = *index_to_pos.get(&source.index()).unwrap_or(&0);
let sink_pos = *index_to_pos.get(&sink.index()).unwrap_or(&0);
let mut parent = vec![(-1, 0); n];
while bfs(&adj, source_pos, sink_pos, n, &mut parent) {
let mut path_flow = f64::INFINITY;
let mut v = sink_pos;
while v != source_pos {
let (u, edge_idx) = parent[v];
let u = u as usize;
if let Some(neighbors) = adj.get(&u) {
if let Some((_, cap)) = neighbors.get(edge_idx) {
path_flow = path_flow.min(*cap);
}
}
v = u;
}
let mut v = sink_pos;
while v != source_pos {
let (u, edge_idx) = parent[v];
let u = u as usize;
if let Some(neighbors) = adj.get_mut(&u) {
if let Some((_target, cap)) = neighbors.get_mut(edge_idx) {
*cap -= path_flow;
let target_val = *_target;
if let Some(reverse_neighbors) = adj.get_mut(&v) {
if let Some((_, rev_cap)) =
reverse_neighbors.iter_mut().find(|(t, _)| *t == target_val)
{
*rev_cap += path_flow;
}
}
}
}
v = u;
}
max_flow += path_flow;
}
max_flow
}
pub fn dinic<T, E, F>(
graph: &mut Graph<T, E>,
source: NodeIndex,
sink: NodeIndex,
mut capacity: F,
) -> f64
where
F: FnMut(NodeIndex, NodeIndex, &E) -> f64,
{
let n = graph.node_count();
if n == 0 {
return 0.0;
}
let node_indices: Vec<NodeIndex> = graph.nodes().map(|n| n.index()).collect();
let index_to_pos: HashMap<usize, usize> = node_indices
.iter()
.enumerate()
.map(|(i, ni)| (ni.index(), i))
.collect();
let mut adj: Vec<Vec<usize>> = vec![Vec::new(); n];
let mut residual: HashMap<usize, HashMap<usize, f64>> = HashMap::with_capacity(n);
for edge in graph.edges() {
if let Ok((src, tgt)) = graph.edge_endpoints(edge.index()) {
if let (Some(&u), Some(&v)) = (
index_to_pos.get(&src.index()),
index_to_pos.get(&tgt.index()),
) {
let cap = capacity(src, tgt, edge.data());
if !residual
.get(&u)
.map(|m| m.contains_key(&v))
.unwrap_or(false)
{
adj[u].push(v);
}
residual.entry(u).or_default().insert(v, cap);
}
}
}
let source_pos = *index_to_pos.get(&source.index()).unwrap_or(&0);
let sink_pos = *index_to_pos.get(&sink.index()).unwrap_or(&0);
let mut max_flow = 0.0;
fn bfs_level(
adj: &[Vec<usize>],
residual: &HashMap<usize, HashMap<usize, f64>>,
source_pos: usize,
sink_pos: usize,
level: &mut [isize],
) -> bool {
let _n = adj.len();
level.fill(-1);
level[source_pos] = 0;
let mut queue = VecDeque::new();
queue.push_back(source_pos);
while let Some(u) = queue.pop_front() {
if let Some(neighbors) = adj.get(u) {
for &v in neighbors {
let cap = residual
.get(&u)
.and_then(|m| m.get(&v))
.copied()
.unwrap_or(0.0);
if level[v] == -1 && cap > 1e-9 {
level[v] = level[u] + 1;
if v == sink_pos {
return true;
}
queue.push_back(v);
}
}
}
}
false
}
fn dfs_block(
u: usize,
flow: f64,
sink_pos: usize,
adj: &[Vec<usize>],
residual: &mut HashMap<usize, HashMap<usize, f64>>,
level: &mut [isize],
ptr: &mut [usize],
) -> f64 {
if u == sink_pos || flow < 1e-9 {
return flow;
}
let start = ptr[u];
for i in start..adj[u].len() {
ptr[u] = i;
let v = adj[u][i];
let cap = residual
.get(&u)
.and_then(|m| m.get(&v))
.copied()
.unwrap_or(0.0);
if level[v] == level[u] + 1 && cap > 1e-9 {
let pushed = dfs_block(v, flow.min(cap), sink_pos, adj, residual, level, ptr);
if pushed > 1e-9 {
*residual.entry(u).or_default().get_mut(&v).unwrap() -= pushed;
*residual.entry(v).or_default().entry(u).or_insert(0.0) += pushed;
return pushed;
}
}
}
0.0
}
let mut level = vec![-1; n];
let mut ptr = vec![0; n];
while bfs_level(&adj, &residual, source_pos, sink_pos, &mut level) {
ptr.fill(0);
while let Some(push) = {
let pushed = dfs_block(
source_pos,
f64::INFINITY,
sink_pos,
&adj,
&mut residual,
&mut level,
&mut ptr,
);
if pushed > 1e-9 {
Some(pushed)
} else {
None
}
} {
max_flow += push;
}
}
max_flow
}
pub fn push_relabel<T, E, F>(
graph: &mut Graph<T, E>,
source: NodeIndex,
sink: NodeIndex,
mut capacity: F,
) -> f64
where
F: FnMut(NodeIndex, NodeIndex, &E) -> f64,
{
let n = graph.node_count();
if n == 0 {
return 0.0;
}
let node_indices: Vec<NodeIndex> = graph.nodes().map(|n| n.index()).collect();
let index_to_pos: HashMap<usize, usize> = node_indices
.iter()
.enumerate()
.map(|(i, ni)| (ni.index(), i))
.collect();
let source_pos = index_to_pos[&source.index()];
let sink_pos = index_to_pos[&sink.index()];
let mut adj: Vec<Vec<usize>> = vec![vec![]; n];
let mut residual: HashMap<usize, HashMap<usize, f64>> = HashMap::with_capacity(n);
for edge in graph.edges() {
if let Ok((src, tgt)) = graph.edge_endpoints(edge.index()) {
if let Some(&u) = index_to_pos.get(&src.index()) {
if let Some(&v) = index_to_pos.get(&tgt.index()) {
let cap = capacity(src, tgt, edge.data());
residual.entry(u).or_default().insert(v, cap);
adj[u].push(v);
adj[v].push(u); }
}
}
}
let mut height = vec![0; n];
let mut excess = vec![0.0; n];
height[source_pos] = n;
for &v in &adj[source_pos] {
if let Some(cap) = residual.get(&source_pos).and_then(|m| m.get(&v)).copied() {
if cap > 1e-9 {
*residual
.entry(source_pos)
.or_default()
.entry(v)
.or_insert(0.0) = 0.0;
*residual
.entry(v)
.or_default()
.entry(source_pos)
.or_insert(0.0) = cap;
excess[v] = cap;
excess[source_pos] -= cap;
}
}
}
let mut queue: VecDeque<usize> = VecDeque::new();
let mut in_queue = vec![false; n];
for i in 0..n {
if i != source_pos && i != sink_pos && excess[i] > 1e-9 {
queue.push_back(i);
in_queue[i] = true;
}
}
while let Some(u) = queue.pop_front() {
in_queue[u] = false;
if excess[u] <= 1e-9 {
continue;
}
let mut pushed = false;
if let Some(neighbors) = adj.get(u) {
for &v in neighbors {
let cap = residual
.get(&u)
.and_then(|m| m.get(&v))
.copied()
.unwrap_or(0.0);
if cap > 1e-9 && height[u] == height[v] + 1 {
let delta = excess[u].min(cap);
*residual.entry(u).or_default().entry(v).or_insert(0.0) -= delta;
*residual.entry(v).or_default().entry(u).or_insert(0.0) += delta;
excess[u] -= delta;
excess[v] += delta;
if v != source_pos && v != sink_pos && !in_queue[v] && excess[v] > 1e-9 {
queue.push_back(v);
in_queue[v] = true;
}
if excess[u] <= 1e-9 {
pushed = true;
break;
}
}
}
}
if !pushed && excess[u] > 1e-9 {
let mut min_height = usize::MAX;
if let Some(neighbors) = adj.get(u) {
for &v in neighbors {
let cap = residual
.get(&u)
.and_then(|m| m.get(&v))
.copied()
.unwrap_or(0.0);
if cap > 1e-9 && height[v] < min_height {
min_height = height[v];
}
}
}
if min_height < usize::MAX {
height[u] = min_height + 1;
}
if !in_queue[u] {
queue.push_back(u);
in_queue[u] = true;
}
}
}
let mut max_flow = 0.0;
if let Some(neighbors) = adj.get(source_pos) {
for &v in neighbors {
let cap = residual
.get(&v)
.and_then(|m| m.get(&source_pos))
.copied()
.unwrap_or(0.0);
if cap > 1e-9 {
max_flow += cap;
}
}
}
max_flow
}
#[cfg(test)]
mod tests {
use super::*;
use crate::graph::builders::GraphBuilder;
#[test]
fn test_edmonds_karp_basic() {
let mut graph = GraphBuilder::directed()
.with_nodes(vec!["S", "A", "B", "C", "D", "T"])
.with_edges(vec![
(0, 1, 16.0), (0, 2, 13.0), (1, 2, 10.0), (1, 3, 12.0), (2, 1, 4.0), (2, 4, 14.0), (3, 1, 9.0), (3, 5, 20.0), (4, 3, 7.0), (4, 5, 4.0), ])
.build()
.unwrap();
let source = NodeIndex::new(0, 1);
let sink = NodeIndex::new(5, 1);
let max_flow = edmonds_karp(&mut graph, source, sink, |_, _, cap| *cap);
assert_eq!(max_flow, 23.0);
}
#[test]
fn test_dinic_basic() {
let mut graph = GraphBuilder::directed()
.with_nodes(vec!["S", "A", "B", "T"])
.with_edges(vec![
(0, 1, 10.0), (0, 2, 5.0), (1, 2, 15.0), (1, 3, 10.0), (2, 3, 10.0), ])
.build()
.unwrap();
let source = NodeIndex::new(0, 1);
let sink = NodeIndex::new(3, 1);
let max_flow = dinic(&mut graph, source, sink, |_, _, cap| *cap);
assert_eq!(max_flow, 15.0);
}
#[test]
fn test_edmonds_karp_simple() {
let mut graph = GraphBuilder::directed()
.with_nodes(vec!["S", "A", "T"])
.with_edges(vec![
(0, 1, 5.0), (1, 2, 3.0), ])
.build()
.unwrap();
let source = NodeIndex::new(0, 1);
let sink = NodeIndex::new(2, 1);
let max_flow = edmonds_karp(&mut graph, source, sink, |_, _, cap| *cap);
assert_eq!(max_flow, 3.0); }
#[test]
fn test_push_relabel_basic() {
let mut graph = GraphBuilder::directed()
.with_nodes(vec!["S", "A", "B", "T"])
.with_edges(vec![
(0, 1, 10.0), (0, 2, 5.0), (1, 2, 15.0), (1, 3, 10.0), (2, 3, 10.0), ])
.build()
.unwrap();
let source = NodeIndex::new(0, 1);
let sink = NodeIndex::new(3, 1);
let max_flow = push_relabel(&mut graph, source, sink, |_, _, cap| *cap);
assert_eq!(max_flow, 15.0);
}
#[test]
fn test_edmonds_karp_no_path() {
let mut graph = GraphBuilder::directed()
.with_nodes(vec!["S", "A", "B", "T"])
.with_edges(vec![
(0, 1, 10.0), (2, 3, 5.0), ])
.build()
.unwrap();
let source = NodeIndex::new(0, 1);
let sink = NodeIndex::new(3, 1);
let max_flow = edmonds_karp(&mut graph, source, sink, |_, _, cap| *cap);
assert_eq!(max_flow, 0.0);
}
#[test]
fn test_dinic_no_path() {
let mut graph = GraphBuilder::directed()
.with_nodes(vec!["S", "A", "B", "T"])
.with_edges(vec![
(0, 1, 10.0), (2, 3, 5.0), ])
.build()
.unwrap();
let source = NodeIndex::new(0, 1);
let sink = NodeIndex::new(3, 1);
let max_flow = dinic(&mut graph, source, sink, |_, _, cap| *cap);
assert_eq!(max_flow, 0.0);
}
#[test]
fn test_edmonds_karp_single_edge() {
let mut graph = GraphBuilder::directed()
.with_nodes(vec!["S", "T"])
.with_edges(vec![(0, 1, 42.0)])
.build()
.unwrap();
let source = NodeIndex::new(0, 1);
let sink = NodeIndex::new(1, 1);
let max_flow = edmonds_karp(&mut graph, source, sink, |_, _, cap| *cap);
assert_eq!(max_flow, 42.0);
}
#[test]
fn test_dinic_single_edge() {
let mut graph = GraphBuilder::directed()
.with_nodes(vec!["S", "T"])
.with_edges(vec![(0, 1, 42.0)])
.build()
.unwrap();
let source = NodeIndex::new(0, 1);
let sink = NodeIndex::new(1, 1);
let max_flow = dinic(&mut graph, source, sink, |_, _, cap| *cap);
assert_eq!(max_flow, 42.0);
}
#[test]
fn test_push_relabel_no_path() {
let mut graph = GraphBuilder::directed()
.with_nodes(vec!["S", "A", "B", "T"])
.with_edges(vec![
(0, 1, 10.0), (2, 3, 5.0), ])
.build()
.unwrap();
let source = NodeIndex::new(0, 1);
let sink = NodeIndex::new(3, 1);
let max_flow = push_relabel(&mut graph, source, sink, |_, _, cap| *cap);
assert_eq!(max_flow, 0.0);
}
#[test]
fn test_edmonds_karp_zero_capacity() {
let mut graph = GraphBuilder::directed()
.with_nodes(vec!["S", "A", "T"])
.with_edges(vec![
(0, 1, 0.0), (1, 2, 5.0), ])
.build()
.unwrap();
let source = NodeIndex::new(0, 1);
let sink = NodeIndex::new(2, 1);
let max_flow = edmonds_karp(&mut graph, source, sink, |_, _, cap| *cap);
assert_eq!(max_flow, 0.0);
}
}