Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

tree_util.tpp

Go to the documentation of this file.
00001 /***
00002  * Copyright (c) 2005, SkeTo Project
00003  * All rights reserved.
00004  */
00011 #ifdef __TREE_UTIL_H__
00012 #ifndef __TREE_UTIL_TPP__
00013 #define __TREE_UTIL_TPP__
00014 
00015 #include <stdio.h>
00016 #include <fstream>
00017 #include <assert.h>
00018 
00020 // Private definitions
00021 namespace tree_util {
00022 
00026   template< typename A >
00027   struct IntermediateVal {
00029     int size;
00031     node< IntermediateVal > *cutnode;
00033     const node< A >* orgnode;
00034   };
00035 
00039   template< typename A >
00040   static node< A >*
00041   construct_tree_from_array_rec( const int** flags,
00042                  const A** values );
00043 
00047   static inline int
00048   ceil_divided_by_m( int x, int m );
00049 
00050   template< typename A >
00051   static bool
00052   compute_size_and_mark_critical( const node< A >* tree,
00053                   const int nprocs,
00054                   node< tree_util::IntermediateVal< A > >** size_critical_tree,
00055                   int *global_size );
00056   
00060   template< typename A >
00061   static bool
00062   write_distributed_tree_to_fstream( node< tree_util::IntermediateVal< A > >* size_critical_tree,
00063                      int globalsize,
00064                      std::fstream &fout );
00065 
00073   template< typename A >
00074   static node< tree_util::IntermediateVal< A > >*
00075   compute_size_rec( const node< A >* tree );
00076 
00086   template< typename A >
00087   static int
00088   mark_critical_node( node< tree_util::IntermediateVal< A > >* size_critical_tree,
00089               const int m );
00090 
00108   template< typename A >
00109   static void
00110   get_global_tree( node< tree_util::IntermediateVal< A > >* root,
00111            int *flags,
00112            int *sizes,
00113            node< tree_util::IntermediateVal< A > >** subroots );
00114 
00118   template< typename A >
00119   static void
00120   get_global_tree_rec( node< tree_util::IntermediateVal< A > >* root,
00121                int *flags,
00122                int *sizes,
00123                node< tree_util::IntermediateVal< A > >** subroots,
00124                int *count );
00125   
00141   template< typename A >
00142   static void
00143   get_local_tree( const node< tree_util::IntermediateVal< A > > *root,
00144           int *local_flags,
00145           A* local_values );
00146   
00147 
00151   template< typename A >
00152   static void
00153   get_local_tree_rec( const node< tree_util::IntermediateVal< A > > *root,
00154               int *local_flags,
00155               A* local_values,
00156               int *local_count );
00157 
00158   template< typename A >
00159   static void
00160   serialize_subtree( const node< A > *root,
00161              int **flags,
00162              A **valus );
00163   
00164 }
00165 
00167 // Implementations
00168 
00169 template< typename A >
00170 node< A >*
00171 tree_util::read_tree_from_file( const char* filename )
00172 {
00173   std::fstream fin( filename, std::ios::in );
00174   if ( fin.fail( ) ) return NULL;
00175 
00176   int nNodes; fin >> nNodes;
00177   if ( nNodes <= 0 ) return NULL;
00178 
00179   int *flags = new int[ nNodes ];
00180   A* values = new A[ nNodes ];
00181 
00182   for ( int i = 0; i < nNodes; i++ ) {
00183     fin >> flags[ i ] >> values[ i ];
00184   }
00185 
00186   return construct_tree_from_array( flags, values );
00187 }
00188 
00189 template< typename A >
00190 node< A >*
00191 tree_util::construct_tree_from_array( const int* flags,
00192                       const A* values )
00193 {
00194   return construct_tree_from_array_rec( &flags, &values );
00195 }
00196 
00197 template< typename A >
00198 static node< A >*
00199 tree_util::construct_tree_from_array_rec( const int** flags,
00200                       const A** values )
00201 {
00202   const int &flag = *((*flags)++);
00203   const A &value = *((*values)++);
00204 
00205   node< A >* rettree = new node< A >( value );
00206   if ( flag == node< A >::SER_NODE ) {
00207     rettree->left  = construct_tree_from_array_rec( flags, values );
00208     rettree->left->parent = rettree;
00209 
00210     rettree->right = construct_tree_from_array_rec( flags, values );
00211     rettree->right->parent = rettree;
00212   }
00213   return rettree;
00214 }
00215 
00216 template< typename A > 
00217 void
00218 tree_util::free_all_tree( node< A >* root )
00219 {
00220   if ( root == NULL ) return;
00221 
00222   free_all_tree( root->left );
00223   free_all_tree( root->right );
00224   delete root;
00225 }
00226 
00227 template< typename A >
00228 bool
00229 tree_util::check_perfect_binary_tree( const node< A >* tree )
00230 {
00231   if ( tree->isLeaf( ) ) return true;
00232   if ( !tree->left || !tree->right ) return false;
00233   return ( check_perfect_binary_tree( tree->left ) &&
00234        check_perfect_binary_tree( tree->right ) );
00235 }
00236 
00237 template< typename A >
00238 bool
00239 tree_util::dist_and_write_to_file( const node< A >* tree,
00240                    const int nprocs,
00241                    const char *filename )
00242 {
00243   if ( !check_perfect_binary_tree( tree ) ) {
00244     return false;
00245   }
00246 
00247   node< IntermediateVal< A > > *size_critical_tree;
00248   int global_size;
00249 
00250   if ( !compute_size_and_mark_critical( tree,
00251                     nprocs,
00252                     &size_critical_tree,
00253                     &global_size ) ) {
00254     return false;
00255   }
00256 
00257   std::fstream fout( filename, std::ios::out );
00258   if ( fout.fail( ) ) return false;
00259 
00260   if ( !write_distributed_tree_to_fstream( size_critical_tree,
00261                        global_size,
00262                        fout ) ) {
00263     return false;
00264   }
00265 
00266   free_all_tree( size_critical_tree );
00267   return true;
00268 }
00269 
00270 static int
00271 tree_util::ceil_divided_by_m( int x, int m )
00272 {
00273   return ( x + ( m - 1 ) ) / m;
00274 }
00275 
00276 template< typename A >
00277 static bool
00278 tree_util::compute_size_and_mark_critical( const node< A >* tree,
00279                        const int nprocs,
00280                        node< IntermediateVal< A > >** size_critical_tree,
00281                        int *global_size )
00282 {
00283   *size_critical_tree = compute_size_rec( tree );
00284   
00285   int size = (*size_critical_tree)->value.size;
00286   int m = 2 * size / ( nprocs / 2 + 1 );
00287   
00288   int ncritical = mark_critical_node( *size_critical_tree, m );
00289 
00290   // check the number of distributed trees is not greater than nprocs. 
00291   assert( ncritical * 2 + 1 <= nprocs );
00292     
00293   *global_size = ncritical * 2 + 1;
00294 
00295   return true;
00296 }
00297 
00298 template< typename A >
00299 static bool
00300 tree_util::write_distributed_tree_to_fstream( node< tree_util::IntermediateVal< A > >* size_critical_tree,
00301                           int globalsize,
00302                           std::fstream &fout )
00303 {
00304   fout << globalsize << std::endl;
00305 
00306   // write global structure
00307   int *sizes = new int[ globalsize ];
00308   node< tree_util::IntermediateVal< A > > **subroots
00309     = new node< tree_util::IntermediateVal< A > >*[ globalsize ];
00310   {
00311     int *flags = new int[ globalsize ];
00312     get_global_tree( size_critical_tree, flags, sizes, subroots );
00313 
00314     for ( int p = 0; p < globalsize; p++ ) {
00315       fout << flags[ p ] << " " << sizes[ p ] << std::endl;
00316     }
00317 
00318     delete [] flags;
00319   }
00320 
00321   // write local subtrees
00322   {
00323     for ( int p = 0; p < globalsize; p++ ) {
00324       int *local_flags = new int[ sizes[ p ] ];
00325       A *local_values = new A[ sizes[ p ] ];
00326       
00327       get_local_tree( subroots[ p ], local_flags, local_values );
00328       
00329       for ( int i = 0; i < sizes[ p ]; i++ ) {
00330     fout << local_flags[ i ] << " " << local_values[ i ] << std::endl;
00331       }
00332       
00333       delete [] local_values;
00334       delete [] local_flags;
00335     }
00336   }
00337 
00338   delete [] subroots;
00339   delete [] sizes;
00340 
00341   return true;
00342 }
00343 
00344 template< typename A >
00345 static node< tree_util::IntermediateVal< A > >*
00346 tree_util::compute_size_rec( const node< A >* tree )
00347 {
00348   node< IntermediateVal< A > >* rettree;
00349   if ( tree->isLeaf( ) ) {
00350     IntermediateVal< A > val;
00351     val.size = 1;
00352     val.cutnode = NULL;
00353     val.orgnode = tree;
00354     rettree = new node< tree_util::IntermediateVal< A > >( val );
00355   } else {
00356     node< tree_util::IntermediateVal< A > >* left
00357       = compute_size_rec( tree->left );
00358     node< tree_util::IntermediateVal< A > >* right
00359       = compute_size_rec( tree->right );
00360       
00361     IntermediateVal< A > val;
00362     val.size = 1 + left->value.size + right->value.size;
00363     val.cutnode = NULL;
00364     val.orgnode = tree;
00365     rettree = new node< IntermediateVal< A > >( val );
00366     rettree->left  = left;  rettree->left->parent  = rettree;
00367     rettree->right = right; rettree->right->parent = rettree;
00368   }
00369   return rettree;
00370 }
00371 
00372 template< typename A >
00373 static int
00374 tree_util::mark_critical_node( node< IntermediateVal< A > >* size_critical_tree,
00375                    const int m )
00376 {
00377   int n_critical = 0;
00378   if ( size_critical_tree->isLeaf( ) ) {
00379   } else {
00380     n_critical += mark_critical_node( size_critical_tree->left,  m );
00381     n_critical += mark_critical_node( size_critical_tree->right, m );
00382 
00383     int size       = size_critical_tree->value.size;
00384     int left_size  = size_critical_tree->left->value.size;
00385     int right_size = size_critical_tree->right->value.size;
00386 
00387     if ( ceil_divided_by_m( size, m ) > ceil_divided_by_m( left_size, m ) &&
00388      ceil_divided_by_m( size, m ) > ceil_divided_by_m( right_size, m ) ) {
00389       size_critical_tree->nodetype = node< IntermediateVal< A > >::CUTNODE;
00390       n_critical += 1;
00391       size_critical_tree->value.cutnode = size_critical_tree;
00392     } else {
00393       node< IntermediateVal< A > >* left_critical
00394     = size_critical_tree->left->value.cutnode;
00395       node< IntermediateVal< A > >* right_critical
00396     = size_critical_tree->right->value.cutnode;
00397       if ( left_critical )  size_critical_tree->value.cutnode = left_critical;
00398       if ( right_critical ) size_critical_tree->value.cutnode = right_critical;
00399     }
00400 
00401   }
00402   return n_critical;
00403 }
00404 
00405 template< typename A >
00406 static void
00407 tree_util::get_global_tree( node< IntermediateVal< A > >* root,
00408                 int *flags,
00409                 int *sizes,
00410                 node< IntermediateVal< A > >** subroots )
00411 {
00412   int count = 0;
00413   get_global_tree_rec( root, flags, sizes, subroots, &count );
00414 }
00415 
00416 template< typename A >
00417 static void
00418 tree_util::get_global_tree_rec( node< IntermediateVal< A > >* root,
00419                 int *flags,
00420                 int *sizes,
00421                 node< IntermediateVal< A > >** subroots,
00422                 int *count )
00423 {
00424   int count_this = (*count)++;
00425   if ( root->value.cutnode ) {
00426     flags[ count_this ]    = node< A >::SER_NODE;
00427     sizes[ count_this ]    = root->value.size - root->value.cutnode->value.size + 1;
00428     subroots[ count_this ] = root;
00429 
00430     get_global_tree_rec( root->value.cutnode->left,
00431              flags, sizes, subroots, count );
00432     get_global_tree_rec( root->value.cutnode->right,
00433              flags, sizes, subroots, count );
00434   } else {
00435     flags[ count_this ]    = node< A >::SER_LEAF;
00436     sizes[ count_this ]    = root->value.size;
00437     subroots[ count_this ] = root;
00438   }
00439 }
00440 
00441 template< typename A >
00442 static void
00443 tree_util::get_local_tree( const node< IntermediateVal< A > > *root,
00444                int *local_flags,
00445                A* local_values )
00446 {
00447   int local_count = 0;
00448   get_local_tree_rec( root, local_flags, local_values, &local_count );
00449 }
00450           
00454 template< typename A >
00455 static void
00456 tree_util::get_local_tree_rec( const node< IntermediateVal< A > > *root,
00457                    int *local_flags,
00458                    A* local_values,
00459                    int *local_count )
00460 {
00461   int current_count = ( *local_count )++;
00462   local_values[ current_count ] = root->value.orgnode->value;
00463   if ( root->isLeaf( ) ) {
00464     local_flags[ current_count ] = node< A >::SER_LEAF;
00465 
00466   } else if ( root->nodetype == node< IntermediateVal< A > >::NORMAL ) {
00467     local_flags[ current_count ] = node< A >::SER_NODE;
00468 
00469   } else {
00470     local_flags[ current_count ] = node< A >::SER_CUTNODE;
00471   }
00472 
00473   if ( !root->isLeaf( ) &&
00474        root->nodetype == node< IntermediateVal< A > >::NORMAL ) {
00475     get_local_tree_rec( root->left,  local_flags, local_values, local_count );
00476     get_local_tree_rec( root->right, local_flags, local_values, local_count );
00477   }
00478 }
00479 
00480 template< typename A >
00481 bool
00482 tree_util::write_to_file( const node< A >* tree,
00483               const char *filename )
00484 {
00485   std::fstream fout( filename, std::ios::out );
00486   if ( fout.fail( ) ) return false;
00487   
00488   int size = get_size_rec( tree );
00489   fout << size << std::endl;
00490   
00491   int *local_flags = new int[ size ];
00492   A *local_values = new A[ size ];
00493       
00494   int *p_flags = local_flags;
00495   A *p_values = local_values;
00496   serialize_subtree( tree, &p_flags, &p_values );
00497 
00498   for ( int i = 0; i < size; i++ ) {
00499     fout << local_flags[ i ] << " " << local_values[ i ] << std::endl;
00500   }
00501 
00502   delete [] local_values;
00503   delete [] local_flags;
00504 
00505   return true;
00506 }
00507 
00508 template< typename A >
00509 int
00510 tree_util::get_size_rec( const node< A >* tree )
00511 {
00512   if ( tree->isLeaf( ) ) {
00513     return 1;
00514   } else {
00515     return 1 + get_size_rec( tree->left )
00516       + get_size_rec( tree->right );
00517   }
00518 }
00519 
00520 template< typename A >
00521 static void
00522 tree_util::serialize_subtree( const node< A > *root,
00523                   int **flags,
00524                   A **values )
00525 {
00526   if ( root->isLeaf( ) && root->nodetype == node< A >::NORMAL ) {
00527     *((*flags)++) = node< A >::SER_LEAF;
00528     *((*values)++) = root->value;
00529   } else if ( root->isLeaf( ) && root->nodetype == node< A >::CUTNODE ) {
00530     *((*flags)++) = node< A >::SER_CUTNODE;
00531     *((*values)++) = root->value;
00532   } else if ( !root->isLeaf( ) ) {
00533     *((*flags)++) = node< A >::SER_NODE;
00534     *((*values)++) = root->value;
00535 
00536     serialize_subtree( root->left,  flags, values );
00537     serialize_subtree( root->right, flags, values );
00538   } else {
00539     assert( false );
00540   }
00541 }
00542 
00543 #endif /* __TREE_UTIL_TPP__ */
00544 #endif /* __TREE_UTIL_H__ */

Generated on Wed Jan 18 22:19:29 2006 for SkeTo -- Skeleton Library in Tokyo by  doxygen 1.4.4