00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "EpetraExt_ConfigDefs.h"
00030 #ifdef HAVE_EXPERIMENTAL
00031 #ifdef HAVE_GRAPH_REORDERINGS
00032
00033 #include <EpetraExt_SymmRCM_CrsGraph.h>
00034
00035 #include <EpetraExt_Transpose_CrsGraph.h>
00036
00037 #include <set>
00038
00039 #include <Epetra_Util.h>
00040 #include <Epetra_CrsGraph.h>
00041 #include <Epetra_Map.h>
00042 #include <Epetra_Import.h>
00043
00044 namespace EpetraExt {
00045
00046 CrsGraph_SymmRCM::
00047 ~CrsGraph_SymmRCM()
00048 {
00049 if( newObj_ ) delete newObj_;
00050
00051 if( RCMColMap_ != RCMMap_ ) delete RCMColMap_;
00052 if( RCMMap_ ) delete RCMMap_;
00053 }
00054
00055 CrsGraph_SymmRCM::NewTypeRef
00056 CrsGraph_SymmRCM::
00057 operator()( CrsGraph_SymmRCM::OriginalTypeRef orig )
00058 {
00059 origObj_ = &orig;
00060
00061 int err;
00062
00063
00064 CrsGraph_Transpose transposeTransform;
00065 Epetra_CrsGraph & trans = transposeTransform( orig );
00066
00067
00068
00069 int NumNodes = orig.NumMyRows();
00070 int * LocalRow;
00071 int * LocalRowTrans;
00072 int RowSize, RowSizeTrans;
00073 std::vector< std::vector<int> > AdjList( NumNodes );
00074 int MinDegree = NumNodes;
00075 int MinDegreeNode;
00076 for( int i = 0; i < NumNodes; ++i )
00077 {
00078 orig.ExtractMyRowView( i, RowSize, LocalRow );
00079 trans.ExtractMyRowView( i, RowSizeTrans, LocalRowTrans );
00080
00081 std::set<int> adjSet;
00082 for( int j = 0; j < RowSize; ++j )
00083 if( LocalRow[j] < NumNodes ) adjSet.insert( LocalRow[j] );
00084 for( int j = 0; j < RowSizeTrans; ++j )
00085 if( LocalRowTrans[j] < NumNodes ) adjSet.insert( LocalRowTrans[j] );
00086
00087 std::set<int>::iterator iterS = adjSet.begin();
00088 std::set<int>::iterator endS = adjSet.end();
00089 AdjList[i].resize( adjSet.size() );
00090 for( int j = 0; iterS != endS; ++iterS, ++j ) AdjList[i][j] = *iterS;
00091
00092 if( AdjList[i].size() < MinDegree )
00093 {
00094 MinDegree = AdjList[i].size();
00095 MinDegreeNode = i;
00096 }
00097 }
00098
00099 BFT * BestBFT;
00100 bool TooWide;
00101
00102
00103
00104 if( bruteForce_ )
00105 {
00106 int bestWidth = NumNodes;
00107 int bestDepth = 0;
00108
00109 for( int i = 0; i < NumNodes; ++i )
00110 {
00111 BFT * TestBFT = new BFT( AdjList, i, NumNodes, TooWide );
00112 if( TestBFT->Depth() > bestDepth ||
00113 ( TestBFT->Depth() == bestDepth && TestBFT->Width() < bestWidth ) )
00114 {
00115 BestBFT = TestBFT;
00116 bestDepth = TestBFT->Depth();
00117 bestWidth = TestBFT->Width();
00118 }
00119 else
00120 delete TestBFT;
00121 }
00122 }
00123 else
00124 {
00125
00126 BestBFT = new BFT( AdjList, MinDegreeNode, NumNodes, TooWide );
00127
00128 int MinWidth = BestBFT->Width();
00129 int BestWidth = MinWidth;
00130 int Diameter = BestBFT->Depth();
00131 std::vector<int> Leaves;
00132 BestBFT->NonNeighborLeaves( Leaves, AdjList, testLeafWidth_ );
00133
00134 bool DeeperFound;
00135 bool NarrowerFound;
00136
00137 bool Finished = false;
00138
00139 while( !Finished )
00140 {
00141 DeeperFound = false;
00142 NarrowerFound = false;
00143
00144 for( int i = 0; i < Leaves.size(); ++i )
00145 {
00146
00147 BFT * TestBFT = new BFT( AdjList, Leaves[i], MinWidth, TooWide );
00148
00149 if( TooWide )
00150 delete TestBFT;
00151 else
00152 {
00153 if( TestBFT->Width() < MinWidth ) MinWidth = TestBFT->Width();
00154
00155 if( TestBFT->Depth() > Diameter )
00156 {
00157 delete BestBFT;
00158 Diameter = TestBFT->Depth();
00159 BestWidth = TestBFT->Width();
00160 BestBFT = TestBFT;
00161 DeeperFound = true;
00162 NarrowerFound = false;
00163 }
00164 else if( (TestBFT->Depth()==Diameter) && (TestBFT->Width()<BestWidth) )
00165 {
00166 delete BestBFT;
00167 BestWidth = TestBFT->Width();
00168 BestBFT = TestBFT;
00169 NarrowerFound = true;
00170 }
00171 else delete TestBFT;
00172 }
00173 }
00174
00175 if( DeeperFound )
00176 BestBFT->NonNeighborLeaves( Leaves, AdjList, testLeafWidth_ );
00177 else if( NarrowerFound )
00178 Finished = true;
00179 else Finished = true;
00180 }
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 std::vector<int> RCM;
00190 BestBFT->ReverseVector( RCM );
00191 for( int i = 0; i < NumNodes; ++i )
00192 RCM[i] = orig.RowMap().GID( RCM[i] );
00193
00194
00195 RCMMap_ = new Epetra_Map( orig.RowMap().NumGlobalElements(),
00196 NumNodes,
00197 &RCM[0],
00198 orig.RowMap().IndexBase(),
00199 orig.RowMap().Comm() );
00200
00201
00202 if( RCMMap_->DistributedGlobal() )
00203 {
00204 std::vector<int> colIndices = RCM;
00205 const Epetra_BlockMap & origColMap = orig.ColMap();
00206
00207 if( origColMap.NumMyElements() > RCMMap_->NumMyElements() )
00208 {
00209 for( int i = RCMMap_->NumMyElements(); i < origColMap.NumMyElements(); ++i )
00210 colIndices.push_back( origColMap.GID(i) );
00211 }
00212
00213 RCMColMap_ = new Epetra_Map( orig.ColMap().NumGlobalElements(),
00214 colIndices.size(),
00215 &colIndices[0],
00216 orig.ColMap().IndexBase(),
00217 orig.ColMap().Comm() );
00218 }
00219 else
00220 RCMColMap_ = RCMMap_;
00221
00222
00223 Epetra_Import Importer( *RCMMap_, orig.RowMap() );
00224 Epetra_CrsGraph * RCMGraph = new Epetra_CrsGraph( Copy, *RCMMap_, *RCMColMap_, 0 );
00225 RCMGraph->Import( orig, Importer, Insert );
00226 RCMGraph->FillComplete();
00227
00228
00229
00230
00231
00232
00233
00234
00235 newObj_ = RCMGraph;
00236
00237 return *RCMGraph;
00238 }
00239
00240 CrsGraph_SymmRCM::BFT::
00241 BFT( const std::vector< std::vector<int> > & adjlist,
00242 int root,
00243 int max_width,
00244 bool & failed )
00245 : width_(0),
00246 depth_(0),
00247 nodes_(adjlist.size()),
00248 failed_(false)
00249 {
00250 std::set<int> touchedNodes;
00251
00252
00253 levelSets_.push_back( std::vector<int>(1) );
00254 levelSets_[0][0] = root;
00255 ++depth_;
00256
00257
00258 touchedNodes.insert( root );
00259
00260 while( touchedNodes.size() < nodes_ )
00261 {
00262
00263 levelSets_.push_back( std::vector<int>() );
00264 ++depth_;
00265
00266 for( int i = 0; i < levelSets_[depth_-2].size(); ++i )
00267 {
00268 int currNode = levelSets_[depth_-2][i];
00269 int adjSize = adjlist[currNode].size();
00270 for( int j = 0; j < adjSize; ++j )
00271 {
00272
00273 int currAdj = adjlist[currNode][j];
00274 if( !touchedNodes.count( currAdj ) )
00275 {
00276 levelSets_[depth_-1].push_back( currAdj );
00277 touchedNodes.insert( currAdj );
00278 }
00279 }
00280 }
00281
00282 int currWidth = levelSets_[depth_-1].size();
00283
00284 if( currWidth )
00285 {
00286 if( currWidth > width_ ) width_ = currWidth;
00287
00288
00289 if( width_ > max_width )
00290 {
00291 failed_ = true;
00292 failed = failed_;
00293 return;
00294 }
00295
00296
00297 std::vector<int> degrees( currWidth );
00298 for( int i = 0; i < currWidth; ++i )
00299 degrees[i] = adjlist[ levelSets_[depth_-1][i] ].size();
00300 int ** indices = new int*[1];
00301 indices[0] = &(levelSets_[depth_-1][0]);
00302 Epetra_Util().Sort( true, currWidth, °rees[0], 0, 0, 1, indices );
00303 }
00304 else
00305 {
00306
00307 bool found = false;
00308 int minDegree = nodes_;
00309 int minDegreeNode;
00310 for( int i = 0; i < nodes_; ++i )
00311 {
00312 if( !touchedNodes.count( i ) && adjlist[i].size() < minDegree )
00313 {
00314 minDegree = adjlist[i].size();
00315 minDegreeNode = i;
00316 found = true;
00317 }
00318 }
00319
00320 if( found )
00321 {
00322 touchedNodes.insert( minDegreeNode );
00323 levelSets_[depth_-1].push_back( minDegreeNode );
00324 }
00325 else
00326 {
00327 --depth_;
00328 failed_ = true;
00329 failed = failed_;
00330 return;
00331 }
00332
00333 }
00334
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 failed = failed_;
00361 }
00362
00363 void
00364 CrsGraph_SymmRCM::BFT::
00365 NonNeighborLeaves( std::vector<int> & leaves,
00366 const std::vector< std::vector<int> > & adjlist,
00367 int count )
00368 {
00369 assert( (depth_>0) && (failed_==false) );
00370
00371 leaves.clear();
00372 int leafWidth = levelSets_[depth_-1].size();
00373 std::set<int> adjSeen;
00374 for( int i = 0; i < leafWidth; ++i )
00375 {
00376 int currLeaf = levelSets_[depth_-1][i];
00377 if( !adjSeen.count( currLeaf ) )
00378 {
00379 leaves.push_back( currLeaf );
00380 for( int j = 0; j < adjlist[currLeaf].size(); ++j )
00381 adjSeen.insert( adjlist[currLeaf][j] );
00382 }
00383 if( leaves.size() == count ) i = leafWidth;
00384 }
00385 }
00386
00387 void
00388 CrsGraph_SymmRCM::BFT::
00389 ReverseVector( std::vector<int> & ordered )
00390 {
00391 assert( (depth_>0) && (failed_==false) );
00392
00393 ordered.resize( nodes_ );
00394 int loc = 0;
00395 for( int i = 0; i < depth_; ++i )
00396 {
00397 int currLevel = depth_ - (i+1);
00398 int currWidth = levelSets_[currLevel].size();
00399 for( int j = 0; j < currWidth; ++j )
00400 ordered[loc++] = levelSets_[currLevel][currWidth-j-1];
00401 }
00402 }
00403
00404 }
00405 #endif //HAVE_GRAPH_REORDERINGS
00406 #endif //HAVE_EXPERIMENTAL