rmat_graph_generator.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  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_RMAT_GENERATOR_HPP
  8. #define BOOST_GRAPH_RMAT_GENERATOR_HPP
  9. #include <math.h>
  10. #include <iterator>
  11. #include <utility>
  12. #include <vector>
  13. #include <queue>
  14. #include <map>
  15. #include <boost/shared_ptr.hpp>
  16. #include <boost/assert.hpp>
  17. #include <boost/random/uniform_int.hpp>
  18. #include <boost/random/uniform_01.hpp>
  19. #include <boost/graph/graph_traits.hpp>
  20. #include <boost/graph/detail/mpi_include.hpp>
  21. #include <boost/type_traits/is_base_and_derived.hpp>
  22. #include <boost/type_traits/is_same.hpp>
  23. // #include <boost/test/floating_point_comparison.hpp>
  24. using boost::shared_ptr;
  25. using boost::uniform_01;
  26. // Returns floor(log_2(n)), and -1 when n is 0
  27. template < typename IntegerType > inline int int_log2(IntegerType n)
  28. {
  29. int l = 0;
  30. while (n > 0)
  31. {
  32. ++l;
  33. n >>= 1;
  34. }
  35. return l - 1;
  36. }
  37. struct keep_all_edges
  38. {
  39. template < typename T > bool operator()(const T&, const T&) { return true; }
  40. };
  41. template < typename Distribution, typename ProcessId > struct keep_local_edges
  42. {
  43. keep_local_edges(const Distribution& distrib, const ProcessId& id)
  44. : distrib(distrib), id(id)
  45. {
  46. }
  47. template < typename T > bool operator()(const T& x, const T& y)
  48. {
  49. return distrib(x) == id || distrib(y) == id;
  50. }
  51. private:
  52. const Distribution& distrib;
  53. const ProcessId& id;
  54. };
  55. template < typename RandomGenerator, typename T >
  56. void generate_permutation_vector(
  57. RandomGenerator& gen, std::vector< T >& vertexPermutation, T n)
  58. {
  59. using boost::uniform_int;
  60. vertexPermutation.resize(n);
  61. // Generate permutation map of vertex numbers
  62. uniform_int< T > rand_vertex(0, n - 1);
  63. for (T i = 0; i < n; ++i)
  64. vertexPermutation[i] = i;
  65. // Can't use std::random_shuffle unless we create another (synchronized)
  66. // PRNG
  67. for (T i = 0; i < n; ++i)
  68. std::swap(vertexPermutation[i], vertexPermutation[rand_vertex(gen)]);
  69. }
  70. template < typename RandomGenerator, typename T >
  71. std::pair< T, T > generate_edge(
  72. shared_ptr< uniform_01< RandomGenerator > > prob, T n, unsigned int SCALE,
  73. double a, double b, double c, double d)
  74. {
  75. T u = 0, v = 0;
  76. T step = n / 2;
  77. for (unsigned int j = 0; j < SCALE; ++j)
  78. {
  79. double p = (*prob)();
  80. if (p < a)
  81. ;
  82. else if (p >= a && p < a + b)
  83. v += step;
  84. else if (p >= a + b && p < a + b + c)
  85. u += step;
  86. else
  87. { // p > a + b + c && p < a + b + c + d
  88. u += step;
  89. v += step;
  90. }
  91. step /= 2;
  92. // 0.2 and 0.9 are hardcoded in the reference SSCA implementation.
  93. // The maximum change in any given value should be less than 10%
  94. a *= 0.9 + 0.2 * (*prob)();
  95. b *= 0.9 + 0.2 * (*prob)();
  96. c *= 0.9 + 0.2 * (*prob)();
  97. d *= 0.9 + 0.2 * (*prob)();
  98. double S = a + b + c + d;
  99. a /= S;
  100. b /= S;
  101. c /= S;
  102. // d /= S;
  103. // Ensure all values add up to 1, regardless of floating point errors
  104. d = 1. - a - b - c;
  105. }
  106. return std::make_pair(u, v);
  107. }
  108. namespace boost
  109. {
  110. /*
  111. Chakrabarti's R-MAT scale free generator.
  112. For all flavors of the R-MAT iterator a+b+c+d must equal 1 and for the
  113. unique_rmat_iterator 'm' << 'n^2'. If 'm' is too close to 'n^2' the
  114. generator may be unable to generate sufficient unique edges
  115. To get a true scale free distribution {a, b, c, d : a > b, a > c, a > d}
  116. */
  117. template < typename RandomGenerator, typename Graph > class rmat_iterator
  118. {
  119. typedef typename graph_traits< Graph >::directed_category directed_category;
  120. typedef
  121. typename graph_traits< Graph >::vertices_size_type vertices_size_type;
  122. typedef typename graph_traits< Graph >::edges_size_type edges_size_type;
  123. public:
  124. typedef std::input_iterator_tag iterator_category;
  125. typedef std::pair< vertices_size_type, vertices_size_type > value_type;
  126. typedef const value_type& reference;
  127. typedef const value_type* pointer;
  128. typedef std::ptrdiff_t difference_type; // Not used
  129. // No argument constructor, set to terminating condition
  130. rmat_iterator() : gen(), edge(0) {}
  131. // Initialize for edge generation
  132. rmat_iterator(RandomGenerator& gen, vertices_size_type n, edges_size_type m,
  133. double a, double b, double c, double d, bool permute_vertices = true)
  134. : gen()
  135. , n(n)
  136. , a(a)
  137. , b(b)
  138. , c(c)
  139. , d(d)
  140. , edge(m)
  141. , permute_vertices(permute_vertices)
  142. , SCALE(int_log2(n))
  143. {
  144. this->gen.reset(new uniform_01< RandomGenerator >(gen));
  145. // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c +
  146. // d, 1., 1.e-5));
  147. if (permute_vertices)
  148. generate_permutation_vector(gen, vertexPermutation, n);
  149. // TODO: Generate the entire adjacency matrix then "Clip and flip" if
  150. // undirected graph
  151. // Generate the first edge
  152. vertices_size_type u, v;
  153. boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d);
  154. if (permute_vertices)
  155. current
  156. = std::make_pair(vertexPermutation[u], vertexPermutation[v]);
  157. else
  158. current = std::make_pair(u, v);
  159. --edge;
  160. }
  161. reference operator*() const { return current; }
  162. pointer operator->() const { return &current; }
  163. rmat_iterator& operator++()
  164. {
  165. vertices_size_type u, v;
  166. boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d);
  167. if (permute_vertices)
  168. current
  169. = std::make_pair(vertexPermutation[u], vertexPermutation[v]);
  170. else
  171. current = std::make_pair(u, v);
  172. --edge;
  173. return *this;
  174. }
  175. rmat_iterator operator++(int)
  176. {
  177. rmat_iterator temp(*this);
  178. ++(*this);
  179. return temp;
  180. }
  181. bool operator==(const rmat_iterator& other) const
  182. {
  183. return edge == other.edge;
  184. }
  185. bool operator!=(const rmat_iterator& other) const
  186. {
  187. return !(*this == other);
  188. }
  189. private:
  190. // Parameters
  191. shared_ptr< uniform_01< RandomGenerator > > gen;
  192. vertices_size_type n;
  193. double a, b, c, d;
  194. int edge;
  195. bool permute_vertices;
  196. int SCALE;
  197. // Internal data structures
  198. std::vector< vertices_size_type > vertexPermutation;
  199. value_type current;
  200. };
  201. // Sorted version for CSR
  202. template < typename T > struct sort_pair
  203. {
  204. bool operator()(const std::pair< T, T >& x, const std::pair< T, T >& y)
  205. {
  206. if (x.first == y.first)
  207. return x.second > y.second;
  208. else
  209. return x.first > y.first;
  210. }
  211. };
  212. template < typename RandomGenerator, typename Graph,
  213. typename EdgePredicate = keep_all_edges >
  214. class sorted_rmat_iterator
  215. {
  216. typedef typename graph_traits< Graph >::directed_category directed_category;
  217. typedef
  218. typename graph_traits< Graph >::vertices_size_type vertices_size_type;
  219. typedef typename graph_traits< Graph >::edges_size_type edges_size_type;
  220. public:
  221. typedef std::input_iterator_tag iterator_category;
  222. typedef std::pair< vertices_size_type, vertices_size_type > value_type;
  223. typedef const value_type& reference;
  224. typedef const value_type* pointer;
  225. typedef std::ptrdiff_t difference_type; // Not used
  226. // No argument constructor, set to terminating condition
  227. sorted_rmat_iterator()
  228. : gen(), values(sort_pair< vertices_size_type >()), done(true)
  229. {
  230. }
  231. // Initialize for edge generation
  232. sorted_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
  233. edges_size_type m, double a, double b, double c, double d,
  234. bool permute_vertices = true, EdgePredicate ep = keep_all_edges())
  235. : gen()
  236. , permute_vertices(permute_vertices)
  237. , values(sort_pair< vertices_size_type >())
  238. , done(false)
  239. {
  240. // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c +
  241. // d, 1., 1.e-5));
  242. this->gen.reset(new uniform_01< RandomGenerator >(gen));
  243. std::vector< vertices_size_type > vertexPermutation;
  244. if (permute_vertices)
  245. generate_permutation_vector(gen, vertexPermutation, n);
  246. // TODO: "Clip and flip" if undirected graph
  247. int SCALE = int_log2(n);
  248. for (edges_size_type i = 0; i < m; ++i)
  249. {
  250. vertices_size_type u, v;
  251. boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d);
  252. if (permute_vertices)
  253. {
  254. if (ep(vertexPermutation[u], vertexPermutation[v]))
  255. values.push(std::make_pair(
  256. vertexPermutation[u], vertexPermutation[v]));
  257. }
  258. else
  259. {
  260. if (ep(u, v))
  261. values.push(std::make_pair(u, v));
  262. }
  263. }
  264. current = values.top();
  265. values.pop();
  266. }
  267. reference operator*() const { return current; }
  268. pointer operator->() const { return &current; }
  269. sorted_rmat_iterator& operator++()
  270. {
  271. if (!values.empty())
  272. {
  273. current = values.top();
  274. values.pop();
  275. }
  276. else
  277. done = true;
  278. return *this;
  279. }
  280. sorted_rmat_iterator operator++(int)
  281. {
  282. sorted_rmat_iterator temp(*this);
  283. ++(*this);
  284. return temp;
  285. }
  286. bool operator==(const sorted_rmat_iterator& other) const
  287. {
  288. return values.empty() && other.values.empty() && done && other.done;
  289. }
  290. bool operator!=(const sorted_rmat_iterator& other) const
  291. {
  292. return !(*this == other);
  293. }
  294. private:
  295. // Parameters
  296. shared_ptr< uniform_01< RandomGenerator > > gen;
  297. bool permute_vertices;
  298. // Internal data structures
  299. std::priority_queue< value_type, std::vector< value_type >,
  300. sort_pair< vertices_size_type > >
  301. values;
  302. value_type current;
  303. bool done;
  304. };
  305. // This version is slow but guarantees unique edges
  306. template < typename RandomGenerator, typename Graph,
  307. typename EdgePredicate = keep_all_edges >
  308. class unique_rmat_iterator
  309. {
  310. typedef typename graph_traits< Graph >::directed_category directed_category;
  311. typedef
  312. typename graph_traits< Graph >::vertices_size_type vertices_size_type;
  313. typedef typename graph_traits< Graph >::edges_size_type edges_size_type;
  314. public:
  315. typedef std::input_iterator_tag iterator_category;
  316. typedef std::pair< vertices_size_type, vertices_size_type > value_type;
  317. typedef const value_type& reference;
  318. typedef const value_type* pointer;
  319. typedef std::ptrdiff_t difference_type; // Not used
  320. // No argument constructor, set to terminating condition
  321. unique_rmat_iterator() : gen(), done(true) {}
  322. // Initialize for edge generation
  323. unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
  324. edges_size_type m, double a, double b, double c, double d,
  325. bool permute_vertices = true, EdgePredicate ep = keep_all_edges())
  326. : gen(), done(false)
  327. {
  328. // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c +
  329. // d, 1., 1.e-5));
  330. this->gen.reset(new uniform_01< RandomGenerator >(gen));
  331. std::vector< vertices_size_type > vertexPermutation;
  332. if (permute_vertices)
  333. generate_permutation_vector(gen, vertexPermutation, n);
  334. int SCALE = int_log2(n);
  335. std::map< value_type, bool > edge_map;
  336. edges_size_type edges = 0;
  337. do
  338. {
  339. vertices_size_type u, v;
  340. boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d);
  341. // Lowest vertex number always comes first
  342. // (this means we don't have to worry about i->j and j->i being in
  343. // the edge list)
  344. if (u > v && is_same< directed_category, undirected_tag >::value)
  345. std::swap(u, v);
  346. if (edge_map.find(std::make_pair(u, v)) == edge_map.end())
  347. {
  348. edge_map[std::make_pair(u, v)] = true;
  349. if (permute_vertices)
  350. {
  351. if (ep(vertexPermutation[u], vertexPermutation[v]))
  352. values.push_back(std::make_pair(
  353. vertexPermutation[u], vertexPermutation[v]));
  354. }
  355. else
  356. {
  357. if (ep(u, v))
  358. values.push_back(std::make_pair(u, v));
  359. }
  360. edges++;
  361. }
  362. } while (edges < m);
  363. // NGE - Asking for more than n^2 edges will result in an infinite loop
  364. // here
  365. // Asking for a value too close to n^2 edges may as well
  366. current = values.back();
  367. values.pop_back();
  368. }
  369. reference operator*() const { return current; }
  370. pointer operator->() const { return &current; }
  371. unique_rmat_iterator& operator++()
  372. {
  373. if (!values.empty())
  374. {
  375. current = values.back();
  376. values.pop_back();
  377. }
  378. else
  379. done = true;
  380. return *this;
  381. }
  382. unique_rmat_iterator operator++(int)
  383. {
  384. unique_rmat_iterator temp(*this);
  385. ++(*this);
  386. return temp;
  387. }
  388. bool operator==(const unique_rmat_iterator& other) const
  389. {
  390. return values.empty() && other.values.empty() && done && other.done;
  391. }
  392. bool operator!=(const unique_rmat_iterator& other) const
  393. {
  394. return !(*this == other);
  395. }
  396. private:
  397. // Parameters
  398. shared_ptr< uniform_01< RandomGenerator > > gen;
  399. // Internal data structures
  400. std::vector< value_type > values;
  401. value_type current;
  402. bool done;
  403. };
  404. // This version is slow but guarantees unique edges
  405. template < typename RandomGenerator, typename Graph,
  406. typename EdgePredicate = keep_all_edges >
  407. class sorted_unique_rmat_iterator
  408. {
  409. typedef typename graph_traits< Graph >::directed_category directed_category;
  410. typedef
  411. typename graph_traits< Graph >::vertices_size_type vertices_size_type;
  412. typedef typename graph_traits< Graph >::edges_size_type edges_size_type;
  413. public:
  414. typedef std::input_iterator_tag iterator_category;
  415. typedef std::pair< vertices_size_type, vertices_size_type > value_type;
  416. typedef const value_type& reference;
  417. typedef const value_type* pointer;
  418. typedef std::ptrdiff_t difference_type; // Not used
  419. // No argument constructor, set to terminating condition
  420. sorted_unique_rmat_iterator()
  421. : gen(), values(sort_pair< vertices_size_type >()), done(true)
  422. {
  423. }
  424. // Initialize for edge generation
  425. sorted_unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
  426. edges_size_type m, double a, double b, double c, double d,
  427. bool bidirectional = false, bool permute_vertices = true,
  428. EdgePredicate ep = keep_all_edges())
  429. : gen()
  430. , bidirectional(bidirectional)
  431. , values(sort_pair< vertices_size_type >())
  432. , done(false)
  433. {
  434. // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c +
  435. // d, 1., 1.e-5));
  436. this->gen.reset(new uniform_01< RandomGenerator >(gen));
  437. std::vector< vertices_size_type > vertexPermutation;
  438. if (permute_vertices)
  439. generate_permutation_vector(gen, vertexPermutation, n);
  440. int SCALE = int_log2(n);
  441. std::map< value_type, bool > edge_map;
  442. edges_size_type edges = 0;
  443. do
  444. {
  445. vertices_size_type u, v;
  446. boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d);
  447. if (bidirectional)
  448. {
  449. if (edge_map.find(std::make_pair(u, v)) == edge_map.end())
  450. {
  451. edge_map[std::make_pair(u, v)] = true;
  452. edge_map[std::make_pair(v, u)] = true;
  453. if (ep(u, v))
  454. {
  455. if (permute_vertices)
  456. {
  457. values.push(std::make_pair(
  458. vertexPermutation[u], vertexPermutation[v]));
  459. values.push(std::make_pair(
  460. vertexPermutation[v], vertexPermutation[u]));
  461. }
  462. else
  463. {
  464. values.push(std::make_pair(u, v));
  465. values.push(std::make_pair(v, u));
  466. }
  467. }
  468. ++edges;
  469. }
  470. }
  471. else
  472. {
  473. // Lowest vertex number always comes first
  474. // (this means we don't have to worry about i->j and j->i being
  475. // in the edge list)
  476. if (u > v
  477. && is_same< directed_category, undirected_tag >::value)
  478. std::swap(u, v);
  479. if (edge_map.find(std::make_pair(u, v)) == edge_map.end())
  480. {
  481. edge_map[std::make_pair(u, v)] = true;
  482. if (permute_vertices)
  483. {
  484. if (ep(vertexPermutation[u], vertexPermutation[v]))
  485. values.push(std::make_pair(
  486. vertexPermutation[u], vertexPermutation[v]));
  487. }
  488. else
  489. {
  490. if (ep(u, v))
  491. values.push(std::make_pair(u, v));
  492. }
  493. ++edges;
  494. }
  495. }
  496. } while (edges < m);
  497. // NGE - Asking for more than n^2 edges will result in an infinite loop
  498. // here
  499. // Asking for a value too close to n^2 edges may as well
  500. current = values.top();
  501. values.pop();
  502. }
  503. reference operator*() const { return current; }
  504. pointer operator->() const { return &current; }
  505. sorted_unique_rmat_iterator& operator++()
  506. {
  507. if (!values.empty())
  508. {
  509. current = values.top();
  510. values.pop();
  511. }
  512. else
  513. done = true;
  514. return *this;
  515. }
  516. sorted_unique_rmat_iterator operator++(int)
  517. {
  518. sorted_unique_rmat_iterator temp(*this);
  519. ++(*this);
  520. return temp;
  521. }
  522. bool operator==(const sorted_unique_rmat_iterator& other) const
  523. {
  524. return values.empty() && other.values.empty() && done && other.done;
  525. }
  526. bool operator!=(const sorted_unique_rmat_iterator& other) const
  527. {
  528. return !(*this == other);
  529. }
  530. private:
  531. // Parameters
  532. shared_ptr< uniform_01< RandomGenerator > > gen;
  533. bool bidirectional;
  534. // Internal data structures
  535. std::priority_queue< value_type, std::vector< value_type >,
  536. sort_pair< vertices_size_type > >
  537. values;
  538. value_type current;
  539. bool done;
  540. };
  541. } // end namespace boost
  542. #include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/rmat_graph_generator.hpp>)
  543. #endif // BOOST_GRAPH_RMAT_GENERATOR_HPP