From 890e078f7e1139ab39715496d5df9aed0fb09d8f Mon Sep 17 00:00:00 2001 From: Maciej Piechotka Date: Wed, 20 Mar 2013 18:02:18 +0100 Subject: [PATCH] Added edge coloring algorithm --- boost/graph/edge_coloring.hpp | 196 ++++++++++++++++++++++++++++++++++ libs/graph/doc/edge_coloring.html | 98 +++++++++++++++++ libs/graph/doc/table_of_contents.html | 1 + libs/graph/example/Jamfile.v2 | 2 +- libs/graph/example/edge_coloring.cpp | 70 ++++++++++++ 5 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 boost/graph/edge_coloring.hpp create mode 100644 libs/graph/doc/edge_coloring.html create mode 100644 libs/graph/example/edge_coloring.cpp diff --git a/boost/graph/edge_coloring.hpp b/boost/graph/edge_coloring.hpp new file mode 100644 index 0000000..6bb6246 --- /dev/null +++ b/boost/graph/edge_coloring.hpp @@ -0,0 +1,196 @@ +//======================================================================= +// Copyright 2013 Maciej Piechotka +// Authors: Maciej Piechotka +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_EDGE_COLORING_HPP +#define BOOST_GRAPH_EDGE_COLORING_HPP + +#include +#include +#include +#include +#include +#include + +/* This algorithm is to find coloring of an edges + + Reference: + + Misra, J., & Gries, D. (1992). A constructive proof of Vizing’s + theorem. In Information Processing Letters. +*/ + +namespace boost { + namespace detail { + template + bool + is_free(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor u, + typename boost::property_traits::value_type free_color) + { + typedef typename boost::property_traits::value_type color_t; + if (free_color == std::numeric_limits::max()) + return false; + BGL_FORALL_OUTEDGES_T(u, e, g, Graph) { + if (get(color, e) == free_color) { + return false; + } + } + return true; + } + + template + std::vector::vertex_descriptor> + maximal_fan(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + typename boost::graph_traits::vertex_descriptor y) + { + typedef typename boost::graph_traits::vertex_descriptor vertex_t; + std::vector fan; + fan.push_back(y); + bool extended; + do { + extended = false; + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) { + vertex_t v = target(e, g); + if (is_free(g, color, fan.back(), get(color, e)) && + std::find(fan.begin(), fan.end(), v) == fan.end()) { + fan.push_back(v); + extended = true; + } + } + } while(extended); + return fan; + } + template + typename boost::property_traits::value_type + find_free_color(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor u) + { + typename boost::property_traits::value_type c = 0; + while (!is_free(g, color, u, c)) c++; + return c; + } + + template + void + invert_cd_path(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + typename boost::graph_traits::edge_descriptor eold, + typename boost::property_traits::value_type c, + typename boost::property_traits::value_type d) + { + put(color, eold, d); + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) { + if (get(color, e) == d && e != eold) { + invert_cd_path(g, color, target(e, g), e, d, c); + return; + } + } + } + + template + void + invert_cd_path(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + typename boost::property_traits::value_type c, + typename boost::property_traits::value_type d) + { + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) { + if (get(color, e) == d) { + invert_cd_path(g, color, target(e, g), e, d, c); + return; + } + } + } + + template + void + rotate_fan(const Graph &g, + ColorMap color, + typename boost::graph_traits::vertex_descriptor x, + ForwardIterator begin, + ForwardIterator end) + { + typedef typename boost::graph_traits::edge_descriptor edge_t; + if (begin == end) { + return; + } + edge_t previous = edge(x, *begin, g).first; + for (begin++; begin != end; begin++) { + edge_t current = edge(x, *begin, g).first; + put(color, previous, get(color, current)); + previous = current; + } + } + + template + class find_free_in_fan + { + public: + find_free_in_fan(const Graph &graph, + const ColorMap color, + typename boost::property_traits::value_type d) + : graph(graph), + color(color), + d(d) {} + bool operator()(const typename boost::graph_traits::vertex_descriptor u) const { + return is_free(graph, color, u, d); + } + private: + const Graph &graph; + const ColorMap color; + const typename boost::property_traits::value_type d; + }; + } + + template + typename boost::property_traits::value_type + color_edge(const Graph &g, + ColorMap color, + typename boost::graph_traits::edge_descriptor e) + { + typedef typename boost::graph_traits::vertex_descriptor vertex_t; + typedef typename boost::property_traits::value_type color_t; + typedef typename std::vector::iterator fan_iterator; + using namespace detail; + vertex_t x = source(e, g), y = target(e, g); + std::vector fan = maximal_fan(g, color, x, y); + color_t c = find_free_color(g, color, x); + color_t d = find_free_color(g, color, fan.back()); + invert_cd_path(g, color, x, c, d); + fan_iterator w = std::find_if(fan.begin(), + fan.end(), + find_free_in_fan(g, color, d)); + rotate_fan(g, color, x, fan.begin(), w + 1); + put(color, edge(x, *w, g).first, d); + return std::max(c, d); + } + + template + typename boost::property_traits::value_type + edge_coloring(const Graph &g, + ColorMap color) + { + typedef typename boost::property_traits::value_type color_t; + BGL_FORALL_EDGES_T(e, g, Graph) { + put(color, e, std::numeric_limits::max()); + } + color_t colors = 0; + BGL_FORALL_EDGES_T(e, g, Graph) { + colors = std::max(colors, color_edge(g, color, e) + 1); + } + return colors; + } +} + +#endif diff --git a/libs/graph/doc/edge_coloring.html b/libs/graph/doc/edge_coloring.html new file mode 100644 index 0000000..5f6436d --- /dev/null +++ b/libs/graph/doc/edge_coloring.html @@ -0,0 +1,98 @@ + + + + + +Boost Graph Library: Edge Coloring + +C++ Boost + +
+ +

