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