Limbo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LPColoring.h
Go to the documentation of this file.
1 
14 #ifndef LIMBO_ALGORITHMS_COLORING_LP
15 #define LIMBO_ALGORITHMS_COLORING_LP
16 
17 #include <iostream>
18 #include <vector>
19 #include <queue>
20 #include <set>
21 #include <cassert>
22 #include <cmath>
23 #include <stdlib.h>
24 #include <cstdio>
25 #include <sstream>
26 #include <algorithm>
27 #include <boost/cstdint.hpp>
28 #include <boost/graph/graph_concepts.hpp>
29 #include <boost/property_map/property_map.hpp>
30 #include <boost/dynamic_bitset.hpp>
31 #include <limbo/string/String.h>
33 #include "gurobi_c++.h"
34 
35 #ifdef DEBUG_NONINTEGERS
36 extern std::vector<unsigned int> vLP1NonInteger;
37 extern std::vector<unsigned int> vLP1HalfInteger;
38 extern std::vector<unsigned int> vLP2NonInteger;
39 extern std::vector<unsigned int> vLP2HalfInteger;
40 extern std::vector<unsigned int> vLPEndNonInteger;
41 extern std::vector<unsigned int> vLPEndHalfInteger;
42 extern std::vector<unsigned int> vLPNumIter;
43 #endif
44 
46 namespace limbo
47 {
49 namespace algorithms
50 {
52 namespace coloring
53 {
54 
55 using std::vector;
56 using std::queue;
57 using std::set;
58 using std::cout;
59 using std::endl;
60 using std::string;
61 
66 template <typename GraphType>
67 class LPColoring : public Coloring<GraphType>
68 {
69  public:
72  typedef typename base_type::graph_type graph_type;
73  typedef typename base_type::graph_vertex_type graph_vertex_type;
74  typedef typename base_type::graph_edge_type graph_edge_type;
75  typedef typename base_type::vertex_iterator_type vertex_iterator_type;
76  typedef typename base_type::edge_iterator_type edge_iterator_type;
77  typedef typename base_type::edge_weight_type edge_weight_type;
78  typedef typename base_type::EdgeHashType edge_hash_type;
80 
83  {
88 
91  : vertex_non_integer_num(std::numeric_limits<uint32_t>::max())
92  , edge_non_integer_num(std::numeric_limits<uint32_t>::max())
93  , vertex_half_integer_num(std::numeric_limits<uint32_t>::max())
94  , edge_half_integer_num(std::numeric_limits<uint32_t>::max())
95  {}
96  };
99  {
100  double coeff;
101  char sense;
102 
105  : coeff(0.0)
106  , sense('>')
107  {}
111  void set(double c, char s)
112  {
113  coeff = c;
114  sense = s;
115  }
119  bool same_direction(ConstrVariableInfo const& rhs) const
120  {
121  if (coeff == 0.0 || rhs.coeff == 0.0)
122  return true;
123  else if (sense == rhs.sense)
124  return (coeff > 0 && rhs.coeff > 0) || (coeff < 0 && rhs.coeff < 0);
125  else
126  return (coeff > 0 && rhs.coeff < 0) || (coeff < 0 && rhs.coeff > 0);
127  }
128  };
129 
130  // member functions
133  LPColoring(graph_type const& g);
136 
138  uint32_t lp_iters() const {return m_lp_iters;}
139 
140  // for debug
143  void print_solution(vector<GRBVar> const& vColorBits) const;
144  protected:
148  double coloring();
149 
152  void apply_solution(vector<GRBVar> const& vColorBits);
153 
155  void initialize();
161  void set_optimize_model(vector<GRBVar>& vColorBits, vector<GRBVar>& vEdgeBits, GRBLinExpr& obj, GRBModel& optModel);
164  void set_anchor(vector<GRBVar>& vColorBits) const;
168  void adjust_variable_pair_in_objective(vector<GRBVar> const& vColorBits, GRBLinExpr& obj) const;
172  void adjust_conflict_edge_vertices_in_objective(vector<GRBVar> const& vColorBits, GRBLinExpr& obj) const;
176  void add_odd_cycle_constraints(vector<GRBVar> const& vColorBits, GRBModel& optModel);
179  void solve_model(GRBModel& optModel);
180 
184  void get_odd_cycles(graph_vertex_type const& v, vector<vector<graph_vertex_type> >& vOddCyle);
186  graph_vertex_type max_degree_vertex() const;
187 
192  void rounding_with_binding_analysis(GRBModel& optModel, vector<GRBVar>& vColorBits, vector<GRBVar>& vEdgeBits);
193 
195  uint32_t post_refinement();
198  bool refine_color(graph_edge_type const& e);
199 
204  void non_integer_num(vector<GRBVar> const& vColorBits, vector<GRBVar> const& vEdgeBits, NonIntegerInfo& info) const;
209  void non_integer_num(vector<GRBVar> const& vVariables, uint32_t& nonIntegerNum, uint32_t& halfIntegerNum) const;
210 
214  bool is_integer(double value) const {return value == floor(value);}
215 
219  uint32_t check_precolored_num(vector<LPColoring<GraphType>::graph_vertex_type> const& vVertex) const;
220 
222  boost::dynamic_bitset<> m_vVertexHandledByOddCycle;
223  uint32_t m_constrs_num;
224  uint32_t m_lp_iters;
225 };
226 
228 template <typename GraphType>
230  : LPColoring<GraphType>::base_type(g)
231  , m_vVertexHandledByOddCycle(boost::num_vertices(g), false)
232  , m_constrs_num(0)
233  , m_lp_iters(0)
234 {
235 }
236 
237 //DFS to search for the odd cycles, stored in m_odd_cycles
238 template <typename GraphType>
239 void LPColoring<GraphType>::get_odd_cycles(graph_vertex_type const& v, vector<vector<LPColoring<GraphType>::graph_vertex_type> >& vOddCyle)
240 {
241  //odd_cycle results
242  vOddCyle.clear();
243 
244  // do not search for odd cycles for the same vertex again
245  if (m_vVertexHandledByOddCycle[v]) return;
246  else m_vVertexHandledByOddCycle[v] = true;
247 
248  //the array denoting the distance/visiting of the graph
249  uint32_t numVertices = boost::num_vertices(this->m_graph);
250  vector<int32_t> vNodeDistColor (numVertices, -1);
251  vector<bool> vNodeVisited (numVertices, false);
252 
253  //inCycle flag
254  vector<bool> vInCycle (numVertices, false);
255 
256  // stack for DFS
257  // use std::vector instead of std::stack for better memory control
258  vector<graph_vertex_type> vVertexStack;
259  vVertexStack.reserve(numVertices);
260  vNodeVisited[v] = true;
261  vNodeDistColor[v] = 0;
262  vVertexStack.push_back(v);
263  while (!vVertexStack.empty())
264  {
265  //determine whether the top element needs to be popped
266  bool popFlag = true;
267  //access the top element on the dfs_stack
268  // current vertex
269  graph_vertex_type cv = vVertexStack.back();
270  //access the neighbors
271  typename boost::graph_traits<graph_type>::adjacency_iterator ui, uie;
272  for(boost::tie(ui, uie) = adjacent_vertices(cv, this->m_graph); ui != uie; ++ui)
273  {
274  graph_vertex_type u = *ui;
275 
276  if(vNodeDistColor[u] == -1)
277  {
278  vNodeDistColor[u] = 1 - vNodeDistColor[cv];
279  vNodeVisited[u] = true;
280  //push to the stack
281  vVertexStack.push_back(u);
282  popFlag = false;
283  break;
284  }
285  } //end for
286 
287  if (true == popFlag)
288  {
289  vector<graph_vertex_type> cycle;
290  //detect the odd cycle
291  for (boost::tie(ui, uie) = adjacent_vertices(cv, this->m_graph); ui != uie; ++ui)
292  {
293  graph_vertex_type u = *ui;
294  if (vNodeVisited[u] && (vNodeDistColor[u] == vNodeDistColor[cv]))
295  //if (*vi == v && (nodeDist[next_index] == nodeDist[curr_index])) // we only care about odd cycle related to v
296  {
297  //suppose v is not in the current cycle
298  vInCycle[v] = false;
299  //detect the cycle between curr_v and *vi
300  int32_t cnt = vVertexStack.size();
301  for(int32_t k = cnt - 1; k >= 0; --k) // back trace cycle
302  {
303  cycle.push_back(vVertexStack[k]);
304  //flag the nodes in cycle
305  vInCycle[vVertexStack[k]] = true;
306  if(vVertexStack[k] == u) break;
307  }
308  //store the cycle, when v is in cycle
309  // if contain precolored vertices, avoid cycle with a lot precolored vertices
310  if (!cycle.empty() && vInCycle[v] && !(this->has_precolored() && check_precolored_num(cycle)+2 > cycle.size()))
311  {
312  vOddCyle.push_back(vector<graph_vertex_type>());
313  vOddCyle.back().swap(cycle);
314  // if we find a small cycle, mark all vertices as handled to reduce the number of duplicate constraints
315  if (cnt == 3)
316  for (int32_t k = 0; k != cnt; ++k)
317  m_vVertexHandledByOddCycle[vVertexStack[k]] = true;
318  }
319  else cycle.clear(); // remember to clear cycle
320  }
321  }
322 
323  //pop the top element
324  vVertexStack.pop_back();
325  vNodeVisited[cv] = false;
326  }//end if popFlag
327  }//end while
328 }
329 
330 // the vertex with the largest degree
331 template <typename GraphType>
332 typename LPColoring<GraphType>::graph_vertex_type LPColoring<GraphType>::max_degree_vertex() const
333 {
334  graph_vertex_type u = 0;
335  uint32_t maxDegree = 0;
336  vertex_iterator_type vi, vie;
337  for (boost::tie(vi, vie) = boost::vertices(this->m_graph); vi != vie; ++vi)
338  {
339  uint32_t d = boost::degree(*vi, this->m_graph);
340  if (d > maxDegree)
341  {
342  u = *vi;
343  maxDegree = d;
344  }
345  }
346  return u;
347 }
348 
349 template <typename GraphType>
350 void LPColoring<GraphType>::set_optimize_model(vector<GRBVar>& vColorBits, vector<GRBVar>& /*vEdgeBits*/, GRBLinExpr& obj, GRBModel& optModel)
351 {
352  uint32_t numVertices = boost::num_vertices(this->m_graph);
353  //uint32_t numEdges = boost::num_edges(this->m_graph);
354  uint32_t numColorBits = numVertices<<1;
355 
356  //set up the LP variables
357  vColorBits.reserve(numColorBits);
358  //vEdgeBits.reserve(numEdges);
359  // vertex and edge variables
360  char buf[64];
361  for (uint32_t i = 0; i != numColorBits; ++i)
362  {
363  sprintf(buf, "v%u", i);
364  // check whether precolored
365  uint32_t vertexIdx = i>>1;
366  int8_t color = this->m_vColor[vertexIdx];
367  if (color < 0) // not precolored
368  vColorBits.push_back(optModel.addVar(0.0, 1.0, 0.0, GRB_CONTINUOUS, buf));
369  else // precolored
370  {
371  int8_t colorBit = (i&1)? (color&1) : (color>>1);
372 #ifdef DEBUG_LPCOLORING
373  assert(colorBit >= 0 && colorBit <= 1);
374 #endif
375  vColorBits.push_back(optModel.addVar(colorBit, colorBit, colorBit, GRB_CONTINUOUS, buf));
376  }
377  }
378  //for (uint32_t i = 0; i != numEdges; ++i)
379  //{
380  // // some variables here may not be used
381  // sprintf(buf, "e%u", i);
382  // vEdgeBits.push_back(optModel.addVar(0.0, 1.0, 0.0, GRB_CONTINUOUS, buf));
383  //}
384  //Integrate new variables
385  optModel.update();
386 
387  // set up objective
388  obj.clear(); // set to 0
389  optModel.setObjective(obj, GRB_MINIMIZE);
390 
391  //set up the LP constraints
392  edge_iterator_type ei, eie;
393  for(boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
394  {
395  graph_edge_type e = *ei;
396  graph_vertex_type s = boost::source(e, this->m_graph);
397  graph_vertex_type t = boost::target(e, this->m_graph);
398 
399  // if both vertices of an edge is precolored, skip
400  // otherwise, it may crash due to intrinsic conflict
401  if (this->has_precolored() && this->m_vColor[s] >= 0 && this->m_vColor[t] >= 0)
402  continue;
403 
404  uint32_t bitIdxS = s<<1;
405  uint32_t bitIdxT = t<<1;
406 
407  edge_weight_type w = this->edge_weight(e);
408  assert_msg(w > 0, "no stitch edge allowed, positive edge weight expected: " << w);
409 
410  sprintf(buf, "R%u", m_constrs_num++);
411  optModel.addConstr(
412  vColorBits[bitIdxS] + vColorBits[bitIdxS+1]
413  + vColorBits[bitIdxT] + vColorBits[bitIdxT+1] >= 1
414  , buf);
415 
416  sprintf(buf, "R%u", m_constrs_num++);
417  optModel.addConstr(
418  1 - vColorBits[bitIdxS] + vColorBits[bitIdxS+1]
419  + 1 - vColorBits[bitIdxT] + vColorBits[bitIdxT+1] >= 1
420  , buf);
421 
422  sprintf(buf, "R%u", m_constrs_num++);
423  optModel.addConstr(
424  vColorBits[bitIdxS] + 1 - vColorBits[bitIdxS+1]
425  + vColorBits[bitIdxT] + 1 - vColorBits[bitIdxT+1] >= 1
426  , buf);
427 
428  sprintf(buf, "R%u", m_constrs_num++);
429  optModel.addConstr(
430  1 - vColorBits[bitIdxS] + 1 - vColorBits[bitIdxS+1]
431  + 1 - vColorBits[bitIdxT] + 1 - vColorBits[bitIdxT+1] >= 1
432  , buf);
433  }
434 
435  if (this->color_num() == base_type::THREE)
436  {
437  for(uint32_t k = 0; k < numColorBits; k += 2)
438  {
439  sprintf(buf, "R%u", m_constrs_num++);
440  optModel.addConstr(
441  vColorBits[k] + vColorBits[k+1] <= 1,
442  buf);
443  }
444  }
445 
446  //Integrate new variables
447  optModel.update();
448 }
449 
450 template <typename GraphType>
451 void LPColoring<GraphType>::set_anchor(vector<GRBVar>& vColorBits) const
452 {
453  if (this->has_precolored()) // no anchor if containing precolored vertices
454  return;
455  //Anchoring the coloring of the vertex with largest degree
456  graph_vertex_type anchorVertex = max_degree_vertex();
457  uint32_t bitIdxAnchor = anchorVertex<<1;
458  vColorBits[bitIdxAnchor].set(GRB_DoubleAttr_UB, 0.0);
459  vColorBits[bitIdxAnchor].set(GRB_DoubleAttr_LB, 0.0);
460  vColorBits[bitIdxAnchor+1].set(GRB_DoubleAttr_UB, 0.0);
461  vColorBits[bitIdxAnchor+1].set(GRB_DoubleAttr_LB, 0.0);
462 }
463 
465 template <typename GraphType>
466 void LPColoring<GraphType>::adjust_variable_pair_in_objective(vector<GRBVar> const& vColorBits, GRBLinExpr& obj) const
467 {
468  for(uint32_t k = 0, ke = vColorBits.size(); k < ke; k += 2)
469  {
470  double value1 = vColorBits[k].get(GRB_DoubleAttr_X);
471  double value2 = vColorBits[k+1].get(GRB_DoubleAttr_X);
472  if (!is_integer(value1) || !is_integer(value2))
473  {
474  if (value1 > value2)
475  obj += vColorBits[k+1]-vColorBits[k];
476  else if (value1 < value2)
477  obj += vColorBits[k]-vColorBits[k+1];
478  }
479  }//end for
480 }
481 
483 template <typename GraphType>
484 void LPColoring<GraphType>::adjust_conflict_edge_vertices_in_objective(vector<GRBVar> const& vColorBits, GRBLinExpr& obj) const
485 {
486  edge_iterator_type ei, eie;
487  for(boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
488  {
489  graph_edge_type e = *ei;
490  graph_vertex_type s = boost::source(e, this->m_graph);
491  graph_vertex_type t = boost::target(e, this->m_graph);
492 
493  for (uint32_t i = 0; i != 2; ++i)
494  {
495  uint32_t bitIdxS = (s<<1)+i;
496  uint32_t bitIdxT = (t<<1)+i;
497 
498  double value1 = vColorBits[bitIdxS].get(GRB_DoubleAttr_X);
499  double value2 = vColorBits[bitIdxT].get(GRB_DoubleAttr_X);
500 
501  if (value1 > value2)
502  obj += vColorBits[bitIdxT]-vColorBits[bitIdxS]; // reverse, as we minimize objective
503  else if (value1 < value2)
504  obj += vColorBits[bitIdxS]-vColorBits[bitIdxT]; // reverse, as we minimize objective
505  }
506  }//end for
507 }
508 
510 template <typename GraphType>
511 void LPColoring<GraphType>::add_odd_cycle_constraints(vector<GRBVar> const& vColorBits, GRBModel& optModel)
512 {
513  char buf[64];
514  vector<vector<graph_vertex_type> > vOddCyle;
515  for(uint32_t k = 0, ke = vColorBits.size(); k < ke; k += 2)
516  {
517  // only add odd cycle for half integer
518  if (vColorBits[k].get(GRB_DoubleAttr_X) != 0.5 && vColorBits[k+1].get(GRB_DoubleAttr_X) != 0.5)
519  continue;
520 
521  graph_vertex_type v = k>>1;
522  this->get_odd_cycles(v, vOddCyle);
523 
524  for (typename vector<vector<graph_vertex_type> >::const_iterator it1 = vOddCyle.begin(), it1e = vOddCyle.end(); it1 != it1e; ++it1)
525  {
526  vector<graph_vertex_type> const& oddCycle = *it1;
527  int32_t cycleLength = oddCycle.size(); // safer to use integer as we do minus afterward
528  GRBLinExpr constraint1 = 0;
529  GRBLinExpr constraint2 = 0;
530 
531  for (typename vector<graph_vertex_type>::const_iterator it2 = oddCycle.begin(), it2e = oddCycle.end(); it2 != it2e; ++it2)
532  {
533  graph_vertex_type u = *it2;
534  constraint1 += vColorBits[u<<1];
535  constraint2 += vColorBits[(u<<1)+1];
536  }
537 
538  sprintf(buf, "ODD%lu_%u", v, m_constrs_num++);
539  optModel.addConstr(constraint1 >= 1, buf);
540  sprintf(buf, "ODD%lu_%u", v, m_constrs_num++);
541  optModel.addConstr(constraint1 <= cycleLength-1, buf);
542  sprintf(buf, "ODD%lu_%u", v, m_constrs_num++);
543  optModel.addConstr(constraint2 >= 1, buf);
544  sprintf(buf, "ODD%lu_%u", v, m_constrs_num++);
545  optModel.addConstr(constraint2 <= cycleLength-1, buf);
546  }
547  }//end for k
548 }
549 
551 template <typename GraphType>
552 void LPColoring<GraphType>::solve_model(GRBModel& optModel)
553 {
554  char buf[64];
555  //optimize the new model
556  optModel.update();
557 #ifdef DEBUG_LPCOLORING
558  sprintf(buf, "%u.lp", m_lp_iters);
559  optModel.write(buf);
560 #endif
561  optModel.optimize();
562  int32_t optStatus = optModel.get(GRB_IntAttr_Status);
563  if (optStatus == GRB_INFEASIBLE)
564  {
565  // write lp
566  sprintf(buf, "%u.lp", m_lp_iters);
567  optModel.write(buf);
568  // write iis
569  optModel.computeIIS();
570  sprintf(buf, "%u.ilp", m_lp_iters);
571  optModel.write(buf);
572  }
573  assert_msg(optStatus != GRB_INFEASIBLE, "model is infeasible");
574  ++m_lp_iters;
575 }
576 
577 //relaxed linear programming based coloring for the conflict graph (this->m_graph)
578 template <typename GraphType>
580 {
581 #ifdef DEBUG_LPCOLORING
582  this->write_graph("initial_input");
583 #endif
584  vector<GRBVar> vColorBits;
585  vector<GRBVar> vEdgeBits;
586  GRBLinExpr obj;
587 
588  //set up the LP environment
589  GRBEnv env;
590  //mute the log from the LP solver
591  env.set(GRB_IntParam_OutputFlag, 0);
592  // set number of threads
593  if (this->m_threads > 0 && this->m_threads < std::numeric_limits<int32_t>::max())
594  env.set(GRB_IntParam_Threads, this->m_threads);
595  // default algorithm
596  env.set(GRB_IntParam_Method, -1);
597  // since GRBModel does not allow default constructor, we have to setup GRBEnv before it
598  GRBModel optModel = GRBModel(env);
599 
600  // initialize model and set anchor vertex
601  set_optimize_model(vColorBits, vEdgeBits, obj, optModel);
602 #ifndef DEBUG_NOANCHOR
603  set_anchor(vColorBits);
604 #endif
605 
606  solve_model(optModel);
607 
608 #ifdef DEBUG_LPCOLORING
609  printf("\nLP %u solution: ", m_lp_iters);
610  print_solution(vColorBits);
611 #endif
612 
613  NonIntegerInfo prevInfo; // initialize to numeric max
614  NonIntegerInfo curInfo;
615  non_integer_num(vColorBits, vEdgeBits, curInfo);
616 #ifdef DEBUG_NONINTEGERS
617  vLP1NonInteger.push_back(curInfo.vertex_non_integer_num);
618  vLP1HalfInteger.push_back(curInfo.vertex_half_integer_num);
619 #endif
620  //iteratively scheme
621  while(curInfo.vertex_non_integer_num > 0 && curInfo.vertex_non_integer_num < prevInfo.vertex_non_integer_num)
622  {
623  //set the new objective
624  //push the non-half_integer to 0/1
625  // tune objective for a pair of values
626  adjust_variable_pair_in_objective(vColorBits, obj);
627  // tune objective for a pair of value along conflict edges
628  // disabled because it has conflicts with odd cycle constraints
629  //adjust_conflict_edge_vertices_in_objective(vColorBits, obj);
630 
631  optModel.setObjective(obj);
632 
633  //add new constraints
634  //odd cycle trick from Prof. Baldick
635  add_odd_cycle_constraints(vColorBits, optModel);
636 
637  solve_model(optModel);
638 
639 #ifdef DEBUG_LPCOLORING
640  printf("LP %u solution: ", m_lp_iters);
641  print_solution(vColorBits);
642 #endif
643 
644  prevInfo = curInfo;
645  non_integer_num(vColorBits, vEdgeBits, curInfo);
646 #ifdef DEBUG_NONINTEGERS
647  if (m_lp_iters == 2)
648  {
649  vLP2NonInteger.push_back(curInfo.vertex_non_integer_num);
650  vLP2HalfInteger.push_back(curInfo.vertex_half_integer_num);
651  }
652 #endif
653  }
654 
655 #ifdef DEBUG_NONINTEGERS
656  vLPEndNonInteger.push_back(curInfo.vertex_non_integer_num);
657  vLPEndHalfInteger.push_back(curInfo.vertex_half_integer_num);
658  vLPNumIter.push_back(m_lp_iters);
659 #endif
660 
661  // binding analysis
662  //rounding_with_binding_analysis(optModel, vColorBits, vEdgeBits);
663  // apply coloring solution
664  apply_solution(vColorBits);
665  // post refinement
666  post_refinement();
667 
668 #ifdef DEBUG_LPCOLORING
669  this->write_graph("final_output");
670 #endif
671  return this->calc_cost(this->m_vColor);
672 }
673 
674 template <typename GraphType>
675 void LPColoring<GraphType>::apply_solution(vector<GRBVar> const& vColorBits)
676 {
677  for (uint32_t i = 0, ie = this->m_vColor.size(); i != ie; ++i)
678  {
679  GRBVar const& var1 = vColorBits[i<<1];
680  GRBVar const& var2 = vColorBits[(i<<1)+1];
681  int8_t b1 = round(var1.get(GRB_DoubleAttr_X));
682  int8_t b2 = round(var2.get(GRB_DoubleAttr_X));
683  // exclude (1, 1) for three coloring
684  this->m_vColor[i] = std::min((b1<<1)+b2, (int8_t)this->color_num()-1);
685  }
686 }
687 
690 template <typename GraphType>
691 void LPColoring<GraphType>::rounding_with_binding_analysis(GRBModel& optModel, vector<GRBVar>& vColorBits, vector<GRBVar>& vEdgeBits)
692 {
693  NonIntegerInfo prevInfo; // initialize to numeric max
694  NonIntegerInfo curInfo;
695  non_integer_num(vColorBits, vEdgeBits, curInfo);
696  //iteratively scheme
697  while(curInfo.vertex_non_integer_num > 0 && curInfo.vertex_non_integer_num < prevInfo.vertex_non_integer_num)
698  {
699  bool modifyFlag = false; // whether binding analysis causes any change
700  for (uint32_t i = 0, ie = vColorBits.size(); i < ie; i += 2)
701  {
702  GRBVar const& var1 = vColorBits[i];
703  GRBVar const& var2 = vColorBits[i+1];
704  double value1 = var1.get(GRB_DoubleAttr_X);
705  double value2 = var2.get(GRB_DoubleAttr_X);
706 
707  if (!(value1 == 0.5 && value2 == 0.5))
708  continue;
709 
710  GRBColumn column[2] = {
711  optModel.getCol(var1),
712  optModel.getCol(var2)
713  };
714 
715  ConstrVariableInfo prevConstrInfo[2];
716  ConstrVariableInfo curConstrInfo[2];
717 
718  // (0, 0), (0, 1), (1, 0), (1, 1)
719  bool mValidColorBits[2][2] = {{true, true}, {true, true}};
720  if (this->color_num() == base_type::THREE)
721  mValidColorBits[1][1] = false;
722 
723  uint32_t invalidCount = 0;
724  bool failFlag = false; // whether optimal rounding is impossible
725  // check all corresponding constraints
726  for (uint32_t j = 0; j != 2 && !failFlag; ++j)
727  for (uint32_t k = 0, ke = column[j].size(); k != ke; ++k)
728  {
729  GRBConstr constr = column[j].getConstr(k);
730  // skip non-binding constraint
731  //if (constr.get(GRB_DoubleAttr_Slack) != 0.0)
732  // continue;
733  char sense = constr.get(GRB_CharAttr_Sense);
734  curConstrInfo[0].set(optModel.getCoeff(constr, var1), sense);
735  curConstrInfo[1].set(optModel.getCoeff(constr, var2), sense);
736 
737  // conflict sensitivity detected
738  if (!curConstrInfo[0].same_direction(prevConstrInfo[0]) || !curConstrInfo[1].same_direction(prevConstrInfo[1]))
739  {
740  failFlag = true;
741  break;
742  }
743 
744  // check all coloring solutions
745  for (int32_t b1 = 0; b1 != 2; ++b1)
746  for (int32_t b2 = 0; b2 != 2; ++b2)
747  {
748  if (mValidColorBits[b1][b2])
749  {
750  double delta = curConstrInfo[0].coeff*(b1-value1) + curConstrInfo[1].coeff*(b2-value2);
751  if ((sense == '>' && delta < 0.0) || (sense == '<' && delta > 0.0)) // fail
752  {
753  mValidColorBits[b1][b2] = false;
754  ++invalidCount;
755  }
756  }
757  }
758 
759  // no valid rounding solution
760  if (invalidCount == 4)
761  {
762  failFlag = true;
763  break;
764  }
765 
766  prevConstrInfo[0] = curConstrInfo[0];
767  prevConstrInfo[1] = curConstrInfo[1];
768  }
769 
770  // apply
771  if (!failFlag)
772  {
773  for (int32_t b1 = 0; b1 != 2; ++b1)
774  for (int32_t b2 = 0; b2 != 2; ++b2)
775  if (mValidColorBits[b1][b2])
776  {
777  vColorBits[i].set(GRB_DoubleAttr_UB, b1);
778  vColorBits[i].set(GRB_DoubleAttr_LB, b1);
779  vColorBits[i+1].set(GRB_DoubleAttr_UB, b2);
780  vColorBits[i+1].set(GRB_DoubleAttr_LB, b2);
781  modifyFlag = true;
782  }
783  }
784  }
785 
786  // exit if nothing changed
787  if (!modifyFlag) break;
788 
789  solve_model(optModel);
790 
791  prevInfo = curInfo;
792  non_integer_num(vColorBits, vEdgeBits, curInfo);
793  }
794 }
795 
796 //post coloring refinement
797 template <typename GraphType>
799 {
800  uint32_t count = 0;
801  if (!this->has_precolored()) // no post refinement if containing precolored vertices
802  {
803  // greedy post refinement
804  // keep refining until no color changed
805  edge_iterator_type ei, eie;
806  do
807  {
808  count = 0;
809  for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
810  count += refine_color(*ei);
811  } while (count);
812  }
813 
814  return count;
815 }
816 
818 template <typename GraphType>
819 bool LPColoring<GraphType>::refine_color(LPColoring<GraphType>::graph_edge_type const& e)
820 {
821  graph_vertex_type v[2] = {
822  boost::source(e, this->m_graph),
823  boost::target(e, this->m_graph)
824  };
825 
826  //if (this->m_vColor[v[0]] != this->m_vColor[v[1]])
827  // return false;
828 
829  // find coloring solution with best cost
830  int8_t bestColor[2] = {0, 0};
831  edge_weight_type bestCost = std::numeric_limits<edge_weight_type>::max();
832  int8_t c[2];
833  for (c[0] = 0; c[0] != this->color_num(); c[0] += 1)
834  for (c[1] = 0; c[1] != this->color_num(); c[1] += 1)
835  {
836  edge_weight_type curCost = 0;
837  typename boost::graph_traits<graph_type>::adjacency_iterator ui, uie;
838  for (int32_t i = 0; i != 2; ++i)
839  {
840  // cv denotes current vertex
841  // ov denotes the other vertex
842  graph_vertex_type cv = v[i], ov = v[!i];
843  for (boost::tie(ui, uie) = boost::adjacent_vertices(cv, this->m_graph); ui != uie; ++ui)
844  {
845  graph_vertex_type u = *ui;
846  if (u != ov && c[i] == this->m_vColor[u])
847  {
848  std::pair<graph_edge_type, bool> eU2cv = boost::edge(cv, u, this->m_graph);
849 #ifdef DEBUG_LPCOLORING
850  assert(eU2cv.second);
851 #endif
852  // edge weight is important since we may deal with merged graphs
853  curCost += std::max((edge_weight_type)1, boost::get(boost::edge_weight, this->m_graph, eU2cv.first));
854  }
855  }
856  }
857  if (c[0] == c[1]) // edge weight is important since we may deal with merged graphs
858  curCost += std::max((edge_weight_type)1, boost::get(boost::edge_weight, this->m_graph, e));
859  if (curCost < bestCost)
860  {
861  bestCost = curCost;
862  bestColor[0] = c[0];
863  bestColor[1] = c[1];
864  }
865  }
866  bool retFlag = false;
867  if (this->m_vColor[v[0]] != bestColor[0] || this->m_vColor[v[1]] != bestColor[1])
868  {
869  this->m_vColor[v[0]] = bestColor[0];
870  this->m_vColor[v[1]] = bestColor[1];
871  retFlag = true;
872  }
873 
874  return retFlag;
875 }
876 
877 // for debug use
878 // it seems doxygen cannot handle template functions with the same name correctly
880 template <typename GraphType>
881 void LPColoring<GraphType>::non_integer_num(vector<GRBVar> const& vColorBits, vector<GRBVar> const& /*vEdgeBits*/, LPColoring<GraphType>::NonIntegerInfo& info) const
882 {
883  non_integer_num(vColorBits, info.vertex_non_integer_num, info.vertex_half_integer_num);
884  //non_integer_num(vEdgeBits, info.edge_non_integer_num, info.edge_half_integer_num);
885 
886 #ifdef DEBUG_LPCOLORING
887  printf("vertex_non_integer_num = %u, vertex_half_integer_num = %u\n", info.vertex_non_integer_num, info.vertex_half_integer_num);
888  //printf("edge_non_integer_num = %u, edge_half_integer_num = %u\n", info.edge_non_integer_num, info.edge_half_integer_num);
889 #endif
890 }
891 
892 template <typename GraphType>
893 void LPColoring<GraphType>::non_integer_num(vector<GRBVar> const& vVariables, uint32_t& nonIntegerNum, uint32_t& halfIntegerNum) const
894 {
895  nonIntegerNum = 0;
896  halfIntegerNum = 0;
897  for (vector<GRBVar>::const_iterator it = vVariables.begin(), ite = vVariables.end(); it != ite; ++it)
898  {
899  double value = it->get(GRB_DoubleAttr_X);
900  if (value != 0.0 && value != 1.0)
901  {
902  ++nonIntegerNum;
903  if (value == 0.5)
904  ++halfIntegerNum;
905  }
906  }
907 }
909 
910 template <typename GraphType>
911 uint32_t LPColoring<GraphType>::check_precolored_num(vector<LPColoring<GraphType>::graph_vertex_type> const& vVertex) const
912 {
913  uint32_t precoloredNum = 0;
914  for (typename vector<graph_vertex_type>::const_iterator vi = vVertex.begin(), vie = vVertex.end(); vi != vie; ++vi)
915  if (this->m_vColor[*vi] >= 0) // precolored vertex
916  ++precoloredNum;
917  return precoloredNum;
918 }
919 
920 template <typename GraphType>
921 void LPColoring<GraphType>::print_solution(vector<GRBVar> const& vColorBits) const
922 {
923  const char* prefix = "";
924  for (uint32_t i = 0, ie = vColorBits.size(); i < ie; i += 2)
925  {
926  printf("%sv%u=(%g,%g)", prefix, i>>1, vColorBits[i].get(GRB_DoubleAttr_X), vColorBits[i+1].get(GRB_DoubleAttr_X));
927  prefix = ", ";
928  }
929  printf("\n");
930 }
931 
932 } // namespace coloring
933 } // namespace algorithms
934 } // namespace limbo
935 
936 #endif
hasher class for graph_edge_type
Definition: Coloring.h:138
void non_integer_num(vector< GRBVar > const &vColorBits, vector< GRBVar > const &vEdgeBits, NonIntegerInfo &info) const
void print_solution(vector< GRBVar > const &vColorBits) const
Definition: LPColoring.h:921
boost::dynamic_bitset m_vVertexHandledByOddCycle
members
Definition: LPColoring.h:222
Boost.Geometry.
Definition: GdsObjects.h:724
void set_anchor(vector< GRBVar > &vColorBits) const
Definition: LPColoring.h:451
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
bool refine_color(graph_edge_type const &e)
Definition: LPColoring.h:819
bool is_integer(string const &s)
check whether string represents an integer
Definition: String.h:28
uint32_t vertex_half_integer_num
number of vertices with half-integer solutions
Definition: LPColoring.h:86
uint32_t m_constrs_num
record number of constraints
Definition: LPColoring.h:223
void add_odd_cycle_constraints(vector< GRBVar > const &vColorBits, GRBModel &optModel)
odd cycle trick from Prof. Baldick
Definition: LPColoring.h:511
bool is_integer(double value) const
Definition: LPColoring.h:214
uint32_t edge_non_integer_num
number of edges with non-integer solutions
Definition: LPColoring.h:85
void initialize()
create the NoStitchGraph (this->m_graph) from the (m_conflict_graph)
uint32_t m_lp_iters
record lp iterations
Definition: LPColoring.h:224
void adjust_variable_pair_in_objective(vector< GRBVar > const &vColorBits, GRBLinExpr &obj) const
tune objective for each color bit pair of vertex
Definition: LPColoring.h:466
void set_optimize_model(vector< GRBVar > &vColorBits, vector< GRBVar > &vEdgeBits, GRBLinExpr &obj, GRBModel &optModel)
Definition: LPColoring.h:350
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
uint32_t post_refinement()
greedy final coloring refinement
Definition: LPColoring.h:798
void adjust_conflict_edge_vertices_in_objective(vector< GRBVar > const &vColorBits, GRBLinExpr &obj) const
tune objective for each color bit pair along conflict edges
Definition: LPColoring.h:484
base class for all graph coloring algorithms
records the information of non-integer values
Definition: LPColoring.h:82
LPColoring(graph_type const &g)
constructor
Definition: LPColoring.h:229
void apply_solution(vector< GRBVar > const &vColorBits)
Definition: LPColoring.h:675
void rounding_with_binding_analysis(GRBModel &optModel, vector< GRBVar > &vColorBits, vector< GRBVar > &vEdgeBits)
Definition: LPColoring.h:691
Check string is integer, floating point, number... Convert string to upper/lower cases.
uint32_t vertex_non_integer_num
number of vertices with non-integer solutions
Definition: LPColoring.h:84
void get_odd_cycles(graph_vertex_type const &v, vector< vector< graph_vertex_type > > &vOddCyle)
Definition: LPColoring.h:239
std::iterator_traits< Iterator >::value_type min(Iterator first, Iterator last)
get min of an array
Definition: Math.h:77
bool same_direction(ConstrVariableInfo const &rhs) const
Definition: LPColoring.h:119
graph_vertex_type max_degree_vertex() const
Definition: LPColoring.h:332
void solve_model(GRBModel &optModel)
solve model
Definition: LPColoring.h:552
information for a variable of a constraint
Definition: LPColoring.h:98
#define assert_msg(condition, message)
assertion with message
Definition: AssertMsg.h:34
uint32_t check_precolored_num(vector< LPColoring< GraphType >::graph_vertex_type > const &vVertex) const
Definition: LPColoring.h:911
uint32_t edge_half_integer_num
number of edges with half-integer solutions
Definition: LPColoring.h:87