fera_graph/graphs/adaptors/
subgraph.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
5use choose::Choose;
6use graphs::OutNeighborFromOutEdge;
7use params::IntoOwned;
8use prelude::*;
9use props::{DelegateEdgeProp, DelegateVertexProp};
10
11use fera_fun::vec;
12
13use std::iter::Cloned;
14use std::slice;
15
16use rand::Rng;
17
18// TODO: Allow a subgraph be reused
19// TODO: delegate all (possible) methods to g
20// TODO: remove Graph bound to allow directed graphs
21pub struct Subgraph<'a, G>
22where
23    G: 'a + Graph,
24{
25    g: &'a G,
26    vertices: Vec<Vertex<G>>,
27    edges: Vec<Edge<G>>,
28    inc: DefaultVertexPropMut<G, Vec<Edge<G>>>,
29}
30
31// Traits implementations
32
33impl<'a, G> AsRef<G> for Subgraph<'a, G>
34where
35    G: 'a + Graph,
36{
37    #[inline]
38    fn as_ref(&self) -> &G {
39        self.g
40    }
41}
42
43impl<'a, 'b, G> VertexTypes<'a, Subgraph<'b, G>> for Subgraph<'b, G>
44where
45    G: 'b + Graph,
46{
47    type VertexIter = Cloned<slice::Iter<'a, Vertex<G>>>;
48    type OutNeighborIter = OutNeighborFromOutEdge<'b, G, OutEdgeIter<'a, Self>>;
49}
50
51impl<'a, G> WithVertex for Subgraph<'a, G>
52where
53    G: 'a + Graph,
54{
55    type Vertex = Vertex<G>;
56    type OptionVertex = OptionVertex<G>;
57}
58
59impl<'a, 'b, G> EdgeTypes<'a, Subgraph<'b, G>> for Subgraph<'b, G>
60where
61    G: 'b + Graph,
62{
63    type EdgeIter = Cloned<slice::Iter<'a, Edge<G>>>;
64    type OutEdgeIter = Cloned<slice::Iter<'a, Edge<G>>>;
65}
66
67impl<'a, G> WithEdge for Subgraph<'a, G>
68where
69    G: 'a + Graph,
70{
71    type Kind = G::Kind;
72    type Edge = Edge<G>;
73    type OptionEdge = OptionEdge<G>;
74
75    fn source(&self, e: Edge<Self>) -> Vertex<Self> {
76        self.g.source(e)
77    }
78
79    fn target(&self, e: Edge<Self>) -> Vertex<Self> {
80        self.g.target(e)
81    }
82
83    fn orientation(&self, e: Edge<Self>) -> Orientation {
84        self.g.orientation(e)
85    }
86
87    fn end_vertices(&self, e: Edge<Self>) -> (Vertex<Self>, Vertex<Self>) {
88        self.g.end_vertices(e)
89    }
90
91    fn opposite(&self, u: Vertex<Self>, e: Edge<Self>) -> Vertex<Self> {
92        self.g.opposite(u, e)
93    }
94
95    fn reverse(&self, e: Edge<Self>) -> Edge<Self> {
96        self.g.reverse(e)
97    }
98
99    fn get_reverse(&self, e: Edge<Self>) -> Option<Edge<Self>> {
100        self.g.get_reverse(e)
101    }
102}
103
104impl<'a, G> VertexList for Subgraph<'a, G>
105where
106    G: 'a + Graph,
107{
108    fn num_vertices(&self) -> usize {
109        self.vertices.len()
110    }
111
112    fn vertices(&self) -> VertexIter<Self> {
113        self.vertices.iter().cloned()
114    }
115}
116
117impl<'a, G> EdgeList for Subgraph<'a, G>
118where
119    G: 'a + Graph,
120{
121    fn num_edges(&self) -> usize {
122        self.edges.len()
123    }
124
125    fn edges(&self) -> EdgeIter<Self> {
126        self.edges.iter().cloned()
127    }
128
129    fn get_edge_by_ends(&self, u: Vertex<Self>, v: Vertex<Self>) -> Option<Edge<Self>> {
130        self.out_edges(u).find(|e| (u, v) == self.ends(*e))
131    }
132}
133
134impl<'a, G> Adjacency for Subgraph<'a, G>
135where
136    G: 'a + Graph,
137{
138    fn out_neighbors(&self, v: Vertex<Self>) -> OutNeighborIter<Self> {
139        OutNeighborFromOutEdge::new(self.g, self.out_edges(v))
140    }
141
142    fn out_degree(&self, v: Vertex<Self>) -> usize {
143        self.inc[v].len()
144    }
145}
146
147impl<'a, G> Incidence for Subgraph<'a, G>
148where
149    G: 'a + Graph,
150{
151    fn out_edges(&self, v: Vertex<Self>) -> OutEdgeIter<Self> {
152        self.inc[v].iter().cloned()
153    }
154}
155
156impl<'a, G, T> WithVertexProp<T> for Subgraph<'a, G>
157where
158    G: 'a + Graph + WithVertexProp<T>,
159{
160    type VertexProp = DelegateVertexProp<G, T>;
161}
162
163impl<'a, G, T> WithEdgeProp<T> for Subgraph<'a, G>
164where
165    G: 'a + Graph + WithEdgeProp<T>,
166{
167    type EdgeProp = DelegateEdgeProp<G, T>;
168}
169
170impl<'a, G> BasicVertexProps for Subgraph<'a, G>
171where
172    G: 'a + Graph,
173{
174}
175
176impl<'a, G> BasicEdgeProps for Subgraph<'a, G>
177where
178    G: 'a + Graph,
179{
180}
181
182impl<'a, G> BasicProps for Subgraph<'a, G>
183where
184    G: 'a + Graph,
185{
186}
187
188// Choose
189
190impl<'a, G> Choose for Subgraph<'a, G>
191where
192    G: 'a + IncidenceGraph,
193{
194    fn choose_vertex<R: Rng>(&self, mut rng: R) -> Option<Vertex<Self>> {
195        self.vertices
196            .get(rng.gen_range(0, self.num_vertices()))
197            .cloned()
198    }
199
200    fn choose_out_neighbor<R: Rng>(&self, v: Vertex<Self>, mut rng: R) -> Option<Vertex<Self>> {
201        self.inc[v]
202            .get(rng.gen_range(0, self.out_degree(v)))
203            .map(|e| self.target(*e))
204    }
205
206    fn choose_edge<R: Rng>(&self, rng: R) -> Option<Edge<Self>> {
207        use graphs::common::gen_range_bool;
208        if let Some((i, rev)) = gen_range_bool(self.num_edges(), rng) {
209            let e = self.edges[i];
210            if rev && self.orientation(e).is_undirected() {
211                let e = self.get_reverse(e);
212                debug_assert!(e.is_some());
213                e
214            } else {
215                Some(e)
216            }
217        } else {
218            None
219        }
220    }
221
222    fn choose_out_edge<R: Rng>(&self, v: Vertex<Self>, mut rng: R) -> Option<Edge<Self>> {
223        if self.out_degree(v) == 0 {
224            None
225        } else {
226            self.inc[v]
227                .get(rng.gen_range(0, self.out_degree(v)))
228                .cloned()
229        }
230    }
231}
232
233// Extensions Traits
234
235pub trait WithSubgraph<G: Graph> {
236    fn empty_spanning_subgraph(&self) -> SpanningSubgraph<G>;
237
238    fn spanning_subgraph<I>(&self, vertices: I) -> SpanningSubgraph<G>
239    where
240        I: IntoIterator,
241        I::Item: IntoOwned<Edge<G>>;
242
243    fn induced_subgraph<I>(&self, vertices: I) -> Subgraph<G>
244    where
245        G: Incidence,
246        I: IntoIterator,
247        I::Item: IntoOwned<Vertex<G>>;
248
249    fn edge_induced_subgraph<I>(&self, edges: I) -> Subgraph<G>
250    where
251        I: IntoIterator,
252        I::Item: IntoOwned<Edge<G>>;
253}
254
255impl<G: Graph> WithSubgraph<G> for G {
256    fn spanning_subgraph<I>(&self, iter: I) -> SpanningSubgraph<G>
257    where
258        I: IntoIterator,
259        I::Item: IntoOwned<Edge<G>>,
260    {
261        let mut sub = SpanningSubgraph::new(self);
262        sub.add_edges(iter);
263        sub
264    }
265
266    fn empty_spanning_subgraph(&self) -> SpanningSubgraph<G> {
267        SpanningSubgraph::new(self)
268    }
269
270    fn edge_induced_subgraph<I>(&self, edges: I) -> Subgraph<G>
271    where
272        I: IntoIterator,
273        I::Item: IntoOwned<Edge<G>>,
274    {
275        // FIXME: should be O(edges), but is O(V) + O(edges)
276        let edges = vec(edges.into_iter().map(IntoOwned::into_owned));
277        let mut vin = self.default_vertex_prop(false);
278        let mut vertices = vec![];
279        let mut inc = self.default_vertex_prop(Vec::<Edge<G>>::new());
280        for (e, u, v) in self.with_ends(&edges) {
281            if !vin[u] {
282                vin[u] = true;
283                vertices.push(u);
284            }
285            if !vin[v] {
286                vin[v] = true;
287                vertices.push(v);
288            }
289            inc[u].push(e);
290            inc[v].push(self.reverse(e));
291        }
292
293        Subgraph {
294            g: self,
295            vertices: vertices,
296            edges: edges,
297            inc: inc,
298        }
299    }
300
301    fn induced_subgraph<I>(&self, vertices: I) -> Subgraph<G>
302    where
303        G: Incidence,
304        I: IntoIterator,
305        I::Item: IntoOwned<Vertex<G>>,
306    {
307        let vertices = vec(vertices.into_iter().map(IntoOwned::into_owned));
308        let mut vs = self.default_vertex_prop(false);
309        let mut edges = vec![];
310        let mut inc = self.default_vertex_prop(Vec::<Edge<G>>::new());
311        for &v in &vertices {
312            vs[v] = true;
313        }
314        for (e, u, v) in self.edges_with_ends() {
315            if vs[u] && vs[v] {
316                edges.push(e);
317                inc[u].push(e);
318                inc[v].push(self.reverse(e));
319            }
320        }
321
322        Subgraph {
323            g: self,
324            vertices: vertices,
325            edges: edges,
326            inc: inc,
327        }
328    }
329}
330
331// TODO: write benchs and optimize
332
333#[cfg(test)]
334mod tests {
335    use fera_fun::{set, vec};
336    use prelude::*;
337
338    fn new_graph() -> (
339        StaticGraph,
340        Edge<StaticGraph>,
341        Edge<StaticGraph>,
342        Edge<StaticGraph>,
343        Edge<StaticGraph>,
344    ) {
345        let g: StaticGraph = graph!(5, (0, 1), (0, 2), (1, 2), (3, 4));
346        let e = vec(g.edges());
347        (g, e[0], e[1], e[2], e[3])
348    }
349
350    #[test]
351    fn test_spanning_subgraph() {
352        let (g, _, e02, e12, _) = new_graph();
353        let s = g.spanning_subgraph(vec![e02, e12]);
354        assert_eq!(vec![0, 1, 2, 3, 4], vec(s.vertices()));
355        assert_eq!(set(vec![e02, e12]), set(s.edges()));
356        assert_eq!(set(vec![e02]), set(s.out_edges(0)));
357        assert_eq!(set(vec![e12]), set(s.out_edges(1)));
358        assert_eq!(set(vec![e02, e12]), set(s.out_edges(2)));
359        assert!(set(s.out_edges(3)).is_empty());
360        assert!(set(s.out_edges(4)).is_empty());
361    }
362
363    #[test]
364    fn test_edge_induced_subgraph() {
365        let (g, e01, e02, _, _) = new_graph();
366        let s = g.edge_induced_subgraph(vec![e01, e02]);
367        assert_eq!(set(vec![0, 1, 2]), set(s.vertices()));
368        assert_eq!(set(vec![e01, e02]), set(s.edges()));
369        assert_eq!(set(vec![e01, e02]), set(s.out_edges(0)));
370        assert_eq!(set(vec![1, 2]), set(s.out_neighbors(0)));
371        assert_eq!(set(vec![e01]), set(s.out_edges(1)));
372        assert_eq!(set(vec![0]), set(s.out_neighbors(1)));
373        assert_eq!(set(vec![e02]), set(s.out_edges(2)));
374        assert_eq!(set(vec![0]), set(s.out_neighbors(2)));
375    }
376
377    #[test]
378    fn test_induced_subgraph() {
379        let (g, e01, e02, e12, _) = new_graph();
380        let s = g.induced_subgraph(vec![0, 1, 2]);
381        assert_eq!(set(vec![0, 1, 2]), set(s.vertices()));
382        assert_eq!(set(vec![e01, e02, e12]), set(s.edges()));
383        assert_eq!(set(vec![e01, e02]), set(s.out_edges(0)));
384        assert_eq!(set(vec![e01, e12]), set(s.out_edges(1)));
385        assert_eq!(set(vec![e02, e12]), set(s.out_edges(2)));
386    }
387}