File indexing completed on 2025-01-18 09:37:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP
0011 #define BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP
0012
0013 #include <boost/assert.hpp>
0014 #include <iterator>
0015 #include <utility>
0016 #include <boost/shared_ptr.hpp>
0017 #include <boost/random/uniform_int.hpp>
0018 #include <boost/graph/graph_traits.hpp>
0019 #include <boost/random/geometric_distribution.hpp>
0020 #include <boost/type_traits/is_base_of.hpp>
0021 #include <boost/type_traits/is_same.hpp>
0022 #include <boost/config/no_tr1/cmath.hpp>
0023 #include <boost/iterator/iterator_facade.hpp>
0024
0025 namespace boost
0026 {
0027
0028 template < typename RandomGenerator, typename Graph >
0029 class erdos_renyi_iterator
0030 : public iterator_facade< erdos_renyi_iterator< RandomGenerator, Graph >,
0031 std::pair< typename graph_traits< Graph >::vertices_size_type,
0032 typename graph_traits< Graph >::vertices_size_type >,
0033 std::input_iterator_tag,
0034 const std::pair< typename graph_traits< Graph >::vertices_size_type,
0035 typename graph_traits< Graph >::vertices_size_type >& >
0036 {
0037 typedef typename graph_traits< Graph >::directed_category directed_category;
0038 typedef
0039 typename graph_traits< Graph >::vertices_size_type vertices_size_type;
0040 typedef typename graph_traits< Graph >::edges_size_type edges_size_type;
0041
0042 BOOST_STATIC_CONSTANT(bool,
0043 is_undirected
0044 = (is_base_of< undirected_tag, directed_category >::value));
0045
0046 public:
0047 erdos_renyi_iterator() : gen(), n(0), edges(0), allow_self_loops(false) {}
0048 erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n,
0049 double fraction = 0.0, bool allow_self_loops = false)
0050 : gen(&gen)
0051 , n(n)
0052 , edges(edges_size_type(fraction * n * n))
0053 , allow_self_loops(allow_self_loops)
0054 {
0055 if (is_undirected)
0056 edges = edges / 2;
0057 next();
0058 }
0059
0060 erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n,
0061 edges_size_type m, bool allow_self_loops = false)
0062 : gen(&gen), n(n), edges(m), allow_self_loops(allow_self_loops)
0063 {
0064 next();
0065 }
0066
0067 const std::pair< vertices_size_type, vertices_size_type >&
0068 dereference() const
0069 {
0070 return current;
0071 }
0072
0073 void increment()
0074 {
0075 --edges;
0076 next();
0077 }
0078
0079 bool equal(const erdos_renyi_iterator& other) const
0080 {
0081 return edges == other.edges;
0082 }
0083
0084 private:
0085 void next()
0086 {
0087 uniform_int< vertices_size_type > rand_vertex(0, n - 1);
0088 current.first = rand_vertex(*gen);
0089 do
0090 {
0091 current.second = rand_vertex(*gen);
0092 } while (current.first == current.second && !allow_self_loops);
0093 }
0094
0095 RandomGenerator* gen;
0096 vertices_size_type n;
0097 edges_size_type edges;
0098 bool allow_self_loops;
0099 std::pair< vertices_size_type, vertices_size_type > current;
0100 };
0101
0102 template < typename RandomGenerator, typename Graph >
0103 class sorted_erdos_renyi_iterator
0104 : public iterator_facade< sorted_erdos_renyi_iterator< RandomGenerator, Graph >,
0105 std::pair< typename graph_traits< Graph >::vertices_size_type,
0106 typename graph_traits< Graph >::vertices_size_type >,
0107 std::input_iterator_tag,
0108 const std::pair< typename graph_traits< Graph >::vertices_size_type,
0109 typename graph_traits< Graph >::vertices_size_type >& >
0110 {
0111 typedef typename graph_traits< Graph >::directed_category directed_category;
0112 typedef
0113 typename graph_traits< Graph >::vertices_size_type vertices_size_type;
0114 typedef typename graph_traits< Graph >::edges_size_type edges_size_type;
0115
0116 BOOST_STATIC_CONSTANT(bool,
0117 is_undirected
0118 = (is_base_of< undirected_tag, directed_category >::value));
0119
0120 public:
0121 sorted_erdos_renyi_iterator()
0122 : gen()
0123 , rand_vertex(0.5)
0124 , n(0)
0125 , allow_self_loops(false)
0126 , src((std::numeric_limits< vertices_size_type >::max)())
0127 , tgt_index(vertices_size_type(-1))
0128 , prob(.5)
0129 {
0130 }
0131
0132
0133
0134
0135 sorted_erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n,
0136 double prob = 0.5, bool loops = false)
0137 : gen()
0138 , rand_vertex(1. - prob)
0139 , n(n)
0140 , allow_self_loops(loops)
0141 , src(0)
0142 , tgt_index(vertices_size_type(-1))
0143 , prob(prob)
0144 {
0145 this->gen.reset(new uniform_01< RandomGenerator* >(&gen));
0146
0147 if (prob == 0.0)
0148 {
0149 src = (std::numeric_limits< vertices_size_type >::max)();
0150 return;
0151 }
0152 next();
0153 }
0154
0155 const std::pair< vertices_size_type, vertices_size_type >&
0156 dereference() const
0157 {
0158 return current;
0159 }
0160
0161 bool equal(const sorted_erdos_renyi_iterator& o) const
0162 {
0163 return src == o.src && tgt_index == o.tgt_index;
0164 }
0165
0166 void increment() { next(); }
0167
0168 private:
0169 void next()
0170 {
0171
0172
0173
0174
0175
0176
0177
0178
0179 BOOST_ASSERT(src != (std::numeric_limits< vertices_size_type >::max)()
0180 && src != n);
0181 while (src != n)
0182 {
0183 vertices_size_type increment = rand_vertex(*gen);
0184 size_t tgt_index_limit
0185 = (is_undirected ? src + 1 : n) + (allow_self_loops ? 0 : -1);
0186 if (tgt_index + increment >= tgt_index_limit)
0187 {
0188
0189 ++src;
0190
0191
0192 tgt_index = vertices_size_type(-1);
0193 continue;
0194 }
0195 else
0196 {
0197 tgt_index += increment;
0198 current.first = src;
0199 current.second = tgt_index
0200 + (!allow_self_loops && !is_undirected && tgt_index >= src
0201 ? 1
0202 : 0);
0203 break;
0204 }
0205 }
0206 if (src == n)
0207 src = (std::numeric_limits< vertices_size_type >::max)();
0208 }
0209
0210 shared_ptr< uniform_01< RandomGenerator* > > gen;
0211 geometric_distribution< vertices_size_type > rand_vertex;
0212 vertices_size_type n;
0213 bool allow_self_loops;
0214 vertices_size_type src, tgt_index;
0215 std::pair< vertices_size_type, vertices_size_type > current;
0216 double prob;
0217 };
0218
0219 }
0220
0221 #endif