fera_graph/algs/
components.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5//! Components related algorithms, including connectivity, cuts, etc.
6
7use prelude::*;
8use props::Color;
9use traverse::*;
10
11use fera_fun::{first, vec};
12use num_traits::{zero, Zero};
13
14use std::cmp::min;
15use std::marker::PhantomData;
16
17// FIXME: restrict the method to appropriated graph type
18pub trait Components: Incidence {
19    fn num_components(&self) -> u64
20    where
21        Self: VertexList + WithVertexProp<Color>,
22    {
23        let mut num = 0;
24        self.dfs(NumComponents(&mut num)).run();
25        num
26    }
27
28    fn connected_components(&self) -> ConnectedComponents<Self, DefaultVertexPropMut<Self, usize>>
29    where
30        Self: VertexList + WithVertexProp<Color> + WithVertexProp<usize>,
31    {
32        let mut cc = ConnectedComponents(self, self.vertex_prop(0));
33        self.dfs(&mut cc).run();
34        cc
35    }
36
37    fn is_connected(&self) -> bool
38    where
39        Self: VertexList + WithVertexProp<Color>,
40    {
41        let mut con = true;
42        self.dfs(IsConnected(&mut con)).run();
43        con
44    }
45
46    fn cut_vertices(&self) -> Vec<Vertex<Self>>
47    where
48        Self: Graph,
49    {
50        if self.num_vertices() == 0 {
51            return vec![];
52        }
53        let mut vis = FindCutVertices {
54            time: 0,
55            discover: self.vertex_prop(0),
56            low: self.vertex_prop(0),
57            root: first(self.vertices()),
58            root_childs: 0,
59            is_cut: self.vertex_prop(false),
60        };
61        self.dfs(&mut vis).run();
62        vec(self.vertices().filter(|&v| vis.is_cut[v]))
63    }
64
65    fn cut_edges(&self) -> Vec<Edge<Self>>
66    where
67        Self: Graph,
68    {
69        let mut vis = FindCutEdges {
70            time: 0,
71            discover: self.vertex_prop(0),
72            low: self.vertex_prop(0),
73            cuts: vec![],
74        };
75        self.dfs(&mut vis).run();
76        vis.cuts
77    }
78}
79
80impl<G: Incidence> Components for G {}
81
82pub struct IsConnected<'a> {
83    connected: &'a mut bool,
84    saw_root: bool,
85}
86
87#[allow(non_snake_case)]
88pub fn IsConnected(con: &mut bool) -> IsConnected {
89    IsConnected {
90        connected: con,
91        saw_root: false,
92    }
93}
94
95impl<'a, G: WithEdge> Visitor<G> for IsConnected<'a> {
96    fn start(&mut self, _g: &G) -> Control {
97        *self.connected = true;
98        self.saw_root = false;
99        Control::Continue
100    }
101
102    fn discover_root_vertex(&mut self, _g: &G, _v: Vertex<G>) -> Control {
103        if self.saw_root {
104            *self.connected = false;
105            Control::Break
106        } else {
107            self.saw_root = true;
108            Control::Continue
109        }
110    }
111}
112
113#[allow(non_snake_case)]
114pub fn NumComponents<T>(num: &mut T) -> OnDiscoverRootVertex<Add1<T>>
115where
116    T: Counter + Zero,
117{
118    *num = zero();
119    OnDiscoverRootVertex(Add1(num))
120}
121
122pub struct ConnectedComponents<G, V> {
123    comp: V,
124    cur: usize,
125    _marker: PhantomData<G>,
126}
127
128#[allow(non_snake_case)]
129pub fn ConnectedComponents<G, V>(_g: &G, comp: V) -> ConnectedComponents<G, V> {
130    ConnectedComponents {
131        comp: comp,
132        cur: 0,
133        _marker: PhantomData,
134    }
135}
136
137impl<G, V> Visitor<G> for ConnectedComponents<G, V>
138where
139    G: WithEdge,
140    V: VertexPropMut<G, usize>,
141{
142    fn finish_root_vertex(&mut self, _g: &G, _v: Vertex<G>) -> Control {
143        self.cur += 1;
144        Control::Continue
145    }
146
147    fn discover_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
148        self.comp[v] = self.cur;
149        Control::Continue
150    }
151}
152
153impl<G, V> ConnectedComponents<G, V>
154where
155    G: WithEdge,
156    V: VertexPropMut<G, usize>,
157{
158    pub fn is_connected(&self, u: Vertex<G>, v: Vertex<G>) -> bool {
159        self.comp[u] == self.comp[v]
160    }
161
162    pub fn is_disconnected(&self, u: Vertex<G>, v: Vertex<G>) -> bool {
163        self.comp[u] != self.comp[v]
164    }
165
166    pub fn component(&self, v: Vertex<G>) -> usize {
167        // FIXME: can fail if the search was interrupted
168        self.comp[v]
169    }
170
171    pub fn num_components(&self) -> usize {
172        self.cur
173    }
174}
175
176pub struct FindCutVertices<G: Graph> {
177    time: u64,
178    discover: DefaultVertexPropMut<G, u64>,
179    low: DefaultVertexPropMut<G, u64>,
180    root: Vertex<G>,
181    root_childs: u64,
182    is_cut: DefaultVertexPropMut<G, bool>,
183}
184
185impl<G: Graph> Visitor<G> for FindCutVertices<G> {
186    fn discover_root_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
187        self.root = v;
188        self.root_childs = 0;
189        Control::Continue
190    }
191
192    fn finish_root_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
193        if self.root_childs > 1 {
194            self.is_cut[v] = true;
195        }
196        Control::Continue
197    }
198
199    fn discover_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
200        self.discover[v] = self.time;
201        self.low[v] = self.time;
202        self.time += 1;
203        Control::Continue
204    }
205
206    fn discover_tree_edge(&mut self, g: &G, e: Edge<G>) -> Control {
207        if self.root == g.source(e) {
208            self.root_childs += 1;
209        }
210        Control::Continue
211    }
212
213    fn discover_back_edge(&mut self, g: &G, e: Edge<G>) -> Control {
214        let (u, v) = g.ends(e);
215        if self.discover[v] != self.discover[u] + 1 {
216            // v is not the dfs parent of u
217            self.low[u] = min(self.low[u], self.discover[v]);
218        }
219        Control::Continue
220    }
221
222    fn finish_tree_edge(&mut self, g: &G, e: Edge<G>) -> Control {
223        let (u, v) = g.ends(e);
224        self.low[u] = min(self.low[u], self.low[v]);
225        if self.root != u && self.low[v] >= self.discover[u] {
226            self.is_cut[u] = true;
227        }
228        Control::Continue
229    }
230}
231
232pub struct FindCutEdges<G: Graph> {
233    time: u64,
234    discover: DefaultVertexPropMut<G, u64>,
235    low: DefaultVertexPropMut<G, u64>,
236    cuts: Vec<Edge<G>>,
237}
238
239impl<G: Graph> Visitor<G> for FindCutEdges<G> {
240    fn discover_vertex(&mut self, _g: &G, v: Vertex<G>) -> Control {
241        self.discover[v] = self.time;
242        self.low[v] = self.time;
243        self.time += 1;
244        Control::Continue
245    }
246
247    fn discover_back_edge(&mut self, g: &G, e: Edge<G>) -> Control {
248        let (v, parent) = g.ends(e);
249        if self.discover[parent] != self.discover[v] + 1 {
250            // this is not an edge to parent
251            self.low[v] = min(self.low[v], self.discover[parent]);
252        }
253        Control::Continue
254    }
255
256    fn finish_tree_edge(&mut self, g: &G, e: Edge<G>) -> Control {
257        let (u, v) = g.ends(e);
258        self.low[u] = min(self.low[u], self.low[v]);
259        if self.low[v] > self.discover[u] {
260            self.cuts.push(e)
261        }
262        Control::Continue
263    }
264}
265
266#[doc(hidden)]
267pub fn cut_vertices_naive<G: IncidenceGraph>(g: &G) -> Vec<Vertex<G>> {
268    vec(g.vertices().filter(|&v| is_cut_vertex_naive(g, v)))
269}
270
271fn is_cut_vertex_naive<G: IncidenceGraph>(g: &G, v: Vertex<G>) -> bool {
272    let sub = g.induced_subgraph(g.vertices().filter(|&u| u != v));
273    sub.num_components() > g.num_components()
274}
275
276#[doc(hidden)]
277pub fn cut_edges_naive<G: IncidenceGraph>(g: &G) -> Vec<Edge<G>> {
278    vec(g.edges().filter(|&e| is_cut_edge_naive(g, e)))
279}
280
281fn is_cut_edge_naive<G: IncidenceGraph>(g: &G, e: Edge<G>) -> bool {
282    let sub = g.spanning_subgraph(g.edges().filter(|&f| f != e));
283    sub.num_components() > g.num_components()
284}
285
286#[cfg(test)]
287mod tests {
288    use super::{cut_edges_naive, cut_vertices_naive, Components};
289    use prelude::*;
290
291    #[test]
292    fn cut_vertices() {
293        // Examples from
294
295        // http://www.geeksforgeeks.org/articulation-points-or-cut-vertices-in-a-graph/
296        // 1 --- 0 --- 3
297        //  \   /      |
298        //    2        4
299        let g: StaticGraph = graph!(5, (0, 1), (0, 2), (0, 3), (1, 2), (3, 4));
300        let exp = vec![0, 3];
301        assert_eq!(exp, sorted(cut_vertices_naive(&g)));
302        assert_eq!(exp, sorted(g.cut_vertices()));
303
304        // 0 -- 1 -- 2 -- 3
305        let g: StaticGraph = graph!(4, (0, 1), (1, 2), (2, 3));
306        let exp = vec![1, 2];
307        assert_eq!(exp, sorted(cut_vertices_naive(&g)));
308        assert_eq!(exp, sorted(g.cut_vertices()));
309
310        // 0       3
311        // | \   /   \
312        // |   1      5
313        // | / | \   /
314        // 2   6   4
315        let g: StaticGraph = graph!(
316            7,
317            (0, 1),
318            (0, 2),
319            (1, 2),
320            (1, 3),
321            (1, 4),
322            (1, 6),
323            (3, 5),
324            (4, 5)
325        );
326        let exp = vec![1];
327        assert_eq!(exp, sorted(cut_vertices_naive(&g)));
328        assert_eq!(exp, sorted(g.cut_vertices()));
329    }
330
331    #[test]
332    fn cut_edges() {
333        // Examples from
334        // http://www.geeksforgeeks.org/bridge-in-a-graph/
335
336        // 1 --- 0 --- 3
337        //  \   /      |
338        //    2        4
339        let g: StaticGraph = graph!(5, (0, 1), (0, 2), (0, 3), (1, 2), (3, 4));
340        let exp = vec![(0, 3), (3, 4)];
341        assert_eq!(exp, sorted_ends(&g, cut_edges_naive(&g)));
342        assert_eq!(exp, sorted_ends(&g, g.cut_edges()));
343
344        // 0 -- 1 -- 2 -- 3
345        let g: StaticGraph = graph!(4, (0, 1), (1, 2), (2, 3));
346        let exp = vec![(0, 1), (1, 2), (2, 3)];
347        assert_eq!(exp, sorted_ends(&g, cut_edges_naive(&g)));
348        assert_eq!(exp, sorted_ends(&g, g.cut_edges()));
349
350        // 0       3
351        // | \   /   \
352        // |   1      5
353        // | / | \   /
354        // 2   6   4
355        let g: StaticGraph = graph!(
356            7,
357            (0, 1),
358            (0, 2),
359            (1, 2),
360            (1, 3),
361            (1, 4),
362            (1, 6),
363            (3, 5),
364            (4, 5)
365        );
366        let exp = vec![(1, 6)];
367        assert_eq!(exp, sorted_ends(&g, cut_edges_naive(&g)));
368        assert_eq!(exp, sorted_ends(&g, g.cut_edges()));
369    }
370
371    fn sorted<T: Ord>(mut v: Vec<T>) -> Vec<T> {
372        v.sort();
373        v
374    }
375
376    fn sorted_ends<G>(g: &G, edges: Vec<Edge<G>>) -> Vec<(Vertex<G>, Vertex<G>)>
377    where
378        G: Graph,
379        Vertex<G>: Ord,
380    {
381        sorted(g.ends(edges).collect())
382    }
383}