HavoqGT
preferential_attachment.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 #include <math.h>
53 #include <stdint.h>
54 #include <assert.h>
55 #include <utility>
56 #include <boost/random.hpp>
57 
58 
59 
60 namespace havoqgt { namespace detail {
61 
62 template <typename DUMMY=uint64_t>
64 public:
65  typedef uint64_t vertex_descriptor;
66  typedef typename std::pair<uint64_t,uint64_t> edge_type;
67 
68  preferential_attachment_helper(uint64_t k, uint64_t m, double beta, uint64_t rng_seed=5489)
69  : m_rng(rng_seed)
70  {
71  m_k = k;
72  m_num_edges = m;
73  m_koffset = m_k*(m_k+1)/2;
74  m_ptr_mask = ~(std::numeric_limits<vertex_descriptor>::max() >> 1);
75  m_alpha = (beta / double(m_k) + double(1)) / (beta / double(m_k) + 2);
76  //std::cout << "beta = " << beta << ", alpha = " << m_alpha << std::endl;
77  }
78 
79  edge_type gen_edge(uint64_t _edge_index) {
80  edge_type to_return;
81  to_return.first = calc_source(_edge_index);
82  if(_edge_index >= m_koffset) {
83  //
84  // Generate random edge_list location based on beta model
85  boost::random::uniform_01<boost::random::mt19937> rand_prob(m_rng);
86  boost::random::uniform_int_distribution<uint64_t> uid(0,_edge_index-1);
87  uint64_t rand = uid(m_rng) * 2;
88  if(rand_prob() > m_alpha) {
89  ++rand;
90  }
91  if(rand % 2 == 0) { //this is a source vertex, we can calc!
92  to_return.second = calc_source(rand/2);
93  } else {
94  uint64_t edge_rand = rand/2;
95  if(edge_rand < m_koffset) { //this is an early edge we can calc!
96  to_return.second = calc_target(edge_rand);
97  } else {
98  to_return.second = make_pointer(edge_rand);
99  }
100  }
101  } else {
102  to_return.second = calc_target(_edge_index);
103  }
104  return to_return;
105  }
106 
107  uint64_t calc_source(uint64_t i) {
108  uint64_t to_return;
109  if(i+1>m_koffset) {
110  to_return = ((i-m_koffset)/m_k)+m_k+1;
111  } else {
112  to_return = (uint64_t) floor(double(-0.5f) +
113  sqrt(double(0.25f)+double(2)*double(i))+1);
114  }
115  return to_return;
116  }
117 
118 
119  uint64_t calc_target(uint64_t i) {
120  uint64_t to_return;
121  if(i+1>m_koffset) {
122  assert(false);
123  to_return = i;
124  } else {
125  double tmp = double(-0.5f) + sqrt(double(0.25f)+double(2)*double(i))+1;
126  to_return = (uint64_t) ((tmp - floor(tmp)) * floor(tmp));
127  }
128  return to_return;
129  }
130 
131  vertex_descriptor make_pointer(vertex_descriptor i) {
132  return i | m_ptr_mask;
133  }
134 
135  bool is_pointer(vertex_descriptor i) {
136  return (i & m_ptr_mask) > 0;
137  }
138 
139  //dereferences point
140  uint64_t value_of_pointer(vertex_descriptor i, uint64_t _num_partitions=1) {
141  i = i & ~m_ptr_mask;
142  uint64_t my_partition = i%_num_partitions;
143  uint64_t my_partition_offset = i/_num_partitions;
144  uint64_t edges_per_partition = m_num_edges / _num_partitions;
145  return my_partition * edges_per_partition + my_partition_offset;
146  }
147 
148 
149 private:
150  boost::random::mt19937 m_rng;
151  uint64_t m_k;
152  uint64_t m_koffset;
153  vertex_descriptor m_ptr_mask;
154  uint64_t m_num_edges;
155  double m_alpha;
156 };
157 
158 
159 }} //end namespace havoqgt::detail
vertex_descriptor make_pointer(vertex_descriptor i)
preferential_attachment_helper(uint64_t k, uint64_t m, double beta, uint64_t rng_seed=5489)
uint64_t value_of_pointer(vertex_descriptor i, uint64_t _num_partitions=1)