|
Zoltan2
|
00001 // @HEADER 00002 // 00003 // *********************************************************************** 00004 // 00005 // Zoltan2: A package of combinatorial algorithms for scientific computing 00006 // Copyright 2012 Sandia Corporation 00007 // 00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00009 // the U.S. Government retains certain rights in this software. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact Karen Devine (kddevin@sandia.gov) 00039 // Erik Boman (egboman@sandia.gov) 00040 // Siva Rajamanickam (srajama@sandia.gov) 00041 // 00042 // *********************************************************************** 00043 // 00044 // @HEADER 00045 #ifndef _ZOLTAN2_ALGSERIALGREEDY_HPP_ 00046 #define _ZOLTAN2_ALGSERIALGREEDY_HPP_ 00047 00048 #include <Zoltan2_Algorithm.hpp> 00049 #include <Zoltan2_GraphModel.hpp> 00050 #include <Zoltan2_ColoringSolution.hpp> 00051 00055 00056 namespace Zoltan2{ 00057 00058 template <typename Adapter> 00059 class AlgSerialGreedy : public Algorithm<Adapter> 00060 { 00061 private: 00062 typedef typename Adapter::lno_t lno_t; 00063 typedef typename Adapter::gno_t gno_t; 00064 typedef typename Adapter::scalar_t scalar_t; 00065 // Class member variables 00066 RCP<GraphModel<typename Adapter::base_adapter_t> > model_; 00067 RCP<Teuchos::ParameterList> pl_; 00068 RCP<Environment> env_; 00069 RCP<Teuchos::Comm<int> > comm_; 00070 00071 public: 00072 AlgSerialGreedy( 00073 const RCP<GraphModel<typename Adapter::base_adapter_t> > &model, 00074 const RCP<Teuchos::ParameterList> &pl, 00075 const RCP<Environment> &env, 00076 const RCP<Teuchos::Comm<int> > &comm 00077 ) : model_(model), pl_(pl), env_(env), comm_(comm) 00078 { 00079 } 00080 00081 // Main entry point for graph coloring. 00082 void color( 00083 const RCP<ColoringSolution<Adapter> > &solution 00084 ) 00085 { 00086 HELLO; 00087 00088 // Color local graph. Global coloring is supported in Zoltan (not Zoltan2). 00089 // Get local graph. 00090 ArrayView<const lno_t> edgeIds; 00091 ArrayView<const lno_t> offsets; 00092 ArrayView<StridedData<lno_t, scalar_t> > wgts; // Not used; needed by getLocalEdgeList 00093 00094 const lno_t nVtx = model_->getLocalNumVertices(); // Assume (0,nvtx-1) 00095 model_->getLocalEdgeList(edgeIds, offsets, wgts); // Don't need wgts 00096 00097 #if 0 00098 // Debug 00099 cout << "Debug: Local graph from getLocalEdgeList" << endl; 00100 cout << "rank " << comm_->getRank() << ": nVtx= " << nVtx << endl; 00101 cout << "rank " << comm_->getRank() << ": edgeIds: " << edgeIds << endl; 00102 cout << "rank " << comm_->getRank() << ": offsets: " << offsets << endl; 00103 #endif 00104 00105 // Get color array to fill. 00106 // TODO: Allow user to input an old coloring. 00107 ArrayRCP<int> colors = solution->getColorsRCP(); 00108 for (lno_t i=0; i<nVtx; i++){ 00109 colors[i] = 0; 00110 } 00111 00112 // Let colorCrsGraph do the real work. 00113 env_->timerStart(MACRO_TIMERS, "Coloring algorithm"); 00114 colorCrsGraph(nVtx, edgeIds, offsets, colors); 00115 env_->timerStop(MACRO_TIMERS, "Coloring algorithm"); 00116 return; 00117 } 00118 00119 // Color graph given by two arrays. API may change. Expert users only! 00120 void colorCrsGraph( 00121 const lno_t nVtx, 00122 ArrayView<const lno_t> edgeIds, 00123 ArrayView<const lno_t> offsets, 00124 ArrayRCP<int> colors 00125 ) 00126 { 00127 HELLO; 00128 00129 // Find max degree, since (max degree)+1 is an upper bound. 00130 lno_t maxDegree = 0; 00131 for (lno_t i=0; i<nVtx; i++){ 00132 if (offsets[i+1]-offsets[i] > maxDegree) 00133 maxDegree = offsets[i+1]-offsets[i]; 00134 } 00135 00136 // Greedy coloring. 00137 // Use natural order for now. 00138 // TODO: Support better orderings (e.g., Smallest-Last) 00139 int maxColor = 0; 00140 00141 // array of size #colors: forbidden[i]=v means color[v]=i so i is forbidden 00142 Teuchos::Array<int> forbidden(maxDegree+2, 0); 00143 00144 // LeastUsed: need array of size #colors 00145 Teuchos::Array<lno_t> numVerticesWithColor(maxDegree+2, 0); 00146 00147 for (lno_t i=0; i<nVtx; i++){ 00148 //std::cout << "Debug: i= " << i << std::endl; 00149 lno_t v=i; // TODO: Use ordering here. 00150 for (lno_t j=offsets[v]; j<offsets[v+1]; j++){ 00151 lno_t nbor = edgeIds[j]; 00152 //std::cout << "Debug: nbor= " << nbor << ", color= " << colors[nbor] << std::endl; 00153 if (colors[nbor] > 0){ 00154 // Neighbors' colors are forbidden 00155 forbidden[colors[nbor]] = v; 00156 } 00157 } 00158 00159 // Pick color for v 00160 std::string colorChoice = "FirstFit"; // TODO make parameter! 00161 00162 // Keep colors[v] if possible, otherwise find valid color. 00163 if ((colors[v]==0) || ((colors[v]>0) && forbidden[colors[v]] == v)){ 00164 00165 if (colorChoice.compare("FirstFit")){ 00166 // Pick first (smallest) available color > 0 00167 for (int c=1; c <= maxColor+1; c++){ 00168 if (forbidden[c] != v){ 00169 colors[v] = c; 00170 break; 00171 } 00172 } 00173 } 00174 else if (colorChoice.compare("Random")){ 00175 // Pick random available color. 00176 // This is slow, please consider RandomFast instead. 00177 int numAvail = 0; 00178 Teuchos::Array<int> avail(maxColor+1); 00179 for (int c=1; c < maxColor+1; c++){ 00180 if (forbidden[c] != v){ 00181 avail[numAvail++] = c; 00182 } 00183 } 00184 if (numAvail==0) 00185 colors[v] = maxColor+1; 00186 else 00187 colors[v] = avail[rand()%numAvail]; 00188 } 00189 else if (colorChoice.compare("RandomFast")){ 00190 // Pick random color, then find first available color after that. 00191 bool foundColor = false; 00192 int r = (rand() % maxColor) +1; 00193 for (int c=r; c <= maxColor; c++){ 00194 if (forbidden[c] != v){ 00195 colors[v] = c; 00196 foundColor = true; 00197 break; 00198 } 00199 } 00200 if (!foundColor){ // Look for colors in [1, r) 00201 for (int c=1; c < r; c++){ 00202 if (forbidden[c] != v){ 00203 colors[v] = c; 00204 foundColor = true; 00205 break; 00206 } 00207 } 00208 } 00209 if (!foundColor) colors[v] = maxColor+1; 00210 } 00211 else if (colorChoice.compare("LeastUsed")){ 00212 // Pick least used available color. 00213 // Simple linear algorithm; could maintain a priority queue but not sure any faster? 00214 int leastUsedColor = 1; 00215 lno_t leastUsedNumber = numVerticesWithColor[1]; 00216 for (int c=1; c <= maxColor; c++){ 00217 if (forbidden[c] != v){ 00218 if (numVerticesWithColor[c] < leastUsedColor){ 00219 leastUsedColor = c; 00220 leastUsedNumber = numVerticesWithColor[c]; 00221 } 00222 } 00223 } 00224 colors[v] = leastUsedColor; 00225 00226 // Update color counts 00227 numVerticesWithColor[colors[v]]++; 00228 } 00229 00230 if ((v==0) && colors[v]==0) colors[v]=1; // Corner case for first vertex 00231 00232 // If we used a new color, increase maxColor. 00233 if (colors[v] > maxColor){ 00234 maxColor = colors[v]; 00235 } 00236 } 00237 } 00238 00239 return; 00240 } 00241 00242 }; 00243 } 00244 #endif
1.7.6.1