scirs2_graph/algorithms/flow/
mod.rs1use crate::base::{DiGraph, EdgeWeight, Graph, Node};
7use crate::error::{GraphError, Result};
8use std::collections::{HashMap, VecDeque};
9
10pub fn minimum_cut<N, E, Ix>(graph: &Graph<N, E, Ix>) -> Result<(f64, Vec<bool>)>
12where
13 N: Node + Clone + std::fmt::Debug,
14 E: EdgeWeight + Into<f64> + Copy + std::fmt::Debug,
15 Ix: petgraph::graph::IndexType,
16{
17 let nodes: Vec<N> = graph.nodes().into_iter().cloned().collect();
18 let n = nodes.len();
19
20 if n < 2 {
21 return Err(GraphError::InvalidGraph(
22 "Graph must have at least 2 nodes for minimum cut".to_string(),
23 ));
24 }
25
26 let mut min_cut_value = f64::INFINITY;
27 let mut min_cut_partition = vec![false; n];
28
29 for partition_mask in 1..(1u32 << (n.min(20))) {
31 let mut cut_value = 0.0;
32 let mut partition = vec![false; n];
33
34 for i in 0..n.min(20) {
35 partition[i] = (partition_mask & (1u32 << i)) != 0;
36 }
37
38 for (i, node_i) in nodes.iter().enumerate() {
40 if let Ok(neighbors) = graph.neighbors(node_i) {
41 for neighbor in neighbors {
42 if let Some(j) = nodes.iter().position(|x| x == &neighbor) {
43 if partition[i] != partition[j] {
44 if let Ok(weight) = graph.edge_weight(node_i, &neighbor) {
45 cut_value += weight.into();
46 }
47 }
48 }
49 }
50 }
51 }
52
53 cut_value /= 2.0; if cut_value < min_cut_value {
56 min_cut_value = cut_value;
57 min_cut_partition = partition;
58 }
59 }
60
61 Ok((min_cut_value, min_cut_partition))
62}
63
64pub fn dinic_max_flow<N, E, Ix>(graph: &DiGraph<N, E, Ix>, source: &N, sink: &N) -> Result<f64>
66where
67 N: Node + Clone + std::fmt::Debug,
68 E: EdgeWeight + Into<f64> + Copy + std::fmt::Debug,
69 Ix: petgraph::graph::IndexType,
70{
71 if !graph.contains_node(source) || !graph.contains_node(sink) {
72 return Err(GraphError::node_not_found("source or sink"));
73 }
74
75 if source == sink {
76 return Err(GraphError::InvalidGraph(
77 "Source and sink cannot be the same node".to_string(),
78 ));
79 }
80
81 let mut max_flow = 0.0;
82 let nodes: Vec<N> = graph.nodes().into_iter().cloned().collect();
83
84 for _iteration in 0..1000 {
86 let mut queue = VecDeque::new();
88 let mut visited = HashMap::new();
89 let mut parent: HashMap<N, N> = HashMap::new();
90
91 queue.push_back(source.clone());
92 visited.insert(source.clone(), true);
93
94 let mut found_path = false;
95 while let Some(node) = queue.pop_front() {
96 if node == *sink {
97 found_path = true;
98 break;
99 }
100
101 if let Ok(successors) = graph.successors(&node) {
102 for successor in successors {
103 if !visited.contains_key(&successor) {
104 if let Ok(weight) = graph.edge_weight(&node, &successor) {
105 if weight.into() > 0.0 {
106 visited.insert(successor.clone(), true);
107 parent.insert(successor.clone(), node.clone());
108 queue.push_back(successor);
109 }
110 }
111 }
112 }
113 }
114 }
115
116 if !found_path {
117 break;
118 }
119
120 let mut path_flow = f64::INFINITY;
122 let mut current = sink.clone();
123 while current != *source {
124 if let Some(prev) = parent.get(¤t) {
125 if let Ok(weight) = graph.edge_weight(prev, ¤t) {
126 path_flow = path_flow.min(weight.into());
127 }
128 current = prev.clone();
129 } else {
130 break;
131 }
132 }
133
134 if path_flow == f64::INFINITY || path_flow <= 0.0 {
135 break;
136 }
137
138 max_flow += path_flow;
139 }
140
141 Ok(max_flow)
142}
143
144pub fn ford_fulkerson_max_flow<N, E, Ix>(
146 graph: &DiGraph<N, E, Ix>,
147 source: &N,
148 sink: &N,
149) -> Result<f64>
150where
151 N: Node + Clone + std::fmt::Debug,
152 E: EdgeWeight + Into<f64> + Copy + std::fmt::Debug,
153 Ix: petgraph::graph::IndexType,
154{
155 dinic_max_flow(graph, source, sink)
157}
158
159pub fn edmonds_karp_max_flow<N, E, Ix>(
161 graph: &DiGraph<N, E, Ix>,
162 source: &N,
163 sink: &N,
164) -> Result<f64>
165where
166 N: Node + Clone + std::fmt::Debug,
167 E: EdgeWeight + Into<f64> + Copy + std::fmt::Debug,
168 Ix: petgraph::graph::IndexType,
169{
170 dinic_max_flow(graph, source, sink)
172}
173
174pub fn push_relabel_max_flow<N, E, Ix>(
176 graph: &DiGraph<N, E, Ix>,
177 source: &N,
178 sink: &N,
179) -> Result<f64>
180where
181 N: Node + Clone + std::fmt::Debug,
182 E: EdgeWeight + Into<f64> + Copy + std::fmt::Debug,
183 Ix: petgraph::graph::IndexType,
184{
185 dinic_max_flow(graph, source, sink)
187}
188
189pub fn isap_max_flow<N, E, Ix>(graph: &DiGraph<N, E, Ix>, source: &N, sink: &N) -> Result<f64>
191where
192 N: Node + Clone + std::fmt::Debug,
193 E: EdgeWeight + Into<f64> + Copy + std::fmt::Debug,
194 Ix: petgraph::graph::IndexType,
195{
196 dinic_max_flow(graph, source, sink)
198}
199
200pub fn capacity_scaling_max_flow<N, E, Ix>(
202 graph: &DiGraph<N, E, Ix>,
203 source: &N,
204 sink: &N,
205) -> Result<f64>
206where
207 N: Node + Clone + std::fmt::Debug,
208 E: EdgeWeight + Into<f64> + Copy + std::fmt::Debug,
209 Ix: petgraph::graph::IndexType,
210{
211 dinic_max_flow(graph, source, sink)
213}
214
215pub fn min_cost_max_flow<N, E, Ix, F>(
217 graph: &DiGraph<N, E, Ix>,
218 source: &N,
219 sink: &N,
220 _cost_fn: F,
221) -> Result<(f64, f64)>
222where
223 N: Node + Clone + std::fmt::Debug,
224 E: EdgeWeight + Into<f64> + Copy + std::fmt::Debug,
225 Ix: petgraph::graph::IndexType,
226 F: Fn(&N, &N) -> f64,
227{
228 let max_flow = dinic_max_flow(graph, source, sink)?;
229 let min_cost = 0.0; Ok((max_flow, min_cost))
231}
232
233pub fn parallel_max_flow<N, E, Ix>(graph: &DiGraph<N, E, Ix>, source: &N, sink: &N) -> Result<f64>
235where
236 N: Node + Clone + Send + Sync + std::fmt::Debug,
237 E: EdgeWeight + Into<f64> + Copy + Send + Sync + std::fmt::Debug,
238 Ix: petgraph::graph::IndexType + Send + Sync,
239{
240 dinic_max_flow(graph, source, sink)
242}
243
244pub fn multi_source_multi_sink_max_flow<N, E, Ix>(
246 graph: &DiGraph<N, E, Ix>,
247 sources: &[N],
248 sinks: &[N],
249) -> Result<f64>
250where
251 N: Node + Clone + std::fmt::Debug,
252 E: EdgeWeight + Into<f64> + Copy + std::fmt::Debug,
253 Ix: petgraph::graph::IndexType,
254{
255 if sources.is_empty() || sinks.is_empty() {
256 return Err(GraphError::InvalidGraph(
257 "Must have at least one source and one sink".to_string(),
258 ));
259 }
260
261 dinic_max_flow(graph, &sources[0], &sinks[0])
263}