HavoqGT
upper_triangle_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 Steven Felldman
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_UPPER_TRIANGLE_EDGE_GENERATOR_INCLUDED
53 #define HAVOQGT_UPPER_TRIANGLE_EDGE_GENERATOR_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 
64  public:
65  // typedef uint64_t vertex_descriptor;
66  typedef std::pair<uint64_t, uint64_t> edge_type;
67 
68 
71 
72  class input_iterator_type : public std::iterator<std::input_iterator_tag,
73  edge_type, ptrdiff_t, const edge_type*, const edge_type&> {
74  private:
75  void get_next() {
76  if (m_count == m_num_edges) {
77  m_current = std::make_pair(0, 0);
78  assert(false);
79  return;
80  }
81 
83  std::swap(m_current.first, m_current.second);
84  m_make_undirected = false;
85  } else {
87  m_make_undirected = true;
88  ++m_count;
89  }
90  }; // get_next
91 
92  public:
93  input_iterator_type(uint64_t max_vertex, uint64_t num_edges,
94  bool undirected)
95  : m_max_vertex(max_vertex)
96  , m_num_edges(num_edges)
97  , m_undirected(undirected)
98  , m_count(num_edges) {
99  m_current = std::make_pair(0, 0);
100  }
101 
102  input_iterator_type(uint64_t max_vertex, uint64_t num_edges,
103  bool undirected, uint64_t i, uint64_t j)
104  : m_max_vertex(max_vertex)
105  , m_num_edges(num_edges)
106  , m_undirected(undirected)
107  , m_i(i)
108  , m_j(j) {
109  // Initilize the first current value
110  get_next();
111  }
112 
113  const edge_type& operator*() const { return m_current; }
114  // const uint64_t* operator->() const { return &(operator*()); }
116  get_next();
117  return *this;
118  }
119 
121  input_iterator_type __tmp = *this;
122  get_next();
123  return __tmp;
124  }
125 
126  edge_type *operator->() {
127  return &m_current;
128  }
129 
130  bool is_equal(const input_iterator_type& _x) const {
131  return m_count == (_x.m_count);
132  }
133 
134  // Return true if x and y are both end or not end, or x and y are the same.
135  friend bool
137  { return x.is_equal(y); }
138 
139  // Return false if x and y are both end or not end, or x and y are the same.
140  friend bool
142  { return !x.is_equal(y); }
143 
144  private:
146 
147  edge_type generate_edge() {
148  if (m_j < m_max_vertex) {
149  m_j++;
150  } else {
151  m_i++;
152  m_j = m_i;
153  }
154  assert(m_i <= m_max_vertex);
155  assert(m_j <= m_max_vertex);
156  return std::make_pair(m_j + 1, m_i + 1);
157  } // generate_edge
158 
159  const uint64_t m_max_vertex, m_num_edges;
160  const bool m_undirected;
161  bool m_make_undirected {false};
162  uint64_t m_count {0}, m_i, m_j;
163  edge_type m_current;
164  }; // class input_iterator_type
165 
166  uint64_t find_max_vertex(uint64_t num_edges) {
167  // (1/2)(x)(x+1) <= num_edges.
168  uint64_t x = 0, y = 0;
169  num_edges *= 2;
170  while (y < num_edges) {
171  x++;
172  y = x * (x + 1);
173  }
174 
175  uint64_t count = 0;
176  for (uint64_t i = 0; i < x; i++) {
177  for (uint64_t j = i; j < x; j++) {
178  count++;
179  }
180  }
181  assert(count * 2 >= num_edges);
182 
183  return x + 1; // +1 because we skip 0 vertex
184  };
185 
186  upper_triangle_edge_generator(uint64_t total_edges, int rank, int size,
187  bool undirected)
188  : m_total_edges(total_edges)
189  , m_undirected(undirected)
190  , m_max_vertex(find_max_vertex(total_edges)) {
191  // Determine the max_vertex id
192  m_lower_edge_id = (total_edges / size) * rank;
193  m_upper_edge_id = (total_edges / size) * (rank + 1);
194  m_upper_edge_id = std::min(total_edges, m_upper_edge_id);
195 
196  uint64_t start_count = (total_edges / size) * rank;
197 
198  uint64_t count = 0;
199  for (m_i = 0; count < start_count && m_i < m_max_vertex; m_i++) {
200  for (m_j = m_i; count < start_count && m_j < m_max_vertex; m_j++) {
201  count++;
202  }
203  }
204  sanity_check();
205  }
206 
207  void sanity_check() {
208  auto itr1 = begin();
209  auto itr2 = begin();
210  auto itr_end = end();
211  while (itr1 != itr_end) {
212  assert(itr1 == itr2);
213  assert(*itr1 == *itr2);
214  itr1++;
215  itr2++;
216  }
217 
218  }
219 
220 
223  const uint64_t num_edges = m_upper_edge_id - m_lower_edge_id;
224  return input_iterator_type(m_max_vertex, num_edges, m_undirected, m_i, m_j);
225  }
226 
229  const uint64_t num_edges = m_upper_edge_id - m_lower_edge_id;
230  return input_iterator_type(m_max_vertex, num_edges, m_undirected);
231  }
232 
233  uint64_t max_vertex_id() {
234  return m_max_vertex;
235  }
236 
237  size_t size() {
238  const uint64_t num_edges = m_upper_edge_id - m_lower_edge_id;
239  return num_edges;
240  }
241 
243  const uint64_t m_total_edges;
244  const bool m_undirected;
245 
246  const uint64_t m_max_vertex;
247  uint64_t m_i, m_j;
248 
249 };
250 
251 
252 
253 } // name space havoqgt
254 
255 #endif // HAVOQGT_UPPER_TRIANGLE_EDGE_GENERATOR_INCLUDED
256 
input_iterator_type(uint64_t max_vertex, uint64_t num_edges, bool undirected, uint64_t i, uint64_t j)
input_iterator_type begin()
Returns the begin of the input iterator.
input_iterator_type end()
Returns the end of the input iterator.
friend bool operator!=(const input_iterator_type &x, const input_iterator_type &y)
input_iterator_type(uint64_t max_vertex, uint64_t num_edges, bool undirected)
InputIterator class for upper_triangle_edge_generator.
upper_triangle_edge_generator(uint64_t total_edges, int rank, int size, bool undirected)
friend bool operator==(const input_iterator_type &x, const input_iterator_type &y)