b-tree-plus-alpha
Loading...
Searching...
No Matches
dynamic_permutation.hpp
1#pragma once
2#include "./permutation/bp_tree_template.hpp"
3
4namespace stool
5{
6 namespace bptree
7 {
14 {
15 public:
16 using Tree = typename PermutationContainer::Tree;
17
21
22 private:
23 Tree pi_tree;
24 Tree inverse_pi_tree;
25
26 public:
30
31
36 {
37 this->set_linked_tree();
38 }
39
44 {
45 this->pi_tree = std::move(other.pi_tree);
46 this->inverse_pi_tree = std::move(other.inverse_pi_tree);
47 this->set_linked_tree();
48 };
53 {
54 this->clear();
55 }
56
58
62
63
71 {
72 if (this != &other)
73 {
74
75 this->pi_tree = std::move(other.pi_tree);
76 this->inverse_pi_tree = std::move(other.inverse_pi_tree);
77 this->pi_tree.set_linked_tree(&this->inverse_pi_tree);
78 this->inverse_pi_tree.set_linked_tree(&this->pi_tree);
79
80 // other->clear();
81 }
82 return *this;
83 };
84
86
90
91
95 {
96 return this->pi_tree;
97 }
102 {
103 return this->inverse_pi_tree;
104 }
108 uint64_t get_max_degree() const
109 {
110 return this->pi_tree.get_max_degree_of_internal_node();
111 }
115 uint64_t size() const
116 {
117 return this->pi_tree.size();
118 }
122 uint64_t size_in_bytes() const
123 {
124 return this->pi_tree.size_in_bytes() + this->inverse_pi_tree.size_in_bytes();
125 }
126
128
132
133
138 int64_t access(int64_t i) const
139 {
140
141 uint64_t idx1 = this->pi_tree.compute_path_from_root_to_leaf(i);
142 const std::vector<NodePointer> &path = const_cast<std::vector<NodePointer> &>(this->pi_tree.get_temporary_path());
143 return this->access(path, idx1);
144 }
149 int64_t inverse(int64_t i) const
150 {
151
152 // std::vector<NodePointer> path;
153 uint64_t idx1 = this->inverse_pi_tree.compute_path_from_root_to_leaf(i);
154 const std::vector<NodePointer> &path = const_cast<std::vector<NodePointer> &>(this->inverse_pi_tree.get_temporary_path());
155
156 assert(path.size() > 0);
157 const NodePointer &leaf_pointer = path[path.size() - 1];
158 uint64_t leaf_index = leaf_pointer.get_leaf_container_index();
159 const PermutationContainer &leaf1 = this->inverse_pi_tree.get_leaf_container(leaf_index);
160 PermutationItem item = leaf1.at(idx1);
161
162 const PermutationContainer &leaf2 = this->pi_tree.get_leaf_container(item.pointer);
163 uint64_t idx2 = leaf2.get_index(PermutationItem(leaf_index, item.key));
164
165 return this->pi_tree.get_value_index(item.pointer, idx2);
166 }
168
172
173
177 std::string to_string() const
178 {
179 std::stringstream ss;
180 auto vec = this->to_pi_vector();
181 ss << stool::ConverterToString::to_integer_string(vec);
182 return ss.str();
183 }
184
188 std::vector<uint64_t> to_pi_vector() const
189 {
190 std::vector<uint64_t> r;
191 uint64_t size = this->size();
192 for (uint64_t i = 0; i < size; i++)
193 {
194 r.push_back(this->access(i));
195 }
196
197 return r;
198 }
202 std::vector<uint64_t> to_inverse_pi_vector() const
203 {
204 std::vector<uint64_t> r;
205 uint64_t size = this->size();
206 for (uint64_t i = 0; i < size; i++)
207 {
208 r.push_back(this->inverse(i));
209 }
210 return r;
211 }
213
217
218
221 void clear()
222 {
223
224 this->pi_tree.set_linked_tree(nullptr);
225 this->inverse_pi_tree.set_linked_tree(nullptr);
226 this->pi_tree.clear();
227 this->inverse_pi_tree.clear();
228 this->pi_tree.set_linked_tree(&this->inverse_pi_tree);
229 this->inverse_pi_tree.set_linked_tree(&this->pi_tree);
230 }
235 {
236 this->pi_tree.swap(item.pi_tree, false);
237 this->inverse_pi_tree.swap(item.inverse_pi_tree, false);
238 }
239
244 void insert(int64_t pi_index_p, int64_t inverse_pi_index_q)
245 {
246 assert(pi_index_p <= (int64_t)this->pi_tree.size());
247 assert(inverse_pi_index_q <= (int64_t)this->inverse_pi_tree.size());
248
249 uint64_t _size1 = this->inverse_pi_tree.get_leaf_container_vector_size();
250 uint64_t _size2 = this->pi_tree.get_leaf_container_vector_size();
251
252 this->pi_tree.insert(pi_index_p, PermutationItem(_size1 + 1, UINT8_MAX), 0);
253 this->inverse_pi_tree.insert(inverse_pi_index_q, PermutationItem(_size2 + 1, UINT8_MAX), 0);
254
255 // std::vector<NodePointer> path1, path2;
256 uint64_t value_idx1 = this->pi_tree.compute_path_from_root_to_leaf(pi_index_p);
257 uint64_t value_idx2 = this->inverse_pi_tree.compute_path_from_root_to_leaf(inverse_pi_index_q);
258 const std::vector<NodePointer> &path1 = this->pi_tree.get_temporary_path();
259 const std::vector<NodePointer> &path2 = this->inverse_pi_tree.get_temporary_path();
260
261 uint64_t idx1 = path1[path1.size() - 1].get_leaf_container_index();
262 uint64_t idx2 = path2[path2.size() - 1].get_leaf_container_index();
263 PermutationContainer &cont1 = this->pi_tree.get_leaf_container(idx1);
264 PermutationContainer &cont2 = this->inverse_pi_tree.get_leaf_container(idx2);
265 uint64_t key = cont1.get_new_key(idx2);
266
267 cont1.set_value(value_idx1, PermutationItem(idx2, key));
268 cont2.set_value(value_idx2, PermutationItem(idx1, key));
269 }
274 void erase(int64_t pi_index_p)
275 {
276 uint64_t idx1 = this->pi_tree.compute_path_from_root_to_leaf(pi_index_p);
277 const std::vector<NodePointer> &path = const_cast<std::vector<NodePointer> &>(this->pi_tree.get_temporary_path());
278 uint64_t inverse_pi_index_q = this->access(path, idx1);
279 this->pi_tree.remove_using_path(path, idx1);
280 assert(inverse_pi_index_q < this->inverse_pi_tree.size());
281 this->inverse_pi_tree.remove(inverse_pi_index_q);
282 assert(this->pi_tree.size() == this->inverse_pi_tree.size());
283 }
284
289 void move_pi_index(int64_t from_p, int64_t to_x)
290 {
291 int64_t inverse_pi_index_q = this->access(from_p);
292 if (from_p < to_x)
293 {
294 this->insert(to_x + 1, inverse_pi_index_q);
295 this->erase(from_p);
296 }
297 else if (from_p > to_x)
298 {
299 this->erase(from_p);
300 this->insert(to_x, inverse_pi_index_q);
301 }
302 }
308 {
309 this->pi_tree.sort_leaf_containers();
310 this->inverse_pi_tree.sort_leaf_containers();
311 }
312
318 template <typename PI_ITERATOR_BEGIN, typename PI_ITERATOR_END>
319 void build(PI_ITERATOR_BEGIN beg, [[maybe_unused]] PI_ITERATOR_END end, uint64_t pi_size, int message_paragraph = stool::Message::SHOW_MESSAGE)
320 {
321
322 if (message_paragraph >= 0 && pi_size > 0)
323 {
324 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Constructing Dynamic Permutation... " << "(input size = " << pi_size << ")" << std::endl;
325 }
326 std::chrono::system_clock::time_point st1, st2;
327 st1 = std::chrono::system_clock::now();
328
329 this->clear();
330 // this->initialize(degree);
331 // this->pi_tree.initialize(degree);
332 // this->inverse_pi_tree.initialize(degree);
333 this->pi_tree.set_linked_tree(nullptr);
334 this->inverse_pi_tree.set_linked_tree(nullptr);
335
336 PermutationItem default_item;
337 default_item.key = 0;
338 default_item.pointer = 0;
339 this->pi_tree.resize(pi_size, default_item);
340 this->inverse_pi_tree.resize(pi_size, default_item);
341
342 // stool::Printer::print("items", pi);
343
344 this->pi_tree.set_linked_tree(&this->inverse_pi_tree);
345 this->inverse_pi_tree.set_linked_tree(&this->pi_tree);
346
347 uint64_t message_counter = 10000;
348 uint64_t processed_node_counter = 0;
349
350 [[maybe_unused]] uint64_t i = 0;
351 for (auto it = this->pi_tree.get_postorder_iterator_begin(); it != this->pi_tree.get_postorder_iterator_end(); ++it)
352 {
353 message_counter++;
354 processed_node_counter++;
355 if (message_paragraph >= 0 && message_counter > 10000)
356 {
357
358 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "Processing... [" << (processed_node_counter / 1000) << "KB] \r" << std::flush;
359 message_counter = 0;
360 }
361
362 if ((*it).is_leaf())
363 {
364 uint64_t pi_leaf_idx = (*it).get_leaf_container_index();
365 PermutationContainer &leaf = this->pi_tree.get_leaf_container(pi_leaf_idx);
366 std::unordered_map<uint64_t, uint64_t> mapper;
367 for (uint64_t j = 0; j < leaf.size(); j++)
368 {
369 uint64_t idx = this->inverse_pi_tree.compute_path_from_root_to_leaf(*beg);
370 ++beg;
371 const auto &path = this->inverse_pi_tree.get_temporary_path();
372 uint64_t inv_leaf_idx = path[path.size() - 1].get_leaf_container_index();
373 PermutationContainer &inv_leaf = this->inverse_pi_tree.get_leaf_container(inv_leaf_idx);
374
375 // uint64_t x1 = std::min(pi[i] / half_degree, pi_tree_vec_size - 1);
376 auto f = mapper.find(inv_leaf_idx);
377 if (f == mapper.end())
378 {
379 mapper[inv_leaf_idx] = 0;
380 }
381 uint64_t key = mapper[inv_leaf_idx];
382 leaf.set_value(j, PermutationItem(inv_leaf_idx, key));
383 inv_leaf.set_value(idx, PermutationItem(pi_leaf_idx, key));
384
385 mapper[inv_leaf_idx] = key + 1;
386 i++;
387 }
388 }
389 }
390
391 st2 = std::chrono::system_clock::now();
392
393 if (message_paragraph >= 0 && pi_size > 0)
394 {
395 uint64_t sec_time = std::chrono::duration_cast<std::chrono::seconds>(st2 - st1).count();
396 uint64_t ms_time = std::chrono::duration_cast<std::chrono::milliseconds>(st2 - st1).count();
397 uint64_t per_time = ((double)ms_time / (double)pi_size) * 1000000;
398 std::cout << std::endl;
399
400 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;
401 }
402 }
404
408
409
414 void print_information_about_performance(int message_paragraph = stool::Message::SHOW_MESSAGE) const
415 {
416 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Performance Information (DynamicPermutation)[" << std::endl;
417 this->pi_tree.print_information_about_performance(message_paragraph + 1);
418 this->inverse_pi_tree.print_information_about_performance(message_paragraph + 1);
419 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "]" << std::endl;
420 }
425 std::vector<std::string> get_memory_usage_info(int message_paragraph = stool::Message::SHOW_MESSAGE) const
426 {
427 std::vector<std::string> log1 = this->pi_tree.get_memory_usage_info(message_paragraph + 1);
428 std::vector<std::string> log2 = this->inverse_pi_tree.get_memory_usage_info(message_paragraph + 1);
429
430 std::vector<std::string> r;
431 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) = ");
432 for (std::string &s : log1)
433 {
434 r.push_back(s);
435 }
436 for (std::string &s : log2)
437 {
438 r.push_back(s);
439 }
440 r.push_back("==");
441 return r;
442 }
447 void print_memory_usage(int message_paragraph = stool::Message::SHOW_MESSAGE) const
448 {
449 std::vector<std::string> log = this->get_memory_usage_info(message_paragraph);
450 for (std::string &s : log)
451 {
452 std::cout << s << std::endl;
453 }
454 }
459 void print_statistics(int message_paragraph = stool::Message::SHOW_MESSAGE) const
460 {
461 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Statistics(DynamicPermutation):" << std::endl;
462 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "The size of permutation: " << this->size() << std::endl;
463 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "Estimated memory usage: " << this->size_in_bytes() << " bytes" << std::endl;
464 this->pi_tree.print_statistics(message_paragraph + 1);
465 this->inverse_pi_tree.print_statistics(message_paragraph + 1);
466 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "[END]" << std::endl;
467 }
472 void print_content(int message_paragraph = stool::Message::SHOW_MESSAGE) const
473 {
474 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "Content(DynamicPermutation):" << std::endl;
475 auto pi_vector = this->to_pi_vector();
476 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "PI: \t" << stool::ConverterToString::to_integer_string(pi_vector) << std::endl;
477 auto inverse_pi_vector = this->to_inverse_pi_vector();
478 std::cout << stool::Message::get_paragraph_string(message_paragraph + 1) << "Inverse PI: \t" << stool::ConverterToString::to_integer_string(inverse_pi_vector) << std::endl;
479 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "[END]" << std::endl;
480 }
485 void print_trees(int message_paragraph = stool::Message::SHOW_MESSAGE) const
486 {
487 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "========= DP ========" << std::endl;
488 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "PI: " << std::endl;
489 auto pi_vec = this->to_pi_vector();
490 stool::DebugPrinter::print_integers(pi_vec, stool::Message::get_paragraph_string(message_paragraph) + "pi_vector");
491 this->pi_tree.print_tree();
492 this->pi_tree.print_leaves();
493 std::cout << std::endl;
494 std::cout << "Inv_PI: " << std::endl;
495 auto inv_pi_vec = this->to_inverse_pi_vector();
496 stool::DebugPrinter::print_integers(inv_pi_vec, stool::Message::get_paragraph_string(message_paragraph) + "inverse_pi_vector");
497 this->inverse_pi_tree.print_tree();
498 this->inverse_pi_tree.print_internal_nodes();
499 this->inverse_pi_tree.print_leaves();
500 std::cout << stool::Message::get_paragraph_string(message_paragraph) << "=====================" << std::endl;
501 }
502
506 void verify() const
507 {
508 assert(this->pi_tree.get_linked_tree() == &this->inverse_pi_tree);
509 assert(this->inverse_pi_tree.get_linked_tree() == &this->pi_tree);
510 }
511
513
517
518
521 static DynamicPermutation load_from_bytes(const std::vector<uint8_t> &data, uint64_t &pos)
522 {
524 Tree pi_tree = Tree::load_from_bytes(data, pos);
525 Tree inverse_pi_tree = Tree::load_from_bytes(data, pos);
526 r.pi_tree.swap(pi_tree, false);
527 r.inverse_pi_tree.swap(inverse_pi_tree, false);
528 r.set_linked_tree();
529 return r;
530 }
534 static DynamicPermutation load_from_file(std::ifstream &ifs)
535 {
537 Tree pi_tree = Tree::load_from_file(ifs);
538 Tree inverse_pi_tree = Tree::load_from_file(ifs);
539 r.pi_tree.swap(pi_tree, false);
540 r.inverse_pi_tree.swap(inverse_pi_tree, false);
541 r.set_linked_tree();
542 return r;
543 }
547 static void store_to_bytes(DynamicPermutation &item, std::vector<uint8_t> &output, uint64_t &pos)
548 {
549 item.pi_tree.sort_leaf_containers();
550 item.inverse_pi_tree.sort_leaf_containers();
551 Tree::store_to_bytes(item.pi_tree, output, pos);
552 Tree::store_to_bytes(item.inverse_pi_tree, output, pos);
553 }
557 static void store_to_file(DynamicPermutation &item, std::ofstream &os)
558 {
559 Tree::store_to_file(item.pi_tree, os);
560 Tree::store_to_file(item.inverse_pi_tree, os);
561 }
562
564
565 private:
566 int64_t access(const std::vector<NodePointer> &path, uint64_t position_to_leaf_index) const
567 {
568 const NodePointer &leaf_pointer = path[path.size() - 1];
569
570 uint64_t leaf_index = leaf_pointer.get_leaf_container_index();
571 const PermutationContainer &leaf1 = this->pi_tree.get_leaf_container(leaf_index);
572 PermutationItem item = leaf1.at(position_to_leaf_index);
573
574 const PermutationContainer &leaf2 = this->inverse_pi_tree.get_leaf_container(item.pointer);
575 uint64_t idx2 = leaf2.get_index(PermutationItem(leaf_index, item.key));
576
577 uint64_t result = this->inverse_pi_tree.get_value_index(item.pointer, idx2);
578
579 return result;
580 }
581 void set_linked_tree(){
582 this->pi_tree.set_linked_tree(&this->inverse_pi_tree);
583 this->inverse_pi_tree.set_linked_tree(&this->pi_tree);
584 }
585 };
586 }
587
588}
A pointer to a node of BPTree [Unchecked AI's Comment].
Definition bp_node_pointer.hpp:14
The iterator of a post-order traversal on BPTree [Unchecked AI's Comment].
Definition bp_postorder_iterator.hpp:13
An implementation of a B+-tree for storing n values S[0..n-1] of type VALUE in leaves.
Definition bp_tree.hpp:29
A dynamic data structure to store a permutation Π[0..n-1] of integers 0, 1, ..., n-1.
Definition dynamic_permutation.hpp:14
void print_information_about_performance(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Print the performance information of this data structure.
Definition dynamic_permutation.hpp:414
std::vector< uint64_t > to_inverse_pi_vector() const
Return the inverse permutation Π^{-1} as a vector of uint64_t.
Definition dynamic_permutation.hpp:202
void swap(DynamicPermutation &item)
Swap operation.
Definition dynamic_permutation.hpp:234
void sort_leaf_containers()
Sorts the leaf containers of the internal trees.
Definition dynamic_permutation.hpp:307
int64_t inverse(int64_t i) const
Return Π^{-1}[i].
Definition dynamic_permutation.hpp:149
std::vector< std::string > get_memory_usage_info(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Return the memory usage information of this data structure as a vector of strings.
Definition dynamic_permutation.hpp:425
uint64_t size() const
Return |Π|.
Definition dynamic_permutation.hpp:115
void print_content(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Print the permutation and inverse permutation stored in this data structure.
Definition dynamic_permutation.hpp:472
DynamicPermutation & operator=(DynamicPermutation &&other) noexcept
Default move assignment operator.
Definition dynamic_permutation.hpp:70
std::vector< uint64_t > to_pi_vector() const
Return the permutation Π as a vector of uint64_t.
Definition dynamic_permutation.hpp:188
DynamicPermutation()
Default constructor with |Π| = 0.
Definition dynamic_permutation.hpp:35
void insert(int64_t pi_index_p, int64_t inverse_pi_index_q)
Insert a given element q at the position p in Π and appropriately modify the elements of Π (i....
Definition dynamic_permutation.hpp:244
uint64_t size_in_bytes() const
Return the total memory usage in bytes.
Definition dynamic_permutation.hpp:122
void verify() const
Verify the internal consistency of this data structure.
Definition dynamic_permutation.hpp:506
int64_t access(int64_t i) const
Return Π[i].
Definition dynamic_permutation.hpp:138
void clear()
Clear the elements in Π
Definition dynamic_permutation.hpp:221
DynamicPermutation(DynamicPermutation &&other) noexcept
Default move constructor.
Definition dynamic_permutation.hpp:43
static void store_to_file(DynamicPermutation &item, std::ofstream &os)
Save the given instance item to a file stream os.
Definition dynamic_permutation.hpp:557
void print_trees(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Print the internal trees in this data structure.
Definition dynamic_permutation.hpp:485
Tree & get_pi_tree()
Return the internal tree storing the permutation Π.
Definition dynamic_permutation.hpp:94
static void store_to_bytes(DynamicPermutation &item, std::vector< uint8_t > &output, uint64_t &pos)
Save the given instance item to a byte vector output at the position pos.
Definition dynamic_permutation.hpp:547
Tree & get_inverse_pi_tree()
Get the internal tree storing the inverse permutation Π^{-1}.
Definition dynamic_permutation.hpp:101
uint64_t get_max_degree() const
Return the maximum degree of internal nodes in the internal trees.
Definition dynamic_permutation.hpp:108
~DynamicPermutation()
Default destructor.
Definition dynamic_permutation.hpp:52
DynamicPermutation & operator=(const DynamicPermutation &)=delete
Deleted copy assignment operator.
void build(PI_ITERATOR_BEGIN beg, PI_ITERATOR_END end, uint64_t pi_size, int message_paragraph=stool::Message::SHOW_MESSAGE)
Build a new DynamicPermutation from a given sequence of length pi_size starting from beg and ending a...
Definition dynamic_permutation.hpp:319
std::string to_string() const
Return the permutation Π as a string.
Definition dynamic_permutation.hpp:177
static DynamicPermutation load_from_file(std::ifstream &ifs)
Returns the DynamicPermutation instance loaded from a file stream ifs.
Definition dynamic_permutation.hpp:534
void print_memory_usage(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Print the memory usage information of this data structure.
Definition dynamic_permutation.hpp:447
void erase(int64_t pi_index_p)
Remove the element Π[p] from Π and appropriately modify the elements of Π (i.e., each element x in Π ...
Definition dynamic_permutation.hpp:274
static DynamicPermutation load_from_bytes(const std::vector< uint8_t > &data, uint64_t &pos)
Returns the DynamicPermutation instance loaded from a byte vector data at the position pos.
Definition dynamic_permutation.hpp:521
void move_pi_index(int64_t from_p, int64_t to_x)
Move the element Π[p] in Π to the position x in Π
Definition dynamic_permutation.hpp:289
void print_statistics(int message_paragraph=stool::Message::SHOW_MESSAGE) const
Print the statistics of this data structure.
Definition dynamic_permutation.hpp:459
The forward iterator of values stored in PermutationContainer.
Definition permutation_container.hpp:28
The container stored in the BPTree of DynamicPermutation [Unchecked AI's Comment].
Definition permutation_container.hpp:13
The value stored in the BPTree of DynamicPermutation [Unchecked AI's Comment].
Definition permutation_item.hpp:14