weavatrix_graph/algo/flow/
core.rs1use super::cut::{indexed_nodes, residual_reachable};
2use crate::{GraphError, IndexGraphView, Result};
3use std::collections::VecDeque;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct MaxFlow<Node, Edge> {
7 value: u64,
8 edge_flows: Vec<(Edge, u64)>,
9 source_side: Vec<Node>,
10}
11
12impl<Node, Edge> MaxFlow<Node, Edge> {
13 #[must_use]
14 pub const fn value(&self) -> u64 {
15 self.value
16 }
17
18 #[must_use]
19 pub fn edge_flows(&self) -> &[(Edge, u64)] {
20 &self.edge_flows
21 }
22
23 #[must_use]
24 pub fn source_side(&self) -> &[Node] {
25 &self.source_side
26 }
27}
28
29pub fn maximum_flow<G, F>(
37 graph: &G,
38 source: G::Node,
39 sink: G::Node,
40 mut edge_capacity: F,
41) -> Result<Option<MaxFlow<G::Node, G::Edge>>>
42where
43 G: IndexGraphView,
44 F: FnMut(G::Edge) -> u64,
45{
46 if !graph.contains_node(source) || !graph.contains_node(sink) {
47 return Ok(None);
48 }
49 let mut capacities = vec![0_u64; graph.edge_bound()];
50 let mut edge_order = Vec::with_capacity(graph.edge_count());
51 for edge in graph.edge_indices() {
52 capacities[G::edge_slot(edge)] = edge_capacity(edge);
53 edge_order.push(edge);
54 }
55 if source == sink {
56 return Ok(Some(MaxFlow {
57 value: 0,
58 edge_flows: edge_order.into_iter().map(|edge| (edge, 0)).collect(),
59 source_side: vec![source],
60 }));
61 }
62
63 let mut flows = vec![0_u64; graph.edge_bound()];
64 let mut levels = vec![-1_i32; graph.node_bound()];
65 let mut level_edges = vec![Vec::new(); graph.node_bound()];
66 let mut total = 0_u64;
67 while build_levels(
68 graph,
69 source,
70 sink,
71 &capacities,
72 &flows,
73 &mut levels,
74 &mut level_edges,
75 ) {
76 let mut next = vec![0_usize; graph.node_bound()];
77 loop {
78 let pushed = augment_level_path::<G>(
79 G::node_slot(source),
80 G::node_slot(sink),
81 &level_edges,
82 &mut next,
83 &capacities,
84 &mut flows,
85 );
86 if pushed == 0 {
87 break;
88 }
89 total = total
90 .checked_add(pushed)
91 .ok_or(GraphError::ArithmeticOverflow {
92 operation: "maximum flow",
93 })?;
94 }
95 }
96
97 let edge_flows = edge_order
98 .into_iter()
99 .map(|edge| (edge, flows[G::edge_slot(edge)]))
100 .collect();
101 let reachable = residual_reachable(graph, source, &capacities, &flows);
102 let source_side = graph
103 .node_indices()
104 .filter(|node| reachable[G::node_slot(*node)])
105 .collect();
106 Ok(Some(MaxFlow {
107 value: total,
108 edge_flows,
109 source_side,
110 }))
111}
112
113#[derive(Clone, Copy)]
114struct ResidualEdge<Edge> {
115 edge: Edge,
116 target: usize,
117 forward: bool,
118}
119
120fn build_levels<G>(
121 graph: &G,
122 source: G::Node,
123 sink: G::Node,
124 capacities: &[u64],
125 flows: &[u64],
126 levels: &mut [i32],
127 level_edges: &mut [Vec<ResidualEdge<G::Edge>>],
128) -> bool
129where
130 G: IndexGraphView,
131{
132 levels.fill(-1);
133 for edges in &mut *level_edges {
134 edges.clear();
135 }
136 let source = G::node_slot(source);
137 let sink = G::node_slot(sink);
138 levels[source] = 0;
139 let mut queue = VecDeque::from([source]);
140 let nodes = indexed_nodes(graph);
141 while let Some(node) = queue.pop_front() {
142 let Some(node_key) = nodes[node] else {
143 continue;
144 };
145 for edge in graph.outgoing_edges(node_key) {
146 let slot = G::edge_slot(edge);
147 if capacities[slot] > flows[slot] {
148 let target = graph
149 .edge_endpoints(edge)
150 .map(|endpoints| G::node_slot(endpoints.target()));
151 add_level_edge(edge, target, true, node, levels, level_edges, &mut queue);
152 }
153 }
154 for edge in graph.incoming_edges(node_key) {
155 let slot = G::edge_slot(edge);
156 if flows[slot] > 0 {
157 let target = graph
158 .edge_endpoints(edge)
159 .map(|endpoints| G::node_slot(endpoints.source()));
160 add_level_edge(edge, target, false, node, levels, level_edges, &mut queue);
161 }
162 }
163 }
164 levels[sink] >= 0
165}
166
167fn add_level_edge<Edge: Copy>(
168 edge: Edge,
169 target: Option<usize>,
170 forward: bool,
171 source: usize,
172 levels: &mut [i32],
173 level_edges: &mut [Vec<ResidualEdge<Edge>>],
174 queue: &mut VecDeque<usize>,
175) {
176 let Some(target) = target else {
177 return;
178 };
179 if levels[target] < 0 {
180 levels[target] = levels[source] + 1;
181 queue.push_back(target);
182 }
183 if levels[target] == levels[source] + 1 {
184 level_edges[source].push(ResidualEdge {
185 edge,
186 target,
187 forward,
188 });
189 }
190}
191
192fn augment_level_path<G>(
193 source: usize,
194 sink: usize,
195 level_edges: &[Vec<ResidualEdge<G::Edge>>],
196 next: &mut [usize],
197 capacities: &[u64],
198 flows: &mut [u64],
199) -> u64
200where
201 G: IndexGraphView,
202{
203 let mut nodes = vec![source];
204 let mut path: Vec<ResidualEdge<G::Edge>> = Vec::new();
205 loop {
206 let node = *nodes.last().unwrap_or(&source);
207 if node == sink {
208 let amount = path
209 .iter()
210 .map(|step| residual::<G>(*step, capacities, flows))
211 .min()
212 .unwrap_or(0);
213 for step in &path {
214 let slot = G::edge_slot(step.edge);
215 if step.forward {
216 flows[slot] += amount;
217 } else {
218 flows[slot] -= amount;
219 }
220 }
221 return amount;
222 }
223 let Some(&step) = level_edges[node].get(next[node]) else {
224 if node == source {
225 return 0;
226 }
227 nodes.pop();
228 path.pop();
229 let parent = *nodes.last().unwrap_or(&source);
230 next[parent] += 1;
231 continue;
232 };
233 if residual::<G>(step, capacities, flows) > 0 {
234 nodes.push(step.target);
235 path.push(step);
236 } else {
237 next[node] += 1;
238 }
239 }
240}
241
242fn residual<G>(step: ResidualEdge<G::Edge>, capacities: &[u64], flows: &[u64]) -> u64
243where
244 G: IndexGraphView,
245{
246 let slot = G::edge_slot(step.edge);
247 if step.forward {
248 capacities[slot] - flows[slot]
249 } else {
250 flows[slot]
251 }
252}