17 #ifndef dealii_graph_coloring_h 18 #define dealii_graph_coloring_h 21 #include <deal.II/base/config.h> 22 #include <deal.II/base/thread_management.h> 23 #include <boost/unordered_map.hpp> 24 #include <boost/unordered_set.hpp> 25 #include <deal.II/lac/sparsity_tools.h> 32 DEAL_II_NAMESPACE_OPEN
52 have_nonempty_intersection (
const std::vector<types::global_dof_index> &indices1,
53 const std::vector<types::global_dof_index> &indices2)
59 std::vector<types::global_dof_index>::const_iterator
62 while ((p != indices1.end()) && (q != indices2.end()))
108 template <
typename Iterator>
109 std::vector<std::vector<Iterator> >
110 create_partitioning(
const Iterator &begin,
111 const typename identity<Iterator>::type &end,
112 const std::function<std::vector<types::global_dof_index> (
const Iterator &)> &get_conflict_indices)
115 unsigned int n_iterators = 0;
118 boost::unordered_map<types::global_dof_index,std::vector<Iterator> > indices_to_iterators;
119 for (Iterator it=begin; it!=end; ++it)
121 const std::vector<types::global_dof_index> conflict_indices = get_conflict_indices(it);
122 const unsigned int n_conflict_indices = conflict_indices.size();
123 for (
unsigned int i=0; i<n_conflict_indices; ++i)
124 indices_to_iterators[conflict_indices[i]].push_back(it);
131 std::vector<std::vector<Iterator> > zones(1,std::vector<Iterator> (1,begin));
132 std::set<Iterator> used_it;
133 used_it.insert(begin);
134 while (used_it.size()!=n_iterators)
139 typename std::vector<Iterator>::iterator previous_zone_it(zones.back().begin());
140 typename std::vector<Iterator>::iterator previous_zone_end(zones.back().end());
141 std::vector<Iterator> new_zone;
142 for (; previous_zone_it!=previous_zone_end; ++previous_zone_it)
144 const std::vector<types::global_dof_index>
145 conflict_indices = get_conflict_indices(*previous_zone_it);
147 const unsigned int n_conflict_indices(conflict_indices.size());
148 for (
unsigned int i=0; i<n_conflict_indices; ++i)
150 const std::vector<Iterator> &conflicting_elements
151 = indices_to_iterators[conflict_indices[i]];
152 for (
unsigned int j=0; j<conflicting_elements.size(); ++j)
160 if ((conflicting_elements[j] != *previous_zone_it)
162 (used_it.count(conflicting_elements[j])==0))
164 new_zone.push_back(conflicting_elements[j]);
165 used_it.insert(conflicting_elements[j]);
175 if (new_zone.size()!=0)
176 zones.push_back(new_zone);
178 for (Iterator it=begin; it!=end; ++it)
179 if (used_it.count(it)==0)
181 zones.push_back(std::vector<Iterator> (1,it));
211 template <
typename Iterator>
213 make_dsatur_coloring(std::vector<Iterator> &partition,
214 const std::function<std::vector<types::global_dof_index> (
const Iterator &)> &get_conflict_indices,
215 std::vector<std::vector<Iterator> > &partition_coloring)
217 partition_coloring.clear ();
220 const unsigned int partition_size(partition.size());
221 std::vector<unsigned int> sorted_vertices(partition_size);
222 std::vector<int> degrees(partition_size);
223 std::vector<std::vector<types::global_dof_index> > conflict_indices(partition_size);
224 std::vector<std::vector<unsigned int> > graph(partition_size);
228 for (
unsigned int i=0; i<partition_size; ++i)
230 conflict_indices[i] = get_conflict_indices(partition[i]);
231 std::sort(conflict_indices[i].begin(), conflict_indices[i].end());
236 for (
unsigned int i=0; i<partition_size; ++i)
237 for (
unsigned int j=i+1; j<partition_size; ++j)
240 if (have_nonempty_intersection (conflict_indices[i], conflict_indices[j]))
244 graph[i].push_back(j);
245 graph[j].push_back(i);
249 std::vector<int>::iterator degrees_it;
250 for (
unsigned int i=0; i<partition_size; ++i)
253 degrees_it = std::max_element(degrees.begin(),degrees.end());
254 sorted_vertices[i] = degrees_it-degrees.begin();
260 std::vector<boost::unordered_set<unsigned int> > colors_used;
261 for (
unsigned int i=0; i<partition_size; ++i)
263 const unsigned int current_vertex(sorted_vertices[i]);
264 bool new_color(
true);
268 for (
unsigned int j=0; j<partition_coloring.size(); ++j)
273 bool unused_color(
true);
274 for (
unsigned int k=0; k<graph[current_vertex].size(); ++k)
275 if (colors_used[j].count(graph[current_vertex][k])==1)
277 unused_color =
false;
282 partition_coloring[j].push_back(partition[current_vertex]);
283 colors_used[j].insert(current_vertex);
291 partition_coloring.push_back(std::vector<Iterator> (1,
292 partition[current_vertex]));
293 boost::unordered_set<unsigned int> tmp;
294 tmp.insert(current_vertex);
295 colors_used.push_back(tmp);
311 template <
typename Iterator>
312 std::vector<std::vector<Iterator> >
313 gather_colors(
const std::vector<std::vector<std::vector<Iterator> > > &partition_coloring)
315 std::vector<std::vector<Iterator> > coloring;
318 const unsigned int partition_size(partition_coloring.size());
319 std::vector<std::vector<unsigned int> > colors_counter(partition_size);
320 for (
unsigned int i=0; i<partition_size; ++i)
322 const unsigned int n_colors(partition_coloring[i].size());
323 colors_counter[i].resize(n_colors);
324 for (
unsigned int j=0; j<n_colors; ++j)
325 colors_counter[i][j] = partition_coloring[i][j].size();
329 unsigned int i_color(0);
330 unsigned int max_even_n_colors(0);
331 const unsigned int colors_size(colors_counter.size());
332 for (
unsigned int i=0; i<colors_size; i+=2)
334 if (max_even_n_colors<colors_counter[i].size())
336 max_even_n_colors = colors_counter[i].size();
340 coloring.resize(max_even_n_colors);
341 for (
unsigned int j=0; j<colors_counter[i_color].size(); ++j)
342 coloring[j] = partition_coloring[i_color][j];
344 for (
unsigned int i=0; i<partition_size; i+=2)
348 boost::unordered_set<unsigned int> used_k;
349 for (
unsigned int j=0; j<colors_counter[i].size(); ++j)
353 std::vector<unsigned int>::iterator it;
354 it = std::max_element(colors_counter[i].begin(),colors_counter[i].end());
355 unsigned int min_iterators (static_cast<unsigned int>(-1));
359 for (
unsigned int k=0; k<max_even_n_colors; ++k)
360 if (used_k.count(k)==0)
361 if (colors_counter[i_color][k]<min_iterators)
363 min_iterators = colors_counter[i_color][k];
366 colors_counter[i_color][pos] += *it;
368 coloring[pos].insert(coloring[pos].end(),
369 partition_coloring[i][it-colors_counter[i].begin()].begin(),
370 partition_coloring[i][it-colors_counter[i].begin()].end());
380 if (partition_size>1)
382 unsigned int max_odd_n_colors(0);
383 for (
unsigned int i=1; i<partition_size; i+=2)
385 if (max_odd_n_colors<colors_counter[i].size())
387 max_odd_n_colors = colors_counter[i].size();
391 coloring.resize(max_even_n_colors+max_odd_n_colors);
392 for (
unsigned int j=0; j<colors_counter[i_color].size(); ++j)
393 coloring[max_even_n_colors+j] = partition_coloring[i_color][j];
395 for (
unsigned int i=1; i<partition_size; i+=2)
399 boost::unordered_set<unsigned int> used_k;
400 for (
unsigned int j=0; j<colors_counter[i].size(); ++j)
404 std::vector<unsigned int>::iterator it;
405 it = std::max_element(colors_counter[i].begin(),colors_counter[i].end());
406 unsigned int min_iterators(static_cast<unsigned int>(-1));
410 for (
unsigned int k=0; k<max_odd_n_colors; ++k)
411 if (used_k.count(k)==0)
412 if (colors_counter[i_color][k]<min_iterators)
414 min_iterators = colors_counter[i_color][k];
417 colors_counter[i_color][pos] += *it;
419 coloring[max_even_n_colors+pos].insert(coloring[max_even_n_colors+pos].end(),
420 partition_coloring[i][it-colors_counter[i].begin()].begin(),
421 partition_coloring[i][it-colors_counter[i].begin()].end());
514 template <
typename Iterator>
515 std::vector<std::vector<Iterator> >
517 const typename identity<Iterator>::type &end,
518 const std::function<std::vector<types::global_dof_index> (
const typename identity<Iterator>::type &)> &get_conflict_indices)
520 Assert (begin != end,
ExcMessage (
"GraphColoring is not prepared to deal with empty ranges!"));
523 std::vector<std::vector<Iterator> >
524 partitioning = internal::create_partitioning (begin,
526 get_conflict_indices);
530 const unsigned int partitioning_size(partitioning.size());
531 std::vector<std::vector<std::vector<Iterator> > >
532 partition_coloring(partitioning_size);
535 for (
unsigned int i=0; i<partitioning_size; ++i)
538 get_conflict_indices,
539 partition_coloring[i]);
543 return internal::gather_colors(partition_coloring);
553 std::vector<unsigned int> &color_indices);
557 DEAL_II_NAMESPACE_CLOSE
Task< RT > new_task(const std::function< RT()> &function)
std::vector< std::vector< Iterator > > make_graph_coloring(const Iterator &begin, const typename identity< Iterator >::type &end, const std::function< std::vector< types::global_dof_index >(const typename identity< Iterator >::type &)> &get_conflict_indices)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
unsigned int color_sparsity_pattern(const SparsityPattern &sparsity_pattern, std::vector< unsigned int > &color_indices)