rmat_graph_generator.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright 2004, 2005 The Trustees of Indiana University.
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Nick Edmonds
  6. // Andrew Lumsdaine
  7. #ifndef BOOST_GRAPH_DISTRIBUTED_RMAT_GENERATOR_HPP
  8. #define BOOST_GRAPH_DISTRIBUTED_RMAT_GENERATOR_HPP
  9. #ifndef BOOST_GRAPH_USE_MPI
  10. #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
  11. #endif
  12. #include <boost/assert.hpp>
  13. #include <boost/graph/parallel/algorithm.hpp>
  14. #include <boost/graph/parallel/process_group.hpp>
  15. #include <math.h>
  16. namespace boost {
  17. // Memory-scalable (amount of memory required will scale down
  18. // linearly as the number of processes increases) generator, which
  19. // requires an MPI process group. Run-time is slightly worse than
  20. // the unique rmat generator. Edge list generated is sorted and
  21. // unique.
  22. template<typename ProcessGroup, typename Distribution,
  23. typename RandomGenerator, typename Graph>
  24. class scalable_rmat_iterator
  25. {
  26. typedef typename graph_traits<Graph>::directed_category directed_category;
  27. typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
  28. typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
  29. public:
  30. typedef std::input_iterator_tag iterator_category;
  31. typedef std::pair<vertices_size_type, vertices_size_type> value_type;
  32. typedef const value_type& reference;
  33. typedef const value_type* pointer;
  34. typedef void difference_type;
  35. // No argument constructor, set to terminating condition
  36. scalable_rmat_iterator()
  37. : gen(), done(true)
  38. { }
  39. // Initialize for edge generation
  40. scalable_rmat_iterator(ProcessGroup pg, Distribution distrib,
  41. RandomGenerator& gen, vertices_size_type n,
  42. edges_size_type m, double a, double b, double c,
  43. double d, bool permute_vertices = true)
  44. : gen(), done(false)
  45. {
  46. BOOST_ASSERT(a + b + c + d == 1);
  47. int id = process_id(pg);
  48. this->gen.reset(new uniform_01<RandomGenerator>(gen));
  49. std::vector<vertices_size_type> vertexPermutation;
  50. if (permute_vertices)
  51. generate_permutation_vector(gen, vertexPermutation, n);
  52. int SCALE = int(floor(log(double(n))/log(2.)));
  53. boost::uniform_01<RandomGenerator> prob(gen);
  54. std::map<value_type, bool> edge_map;
  55. edges_size_type generated = 0, local_edges = 0;
  56. do {
  57. edges_size_type tossed = 0;
  58. do {
  59. vertices_size_type u, v;
  60. boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d);
  61. if (permute_vertices) {
  62. u = vertexPermutation[u];
  63. v = vertexPermutation[v];
  64. }
  65. // Lowest vertex number always comes first (this
  66. // means we don't have to worry about i->j and j->i
  67. // being in the edge list)
  68. if (u > v && is_same<directed_category, undirected_tag>::value)
  69. std::swap(u, v);
  70. if (distrib(u) == id || distrib(v) == id) {
  71. if (edge_map.find(std::make_pair(u, v)) == edge_map.end()) {
  72. edge_map[std::make_pair(u, v)] = true;
  73. local_edges++;
  74. } else {
  75. tossed++;
  76. // special case - if both u and v are on same
  77. // proc, ++ twice, since we divide by two (to
  78. // cover the two process case)
  79. if (distrib(u) == id && distrib(v) == id)
  80. tossed++;
  81. }
  82. }
  83. generated++;
  84. } while (generated < m);
  85. tossed = all_reduce(pg, tossed, boost::parallel::sum<vertices_size_type>());
  86. generated -= (tossed / 2);
  87. } while (generated < m);
  88. // NGE - Asking for more than n^2 edges will result in an infinite loop here
  89. // Asking for a value too close to n^2 edges may as well
  90. values.reserve(local_edges);
  91. typename std::map<value_type, bool>::reverse_iterator em_end = edge_map.rend();
  92. for (typename std::map<value_type, bool>::reverse_iterator em_i = edge_map.rbegin();
  93. em_i != em_end ;
  94. ++em_i) {
  95. values.push_back(em_i->first);
  96. }
  97. current = values.back();
  98. values.pop_back();
  99. }
  100. reference operator*() const { return current; }
  101. pointer operator->() const { return &current; }
  102. scalable_rmat_iterator& operator++()
  103. {
  104. if (!values.empty()) {
  105. current = values.back();
  106. values.pop_back();
  107. } else
  108. done = true;
  109. return *this;
  110. }
  111. scalable_rmat_iterator operator++(int)
  112. {
  113. scalable_rmat_iterator temp(*this);
  114. ++(*this);
  115. return temp;
  116. }
  117. bool operator==(const scalable_rmat_iterator& other) const
  118. {
  119. return values.empty() && other.values.empty() && done && other.done;
  120. }
  121. bool operator!=(const scalable_rmat_iterator& other) const
  122. { return !(*this == other); }
  123. private:
  124. // Parameters
  125. shared_ptr<uniform_01<RandomGenerator> > gen;
  126. // Internal data structures
  127. std::vector<value_type> values;
  128. value_type current;
  129. bool done;
  130. };
  131. } // end namespace boost
  132. #endif // BOOST_GRAPH_DISTRIBUTED_RMAT_GENERATOR_HPP