1use 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
17pub 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 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 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 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 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 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 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 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 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 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}