rs_graph/maxflow/
dinic.rs

1// Copyright (c) 2015-2022 Frank Fischer <frank-fischer@shadow-soft.de>
2//
3// This program is free software: you can redistribute it and/or
4// modify it under the terms of the GNU General Public License as
5// published by the Free Software Foundation, either version 3 of the
6// License, or (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful, but
9// WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11// General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program.  If not, see  <http://www.gnu.org/licenses/>
15//
16
17//! This module implements Dinic' max flow algorithm
18//!
19//! # Example
20//!
21//! ```
22//! use rs_graph::traits::*;
23//! use rs_graph::maxflow::dinic;
24//! use rs_graph::Net;
25//! use rs_graph::string::{Data, from_ascii};
26//!
27//! let Data { graph: g, weights: upper, nodes } = from_ascii::<Net>(r"
28//!      a---2-->b
29//!     @|\      ^\
30//!    / | \     | 4
31//!   5  |  \    |  \
32//!  /   |   |   |   @
33//! s    1   1   2    t
34//!  \   |   |   |   @
35//!   5  |    \  |  /
36//!    \ |     \ | 5
37//!     @v      @|/
38//!      c---2-->d
39//!     ").unwrap();
40//!
41//! let s = g.id2node(nodes[&'s']);
42//! let t = g.id2node(nodes[&'t']);
43//! let v1 = g.id2node(nodes[&'a']);
44//! let v2 = g.id2node(nodes[&'b']);
45//! let v3 = g.id2node(nodes[&'c']);
46//! let v4 = g.id2node(nodes[&'d']);
47//!
48//! let (value, flow, mut mincut) = dinic(&g, s, t, |e| upper[e.index()]);
49//!
50//! assert_eq!(value, 5);
51//! assert!(flow.iter().all(|&(e, f)| f >= 0 && f <= upper[e.index()]));
52//! assert!(g.nodes().filter(|&u| u != s && u != t).all(|u| {
53//!     g.outedges(u).map(|(e,_)| flow[g.edge_id(e)].1).sum::<usize>() ==
54//!     g.inedges(u).map(|(e,_)| flow[g.edge_id(e)].1).sum::<usize>()
55//! }));
56//!
57//! mincut.sort_by_key(|u| u.index());
58//! assert_eq!(mincut, vec![v1, s, v3]);
59//! ```
60//!
61//! ```
62//! use rs_graph::traits::*;
63//! use rs_graph::maxflow::dinic;
64//! use rs_graph::Net;
65//! use rs_graph::string::{Data, from_ascii};
66//!
67//! let Data { graph: g, weights: upper, nodes } = from_ascii::<Net>(r"
68//!                ---8-->a---10---
69//!               /       |        \
70//!              /        1  --3--  |
71//!             /         | /     \ |
72//!            /          v@       \v
73//!      ---->b-----9---->c----8--->d----
74//!     /      \         @         @^    \
75//!   18        ---6--  /         / |     33
76//!   /               \/         /  |      \
77//!  /                /\    -----   |       @
78//! s           --5--- |   /        |        t
79//!  \         /       |  /         |       @
80//!   27      |  ----2-|--         /       /
81//!    \      | /      |  /----8---       6
82//!     \     |/       @  |              /
83//!      ---->e----9-->f------6---->g----
84//!            \          |        @
85//!             \         |       /
86//!              --5----->h---4---
87//!     ").unwrap();
88//!
89//! let s = g.id2node(nodes[&'s']);
90//! let t = g.id2node(nodes[&'t']);
91//!
92//! assert_eq!(g.num_edges(), 18);
93//!
94//! let (value, flow, mut mincut) = dinic(&g, s, t, |e| upper[e.index()]);
95//! assert_eq!(value, 29);
96//!
97//! mincut.sort_by_key(|u| u.index());
98//! assert_eq!(mincut, "bcsef".chars().map(|v| g.id2node(nodes[&v])).collect::<Vec<_>>());
99//! ```
100
101use crate::traits::IndexDigraph;
102
103use std::cmp::min;
104use std::collections::VecDeque;
105
106use crate::num::traits::NumAssign;
107
108/// The dinic max-flow algorithm.
109pub struct Dinic<'a, G, F>
110where
111    G: IndexDigraph,
112{
113    g: &'a G,
114    nodes: Vec<NodeInfo>,
115    neighs: Vec<Vec<(usize, usize)>>,
116    edges: Vec<EdgeInfo<F>>,
117    queue: VecDeque<usize>,
118    value: F,
119}
120
121#[derive(Clone)]
122struct NodeInfo {
123    dist: usize,
124    first_lvl: (usize, usize),
125}
126
127#[derive(Clone)]
128struct EdgeInfo<F> {
129    flow: F,
130    next_lvl: (usize, usize),
131}
132
133impl<'a, G, F> Dinic<'a, G, F>
134where
135    G: IndexDigraph,
136    F: NumAssign + Ord + Copy,
137{
138    /// Create a new Dinic algorithm instance for a graph.
139    pub fn new(g: &'a G) -> Self {
140        Dinic {
141            g,
142            nodes: vec![
143                NodeInfo {
144                    dist: 0,
145                    first_lvl: (usize::max_value(), usize::max_value()),
146                };
147                g.num_nodes()
148            ],
149            neighs: g
150                .nodes()
151                .map(|u| {
152                    g.outedges(u)
153                        .map(|(e, v)| (g.edge_id(e) << 1, g.node_id(v)))
154                        .chain(g.inedges(u).map(|(e, v)| ((g.edge_id(e) << 1) | 1, g.node_id(v))))
155                        .collect()
156                })
157                .collect(),
158            edges: vec![
159                EdgeInfo {
160                    flow: F::zero(),
161                    next_lvl: (usize::max_value(), usize::max_value()),
162                };
163                g.num_edges() * 2
164            ],
165            queue: VecDeque::with_capacity(g.num_nodes()),
166            value: F::zero(),
167        }
168    }
169
170    /// Return the underlying graph.
171    pub fn as_graph(&self) -> &'a G {
172        self.g
173    }
174
175    /// Return the value of the latest computed maximum flow.
176    pub fn value(&self) -> F {
177        self.value
178    }
179
180    /// Return the flow value on edge `e`
181    pub fn flow(&self, e: G::Edge<'_>) -> F {
182        self.edges[self.g.edge_id(e) << 1].flow
183    }
184
185    /// Return an iterator over all (edge, flow) pairs.
186    pub fn flow_iter<'b>(&'b self) -> impl Iterator<Item = (G::Edge<'a>, F)> + 'b {
187        self.g
188            .edges()
189            .enumerate()
190            .map(move |(i, e)| (e, self.edges[i << 1].flow))
191    }
192
193    /// Solve the maxflow problem.
194    ///
195    /// The method solved the max flow problem from the source node
196    /// `src` to the sink node `snk` with the given `upper` bounds on
197    /// the edges.
198    pub fn solve<Us>(&mut self, src: G::Node<'_>, snk: G::Node<'_>, upper: Us)
199    where
200        Us: Fn(G::Edge<'a>) -> F,
201    {
202        let src = self.g.node_id(src);
203        let snk = self.g.node_id(snk);
204        assert_ne!(src, snk, "Source and sink node must not be equal");
205
206        // initialize network flow of reverse edges
207        for (e, einfo) in self.edges.iter_mut().enumerate() {
208            einfo.flow = if (e & 1) == 0 {
209                F::zero()
210            } else {
211                upper(self.g.id2edge(e >> 1))
212            };
213        }
214
215        self.value = F::zero();
216        while self.search(src, snk) {
217            let v = self.augment(src, snk, None);
218            self.value += v;
219        }
220    }
221
222    /// Return the minimal cut associated with the last maximum flow.
223    pub fn mincut(&self) -> Vec<G::Node<'a>> {
224        let n = self.g.num_nodes();
225        self.g
226            .nodes()
227            .filter(|&u| self.nodes[self.g.node_id(u)].dist < n)
228            .collect()
229    }
230
231    fn search(&mut self, src: usize, snk: usize) -> bool {
232        let n = self.g.num_nodes();
233
234        for node in &mut self.nodes {
235            node.dist = n;
236            node.first_lvl = (usize::max_value(), usize::max_value());
237        }
238        self.nodes[src].dist = 0;
239
240        self.queue.clear();
241        self.queue.push_back(src);
242
243        let mut snk_d = n;
244        while let Some(u) = self.queue.pop_front() {
245            let d = self.nodes[u].dist;
246
247            if d >= snk_d {
248                return true;
249            }
250
251            for &(e, v) in &self.neighs[u] {
252                if self.edges[e ^ 1].flow > F::zero() {
253                    if self.nodes[v].dist == n {
254                        self.nodes[v].dist = d + 1;
255                        self.queue.push_back(v);
256                        if v == snk {
257                            snk_d = d + 1
258                        }
259                    } else if self.nodes[v].dist != d + 1 {
260                        continue;
261                    }
262                    self.edges[e].next_lvl = self.nodes[u].first_lvl;
263                    self.nodes[u].first_lvl = (e, v);
264                }
265            }
266        }
267
268        false
269    }
270
271    fn augment(&mut self, src: usize, snk: usize, target_flow: Option<F>) -> F {
272        if src == snk {
273            return target_flow.expect("Unbounded flow (are source and sink the same?)");
274        }
275
276        let mut df = F::zero();
277
278        loop {
279            let (e, v) = self.nodes[src].first_lvl;
280            if e == usize::max_value() {
281                break;
282            }
283            let f = e ^ 1;
284            let rem_cap = match target_flow {
285                Some(target_flow) => min(self.edges[f].flow, target_flow - df),
286                None => self.edges[f].flow,
287            };
288            if rem_cap > F::zero() {
289                let cf = self.augment(v, snk, Some(rem_cap));
290                self.edges[e].flow += cf;
291                self.edges[f].flow -= cf;
292                df += cf;
293                if target_flow.map(|t| df == t).unwrap_or(false) {
294                    break;
295                }
296            }
297
298            // edge is saturated or blocked
299            self.nodes[src].first_lvl = self.edges[e].next_lvl;
300        }
301
302        if df.is_zero() {
303            // nothing can be sent from this node, delete the node and
304            // all adjacent edges (we just remove the outgoing edges
305            // so that they won't be seen)
306            self.nodes[src].first_lvl = (usize::max_value(), usize::max_value());
307        }
308
309        df
310    }
311}
312
313/// Solve the maxflow problem using the algorithm of Dinic.
314///
315/// The function solves the max flow problem from the source nodes
316/// `src` to the sink node `snk` with the given `upper` bounds on
317/// the edges.
318///
319/// The function returns the flow value, the flow on each edge and the
320/// nodes in a minimal cut.
321pub fn dinic<'a, G, F, Us>(
322    g: &'a G,
323    src: G::Node<'_>,
324    snk: G::Node<'_>,
325    upper: Us,
326) -> (F, Vec<(G::Edge<'a>, F)>, Vec<G::Node<'a>>)
327where
328    G: IndexDigraph,
329    F: 'a + NumAssign + Ord + Copy,
330    Us: Fn(G::Edge<'_>) -> F,
331{
332    let mut maxflow = Dinic::new(g);
333    maxflow.solve(src, snk, upper);
334    (maxflow.value(), maxflow.flow_iter().collect(), maxflow.mincut())
335}