Limbo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Coloring.h
Go to the documentation of this file.
1 
8 #ifndef LIMBO_ALGORITHMS_COLORING_COLORING
9 #define LIMBO_ALGORITHMS_COLORING_COLORING
10 
11 #include <fstream>
12 #include <vector>
13 #include <boost/cstdint.hpp>
14 #include <boost/functional/hash.hpp>
15 #include <boost/graph/graph_concepts.hpp>
16 #include <boost/graph/adjacency_list.hpp>
17 #include <boost/property_map/property_map.hpp>
20 
22 namespace limbo
23 {
25 namespace algorithms
26 {
28 namespace coloring
29 {
30 
31 using boost::uint32_t;
32 using boost::int32_t;
33 using boost::int8_t;
34 
35 namespace la = limbo::algorithms;
36 
39 template <typename GraphType>
41 {
43  typedef GraphType graph_type;
45  typedef typename base_type::vertex_descriptor vertex_descriptor;
47 
48  std::vector<int8_t> const& vColor;
49 
53  ColoringVertexLabelWriter(graph_type const& g, std::vector<int8_t> const& vc) : base_type(g), vColor(vc) {}
54 
58  std::string label(vertex_descriptor v) const
59  {
60  std::ostringstream oss;
61  oss << v << ":" << (int32_t)vColor[v];
62  return oss.str();
63  }
64 };
65 
68 template <typename GraphType>
69 struct ColoringEdgeLabelWriter : public la::EdgeLabelWriter<GraphType>
70 {
72  typedef GraphType graph_type;
74  typedef typename base_type::edge_descriptor edge_descriptor;
75  typedef typename base_type::edge_weight_type edge_weight_type;
76  typedef typename boost::graph_traits<graph_type>::vertex_descriptor vertex_descriptor;
78 
79  std::vector<int8_t> const& vColor;
80 
84  ColoringEdgeLabelWriter(graph_type const& g, std::vector<int8_t> const& vc) : base_type(g), vColor(vc) {}
85 
89  edge_weight_type label(edge_descriptor e) const {return boost::get(boost::edge_weight, this->g, e);}
93  std::string color(edge_descriptor e) const
94  {
95  vertex_descriptor s = boost::source(e, this->g);
96  vertex_descriptor t = boost::target(e, this->g);
97  edge_weight_type w = boost::get(boost::edge_weight, this->g, e);
98  bool conflict_flag = (vColor[s] >= 0 && vColor[s] == vColor[t]);
99  if (w >= 0 && conflict_flag) // conflict
100  return "red";
101  else return "black";
102  }
106  std::string style(edge_descriptor e) const {return (boost::get(boost::edge_weight, this->g, e) >= 0)? "solid" : "dashed";}
107 };
108 
113 template <typename GraphType>
114 class Coloring
115 {
116  public:
118  typedef GraphType graph_type;
119  typedef typename boost::graph_traits<graph_type>::vertex_descriptor graph_vertex_type;
120  typedef typename boost::graph_traits<graph_type>::edge_descriptor graph_edge_type;
121  typedef typename boost::graph_traits<graph_type>::vertex_iterator vertex_iterator_type;
122  typedef typename boost::graph_traits<graph_type>::edge_iterator edge_iterator_type;
123  // value type for edge weight, integer or double...
124  typedef typename boost::property_traits<typename boost::property_map<graph_type, boost::edge_weight_t>::const_type>::value_type edge_weight_type;
125  // edge weight is used to differentiate conflict edge and stitch edge
126  // non-negative weight implies conflict edge
127  // negative weight implies stitch edge
128  typedef typename boost::property_traits<typename boost::property_map<graph_type, boost::edge_index_t>::const_type>::value_type edge_index_type;
130 
133  {
134  THREE = 3,
135  FOUR = 4
136  };
138  struct EdgeHashType : std::unary_function<graph_edge_type, std::size_t>
139  {
142  std::size_t operator()(graph_edge_type const& e) const
143  {
144  std::size_t seed = 0;
145  boost::hash_combine(seed, e.m_source);
146  boost::hash_combine(seed, e.m_target);
147  return seed;
148  }
149  };
150 
151 
154  Coloring(graph_type const& g);
156  virtual ~Coloring() {};
157 
158  // member functions
161  virtual double operator()();
162 
165  virtual void color_num(ColorNumType cn) {m_color_num = cn;}
168  virtual void color_num(int8_t cn) {m_color_num = (cn == 3)? THREE : FOUR;}
170  virtual ColorNumType color_num() const {return m_color_num;}
171 
175  virtual void precolor(graph_vertex_type v, int8_t c) {m_vColor[v] = c; m_has_precolored = true;}
176 
178  virtual bool has_precolored() const {return m_has_precolored;}
179 
181  virtual double stitch_weight() const {return m_stitch_weight;}
184  virtual void stitch_weight(double w) {m_stitch_weight = w;}
185 
188  virtual void threads(int32_t t) {m_threads = t;}
189 
193  virtual int8_t color(graph_vertex_type v) const {return m_vColor[v];}
194 
195  // helper functions
199  inline virtual edge_weight_type edge_weight(graph_edge_type const& e) const {return boost::get(boost::edge_weight, m_graph, e);}
200 
204  virtual edge_weight_type calc_cost(std::vector<int8_t> const& vColor) const;
205 
210  void check_edge_weight(graph_type const& g, edge_weight_type lb, edge_weight_type ub) const;
211 
214  void print_edge_weight(graph_type const& g) const;
215 
216  // for debug
219  virtual void write_graph(std::string const& filename) const;
224  virtual void write_graph(std::string const& filename, graph_type const& g, std::vector<int8_t> const& vColor) const;
225  protected:
227  virtual double coloring() = 0;
228 
229  graph_type const& m_graph;
230  std::vector<int8_t> m_vColor;
231 
234  int32_t m_threads;
236 };
237 
238 template <typename GraphType>
239 Coloring<GraphType>::Coloring(Coloring<GraphType>::graph_type const& g)
240  : m_graph(g)
241  , m_vColor(boost::num_vertices(g), -1)
242  , m_color_num(THREE)
243  , m_stitch_weight(0.1)
244  , m_threads(std::numeric_limits<int32_t>::max())
245  , m_has_precolored(false)
246 {}
247 
248 template <typename GraphType>
250 {
251  if (boost::num_vertices(m_graph) <= color_num()) // if vertex number is no larger than color number, directly assign color
252  {
253  // need to consider precolored vertices
254  bool unusedColors[4] = {true, true, true, true};
255  if (color_num() == THREE)
256  unusedColors[3] = false;
257  for (int32_t i = 0, ie = m_vColor.size(); i != ie; ++i)
258  {
259  if (m_vColor[i] < 0) // if not precolored, assign to an unused color
260  {
261  for (int8_t c = 0; c != 4; ++c)
262  if (unusedColors[c])
263  {
264  m_vColor[i] = c;
265  break;
266  }
267  }
268  // must have valid color after assignment
269  assert(m_vColor[i] >= 0);
270  unusedColors[m_vColor[i]] = false;
271  }
272  return calc_cost(m_vColor);
273  }
274  else // perform coloring algorithm
275  return this->coloring();
276 }
277 
278 template <typename GraphType>
279 typename Coloring<GraphType>::edge_weight_type Coloring<GraphType>::calc_cost(std::vector<int8_t> const& vColor) const
280 {
281  assert(vColor.size() == boost::num_vertices(this->m_graph));
282  double cost = 0;
283  edge_iterator_type ei, eie;
284  for (boost::tie(ei, eie) = boost::edges(m_graph); ei != eie; ++ei)
285  {
286  edge_weight_type w = boost::get(boost::edge_weight, m_graph, *ei);
287  graph_vertex_type s = boost::source(*ei, m_graph);
288  graph_vertex_type t = boost::target(*ei, m_graph);
289  if (s == t) // skip self edges
290  continue;
291  if (w >= 0) // conflict edge
292  cost += (vColor[s] == vColor[t])*w;
293  else // stitch edge
294  cost += (vColor[s] != vColor[t])*w;
295  }
296  return cost;
297 }
298 
299 template <typename GraphType>
300 void Coloring<GraphType>::check_edge_weight(typename Coloring<GraphType>::graph_type const& g, typename Coloring<GraphType>::edge_weight_type lb, typename Coloring<GraphType>::edge_weight_type ub) const
301 {
302  edge_iterator_type ei, eie;
303  for (boost::tie(ei, eie) = boost::edges(g); ei != eie; ++ei)
304  {
305  edge_weight_type w = boost::get(boost::edge_weight, m_graph, *ei);
306  assert_msg(w >= lb && w <= ub, "edge weight out of range: " << w);
307  }
308 }
309 
310 template <typename GraphType>
311 void Coloring<GraphType>::print_edge_weight(typename Coloring<GraphType>::graph_type const& g) const
312 {
313  edge_iterator_type ei, eie;
314  for (boost::tie(ei, eie) = boost::edges(g); ei != eie; ++ei)
315  {
316  edge_weight_type w = boost::get(boost::edge_weight, m_graph, *ei);
317  std::cout << w << " ";
318  }
319  std::cout << "\n";
320 }
321 
322 // it seems doxygen cannot handle template functions with the same name correctly
324 template <typename GraphType>
325 void Coloring<GraphType>::write_graph(std::string const& filename) const
326 {
327  write_graph(filename, m_graph, m_vColor);
328 }
329 
330 template <typename GraphType>
331 void Coloring<GraphType>::write_graph(std::string const& filename, Coloring<GraphType>::graph_type const& g, std::vector<int8_t> const& vColor) const
332 {
333  std::ofstream out ((filename+".gv").c_str());
334  la::write_graph(out, g, ColoringVertexLabelWriter<graph_type>(g, vColor), ColoringEdgeLabelWriter<graph_type>(g, vColor));
335  out.close();
336  la::graphviz2pdf(filename);
337 }
339 
340 } // namespace coloring
341 } // namespace algorithms
342 } // namespace limbo
343 
344 #endif
hasher class for graph_edge_type
Definition: Coloring.h:138
Coloring(graph_type const &g)
Definition: Coloring.h:239
Boost.Geometry.
Definition: GdsObjects.h:724
virtual edge_weight_type calc_cost(std::vector< int8_t > const &vColor) const
Definition: Coloring.h:279
void write_graph(std::ofstream &out, GraphType const &g, VertexLabelType const &vl, EdgeLabelType const &el)
write graph to graphviz format and convert to pdf. Although Boost.Graph has write_graphviz component...
Definition: GraphUtility.h:119
default EdgeLabelWriter for write_graph
Definition: GraphUtility.h:87
virtual void precolor(graph_vertex_type v, int8_t c)
Definition: Coloring.h:175
int32_t m_threads
control number of threads for ILP solver
Definition: Coloring.h:234
virtual double stitch_weight() const
Definition: Coloring.h:181
assertion with message
some graph utilities such as compute complement graph and graphviz writer.
ColoringVertexLabelWriter(graph_type const &g, std::vector< int8_t > const &vc)
Definition: Coloring.h:53
virtual ~Coloring()
destructor
Definition: Coloring.h:156
virtual edge_weight_type edge_weight(graph_edge_type const &e) const
Definition: Coloring.h:199
virtual bool has_precolored() const
Definition: Coloring.h:178
bool m_has_precolored
whether contain precolored vertices
Definition: Coloring.h:235
graph_type const & g
bind graph object
Definition: GraphUtility.h:95
void print_edge_weight(graph_type const &g) const
Definition: Coloring.h:311
virtual void threads(int32_t t)
Definition: Coloring.h:188
std::vector< int8_t > m_vColor
coloring solutions
Definition: Coloring.h:230
virtual void color_num(int8_t cn)
Definition: Coloring.h:168
std::vector< int8_t > const & vColor
coloring solutions
Definition: Coloring.h:79
namespace for Limbo
Definition: GraphUtility.h:22
std::iterator_traits< Iterator >::value_type max(Iterator first, Iterator last)
get max of an array
Definition: Math.h:61
graph_type const & m_graph
initial graph
Definition: Coloring.h:229
std::string label(vertex_descriptor v) const
Definition: Coloring.h:58
graph_type const & g
bind graph object
Definition: GraphUtility.h:74
virtual void write_graph(std::string const &filename) const
std::size_t operator()(graph_edge_type const &e) const
Definition: Coloring.h:142
virtual ColorNumType color_num() const
Definition: Coloring.h:170
namespace for Limbo.algorithms
Definition: GraphUtility.h:25
void check_edge_weight(graph_type const &g, edge_weight_type lb, edge_weight_type ub) const
Definition: Coloring.h:300
virtual void color_num(ColorNumType cn)
Definition: Coloring.h:165
ColorNumType m_color_num
number of colors
Definition: Coloring.h:232
std::string style(edge_descriptor e) const
Definition: Coloring.h:106
default VertexLabelWriter for write_graph
Definition: GraphUtility.h:67
std::vector< int8_t > const & vColor
coloring solutions
Definition: Coloring.h:48
edge_weight_type label(edge_descriptor e) const
Definition: Coloring.h:89
ColoringEdgeLabelWriter(graph_type const &g, std::vector< int8_t > const &vc)
Definition: Coloring.h:84
virtual int8_t color(graph_vertex_type v) const
Definition: Coloring.h:193
std::string color(edge_descriptor e) const
Definition: Coloring.h:93
virtual void stitch_weight(double w)
Definition: Coloring.h:184
double m_stitch_weight
stitch weight
Definition: Coloring.h:233
void graphviz2pdf(std::string const &filename, const char *suffix=".gv")
convert graphviz format to pdf. The input filename should be filename+suffix
Definition: GraphUtility.h:150
#define assert_msg(condition, message)
assertion with message
Definition: AssertMsg.h:34