17#ifndef dealii_graph_coloring_h
18# define dealii_graph_coloring_h
28# include <unordered_map>
29# include <unordered_set>
55 const std::vector<types::global_dof_index> &indices1,
56 const std::vector<types::global_dof_index> &indices2)
62 std::vector<types::global_dof_index>::const_iterator p = indices1.begin(),
64 while ((p != indices1.end()) && (q != indices2.end()))
108 template <
typename Iterator>
109 std::vector<std::vector<Iterator>>
111 const Iterator & begin,
113 const std::function<std::vector<types::global_dof_index>(
114 const Iterator &)> & get_conflict_indices)
117 unsigned int n_iterators = 0;
120 std::unordered_map<types::global_dof_index, std::vector<Iterator>>
121 indices_to_iterators;
122 for (Iterator it = begin; it != end; ++it)
124 const std::vector<types::global_dof_index> conflict_indices =
125 get_conflict_indices(it);
126 const unsigned int n_conflict_indices = conflict_indices.size();
127 for (
unsigned int i = 0; i < n_conflict_indices; ++i)
128 indices_to_iterators[conflict_indices[i]].push_back(it);
135 std::vector<std::vector<Iterator>> zones(1,
136 std::vector<Iterator>(1, begin));
137 std::set<Iterator> used_it;
138 used_it.insert(begin);
139 while (used_it.size() != n_iterators)
144 typename std::vector<Iterator>::iterator previous_zone_it(
145 zones.back().begin());
146 typename std::vector<Iterator>::iterator previous_zone_end(
148 std::vector<Iterator> new_zone;
149 for (; previous_zone_it != previous_zone_end; ++previous_zone_it)
151 const std::vector<types::global_dof_index> conflict_indices =
152 get_conflict_indices(*previous_zone_it);
154 const unsigned int n_conflict_indices(conflict_indices.size());
155 for (
unsigned int i = 0; i < n_conflict_indices; ++i)
157 const std::vector<Iterator> &conflicting_elements =
158 indices_to_iterators[conflict_indices[i]];
159 for (
unsigned int j = 0; j < conflicting_elements.size(); ++j)
167 if ((conflicting_elements[j] != *previous_zone_it) &&
168 (used_it.count(conflicting_elements[j]) == 0))
170 new_zone.push_back(conflicting_elements[j]);
171 used_it.insert(conflicting_elements[j]);
182 if (new_zone.size() != 0)
183 zones.push_back(new_zone);
185 for (Iterator it = begin; it != end; ++it)
186 if (used_it.count(it) == 0)
188 zones.push_back(std::vector<Iterator>(1, it));
221 template <
typename Iterator>
224 std::vector<Iterator> & partition,
225 const std::function<std::vector<types::global_dof_index>(
226 const Iterator &)> & get_conflict_indices,
227 std::vector<std::vector<Iterator>> &partition_coloring)
229 partition_coloring.clear();
232 const unsigned int partition_size(partition.size());
233 std::vector<unsigned int> sorted_vertices(partition_size);
234 std::vector<int> degrees(partition_size);
235 std::vector<std::vector<types::global_dof_index>> conflict_indices(
237 std::vector<std::vector<unsigned int>> graph(partition_size);
242 for (
unsigned int i = 0; i < partition_size; ++i)
244 conflict_indices[i] = get_conflict_indices(partition[i]);
245 std::sort(conflict_indices[i].begin(), conflict_indices[i].end());
250 for (
unsigned int i = 0; i < partition_size; ++i)
251 for (
unsigned int j = i + 1; j < partition_size; ++j)
255 conflict_indices[j]))
259 graph[i].push_back(j);
260 graph[j].push_back(i);
264 std::vector<int>::iterator degrees_it;
265 for (
unsigned int i = 0; i < partition_size; ++i)
268 degrees_it = std::max_element(degrees.begin(), degrees.end());
269 sorted_vertices[i] = degrees_it - degrees.begin();
275 std::vector<std::unordered_set<unsigned int>> colors_used;
276 for (
unsigned int i = 0; i < partition_size; ++i)
278 const unsigned int current_vertex(sorted_vertices[i]);
279 bool new_color(
true);
283 for (
unsigned int j = 0; j < partition_coloring.size(); ++j)
288 bool unused_color(
true);
289 for (
const auto adjacent_vertex : graph[current_vertex])
290 if (colors_used[j].count(adjacent_vertex) == 1)
292 unused_color =
false;
297 partition_coloring[j].push_back(partition[current_vertex]);
298 colors_used[j].insert(current_vertex);
306 partition_coloring.push_back(
307 std::vector<Iterator>(1, partition[current_vertex]));
308 std::unordered_set<unsigned int> tmp;
309 tmp.insert(current_vertex);
310 colors_used.push_back(tmp);
326 template <
typename Iterator>
327 std::vector<std::vector<Iterator>>
329 const std::vector<std::vector<std::vector<Iterator>>> &partition_coloring)
331 std::vector<std::vector<Iterator>> coloring;
334 const unsigned int partition_size(partition_coloring.size());
335 std::vector<std::vector<unsigned int>> colors_counter(partition_size);
336 for (
unsigned int i = 0; i < partition_size; ++i)
338 const unsigned int n_colors(partition_coloring[i].size());
339 colors_counter[i].resize(n_colors);
340 for (
unsigned int j = 0; j < n_colors; ++j)
341 colors_counter[i][j] = partition_coloring[i][j].size();
346 unsigned int i_color(0);
347 unsigned int max_even_n_colors(0);
348 const unsigned int colors_size(colors_counter.size());
349 for (
unsigned int i = 0; i < colors_size; i += 2)
351 if (max_even_n_colors < colors_counter[i].size())
353 max_even_n_colors = colors_counter[i].size();
357 coloring.resize(max_even_n_colors);
358 for (
unsigned int j = 0; j < colors_counter[i_color].size(); ++j)
359 coloring[j] = partition_coloring[i_color][j];
361 for (
unsigned int i = 0; i < partition_size; i += 2)
365 std::unordered_set<unsigned int> used_k;
366 for (
unsigned int j = 0; j < colors_counter[i].size(); ++j)
370 std::vector<unsigned int>::iterator it;
371 it = std::max_element(colors_counter[i].begin(),
372 colors_counter[i].end());
373 unsigned int min_iterators(
static_cast<unsigned int>(-1));
377 for (
unsigned int k = 0; k < max_even_n_colors; ++k)
378 if (used_k.count(k) == 0)
379 if (colors_counter[i_color][k] < min_iterators)
381 min_iterators = colors_counter[i_color][k];
384 colors_counter[i_color][pos] += *it;
386 coloring[pos].insert(
388 partition_coloring[i][it - colors_counter[i].begin()]
390 partition_coloring[i][it - colors_counter[i].begin()]
401 if (partition_size > 1)
403 unsigned int max_odd_n_colors(0);
404 for (
unsigned int i = 1; i < partition_size; i += 2)
406 if (max_odd_n_colors < colors_counter[i].size())
408 max_odd_n_colors = colors_counter[i].size();
412 coloring.resize(max_even_n_colors + max_odd_n_colors);
413 for (
unsigned int j = 0; j < colors_counter[i_color].size(); ++j)
414 coloring[max_even_n_colors + j] = partition_coloring[i_color][j];
416 for (
unsigned int i = 1; i < partition_size; i += 2)
420 std::unordered_set<unsigned int> used_k;
421 for (
unsigned int j = 0; j < colors_counter[i].size(); ++j)
425 std::vector<unsigned int>::iterator it;
426 it = std::max_element(colors_counter[i].begin(),
427 colors_counter[i].end());
428 unsigned int min_iterators(
static_cast<unsigned int>(-1));
432 for (
unsigned int k = 0; k < max_odd_n_colors; ++k)
433 if (used_k.count(k) == 0)
434 if (colors_counter[i_color][k] < min_iterators)
436 min_iterators = colors_counter[i_color][k];
439 colors_counter[i_color][pos] += *it;
442 coloring[max_even_n_colors + pos].insert(
443 coloring[max_even_n_colors + pos].end(),
444 partition_coloring[i][it - colors_counter[i].begin()]
446 partition_coloring[i][it - colors_counter[i].begin()]
539 template <
typename Iterator>
540 std::vector<std::vector<Iterator>>
542 const Iterator & begin,
544 const std::function<std::vector<types::global_dof_index>(
549 "GraphColoring is not prepared to deal with empty ranges!"));
552 std::vector<std::vector<Iterator>> partitioning =
557 const unsigned int partitioning_size(partitioning.size());
558 std::vector<std::vector<std::vector<Iterator>>> partition_coloring(
562 for (
unsigned int i = 0; i < partitioning_size; ++i)
565 get_conflict_indices,
566 partition_coloring[i]);
581 std::vector<unsigned int> &color_indices);
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
static ::ExceptionBase & ExcMessage(std::string arg1)
Task< RT > new_task(const std::function< RT()> &function)
std::vector< std::vector< Iterator > > gather_colors(const std::vector< std::vector< std::vector< Iterator > > > &partition_coloring)
std::vector< std::vector< Iterator > > create_partitioning(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, const std::function< std::vector< types::global_dof_index >(const Iterator &)> &get_conflict_indices)
bool have_nonempty_intersection(const std::vector< types::global_dof_index > &indices1, const std::vector< types::global_dof_index > &indices2)
void make_dsatur_coloring(std::vector< Iterator > &partition, const std::function< std::vector< types::global_dof_index >(const Iterator &)> &get_conflict_indices, std::vector< std::vector< Iterator > > &partition_coloring)
std::vector< std::vector< Iterator > > make_graph_coloring(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, const std::function< std::vector< types::global_dof_index >(const std_cxx20::type_identity_t< Iterator > &)> &get_conflict_indices)
unsigned int color_sparsity_pattern(const SparsityPattern &sparsity_pattern, std::vector< unsigned int > &color_indices)
typename type_identity< T >::type type_identity_t