Limbo 3.5.4
Loading...
Searching...
No Matches
LPColoring.h
Go to the documentation of this file.
1
13
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
36extern std::vector<unsigned int> vLP1NonInteger;
37extern std::vector<unsigned int> vLP1HalfInteger;
38extern std::vector<unsigned int> vLP2NonInteger;
39extern std::vector<unsigned int> vLP2HalfInteger;
40extern std::vector<unsigned int> vLPEndNonInteger;
41extern std::vector<unsigned int> vLPEndHalfInteger;
42extern std::vector<unsigned int> vLPNumIter;
43#endif
44
46namespace limbo
47{
49namespace algorithms
50{
52namespace coloring
53{
54
55using std::vector;
56using std::queue;
57using std::set;
58using std::cout;
59using std::endl;
60using std::string;
61
66template <typename GraphType>
67class LPColoring : public Coloring<GraphType>
68{
69 public:
71 typedef Coloring<GraphType> base_type;
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 };
97
99 {
100 double coeff;
101 char sense;
102
105 : coeff(0.0)
106 , sense('>')
107 {}
108
111 void set(double c, char s)
112 {
113 coeff = c;
114 sense = s;
115 }
116
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
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
228template <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
238template <typename GraphType>
239void 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 {
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
331template <typename GraphType>
332typename 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
349template <typename GraphType>
350void 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 limboAssert(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 limboAssertMsg(w > 0, "no stitch edge allowed, positive edge weight expected: %u", 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
450template <typename GraphType>
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
465template <typename GraphType>
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
483template <typename GraphType>
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
510template <typename GraphType>
511void LPColoring<GraphType>::add_odd_cycle_constraints(vector<GRBVar> const& vColorBits, GRBModel& optModel)
512{
513 char buf[64];
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
551template <typename GraphType>
552void 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 limboAssertMsg(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)
578template <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
667
668#ifdef DEBUG_LPCOLORING
669 this->write_graph("final_output");
670#endif
671 return this->calc_cost(this->m_vColor);
672}
673
674template <typename GraphType>
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
690template <typename GraphType>
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
797template <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
818template <typename GraphType>
819bool 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 limboAssert(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
880template <typename GraphType>
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
892template <typename GraphType>
893void 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
910template <typename GraphType>
911uint32_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
920template <typename GraphType>
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
#define limboAssertMsg(condition, args...)
custom assertion with message
Definition AssertMsg.h:24
#define limboAssert(condition)
custom assertion without message
Definition AssertMsg.h:36
base class for all graph coloring algorithms
Check string is integer, floating point, number... Convert string to upper/lower cases.
virtual int8_t color(graph_vertex_type v) const
Definition Coloring.h:196
graph_type const & m_graph
initial graph
Definition Coloring.h:239
virtual edge_weight_type edge_weight(graph_edge_type const &e) const
Definition Coloring.h:202
int32_t m_threads
control number of threads for ILP solver
Definition Coloring.h:244
virtual bool has_precolored() const
Definition Coloring.h:181
std::vector< int8_t > m_vColor
coloring solutions
Definition Coloring.h:240
virtual edge_weight_type calc_cost(std::vector< int8_t > const &vColor) const
Definition Coloring.h:397
virtual void color_num(ColorNumType cn)
Definition Coloring.h:168
void set_optimize_model(vector< GRBVar > &vColorBits, vector< GRBVar > &vEdgeBits, GRBLinExpr &obj, GRBModel &optModel)
Definition LPColoring.h:350
uint32_t m_lp_iters
record lp iterations
Definition LPColoring.h:224
bool refine_color(graph_edge_type const &e)
Definition LPColoring.h:819
uint32_t m_constrs_num
record number of constraints
Definition LPColoring.h:223
uint32_t check_precolored_num(vector< LPColoring< GraphType >::graph_vertex_type > const &vVertex) const
Definition LPColoring.h:911
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 rounding_with_binding_analysis(GRBModel &optModel, vector< GRBVar > &vColorBits, vector< GRBVar > &vEdgeBits)
Definition LPColoring.h:691
void print_solution(vector< GRBVar > const &vColorBits) const
Definition LPColoring.h:921
void add_odd_cycle_constraints(vector< GRBVar > const &vColorBits, GRBModel &optModel)
odd cycle trick from Prof. Baldick
Definition LPColoring.h:511
void solve_model(GRBModel &optModel)
solve model
Definition LPColoring.h:552
void set_anchor(vector< GRBVar > &vColorBits) const
Definition LPColoring.h:451
void non_integer_num(vector< GRBVar > const &vColorBits, vector< GRBVar > const &vEdgeBits, NonIntegerInfo &info) const
bool is_integer(double value) const
Definition LPColoring.h:214
void get_odd_cycles(graph_vertex_type const &v, vector< vector< graph_vertex_type > > &vOddCyle)
Definition LPColoring.h:239
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
void non_integer_num(vector< GRBVar > const &vVariables, uint32_t &nonIntegerNum, uint32_t &halfIntegerNum) const
LPColoring(graph_type const &g)
constructor
Definition LPColoring.h:229
uint32_t post_refinement()
greedy final coloring refinement
Definition LPColoring.h:798
graph_vertex_type max_degree_vertex() const
Definition LPColoring.h:332
boost::dynamic_bitset m_vVertexHandledByOddCycle
members
Definition LPColoring.h:222
void apply_solution(vector< GRBVar > const &vColorBits)
Definition LPColoring.h:675
void initialize()
create the NoStitchGraph (this->m_graph) from the (m_conflict_graph)
Boost.Geometry.
Definition GdsObjects.h:740
namespace for Limbo.Algorithms.Coloring
namespace for Limbo.algorithms
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,...
namespace for Limbo
std::iterator_traits< Iterator >::value_type max(Iterator first, Iterator last)
get max of an array
Definition Math.h:61
bool is_integer(string const &s)
check whether string represents an integer
Definition String.h:28
information for a variable of a constraint
Definition LPColoring.h:99
bool same_direction(ConstrVariableInfo const &rhs) const
Definition LPColoring.h:119
records the information of non-integer values
Definition LPColoring.h:83
uint32_t vertex_non_integer_num
number of vertices with non-integer solutions
Definition LPColoring.h:84
uint32_t vertex_half_integer_num
number of vertices with half-integer solutions
Definition LPColoring.h:86
uint32_t edge_non_integer_num
number of edges with non-integer solutions
Definition LPColoring.h:85
uint32_t edge_half_integer_num
number of edges with half-integer solutions
Definition LPColoring.h:87