From 5e197439d404bccf688875d707995be26eef97f0 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 | 189 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 boost/graph/edge_coloring.hpp diff --git a/boost/graph/edge_coloring.hpp b/boost/graph/edge_coloring.hpp new file mode 100644 index 0000000..d7ffafd --- /dev/null +++ b/boost/graph/edge_coloring.hpp @@ -0,0 +1,189 @@ +//======================================================================= +// 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 + +/* 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_map, + typename boost::graph_traits::vertex_descriptor u, + typename boost::property_traits::value_type color) + { + typedef typename boost::property_traits::value_type color_t; + if (color == std::numeric_limits::max()) + return false; + BOOST_FOREACH(typename boost::graph_traits::edge_descriptor e, + boost::out_edges(u, g)) { + if (boost::get(color_map, e) == color) { + return false; + } + } + return true; + } + + template + std::vector::vertex_descriptor> + maximal_fan(const Graph &g, + ColorMap color_map, + typename boost::graph_traits::vertex_descriptor x, + typename boost::graph_traits::vertex_descriptor y) + { + typedef typename boost::property_traits::value_type color_t; + typedef typename boost::graph_traits::vertex_descriptor vertex_t; + std::vector fan; + fan.push_back(y); + bool extended; + do { + extended = false; + BOOST_FOREACH(typename boost::graph_traits::edge_descriptor e, + boost::out_edges(x, g)) { + vertex_t v = boost::target(e, g); + if (is_free(g, color_map, fan.back(), boost::get(color_map, 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_map, + typename boost::graph_traits::vertex_descriptor u) + { + typename boost::property_traits::value_type c = 0; + while (!is_free(g, color_map, u, c)) c++; + return c; + } + + template + void + invert_cd_path(const Graph &g, + ColorMap color_map, + 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) + { + typedef typename boost::graph_traits::edge_descriptor edge_t; + boost::put(color_map, eold, d); + BOOST_FOREACH(edge_t e, boost::out_edges(x, g)) { + if (boost::get(color_map, e) == d && e != eold) { + invert_cd_path(g, color_map, boost::target(e, g), e, d, c); + return; + } + } + } + + template + void + invert_cd_path(const Graph &g, + ColorMap color_map, + typename boost::graph_traits::vertex_descriptor x, + typename boost::property_traits::value_type c, + typename boost::property_traits::value_type d) + { + typedef typename boost::graph_traits::edge_descriptor edge_t; + BOOST_FOREACH(edge_t e, boost::out_edges(x, g)) { + if (boost::get(color_map, e) == d) { + invert_cd_path(g, color_map, boost::target(e, g), e, d, c); + return; + } + } + } + + template + void + rotate_fan(const Graph &g, + ColorMap color_map, + typename boost::graph_traits::vertex_descriptor x, + ForwardIterator begin, + ForwardIterator end) + { + typedef typename boost::graph_traits::edge_descriptor edge_t; + typedef typename boost::property_traits::value_type color_t; + if (begin == end) { + return; + } + edge_t previous = boost::edge(x, *begin, g).first; + for (begin++; begin != end; begin++) { + edge_t current = boost::edge(x, *begin, g).first; + boost::put(color_map, previous, boost::get(color_map, current)); + previous = current; + } + } + } + + template + typename boost::property_traits::value_type + color_edge(const Graph &g, + ColorMap color_map, + 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; + namespace ph = boost::phoenix; + vertex_t x = boost::source(e, g), y = boost::target(e, g); + std::vector fan = maximal_fan(g, color_map, x, y); + color_t c = find_free_color(g, color_map, x); + color_t d = find_free_color(g, color_map, fan.back()); + invert_cd_path(g, color_map, x, c, d); + fan_iterator w = std::find_if(fan.begin(), + fan.end(), + ph::bind(&is_free, + ph::val(g), + ph::val(color_map), + ph::arg_names::arg1, + ph::val(d))); + rotate_fan(g, color_map, x, fan.begin(), w + 1); + boost::put(color_map, boost::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_map) + { + typedef typename boost::graph_traits::vertex_descriptor vertex_t; + typedef typename boost::graph_traits::edge_descriptor edge_t; + typedef typename boost::property_traits::value_type color_t; + BOOST_FOREACH(edge_t e, boost::edges(g)) { + boost::put(color_map, e, std::numeric_limits::max()); + } + color_t colors = 0; + BOOST_FOREACH(edge_t e, boost::edges(g)) { + colors = std::max(colors, color_edge(g, color_map, e) + 1); + } + return colors; + } +} + +#endif -- 1.8.1.5