File indexing completed on 2025-01-18 09:37:36
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GRAPH_RMAT_GENERATOR_HPP
0010 #define BOOST_GRAPH_RMAT_GENERATOR_HPP
0011
0012 #include <math.h>
0013 #include <iterator>
0014 #include <utility>
0015 #include <vector>
0016 #include <queue>
0017 #include <map>
0018 #include <boost/shared_ptr.hpp>
0019 #include <boost/assert.hpp>
0020 #include <boost/random/uniform_int.hpp>
0021 #include <boost/random/uniform_01.hpp>
0022 #include <boost/graph/graph_traits.hpp>
0023 #include <boost/graph/detail/mpi_include.hpp>
0024 #include <boost/type_traits/is_base_and_derived.hpp>
0025 #include <boost/type_traits/is_same.hpp>
0026
0027
0028 using boost::shared_ptr;
0029 using boost::uniform_01;
0030
0031
0032 template < typename IntegerType > inline int int_log2(IntegerType n)
0033 {
0034 int l = 0;
0035 while (n > 0)
0036 {
0037 ++l;
0038 n >>= 1;
0039 }
0040 return l - 1;
0041 }
0042
0043 struct keep_all_edges
0044 {
0045 template < typename T > bool operator()(const T&, const T&) { return true; }
0046 };
0047
0048 template < typename Distribution, typename ProcessId > struct keep_local_edges
0049 {
0050
0051 keep_local_edges(const Distribution& distrib, const ProcessId& id)
0052 : distrib(distrib), id(id)
0053 {
0054 }
0055
0056 template < typename T > bool operator()(const T& x, const T& y)
0057 {
0058 return distrib(x) == id || distrib(y) == id;
0059 }
0060
0061 private:
0062 const Distribution& distrib;
0063 const ProcessId& id;
0064 };
0065
0066 template < typename RandomGenerator, typename T >
0067 void generate_permutation_vector(
0068 RandomGenerator& gen, std::vector< T >& vertexPermutation, T n)
0069 {
0070 using boost::uniform_int;
0071
0072 vertexPermutation.resize(n);
0073
0074
0075 uniform_int< T > rand_vertex(0, n - 1);
0076 for (T i = 0; i < n; ++i)
0077 vertexPermutation[i] = i;
0078
0079
0080
0081 for (T i = 0; i < n; ++i)
0082 std::swap(vertexPermutation[i], vertexPermutation[rand_vertex(gen)]);
0083 }
0084
0085 template < typename RandomGenerator, typename T >
0086 std::pair< T, T > generate_edge(
0087 shared_ptr< uniform_01< RandomGenerator > > prob, T n, unsigned int SCALE,
0088 double a, double b, double c, double d)
0089 {
0090 T u = 0, v = 0;
0091 T step = n / 2;
0092 for (unsigned int j = 0; j < SCALE; ++j)
0093 {
0094 double p = (*prob)();
0095
0096 if (p < a)
0097 ;
0098 else if (p >= a && p < a + b)
0099 v += step;
0100 else if (p >= a + b && p < a + b + c)
0101 u += step;
0102 else
0103 {
0104 u += step;
0105 v += step;
0106 }
0107
0108 step /= 2;
0109
0110
0111
0112 a *= 0.9 + 0.2 * (*prob)();
0113 b *= 0.9 + 0.2 * (*prob)();
0114 c *= 0.9 + 0.2 * (*prob)();
0115 d *= 0.9 + 0.2 * (*prob)();
0116
0117 double S = a + b + c + d;
0118
0119 a /= S;
0120 b /= S;
0121 c /= S;
0122
0123
0124 d = 1. - a - b - c;
0125 }
0126
0127 return std::make_pair(u, v);
0128 }
0129
0130 namespace boost
0131 {
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143 template < typename RandomGenerator, typename Graph > class rmat_iterator
0144 {
0145 typedef typename graph_traits< Graph >::directed_category directed_category;
0146 typedef
0147 typename graph_traits< Graph >::vertices_size_type vertices_size_type;
0148 typedef typename graph_traits< Graph >::edges_size_type edges_size_type;
0149
0150 public:
0151 typedef std::input_iterator_tag iterator_category;
0152 typedef std::pair< vertices_size_type, vertices_size_type > value_type;
0153 typedef const value_type& reference;
0154 typedef const value_type* pointer;
0155 typedef std::ptrdiff_t difference_type;
0156
0157
0158 rmat_iterator() : gen(), edge(0) {}
0159
0160
0161 rmat_iterator(RandomGenerator& gen, vertices_size_type n, edges_size_type m,
0162 double a, double b, double c, double d, bool permute_vertices = true)
0163 : gen()
0164 , n(n)
0165 , a(a)
0166 , b(b)
0167 , c(c)
0168 , d(d)
0169 , edge(m)
0170 , permute_vertices(permute_vertices)
0171 , SCALE(int_log2(n))
0172
0173 {
0174 this->gen.reset(new uniform_01< RandomGenerator >(gen));
0175
0176
0177
0178
0179 if (permute_vertices)
0180 generate_permutation_vector(gen, vertexPermutation, n);
0181
0182
0183
0184
0185
0186 vertices_size_type u, v;
0187 boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d);
0188
0189 if (permute_vertices)
0190 current
0191 = std::make_pair(vertexPermutation[u], vertexPermutation[v]);
0192 else
0193 current = std::make_pair(u, v);
0194
0195 --edge;
0196 }
0197
0198 reference operator*() const { return current; }
0199 pointer operator->() const { return ¤t; }
0200
0201 rmat_iterator& operator++()
0202 {
0203 vertices_size_type u, v;
0204 boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d);
0205
0206 if (permute_vertices)
0207 current
0208 = std::make_pair(vertexPermutation[u], vertexPermutation[v]);
0209 else
0210 current = std::make_pair(u, v);
0211
0212 --edge;
0213
0214 return *this;
0215 }
0216
0217 rmat_iterator operator++(int)
0218 {
0219 rmat_iterator temp(*this);
0220 ++(*this);
0221 return temp;
0222 }
0223
0224 bool operator==(const rmat_iterator& other) const
0225 {
0226 return edge == other.edge;
0227 }
0228
0229 bool operator!=(const rmat_iterator& other) const
0230 {
0231 return !(*this == other);
0232 }
0233
0234 private:
0235
0236 shared_ptr< uniform_01< RandomGenerator > > gen;
0237 vertices_size_type n;
0238 double a, b, c, d;
0239 int edge;
0240 bool permute_vertices;
0241 int SCALE;
0242
0243
0244 std::vector< vertices_size_type > vertexPermutation;
0245 value_type current;
0246 };
0247
0248
0249 template < typename T > struct sort_pair
0250 {
0251 bool operator()(const std::pair< T, T >& x, const std::pair< T, T >& y)
0252 {
0253 if (x.first == y.first)
0254 return x.second > y.second;
0255 else
0256 return x.first > y.first;
0257 }
0258 };
0259
0260 template < typename RandomGenerator, typename Graph,
0261 typename EdgePredicate = keep_all_edges >
0262 class sorted_rmat_iterator
0263 {
0264 typedef typename graph_traits< Graph >::directed_category directed_category;
0265 typedef
0266 typename graph_traits< Graph >::vertices_size_type vertices_size_type;
0267 typedef typename graph_traits< Graph >::edges_size_type edges_size_type;
0268
0269 public:
0270 typedef std::input_iterator_tag iterator_category;
0271 typedef std::pair< vertices_size_type, vertices_size_type > value_type;
0272 typedef const value_type& reference;
0273 typedef const value_type* pointer;
0274 typedef std::ptrdiff_t difference_type;
0275
0276
0277 sorted_rmat_iterator()
0278 : gen(), values(sort_pair< vertices_size_type >()), done(true)
0279 {
0280 }
0281
0282
0283 sorted_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
0284 edges_size_type m, double a, double b, double c, double d,
0285 bool permute_vertices = true, EdgePredicate ep = keep_all_edges())
0286 : gen()
0287 , permute_vertices(permute_vertices)
0288 , values(sort_pair< vertices_size_type >())
0289 , done(false)
0290
0291 {
0292
0293
0294
0295 this->gen.reset(new uniform_01< RandomGenerator >(gen));
0296
0297 std::vector< vertices_size_type > vertexPermutation;
0298 if (permute_vertices)
0299 generate_permutation_vector(gen, vertexPermutation, n);
0300
0301
0302 int SCALE = int_log2(n);
0303
0304 for (edges_size_type i = 0; i < m; ++i)
0305 {
0306
0307 vertices_size_type u, v;
0308 boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d);
0309
0310 if (permute_vertices)
0311 {
0312 if (ep(vertexPermutation[u], vertexPermutation[v]))
0313 values.push(std::make_pair(
0314 vertexPermutation[u], vertexPermutation[v]));
0315 }
0316 else
0317 {
0318 if (ep(u, v))
0319 values.push(std::make_pair(u, v));
0320 }
0321 }
0322
0323 current = values.top();
0324 values.pop();
0325 }
0326
0327 reference operator*() const { return current; }
0328 pointer operator->() const { return ¤t; }
0329
0330 sorted_rmat_iterator& operator++()
0331 {
0332 if (!values.empty())
0333 {
0334 current = values.top();
0335 values.pop();
0336 }
0337 else
0338 done = true;
0339
0340 return *this;
0341 }
0342
0343 sorted_rmat_iterator operator++(int)
0344 {
0345 sorted_rmat_iterator temp(*this);
0346 ++(*this);
0347 return temp;
0348 }
0349
0350 bool operator==(const sorted_rmat_iterator& other) const
0351 {
0352 return values.empty() && other.values.empty() && done && other.done;
0353 }
0354
0355 bool operator!=(const sorted_rmat_iterator& other) const
0356 {
0357 return !(*this == other);
0358 }
0359
0360 private:
0361
0362 shared_ptr< uniform_01< RandomGenerator > > gen;
0363 bool permute_vertices;
0364
0365
0366 std::priority_queue< value_type, std::vector< value_type >,
0367 sort_pair< vertices_size_type > >
0368 values;
0369 value_type current;
0370 bool done;
0371 };
0372
0373
0374 template < typename RandomGenerator, typename Graph,
0375 typename EdgePredicate = keep_all_edges >
0376 class unique_rmat_iterator
0377 {
0378 typedef typename graph_traits< Graph >::directed_category directed_category;
0379 typedef
0380 typename graph_traits< Graph >::vertices_size_type vertices_size_type;
0381 typedef typename graph_traits< Graph >::edges_size_type edges_size_type;
0382
0383 public:
0384 typedef std::input_iterator_tag iterator_category;
0385 typedef std::pair< vertices_size_type, vertices_size_type > value_type;
0386 typedef const value_type& reference;
0387 typedef const value_type* pointer;
0388 typedef std::ptrdiff_t difference_type;
0389
0390
0391 unique_rmat_iterator() : gen(), done(true) {}
0392
0393
0394 unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
0395 edges_size_type m, double a, double b, double c, double d,
0396 bool permute_vertices = true, EdgePredicate ep = keep_all_edges())
0397 : gen(), done(false)
0398
0399 {
0400
0401
0402
0403 this->gen.reset(new uniform_01< RandomGenerator >(gen));
0404
0405 std::vector< vertices_size_type > vertexPermutation;
0406 if (permute_vertices)
0407 generate_permutation_vector(gen, vertexPermutation, n);
0408
0409 int SCALE = int_log2(n);
0410
0411 std::map< value_type, bool > edge_map;
0412
0413 edges_size_type edges = 0;
0414 do
0415 {
0416 vertices_size_type u, v;
0417 boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d);
0418
0419
0420
0421
0422 if (u > v && is_same< directed_category, undirected_tag >::value)
0423 std::swap(u, v);
0424
0425 if (edge_map.find(std::make_pair(u, v)) == edge_map.end())
0426 {
0427 edge_map[std::make_pair(u, v)] = true;
0428
0429 if (permute_vertices)
0430 {
0431 if (ep(vertexPermutation[u], vertexPermutation[v]))
0432 values.push_back(std::make_pair(
0433 vertexPermutation[u], vertexPermutation[v]));
0434 }
0435 else
0436 {
0437 if (ep(u, v))
0438 values.push_back(std::make_pair(u, v));
0439 }
0440
0441 edges++;
0442 }
0443 } while (edges < m);
0444
0445
0446
0447
0448 current = values.back();
0449 values.pop_back();
0450 }
0451
0452 reference operator*() const { return current; }
0453 pointer operator->() const { return ¤t; }
0454
0455 unique_rmat_iterator& operator++()
0456 {
0457 if (!values.empty())
0458 {
0459 current = values.back();
0460 values.pop_back();
0461 }
0462 else
0463 done = true;
0464
0465 return *this;
0466 }
0467
0468 unique_rmat_iterator operator++(int)
0469 {
0470 unique_rmat_iterator temp(*this);
0471 ++(*this);
0472 return temp;
0473 }
0474
0475 bool operator==(const unique_rmat_iterator& other) const
0476 {
0477 return values.empty() && other.values.empty() && done && other.done;
0478 }
0479
0480 bool operator!=(const unique_rmat_iterator& other) const
0481 {
0482 return !(*this == other);
0483 }
0484
0485 private:
0486
0487 shared_ptr< uniform_01< RandomGenerator > > gen;
0488
0489
0490 std::vector< value_type > values;
0491 value_type current;
0492 bool done;
0493 };
0494
0495
0496 template < typename RandomGenerator, typename Graph,
0497 typename EdgePredicate = keep_all_edges >
0498 class sorted_unique_rmat_iterator
0499 {
0500 typedef typename graph_traits< Graph >::directed_category directed_category;
0501 typedef
0502 typename graph_traits< Graph >::vertices_size_type vertices_size_type;
0503 typedef typename graph_traits< Graph >::edges_size_type edges_size_type;
0504
0505 public:
0506 typedef std::input_iterator_tag iterator_category;
0507 typedef std::pair< vertices_size_type, vertices_size_type > value_type;
0508 typedef const value_type& reference;
0509 typedef const value_type* pointer;
0510 typedef std::ptrdiff_t difference_type;
0511
0512
0513 sorted_unique_rmat_iterator()
0514 : gen(), values(sort_pair< vertices_size_type >()), done(true)
0515 {
0516 }
0517
0518
0519 sorted_unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n,
0520 edges_size_type m, double a, double b, double c, double d,
0521 bool bidirectional = false, bool permute_vertices = true,
0522 EdgePredicate ep = keep_all_edges())
0523 : gen()
0524 , bidirectional(bidirectional)
0525 , values(sort_pair< vertices_size_type >())
0526 , done(false)
0527
0528 {
0529
0530
0531
0532 this->gen.reset(new uniform_01< RandomGenerator >(gen));
0533
0534 std::vector< vertices_size_type > vertexPermutation;
0535 if (permute_vertices)
0536 generate_permutation_vector(gen, vertexPermutation, n);
0537
0538 int SCALE = int_log2(n);
0539
0540 std::map< value_type, bool > edge_map;
0541
0542 edges_size_type edges = 0;
0543 do
0544 {
0545
0546 vertices_size_type u, v;
0547 boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d);
0548
0549 if (bidirectional)
0550 {
0551 if (edge_map.find(std::make_pair(u, v)) == edge_map.end())
0552 {
0553 edge_map[std::make_pair(u, v)] = true;
0554 edge_map[std::make_pair(v, u)] = true;
0555
0556 if (ep(u, v))
0557 {
0558 if (permute_vertices)
0559 {
0560 values.push(std::make_pair(
0561 vertexPermutation[u], vertexPermutation[v]));
0562 values.push(std::make_pair(
0563 vertexPermutation[v], vertexPermutation[u]));
0564 }
0565 else
0566 {
0567 values.push(std::make_pair(u, v));
0568 values.push(std::make_pair(v, u));
0569 }
0570 }
0571
0572 ++edges;
0573 }
0574 }
0575 else
0576 {
0577
0578
0579
0580 if (u > v
0581 && is_same< directed_category, undirected_tag >::value)
0582 std::swap(u, v);
0583
0584 if (edge_map.find(std::make_pair(u, v)) == edge_map.end())
0585 {
0586 edge_map[std::make_pair(u, v)] = true;
0587
0588 if (permute_vertices)
0589 {
0590 if (ep(vertexPermutation[u], vertexPermutation[v]))
0591 values.push(std::make_pair(
0592 vertexPermutation[u], vertexPermutation[v]));
0593 }
0594 else
0595 {
0596 if (ep(u, v))
0597 values.push(std::make_pair(u, v));
0598 }
0599
0600 ++edges;
0601 }
0602 }
0603
0604 } while (edges < m);
0605
0606
0607
0608
0609 current = values.top();
0610 values.pop();
0611 }
0612
0613 reference operator*() const { return current; }
0614 pointer operator->() const { return ¤t; }
0615
0616 sorted_unique_rmat_iterator& operator++()
0617 {
0618 if (!values.empty())
0619 {
0620 current = values.top();
0621 values.pop();
0622 }
0623 else
0624 done = true;
0625
0626 return *this;
0627 }
0628
0629 sorted_unique_rmat_iterator operator++(int)
0630 {
0631 sorted_unique_rmat_iterator temp(*this);
0632 ++(*this);
0633 return temp;
0634 }
0635
0636 bool operator==(const sorted_unique_rmat_iterator& other) const
0637 {
0638 return values.empty() && other.values.empty() && done && other.done;
0639 }
0640
0641 bool operator!=(const sorted_unique_rmat_iterator& other) const
0642 {
0643 return !(*this == other);
0644 }
0645
0646 private:
0647
0648 shared_ptr< uniform_01< RandomGenerator > > gen;
0649 bool bidirectional;
0650
0651
0652 std::priority_queue< value_type, std::vector< value_type >,
0653 sort_pair< vertices_size_type > >
0654 values;
0655 value_type current;
0656 bool done;
0657 };
0658
0659 }
0660
0661 #include BOOST_GRAPH_MPI_INCLUDE( <boost/graph/distributed/rmat_graph_generator.hpp >)
0662
0663 #endif