Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Zoltan2_AlgSerialGreedy.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Zoltan2: A package of combinatorial algorithms for scientific computing
4 //
5 // Copyright 2012 NTESS and the Zoltan2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef _ZOLTAN2_ALGSERIALGREEDY_HPP_
11 #define _ZOLTAN2_ALGSERIALGREEDY_HPP_
12 
13 #include <Zoltan2_Algorithm.hpp>
14 #include <Zoltan2_GraphModel.hpp>
16 
20 
21 namespace Zoltan2{
22 
23 template <typename Adapter>
24 class AlgSerialGreedy : public Algorithm<Adapter>
25 {
26  private:
27  typedef typename Adapter::lno_t lno_t;
28  typedef typename Adapter::gno_t gno_t;
29  typedef typename Adapter::offset_t offset_t;
30  typedef typename Adapter::scalar_t scalar_t;
31  // Class member variables
32  const RCP<const typename Adapter::base_adapter_t> adapter_;
33  RCP<Teuchos::ParameterList> pl_;
34  RCP<Environment> env_;
35  RCP<const Teuchos::Comm<int> > comm_;
36  modelFlag_t graphFlags_;
37 
38  public:
40  const RCP<const typename Adapter::base_adapter_t> &adapter,
41  const RCP<Teuchos::ParameterList> &pl,
42  const RCP<Environment> &env,
43  const RCP<const Teuchos::Comm<int> > &comm,
44  modelFlag_t graphFlags
45  ) : adapter_(adapter), pl_(pl), env_(env), comm_(comm), graphFlags_(graphFlags)
46  {
47  }
48 
49  // Main entry point for graph coloring.
50  void color(
51  const RCP<ColoringSolution<Adapter> > &solution
52  )
53  {
54  HELLO;
55 
56  // Color local graph. Global coloring is supported in Zoltan (not Zoltan2).
57  // Get local graph.
58  ArrayView<const gno_t> edgeIds;
59  ArrayView<const offset_t> offsets;
60  ArrayView<StridedData<lno_t, scalar_t> > wgts; // Not used; needed by getLocalEdgeList
61 
62  const auto model = rcp(new GraphModel<typename Adapter::base_adapter_t>(adapter_, env_, comm_, graphFlags_));
63  const size_t nVtx = model->getLocalNumVertices(); // Assume (0,nvtx-1)
64  model->getEdgeList(edgeIds, offsets, wgts); // Don't need wgts
65 
66 #if 0
67  // Debug
68  cout << "Debug: Local graph from getLocalEdgeList" << endl;
69  cout << "rank " << comm_->getRank() << ": nVtx= " << nVtx << endl;
70  cout << "rank " << comm_->getRank() << ": edgeIds: " << edgeIds << endl;
71  cout << "rank " << comm_->getRank() << ": offsets: " << offsets << endl;
72 #endif
73 
74  // Get color array to fill.
75  // TODO: Allow user to input an old coloring.
76  ArrayRCP<int> colors = solution->getColorsRCP();
77  for (size_t i=0; i<nVtx; i++){
78  colors[i] = 0;
79  }
80 
81  // Let colorCrsGraph do the real work.
82  env_->timerStart(MACRO_TIMERS, "Coloring algorithm");
83  colorCrsGraph(nVtx, edgeIds, offsets, colors);
84  env_->timerStop(MACRO_TIMERS, "Coloring algorithm");
85  return;
86  }
87 
88  // Color graph given by two arrays. API may change. Expert users only!
90  const size_t nVtx,
91  ArrayView<const gno_t> edgeIds,
92  ArrayView<const offset_t> offsets,
93  ArrayRCP<int> colors
94  )
95  {
96  HELLO;
97 
98  // Find max degree, since (max degree)+1 is an upper bound.
99  offset_t maxDegree = 0;
100  for (size_t i=0; i<nVtx; i++){
101  if (offsets[i+1]-offsets[i] > maxDegree)
102  maxDegree = offsets[i+1]-offsets[i];
103  }
104 
105  // Greedy coloring.
106  // Use natural order for now.
107  // TODO: Support better orderings (e.g., Smallest-Last)
108  int maxColor = 0;
109 
110  // array of size #colors: forbidden[i]=v means color[v]=i so i is forbidden
111  Teuchos::Array<int> forbidden(maxDegree+2, 0);
112 
113  // LeastUsed: need array of size #colors
114  Teuchos::Array<lno_t> numVerticesWithColor(maxDegree+2, 0);
115 
116  // Get colorChoice from parameter list.
117  Teuchos::ParameterList &pl = env_->getParametersNonConst();
118  std::string colorChoice = pl.get<std::string>("color_choice", "FirstFit");
119 
120  for (size_t i=0; i<nVtx; i++){
121  //std::cout << "Debug: i= " << i << std::endl;
122  lno_t v=i; // TODO: Use ordering here.
123  for (offset_t j=offsets[v]; j<offsets[v+1]; j++){
124  gno_t nbor = edgeIds[j];
125  //std::cout << "Debug: nbor= " << nbor << ", color= " << colors[nbor] << std::endl;
126  if (colors[nbor] > 0){
127  // Neighbors' colors are forbidden
128  forbidden[colors[nbor]] = v;
129  }
130  }
131 
132  // Pick color for v
133 
134  // Keep colors[v] if possible, otherwise find valid color.
135  if ((colors[v]==0) || ((colors[v]>0) && forbidden[colors[v]] == v)){
136 
137  if (colorChoice.compare("FirstFit")){
138  // Pick first (smallest) available color > 0
139  for (int c=1; c <= maxColor+1; c++){
140  if (forbidden[c] != v){
141  colors[v] = c;
142  break;
143  }
144  }
145  }
146  else if (colorChoice.compare("Random")){
147  // Pick random available color.
148  // Truely random is slow, please consider RandomFast instead.
149  int numAvail = 0;
150  Teuchos::Array<int> avail(maxColor+1);
151  for (int c=1; c < maxColor+1; c++){
152  if (forbidden[c] != v){
153  avail[numAvail++] = c;
154  }
155  }
156  if (numAvail==0)
157  colors[v] = maxColor+1;
158  else
159  colors[v] = avail[rand()%numAvail];
160  }
161  else if (colorChoice.compare("RandomFast")){
162  // Pick random color, then find first available color after that.
163  bool foundColor = false;
164  int r = (rand() % maxColor) +1;
165  for (int c=r; c <= maxColor; c++){
166  if (forbidden[c] != v){
167  colors[v] = c;
168  foundColor = true;
169  break;
170  }
171  }
172  if (!foundColor){ // Look for colors in [1, r)
173  for (int c=1; c < r; c++){
174  if (forbidden[c] != v){
175  colors[v] = c;
176  foundColor = true;
177  break;
178  }
179  }
180  }
181  if (!foundColor) colors[v] = maxColor+1;
182  }
183  else if (colorChoice.compare("LeastUsed")){
184  // Pick least used available color.
185  // Simple linear algorithm; could maintain a priority queue but not sure any faster?
186  int leastUsedColor = 1;
187  for (int c=1; c <= maxColor; c++){
188  if (forbidden[c] != v){
189  if (numVerticesWithColor[c] < leastUsedColor){
190  leastUsedColor = c;
191  }
192  }
193  }
194  colors[v] = leastUsedColor;
195 
196  // Update color counts
197  numVerticesWithColor[colors[v]]++;
198  }
199 
200  if ((v==0) && colors[v]==0) colors[v]=1; // Corner case for first vertex
201 
202  // If we used a new color, increase maxColor.
203  if (colors[v] > maxColor){
204  maxColor = colors[v];
205  }
206  }
207  }
208 
209  return;
210  }
211 
214  static void getValidParameters(ParameterList & pl)
215  {
216  RCP<Teuchos::StringValidator> color_choice_Validator = Teuchos::rcp(
217  new Teuchos::StringValidator(
218  Teuchos::tuple<std::string>(
219  "FirstFit", "Random", "RandomFast", "LeastUsed" )));
220  pl.set("color_choice", "FirstFit", "selection criterion for coloring",
221  color_choice_Validator);
222  }
223 };
224 }
225 #endif
#define HELLO
Time an algorithm (or other entity) as a whole.
std::bitset< NUM_MODEL_FLAGS > modelFlag_t
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:27
void color(const RCP< ColoringSolution< Adapter > > &solution)
Coloring method.
Algorithm defines the base class for all algorithms.
map_t::local_ordinal_type lno_t
Definition: mapRemotes.cpp:26
GraphModel defines the interface required for graph models.
Defines the ColoringSolution class.
Defines the GraphModel interface.
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm.
AlgSerialGreedy(const RCP< const typename Adapter::base_adapter_t > &adapter, const RCP< Teuchos::ParameterList > &pl, const RCP< Environment > &env, const RCP< const Teuchos::Comm< int > > &comm, modelFlag_t graphFlags)
void colorCrsGraph(const size_t nVtx, ArrayView< const gno_t > edgeIds, ArrayView< const offset_t > offsets, ArrayRCP< int > colors)
The class containing coloring solution.