small_world_generator.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright 2004 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_SMALL_WORLD_GENERATOR_HPP
  8. #define BOOST_GRAPH_SMALL_WORLD_GENERATOR_HPP
  9. #include <iterator>
  10. #include <utility>
  11. #include <boost/random/uniform_01.hpp>
  12. #include <boost/random/uniform_int.hpp>
  13. namespace boost {
  14. // Assumes undirected
  15. template<typename RandomGenerator, typename Graph>
  16. class small_world_iterator
  17. {
  18. typedef typename graph_traits<Graph>::vertices_size_type
  19. vertices_size_type;
  20. public:
  21. typedef std::input_iterator_tag iterator_category;
  22. typedef std::pair<vertices_size_type, vertices_size_type> value_type;
  23. typedef const value_type& reference;
  24. typedef const value_type* pointer;
  25. typedef void difference_type;
  26. small_world_iterator() : gen(0) {}
  27. small_world_iterator(RandomGenerator& gen, vertices_size_type n,
  28. vertices_size_type k, double prob = 0.0,
  29. bool allow_self_loops = false)
  30. : gen(&gen), n(n), k(k), prob(prob), source(0),
  31. target(allow_self_loops? 0 : 1),
  32. allow_self_loops(allow_self_loops),
  33. current(0, allow_self_loops? 0 : 1)
  34. { }
  35. reference operator*() const { return current; }
  36. pointer operator->() const { return &current; }
  37. small_world_iterator& operator++()
  38. {
  39. target = (target + 1) % n;
  40. if (target == (source + k/2 + 1) % n) {
  41. ++source;
  42. if (allow_self_loops) target = source;
  43. else target = (source + 1) % n;
  44. }
  45. current.first = source;
  46. uniform_01<RandomGenerator, double> rand01(*gen);
  47. uniform_int<vertices_size_type> rand_vertex_gen(0, n-1);
  48. double x = rand01();
  49. *gen = rand01.base(); // GRRRR
  50. if (x < prob) {
  51. vertices_size_type lower = (source + n - k/2) % n;
  52. vertices_size_type upper = (source + k/2) % n;
  53. do {
  54. current.second = rand_vertex_gen(*gen);
  55. } while ((current.second >= lower && current.second <= upper)
  56. || (upper < lower
  57. && (current.second >= lower || current.second <= upper)));
  58. } else {
  59. current.second = target;
  60. }
  61. return *this;
  62. }
  63. small_world_iterator operator++(int)
  64. {
  65. small_world_iterator temp(*this);
  66. ++(*this);
  67. return temp;
  68. }
  69. bool operator==(const small_world_iterator& other) const
  70. {
  71. if (!gen && other.gen) return other == *this;
  72. else if (gen && !other.gen) return source == n;
  73. else if (!gen && !other.gen) return true;
  74. return source == other.source && target == other.target;
  75. }
  76. bool operator!=(const small_world_iterator& other) const
  77. { return !(*this == other); }
  78. private:
  79. void next()
  80. {
  81. uniform_int<vertices_size_type> rand_vertex(0, n-1);
  82. current.first = rand_vertex(*gen);
  83. do {
  84. current.second = rand_vertex(*gen);
  85. } while (current.first == current.second && !allow_self_loops);
  86. }
  87. RandomGenerator* gen;
  88. vertices_size_type n;
  89. vertices_size_type k;
  90. double prob;
  91. vertices_size_type source;
  92. vertices_size_type target;
  93. bool allow_self_loops;
  94. value_type current;
  95. };
  96. } // end namespace boost
  97. #endif // BOOST_GRAPH_SMALL_WORLD_GENERATOR_HPP