b-tree-plus-alpha
Loading...
Searching...
No Matches
dynamic_permutation.hpp
1#pragma once
2#include "./bp_tree_template.hpp"
3
4namespace stool
5{
6 namespace bptree
7 {
14 {
15 public:
16 //using Tree = bptree::BPTree<PermutationContainer, PermutationItem, true, false, bptree::DEFAULT_MAX_DEGREE_OF_INTERNAL_NODE, bptree::DEFAULT_MAX_COUNT_OF_VALUES_IN_LEAF>;
17 using Tree = typename PermutationContainer::Tree;
18
22
23 private:
24 Tree pi_tree;
25 Tree inverse_pi_tree;
26
27
28 public:
30 {
31 this->pi_tree.set_linked_tree(&this->inverse_pi_tree);
32 this->inverse_pi_tree.set_linked_tree(&this->pi_tree);
33
34 //this->set_degree(Tree::DEFAULT_MAX_DEGREE_OF_INTERNAL_NODE);
35 }
36
38 {
39 this->clear();
40 }
41 DynamicPermutation &operator=(const DynamicPermutation &) = delete;
43 {
44 this->pi_tree = std::move(other.pi_tree);
45 this->inverse_pi_tree = std::move(other.inverse_pi_tree);
46 this->pi_tree.set_linked_tree(&this->inverse_pi_tree);
47 this->inverse_pi_tree.set_linked_tree(&this->pi_tree);
48 };
49 DynamicPermutation &operator=(DynamicPermutation &&other) noexcept
50 {
51 if (this != &other)
52 {
53
54 this->pi_tree = std::move(other.pi_tree);
55 this->inverse_pi_tree = std::move(other.inverse_pi_tree);
56 this->pi_tree.set_linked_tree(&this->inverse_pi_tree);
57 this->inverse_pi_tree.set_linked_tree(&this->pi_tree);
58
59 // other->clear();
60 }
61 return *this;
62 };
63
64 public:
65 /*
66 void set_degree(uint64_t degree)
67 {
68 this->pi_tree.initialize(degree);
69 this->inverse_pi_tree.initialize(degree);
70 }
71 */
72
73 void swap(DynamicPermutation &perm)
74 {
75 // this->pi_tree.set_linked_tree(&perm.inverse_pi_tree);
76 // perm.pi_tree.set_linked_tree(&this->inverse_pi_tree);
77
78 // this->inverse_pi_tree.set_linked_tree(&perm.pi_tree);
79 // perm.inverse_pi_tree.set_linked_tree(&this->pi_tree);
80
81 this->pi_tree.swap(perm.pi_tree, false);
82 this->inverse_pi_tree.swap(perm.inverse_pi_tree, false);
83 }
84 Tree &get_pi_tree()
85 {
86 return this->pi_tree;
87 }
88 Tree &get_inverse_pi_tree()
89 {
90 return this->inverse_pi_tree;
91 }
92 uint64_t get_max_degree() const
93 {
94 return this->pi_tree.get_max_degree_of_internal_node();
95 }
96
97 template <typename PI_ITERATOR_BEGIN, typename PI_ITERATOR_END>
98 void build(PI_ITERATOR_BEGIN beg, [[maybe_unused]] PI_ITERATOR_END end, uint64_t pi_size, int message_paragraph = stool::Message::SHOW_MESSAGE)
99 {
100
101 if (message_paragraph >= 0 && pi_size > 0)
102 {
103 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Constructing Dynamic Permutation... " << "(input size = " << pi_size << ")" << std::endl;
104 }
105 std::chrono::system_clock::time_point st1, st2;
106 st1 = std::chrono::system_clock::now();
107
108 this->clear();
109 // this->initialize(degree);
110 // this->pi_tree.initialize(degree);
111 // this->inverse_pi_tree.initialize(degree);
112 this->pi_tree.set_linked_tree(nullptr);
113 this->inverse_pi_tree.set_linked_tree(nullptr);
114
116 default_item.key = 0;
117 default_item.pointer = 0;
118 this->pi_tree.resize(pi_size, default_item);
119 this->inverse_pi_tree.resize(pi_size, default_item);
120
121 // stool::Printer::print("items", pi);
122
123 this->pi_tree.set_linked_tree(&this->inverse_pi_tree);
124 this->inverse_pi_tree.set_linked_tree(&this->pi_tree);
125
128
129 [[maybe_unused]] uint64_t i = 0;
130 for (auto it = this->pi_tree.get_postorder_iterator_begin(); it != this->pi_tree.get_postorder_iterator_end(); ++it)
131 {
134 if (message_paragraph >= 0 && message_counter > 10000)
135 {
136
137 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "Processing... [" << (processed_node_counter / 1000) << "KB] \r" << std::flush;
138 message_counter = 0;
139 }
140
141 if ((*it).is_leaf())
142 {
143 uint64_t pi_leaf_idx = (*it).get_leaf_container_index();
145 std::unordered_map<uint64_t, uint64_t> mapper;
146 for (uint64_t j = 0; j < leaf.size(); j++)
147 {
148 uint64_t idx = this->inverse_pi_tree.compute_path_from_root_to_leaf(*beg);
149 ++beg;
150 const auto &path = this->inverse_pi_tree.get_temporary_path();
151 uint64_t inv_leaf_idx = path[path.size() - 1].get_leaf_container_index();
153
154 // uint64_t x1 = std::min(pi[i] / half_degree, pi_tree_vec_size - 1);
155 auto f = mapper.find(inv_leaf_idx);
156 if (f == mapper.end())
157 {
158 mapper[inv_leaf_idx] = 0;
159 }
160 uint64_t key = mapper[inv_leaf_idx];
161 leaf.set_value(j, PermutationItem(inv_leaf_idx, key));
162 inv_leaf.set_value(idx, PermutationItem(pi_leaf_idx, key));
163
164 mapper[inv_leaf_idx] = key + 1;
165 i++;
166 }
167 }
168 }
169
170 st2 = std::chrono::system_clock::now();
171
172 if (message_paragraph >= 0 && pi_size > 0)
173 {
174 uint64_t sec_time = std::chrono::duration_cast<std::chrono::seconds>(st2 - st1).count();
175 uint64_t ms_time = std::chrono::duration_cast<std::chrono::milliseconds>(st2 - st1).count();
176 uint64_t per_time = ((double)ms_time / (double)pi_size) * 1000000;
177 std::cout << std::endl;
178
179 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "[END], the number of nodes = " << processed_node_counter << ", Elapsed Time: " << sec_time << " sec (" << per_time << " ms/MB)" << std::endl;
180 }
181 }
182
184 {
185 assert(pi_index <= (int64_t)this->pi_tree.size());
186 assert(inverse_pi_index<= (int64_t)this->inverse_pi_tree.size());
187
188 uint64_t _size1 = this->inverse_pi_tree.get_leaf_container_vector_size();
190
191 // std::vector<NodePointer>& path1 = const_cast<std::vector<NodePointer>&>(this->pi_tmp_path);
192 // std::vector<NodePointer>& path2 = const_cast<std::vector<NodePointer>&>(this->inverse_pi_tmp_path);
193
194
195 this->pi_tree.insert(pi_index, PermutationItem(_size1 + 1, UINT8_MAX), 0);
196 this->inverse_pi_tree.insert(inverse_pi_index, PermutationItem(_size2 + 1, UINT8_MAX), 0);
197
198
199
200 // std::vector<NodePointer> path1, path2;
203 const std::vector<NodePointer> &path1 = this->pi_tree.get_temporary_path();
204 const std::vector<NodePointer> &path2 = this->inverse_pi_tree.get_temporary_path();
205
206 uint64_t idx1 = path1[path1.size() - 1].get_leaf_container_index();
207 uint64_t idx2 = path2[path2.size() - 1].get_leaf_container_index();
209 PermutationContainer &cont2 = this->inverse_pi_tree.get_leaf_container(idx2);
210 uint64_t key = cont1.get_new_key(idx2);
211
212 cont1.set_value(value_idx1, PermutationItem(idx2, key));
213 cont2.set_value(value_idx2, PermutationItem(idx1, key));
214
215
216 }
217 void erase(int64_t pi_index)
218 {
220 const std::vector<NodePointer> &path = const_cast<std::vector<NodePointer> &>(this->pi_tree.get_temporary_path());
221 uint64_t inverse_pi_index = this->access(path, idx1);
222 this->pi_tree.remove_using_path(path, idx1);
223 assert(inverse_pi_index < this->inverse_pi_tree.size());
224 this->inverse_pi_tree.remove(inverse_pi_index);
225 assert(this->pi_tree.size() == this->inverse_pi_tree.size());
226 }
227 void clear()
228 {
229
230 this->pi_tree.set_linked_tree(nullptr);
231 this->inverse_pi_tree.set_linked_tree(nullptr);
232 this->pi_tree.clear();
233 this->inverse_pi_tree.clear();
234 this->pi_tree.set_linked_tree(&this->inverse_pi_tree);
235 this->inverse_pi_tree.set_linked_tree(&this->pi_tree);
236 }
237
238 void move_pi_index(int64_t from, int64_t to)
239 {
240 int64_t inverse_pi_index = this->access(from);
241 if (from < to)
242 {
243 this->insert(to + 1, inverse_pi_index);
244 this->erase(from);
245 }
246 else if (from > to)
247 {
248 this->erase(from);
249 this->insert(to, inverse_pi_index);
250 }
251 }
252 void verify() const
253 {
254 assert(this->pi_tree.get_linked_tree() == &this->inverse_pi_tree);
255 assert(this->inverse_pi_tree.get_linked_tree() == &this->pi_tree);
256 }
257 uint64_t size() const
258 {
259 return this->pi_tree.size();
260 }
261
262 int64_t access(const std::vector<NodePointer> &path, uint64_t position_to_leaf_index) const
263 {
264 const NodePointer &leaf_pointer = path[path.size() - 1];
265
266 uint64_t leaf_index = leaf_pointer.get_leaf_container_index();
269
270 const PermutationContainer &leaf2 = this->inverse_pi_tree.get_leaf_container(item.pointer);
272
273 uint64_t result = this->inverse_pi_tree.get_value_index(item.pointer, idx2);
274
275 return result;
276 }
277
278 int64_t access(int64_t pi_index) const
279 {
280
282 const std::vector<NodePointer> &path = const_cast<std::vector<NodePointer> &>(this->pi_tree.get_temporary_path());
283 return this->access(path, idx1);
284 }
285 int64_t inverse(int64_t inverse_pi_index) const
286 {
287
288 // std::vector<NodePointer> path;
290 const std::vector<NodePointer> &path = const_cast<std::vector<NodePointer> &>(this->inverse_pi_tree.get_temporary_path());
291
292 assert(path.size() > 0);
293 const NodePointer &leaf_pointer = path[path.size() - 1];
294 uint64_t leaf_index = leaf_pointer.get_leaf_container_index();
295 const PermutationContainer &leaf1 = this->inverse_pi_tree.get_leaf_container(leaf_index);
297
298 const PermutationContainer &leaf2 = this->pi_tree.get_leaf_container(item.pointer);
300
301 return this->pi_tree.get_value_index(item.pointer, idx2);
302 }
303 std::string to_string() const
304 {
305 std::stringstream ss;
306 auto vec = this->get_pi_vector();
307 ss << stool::DebugPrinter::to_integer_string(vec);
308 return ss.str();
309 }
310
311 std::vector<uint64_t> get_pi_vector() const
312 {
313 std::vector<uint64_t> r;
314 uint64_t size = this->size();
315 for (uint64_t i = 0; i < size; i++)
316 {
317 r.push_back(this->access(i));
318 }
319
320 return r;
321 }
322 std::vector<uint64_t> get_inverse_pi_vector() const
323 {
324 std::vector<uint64_t> r;
325 uint64_t size = this->size();
326 for (uint64_t i = 0; i < size; i++)
327 {
328 r.push_back(this->inverse(i));
329 }
330 return r;
331 }
332 void print(int message_paragraph = stool::Message::SHOW_MESSAGE) const
333 {
334 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "========= DP ========" << std::endl;
335 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "PI: " << std::endl;
336 auto pi_vec = this->get_pi_vector();
337 stool::DebugPrinter::print_integers(pi_vec, stool::Message::get_paragraph_string(message_paragraph) + "pi_vector");
338 this->pi_tree.print_tree();
339 this->pi_tree.print_leaves();
340 std::cout << std::endl;
341 std::cout << "Inv_PI: " << std::endl;
342 auto inv_pi_vec = this->get_inverse_pi_vector();
343 stool::DebugPrinter::print_integers(inv_pi_vec, stool::Message::get_paragraph_string(message_paragraph) +"inverse_pi_vector");
344 this->inverse_pi_tree.print_tree();
345 this->inverse_pi_tree.print_internal_nodes();
346 this->inverse_pi_tree.print_leaves();
347 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "=====================" << std::endl;
348 }
349 void print_information_about_performance(int message_paragraph = stool::Message::SHOW_MESSAGE) const{
350 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Performance Information (DynamicPermutation)[" << std::endl;
351 this->pi_tree.print_information_about_performance(message_paragraph + 1);
352 this->inverse_pi_tree.print_information_about_performance(message_paragraph + 1);
353 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "]" << std::endl;
354 }
355
356 uint64_t size_in_bytes() const
357 {
358 return this->pi_tree.size_in_bytes() + this->inverse_pi_tree.size_in_bytes();
359 }
360 std::vector<std::string> get_memory_usage_info(int message_paragraph = stool::Message::SHOW_MESSAGE) const
361 {
362 std::vector<std::string> log1 = this->pi_tree.get_memory_usage_info(message_paragraph + 1);
363 std::vector<std::string> log2 = this->inverse_pi_tree.get_memory_usage_info(message_paragraph + 1);
364
365 std::vector<std::string> r;
366 r.push_back("=Dynamic Permutation: " + std::to_string(this->size_in_bytes()) + " bytes ( " + std::to_string(this->size_in_bytes() / this->size()) + " bytes per element) = ");
367 for (std::string &s : log1)
368 {
369 r.push_back(s);
370 }
371 for (std::string &s : log2)
372 {
373 r.push_back(s);
374 }
375 r.push_back("==");
376 return r;
377 }
378 void print_memory_usage(int message_paragraph = stool::Message::SHOW_MESSAGE) const
379 {
380 std::vector<std::string> log = this->get_memory_usage_info(message_paragraph);
381 for (std::string &s : log)
382 {
383 std::cout << s << std::endl;
384 }
385 }
386
387 void sort_leaf_containers()
388 {
389 this->pi_tree.sort_leaf_containers();
390 // this->pi_tree.print_leaf_containers();
391 // this->inverse_pi_tree.print_leaves();
392 this->inverse_pi_tree.sort_leaf_containers();
393 }
394 void print_statistics(int message_paragraph = stool::Message::SHOW_MESSAGE) const
395 {
396 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Statistics(DynamicPermutation):" << std::endl;
397 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The size of permutation: " << this->size() << std::endl;
398 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "Estimated memory usage: " << this->size_in_bytes() << " bytes" << std::endl;
399 this->pi_tree.print_statistics(message_paragraph + 1);
400 this->inverse_pi_tree.print_statistics(message_paragraph + 1);
401 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "[END]" << std::endl;
402 }
403 void print_content(int message_paragraph = stool::Message::SHOW_MESSAGE) const
404 {
405 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Content(DynamicPermutation):" << std::endl;
406 auto pi_vector = this->get_pi_vector();
407 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "PI: \t" << stool::DebugPrinter::to_integer_string(pi_vector) << std::endl;
408 auto inverse_pi_vector = this->get_inverse_pi_vector();
409 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "Inverse PI: \t" << stool::DebugPrinter::to_integer_string(inverse_pi_vector) << std::endl;
410 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "[END]" << std::endl;
411 }
412
413 static void save(DynamicPermutation &dp, std::vector<uint8_t> &output, uint64_t &pos)
414 {
415 dp.pi_tree.sort_leaf_containers();
416 dp.inverse_pi_tree.sort_leaf_containers();
417 dp.pi_tree.save(output, pos);
418 dp.inverse_pi_tree.save(output, pos);
419 }
420 static void save(DynamicPermutation &dp, std::ofstream &os)
421 {
422 dp.pi_tree.save(os);
423 dp.inverse_pi_tree.save(os);
424 }
425
426 static DynamicPermutation build_from_data(const std::vector<uint8_t> &data, uint64_t &pos)
427 {
429 r.pi_tree.build_from_data(data, pos);
430 r.inverse_pi_tree.build_from_data(data, pos);
431 return r;
432 }
433
434 static DynamicPermutation build_from_data(std::ifstream &ifs)
435 {
437 r.pi_tree.build_from_data(ifs);
438 r.inverse_pi_tree.build_from_data(ifs);
439 return r;
440 }
441 };
442 }
443
444}
An implementation of B+-tree.
Definition bp_tree.hpp:24
uint64_t get_value_index(uint64_t leaf_index, uint64_t position_in_leaf_container) const
Returns the value index at position pos in the B+ tree.
Definition bp_tree.hpp:610
const LEAF_CONTAINER & get_leaf_container(uint64_t leaf_index) const
Returns the leaf container at position leaf_index.
Definition bp_tree.hpp:656
VALUE at(uint64_t pos) const
Returns the value at position pos in the B+ tree.
Definition bp_tree.hpp:574
void print_statistics(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Prints statistical information about the B+ tree.
Definition bp_tree.hpp:3037
const std::vector< NodePointer > & get_temporary_path() const
Returns the temporary path used during tree operations.
Definition bp_tree.hpp:270
int64_t compute_path_from_root_to_leaf(uint64_t i) const
Computes the path from the root to the leaf at position i.
Definition bp_tree.hpp:1207
void resize(uint64_t _size, VALUE default_value)
Resizes the B+ tree to contain a specified number of elements.
Definition bp_tree.hpp:2190
uint64_t size() const
Return the number of values stored in this tree.
Definition bp_tree.hpp:316
uint64_t get_leaf_container_vector_size() const
Return the size of the vector that stores leaf containers.
Definition bp_tree.hpp:345
PostorderIterator get_postorder_iterator_begin() const
Returns an iterator pointing to the first node in postorder traversal.
Definition bp_tree.hpp:366
void sort_leaf_containers()
Sorts the leaf containers in the B+ tree.
Definition bp_tree.hpp:2536
void push_back(VALUE value)
Pushes a single value to the B+ tree.
Definition bp_tree.hpp:1849
PostorderIterator get_postorder_iterator_end() const
Returns an iterator pointing to the end of postorder traversal.
Definition bp_tree.hpp:391
uint64_t get_max_degree_of_internal_node() const
Return the max degree of this tree. The number of children of every internal node does not exceed the...
Definition bp_tree.hpp:278
void build_from_data(const std::vector< uint8_t > &data, uint64_t &pos)
Builds a B+ tree from serialized data in a byte vector.
Definition bp_tree.hpp:2968
uint64_t size_in_bytes() const
Returns the total memory size of the B+ tree.
Definition bp_tree.hpp:931
void set_linked_tree(BPTree *_tree)
Sets the linked B+ tree.
Definition bp_tree.hpp:2243
void insert(uint64_t pos, VALUE value, uint64_t sum_delta)
Inserts a value at a specific position in the B+ tree.
Definition bp_tree.hpp:2120
std::vector< std::string > get_memory_usage_info(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Returns a vector of strings containing memory usage information about the B+ tree.
Definition bp_tree.hpp:1068
A dynamic data structure storing a permutation.
Definition dynamic_permutation.hpp:14
The forward iterator of values stored in PermutationContainer.
Definition permutation_container.hpp:30
The container stored in the BPTree of DynamicPermutation.
Definition permutation_container.hpp:14
The value stored in the BPTree of DynamicPermutation.
Definition permutation_item.hpp:15