5template <
class X1,
template<
typename>
class predicate>
7 if( p_dataset )
throw std::runtime_error(
"CMMTree<X1, predicate>::join_data(): This tree is already assigned with data.\nConsider using the tree_clear() function.");
11template <
class X1,
template<
typename>
class predicate>
13 if( p_dataset )
throw std::runtime_error(
"CMMTree<X1, predicate>::join_data(): This tree is already assigned with data.\nConsider using the tree_clear() function.");
15 root->data_address()=pos;
18template <
class X1,
template<
typename>
class predicate>
21 if( generation == MTree.size() ){
22 MTree.emplace_back( firstborns( 1, node_adr ) );
25 MTree[generation].push_back(node_adr);
29template <
class X1,
template<
typename>
class predicate>
33 typename std::vector<X1>::const_iterator pos ;
35 for(
size_t i = 0; i < MTree[generation].size(); ++i ){
37 sn = MTree[generation][i]->siblings_number() ;
38 p_current_node = MTree[generation][i];
42 p_current_node=(*p_current_node->parent->children)[k];
44 pos = p_dataset->begin();
45 while( pos != p_dataset->end() ){
46 if( condition( p_current_node, pos ) ) {
49 add_next_firstborn(generation+1, (*p_current_node->children)[0] );
58template <
class X1,
template<
typename>
class predicate>
60 if( !root->isNULLit(root->d_iterator) || root->children )
61 throw std::runtime_error(
"CMMTree<X1, predicate>::create_subtrees_roots():\nThis function can only be called if the root node is not associated with any element of the input dataset and has no children yet.");
63 typename std::vector<X1>::const_iterator pos = roots_data.begin();
64 while( pos != roots_data.end() ){
65 root->add_new_node( pos );
66 if( root->children_number() == 1 ){
67 add_next_firstborn(1, (*root->children)[0] );
73template <
class X1,
template<
typename>
class predicate>
75 if(!p_dataset)
throw std::runtime_error(
"CMMTree<X1, predicate>::tree_create(): The tree is not assigned to the data.\nConsider using the join_data() function.\n");
77 auto t1 = std::chrono::high_resolution_clock::now();
80 find_new_generation( cht-1 );
81 }
while(cht < MTree.size());
82 auto t2 = std::chrono::high_resolution_clock::now();
83 return std::chrono::duration_cast<std::chrono::microseconds> (t2 - t1).count();
86template <
class X1,
template<
typename>
class predicate>
89 throw std::runtime_error(
"CMMTree<X1, predicate>::firstborns_number(): The argument out of range.");
90 return MTree[i].size();
93template <
class X1,
template<
typename>
class predicate>
96 throw std::runtime_error(
"CMMTree<X1, predicate>::leaves_number(): The argument out of range.");
99 if( !MTree[0][0]->children )
return 1;
102 for(
size_t j = 0; j < MTree[i].size(); ++j )
103 for(
size_t k = 0; k < MTree[i][j]->parent->children_number(); ++k )
104 if( !(*MTree[i][j]->parent->children)[k]->children )
109template <
class X1,
template<
typename>
class predicate>
112 throw std::runtime_error(
"CMMTree<X1, predicate>::generation_size(size_t i): The argument out of range.");
115 for(
size_t j = 0; j < MTree[i].size(); ++j )
116 tmp+=MTree[i][j]->parent->children_number();
120template <
class X1,
template<
typename>
class predicate>
124 throw std::runtime_error(
"CMMTree<X1, predicate>::generation_addresses(): The first argument out of range.");
127 vec.push_back( MTree[0][0] );
130 for(
size_t j = 0; j < MTree[i].size(); ++j ){
131 for(
size_t k = 0; k < MTree[i][j]->parent->children_number(); ++k ){
132 vec.push_back( (*MTree[i][j]->parent->children)[k] );
138template <
class X1,
template<
typename>
class predicate>
142 throw std::runtime_error(
"CMMTree<X1, predicate>::generation_addresses(): The first argument out of range.");
145 vec.push_back( MTree[0][0] );
148 for(
size_t j = 0; j < MTree[i].size(); ++j ){
149 for(
size_t k = 0; k < MTree[i][j]->parent->children_number(); ++k ){
150 vec.push_back( (*MTree[i][j]->parent->children)[k] );
156template <
class X1,
template<
typename>
class predicate>
161 throw std::runtime_error(
"CMMTree<X1, predicate>::leaves_addresses(): The first argument out of range.");
163 if(!MTree[0][0]->children ){
164 vec.push_back( MTree[0][0] );
168 for(
size_t j = 0; j < MTree[i].size(); ++j ){
169 for(
size_t k = 0; k < MTree[i][j]->parent->children_number(); ++k ){
170 if( !(*MTree[i][j]->parent->children)[k]->children ){
171 vec.push_back( (*MTree[i][j]->parent->children)[k] );
178template <
class X1,
template<
typename>
class predicate>
182 if( i < ptr->prev->children->size() )
183 return ptr->prev->children->operator[](i);
187template <
class X1,
template<
typename>
class predicate>
189 if(i >= MTree.size() )
throw std::runtime_error(
"CMMTree<X1, predicate>::firstborn_address(): The first argument out of range.");
190 if(j >= MTree[i].size() )
throw std::runtime_error(
"CMMTree<X1, predicate>::firstborn_address(): The second argument out of range.");
194template <
class X1,
template<
typename>
class predicate>
197 for(
size_t i=lev; i<MTree.size();++i){
200 if( root->children_number() ){
201 MTree[i].push_back(root->children->operator[](0));
208 for(
auto& r: MTree[i-1]){
209 for(
auto& rc: *r->parent->children ){
210 if( rc->children_number() ){
211 MTree[i].push_back(rc->children->operator[](0));
215 if( !MTree[i].size() ){
222template <
class X1,
template<
typename>
class predicate>
225 if(!to_del->parent)
throw std::runtime_error(
"CMMTree<X1, predicate>::delete_node(): The root node can not be deleted!\n");
227 size_t i=0, cs=prev->children->size();
229 if(prev->children->operator[](i) == to_del){
230 delete prev->children->operator[](i);
233 prev->children->operator[](i)=prev->children->operator[](i+1);
237 prev->children->pop_back();
238 if(!prev->children->size()){
239 delete prev->children;
240 prev->children =
nullptr;
242 jagged_table_reconstruction( to_del->
node_level() );
245template <
class X1,
template<
typename>
class predicate>
247 if(!lev)
throw std::runtime_error(
"CMMTree<X1, predicate>::delete_node(): The root node can not be deleted!\n");
248 for(
auto& r: to_del){
250 size_t i=0, cs=prev->children->size();
252 if(prev->children->operator[](i) == r){
253 delete prev->children->operator[](i);
256 prev->children->operator[](i)=prev->children->operator[](i+1);
260 prev->children->pop_back();
261 if(!prev->children->size()){
262 delete prev->children;
263 prev->children =
nullptr;
266 jagged_table_reconstruction( lev );
269template <
class X1,
template<
typename>
class predicate>
271 if(root->children_number()){
272 for (
auto& r : *root->children)
274 delete root->children;
282template <
class X1,
template<
typename>
class predicate>
284 out<<
"\nThe shape of the CMMTree ( N - number of nodes, F - number of firstborns, L - number of leaves ).\n";
286 size_t T_s= MTree.size();
287 long N_i= 0, N_ip= 0;
288 long F_i= 0, F_ip= 0;
289 long L_i= 0, L_ip= 0;
290 long SN1= 0, SN2 = 0;
291 long SF1= 0, SF2 = 0;
294 std::vector< const node<X1>* > N_ip_vec;
295 std::vector< const node<X1>* > F_ip_vec;
299 out<<
"Lev ; N ; F ; L ; F/N ; L/N ; dF/Ni ; dL/Ni ; dF/(Fi+Fip); dF/(Ni+Nip); dL/(Ni+Nip);(SN2-SN1)/Ni;(SF2-SF1)/Ni;\n";
300 out<<
"----;------------;------------;------------;------------;------------;------------;------------;------------;------------;------------;------------;------------;\n";
302 for(
size_t i=0; i<T_s ; ++i){
303 N_i= (long)generation_size(i);
304 F_i= (long)firstborns_number(i);
305 L_i= (long)leaves_number(i);
312 for( ; j < MTree[i-1].size()/2; ++j ){
313 MTree[i-1][j]->all_siblings_addresses( F_ip_vec );
314 for(
auto&& r:F_ip_vec){
315 SF1+= (long)r->children_number();
319 for( ; j < MTree[i-1].size(); ++j ){
320 MTree[i-1][j]->all_siblings_addresses( F_ip_vec );
321 for(
auto&& r:F_ip_vec){
322 SF2+= (long)r->children_number();
328 for( ; j < MTree[i-1].size()/2; ++j ){
329 MTree[i-1][j]->all_siblings_addresses( F_ip_vec );
330 for(
auto&& r:F_ip_vec){
331 SF1+= (long)r->children_number();
334 for( ; j < MTree[i-1].size(); ++j ){
335 MTree[i-1][j]->all_siblings_addresses( F_ip_vec );
336 for(
auto&& r:F_ip_vec) {
337 SF2+= (long)r->children_number();
344 generation_addresses(i-1, N_ip_vec) ;
345 if(N_ip_vec.size() % 2){
347 for( ; j < N_ip_vec.size()/2; ++j ){
348 SN1+= (long)N_ip_vec[j]->children_number();
351 for( ; j < N_ip_vec.size(); ++j ){
352 SN2+= (long)N_ip_vec[j]->children_number();
357 for( ; j < N_ip_vec.size()/2; ++j ){
358 SN1+= (long)N_ip_vec[j]->children_number();
360 for( ; j < N_ip_vec.size(); ++j ){
361 SN2+= (long)N_ip_vec[j]->children_number();
376 out << (double)F_i/(
double)N_i <<
';';
378 out << (double)L_i/(
double)N_i <<
';';
380 out << (double)(F_i - F_ip)/(double)N_i <<
';';
382 out << (double)(L_i - L_ip)/(double)N_i <<
';';
384 out << (double)(F_i - F_ip)/(double)(F_i + F_ip) <<
';';
386 out << (double)(F_i - F_ip)/(double)(N_i + N_ip) <<
';';
388 out << (double)(L_i - L_ip)/(double)(N_i + N_ip) <<
';';
390 out << (double)(SN2 - SN1)/(double)N_i <<
';';
392 out << (double)(SF2 - SF1)/(double)N_i <<
';';
396 N_ip= (long)generation_size(i);
397 F_ip= (long)firstborns_number(i);
398 L_ip= (long)leaves_number(i);
400 out<<
"----;------------;------------;------------;------------;------------;------------;------------;------------;------------;------------;------------;------------;\n";
403template <
class X1,
template<
typename>
class predicate>
406 std::string msg(
"\n");
409 #ifdef MAX_NODES_TO_PRINT
413 msg = (
"\nCMMTree has more nodes than was defined using the \'MAX_NODES_TO_PRINT\' directive.\n");
415 msg =
"\n\'MAX_NODES_TO_PRINT\' is not defined.\n";
418 msg =
"\nPlease define the \'NODE_COUNTER\' and \'MAX_NODES_TO_PRINT\' directives.\n";
422 std::vector< node<X1>
const* > vec;
423 #ifdef PRINT_ALL_PATHS
424 std::vector< typename std::vector<X1>::const_iterator > path;
426 for(
size_t i=0; i<r.MTree.size() ; ++i){
428 out <<
"--Level : " << i <<
" --" << std::endl;
430 for(
size_t j=0; j<vec.size() ; ++j){
431 out <<
"---Path : " << j <<
" ---" << std::endl;
432 vec[j]->data_on_path(path);
435 out<<*path[--k] <<
"\n";
441 for(
size_t i=0; i<r.MTree.size() ; ++i){
443 for(
size_t j=0; j<vec.size() ; ++j){
447 out<< *vec[j]->data_address();
455 out <<
"CMMTree hight : " << r.
tree_height() << msg;
The Conditional Multiway Mapped Tree (CMMTree) class definition.
size_t firstborns_number(size_t i) const
This function returns the number of firstborn nodes of one generation of the CMMTree - at the level p...
size_t generation_size(size_t i) const
This function returns the total number of nodes one generation of the CMMTree - at the level passed b...
void generation_addresses(size_t i, std::vector< const node< X1 > * > &vec) const
This function allows you to get all the addresses of the i-th generation firstborn nodes....
void tree_shape(std::ostream &out) const
This function allows you to represent a tree in a parametric form.
void join_data(std::vector< X1 >const *const &adr)
This function is used to connect the CMMTree object to the input data vector.
void tree_clear()
This function clears the entire CMMTree object.
long long tree_create()
A function that starts the process of the CMMTree construction.
void delete_one_node(node< X1 > *&to_del)
This function deletes the node whose address is passed as an argument.
const node< X1 > * brother_address(const node< X1 > *ptr, size_t i) const
This function allows you to obtain the address of the i-th brother of the firstborn node.
void create_subtrees_roots(std::vector< X1 > const &roots_data)
This function allows you to initialize the creation of a forest using a separate data set - different...
node< X1 > const *const & firstborn_address(size_t i, size_t j) const
The function returns the address of the j-th firstborn of the i-th generation.
size_t all_nodes_number() const
This function returns the number of all nodes in the CMMTree.
size_t tree_height() const
This function returns the CMMTree height.
void delete_nodes(std::vector< node< X1 > * > &to_del, size_t lev)
Using this function you can delete more than one node from a specified node generation at once.
void leaves_addresses(size_t i, std::vector< const node< X1 > * > &vec) const
This function allows you to get all the addresses of the i-th generation leaves.
size_t leaves_number(size_t i) const
This function returns the number of leaves one generation of the CMMTree - at the level passed by the...
The node class definition. This is a template of a class whose objects are used to build a tree of re...
size_t node_level() const
This function returns the level of the CMMTree where a given node is located.
void change_children_capacity() const
A function that reduces the size of the vector of parent's children's addresses - from capacity() to ...
size_t children_number() const
The function returns the number of children of a given node.
void add_new_node(data_addr const &pos)
This function is used to create another CMMTree node.
std::ostream & operator<<(std::ostream &out, CMMTree< X1, predicate > const &r)
std::vector< T >::const_iterator const & Null_iterator(T)
An iterator that is supposed to point to "nothing" of specified type ;).