fera_graph/choose.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//! Random selection of vertices and edges.
6//!
7//! # Examples
8//!
9//! ```
10//! extern crate rand;
11//! extern crate fera_graph;
12//!
13//! use fera_graph::prelude::*;
14//! use fera_graph::choose::Choose;
15//!
16//! # fn main() {
17//! let g = CompleteGraph::new(5);
18//! let iter = g.choose_vertex_iter(rand::weak_rng()).take(100);
19//!
20//! let mut saw = g.default_vertex_prop(false);
21//! for v in iter {
22//! saw[v] = true;
23//! }
24//! // or saw.set_values(iter, true);
25//!
26//! // The probability of this test failing is left as an exercise for the reader.
27//! assert!(g.vertices().all(|v| saw[v]));
28//! # }
29//! ```
30use prelude::*;
31
32use rand::Rng;
33
34// TODO: specialization of *_iter
35// TODO: remove WithEdge bound and add bounds to methods
36// TODO: ex: g.choose().vertex(), g.choose_with_rng(rng).vertices()
37/// A graph from which vertices and edges can be randomly selected.
38///
39/// See the [module documentation] for examples.
40///
41/// [module documentation]: index.html
42pub trait Choose: WithEdge {
43 /// Returns a random vertex of this graph or `None` if the graph has no vertices.
44 fn choose_vertex<R: Rng>(&self, rng: R) -> Option<Vertex<Self>>;
45
46 /// Returns an iterator that repeatedly calls `choose_vertex`.
47 fn choose_vertex_iter<R: Rng>(&self, rng: R) -> ChooseVertexIter<Self, R> {
48 ChooseVertexIter { g: self, rng: rng }
49 }
50
51 /// Returns a random neighbor vertex of `v` or `None` if `v` has no neighbors.
52 fn choose_out_neighbor<R: Rng>(&self, v: Vertex<Self>, rng: R) -> Option<Vertex<Self>>;
53
54 /// Returns an iterator that repeatedly calls `choose_out_neighbor(v)`.
55 fn choose_out_neighbor_iter<R: Rng>(
56 &self,
57 v: Vertex<Self>,
58 rng: R,
59 ) -> ChooseOutNeighborIter<Self, R> {
60 ChooseOutNeighborIter {
61 g: self,
62 v: v,
63 rng: rng,
64 }
65 }
66
67 /// Returns a random edge of this graph or `None` if the graph has no edges.
68 fn choose_edge<R: Rng>(&self, rng: R) -> Option<Edge<Self>>;
69
70 /// Returns an iterator that repeatedly calls `choose_edge`.
71 fn choose_edge_iter<R: Rng>(&self, rng: R) -> ChooseEdgeIter<Self, R> {
72 ChooseEdgeIter { g: self, rng: rng }
73 }
74
75 /// Returns a random out edge of `v` or `None` if `v` has no out edges.
76 fn choose_out_edge<R: Rng>(&self, v: Vertex<Self>, rng: R) -> Option<Edge<Self>>;
77
78 /// Returns an iterator that repeatedly calls `choose_out_edge(v)`.
79 fn choose_out_edge_iter<R: Rng>(&self, v: Vertex<Self>, rng: R) -> ChooseOutEdgeIter<Self, R> {
80 ChooseOutEdgeIter {
81 g: self,
82 v: v,
83 rng: rng,
84 }
85 }
86
87 /// Returns a iterator that produces a sequence of random edges that forms a walk, that is, the
88 /// target vertex of the previous edge is the source vertex of the next edge.
89 fn random_walk<R: Rng>(&self, mut rng: R) -> RandomWalk<Self, R> {
90 let cur = self.choose_vertex(&mut rng);
91 RandomWalk {
92 g: self,
93 cur: cur,
94 rng: rng,
95 }
96 }
97}
98
99/// An iterator that produces random selected vertices of a graph.
100///
101/// This `struct` is created by [`Choose::choose_vertex_iter`].
102///
103/// [`Choose::choose_vertex_iter`]: trait.Choose.html#method.choose_vertex_iter
104pub struct ChooseVertexIter<'a, G: 'a, R> {
105 g: &'a G,
106 rng: R,
107}
108
109impl<'a, G, R> Iterator for ChooseVertexIter<'a, G, R>
110where
111 G: 'a + Choose,
112 R: Rng,
113{
114 type Item = Vertex<G>;
115
116 fn next(&mut self) -> Option<Vertex<G>> {
117 G::choose_vertex(self.g, &mut self.rng)
118 }
119}
120
121/// An iterator that produces random selected neighbors of a vertex.
122///
123/// This `struct` is created by [`Choose::choose_out_neighbor_iter`].
124///
125/// [`Choose::choose_out_neighbor_iter`]: trait.Choose.html#method.choose_out_neighbor_iter
126pub struct ChooseOutNeighborIter<'a, G: 'a + WithVertex, R> {
127 g: &'a G,
128 v: Vertex<G>,
129 rng: R,
130}
131
132impl<'a, G, R> Iterator for ChooseOutNeighborIter<'a, G, R>
133where
134 G: 'a + Choose,
135 R: Rng,
136{
137 type Item = Vertex<G>;
138
139 fn next(&mut self) -> Option<Vertex<G>> {
140 G::choose_out_neighbor(self.g, self.v, &mut self.rng)
141 }
142}
143
144/// An iterator that produces random selected edges of a graph.
145///
146/// This `struct` is created by [`Choose::choose_edge_iter`].
147///
148/// [`Choose::choose_edge_iter`]: trait.Choose.html#method.choose_edge_iter
149pub struct ChooseEdgeIter<'a, G: 'a, R> {
150 g: &'a G,
151 rng: R,
152}
153
154impl<'a, G, R> Iterator for ChooseEdgeIter<'a, G, R>
155where
156 G: 'a + Choose,
157 R: Rng,
158{
159 type Item = Edge<G>;
160
161 fn next(&mut self) -> Option<Edge<G>> {
162 G::choose_edge(self.g, &mut self.rng)
163 }
164}
165
166/// An iterator that produces random selected out edges of a vertex.
167///
168/// This `struct` is created by [`Choose::choose_out_edge_iter`].
169///
170/// [`Choose::choose_out_edge_iter`]: trait.Choose.html#method.choose_out_edge_iter
171pub struct ChooseOutEdgeIter<'a, G: 'a + WithVertex, R> {
172 g: &'a G,
173 v: Vertex<G>,
174 rng: R,
175}
176
177impl<'a, G, R> Iterator for ChooseOutEdgeIter<'a, G, R>
178where
179 G: 'a + Choose,
180 R: Rng,
181{
182 type Item = Edge<G>;
183
184 fn next(&mut self) -> Option<Edge<G>> {
185 G::choose_out_edge(self.g, self.v, &mut self.rng)
186 }
187}
188
189/// An iterator that produces a sequence of edges that forms a walk.
190///
191/// This `struct` is created by [`Choose::random_walk`].
192///
193/// [`Choose::random_walk`]: trait.Choose.html#method.random_walk
194pub struct RandomWalk<'a, G: 'a + WithVertex, R> {
195 g: &'a G,
196 cur: Option<Vertex<G>>,
197 rng: R,
198}
199
200impl<'a, G: 'a + WithVertex, R> RandomWalk<'a, G, R> {
201 pub fn start(mut self, v: Vertex<G>) -> Self {
202 self.cur = Some(v);
203 self
204 }
205}
206
207impl<'a, G, R> Iterator for RandomWalk<'a, G, R>
208where
209 G: 'a + Choose,
210 R: Rng,
211{
212 type Item = Edge<G>;
213
214 fn next(&mut self) -> Option<Self::Item> {
215 self.cur.and_then(|cur| {
216 if let Some(e) = self.g.choose_out_edge(cur, &mut self.rng) {
217 self.cur = Some(self.g.target(e));
218 Some(e)
219 } else {
220 self.cur = None;
221 None
222 }
223 })
224 }
225}
226
227// TODO: write tests