annotate DEPENDENCIES/generic/include/boost/graph/rmat_graph_generator.hpp @ 133:4acb5d8d80b6 tip

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