A platform for high-performance distributed tool and library development written in C++. It can be deployed in two different cluster modes: standalone or distributed. API for v0.5.0, released on June 13, 2018.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
TopKQueue.cc
Go to the documentation of this file.
1 /*****************************************************************************
2  * *
3  * Copyright 2018 Rice University *
4  * *
5  * Licensed under the Apache License, Version 2.0 (the "License"); *
6  * you may not use this file except in compliance with the License. *
7  * You may obtain a copy of the License at *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
14  * See the License for the specific language governing permissions and *
15  * limitations under the License. *
16  * *
17  *****************************************************************************/
18 #ifndef TOP_K_QUEUE_CC
19 #define TOP_K_QUEUE_CC
20 
21 #include "TopKQueue.h"
22 
23 namespace pdb {
24 
25 template <class Score, class ValueType>
27 
28  // set up the type info
29  scoreTypeInfo.setup<Score>();
30  valueTypeInfo.setup<ValueType>();
31 
32  // set up the size info
33  mySize = sizeof(TopKQueue<Score, ValueType>);
34  valueOffset = ((char*)&tempValue) - ((char*)this);
35 
36  // and set up k
37  k = kIn;
38 }
39 
40 template <class Score, class ValueType>
42 
43  // set up the type info
44  scoreTypeInfo.setup<Score>();
45  valueTypeInfo.setup<ValueType>();
46 
47  // set up the size info
48  mySize = sizeof(TopKQueue<Score, ValueType>);
49  valueOffset = ((char*)&tempValue) - ((char*)this);
50 }
51 
52 template <class Score, class ValueType>
53 TopKQueue<Score, ValueType>::TopKQueue(unsigned kIn, Score initScore, ValueType initValue) {
54 
55  // set up the type info
56  scoreTypeInfo.setup<Score>();
57  valueTypeInfo.setup<ValueType>();
58 
59  // set up the size info
60  mySize = sizeof(TopKQueue<Score, ValueType>);
61  valueOffset = ((char*)&tempValue) - ((char*)this);
62 
63  // we are not empty
64  empty = false;
65 
66  // remember the initial score and value
67  tempScore = initScore;
68  tempValue = initValue;
69 
70  // and remember the limit
71  k = kIn;
72 }
73 
74 template <class Score, class ValueType>
75 void TopKQueue<Score, ValueType>::setUpAndCopyFrom(void* target, void* source) const {
76 
77  // get pointers to the object to copy
80 
81  // set up the nullptrs for the handles in the destination
82  to->allScores.setOffset(-1);
83  to->allValues.setOffset(-1);
84 
85  // copy the key
86  to->myKey = from->myKey;
87 
88  // set up the type info
89  to->scoreTypeInfo = from->scoreTypeInfo;
90  to->valueTypeInfo = from->valueTypeInfo;
91 
92  // and remember the meta-data
93  to->empty = from->empty;
94  to->mySize = from->mySize;
95  to->valueOffset = from->valueOffset;
96  to->k = from->k;
97 
98  // zero out the score and copy him over
99  if (!to->scoreTypeInfo.descendsFromObject()) {
100  memmove((void*)&(to->tempScore),
101  (void*)&(from->tempScore),
103  } else {
105  }
106 
107  // zero out the score and copy him over
108  if (!to->valueTypeInfo.descendsFromObject()) {
109  memmove(from->valueOffset + (char*)to,
110  from->valueOffset + (char*)from,
112  } else {
114  from->valueOffset + (char*)from);
115  }
116 
117  // copy over the arrays of scores and values
118  to->allScores = from->allScores;
119  to->allValues = from->allValues;
120 }
121 
122 template <class Score, class ValueType>
128  foo->valueTypeInfo.deleteConstituentObject(foo->valueOffset + (char*)foo);
129  foo->allScores = nullptr;
130  foo->allValues = nullptr;
131 }
132 
133 template <class Score, class ValueType>
136  return target.mySize;
137 }
138 
139 template <class Score, class ValueType>
141 
142  Score* scores = allScores->c_ptr();
143  ValueType* values = allValues->c_ptr();
144  tempScore = scores[i];
145  tempValue = values[i];
146  scores[i] = scores[j];
147  values[i] = values[j];
148  scores[j] = tempScore;
149  values[j] = tempValue;
150 }
151 
152 template <class Score, class ValueType>
153 void TopKQueue<Score, ValueType>::insert(Score& score, ValueType& value) {
154  // std :: cout << "incoming score=" << score << std :: endl;
155  // for an empty heap, just insert
156  if (empty) {
157  tempScore = score;
158  tempValue = value;
159  empty = false;
160  return;
161  } else if (allScores == nullptr) {
162  allScores = makeObject<Vector<Score>>();
163  allValues = makeObject<Vector<ValueType>>();
164  allScores->push_back(tempScore);
165  allValues->push_back(tempValue);
166  }
167 
168  // don't do anything if the new guy is not good enough
169  if (score < (*allScores)[0] && allScores->size() >= k)
170  return;
171 
172  // insert the new guy at the bottom level of the heap
173 
174  allScores->push_back(score);
175  allValues->push_back(value);
176 
177  // now, swap until we have a heap
178  Score* scores = allScores->c_ptr();
179  ValueType* values = allValues->c_ptr();
180  // std :: cout << "score=" << score << " inserted" << std :: endl;
181  int current = allScores->size() - 1;
182  while (current > 0 && scores[current] < scores[(current - 1) / 2]) {
183  // JiaNote: below is the original code
184  // swap (current, current / 2);
185  // JiaNote: below is the fixed code
186  swap(current, (current - 1) / 2);
187  current = (current - 1) / 2;
188  }
189 
190  // if we can fit everyone, then just exit
191  if (allScores->size() <= k)
192  return;
193 
194  // we cannot fit everyone, so we need to remove the worst one
195  // put the last one at the first position
196  /*for (int i = 0; i < allScores->size(); i++) {
197  std :: cout << "score[" << i << "]=" << scores[i] << std :: endl;
198  }*/
199  // std :: cout << "score=" << scores [0] << " removed" << std :: endl;
200  scores[0] = scores[allScores->size() - 1];
201  values[0] = values[allScores->size() - 1];
202  allScores->pop_back();
203  allValues->pop_back();
204 
205  // now, swap until we again have a heap
206  current = 0;
207  int limit = allScores->size();
208  while (true) {
209 
210  if (current * 2 + 2 < limit) {
211 
212  // figure out the smaller child
213  int smallPos;
214  if (scores[current * 2 + 1] < scores[current * 2 + 2]) {
215  smallPos = current * 2 + 1;
216  } else {
217  smallPos = current * 2 + 2;
218  }
219 
220  // see if we are larger than the smaller child
221  if (scores[smallPos] < scores[current]) {
222  swap(smallPos, current);
223  current = smallPos;
224  } else {
225  break;
226  }
227 
228  } else if (current * 2 + 1 < limit) {
229  int smallPos = current * 2 + 1;
230 
231  // see if we are larger than the smaller child
232  if (scores[smallPos] < scores[current]) {
233  swap(smallPos, current);
234  current = smallPos;
235  } else {
236  break;
237  }
238  } else {
239  break;
240  }
241  }
242 }
243 
244 template <class Score, class ValueType>
246  return myKey;
247 }
248 
249 template <class Score, class ValueType>
251  return *this;
252 }
253 
254 template <class Score, class ValueType>
256  TopKQueue<Score, ValueType>& addMeIn) {
257 
258  // if the guy we are adding is empty, do nothing
259  if (addMeIn.empty) {
260  return *this;
261  }
262 
263  // in the case where the other guy is not a list, just add his singleton
264  if (addMeIn.allScores == nullptr) {
265  insert(addMeIn.tempScore, addMeIn.tempValue);
266  return *this;
267  }
268 
269  // in this case, just add in the other guy
270  int len = addMeIn.allScores->size();
271  Score* scores = addMeIn.allScores->c_ptr();
272  ValueType* values = addMeIn.allValues->c_ptr();
273  for (int i = 0; i < len; i++) {
274  try {
275  insert(scores[i], values[i]);
276  } catch (NotEnoughSpace& n) {
277  std::cout << "Not enough space when trying to insert the " << i << "-th score"
278  << std::endl;
279  throw n;
280  }
281  }
282 
283  return *this;
284 }
285 
286 template <class Score, class ValueType>
288  return allValues->size();
289 }
290 
291 template <class Score, class ValueType>
293  if (empty) {
294  std::cout << "You tried to extract a value from an empty queue!\n";
295  exit(1);
296  }
297 
298  if (allValues == nullptr && i == 0) {
299  ScoreValuePair<Score, ValueType> temp(tempScore, tempValue);
300  return temp;
301  }
302 
303  if (allValues == nullptr) {
304  std::cout << "You tried to extract a value from past the end of the queue!\n";
305  exit(1);
306  }
307 
308  if (i < allValues->size()) {
309  ScoreValuePair<Score, ValueType> temp((*allScores)[i], (*allValues)[i]);
310  return temp;
311  }
312 
313  std::cout << "You tried to extract a value from past the end of the queue!\n";
314  exit(1);
315 }
316 }
317 
318 #endif
ValueType tempValue
Definition: TopKQueue.h:64
size_t getSizeOfConstituentObject(void *forMe) const
void deleteConstituentObject(void *deleteMe) const
ScoreValuePair< Score, ValueType > operator[](unsigned i)
Definition: TopKQueue.cc:292
void setUpAndCopyFrom(void *target, void *source) const
Definition: TopKQueue.cc:75
void setUpAndCopyFromConstituentObject(void *target, void *source) const
Score tempScore
Definition: TopKQueue.h:63
TopKQueue< Score, ValueType > & operator+(TopKQueue< Score, ValueType > &addMeIn)
Definition: TopKQueue.cc:255
void deleteObject(void *deleteMe)
Definition: TopKQueue.cc:123
void insert(Score &score, ValueType &value)
Definition: TopKQueue.cc:153
Handle< Vector< ValueType > > allValues
Definition: TopKQueue.h:51
void swap(int i, int j)
Definition: TopKQueue.cc:140
unsigned valueOffset
Definition: TopKQueue.h:57
PDBTemplateBase scoreTypeInfo
Definition: TopKQueue.h:46
Handle< Vector< Score > > allScores
Definition: TopKQueue.h:50
size_t getSize(void *forMe)
Definition: TopKQueue.cc:134
int & getKey()
Definition: TopKQueue.cc:245
PDBTemplateBase valueTypeInfo
Definition: TopKQueue.h:47
bool descendsFromObject() const
TopKQueue< Score, ValueType > & getValue()
Definition: TopKQueue.cc:250
unsigned k
Definition: TopKQueue.h:60
unsigned mySize
Definition: TopKQueue.h:54
unsigned size()
Definition: TopKQueue.cc:287