+(Python) +edge_coloring +

+ + +

+

+ + + + + + + + + + +
Graphs:undirected, loop-free
Properties:color
Complexity:time: O(|E| |V|)
+
+ + +
+  template <class Graph, class ColorMap>
+  typename boost::property_traits::value_type
+  edge_coloring(const Graph &g, ColorMap color);
+
+ +

Computes an edge coloring for the vertices in the graph, using +an algorithm proposed by Mista et al. []. Given edges ordered +e1, e2, ..., en it assignes a +colors c1, c2, ..., cn in a way +that no vertex connects with 2 edges of the same color. Furthermore +at most m + 1 colors are used. + + + +

Where defined

+boost/graph/edge_coloring.hpp + +

Parameters

+ +IN: const Graph& g +
+ The graph object on which the algorithm will be applied. The type + Graph must be a model of + Edge List Graph and Incidence + Graph. +
+ +OUT: ColorMap color +
+ This property map records the colors of each edges. It must be a + model of + Read/Write Property Map whose key type is the same as the edge + descriptor type of the graph and whose value type is an integral type + that can store all values smaller or equal to m. +
+ + +

Example

+ +See example/king_ordering.cpp. + +

See Also

+ +sequential vertex ordering. + +
+
+ + +
Copyright © 2013 +Maciej Piechotka (uzytkownik2@gmail.com) +
+ + + diff --git a/libs/graph/doc/table_of_contents.html b/libs/graph/doc/table_of_contents.html index 0fd36e8..f2131c9 100644 --- a/libs/graph/doc/table_of_contents.html +++ b/libs/graph/doc/table_of_contents.html @@ -285,6 +285,7 @@
  1. metric_tsp_approx
  2. sequential_vertex_coloring +
  3. edge_coloring
  4. is_bipartite (including two-coloring of bipartite graphs)
  5. find_odd_cycle
  6. maximum_adjacency_search diff --git a/libs/graph/example/Jamfile.v2 b/libs/graph/example/Jamfile.v2 index ce155c6..8998182 100644 --- a/libs/graph/example/Jamfile.v2 +++ b/libs/graph/example/Jamfile.v2 @@ -50,4 +50,4 @@ exe subgraph_properties : subgraph_properties.cpp ; exe vf2_sub_graph_iso_example : vf2_sub_graph_iso_example.cpp ; exe vf2_sub_graph_iso_multi_example : vf2_sub_graph_iso_multi_example.cpp ; exe sloan_ordering : sloan_ordering.cpp ; - +exe edge_coloring : edge_coloring.cpp ; diff --git a/libs/graph/example/edge_coloring.cpp b/libs/graph/example/edge_coloring.cpp new file mode 100644 index 0000000..81a8a38 --- /dev/null +++ b/libs/graph/example/edge_coloring.cpp @@ -0,0 +1,70 @@ +//======================================================================= +// Copyright 2013 Maciej Piechotka +// Authors: Maciej Piechotka +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include +#include +#include + +/* + Sample output + Colored using 5 colors + a-d: 4 + a-f: 0 + b-c: 2 + b-e: 3 + b-g: 1 + b-j: 0 + c-d: 0 + c-e: 1 + d-f: 2 + d-i: 1 + e-g: 4 + f-g: 3 + f-h: 1 + g-h: 0 +*/ + +int main(int, char *[]) +{ + using namespace boost; + using namespace std; + typedef adjacency_list Graph; + + typedef std::pair Pair; + Pair edges[14] = { Pair(0,3), //a-d + Pair(0,5), //a-f + Pair(1,2), //b-c + Pair(1,4), //b-e + Pair(1,6), //b-g + Pair(1,9), //b-j + Pair(2,3), //c-d + Pair(2,4), //c-e + Pair(3,5), //d-f + Pair(3,8), //d-i + Pair(4,6), //e-g + Pair(5,6), //f-g + Pair(5,7), //f-h + Pair(6,7) }; //g-h + + Graph G(10); + + for (size_t i = 0; i < sizeof(edges)/sizeof(edges[0]); i++) + add_edge(edges[i].first, edges[i].second, G).first; + + size_t colors = edge_coloring(G, get(edge_bundle, G)); + + cout << "Colored using " << colors << " colors" << endl; + for (size_t i = 0; i < sizeof(edges)/sizeof(edges[0]); i++) { + cout << " " << (char)('a' + edges[i].first) << "-" << (char)('a' + edges[i].second) << ": " << G[edge(edges[i].first, edges[i].second, G).first] << endl; + } + + return 0; +} + -- 1.8.3.2