fera_graph/graphs/adaptors/
spanning_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 std::iter::Cloned;
12use std::slice;
13
14use fera_fun::position_of;
15use rand::Rng;
16
17// FIXME: unify SpanningSubgraph with Subgraph
18pub struct SpanningSubgraph<'a, G>
19where
20    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>>,
21{
22    g: &'a G,
23    edges: Vec<Edge<G>>,
24    out_edges: DefaultVertexPropMut<G, Vec<Edge<G>>>,
25}
26
27impl<'a, G> SpanningSubgraph<'a, G>
28where
29    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>>,
30{
31    #[doc(hidden)]
32    pub fn new(g: &'a G) -> Self {
33        SpanningSubgraph {
34            g: g,
35            edges: vec![],
36            out_edges: g.vertex_prop(vec![]),
37        }
38    }
39
40    pub fn add_edge(&mut self, e: Edge<G>) {
41        let (u, v) = self.g.ends(e);
42        self.edges.push(e);
43        self.out_edges[u].push(e);
44        if self.g.orientation(e).is_undirected() {
45            self.out_edges[v].push(self.g.get_reverse(e).unwrap());
46        }
47    }
48
49    pub fn set_edges<I>(&mut self, iter: I)
50    where
51        G: VertexList,
52        I: IntoIterator,
53        I::Item: IntoOwned<Edge<G>>,
54    {
55        self.clear_edges();
56        for e in iter {
57            self.add_edge(e.into_owned());
58        }
59    }
60
61    pub fn add_edges<I>(&mut self, iter: I)
62    where
63        I: IntoIterator,
64        I::Item: IntoOwned<Edge<G>>,
65    {
66        for e in iter {
67            self.add_edge(e.into_owned());
68        }
69    }
70
71    pub fn clear_edges(&mut self)
72    where
73        G: VertexList,
74    {
75        // FIXME: this should be linear in |E|
76        self.edges.clear();
77        for u in self.g.vertices() {
78            self.out_edges[u].clear();
79        }
80    }
81
82    pub fn replace_edge(&mut self, old: Edge<G>, new: Edge<G>) {
83        self.remove_edge(old);
84        self.add_edge(new);
85    }
86
87    pub fn remove_edge(&mut self, e: Edge<G>) {
88        let (u, v) = self.g.ends(e);
89        assert!(vec_find_swap_remove(&mut self.edges, &e));
90        assert!(vec_find_swap_remove(&mut self.out_edges[u], &e));
91        if self.g.orientation(e).is_undirected() {
92            assert!(vec_find_swap_remove(&mut self.out_edges[v], &e));
93        }
94    }
95}
96
97#[inline]
98fn vec_find_swap_remove<T: PartialEq>(vec: &mut Vec<T>, value: &T) -> bool {
99    if let Some(i) = position_of(&*vec, value) {
100        vec.swap_remove(i);
101        true
102    } else {
103        false
104    }
105}
106
107// Trait implementations
108
109impl<'a, G> AsRef<G> for SpanningSubgraph<'a, G>
110where
111    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>>,
112{
113    #[inline]
114    fn as_ref(&self) -> &G {
115        self.g
116    }
117}
118
119impl<'a, 'b, G> VertexTypes<'a, SpanningSubgraph<'b, G>> for SpanningSubgraph<'b, G>
120where
121    G: 'b + WithEdge + WithVertexProp<Vec<Edge<G>>>,
122{
123    type VertexIter = VertexIter<'b, G>;
124    type OutNeighborIter = OutNeighborFromOutEdge<'b, G, OutEdgeIter<'a, Self>>;
125}
126
127impl<'a, G> WithVertex for SpanningSubgraph<'a, G>
128where
129    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>>,
130{
131    type Vertex = Vertex<G>;
132    type OptionVertex = OptionVertex<G>;
133}
134
135impl<'a, 'b, G> EdgeTypes<'a, SpanningSubgraph<'b, G>> for SpanningSubgraph<'b, G>
136where
137    G: 'b + WithEdge + WithVertexProp<Vec<Edge<G>>>,
138{
139    type EdgeIter = Cloned<slice::Iter<'a, Edge<G>>>;
140    type OutEdgeIter = Cloned<slice::Iter<'a, Edge<G>>>;
141}
142
143impl<'a, G> WithEdge for SpanningSubgraph<'a, G>
144where
145    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>>,
146{
147    type Kind = G::Kind;
148    type Edge = Edge<G>;
149    type OptionEdge = OptionEdge<G>;
150
151    fn source(&self, e: Edge<Self>) -> Vertex<Self> {
152        self.g.source(e)
153    }
154
155    fn target(&self, e: Edge<Self>) -> Vertex<Self> {
156        self.g.target(e)
157    }
158
159    fn orientation(&self, e: Edge<Self>) -> Orientation {
160        self.g.orientation(e)
161    }
162
163    fn end_vertices(&self, e: Edge<Self>) -> (Vertex<Self>, Vertex<Self>) {
164        self.g.end_vertices(e)
165    }
166
167    fn opposite(&self, u: Vertex<Self>, e: Edge<Self>) -> Vertex<Self> {
168        self.g.opposite(u, e)
169    }
170
171    // The compiler is not smart enough to allow this, so we use the default reverse
172    // implemenetation
173    //
174    // fn reverse(&self, e: Edge<Self>) -> Edge<Self> where Self: WithEdge<Kind = Undirected> {
175    //     self.g.reverse(e)
176    // }
177
178    fn get_reverse(&self, e: Edge<Self>) -> Option<Edge<Self>> {
179        self.g.get_reverse(e)
180    }
181}
182
183impl<'a, G> VertexList for SpanningSubgraph<'a, G>
184where
185    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>> + VertexList,
186{
187    fn num_vertices(&self) -> usize {
188        self.g.num_vertices()
189    }
190
191    fn vertices(&self) -> VertexIter<Self> {
192        self.g.vertices()
193    }
194}
195
196impl<'a, G> EdgeList for SpanningSubgraph<'a, G>
197where
198    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>>,
199{
200    fn num_edges(&self) -> usize {
201        self.edges.len()
202    }
203
204    fn edges(&self) -> EdgeIter<Self> {
205        self.edges.iter().cloned()
206    }
207
208    fn get_edge_by_ends(&self, u: Vertex<Self>, v: Vertex<Self>) -> Option<Edge<Self>> {
209        self.out_edges(u).find(|e| (u, v) == self.ends(*e))
210    }
211}
212
213impl<'a, G> Adjacency for SpanningSubgraph<'a, G>
214where
215    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>>,
216{
217    fn out_neighbors(&self, v: Vertex<Self>) -> OutNeighborIter<Self> {
218        OutNeighborFromOutEdge::new(self.g, self.out_edges(v))
219    }
220
221    fn out_degree(&self, v: Vertex<Self>) -> usize {
222        self.out_edges[v].len()
223    }
224}
225
226impl<'a, G> Incidence for SpanningSubgraph<'a, G>
227where
228    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>>,
229{
230    fn out_edges(&self, v: Vertex<Self>) -> OutEdgeIter<Self> {
231        self.out_edges[v].iter().cloned()
232    }
233}
234
235impl<'a, G, T> WithVertexProp<T> for SpanningSubgraph<'a, G>
236where
237    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>> + WithVertexProp<T>,
238{
239    type VertexProp = DelegateVertexProp<G, T>;
240}
241
242impl<'a, G, T> WithEdgeProp<T> for SpanningSubgraph<'a, G>
243where
244    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>> + WithEdgeProp<T>,
245{
246    type EdgeProp = DelegateEdgeProp<G, T>;
247}
248
249impl<'a, G> BasicVertexProps for SpanningSubgraph<'a, G>
250where
251    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>> + BasicVertexProps,
252{
253}
254
255impl<'a, G> BasicEdgeProps for SpanningSubgraph<'a, G>
256where
257    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>> + BasicEdgeProps,
258{
259}
260
261impl<'a, G> BasicProps for SpanningSubgraph<'a, G>
262where
263    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>> + BasicProps,
264{
265}
266
267impl<'a, G> Choose for SpanningSubgraph<'a, G>
268where
269    G: 'a + WithEdge + WithVertexProp<Vec<Edge<G>>> + Choose,
270{
271    fn choose_vertex<R: Rng>(&self, rng: R) -> Option<Vertex<Self>> {
272        self.g.choose_vertex(rng)
273    }
274
275    fn choose_out_neighbor<R: Rng>(&self, v: Vertex<Self>, rng: R) -> Option<Vertex<Self>> {
276        self.g.choose_out_edge(v, rng).map(|e| self.target(e))
277    }
278
279    fn choose_edge<R: Rng>(&self, rng: R) -> Option<Edge<Self>> {
280        use graphs::common::gen_range_bool;
281        if let Some((i, rev)) = gen_range_bool(self.num_edges(), rng) {
282            let e = self.edges[i];
283            if rev && self.orientation(e).is_undirected() {
284                let e = self.get_reverse(e);
285                debug_assert!(e.is_some());
286                e
287            } else {
288                Some(e)
289            }
290        } else {
291            None
292        }
293    }
294
295    fn choose_out_edge<R: Rng>(&self, v: Vertex<Self>, mut rng: R) -> Option<Edge<Self>> {
296        if self.out_degree(v) == 0 {
297            None
298        } else {
299            self.out_edges[v]
300                .get(rng.gen_range(0, self.out_degree(v)))
301                .cloned()
302        }
303    }
304}