Limbo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ILPColoringLemonCbc.h
Go to the documentation of this file.
1 
12 #ifndef LIMBO_ALGORITHMS_COLORING_ILPCOLORINGLEMONCBC
13 #define LIMBO_ALGORITHMS_COLORING_ILPCOLORINGLEMONCBC
14 
15 #include <iostream>
16 #include <vector>
17 #include <queue>
18 #include <set>
19 #include <limits>
20 #include <cassert>
21 #include <cmath>
22 #include <stdlib.h>
23 #include <cstdio>
24 #include <sstream>
25 #include <algorithm>
26 #include <boost/cstdint.hpp>
27 #include <boost/unordered_map.hpp>
28 #include <boost/graph/graph_concepts.hpp>
29 #include <boost/graph/subgraph.hpp>
30 #include <boost/property_map/property_map.hpp>
31 //#include <boost/graph/bipartite.hpp>
32 //#include <boost/graph/kruskal_min_spanning_tree.hpp>
33 //#include <boost/graph/prim_minimum_spanning_tree.hpp>
34 //#include <boost/graph/dijkstra_shortest_paths.hpp>
35 #include <limbo/string/String.h>
37 #include <lemon/cbc.h>
38 #include <lemon/lp.h>
39 
41 namespace limbo
42 {
44 namespace algorithms
45 {
47 namespace coloring
48 {
49 
50 using std::ostringstream;
51 using boost::unordered_map;
52 
64 template <typename GraphType>
65 class ILPColoringLemonCbc : public Coloring<GraphType>
66 {
67  public:
70  using typename base_type::graph_type;
71  using typename base_type::graph_vertex_type;
72  using typename base_type::graph_edge_type;
73  using typename base_type::vertex_iterator_type;
74  using typename base_type::edge_iterator_type;
75  using typename base_type::edge_weight_type;
76  using typename base_type::ColorNumType;
78 
80  struct edge_hash_type : std::unary_function<graph_edge_type, std::size_t>
81  {
85  std::size_t operator()(graph_edge_type const& e) const
86  {
87  std::size_t seed = 0;
88  boost::hash_combine(seed, e.m_source);
89  boost::hash_combine(seed, e.m_target);
90  return seed;
91  }
92  };
93 
96  ILPColoringLemonCbc(graph_type const& g)
97  : base_type(g)
98  {}
100  virtual ~ILPColoringLemonCbc() {}
101 
102  protected:
104  virtual double coloring();
105 };
106 
107 template <typename GraphType>
109 {
110  uint32_t vertex_num = boost::num_vertices(this->m_graph);
111  uint32_t edge_num = boost::num_edges(this->m_graph);
112  uint32_t vertex_variable_num = vertex_num<<1;
113 
114  unordered_map<graph_vertex_type, uint32_t> hVertexIdx; // vertex index
115  unordered_map<graph_edge_type, uint32_t, edge_hash_type> hEdgeIdx; // edge index
116 
117  vertex_iterator_type vi, vie;
118  uint32_t cnt = 0;
119  for (boost::tie(vi, vie) = boost::vertices(this->m_graph); vi != vie; ++vi, ++cnt)
120  hVertexIdx[*vi] = cnt;
121  edge_iterator_type ei, eie;
122  cnt = 0;
123  for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei, ++cnt)
124  hEdgeIdx[*ei] = cnt;
125 
126  typedef lemon::MipSolver::Row Row; // constraints dimension
127  typedef lemon::MipSolver::Col Col; // variable dimension
128  typedef lemon::MipSolver::Expr Expr; // expression
129 
130  // ILP environment
131  lemon::CbcMip opt_model;
132  //mute the log from the LP solver
133  // set threads
134  //set up the ILP variables
135  vector<Col> vVertexBit;
136  vector<Col> vEdgeBit;
137 
138  // vertex variables
139  vVertexBit.reserve(vertex_variable_num);
140  for (uint32_t i = 0; i != vertex_variable_num; ++i)
141  {
142  uint32_t vertex_idx = (i>>1);
143  ostringstream oss;
144  oss << "v" << i;
145  if (this->m_vColor[vertex_idx] >= 0 && this->m_vColor[vertex_idx] < this->m_color_num) // precolored
146  {
147  int8_t color_bit;
148  if ((i&1) == 0) color_bit = (this->m_vColor[vertex_idx]>>1)&1;
149  else color_bit = this->m_vColor[vertex_idx]&1;
150  vVertexBit.push_back(opt_model.addCol());
151  Col const& x = vVertexBit.back();
152  opt_model.colBounds(x, color_bit, color_bit);
153  opt_model.colType(x, lemon::MipSolver::INTEGER);
154  opt_model.colName(x, oss.str());
155  }
156  else // uncolored
157  {
158  vVertexBit.push_back(opt_model.addCol());
159  Col const& x = vVertexBit.back();
160  opt_model.colBounds(x, 0, 1);
161  opt_model.colType(x, lemon::MipSolver::INTEGER);
162  opt_model.colName(x, oss.str());
163  }
164  }
165 
166  // edge variables
167  vEdgeBit.reserve(edge_num);
168  for (uint32_t i = 0; i != edge_num; ++i)
169  {
170  ostringstream oss;
171  oss << "e" << i;
172  vEdgeBit.push_back(opt_model.addCol());
173  Col const& x = vEdgeBit.back();
174  opt_model.colBounds(x, 0, 1);
175  opt_model.colType(x, lemon::MipSolver::REAL);
176  opt_model.colName(x, oss.str());
177  }
178 
179  // update model
180 
181  // set up the objective
182  Expr obj;
183  for (boost::tie(ei, eie) = edges(this->m_graph); ei != eie; ++ei)
184  {
185  edge_weight_type w = boost::get(boost::edge_weight, this->m_graph, *ei);
186  if (w > 0) // weighted conflict
187  obj += w*vEdgeBit[hEdgeIdx[*ei]];
188  else if (w < 0) // weighted stitch
189  obj += this->m_stitch_weight*(-w)*vEdgeBit[hEdgeIdx[*ei]];
190  }
191  opt_model.obj(obj);
192  opt_model.min();
193 
194  // set up the constraints
195  //uint32_t constr_num = 0;
196  for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
197  {
198  graph_vertex_type s = boost::source(*ei, this->m_graph);
199  graph_vertex_type t = boost::target(*ei, this->m_graph);
200  uint32_t sIdx = hVertexIdx[s];
201  uint32_t tIdx = hVertexIdx[t];
202 
203  uint32_t vertex_idx1 = sIdx<<1;
204  uint32_t vertex_idx2 = tIdx<<1;
205 
206  edge_weight_type w = boost::get(boost::edge_weight, this->m_graph, *ei);
207  uint32_t edge_idx = hEdgeIdx[*ei];
208 
209  //char buf[100];
210  if (w >= 0) // constraints for conflict edges
211  {
212  //sprintf(buf, "R%u", constr_num++);
213  opt_model.addRow(
214  vVertexBit[vertex_idx1] + vVertexBit[vertex_idx1+1]
215  + vVertexBit[vertex_idx2] + vVertexBit[vertex_idx2+1]
216  + vEdgeBit[edge_idx] >= 1
217  );
218 
219  //sprintf(buf, "R%u", constr_num++);
220  opt_model.addRow(
221  1 - vVertexBit[vertex_idx1] + vVertexBit[vertex_idx1+1]
222  + 1 - vVertexBit[vertex_idx2] + vVertexBit[vertex_idx2+1]
223  + vEdgeBit[edge_idx] >= 1
224  );
225 
226  //sprintf(buf, "R%u", constr_num++);
227  opt_model.addRow(
228  vVertexBit[vertex_idx1] + 1 - vVertexBit[vertex_idx1+1]
229  + vVertexBit[vertex_idx2] + 1 - vVertexBit[vertex_idx2+1]
230  + vEdgeBit[edge_idx] >= 1
231  );
232 
233  //sprintf(buf, "R%u", constr_num++);
234  opt_model.addRow(
235  1 - vVertexBit[vertex_idx1] + 1 - vVertexBit[vertex_idx1+1]
236  + 1 - vVertexBit[vertex_idx2] + 1 - vVertexBit[vertex_idx2+1]
237  + vEdgeBit[edge_idx] >= 1
238  );
239 
240  }
241  else // constraints for stitch edges
242  {
243  //sprintf(buf, "R%u", constr_num++);
244  opt_model.addRow(
245  vVertexBit[vertex_idx1] - vVertexBit[vertex_idx2] - vEdgeBit[edge_idx] <= 0
246  );
247 
248  //sprintf(buf, "R%u", constr_num++);
249  opt_model.addRow(
250  vVertexBit[vertex_idx2] - vVertexBit[vertex_idx1] - vEdgeBit[edge_idx] <= 0
251  );
252 
253  //sprintf(buf, "R%u", constr_num++);
254  opt_model.addRow(
255  vVertexBit[vertex_idx1+1] - vVertexBit[vertex_idx2+1] - vEdgeBit[edge_idx] <= 0
256  );
257 
258  //sprintf(buf, "R%u", constr_num++);
259  opt_model.addRow(
260  vVertexBit[vertex_idx2+1] - vVertexBit[vertex_idx1+1] - vEdgeBit[edge_idx] <= 0
261  );
262  }
263  }
264 
265  // additional constraints for 3-coloring
266  if (this->m_color_num == base_type::THREE)
267  {
268  //char buf[100];
269  for(uint32_t k = 0; k != vertex_variable_num; k += 2)
270  {
271  //sprintf(buf, "R%u", constr_num++);
272  opt_model.addRow(vVertexBit[k] + vVertexBit[k+1] <= 1);
273  }
274  }
275 
276  //optimize model
277  opt_model.solve();
278  int32_t opt_status = opt_model.type();
279  if (opt_status == lemon::MipSolver::INFEASIBLE)
280  {
281  cout << "ERROR: The model is infeasible... EXIT" << endl;
282  exit(1);
283  }
284 
285  // collect coloring solution
286  for (uint32_t k = 0; k != vertex_variable_num; k += 2)
287  {
288  int8_t color = (opt_model.sol(vVertexBit[k])*2) + opt_model.sol(vVertexBit[k+1]);
289  uint32_t vertex_idx = (k>>1);
290 
291  assert(color >= 0 && color < this->m_color_num);
292  if (this->m_vColor[vertex_idx] >= 0 && this->m_vColor[vertex_idx] < this->m_color_num) // check precolored vertex
293  assert(this->m_vColor[vertex_idx] == color);
294  else // assign color to uncolored vertex
295  this->m_vColor[vertex_idx] = color;
296  }
297 
298  // return objective value
299  return opt_model.solValue();
300 }
301 
302 } // namespace coloring
303 } // namespace algorithms
304 } // namespace limbo
305 
306 #endif
std::size_t operator()(graph_edge_type const &e) const
the model is infeasible
Definition: Solvers.h:37
namespace for Limbo
Definition: GraphUtility.h:22
base class for all graph coloring algorithms
Check string is integer, floating point, number... Convert string to upper/lower cases.
integer number
Definition: Solvers.h:34