1 /* boost random.hpp header file |
1 //======================================================================= |
2 * |
2 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. |
3 * Copyright Jens Maurer 2000-2001 |
3 // Copyright (C) Vladimir Prus 2003 |
4 * Distributed under the Boost Software License, Version 1.0. (See |
4 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek |
5 * accompanying file LICENSE_1_0.txt or copy at |
5 // |
6 * http://www.boost.org/LICENSE_1_0.txt) |
6 // Distributed under the Boost Software License, Version 1.0. (See |
7 * |
7 // accompanying file LICENSE_1_0.txt or copy at |
8 * See http://www.boost.org/libs/random for documentation. |
8 // http://www.boost.org/LICENSE_1_0.txt) |
9 * |
9 //======================================================================= |
10 * $Id: random.hpp,v 1.18 2004/07/27 03:43:27 dgregor Exp $ |
10 #ifndef BOOST_GRAPH_RANDOM_HPP |
11 * |
11 #define BOOST_GRAPH_RANDOM_HPP |
12 * Revision history |
12 |
13 * 2000-02-18 portability fixes (thanks to Beman Dawes) |
13 #include <boost/graph/graph_traits.hpp> |
14 * 2000-02-21 shuffle_output, inversive_congruential_schrage, |
14 #include <boost/random/uniform_int.hpp> |
15 * generator_iterator, uniform_smallint |
15 #include <boost/random/variate_generator.hpp> |
16 * 2000-02-23 generic modulus arithmetic helper, removed *_schrage classes, |
16 |
17 * implemented Streamable and EqualityComparable concepts for |
17 #include <boost/pending/property.hpp> |
18 * generators, added Bernoulli distribution and Box-Muller |
18 #include <boost/graph/properties.hpp> |
19 * transform |
19 |
20 * 2000-03-01 cauchy, lognormal, triangle distributions; fixed |
20 #include <boost/graph/adjacency_list.hpp> |
21 * uniform_smallint; renamed gaussian to normal distribution |
21 #include <boost/graph/copy.hpp> |
22 * 2000-03-05 implemented iterator syntax for distribution functions |
22 #include <boost/mpl/if.hpp> |
23 * 2000-04-21 removed some optimizations for better BCC/MSVC compatibility |
23 #include <boost/type_traits/is_convertible.hpp> |
24 * 2000-05-10 adapted to BCC and MSVC |
24 |
25 * 2000-06-13 incorporated review results |
25 #include <iostream> |
26 * 2000-07-06 moved basic templates from namespace detail to random |
|
27 * 2000-09-23 warning removals and int64 fixes (Ed Brey) |
|
28 * 2000-09-24 added lagged_fibonacci generator (Matthias Troyer) |
|
29 * 2001-02-18 moved to individual header files |
|
30 */ |
|
31 |
|
32 #ifndef BOOST_RANDOM_HPP |
|
33 #define BOOST_RANDOM_HPP |
|
34 |
|
35 // generators |
|
36 #include <boost/random/linear_congruential.hpp> |
|
37 #include <boost/random/additive_combine.hpp> |
|
38 #include <boost/random/inversive_congruential.hpp> |
|
39 #include <boost/random/shuffle_output.hpp> |
|
40 #include <boost/random/mersenne_twister.hpp> |
|
41 #include <boost/random/lagged_fibonacci.hpp> |
|
42 #include <boost/random/ranlux.hpp> |
|
43 #include <boost/random/linear_feedback_shift.hpp> |
|
44 #include <boost/random/xor_combine.hpp> |
|
45 |
26 |
46 namespace boost { |
27 namespace boost { |
47 typedef random::xor_combine<random::xor_combine<random::linear_feedback_shift<uint32_t, 32, 31, 13, 12, 0>, 0, |
28 |
48 random::linear_feedback_shift<uint32_t, 32, 29, 2, 4, 0>, 0, 0>, 0, |
29 // grab a random vertex from the graph's vertex set |
49 random::linear_feedback_shift<uint32_t, 32, 28, 3, 17, 0>, 0, 0> taus88; |
30 template <class Graph, class RandomNumGen> |
50 } // namespace boost |
31 typename graph_traits<Graph>::vertex_descriptor |
51 |
32 random_vertex(Graph& g, RandomNumGen& gen) |
52 // misc |
33 { |
53 #include <boost/random/random_number_generator.hpp> |
34 if (num_vertices(g) > 1) { |
54 |
35 #if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581)) |
55 // distributions |
36 std::size_t n = std::random( num_vertices(g) ); |
56 #include <boost/random/uniform_smallint.hpp> |
37 #else |
57 #include <boost/random/uniform_int.hpp> |
38 uniform_int<> distrib(0, num_vertices(g)-1); |
58 #include <boost/random/uniform_01.hpp> |
39 variate_generator<RandomNumGen&, uniform_int<> > rand_gen(gen, distrib); |
59 #include <boost/random/uniform_real.hpp> |
40 std::size_t n = rand_gen(); |
60 #include <boost/random/triangle_distribution.hpp> |
41 #endif |
61 #include <boost/random/bernoulli_distribution.hpp> |
42 typename graph_traits<Graph>::vertex_iterator |
62 #include <boost/random/cauchy_distribution.hpp> |
43 i = vertices(g).first; |
63 #include <boost/random/exponential_distribution.hpp> |
44 while (n-- > 0) ++i; // std::advance not VC++ portable |
64 #include <boost/random/geometric_distribution.hpp> |
45 return *i; |
65 #include <boost/random/normal_distribution.hpp> |
46 } else |
66 #include <boost/random/lognormal_distribution.hpp> |
47 return *vertices(g).first; |
67 #include <boost/random/poisson_distribution.hpp> |
48 } |
68 #include <boost/random/gamma_distribution.hpp> |
49 |
69 #include <boost/random/binomial_distribution.hpp> |
50 template <class Graph, class RandomNumGen> |
70 #include <boost/random/uniform_on_sphere.hpp> |
51 typename graph_traits<Graph>::edge_descriptor |
71 |
52 random_edge(Graph& g, RandomNumGen& gen) { |
72 #endif // BOOST_RANDOM_HPP |
53 if (num_edges(g) > 1) { |
|
54 #if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581)) |
|
55 typename graph_traits<Graph>::edges_size_type |
|
56 n = std::random( num_edges(g) ); |
|
57 #else |
|
58 uniform_int<> distrib(0, num_edges(g)-1); |
|
59 variate_generator<RandomNumGen&, uniform_int<> > rand_gen(gen, distrib); |
|
60 typename graph_traits<Graph>::edges_size_type |
|
61 n = rand_gen(); |
|
62 #endif |
|
63 typename graph_traits<Graph>::edge_iterator |
|
64 i = edges(g).first; |
|
65 while (n-- > 0) ++i; // std::advance not VC++ portable |
|
66 return *i; |
|
67 } else |
|
68 return *edges(g).first; |
|
69 } |
|
70 |
|
71 namespace detail { |
|
72 class dummy_property_copier { |
|
73 public: |
|
74 template<class V1, class V2> |
|
75 void operator()(const V1&, const V2&) const {} |
|
76 }; |
|
77 } |
|
78 |
|
79 template <typename MutableGraph, class RandNumGen> |
|
80 void generate_random_graph1 |
|
81 (MutableGraph& g, |
|
82 typename graph_traits<MutableGraph>::vertices_size_type V, |
|
83 typename graph_traits<MutableGraph>::vertices_size_type E, |
|
84 RandNumGen& gen, |
|
85 bool allow_parallel = true, |
|
86 bool self_edges = false) |
|
87 { |
|
88 typedef graph_traits<MutableGraph> Traits; |
|
89 typedef typename Traits::vertices_size_type v_size_t; |
|
90 typedef typename Traits::edges_size_type e_size_t; |
|
91 typedef typename Traits::vertex_descriptor vertex_descriptor; |
|
92 |
|
93 // When parallel edges are not allowed, we create a new graph which |
|
94 // does not allow parallel edges, construct it and copy back. |
|
95 // This is not efficient if 'g' already disallow parallel edges, |
|
96 // but that's task for later. |
|
97 if (!allow_parallel) { |
|
98 |
|
99 typedef typename boost::graph_traits<MutableGraph>::directed_category dir; |
|
100 typedef typename mpl::if_<is_convertible<dir, directed_tag>, |
|
101 directedS, undirectedS>::type select; |
|
102 adjacency_list<setS, vecS, select> g2; |
|
103 generate_random_graph1(g2, V, E, gen, true, self_edges); |
|
104 |
|
105 copy_graph(g2, g, vertex_copy(detail::dummy_property_copier()). |
|
106 edge_copy(detail::dummy_property_copier())); |
|
107 |
|
108 } else { |
|
109 |
|
110 for (v_size_t i = 0; i < V; ++i) |
|
111 add_vertex(g); |
|
112 |
|
113 for (e_size_t j = 0; j < E; ++j) { |
|
114 vertex_descriptor a = random_vertex(g, gen), b; |
|
115 do { |
|
116 b = random_vertex(g, gen); |
|
117 } while (self_edges == false && a == b); |
|
118 add_edge(a, b, g); |
|
119 } |
|
120 } |
|
121 } |
|
122 |
|
123 template <typename MutableGraph, class RandNumGen> |
|
124 void generate_random_graph |
|
125 (MutableGraph& g, |
|
126 typename graph_traits<MutableGraph>::vertices_size_type V, |
|
127 typename graph_traits<MutableGraph>::vertices_size_type E, |
|
128 RandNumGen& gen, |
|
129 bool allow_parallel = true, |
|
130 bool self_edges = false) |
|
131 { |
|
132 generate_random_graph1(g, V, E, gen, allow_parallel, self_edges); |
|
133 } |
|
134 |
|
135 template <typename MutableGraph, typename RandNumGen, |
|
136 typename VertexOutputIterator, typename EdgeOutputIterator> |
|
137 void generate_random_graph |
|
138 (MutableGraph& g, |
|
139 typename graph_traits<MutableGraph>::vertices_size_type V, |
|
140 typename graph_traits<MutableGraph>::vertices_size_type E, |
|
141 RandNumGen& gen, |
|
142 VertexOutputIterator vertex_out, |
|
143 EdgeOutputIterator edge_out, |
|
144 bool self_edges = false) |
|
145 { |
|
146 typedef graph_traits<MutableGraph> Traits; |
|
147 typedef typename Traits::vertices_size_type v_size_t; |
|
148 typedef typename Traits::edges_size_type e_size_t; |
|
149 typedef typename Traits::vertex_descriptor vertex_t; |
|
150 typedef typename Traits::edge_descriptor edge_t; |
|
151 |
|
152 for (v_size_t i = 0; i < V; ++i) |
|
153 *vertex_out++ = add_vertex(g); |
|
154 |
|
155 for (e_size_t j = 0; j < E; ++j) { |
|
156 vertex_t a = random_vertex(g, gen), b; |
|
157 do { |
|
158 b = random_vertex(g, gen); |
|
159 } while (self_edges == false && a == b); |
|
160 edge_t e; bool inserted; |
|
161 tie(e, inserted) = add_edge(a, b, g); |
|
162 if (inserted) |
|
163 *edge_out++ = std::make_pair(source(e, g), target(e, g)); |
|
164 } |
|
165 } |
|
166 |
|
167 namespace detail { |
|
168 |
|
169 template<class Property, class G, class RandomGenerator> |
|
170 void randomize_property(G& g, RandomGenerator& rg, |
|
171 Property, vertex_property_tag) |
|
172 { |
|
173 typename property_map<G, Property>::type pm = get(Property(), g); |
|
174 typename graph_traits<G>::vertex_iterator vi, ve; |
|
175 for (tie(vi, ve) = vertices(g); vi != ve; ++vi) { |
|
176 pm[*vi] = rg(); |
|
177 } |
|
178 } |
|
179 |
|
180 template<class Property, class G, class RandomGenerator> |
|
181 void randomize_property(G& g, RandomGenerator& rg, |
|
182 Property, edge_property_tag) |
|
183 { |
|
184 typename property_map<G, Property>::type pm = get(Property(), g); |
|
185 typename graph_traits<G>::edge_iterator ei, ee; |
|
186 for (tie(ei, ee) = edges(g); ei != ee; ++ei) { |
|
187 pm[*ei] = rg(); |
|
188 } |
|
189 } |
|
190 } |
|
191 |
|
192 template<class Property, class G, class RandomGenerator> |
|
193 void randomize_property(G& g, RandomGenerator& rg) |
|
194 { |
|
195 detail::randomize_property |
|
196 (g, rg, Property(), typename property_kind<Property>::type()); |
|
197 } |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 } |
|
203 |
|
204 |
|
205 #endif |