small_world_generator.hpp 3.6 KB

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