fera_graph/
arbitrary.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//! Generate arbitrary graphs to be use in [quickcheck] tests.
6//!
7//! This requires enabling `quickcheck` feature.
8//!
9//! # Examples:
10//!
11//! Testing [`WithBuilder::new_gn_connected`] against [`Components::is_connected`]:
12//!
13//! ```
14//! #[macro_use]
15//! extern crate quickcheck;
16//! extern crate fera_graph;
17//!
18//! use fera_graph::prelude::*;
19//! use fera_graph::algs::Components;
20//! use fera_graph::arbitrary::GnConnected;
21//! use quickcheck::quickcheck;
22//!
23//! fn main() {
24//!     fn tree(g: GnConnected<StaticGraph>) -> bool {
25//!         let GnConnected(g) = g;
26//!         g.is_connected()
27//!     }
28//!
29//!     quickcheck(tree as fn(GnConnected<StaticGraph>) -> bool);
30//! }
31//! ```
32//!
33//! [quickcheck]: https://github.com/BurntSushi/quickcheck
34//! [`Components::is_connected`]: ../algs/components/trait.Components.html#method.is_connected
35//! [`WithBuilder::new_gn_connected`]: ../builder/trait.WithBuilder.html#method.new_gn_connected
36
37use graphs::adjset::{AdjSetEdge, UndirectedEdge};
38use prelude::*;
39use props::HashMapProp;
40
41use fera_fun::vec;
42use quickcheck::{Arbitrary, Gen};
43use rand::Rng;
44
45use std::cmp;
46use std::collections::HashSet;
47use std::fmt::Debug;
48
49fn shrink_graph<G>(g: &G) -> Box<Iterator<Item = G>>
50where
51    G: EdgeList + VertexList + WithBuilder,
52    G::Kind: UniformEdgeKind,
53{
54    let mut id: HashMapProp<Vertex<G>, usize> = g.vertex_prop(0);
55    for (i, v) in g.vertices().enumerate() {
56        id[v] = i;
57    }
58    let edges = vec(g.edges_ends().map(|(u, v)| (id[u], id[v])));
59    let iter = edges.shrink().map(|edges| {
60        let n = edges
61            .iter()
62            .map(|&(u, v)| cmp::max(u, v) + 1)
63            .max()
64            .unwrap_or(0);
65        if G::Kind::is_undirected() {
66            let set: HashSet<_> = edges
67                .iter()
68                .filter(|&&(u, v)| u != v)
69                .map(|&(u, v)| UndirectedEdge::new(u, v))
70                .collect();
71            let edges = set.into_iter().map(|e| (e.source(), e.target()));
72            G::new_with_edges(n, edges)
73        } else {
74            let set: HashSet<_> = edges.iter().filter(|&&(u, v)| u != v).cloned().collect();
75            G::new_with_edges(n, set)
76        }
77    });
78    Box::new(iter)
79}
80
81macro_rules! def_random {
82    ($(#[$name_meta:meta])* $name:ident,
83     $(#[$namev_meta:meta])* $namev:ident,
84     $(#[$namee_meta:meta])* $namee:ident,
85     $fun:ident) => (
86        $(#[$name_meta])*
87        #[derive(Clone, Debug)]
88        pub struct $name<G>(pub G);
89
90        impl<G> Arbitrary for $name<G>
91            where G: Clone + Send + 'static + VertexList + EdgeList + WithBuilder,
92                  G::Kind: UniformEdgeKind
93        {
94            fn arbitrary<Ge: Gen>(gen: &mut Ge) -> Self {
95                let s = gen.size();
96                let n = gen.gen_range(0, s);
97                $name(G::$fun(n, gen))
98            }
99
100            fn shrink(&self) -> Box<Iterator<Item = Self>> {
101                Box::new(shrink_graph(&self.0).map($name))
102            }
103        }
104
105        $(#[$namev_meta])*
106        #[derive(Clone, Debug)]
107        pub struct $namev<G, T>(pub G, pub DefaultVertexPropMut<G, T>)
108            where G: WithVertexProp<T>,
109                  DefaultVertexPropMut<G, T>: Debug + Clone;
110
111        impl<G, T> Arbitrary for $namev<G, T>
112            where G: Clone + Send + 'static + VertexList + EdgeList + WithBuilder,
113                  G::Kind: UniformEdgeKind,
114                  G: WithVertexProp<T>,
115                  DefaultVertexPropMut<G, T>: Debug + Clone + Send + 'static,
116                  T: Arbitrary + Default + Clone
117        {
118            fn arbitrary<Ge: Gen>(g: &mut Ge) -> Self {
119                let $name(graph) = $name::<G>::arbitrary(g);
120                let prop = graph.default_vertex_prop_from_fn(|_| T::arbitrary(g));
121                $namev(graph, prop)
122            }
123
124            fn shrink(&self) -> Box<Iterator<Item = Self>> {
125                let g = $name(self.0.clone());
126                let prop = self.1.clone();
127                let iter = g.shrink()
128                    .map(move |g| {
129                             let prop = g.0.default_vertex_prop_from_fn(|v| prop[v].clone());
130                             $namev(g.0, prop)
131                         });
132                Box::new(iter)
133            }
134        }
135
136        $(#[$namee_meta])*
137        #[derive(Clone, Debug)]
138        pub struct $namee<G, T>(pub G, pub DefaultEdgePropMut<G, T>)
139            where G: WithEdgeProp<T>,
140                  DefaultEdgePropMut<G, T>: Debug + Clone;
141
142        impl<G, T> Arbitrary for $namee<G, T>
143            where G: Clone + Send + 'static + VertexList + EdgeList + WithBuilder,
144                  G::Kind: UniformEdgeKind,
145                  G: WithEdgeProp<T>,
146                  DefaultEdgePropMut<G, T>: Debug + Clone + Send + 'static,
147                  T: Arbitrary + Default + Clone
148        {
149            fn arbitrary<Ge: Gen>(g: &mut Ge) -> Self {
150                let $name(graph) = $name::<G>::arbitrary(g);
151                let prop = graph.default_edge_prop_from_fn(|_| T::arbitrary(g));
152                $namee(graph, prop)
153            }
154
155            fn shrink(&self) -> Box<Iterator<Item = Self>> {
156                let g = $name(self.0.clone());
157                let prop = self.1.clone();
158                let iter = g.shrink()
159                    .map(move |$name(gn)| {
160                        let mut propn = gn.default_edge_prop(T::default());
161                        for (en, u, v) in gn.edges_with_ends() {
162                            if let Some(e) = g.0.get_edge_by_ends(u, v) {
163                                propn[en] = prop[e].clone();
164                            }
165                        }
166                        $namee(gn, propn)
167                    });
168                Box::new(iter)
169            }
170        }
171    )
172}
173
174def_random!{
175    /// A wrapper to create arbitrary graphs using [`WithBuilder::new_gn`].
176    ///
177    /// [`WithBuilder::new_gn`]: ../builder/trait.WithBuilder.html#method.new_gn
178    Gn,
179
180    /// A wrapper to create arbitrary graphs with a vertex property using [`WithBuilder::new_gn`].
181    ///
182    /// [`WithBuilder::new_gn`]: ../builder/trait.WithBuilder.html#method.new_gn
183    GnWithVertexProp,
184
185    /// A wrapper to create arbitrary graphs with an edge property using [`WithBuilder::new_gn`].
186    ///
187    /// [`WithBuilder::new_gn`]: ../builder/trait.WithBuilder.html#method.new_gn
188    GnWithEdgeProp,
189
190    new_gn
191}
192
193def_random!{
194    /// A wrapper to create arbitrary graphs using [`WithBuilder::new_gn_connected`].
195    ///
196    /// [`WithBuilder::new_gn_connected`]: trait.WithBuilder.html#method.new_gn_connected
197    GnConnected,
198
199    /// A wrapper to create arbitrary graphs with a vertex property using
200    /// [`WithBuilder::new_gn_connected`].
201    ///
202    /// [`WithBuilder::new_gn_connected`]: ../builder/trait.WithBuilder.html#method.new_gn_connected
203    GnConnectedWithVertexProp,
204
205    /// A wrapper to create arbitrary graphs with an edge property using
206    /// [`WithBuilder::new_gn_connected`].
207    ///
208    /// [`WithBuilder::new_gn_connected`]: ../builder/trait.WithBuilder.html#method.new_gn_connected
209    GnConnectedWithEdgeProp,
210    new_gn_connected
211}
212
213// TODO: add CompleteWithVertexProp and CompleteWithVertexProp
214impl Arbitrary for CompleteGraph {
215    fn arbitrary<G: Gen>(gen: &mut G) -> Self {
216        let s = gen.size();
217        let n = gen.gen_range(0, s) as u32;
218        CompleteGraph::new(n)
219    }
220
221    fn shrink(&self) -> Box<Iterator<Item = Self>> {
222        let n = self.num_vertices();
223        Box::new(n.shrink().map(|n| CompleteGraph::new(n as u32)))
224    }
225}