ssca_graph_generator.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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_SSCA_GENERATOR_HPP
  8. #define BOOST_GRAPH_SSCA_GENERATOR_HPP
  9. #include <iterator>
  10. #include <utility>
  11. #include <vector>
  12. #include <queue>
  13. #include <boost/config.hpp>
  14. #include <boost/random/uniform_int.hpp>
  15. #include <boost/graph/graph_traits.hpp>
  16. #include <boost/type_traits/is_base_and_derived.hpp>
  17. #include <boost/type_traits/is_same.hpp>
  18. enum Direction {FORWARD = 1, BACKWARD = 2, BOTH = FORWARD | BACKWARD};
  19. namespace boost {
  20. // This generator generates graphs according to the method specified
  21. // in SSCA 1.1. Current versions of SSCA use R-MAT graphs
  22. template<typename RandomGenerator, typename Graph>
  23. class ssca_iterator
  24. {
  25. typedef typename graph_traits<Graph>::directed_category directed_category;
  26. typedef typename graph_traits<Graph>::vertices_size_type
  27. vertices_size_type;
  28. public:
  29. typedef std::input_iterator_tag iterator_category;
  30. typedef std::pair<vertices_size_type, vertices_size_type> value_type;
  31. typedef const value_type& reference;
  32. typedef const value_type* pointer;
  33. typedef void difference_type;
  34. // No argument constructor, set to terminating condition
  35. ssca_iterator()
  36. : gen(), verticesRemaining(0) { }
  37. // Initialize for edge generation
  38. ssca_iterator(RandomGenerator& gen, vertices_size_type totVertices,
  39. vertices_size_type maxCliqueSize, double probUnidirectional,
  40. int maxParallelEdges, double probIntercliqueEdges)
  41. : gen(&gen), totVertices(totVertices), maxCliqueSize(maxCliqueSize),
  42. probUnidirectional(probUnidirectional), maxParallelEdges(maxParallelEdges),
  43. probIntercliqueEdges(probIntercliqueEdges), currentClique(0),
  44. verticesRemaining(totVertices)
  45. {
  46. cliqueNum = std::vector<int>(totVertices, -1);
  47. current = std::make_pair(0,0);
  48. }
  49. reference operator*() const { return current; }
  50. pointer operator->() const { return &current; }
  51. ssca_iterator& operator++()
  52. {
  53. BOOST_USING_STD_MIN();
  54. while (values.empty() && verticesRemaining > 0) { // If there are no values left, generate a new clique
  55. uniform_int<vertices_size_type> clique_size(1, maxCliqueSize);
  56. uniform_int<vertices_size_type> rand_vertex(0, totVertices-1);
  57. uniform_int<int> num_parallel_edges(1, maxParallelEdges);
  58. uniform_int<short> direction(0,1);
  59. uniform_01<RandomGenerator> prob(*gen);
  60. std::vector<vertices_size_type> cliqueVertices;
  61. cliqueVertices.clear();
  62. vertices_size_type size = min BOOST_PREVENT_MACRO_SUBSTITUTION (clique_size(*gen), verticesRemaining);
  63. while (cliqueVertices.size() < size) {
  64. vertices_size_type v = rand_vertex(*gen);
  65. if (cliqueNum[v] == -1) {
  66. cliqueNum[v] = currentClique;
  67. cliqueVertices.push_back(v);
  68. verticesRemaining--;
  69. }
  70. } // Nick: This is inefficient when only a few vertices remain...
  71. // I should probably just select the remaining vertices
  72. // in order when only a certain fraction remain.
  73. typename std::vector<vertices_size_type>::iterator first, second;
  74. for (first = cliqueVertices.begin(); first != cliqueVertices.end(); ++first)
  75. for (second = first+1; second != cliqueVertices.end(); ++second) {
  76. Direction d;
  77. int edges;
  78. d = prob() < probUnidirectional ? (direction(*gen) == 0 ? FORWARD : BACKWARD) : BOTH;
  79. if (d & FORWARD) {
  80. edges = num_parallel_edges(*gen);
  81. for (int i = 0; i < edges; ++i)
  82. values.push(std::make_pair(*first, *second));
  83. }
  84. if (d & BACKWARD) {
  85. edges = num_parallel_edges(*gen);
  86. for (int i = 0; i < edges; ++i)
  87. values.push(std::make_pair(*second, *first));
  88. }
  89. }
  90. if (verticesRemaining == 0) {
  91. // Generate interclique edges
  92. for (vertices_size_type i = 0; i < totVertices; ++i) {
  93. double p = probIntercliqueEdges;
  94. for (vertices_size_type d = 2; d < totVertices/2; d *= 2, p/= 2) {
  95. vertices_size_type j = (i+d) % totVertices;
  96. if (cliqueNum[j] != cliqueNum[i] && prob() < p) {
  97. int edges = num_parallel_edges(*gen);
  98. for (int i = 0; i < edges; ++i)
  99. values.push(std::make_pair(i, j));
  100. }
  101. }
  102. }
  103. }
  104. currentClique++;
  105. }
  106. if (!values.empty()) { // If we're not done return a value
  107. current = values.front();
  108. values.pop();
  109. }
  110. return *this;
  111. }
  112. ssca_iterator operator++(int)
  113. {
  114. ssca_iterator temp(*this);
  115. ++(*this);
  116. return temp;
  117. }
  118. bool operator==(const ssca_iterator& other) const
  119. {
  120. return verticesRemaining == other.verticesRemaining && values.empty() && other.values.empty();
  121. }
  122. bool operator!=(const ssca_iterator& other) const
  123. { return !(*this == other); }
  124. private:
  125. // Parameters
  126. RandomGenerator* gen;
  127. vertices_size_type totVertices;
  128. vertices_size_type maxCliqueSize;
  129. double probUnidirectional;
  130. int maxParallelEdges;
  131. double probIntercliqueEdges;
  132. // Internal data structures
  133. std::vector<int> cliqueNum;
  134. std::queue<value_type> values;
  135. int currentClique;
  136. vertices_size_type verticesRemaining;
  137. value_type current;
  138. };
  139. } // end namespace boost
  140. #endif // BOOST_GRAPH_SSCA_GENERATOR_HPP