small_world_generator.hpp 3.6 KB

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