19 #ifndef LIMBO_ALGORITHMS_COLORING_LP
20 #define LIMBO_ALGORITHMS_COLORING_LP
30 #include <boost/cstdint.hpp>
31 #include <boost/unordered_map.hpp>
32 #include <boost/graph/graph_concepts.hpp>
33 #include <boost/graph/subgraph.hpp>
34 #include <boost/property_map/property_map.hpp>
35 #include <boost/graph/bipartite.hpp>
36 #include "gurobi_c++.h"
45 using std::ostringstream;
47 using boost::unordered_map;
48 using boost::uint32_t;
61 template <
typename GraphType>
65 typedef GraphType graph_type;
67 typedef typename boost::graph_traits<graph_type>::vertex_descriptor graph_vertex_type;
68 typedef typename boost::graph_traits<graph_type>::edge_descriptor graph_edge_type;
72 typedef typename boost::property_map<graph_type, boost::edge_weight_t>::const_type edge_weight_map_type;
74 typedef typename boost::property_map<graph_type, boost::vertex_color_t>::const_type vertex_color_map_type;
90 struct edge_hash_type : std::unary_function<graph_edge_type, std::size_t>
92 std::size_t
operator()(graph_edge_type
const& e)
const
95 boost::hash_combine(seed, e.m_source);
96 boost::hash_combine(seed, e.m_target);
110 bool conflictCost()
const {
return m_conflict_cost;}
111 void conflictCost(
bool flag) {m_conflict_cost = flag;}
114 RoundingScheme roundingScheme()
const {
return m_rounding_scheme;}
115 void roundingScheme(RoundingScheme rs) {m_rounding_scheme = rs;}
120 void oddCycles(graph_vertex_type& v);
123 void graphColoring();
128 void ILPColoring(vector<GRBVar>& coloringBits, vector<GRBVar>& vEdgeBit);
131 void rounding_bindingAnalysis(GRBModel& opt_model, vector<GRBVar>& coloringBits, vector<GRBVar>& vEdgeBit);
138 void rounding_ILP(GRBModel& opt_model, vector<GRBVar>& coloringBits, vector<GRBVar>& vEdgeBit);
140 void rounding_Greedy_v0(vector<GRBVar>& coloringBits);
141 void rounding_Greedy(vector<GRBVar>& coloringBits);
144 uint32_t vertexColor(graph_vertex_type& node)
const;
145 uint32_t conflictNum()
const;
146 uint32_t stitchNum()
const;
148 uint32_t lpConflictNum()
const;
149 uint32_t lpStitchNum()
const;
151 void store_lp_coloring(vector<GRBVar>& coloringBits);
153 pair<uint32_t, uint32_t> nonIntegerNum(
const vector<GRBVar>& coloringBits,
const vector<GRBVar>& vEdgeBit)
const;
155 void printBoolVec(vector<bool>& vec)
const;
156 void printBoolArray(
bool* vec, uint32_t vec_size)
const;
158 void write_graph_dot(graph_vertex_type& v)
const;
159 void write_graph_dot()
const;
160 void write_graph_color()
const;
164 const uint32_t COLORING_BITS;
169 bool isInteger(
double value)
const {
return value == floor(value);}
171 bool sameColor(graph_vertex_type v1, graph_vertex_type v2)
const;
173 bool lpSameColor(graph_vertex_type v1, graph_vertex_type v2)
const;
175 bool hasConflict(graph_edge_type e)
const;
177 bool hasLPConflict(graph_edge_type e)
const;
179 bool hasStitch(graph_edge_type e)
const;
181 bool hasLPStitch(graph_edge_type e)
const;
187 unordered_map<graph_vertex_type, uint32_t> m_vertex_map;
188 unordered_map<uint32_t, graph_vertex_type> m_inverse_vertex_map;
190 unordered_map<graph_edge_type, uint32_t, edge_hash_type> m_edge_map;
192 edge_weight_map_type m_edge_weight_map;
194 vertex_color_map_type m_vertex_color_map;
196 unordered_map<graph_vertex_type, uint32_t> m_coloring;
198 vector<double> m_lp_coloring;
200 vector< vector<graph_vertex_type> > m_odd_cycles;
203 bool m_conflict_cost;
207 RoundingScheme m_rounding_scheme;
211 uint32_t m_lp_iter_cnt;
213 uint32_t m_ilp_iter_cnt;
216 unordered_map<string, bool> m_stitch_constrs;
221 template <
typename GraphType>
224 m_conflict_cost =
true;
226 m_rounding_scheme = FIXED_ILP;
235 template<
typename GraphType>
236 void LPColoring<GraphType>::setMap()
239 pair<typename graph_type::vertex_iterator, typename graph_type::vertex_iterator> vertex_range = vertices(m_graph);
240 m_vertex_map.clear();
241 m_inverse_vertex_map.clear();
242 uint32_t vertex_num = 0;
243 for(BOOST_AUTO(itr, vertex_range.first); itr != vertex_range.second; ++itr)
245 m_vertex_map[*itr] = vertex_num;
246 m_inverse_vertex_map[vertex_num] = *itr;
250 pair<typename graph_type::edge_iterator, typename graph_type::edge_iterator> edge_range = edges(m_graph);
252 uint32_t edge_num = 0;
253 for (BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
255 m_edge_map[*itr] = edge_num;
259 m_edge_weight_map =
get(boost::edge_weight, m_graph);
260 m_vertex_color_map =
get(boost::vertex_color, m_graph);
264 template<
typename GraphType>
265 void LPColoring<GraphType>::oddCycles(graph_vertex_type& v)
268 #ifdef DEBUG_LPCOLORING
269 assert(m_vertex_map.find(v) != m_vertex_map.end());
272 this->m_odd_cycles.clear();
275 uint32_t vertex_num = num_edges(m_graph);
276 int32_t nodeDist[vertex_num];
277 bool nodeVisited[vertex_num];
278 for(uint32_t k = 0; k < vertex_num; k++)
281 nodeVisited[k] =
false;
285 bool inCycle[vertex_num];
286 for(uint32_t k = 0; k < vertex_num; k++) inCycle[k] =
false;
289 vector<graph_vertex_type> dfs_stack;
290 dfs_stack.reserve(vertex_num);
291 uint32_t v_index = m_vertex_map[v];
292 nodeVisited[v_index] =
true;
293 nodeDist[v_index] = 0;
294 dfs_stack.push_back(v);
295 while(
false == dfs_stack.empty())
300 graph_vertex_type curr_v = dfs_stack.back();
301 uint32_t curr_index = m_vertex_map[curr_v];
303 typename boost::graph_traits<graph_type>::adjacency_iterator vi_begin, vi_end;
304 boost::tie(vi_begin, vi_end) = adjacent_vertices(curr_v, m_graph);
305 for(BOOST_AUTO(vi, vi_begin); vi != vi_end; ++vi)
307 BOOST_AUTO(found_edge, boost::edge(curr_v, *vi, m_graph));
308 #ifdef DEBUG_LPCOLORING
309 assert(found_edge.second);
312 if (m_edge_weight_map[found_edge.first] < 0)
continue;
314 uint32_t next_index = m_vertex_map[*vi];
315 if(nodeDist[next_index] < 0)
317 nodeDist[next_index] = 1 - nodeDist[curr_index];
318 nodeVisited[next_index] =
true;
320 dfs_stack.push_back(*vi);
329 for(BOOST_AUTO(vi, vi_begin); vi != vi_end; ++vi)
331 uint32_t next_index = m_vertex_map[*vi];
332 if(
true == nodeVisited[next_index] && (nodeDist[next_index] == nodeDist[curr_index]))
335 inCycle[v_index] =
true;
337 vector<graph_vertex_type> cycle;
338 int cnt = dfs_stack.size();
339 for(
int k = cnt - 1; k >= 0; k--)
341 cycle.push_back(dfs_stack[k]);
343 inCycle[m_vertex_map[dfs_stack[k]]] =
true;
344 if(dfs_stack[k] == (*vi))
break;
347 if(cycle.size() > 0 && inCycle[v_index])
349 this->m_odd_cycles.push_back(cycle);
351 else if(cycle.size() == 0)
353 cout <<
"ERROR: the cycle detected contains no nodes" << endl;
359 dfs_stack.pop_back();
360 nodeVisited[curr_index] =
false;
364 #ifdef DEBUG_LPCOLORING
365 if(m_odd_cycles.size() > 0) cout << m_odd_cycles.size() <<
" cycles detected." << endl;
366 else cout <<
"No cycles detected." << endl;
371 template<
typename GraphType>
372 void LPColoring<GraphType>::graphColoring()
379 m_vertex_map.clear(), m_inverse_vertex_map.clear();
380 uint32_t vertex_num = 0;
381 for(BOOST_AUTO(itr, vertex_range.first); itr != vertex_range.second; ++itr)
383 m_vertex_map[*itr] = vertex_num;
384 m_inverse_vertex_map[vertex_num] = *itr;
388 cout <<
"---------------------------------------Iterative LP based coloring scheme------------------------------------\n";
390 m_lp_iter_cnt = m_ilp_iter_cnt = 0;
392 uint32_t vertex_num = boost::num_vertices(m_graph);
393 uint32_t edge_num = boost::num_edges(m_graph);
394 uint32_t coloring_bits_num = COLORING_BITS*vertex_num;
398 GRBEnv env = GRBEnv();
401 GRBModel opt_model = GRBModel(env);
403 vector<GRBVar> coloringBits;
404 vector<GRBVar> vEdgeBit;
406 coloringBits.reserve(coloring_bits_num);
407 for (uint32_t i = 0; i != coloring_bits_num; ++i)
411 if (roundingScheme() == DIRECT_ILP)
412 coloringBits.push_back(opt_model.addVar(0.0, 1.0, 0.0, GRB_INTEGER, oss.str()));
414 coloringBits.push_back(opt_model.addVar(0.0, 1.0, 0.0, GRB_CONTINUOUS, oss.str()));
416 vEdgeBit.reserve(edge_num);
417 for (uint32_t i = 0; i != edge_num; ++i)
422 vEdgeBit.push_back(opt_model.addVar(0.0, 1.0, 0.0, GRB_CONTINUOUS, oss.str()));
426 pair<typename graph_type::edge_iterator, typename graph_type::edge_iterator> edge_range = edges(m_graph);
431 GRBLinExpr obj_init (0);
433 if (this->conflictCost())
435 for (BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
437 BOOST_AUTO(w, m_edge_weight_map[*itr]);
438 uint32_t edge_idx = m_edge_map[*itr];
440 obj_init += vEdgeBit[edge_idx];
443 for (BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
445 BOOST_AUTO(w, m_edge_weight_map[*itr]);
446 uint32_t edge_idx = m_edge_map[*itr];
448 obj_init += m_stitch_weight*vEdgeBit[edge_idx];
451 opt_model.setObjective(obj, GRB_MINIMIZE);
456 for(BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
458 BOOST_AUTO(from, source(*itr, m_graph));
459 uint32_t f_ind = m_vertex_map[from];
460 BOOST_AUTO(to, target(*itr, m_graph));
461 uint32_t t_ind = m_vertex_map[to];
463 uint32_t vertex_idx1 = f_ind<<1;
464 uint32_t vertex_idx2 = t_ind<<1;
466 BOOST_AUTO(w, m_edge_weight_map[*itr]);
469 string tmpConstr_name;
474 sprintf(buf,
"%u", m_constrs_num++);
475 tmpConstr_name =
"R" + string(buf);
476 tmpConstr = opt_model.addConstr(
477 coloringBits[vertex_idx1] + coloringBits[vertex_idx1+1]
478 + coloringBits[vertex_idx2] + coloringBits[vertex_idx2+1] >= 1
480 #ifdef DEBUG_LPCOLORING
481 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
483 m_stitch_constrs[tmpConstr_name] =
false;
485 sprintf(buf,
"%u", m_constrs_num++);
486 tmpConstr_name =
"R" + string(buf);
487 tmpConstr = opt_model.addConstr(
488 1 - coloringBits[vertex_idx1] + coloringBits[vertex_idx1+1]
489 + 1 - coloringBits[vertex_idx2] + coloringBits[vertex_idx2+1] >= 1
491 #ifdef DEBUG_LPCOLORING
492 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
494 m_stitch_constrs[tmpConstr_name] =
false;
496 sprintf(buf,
"%u", m_constrs_num++);
497 tmpConstr_name =
"R" + string(buf);
498 tmpConstr = opt_model.addConstr(
499 coloringBits[vertex_idx1] + 1 - coloringBits[vertex_idx1+1]
500 + coloringBits[vertex_idx2] + 1 - coloringBits[vertex_idx2+1] >= 1
502 #ifdef DEBUG_LPCOLORING
503 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
505 m_stitch_constrs[tmpConstr_name] =
false;
507 sprintf(buf,
"%u", m_constrs_num++);
508 tmpConstr_name =
"R" + string(buf);
509 tmpConstr = opt_model.addConstr(
510 1 - coloringBits[vertex_idx1] + 1 - coloringBits[vertex_idx1+1]
511 + 1 - coloringBits[vertex_idx2] + 1 - coloringBits[vertex_idx2+1] >= 1
513 #ifdef DEBUG_LPCOLORING
514 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
516 m_stitch_constrs[tmpConstr_name] =
false;
521 uint32_t edge_idx = m_edge_map[*itr];
523 sprintf(buf,
"%u", m_constrs_num++);
524 tmpConstr_name =
"R" + string(buf);
525 tmpConstr = opt_model.addConstr(
526 coloringBits[vertex_idx1] + coloringBits[vertex_idx1+1]
527 + coloringBits[vertex_idx2] + coloringBits[vertex_idx2+1]
528 + vEdgeBit[edge_idx] >= 1
530 #ifdef DEBUG_LPCOLORING
531 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
533 m_stitch_constrs[tmpConstr_name] =
false;
535 sprintf(buf,
"%u", m_constrs_num++);
536 tmpConstr_name =
"R" + string(buf);
537 tmpConstr = opt_model.addConstr(
538 1 - coloringBits[vertex_idx1] + coloringBits[vertex_idx1+1]
539 + 1 - coloringBits[vertex_idx2] + coloringBits[vertex_idx2+1]
540 + vEdgeBit[edge_idx] >= 1
542 #ifdef DEBUG_LPCOLORING
543 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
545 m_stitch_constrs[tmpConstr_name] =
false;
547 sprintf(buf,
"%u", m_constrs_num++);
548 tmpConstr_name =
"R" + string(buf);
549 tmpConstr = opt_model.addConstr(
550 coloringBits[vertex_idx1] + 1 - coloringBits[vertex_idx1+1]
551 + coloringBits[vertex_idx2] + 1 - coloringBits[vertex_idx2+1]
552 + vEdgeBit[edge_idx] >= 1
554 #ifdef DEBUG_LPCOLORING
555 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
557 m_stitch_constrs[tmpConstr_name] =
false;
559 sprintf(buf,
"%u", m_constrs_num++);
560 tmpConstr_name =
"R" + string(buf);
561 tmpConstr = opt_model.addConstr(
562 1 - coloringBits[vertex_idx1] + 1 - coloringBits[vertex_idx1+1]
563 + 1 - coloringBits[vertex_idx2] + 1 - coloringBits[vertex_idx2+1]
564 + vEdgeBit[edge_idx] >= 1
566 #ifdef DEBUG_LPCOLORING
567 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
569 m_stitch_constrs[tmpConstr_name] =
false;
575 uint32_t edge_idx = m_edge_map[*itr];
577 sprintf(buf,
"%u", m_constrs_num++);
578 tmpConstr_name =
"R" + string(buf);
579 tmpConstr = opt_model.addConstr(
580 coloringBits[vertex_idx1] - coloringBits[vertex_idx2] - vEdgeBit[edge_idx] <= 0
582 #ifdef DEBUG_LPCOLORING
583 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
585 m_stitch_constrs[tmpConstr_name] =
true;
587 sprintf(buf,
"%u", m_constrs_num++);
588 tmpConstr_name =
"R" + string(buf);
589 tmpConstr = opt_model.addConstr(
590 coloringBits[vertex_idx2] - coloringBits[vertex_idx1] - vEdgeBit[edge_idx] <= 0
592 #ifdef DEBUG_LPCOLORING
593 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
595 m_stitch_constrs[tmpConstr_name] =
true;
597 sprintf(buf,
"%u", m_constrs_num++);
598 tmpConstr_name =
"R" + string(buf);
599 tmpConstr = opt_model.addConstr(
600 coloringBits[vertex_idx1+1] - coloringBits[vertex_idx2+1] - vEdgeBit[edge_idx] <= 0
602 #ifdef DEBUG_LPCOLORING
603 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
605 m_stitch_constrs[tmpConstr_name] =
true;
607 sprintf(buf,
"%u", m_constrs_num++);
608 tmpConstr_name =
"R" + string(buf);
609 tmpConstr = opt_model.addConstr(
610 coloringBits[vertex_idx2+1] - coloringBits[vertex_idx1+1] - vEdgeBit[edge_idx] <= 0
612 #ifdef DEBUG_LPCOLORING
613 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
615 m_stitch_constrs[tmpConstr_name] =
true;
620 if (colorNum() == THREE)
623 string tmpConstr_name;
625 for(uint32_t k = 0; k < coloring_bits_num; k += COLORING_BITS)
627 sprintf(buf,
"%u", m_constrs_num++);
628 tmpConstr_name =
"R" + string(buf);
629 tmpConstr = opt_model.addConstr(coloringBits[k] + coloringBits[k+1] <= 1, tmpConstr_name);
630 #ifdef DEBUG_LPCOLORING
631 assert(m_stitch_constrs.find(tmpConstr_name) == m_stitch_constrs.end());
633 m_stitch_constrs[tmpConstr_name] =
false;
638 cout <<
"================== LP iteration #" << m_lp_iter_cnt++ <<
" ==================\n";
639 opt_model.optimize();
640 #ifdef DEBUG_LPCOLORING
641 opt_model.write(
"graph.lp");
642 opt_model.write(
"graph.sol");
644 int optim_status = opt_model.get(GRB_IntAttr_Status);
645 if(optim_status == GRB_INFEASIBLE)
647 cout <<
"ERROR: The model is infeasible... EXIT" << endl;
655 uint32_t non_integer_num, half_integer_num;
656 BOOST_AUTO(pair, this->nonIntegerNum(coloringBits, vEdgeBit));
657 non_integer_num = pair.first;
658 half_integer_num = pair.second;
659 if(non_integer_num == 0)
break;
661 this->store_lp_coloring(coloringBits);
671 #ifdef DEBUG_LPCOLORING
673 this->lpConflictNum();
674 this->write_graph_dot();
677 vector<bool> non_integer_flag(coloring_bits_num,
false);
682 for(uint32_t k = 0; k < coloring_bits_num; k += COLORING_BITS)
684 double value1 = coloringBits[k].get(GRB_DoubleAttr_X);
685 double value2 = coloringBits[k+1].get(GRB_DoubleAttr_X);
686 if (!isInteger(value1) || !isInteger(value2))
691 obj += coloringBits[k+1]-coloringBits[k];
693 else if (value1 < value2)
696 obj += coloringBits[k]-coloringBits[k+1];
698 if (value1 == 0.5) non_integer_flag[k] =
true;
699 if (value2 == 0.5) non_integer_flag[k+1] =
true;
705 obj = obj + 2*coloringBits[k];
706 non_integer_flag[k] =
false;
708 else if (value > 0.5)
711 obj = obj - 2*coloringBits[k];
712 non_integer_flag[k] =
false;
716 non_integer_flag[k] =
true;
724 for(BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
726 BOOST_AUTO(from, source(*itr, m_graph));
727 uint32_t f_ind = m_vertex_map[from];
728 BOOST_AUTO(to, target(*itr, m_graph));
729 uint32_t t_ind = m_vertex_map[to];
730 uint32_t vertex_idx1 = f_ind<<1;
731 uint32_t vertex_idx2 = t_ind<<1;
732 if (m_lp_coloring[vertex_idx1] > m_lp_coloring[vertex_idx2])
734 obj += coloringBits[vertex_idx2] - coloringBits[vertex_idx1];
736 else if (m_lp_coloring[vertex_idx1] < m_lp_coloring[vertex_idx2])
738 obj += coloringBits[vertex_idx1] - coloringBits[vertex_idx2];
743 if (m_lp_coloring[vertex_idx1] > m_lp_coloring[vertex_idx2])
745 obj += coloringBits[vertex_idx2] - coloringBits[vertex_idx1];
747 else if (m_lp_coloring[vertex_idx1] < m_lp_coloring[vertex_idx2])
749 obj += coloringBits[vertex_idx1] - coloringBits[vertex_idx2];
754 opt_model.setObjective(obj);
758 for(uint32_t k = 0; k < coloring_bits_num; k++)
761 if(
false == non_integer_flag[k])
continue;
763 uint32_t vertex_index = k/COLORING_BITS;
764 #ifdef DEBUG_LPCOLORING
765 assert(m_inverse_vertex_map.find(vertex_index) != m_inverse_vertex_map.end());
767 graph_vertex_type curr_v = m_inverse_vertex_map[vertex_index];
769 this->oddCycles(curr_v);
770 #ifdef DEBUG_LPCOLORING
771 this->write_graph_dot(curr_v);
774 uint32_t odd_cycle_cnt = m_odd_cycles.size();
775 for(uint32_t m = 0; m < odd_cycle_cnt; m++)
777 uint32_t cycle_len = m_odd_cycles[m].size();
778 GRBLinExpr constraint1 = 0;
779 GRBLinExpr constraint2 = 0;
780 #ifdef DEBUG_LPCOLORING
781 assert(cycle_len%2 == 1);
783 for(uint32_t n = 0; n < cycle_len; ++n)
785 #ifdef DEBUG_LPCOLORING
786 assert(m_vertex_map.find(m_odd_cycles[m][n]) != m_vertex_map.end());
788 uint32_t vi_index = m_vertex_map[m_odd_cycles[m][n]];
789 constraint1 += coloringBits[vi_index<<1];
790 constraint2 += coloringBits[(vi_index<<1)+1];
793 for(uint32_t x = 0; x < COLORING_BITS; x++)
795 non_integer_flag[vi_index*COLORING_BITS + x] =
false;
798 opt_model.addConstr(constraint1 >= 1);
799 opt_model.addConstr(constraint2 >= 1);
809 cout <<
"================== LP iteration #" << m_lp_iter_cnt++ <<
" ==================\n";
810 opt_model.optimize();
811 #ifdef DEBUG_LPCOLORING
812 opt_model.write(
"graph.lp");
813 opt_model.write(
"graph.sol");
815 optim_status = opt_model.get(GRB_IntAttr_Status);
816 if(optim_status == GRB_INFEASIBLE)
818 cout <<
"ERROR: the model is infeasible... EXIT" << endl;
824 uint32_t non_integer_num_updated, half_integer_num_updated;
825 pair = this->nonIntegerNum(coloringBits, vEdgeBit);
826 non_integer_num_updated = pair.first;
827 half_integer_num_updated = pair.second;
829 if ( half_integer_num_updated == 0 ||
830 (non_integer_num_updated >= non_integer_num && half_integer_num_updated >= half_integer_num))
break;
832 cout <<
"\n\n-----------------------------------Next iteration------------------------------" << endl;
836 this->store_lp_coloring(coloringBits);
847 #ifdef DEBUG_LPCOLORING
849 this->lpConflictNum();
850 this->write_graph_dot();
854 this->rounding_bindingAnalysis(opt_model, coloringBits, vEdgeBit);
855 if (roundingScheme() == DIRECT_ILP)
856 this->rounding_Greedy(coloringBits);
857 else if (roundingScheme() == FIXED_ILP)
858 this->ILPColoring(coloringBits, vEdgeBit);
859 else if (roundingScheme() == ITERATIVE_ILP)
860 this->rounding_ILP(opt_model, coloringBits, vEdgeBit);
861 else if (roundingScheme() == GREEDY)
862 this->rounding_Greedy(coloringBits);
866 this->write_graph_color();
867 #ifdef DEBUG_LPCOLORING
870 switch (roundingScheme())
873 cout <<
"DIRECT_ILP mode ";
break;
875 cout <<
"FIXED_ILP mode ";
break;
877 cout <<
"ITERATIVE_ILP mode ";
break;
879 cout <<
"GREEDY mode ";
break;
881 cout <<
"Unknown mode "; assert(0);
883 cout <<
"problem solved in " << m_lp_iter_cnt <<
" LP iterations, " << m_ilp_iter_cnt <<
" ILP iterations" << endl;
890 template<
typename GraphType>
891 void LPColoring<GraphType>::ILPColoring(vector<GRBVar>& coloringBits, vector<GRBVar>& vEdgeBit)
893 uint32_t coloring_bits_num = coloringBits.size();
896 GRBEnv env = GRBEnv();
899 GRBModel opt_model_updated = GRBModel(env);
901 vector<GRBVar> coloringBits_updated;
902 vector<GRBVar> vEdgeBit_updated;
904 coloringBits_updated.reserve(coloring_bits_num);
906 for(uint32_t k = 0; k < coloring_bits_num; k++)
910 double value = coloringBits[k].get(GRB_DoubleAttr_X);
914 coloringBits_updated.push_back(opt_model_updated.addVar(0.0, 0.0, 0.0, GRB_CONTINUOUS, oss.str()));
916 else if (value == 1.0)
919 coloringBits_updated.push_back(opt_model_updated.addVar(1.0, 1.0, 0.0, GRB_CONTINUOUS, oss.str()));
924 coloringBits_updated.push_back(opt_model_updated.addVar(0.0, 1.0, 0.0, GRB_INTEGER, oss.str()));
927 uint32_t edge_num = vEdgeBit.size();
928 vEdgeBit_updated.reserve(edge_num);
929 for (uint32_t i = 0; i != edge_num; ++i)
935 vEdgeBit_updated.push_back(opt_model_updated.addVar(0.0, 1.0, 0.0, GRB_CONTINUOUS, oss.str()));
938 opt_model_updated.update();
940 pair<typename graph_type::edge_iterator, typename graph_type::edge_iterator> edge_range = edges(m_graph);
942 GRBLinExpr obj_init (0);
943 for (BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
945 BOOST_AUTO(w, m_edge_weight_map[*itr]);
946 uint32_t edge_idx = m_edge_map[*itr];
948 obj_init += vEdgeBit_updated[edge_idx];
950 obj_init += m_stitch_weight*vEdgeBit_updated[edge_idx];
952 opt_model_updated.setObjective(obj_init, GRB_MINIMIZE);
954 for(BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
956 BOOST_AUTO(from, source(*itr, m_graph));
957 uint32_t f_ind = m_vertex_map[from];
958 BOOST_AUTO(to, target(*itr, m_graph));
959 uint32_t t_ind = m_vertex_map[to];
961 uint32_t vertex_idx1 = f_ind<<1;
962 uint32_t vertex_idx2 = t_ind<<1;
964 BOOST_AUTO(w, m_edge_weight_map[*itr]);
967 uint32_t edge_idx = m_edge_map[*itr];
968 opt_model_updated.addConstr(
969 coloringBits_updated[vertex_idx1] + coloringBits_updated[vertex_idx1+1]
970 + coloringBits_updated[vertex_idx2] + coloringBits_updated[vertex_idx2+1]
971 + vEdgeBit_updated[edge_idx] >= 1
973 opt_model_updated.addConstr(
974 1 - coloringBits_updated[vertex_idx1] + coloringBits_updated[vertex_idx1+1]
975 + 1 - coloringBits_updated[vertex_idx2] + coloringBits_updated[vertex_idx2+1]
976 + vEdgeBit_updated[edge_idx] >= 1
978 opt_model_updated.addConstr(
979 coloringBits_updated[vertex_idx1] + 1 - coloringBits_updated[vertex_idx1+1]
980 + coloringBits_updated[vertex_idx2] + 1 - coloringBits_updated[vertex_idx2+1]
981 + vEdgeBit_updated[edge_idx] >= 1
983 opt_model_updated.addConstr(
984 1 - coloringBits_updated[vertex_idx1] + 1 - coloringBits_updated[vertex_idx1+1]
985 + 1 - coloringBits_updated[vertex_idx2] + 1 - coloringBits_updated[vertex_idx2+1]
986 + vEdgeBit_updated[edge_idx] >= 1
991 uint32_t edge_idx = m_edge_map[*itr];
992 opt_model_updated.addConstr(
993 coloringBits_updated[vertex_idx1] - coloringBits_updated[vertex_idx2] - vEdgeBit_updated[edge_idx] <= 0
995 opt_model_updated.addConstr(
996 coloringBits_updated[vertex_idx2] - coloringBits_updated[vertex_idx1] - vEdgeBit_updated[edge_idx] <= 0
998 opt_model_updated.addConstr(
999 coloringBits_updated[vertex_idx1+1] - coloringBits_updated[vertex_idx2+1] - vEdgeBit_updated[edge_idx] <= 0
1001 opt_model_updated.addConstr(
1002 coloringBits_updated[vertex_idx2+1] - coloringBits_updated[vertex_idx1+1] - vEdgeBit_updated[edge_idx] <= 0
1006 if (colorNum() == THREE)
1008 for(uint32_t k = 0; k < coloring_bits_num; k += COLORING_BITS)
1010 opt_model_updated.addConstr(coloringBits_updated[k] + coloringBits_updated[k+1] <= 1);
1014 opt_model_updated.update();
1016 #ifdef DEBUG_LPCOLORING
1017 opt_model_updated.write(
"graph_ilp.lp");
1021 cout <<
"================== ILP iteration #" << m_ilp_iter_cnt++ <<
" ==================\n";
1022 opt_model_updated.optimize();
1023 int optim_status = opt_model_updated.get(GRB_IntAttr_Status);
1024 if(optim_status == GRB_INFEASIBLE)
1026 cout <<
"ERROR: The model is infeasible... EXIT" << endl;
1030 cout <<
"ILP solved to seek a coloring solution." << endl;
1033 this->store_lp_coloring(coloringBits_updated);
1035 for(uint32_t k = 0; k < coloring_bits_num; k = k + COLORING_BITS) {
1036 uint32_t vertex_index = k/COLORING_BITS;
1037 graph_vertex_type vertex_key = this->m_inverse_vertex_map[vertex_index];
1040 for(uint32_t m = 0; m < COLORING_BITS; m++) {
1041 double value = coloringBits_updated[k+m].get(GRB_DoubleAttr_X);
1042 #if DEBUG_LPCOLORING
1043 assert(value == 0.0 || value == 1.0);
1045 if(value == 1.0) color = color + base;
1049 this->m_coloring[vertex_key] = color;
1054 template<
typename GraphType>
1055 void LPColoring<GraphType>::rounding_bindingAnalysis(GRBModel& opt_model, vector<GRBVar>& coloringBits, vector<GRBVar>& vEdgeBit) {
1056 cout <<
"\n\n---------------------------------------Optimal rounding from binding analysis------------------------------------\n";
1066 uint32_t non_integer_num, half_integer_num;
1067 uint32_t non_integer_num_updated, half_integer_num_updated;
1171 BOOST_AUTO(pair, this->nonIntegerNum(coloringBits, vEdgeBit));
1172 non_integer_num = pair.first;
1173 half_integer_num = pair.second;
1174 if(non_integer_num == 0)
return;
1176 this->store_lp_coloring(coloringBits);
1179 bool rounding_flag =
true;
1180 double bit1 = 0.0, bit2 = 0.0;
1181 uint32_t variable_num = coloringBits.size();
1182 for(uint32_t k = 0; k < variable_num; k = k + COLORING_BITS) {
1183 double value1 = coloringBits[k].get(GRB_DoubleAttr_X);
1184 double value2 = coloringBits[k+1].get(GRB_DoubleAttr_X);
1185 if(isInteger(value1) && isInteger(value2))
continue;
1186 #ifdef DEBUG_LPCOLORING
1191 GRBColumn column1 = opt_model.getCol(coloringBits[k]);
1192 GRBColumn column2 = opt_model.getCol(coloringBits[k+1]);
1193 int column1_size = column1.size();
1194 int column2_size = column2.size();
1198 unordered_map<string, bool> constrs_flag1;
1199 unordered_map<string, double> constrs_coeff1;
1200 unordered_map<string, char> constrs_sense1;
1201 unordered_map<string, bool> constrs_flag2;
1202 unordered_map<string, double> constrs_coeff2;
1203 unordered_map<string, char> constrs_sense2;
1205 #ifdef DEBUG_LPCOLORING
1206 cout << endl << endl << k <<
"th non-integer variable" << endl;
1208 for(
int m = 0; m < column1_size; m++) {
1209 GRBConstr constr = column1.getConstr(m);
1210 double slack = constr.get(GRB_DoubleAttr_Slack);
1212 if(slack != 0.0)
continue;
1213 double coeff = opt_model.getCoeff(constr, coloringBits[k]);
1214 char sense = constr.get(GRB_CharAttr_Sense);
1215 #ifdef DEBUG_LPCOLORING
1216 cout <<
"The slack for " << constr.get(GRB_StringAttr_ConstrName) <<
": " << slack << endl;
1217 cout <<
"The constraint sense for " << constr.get(GRB_StringAttr_ConstrName) <<
": " << sense << endl;
1218 cout <<
"The coefficient for " << constr.get(GRB_StringAttr_ConstrName) <<
": " << coeff << endl << endl;
1220 #ifdef DEBUG_LPCOLORING
1221 assert(coeff == 1.0 || coeff == -1.0);
1222 assert(sense ==
'>' || sense ==
'<');
1224 string name = constr.get(GRB_StringAttr_ConstrName);
1225 constrs_flag1[name] =
false;
1226 constrs_coeff1[name] = coeff;
1227 constrs_sense1[name] = sense;
1230 #ifdef DEBUG_LPCOLORING
1231 cout << endl << endl << (k+1) <<
"th non-integer variable" << endl;
1234 for(
int m = 0; m < column2_size; m++) {
1235 GRBConstr constr = column2.getConstr(m);
1236 double slack = constr.get(GRB_DoubleAttr_Slack);
1238 if(slack != 0.0)
continue;
1239 double coeff = opt_model.getCoeff(constr, coloringBits[k+1]);
1240 char sense = constr.get(GRB_CharAttr_Sense);
1241 #ifdef DEBUG_LPCOLORING
1242 cout <<
"The slack for " << constr.get(GRB_StringAttr_ConstrName) <<
": " << slack << endl;
1243 cout <<
"The constraint sense for " << constr.get(GRB_StringAttr_ConstrName) <<
": " << sense << endl;
1244 cout <<
"The coefficient for " << constr.get(GRB_StringAttr_ConstrName) <<
": " << coeff << endl << endl;
1246 #ifdef DEBUG_LPCOLORING
1247 assert(coeff == 1.0 || coeff == -1.0);
1248 assert(sense ==
'>' || sense ==
'<');
1250 string name = constr.get(GRB_StringAttr_ConstrName);
1251 if(constrs_flag1.find(name) == constrs_flag1.end())
1253 constrs_flag2[name] =
false;
1254 constrs_coeff2[name] = coeff;
1255 constrs_sense2[name] = sense;
1259 constrs_flag1[name] =
true;
1260 constrs_flag2[name] =
true;
1261 constrs_coeff2[name] = coeff;
1262 constrs_sense2[name] = sense;
1267 unordered_map<string, double> shared_constrs_coeff1;
1268 unordered_map<string, char> shared_constrs_sense1;
1269 BOOST_AUTO(end, constrs_flag1.end());
1270 for(BOOST_AUTO(itr, constrs_flag1.begin()); itr != end; ++itr) {
1272 if(
true == itr->second)
1274 shared_constrs_coeff1[itr->first] = constrs_coeff1[itr->first];
1275 shared_constrs_sense1[itr->first] = constrs_sense1[itr->first];
1278 if(-1.0 == constrs_coeff1[itr->first])
1281 constrs_coeff1[itr->first] = 1.0;
1282 if(constrs_sense1[itr->first] ==
'<') constrs_sense1[itr->first] =
'>';
1283 else constrs_sense1[itr->first] =
'<';
1287 unordered_map<string, double> shared_constrs_coeff2;
1288 unordered_map<string, double> shared_constrs_sense2;
1289 end = constrs_flag2.end();
1290 for(BOOST_AUTO(itr, constrs_flag2.begin()); itr != end; ++itr) {
1292 if(
true == itr->second)
1294 shared_constrs_coeff2[itr->first] = constrs_coeff2[itr->first];
1295 shared_constrs_sense2[itr->first] = constrs_sense2[itr->first];
1298 if(-1.0 == constrs_coeff2[itr->first])
1301 constrs_coeff2[itr->first] = 1.0;
1302 if(constrs_sense2[itr->first] ==
'<') constrs_sense2[itr->first] =
'>';
1303 else constrs_sense2[itr->first] =
'<';
1306 #ifdef DEBUG_LPCOLORING
1307 assert(shared_constrs_coeff1.size() == shared_constrs_coeff2.size());
1311 bool rounding_flag1 =
true;
1312 char pre_sense1 =
'=';
1313 bool pre_sense_flag =
false;
1314 end = constrs_flag1.end();
1315 for(BOOST_AUTO(itr, constrs_flag1.begin()); itr != end; ++itr) {
1317 if(
true == itr->second)
continue;
1318 #ifdef DEBUG_LPCOLORING
1319 assert(1.0 == constrs_coeff1[itr->first]);
1321 if(
false == pre_sense_flag)
1323 pre_sense1 = constrs_sense1[itr->first];
1324 pre_sense_flag =
true;
1328 if(pre_sense1 != constrs_sense1[itr->first]) {
1329 rounding_flag1 =
false;
1336 bool rounding_flag2 =
true;
1337 char pre_sense2 =
'=';
1338 pre_sense_flag =
false;
1339 end = constrs_flag2.end();
1340 for(BOOST_AUTO(itr, constrs_flag2.begin()); itr != end; ++itr) {
1342 if(
true == itr->second)
continue;
1343 #ifdef DEBUG_LPCOLORING
1344 assert(1.0 == constrs_coeff2[itr->first]);
1346 if(
false == pre_sense_flag)
1348 pre_sense2 = constrs_sense2[itr->first];
1349 pre_sense_flag =
true;
1353 if(pre_sense2 != constrs_sense2[itr->first]) {
1354 rounding_flag2 =
false;
1361 rounding_flag = rounding_flag1 & rounding_flag2;
1362 if(
false == rounding_flag)
break;
1366 bool bit_pair_flag =
false;
1367 bit1 = 0.0, bit2 = 0.0;
1368 for(bit1 = 0.0; bit1 <= 1.0; bit1 = bit1 + 1.0) {
1369 if(pre_sense1 ==
'<' && bit1 == 1.0)
continue;
1370 if(pre_sense1 ==
'>' && bit1 == 0.0)
continue;
1371 for(bit2 = 0.0; bit2 <= 1.0; bit2 = bit2 + 1.0) {
1372 if(pre_sense2 ==
'<' && bit2 == 1.0)
continue;
1373 if(pre_sense2 ==
'>' && bit2 == 0.0)
continue;
1374 cout <<
"bit1: " << bit1 <<
"; bit2: " << bit2 << endl;
1375 if (colorNum() == THREE && (bit1 == 1.0) && (bit2 == 1.0))
continue;
1377 BOOST_AUTO(itr_end, shared_constrs_coeff1.end());
1378 for(BOOST_AUTO(itr, shared_constrs_coeff1.begin()); itr != itr_end; ++itr) {
1379 double delta_value = itr->second * (bit1 - value1) + shared_constrs_coeff2[itr->first] * (bit2 - value2);
1380 char sense = shared_constrs_sense1[itr->first];
1381 if(delta_value < 0 && sense == '>
') {
1382 rounding_flag = false;
1385 if(delta_value > 0 && sense == '<
') {
1386 rounding_flag = false;
1390 bit_pair_flag = true;
1391 if(true == rounding_flag) break;
1393 if(true == rounding_flag) break;
1395 //rounding the first feasible variable
1396 if(true == rounding_flag && true == bit_pair_flag) {
1397 #ifdef DEBUG_LPCOLORING
1399 coloringBits[k].set(GRB_DoubleAttr_UB, bit1);
1400 coloringBits[k].set(GRB_DoubleAttr_LB, bit1);
1401 coloringBits[k+1].set(GRB_DoubleAttr_UB, bit2);
1402 coloringBits[k+1].set(GRB_DoubleAttr_LB, bit2);
1407 if(true == rounding_flag) {
1408 //update the model and optimize
1410 opt_model.optimize();
1411 #ifdef DEBUG_LPCOLORING
1412 opt_model.write("graph.lp");
1413 opt_model.write("graph.sol");
1414 this->store_lp_coloring(coloringBits);
1415 this->write_graph_dot();
1417 int optim_status = opt_model.get(GRB_IntAttr_Status);
1418 if(optim_status == GRB_INFEASIBLE)
1420 cout << "ERROR: the model after binding analysis is infeasible... Quit ILP based rounding" << endl;
1425 //no more non-integers are removed
1426 pair = this->nonIntegerNum(coloringBits, vEdgeBit);
1427 non_integer_num_updated = pair.first;
1428 half_integer_num_updated = pair.second;
1429 if (/*non_integer_num_updated == 0*/ half_integer_num_updated == 0 ||
1430 (non_integer_num_updated >= non_integer_num && half_integer_num_updated >= half_integer_num)) break;
1435 this->store_lp_coloring(coloringBits);
1440 template<typename GraphType>
1441 void LPColoring<GraphType>::rounding_ILP(GRBModel& opt_model, vector<GRBVar>& coloringBits, vector<GRBVar>& vEdgeBit)
1443 cout << "\n\n---------------------------------------ILP rounding scheme------------------------------------\n";
1444 uint32_t non_integer_num, half_integer_num;
1445 uint32_t non_integer_num_updated, half_integer_num_updated;
1448 BOOST_AUTO(pair, this->nonIntegerNum(coloringBits, vEdgeBit));
1449 non_integer_num = pair.first;
1450 half_integer_num = pair.second;
1451 if(non_integer_num == 0) break;
1452 //store the lp coloring results
1453 this->store_lp_coloring(coloringBits);
1454 #ifdef DEBUG_LPCOLORING
1455 // compare unrounded conflict number is more fair
1456 this->lpConflictNum();
1458 //update the ILP model
1459 uint32_t coloring_bits_num = coloringBits.size();
1460 for(uint32_t k = 0; k < coloring_bits_num; ++k)
1462 double value = coloringBits[k].get(GRB_DoubleAttr_X);
1463 if(value == 1.0 || value == 0.0)
1465 coloringBits[k].set(GRB_CharAttr_VType, 'C
');
1469 coloringBits[k].set(GRB_CharAttr_VType, 'I
');
1473 #ifdef DEBUG_LPCOLORING
1474 opt_model.write("graph_ilp.lp");
1476 cout << "================== ILP iteration #" << m_ilp_iter_cnt++ << " ==================\n";
1477 opt_model.optimize();
1478 int optim_status = opt_model.get(GRB_IntAttr_Status);
1479 if(optim_status == GRB_INFEASIBLE)
1481 cout << "ERROR: the ILP model is infeasible... Quit ILP based rounding" << endl;
1482 #ifdef DEBUG_LPCOLORING
1483 opt_model.computeIIS();
1484 opt_model.write("graph_ilp.ilp");
1489 //no more non-integers are removed
1490 pair = this->nonIntegerNum(coloringBits, vEdgeBit);
1491 non_integer_num_updated = pair.first;
1492 half_integer_num_updated = pair.second;
1493 if (/*non_integer_num_updated == 0*/ half_integer_num_updated == 0 ||
1494 (non_integer_num_updated >= non_integer_num && half_integer_num_updated >= half_integer_num)) break;
1497 //final greedy rounding
1498 this->rounding_Greedy(coloringBits);
1501 //greedy rounding scheme, need better scheme later on
1502 template<typename GraphType>
1503 void LPColoring<GraphType>::rounding_Greedy_v0(vector<GRBVar>& coloringBits)
1505 cout << "\n\n---------------------------------------Greedy rounding scheme------------------------------------\n";
1507 //greedy rounding scheme
1508 uint32_t vec_size = coloringBits.size();
1509 //the rounding results
1510 vector<bool> coloringBinary(vec_size, false);
1511 //the flag denoting whether current bit is rounded or not
1512 vector<bool> roundingFlag(vec_size, false);
1514 for(uint32_t k = 0; k < vec_size; k++)
1516 double value = coloringBits[k].get(GRB_DoubleAttr_X);
1519 coloringBinary[k] = false;
1520 roundingFlag[k] = true;
1522 else if (1.0 == value)
1524 coloringBinary[k] = true;
1525 roundingFlag[k] = true;
1529 coloringBinary[k] = false;
1530 roundingFlag[k] = false;
1534 //rounding of the half integer
1535 //greedy rounding schme should minimize the conflict and stitch number
1536 for(uint32_t k = 0; k < vec_size; k++)
1538 if(true == roundingFlag[k]) continue;
1539 #ifdef DEBUG_LPCOLORING
1540 //this->printBoolArray(roundingFlag, vec_size);
1541 //this->printBoolArray(coloringBinary, vec_size);
1542 //cout << endl << endl;
1544 //greedy rounding scheme
1545 uint32_t vertex_index = k/COLORING_BITS;
1546 vector<bool> color_bits;
1547 color_bits.reserve(COLORING_BITS);
1548 vector<bool> best_bits;
1549 best_bits.reserve(COLORING_BITS);
1550 //initialize the color_bits
1551 for(uint32_t m = 0; m < COLORING_BITS; ++m)
1553 color_bits.push_back(coloringBinary[vertex_index*COLORING_BITS + m]);
1557 typename boost::graph_traits<graph_type>::adjacency_iterator vi_begin, vi_end;
1558 BOOST_AUTO(vertex_key, m_inverse_vertex_map[vertex_index]);
1559 boost::tie(vi_begin, vi_end) = adjacent_vertices(vertex_key, m_graph);
1560 //calculate the current
1561 uint32_t same_color_bound = std::numeric_limits<uint32_t>::max();
1562 uint32_t same_color_count = 0;
1567 same_color_bound = std::numeric_limits<uint32_t>::max();
1568 same_color_count = 0;
1571 for(uint32_t m = 0; m < COLORING_BITS; ++m)
1573 if(color_bits[m]) color = color + base;
1576 //check the same color neighbors
1577 for(BOOST_AUTO(vi, vi_begin); vi != vi_end; ++vi)
1579 if(this->m_coloring.find(*vi) == m_vertex_map.end()) continue;
1580 if(this->m_coloring[*vi] == color) same_color_count++;
1582 //assign better color
1583 if(same_color_count < same_color_bound)
1585 same_color_bound = same_color_count;
1586 best_bits = color_bits;
1589 //explore the next color_bits
1590 bool nextFlag = false;
1591 for(uint32_t m = 0; m < COLORING_BITS; ++m)
1593 if(color_bits[m] == false && roundingFlag[vertex_index*COLORING_BITS + m] == false)
1595 //flip the color bit that has not be rounded
1596 color_bits[m] = true;
1598 //for Triple patterning mode
1599 if((colorNum() == THREE) && (m == COLORING_BITS - 1)) nextFlag = false;
1603 //all the color_bits are explored
1604 if(nextFlag == false) break;
1607 //the vertex is colored
1610 for(uint32_t m = 0; m < COLORING_BITS; m++)
1612 coloringBinary[vertex_index*COLORING_BITS + m] = best_bits[m];
1613 roundingFlag[vertex_index*COLORING_BITS + m] = true;
1614 if(best_bits[m]) color = color + base;
1617 #ifdef DEBUG_LPCOLORING
1620 this->m_coloring[vertex_key] = color;
1623 //assign the coloring results
1624 for(uint32_t k = 0; k < vec_size; k = k + COLORING_BITS)
1626 BOOST_AUTO(vertex_key, this->m_inverse_vertex_map[(k/COLORING_BITS)]);
1629 for(uint32_t m = 0; m < COLORING_BITS; ++m)
1631 if(coloringBinary[k + m]) {
1632 this->m_lp_coloring[k + m] = 1.0;
1633 color = color + base;
1635 this->m_lp_coloring[k + m] = 0.0;
1639 if(this->m_coloring.find(vertex_key) == this->m_coloring.end())
1640 this->m_coloring[vertex_key] = color;
1641 #ifdef DEBUG_LPCOLORING
1644 //cout << "stored color-" << this->m_coloring[vertex_key] << " vs assigned color-" << color << endl;
1645 assert(this->m_coloring[vertex_key] == color);
1651 template<typename GraphType>
1652 void LPColoring<GraphType>::rounding_Greedy(vector<GRBVar>& coloringBits)
1654 cout << "\n\n---------------------------------------Greedy rounding scheme------------------------------------\n";
1656 //greedy rounding scheme
1657 uint32_t vec_size = coloringBits.size();
1658 this->store_lp_coloring(coloringBits);
1660 //greedy rounding schme should minimize the conflict and stitch number
1661 for(uint32_t k = 0; k < vec_size; k = k + COLORING_BITS)
1663 double value1 = coloringBits[k].get(GRB_DoubleAttr_X);
1664 double value2 = coloringBits[k+1].get(GRB_DoubleAttr_X);
1665 if(isInteger(value1) && isInteger(value2)) continue;
1666 //greedy rounding scheme
1667 uint32_t vertex_index = k/COLORING_BITS;
1670 typename boost::graph_traits<graph_type>::adjacency_iterator vi_begin, vi_end;
1671 BOOST_AUTO(vertex_key, m_inverse_vertex_map[vertex_index]);
1672 boost::tie(vi_begin, vi_end) = adjacent_vertices(vertex_key, m_graph);
1673 //calculate the current
1674 uint32_t same_color_bound = std::numeric_limits<uint32_t>::max();
1675 uint32_t same_color_count = 0;
1676 double best_bit1 = 0.0, best_bit2 = 0.0;
1678 for(double bit1 = 0.0; bit1 <= 1.0; bit1 = bit1 + 1.0)
1680 if(isInteger(value1) && (bit1 != value1)) continue;
1681 for(double bit2 = 0.0; bit2 <= 1.0; bit2 = bit2 + 1.0)
1683 if(isInteger(value2) && (bit2 != value2)) continue;
1684 if (colorNum() == THREE && (bit1 == 1.0) && (bit2 == 1.0)) continue;
1685 same_color_count = 0;
1686 //cout << endl << "current_index: " << vertex_index << ", bits: " << bit1 << bit2 << endl;
1687 //check the same color neighbors
1688 for(BOOST_AUTO(vi, vi_begin); vi != vi_end; ++vi)
1690 #ifdef DEBUG_LPCOLORING
1691 assert(this->m_vertex_map.find(*vi) != m_vertex_map.end());
1693 uint32_t neighbor_index = this->m_vertex_map[*vi];
1694 //same color neighbor
1695 if((m_lp_coloring[2*neighbor_index] == bit1) && (m_lp_coloring[2*neighbor_index+1] == bit2))
1698 //cout << "conflict neighbor_index: " << neighbor_index << endl;
1701 //assign better color
1702 if(same_color_count < same_color_bound)
1704 same_color_bound = same_color_count;
1711 //the vertex is colored
1712 this->m_lp_coloring[k] = best_bit1;
1713 this->m_lp_coloring[k+1] = best_bit2;
1716 //assign the coloring results
1717 for(uint32_t k = 0; k < vec_size; k = k + COLORING_BITS)
1719 BOOST_AUTO(vertex_key, this->m_inverse_vertex_map[(k/COLORING_BITS)]);
1722 for(uint32_t m = 0; m < COLORING_BITS; ++m)
1724 #ifdef DEBUG_LPCOLORING
1725 assert(isInteger(this->m_lp_coloring[k + m]));
1727 if(this->m_lp_coloring[k + m] == 1.0) color = color + base;
1730 if(this->m_coloring.find(vertex_key) == this->m_coloring.end())
1731 this->m_coloring[vertex_key] = color;
1732 #ifdef DEBUG_LPCOLORING
1735 //cout << "stored color-" << this->m_coloring[vertex_key] << " vs assigned color-" << color << endl;
1736 assert(this->m_coloring[vertex_key] == color);
1744 //get the vertex color
1745 template<typename GraphType>
1746 uint32_t LPColoring<GraphType>::vertexColor(graph_vertex_type& node) const
1748 //the graph is not colored
1749 if(this->m_coloring.empty()) return 0; //this->graphColoring(m_graph);
1750 return this->m_coloring.at(node);
1753 template <typename GraphType>
1754 bool LPColoring<GraphType>::sameColor(typename LPColoring<GraphType>::graph_vertex_type v1,
1755 typename LPColoring<GraphType>::graph_vertex_type v2) const
1757 assert(!m_coloring.empty());
1758 #ifdef DEBUG_LPCOLORING
1759 assert(this->m_coloring.find(v1) != this->m_coloring.end());
1760 assert(this->m_coloring.find(v2) != this->m_coloring.end());
1762 return m_coloring.at(v1) == m_coloring.at(v2);
1765 template <typename GraphType>
1766 bool LPColoring<GraphType>::hasConflict(typename LPColoring<GraphType>::graph_edge_type e) const
1768 BOOST_AUTO(w, m_edge_weight_map[e]);
1769 // skip stitch edges
1770 if (w < 0) return false;
1772 BOOST_AUTO(from, source(e, m_graph));
1773 BOOST_AUTO(to, target(e, m_graph));
1774 return sameColor(from, to);
1777 template <typename GraphType>
1778 bool LPColoring<GraphType>::hasStitch(typename LPColoring<GraphType>::graph_edge_type e) const
1780 BOOST_AUTO(w, m_edge_weight_map[e]);
1781 // skip conflict edges
1782 if (w >= 0) return false;
1784 BOOST_AUTO(from, source(e, m_graph));
1785 BOOST_AUTO(to, target(e, m_graph));
1786 return !sameColor(from, to);
1789 //report the conflict number
1790 template<typename GraphType>
1791 uint32_t LPColoring<GraphType>::conflictNum() const
1793 //the graph is not colored
1794 if (this->m_coloring.empty()) return 0; //this->graphColoring();
1795 //check the coloring results
1796 uint32_t conflict_edge_num = 0;
1797 uint32_t conflict_num = 0;
1798 pair<typename graph_type::edge_iterator, typename graph_type::edge_iterator> edge_range = edges(m_graph);
1799 for(BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
1801 if (hasConflict(*itr))
1803 ++conflict_edge_num;
1805 cout << "Conflict number: " << conflict_num << " out of " << conflict_edge_num << " conflict edges" << endl;
1806 return conflict_num;
1809 //report the stitch number
1810 template<typename GraphType>
1811 uint32_t LPColoring<GraphType>::stitchNum() const
1813 //the graph is not colored
1814 if(this->m_coloring.empty()) return 0; //this->graphColoring(m_graph);
1816 //check the coloring results
1817 uint32_t stitch_edge_num = 0;
1818 uint32_t stitch_num = 0;
1819 pair<typename graph_type::edge_iterator, typename graph_type::edge_iterator> edge_range = edges(m_graph);
1820 for(BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
1822 if (hasStitch(*itr))
1826 cout << "Stitch number: " << stitch_num << " out of " << stitch_edge_num << " stitch edges" << endl;
1830 template <typename GraphType>
1831 bool LPColoring<GraphType>::lpSameColor(typename LPColoring<GraphType>::graph_vertex_type v1,
1832 typename LPColoring<GraphType>::graph_vertex_type v2) const
1834 assert(!m_lp_coloring.empty());
1836 uint32_t f_ind = m_vertex_map.at(v1);
1837 uint32_t t_ind = m_vertex_map.at(v2);
1838 uint32_t vertex_idx1 = f_ind<<1;
1839 uint32_t vertex_idx2 = t_ind<<1;
1841 return m_lp_coloring.at(vertex_idx1) == m_lp_coloring.at(vertex_idx2)
1842 && m_lp_coloring.at(vertex_idx1+1) == m_lp_coloring.at(vertex_idx2+1);
1845 template <typename GraphType>
1846 bool LPColoring<GraphType>::hasLPConflict(typename LPColoring<GraphType>::graph_edge_type e) const
1848 BOOST_AUTO(w, m_edge_weight_map[e]);
1849 // skip stitch edges
1850 if (w < 0) return false;
1852 BOOST_AUTO(from, source(e, m_graph));
1853 BOOST_AUTO(to, target(e, m_graph));
1854 return lpSameColor(from, to);
1857 template <typename GraphType>
1858 bool LPColoring<GraphType>::hasLPStitch(typename LPColoring<GraphType>::graph_edge_type e) const
1860 BOOST_AUTO(w, m_edge_weight_map[e]);
1861 // skip conflict edges
1862 if (w >= 0) return false;
1864 BOOST_AUTO(from, source(e, m_graph));
1865 BOOST_AUTO(to, target(e, m_graph));
1866 return !lpSameColor(from, to);
1869 //report the unrounded LP conflict number
1870 template<typename GraphType>
1871 uint32_t LPColoring<GraphType>::lpConflictNum() const
1873 if (m_lp_coloring.empty()) return 0;
1874 //check the coloring results
1875 uint32_t conflict_edge_num = 0;
1876 uint32_t conflict_num = 0;
1877 pair<typename graph_type::edge_iterator, typename graph_type::edge_iterator> edge_range = edges(m_graph);
1878 for(BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
1880 if (hasLPConflict(*itr))
1882 ++conflict_edge_num;
1884 cout << "LP Conflict number: " << conflict_num << " out of " << conflict_edge_num << " conflict edges" << endl;
1885 return conflict_num;
1888 //report the unrounded LP stitch number
1889 template<typename GraphType>
1890 uint32_t LPColoring<GraphType>::lpStitchNum() const
1892 if (m_lp_coloring.empty()) return 0;
1893 //check the coloring results
1894 uint32_t stitch_edge_num = 0;
1895 uint32_t stitch_num = 0;
1896 pair<typename graph_type::edge_iterator, typename graph_type::edge_iterator> edge_range = edges(m_graph);
1897 for(BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
1899 if (hasLPStitch(*itr))
1905 cout << "LP Stitch number: " << stitch_num << " out of " << stitch_edge_num << " stitch edges" << endl;
1909 //store the lp coloring results
1910 template<typename GraphType>
1911 void LPColoring<GraphType>::store_lp_coloring(vector<GRBVar>& coloringBits) {
1912 uint32_t coloring_bits_num = coloringBits.size();
1913 m_lp_coloring.clear();
1914 m_lp_coloring.reserve(coloring_bits_num);
1915 for(uint32_t k = 0; k < coloring_bits_num; k++)
1917 double value = coloringBits[k].get(GRB_DoubleAttr_X);
1918 m_lp_coloring.push_back(value);
1924 template<typename GraphType>
1925 pair<uint32_t, uint32_t> LPColoring<GraphType>::nonIntegerNum(const vector<GRBVar>& coloringBits, const vector<GRBVar>& vEdgeBit) const
1927 uint32_t non_integer_num = 0;
1928 uint32_t half_num = 0;
1929 uint32_t vec_size = coloringBits.size();
1930 for(uint32_t k = 0; k < vec_size; k = k + COLORING_BITS)
1932 for(uint32_t m = 0; m < COLORING_BITS; m++)
1934 double value = coloringBits[k + m].get(GRB_DoubleAttr_X);
1935 if(value != 0.0 && value != 1.0)
1940 if(value == 0.5) half_num++;
1941 cout << k+m << "-" << value << " ";
1945 cout << "NonInteger count: " << non_integer_num << ", half integer count: " << half_num << ", out of " << vec_size << " vertex variable" << endl;
1947 uint32_t non_integer_num_edge = 0;
1948 uint32_t half_num_edge = 0;
1949 uint32_t conflict_num = 0;
1950 vec_size = vEdgeBit.size();
1951 for(uint32_t k = 0; k < vec_size; ++k)
1953 double value = vEdgeBit[k].get(GRB_DoubleAttr_X);
1954 if(value != 0.0 && value != 1.0)
1956 non_integer_num_edge++;
1959 if(value == 0.5) half_num_edge++;
1960 if(value == 1) conflict_num++;
1961 cout << k << "-" << value << " ";
1964 cout << "NonInteger count: " << non_integer_num_edge << ", half integer count: " << half_num_edge << ", out of " << vec_size << " edge variable" << endl;
1965 //cout << "conflict variable number: " << conflict_num << endl;
1966 return pair<uint32_t, uint32_t>(non_integer_num+non_integer_num_edge, half_num+half_num_edge);
1969 template<typename GraphType>
1970 void LPColoring<GraphType>::printBoolVec(vector<bool>& vec) const
1972 uint32_t vec_size = vec.size();
1973 for(uint32_t k = 0; k < vec_size; k++)
1975 //cout << k << "-" << vec[k] << "; ";
1981 template<typename GraphType>
1982 void LPColoring<GraphType>::printBoolArray(bool* vec, uint32_t vec_size) const
1984 for(uint32_t k = 0; k < vec_size; k++)
1986 //cout << k << "-" << vec[k] << "; ";
1993 template<typename GraphType>
1994 void LPColoring<GraphType>::write_graph_dot(graph_vertex_type& v) const
1996 #ifdef DEBUG_LPCOLORING
1997 // assert(m_graph_ptr);
1999 //if(m_vertex_map.empty() || m_inverse_vertex_map.empty()) this->setMap();
2001 ofstream dot_file("graph.dot");
2002 dot_file << "graph D { \n"
2004 << " size=\"4, 3\"\n"
2005 << " ratio=\"fill\"\n"
2006 << " edge[style=\"bold\",fontsize=120]\n"
2007 << " node[shape=\"circle\",fontsize=120]\n";
2010 uint32_t vertex_num = num_vertices(m_graph);
2012 bool inCycle[vertex_num];
2013 for(uint32_t k = 0; k < vertex_num; k++) inCycle[k] = false;
2014 uint32_t cycle_cnt = m_odd_cycles.size();
2015 for(uint32_t k = 0; k < cycle_cnt; k++)
2017 uint32_t cycle_len = m_odd_cycles[k].size();
2018 for(uint32_t m = 0; m < cycle_len; m++)
2020 uint32_t index = m_vertex_map.at(m_odd_cycles[k][m]);
2021 inCycle[index] = true;
2025 #ifdef DEBUG_LPCOLORING
2026 assert(m_vertex_map.find(v) != m_vertex_map.end());
2028 uint32_t start_index = m_vertex_map.at(v);
2029 for(uint32_t k = 0; k < vertex_num; k++)
2031 if(k == start_index) dot_file << " " << k << "[shape=\"square\"";
2032 else dot_file << " " << k << "[shape=\"circle\"";
2033 //output coloring label
2034 dot_file << ",label=\"" << k << ":(" << m_lp_coloring[2*k] << "," << m_lp_coloring[2*k+1] << ")\"";
2035 if(inCycle[k]) dot_file << ",color=\"red\"]\n";
2036 else dot_file << "]\n";
2040 pair<typename graph_type::edge_iterator, typename graph_type::edge_iterator> edge_range = edges(m_graph);
2041 for(BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
2043 BOOST_AUTO(from, source(*itr, m_graph));
2044 uint32_t f_ind = m_vertex_map.at(from);
2045 BOOST_AUTO(to, target(*itr, m_graph));
2046 uint32_t t_ind = m_vertex_map.at(to);
2047 bool conflict_flag = false;
2048 if(m_lp_coloring[2*f_ind] == m_lp_coloring[2*t_ind] && m_lp_coloring[2*f_ind+1] == m_lp_coloring[2*t_ind+1]) {
2049 conflict_flag = true;
2051 if (m_edge_weight_map[*itr] >= 0) // conflict edge
2054 dot_file << " " << f_ind << "--" << t_ind << "[color=\"blue\",style=\"solid\"]\n";
2056 dot_file << " " << f_ind << "--" << t_ind << "[color=\"black\",style=\"solid\"]\n";
2059 dot_file << " " << f_ind << "--" << t_ind << "[color=\"black\",style=\"dashed\"]\n";
2063 system("dot -Tpdf graph.dot -o graph.pdf");
2067 template<typename GraphType>
2068 void LPColoring<GraphType>::write_graph_dot() const
2070 #ifdef DEBUG_LPCOLORING
2071 // assert(m_graph_ptr);
2073 //if(m_vertex_map.empty() || m_inverse_vertex_map.empty()) this->setMap();
2075 ofstream dot_file("graph.dot");
2076 dot_file << "graph D { \n"
2078 << " size=\"4, 3\"\n"
2079 << " ratio=\"fill\"\n"
2080 << " edge[style=\"bold\",fontsize=200]\n"
2081 << " node[shape=\"circle\",fontsize=200]\n";
2084 uint32_t vertex_num = num_vertices(m_graph);
2085 for(uint32_t k = 0; k < vertex_num; k++)
2087 dot_file << " " << k << "[shape=\"circle\"";
2088 //output coloring label
2089 //dot_file << ",label=\"" << k << ":(" << m_lp_coloring[2*k] << "," << m_lp_coloring[2*k+1] << ")\"";
2090 dot_file << ",label=\"(" << m_lp_coloring[2*k] << "," << m_lp_coloring[2*k+1] << ")\"";
2095 pair<typename graph_type::edge_iterator, typename graph_type::edge_iterator> edge_range = edges(m_graph);
2096 for(BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
2098 BOOST_AUTO(from, source(*itr, m_graph));
2099 uint32_t f_ind = m_vertex_map.at(from);
2100 BOOST_AUTO(to, target(*itr, m_graph));
2101 uint32_t t_ind = m_vertex_map.at(to);
2102 bool conflict_flag = false;
2103 if(m_lp_coloring[2*f_ind] == m_lp_coloring[2*t_ind] && m_lp_coloring[2*f_ind+1] == m_lp_coloring[2*t_ind+1])
2105 conflict_flag = true;
2107 if (m_edge_weight_map[*itr] >= 0) // conflict edge
2111 dot_file << " " << f_ind << "--" << t_ind << "[color=\"blue\",style=\"solid\",penwidth=3]\n";
2112 cout << "conflict (" << f_ind << ", " << t_ind << ")" << endl;
2115 dot_file << " " << f_ind << "--" << t_ind << "[color=\"black\",style=\"solid\",penwidth=3]\n";
2118 dot_file << " " << f_ind << "--" << t_ind << "[color=\"black\",style=\"dashed\",penwidth=3]\n";
2122 system("dot -Tpdf graph.dot -o graph.pdf");
2127 template<typename GraphType>
2128 void LPColoring<GraphType>::write_graph_color() const
2130 #ifdef DEBUG_LPCOLORING
2131 // assert(m_graph_ptr);
2133 //if(m_vertex_map.empty() || m_inverse_vertex_map.empty()) this->setMap();
2134 ofstream dot_file("color_graph.dot");
2135 dot_file << "graph D { \n"
2137 << " size=\"4, 3\"\n"
2138 << " ratio=\"fill\"\n"
2139 << " edge[style=\"bold\",fontsize=120]\n"
2140 << " node[shape=\"circle\",fontsize=120]\n";
2143 uint32_t vertex_num = num_vertices(m_graph);
2145 bool inCycle[vertex_num];
2146 for(uint32_t k = 0; k < vertex_num; k++) inCycle[k] = false;
2147 uint32_t cycle_cnt = m_odd_cycles.size();
2148 for(uint32_t k = 0; k < cycle_cnt; k++)
2150 uint32_t cycle_len = m_odd_cycles[k].size();
2151 for(uint32_t m = 0; m < cycle_len; m++)
2153 uint32_t index = m_vertex_map.at(m_odd_cycles[k][m]);
2154 inCycle[index] = true;
2158 for(uint32_t k = 0; k < vertex_num; k++)
2160 dot_file << " " << k << "[shape=\"circle\"";
2161 //output coloring label
2162 dot_file << ",label=\"" << m_coloring.at(m_inverse_vertex_map.at(k)) << "\"";
2163 if(inCycle[k]) dot_file << ",color=\"red\"]\n";
2164 else dot_file << "]\n";
2168 pair<typename graph_type::edge_iterator, typename graph_type::edge_iterator> edge_range = edges(m_graph);
2169 for(BOOST_AUTO(itr, edge_range.first); itr != edge_range.second; ++itr)
2171 BOOST_AUTO(from, source(*itr, m_graph));
2172 uint32_t f_ind = m_vertex_map.at(from);
2173 BOOST_AUTO(to, target(*itr, m_graph));
2174 uint32_t t_ind = m_vertex_map.at(to);
2176 if (m_edge_weight_map[*itr] >= 0) // conflict edge
2178 if(m_coloring.at(from) != m_coloring.at(to))
2179 dot_file << " " << f_ind << "--" << t_ind << "[color=\"black\",style=\"solid\",penwidth=3]\n";
2181 dot_file << " " << f_ind << "--" << t_ind << "[color=\"blue\",style=\"solid\",penwidth=3]\n";
2185 if(m_coloring.at(from) == m_coloring.at(to))
2186 dot_file << " " << f_ind << "--" << t_ind << "[color=\"black\",style=\"dashed\",penwidth=3]\n";
2188 dot_file << " " << f_ind << "--" << t_ind << "[color=\"blue\",style=\"dashed\",penwidth=3]\n";
2193 system("dot -Tpdf color_graph.dot -o color_graph.pdf");
2196 } // namespace coloring
2197 } // namespace algorithms
2198 } // namespace limbo
uint32_t m_constrs_num
record number of constraints
virtual double operator()()
graph_type const & m_graph
initial graph
LPColoring(graph_type const &g)
constructor
std::size_t operator()(graph_edge_type const &e) const
ColorNumType m_color_num
number of colors
double m_stitch_weight
stitch weight