00001
00002
00003
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
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
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
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
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
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
00544 #endif