Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Welsh powell coloring #395

Merged
merged 12 commits into from
Feb 2, 2024
Merged
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,30 @@ The idea behind the algorithm is as follows: as long as there is a path from the
### Kahn's Algorithm
[Kahn's Algorithm](https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm) finds topological
ordering by iteratively removing nodes in the graph which have no incoming edges. When a node is removed from the graph, it is added to the topological ordering and all its edges are removed allowing for the next set of nodes with no incoming edges to be selected.
### Welsh Powell Coloring Algorithms
[Welsh Powell Coloring algorithm](https://www.geeksforgeeks.org/welsh-powell-graph-colouring-algorithm/) is a greedy vertex coloring algorithm. This algorithm is also used to find the chromatic number of a graph.

Welsh Powell Algorithm consists of following steps :

1. Find the degree of each vertex.
2. List the vertices in order of descending degrees.
3. Colour the first vertex with color 1.
4. Move down the list and color all the vertices not connected to the coloured vertex, with the same color.
5. Repeat step 4 on all uncolored vertices with a new color, in descending order of degrees until all the vertices are coloured.
Hi there, I'm creating a pull request to merge the Welsh Powell Coloring algorithm into the master branch.

The algorithm returns a std::map<Node, int> result that assigns each node to a color ordered by integers.
Users can also query the minimum chromatic order of the graph by querying the highest value from the resulting map.
```C++
std::map<Node, int> result = graph.welshPowellColoring();
auto chromatic_color = std::max_element(result.begin(), result.end(),
[](const auto& lhs, const auto& rhs) {
return lhs.second < rhs.second;
}
```
The minimum coloring starts from 1 instead of 0.

The algorithm assumes the graph to be undirected. All sources and inspirations are linked in the declaration of the algorithm and test cases.
## Partition Algorithm Explanation

### Vertex-Cut
Expand Down
27 changes: 10 additions & 17 deletions include/CXXGraph/Graph/Algorithm/welshPowellColoring_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,43 +13,36 @@ namespace CXXGraph {
template <typename T>
std::map<Node<T>, int> Graph<T>::welshPowellColoring() const {
auto adjMatrix = *getAdjMatrix();
std::unordered_map<std::shared_ptr<const Node<T>>, int> degreeOfVertexMap = {};

// Find the degree of each vertex and put them in a map
for (auto &[nodeFrom, nodeToEdgeVec] : adjMatrix) {
degreeOfVertexMap[nodeFrom] = nodeToEdgeVec.size();
std::vector<std::pair<std::shared_ptr<const Node<T>>, int>> degreeOfVertexVector = {};
// Find the degree of each vertex and put them in a vector
for (const auto &[nodeFrom, nodeToEdgeVec] : adjMatrix) {
degreeOfVertexVector.push_back({nodeFrom, nodeToEdgeVec.size()});
}

// Transform the map to the vector to sort
std::vector<std::pair<std::shared_ptr<const Node<T>>, int>> degreeOfVertexVector(degreeOfVertexMap.begin(), degreeOfVertexMap.end());

// Sort them based on the vertex degree
std::sort(degreeOfVertexVector.begin(), degreeOfVertexVector.end(), [](const auto& left, const auto& right) {
return left.second > right.second;
});

// Create a new map of coloring, where the keys are the nodes, and the value is the color order (assigned by integer)
// Create a new map of coloring, where the keys a re the nodes, and the value is the color order (assigned by integer)
std::map<Node<T>, int> mapOfColoring;
for (auto &[nodeFrom, _] : adjMatrix) {
for (const auto &[nodeFrom, _] : adjMatrix) {
mapOfColoring[*nodeFrom] = 0;
}

// Going down the list of vertex based on degrees
std::vector<int> usedColors(degreeOfVertexVector.size() + 1, 0);
for (const auto& [node, _] : degreeOfVertexVector) {
// Find the smallest unused color for the current vertex
std::vector<int> usedColors(degreeOfVertexVector.size() + 1, 0);

std::fill(usedColors.begin(), usedColors.end(), 0);
for (const auto &[neighbor, _] : adjMatrix[node]) {
usedColors[mapOfColoring[*neighbor]] = 1;
}

// Assign the smallest unused color to the current vertex
for (int c = 1; c < usedColors.size(); c++) {
if (usedColors[c] == 0) {
mapOfColoring[*node] = c;
break;
}
}
auto it = std::find(usedColors.begin() + 1, usedColors.end(), 0);
mapOfColoring[*node] = std::distance(usedColors.begin(), it);
}

return mapOfColoring;
Expand Down
Loading