dune-assembler 2.12
Loading...
Searching...
No Matches
graphcoloring.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
3
4#ifndef DUNE_ASSEMBLER_PARALLEL_GRAPHCOLORING_HH
5#define DUNE_ASSEMBLER_PARALLEL_GRAPHCOLORING_HH
6
7#include <algorithm>
8#include <initializer_list>
9#include <limits>
10#include <queue>
11#include <type_traits>
12#include <utility>
13#include <vector>
14
16
18
19
20
47template <class Adjacency, class SeedNodesContainer>
49{
50
51 // Hack to access i-th entry without adjacency[i].
52 // This is necessary to support TransformedRangeView,
53 // because the latter does not provide operator[]
54 // in dune-2.9 although the range is random-access.
55 auto adjacentNodes = [&](auto i) {
56 return adjacency.begin()[i];
57 };
58
59 using size_type = std::decay_t<decltype(*adjacentNodes(0).begin())>;
60
61 // Use magic values to tag fully unprocessed and queued (but non-colored) entries.
64
65 // Initialize result vector with unprocessed state for all entries.
67
68 // Queue for the advancing front method
69 auto queue = std::queue<size_type>();
70
71 // Some helper methods to make code more expressive
72 auto isColored = [&](const auto& i) {
73 return color[i]<queuedStatus;
74 };
75 auto isNonProcessed = [&](const auto& i) {
76 return color[i]==nonProcessedStatus;
77 };
78 auto queueNode = [&](const auto& i) {
79 color[i] = queuedStatus;
80 queue.push(i);
81 };
82
83 // Fill queue with seed nodes (or {0} if seed node container is empty)
84 for (size_type i : seedNodes)
85 queueNode(i);
86 if (queue.empty())
87 queueNode(0);
88
89 // A temporary data structure to store the colors of already
90 // colored neighbors.
91 //
92 // There's various possible data structures here. The most
93 // obvious would be a set-like container storing the used
94 // color indices. This could be (with increasing performance)
95 // std::set, std::unordered_set, std::vector (keep sorted and unique),
96 // std::vector (just append, sort and remove duplicates afterwards).
97 // Since we expect that the total number of colors is small,
98 // it is significantly faster to simply mark used colors in
99 // a flag vector. Because memory usage is not an issue here,
100 // we use std::vector<char> which measurably outperformes
101 // std::vector<bool> due to faster bit access.
103 colorIsUsed.resize(32);
104
105 // If the graph has several connected components that are not
106 // reachable by the seed nodes, then we need to do several sweeps
107 // of the advancing front method.
108 while (not queue.empty())
109 {
110 // Use advancing front method to traverse graph
111 while (not queue.empty())
112 {
113 // Process next entry from queue
114 auto i = queue.front();
115 queue.pop();
116
117 // Collect colors of already colored neighbors,
118 // put nonprocessed neighbors into queue,
119 // and do nothing with already queued neighbors.
120 colorIsUsed.assign(colorIsUsed.size(), false);
121 for (const auto& neighbor: adjacentNodes(i))
122 {
123 if (isColored(neighbor))
124 colorIsUsed[color[neighbor]] = true;
125 else if (isNonProcessed(neighbor))
126 queueNode(neighbor);
127 }
128
129 // Assign first color that is not used by any processed neighbor to the current node
130 color[i] = std::find(colorIsUsed.begin(), colorIsUsed.end(), false) - colorIsUsed.begin();
131
132 // If necessary: Resize flag vector
133 if (color[i]==colorIsUsed.size())
134 colorIsUsed.resize(color[i]+1);
135 }
136
137 // If there are still some uncolored nodes, then the graph has connected
138 // components that are not reachable by the provided seed nodes. Hence we
139 // do another advancing front sweep starting from the first uncolored node.
140 auto firstNonProcessedIt = std::find(color.begin(), color.end(), nonProcessedStatus);
141 if (firstNonProcessedIt!=color.end())
143 }
144
145 return color;
146}
147
148
149
174template <class Adjacency, class T>
179
180
181
215template <class Adjacency>
217{
218 return computeColoring(adjacency, {0});
219}
220
221
222
223} // end namespace Dune::Assembler::Experimental
224
225#endif // DUNE_ASSEMBLER_PARALLEL_GRAPHCOLORING_HH
Definition barrier.hh:11
auto computeColoring(const Adjacency &adjacency, SeedNodesContainer &&seedNodes)
Compute a graph coloring from neighboring information.
Definition graphcoloring.hh:48
RowIterator end()
RowIterator begin()
T begin(T... args)
T end(T... args)
T find(T... args)
T max(T... args)