plod_generator.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. // Copyright 2004-2006 The Trustees of Indiana University.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Douglas Gregor
  6. // Andrew Lumsdaine
  7. #ifndef BOOST_GRAPH_PLOD_GENERATOR_HPP
  8. #define BOOST_GRAPH_PLOD_GENERATOR_HPP
  9. #include <iterator>
  10. #include <utility>
  11. #include <boost/random/uniform_int.hpp>
  12. #include <boost/shared_ptr.hpp>
  13. #include <boost/graph/graph_traits.hpp>
  14. #include <vector>
  15. #include <map>
  16. #include <boost/config/no_tr1/cmath.hpp>
  17. #include <boost/mpl/if.hpp>
  18. namespace boost
  19. {
  20. template < typename RandomGenerator > class out_directed_plod_iterator
  21. {
  22. public:
  23. typedef std::forward_iterator_tag iterator_category;
  24. typedef std::pair< std::size_t, std::size_t > value_type;
  25. typedef const value_type& reference;
  26. typedef const value_type* pointer;
  27. typedef std::ptrdiff_t difference_type;
  28. out_directed_plod_iterator() : gen(0), at_end(true) {}
  29. out_directed_plod_iterator(RandomGenerator& gen, std::size_t n,
  30. double alpha, double beta, bool allow_self_loops)
  31. : gen(&gen)
  32. , n(n)
  33. , alpha(alpha)
  34. , beta(beta)
  35. , allow_self_loops(allow_self_loops)
  36. , at_end(false)
  37. , degree(0)
  38. , current(0, 0)
  39. {
  40. using std::pow;
  41. uniform_int< std::size_t > x(0, n - 1);
  42. std::size_t xv = x(gen);
  43. degree = (xv == 0 ? 0 : std::size_t(beta * pow(xv, -alpha)));
  44. }
  45. reference operator*() const { return current; }
  46. pointer operator->() const { return &current; }
  47. out_directed_plod_iterator& operator++()
  48. {
  49. using std::pow;
  50. uniform_int< std::size_t > x(0, n - 1);
  51. // Continue stepping through source nodes until the
  52. // (out)degree is > 0
  53. while (degree == 0)
  54. {
  55. // Step to the next source node. If we've gone past the
  56. // number of nodes we're responsible for, we're done.
  57. if (++current.first >= n)
  58. {
  59. at_end = true;
  60. return *this;
  61. }
  62. std::size_t xv = x(*gen);
  63. degree = (xv == 0 ? 0 : std::size_t(beta * pow(xv, -alpha)));
  64. }
  65. do
  66. {
  67. current.second = x(*gen);
  68. } while (current.first == current.second && !allow_self_loops);
  69. --degree;
  70. return *this;
  71. }
  72. out_directed_plod_iterator operator++(int)
  73. {
  74. out_directed_plod_iterator temp(*this);
  75. ++(*this);
  76. return temp;
  77. }
  78. bool operator==(const out_directed_plod_iterator& other) const
  79. {
  80. return at_end == other.at_end;
  81. }
  82. bool operator!=(const out_directed_plod_iterator& other) const
  83. {
  84. return !(*this == other);
  85. }
  86. private:
  87. RandomGenerator* gen;
  88. std::size_t n;
  89. double alpha;
  90. double beta;
  91. bool allow_self_loops;
  92. bool at_end;
  93. std::size_t degree;
  94. value_type current;
  95. };
  96. template < typename RandomGenerator > class undirected_plod_iterator
  97. {
  98. typedef std::vector< std::pair< std::size_t, std::size_t > > out_degrees_t;
  99. public:
  100. typedef std::input_iterator_tag iterator_category;
  101. typedef std::pair< std::size_t, std::size_t > value_type;
  102. typedef const value_type& reference;
  103. typedef const value_type* pointer;
  104. typedef std::ptrdiff_t difference_type;
  105. undirected_plod_iterator()
  106. : gen(0), out_degrees(), degrees_left(0), allow_self_loops(false)
  107. {
  108. }
  109. undirected_plod_iterator(RandomGenerator& gen, std::size_t n, double alpha,
  110. double beta, bool allow_self_loops = false)
  111. : gen(&gen)
  112. , n(n)
  113. , out_degrees(new out_degrees_t)
  114. , degrees_left(0)
  115. , allow_self_loops(allow_self_loops)
  116. {
  117. using std::pow;
  118. uniform_int< std::size_t > x(0, n - 1);
  119. for (std::size_t i = 0; i != n; ++i)
  120. {
  121. std::size_t xv = x(gen);
  122. std::size_t degree
  123. = (xv == 0 ? 0 : std::size_t(beta * pow(xv, -alpha)));
  124. if (degree == 0)
  125. degree = 1;
  126. else if (degree >= n)
  127. degree = n - 1;
  128. out_degrees->push_back(std::make_pair(i, degree));
  129. degrees_left += degree;
  130. }
  131. next();
  132. }
  133. reference operator*() const { return current; }
  134. pointer operator->() const { return &current; }
  135. undirected_plod_iterator& operator++()
  136. {
  137. next();
  138. return *this;
  139. }
  140. undirected_plod_iterator operator++(int)
  141. {
  142. undirected_plod_iterator temp(*this);
  143. ++(*this);
  144. return temp;
  145. }
  146. bool operator==(const undirected_plod_iterator& other) const
  147. {
  148. return degrees_left == other.degrees_left;
  149. }
  150. bool operator!=(const undirected_plod_iterator& other) const
  151. {
  152. return !(*this == other);
  153. }
  154. private:
  155. void next()
  156. {
  157. std::size_t source, target;
  158. while (true)
  159. {
  160. /* We may get to the point where we can't actually find any
  161. new edges, so we just add some random edge and set the
  162. degrees left = 0 to signal termination. */
  163. if (out_degrees->size() < 2)
  164. {
  165. uniform_int< std::size_t > x(0, n - 1);
  166. current.first = x(*gen);
  167. do
  168. {
  169. current.second = x(*gen);
  170. } while (current.first == current.second && !allow_self_loops);
  171. degrees_left = 0;
  172. out_degrees->clear();
  173. return;
  174. }
  175. uniform_int< std::size_t > x(0, out_degrees->size() - 1);
  176. // Select source vertex
  177. source = x(*gen);
  178. if ((*out_degrees)[source].second == 0)
  179. {
  180. (*out_degrees)[source] = out_degrees->back();
  181. out_degrees->pop_back();
  182. continue;
  183. }
  184. // Select target vertex
  185. target = x(*gen);
  186. if ((*out_degrees)[target].second == 0)
  187. {
  188. (*out_degrees)[target] = out_degrees->back();
  189. out_degrees->pop_back();
  190. continue;
  191. }
  192. else if (source != target
  193. || (allow_self_loops && (*out_degrees)[source].second > 2))
  194. {
  195. break;
  196. }
  197. }
  198. // Update degree counts
  199. --(*out_degrees)[source].second;
  200. --degrees_left;
  201. --(*out_degrees)[target].second;
  202. --degrees_left;
  203. current.first = (*out_degrees)[source].first;
  204. current.second = (*out_degrees)[target].first;
  205. }
  206. RandomGenerator* gen;
  207. std::size_t n;
  208. shared_ptr< out_degrees_t > out_degrees;
  209. std::size_t degrees_left;
  210. bool allow_self_loops;
  211. value_type current;
  212. };
  213. template < typename RandomGenerator, typename Graph >
  214. class plod_iterator
  215. : public mpl::if_<
  216. is_convertible< typename graph_traits< Graph >::directed_category,
  217. directed_tag >,
  218. out_directed_plod_iterator< RandomGenerator >,
  219. undirected_plod_iterator< RandomGenerator > >::type
  220. {
  221. typedef typename mpl::if_<
  222. is_convertible< typename graph_traits< Graph >::directed_category,
  223. directed_tag >,
  224. out_directed_plod_iterator< RandomGenerator >,
  225. undirected_plod_iterator< RandomGenerator > >::type inherited;
  226. public:
  227. plod_iterator() : inherited() {}
  228. plod_iterator(RandomGenerator& gen, std::size_t n, double alpha,
  229. double beta, bool allow_self_loops = false)
  230. : inherited(gen, n, alpha, beta, allow_self_loops)
  231. {
  232. }
  233. };
  234. } // end namespace boost
  235. #endif // BOOST_GRAPH_PLOD_GENERATOR_HPP