HavoqGT
rmat_edge_generator.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, Lawrence Livermore National Security, LLC.
3  * Produced at the Lawrence Livermore National Laboratory.
4  * Written by Roger Pearce <rpearce@llnl.gov>.
5  * LLNL-CODE-644630.
6  * All rights reserved.
7  *
8  * This file is part of HavoqGT, Version 0.1.
9  * For details, see https://computation.llnl.gov/casc/dcca-pub/dcca/Downloads.html
10  *
11  * Please also read this link – Our Notice and GNU Lesser General Public License.
12  * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
13  *
14  * This program is free software; you can redistribute it and/or modify it under
15  * the terms of the GNU Lesser General Public License (as published by the Free
16  * Software Foundation) version 2.1 dated February 1999.
17  *
18  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
19  * WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS FOR A
20  * PARTICULAR PURPOSE. See the terms and conditions of the GNU General Public
21  * License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public License along
24  * with this program; if not, write to the Free Software Foundation, Inc.,
25  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26  *
27  * OUR NOTICE AND TERMS AND CONDITIONS OF THE GNU GENERAL PUBLIC LICENSE
28  *
29  * Our Preamble Notice
30  *
31  * A. This notice is required to be provided under our contract with the
32  * U.S. Department of Energy (DOE). This work was produced at the Lawrence
33  * Livermore National Laboratory under Contract No. DE-AC52-07NA27344 with the DOE.
34  *
35  * B. Neither the United States Government nor Lawrence Livermore National
36  * Security, LLC nor any of their employees, makes any warranty, express or
37  * implied, or assumes any liability or responsibility for the accuracy,
38  * completeness, or usefulness of any information, apparatus, product, or process
39  * disclosed, or represents that its use would not infringe privately-owned rights.
40  *
41  * C. Also, reference herein to any specific commercial products, process, or
42  * services by trade name, trademark, manufacturer or otherwise does not
43  * necessarily constitute or imply its endorsement, recommendation, or favoring by
44  * the United States Government or Lawrence Livermore National Security, LLC. The
45  * views and opinions of authors expressed herein do not necessarily state or
46  * reflect those of the United States Government or Lawrence Livermore National
47  * Security, LLC, and shall not be used for advertising or product endorsement
48  * purposes.
49  *
50  */
51 
52 #ifndef HAVOQGT_RMAT_EDGE_GENERATOR_HPP_INCLUDED
53 #define HAVOQGT_RMAT_EDGE_GENERATOR_HPP_INCLUDED
54 
55 #include <boost/random.hpp>
56 #include <havoqgt/detail/hash.hpp>
57 
58 #include <utility>
59 #include <stdint.h>
60 
61 namespace havoqgt {
62 
69 
70 public:
71  typedef uint64_t vertex_descriptor;
72  typedef std::pair<uint64_t, uint64_t> edge_type;
73 
74 
77 
78  class input_iterator_type : public std::iterator<std::input_iterator_tag, edge_type, ptrdiff_t, const edge_type*, const edge_type&> {
79 
80  public:
81  input_iterator_type(rmat_edge_generator* ptr_rmat, uint64_t count)
82  : m_ptr_rmat(ptr_rmat)
83  , m_rng(ptr_rmat->m_seed)
84  , m_gen(m_rng)
85  , m_count(count)
86  , m_make_undirected(false) {
87  if(m_count == 0) {
88  get_next();
89  m_count = 0; //reset to zero
90  }
91  }
92 
93  const edge_type& operator*() const { return m_current; }
94  //const uint64_t* operator->() const { return &(operator*()); }
96  get_next();
97  return *this;
98  }
99 
101  input_iterator_type __tmp = *this;
102  get_next();
103  return __tmp;
104  }
105 
106  edge_type *operator->() {
107  return &m_current;
108  }
109 
110  bool is_equal(const input_iterator_type& _x) const {
111  return m_count == (_x.m_count);
112  }
113 
115  friend bool
117  { return x.is_equal(y); }
118 
120  friend bool
122  { return !x.is_equal(y); }
123 
124  private:
126 
127  void get_next() {
129  std::swap(m_current.first, m_current.second);
130  m_make_undirected = false;
131  } else {
133  ++m_count;
134  m_make_undirected = true;
135  }
136  assert(m_current.first <= m_ptr_rmat->max_vertex_id());
137  assert(m_current.second <= m_ptr_rmat->max_vertex_id());
138  }
139 
141  boost::mt19937 m_rng;
142  boost::uniform_01<boost::mt19937> m_gen;
143  uint64_t m_count;
144  edge_type m_current;
146  };
147 
148 
150  rmat_edge_generator(uint64_t seed, uint64_t vertex_scale,
151  uint64_t edge_count, double a, double b, double c,
152  double d, bool scramble, bool undirected)
153  : m_seed(seed)
154  , m_rng(seed)
155  , m_gen(m_rng)
156  , m_vertex_scale(vertex_scale)
157  , m_edge_count(edge_count)
158  , m_scramble(scramble)
159  , m_undirected(undirected)
160  , m_rmat_a(a)
161  , m_rmat_b(b)
162  , m_rmat_c(c)
163  , m_rmat_d(d) {
164 
165  // sanity_max_vertex_id();
166 
167  // #ifdef DEBUG
168  // auto itr1 = begin();
169  // auto itr2 = begin();
170  // while (itr1 != end()) {
171  // assert(itr2 != end());
172  // assert(*itr1 == *itr2);
173  // assert(itr1 == itr2);
174  // itr1++;
175  // itr2++;
176  // }
177  // #endif
178  }
179 
180 
183  return input_iterator_type(this, 0);
184  }
185 
188  return input_iterator_type(this, m_edge_count);
189  }
190 
192  auto itr = begin();
193  auto itr_end = end();
194 
195  uint64_t value = 0;
196  while (itr != itr_end) {
197  value = std::max(value, (*itr).first);
198  value = std::max(value, (*itr).second);
199  }
200 
201  std::cout << " value: " << value << std::endl;
202  assert(max_vertex_id() == value);
203 
204  }
205  uint64_t max_vertex_id() {
206  return (uint64_t(1) << uint64_t(m_vertex_scale)) - 1;
207  }
208 
209  size_t size() {
210  return m_edge_count;
211  }
212 
213 protected:
215  edge_type generate_edge() {
216  return generate_edge(m_gen);
217  }
218  edge_type generate_edge(boost::uniform_01<boost::mt19937> &gen) {
219  double rmat_a = m_rmat_a;
220  double rmat_b = m_rmat_b;
221  double rmat_c = m_rmat_c;
222  double rmat_d = m_rmat_d;
223  uint64_t u = 0, v = 0;
224  uint64_t step = (uint64_t(1) << m_vertex_scale)/2;
225  for (unsigned int j = 0; j < m_vertex_scale; ++j) {
226  double p = gen();
227 
228  if (p < rmat_a)
229  ;
230  else if (p >= rmat_a && p < rmat_a + rmat_b)
231  v += step;
232  else if (p >= rmat_a + rmat_b && p < rmat_a + rmat_b + rmat_c)
233  u += step;
234  else { // p > a + b + c && p < a + b + c + d
235  u += step;
236  v += step;
237  }
238 
239  step /= 2;
240 
241  // 0.2 and 0.9 are hardcoded in the reference SSCA implementation.
242  // The maximum change in any given value should be less than 10%
243  rmat_a *= 0.9 + 0.2 * gen();
244  rmat_b *= 0.9 + 0.2 * gen();
245  rmat_c *= 0.9 + 0.2 * gen();
246  rmat_d *= 0.9 + 0.2 * gen();
247 
248  double S = rmat_a + rmat_b + rmat_c + rmat_d;
249 
250  rmat_a /= S; rmat_b /= S; rmat_c /= S;
251  // d /= S;
252  // Ensure all values add up to 1, regardless of floating point errors
253  rmat_d = 1. - rmat_a - rmat_b - rmat_c;
254  }
255  if(m_scramble) {
256  u = havoqgt::detail::hash_nbits(u, m_vertex_scale);
257  v = havoqgt::detail::hash_nbits(v, m_vertex_scale);
258  }
259 
260  return std::make_pair(u, v);
261  }
262 
263 
264  const uint64_t m_seed;
265  boost::mt19937 m_rng;
266  boost::uniform_01<boost::mt19937> m_gen;
267  const uint64_t m_vertex_scale;
268  const uint64_t m_edge_count;
269  const bool m_scramble;
270  const bool m_undirected;
271  const double m_rmat_a;
272  const double m_rmat_b;
273  const double m_rmat_c;
274  const double m_rmat_d;
275 };
276 
277 } //end namespace havoqgt
278 
279 #endif //HAVOQGT_RMAT_EDGE_GENERATOR_HPP_INCLUDED
edge_type generate_edge()
Generates a new RMAT edge. This function was adapted from the Boost Graph Library.
InputIterator class for rmat_edge_generator.
std::pair< uint64_t, uint64_t > edge_type
input_iterator_type begin()
Returns the begin of the input iterator.
rmat_edge_generator(uint64_t seed, uint64_t vertex_scale, uint64_t edge_count, double a, double b, double c, double d, bool scramble, bool undirected)
seed used to be 5489
#define S(x)
Definition: error.hpp:57
uint64_t hash_nbits(uint64_t input, int n)
Definition: hash.hpp:115
friend bool operator!=(const input_iterator_type &x, const input_iterator_type &y)
Return false if x and y are both end or not end, or x and y are the same.
friend bool operator==(const input_iterator_type &x, const input_iterator_type &y)
Return true if x and y are both end or not end, or x and y are the same.
input_iterator_type(rmat_edge_generator *ptr_rmat, uint64_t count)
boost::uniform_01< boost::mt19937 > m_gen
bool is_equal(const input_iterator_type &_x) const
input_iterator_type end()
Returns the end of the input iterator.
edge_type generate_edge(boost::uniform_01< boost::mt19937 > &gen)