Limbo 3.5.4
Loading...
Searching...
No Matches
ILPColoringUpdated.h
Go to the documentation of this file.
1
7
8#ifndef LIMBO_ALGORITHMS_COLORING_ILPColoringUpdated
9#define LIMBO_ALGORITHMS_COLORING_ILPColoringUpdated
10
11#include <iostream>
12#include <vector>
13#include <queue>
14#include <set>
15#include <limits>
16#include <cassert>
17#include <cmath>
18#include <stdlib.h>
19#include <cstdio>
20#include <sstream>
21#include <algorithm>
22#include <boost/cstdint.hpp>
23#include <boost/unordered_map.hpp>
24#include <boost/graph/graph_concepts.hpp>
25#include <boost/graph/subgraph.hpp>
26#include <boost/property_map/property_map.hpp>
27//#include <boost/graph/bipartite.hpp>
28//#include <boost/graph/kruskal_min_spanning_tree.hpp>
29//#include <boost/graph/prim_minimum_spanning_tree.hpp>
30//#include <boost/graph/dijkstra_shortest_paths.hpp>
31#include <limbo/string/String.h>
35
37namespace limbo
38{
40namespace algorithms
41{
43namespace coloring
44{
45
53template <typename GraphType>
54class ILPColoringUpdated : public Coloring<GraphType>
55{
56 public:
58 typedef Coloring<GraphType> base_type;
59 using typename base_type::graph_type;
60 using typename base_type::graph_vertex_type;
61 using typename base_type::graph_edge_type;
62 using typename base_type::vertex_iterator_type;
63 using typename base_type::edge_iterator_type;
64 using typename base_type::edge_weight_type;
65 using typename base_type::ColorNumType;
66 typedef typename base_type::EdgeHashType edge_hash_type;
70
73 ILPColoringUpdated(graph_type const& g)
74 : base_type(g)
75 {}
76
78
83 void write_graph_sol(string const& filename, model_type const& opt_model, std::vector<model_type::variable_type> const& vVertexBit) const;
84
85 protected:
88 virtual double coloring();
89};
90
91template <typename GraphType>
93{
94 uint32_t vertex_num = boost::num_vertices(this->m_graph);
95 uint32_t edge_num = boost::num_edges(this->m_graph);
96 uint32_t vertex_variable_num = vertex_num<<1;
97
98 boost::unordered_map<graph_edge_type, uint32_t, edge_hash_type> hEdgeIdx; // edge index
99
100 uint32_t stitch_cnt = 0;
101 edge_iterator_type ei, eie;
102 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
103 {
104 edge_weight_type w = boost::get(boost::edge_weight, this->m_graph, *ei);
105 if(w<0){
106 hEdgeIdx[*ei] = stitch_cnt;
107 stitch_cnt++;
108 }
109
110 }
111
112
114 model_type opt_model;
116 gurobiParams.setOutputFlag(0);
117 gurobiParams.setNumThreads(this->m_threads);
118 //set up the ILP variables
119 std::vector<model_type::variable_type> vVertexBit;
120 std::vector<model_type::variable_type> vEdgeBit;
121
122 opt_model.reserveVariables(vertex_variable_num+edge_num);
123 if (this->m_color_num == base_type::THREE)
124 opt_model.reserveConstraints(edge_num*4+vertex_num);
125 else
126 opt_model.reserveConstraints(edge_num*4);
127
128 // vertex variables
129 vVertexBit.reserve(vertex_variable_num);
130 for (uint32_t i = 0; i != vertex_variable_num; ++i)
131 {
132 uint32_t vertex_idx = (i>>1);
133 std::ostringstream oss;
134 oss << "v" << i;
135 if (this->m_vColor[vertex_idx] >= 0 && this->m_vColor[vertex_idx] < this->m_color_num) // precolored
136 {
137 int8_t color_bit;
138 if ((i&1) == 0) color_bit = (this->m_vColor[vertex_idx]>>1)&1;
139 else color_bit = this->m_vColor[vertex_idx]&1;
140 vVertexBit.push_back(opt_model.addVariable(color_bit, color_bit, limbo::solvers::INTEGER, oss.str()));
141 }
142 else // uncolored
143 vVertexBit.push_back(opt_model.addVariable(0, 1, limbo::solvers::INTEGER, oss.str()));
144 }
145
146 // edge variables
147
148 // //New version by Wei
149 // int m_stitch_index = 0;
150 // uint32_t stitch_edge_num = 0;
151 // //parent node in non-stitch graph index of each node in stitch graph
152 // std::vector<int> stitch_relation_set;
153
154 // //Step 1. Firstly, count the number of stitch edges and store all of the stitch relations
155 // vertex_iterator_type vi, vie,next;
156 // boost::tie(vi, vie) = vertices(this->m_graph);
157 // std::vector<bool> visited(boost::num_vertices(this->m_graph), false);
158 // stitch_relation_set.assign(boost::num_vertices(this->m_graph),-1);
159 // for (next = vi; vi != vie; vi = next)
160 // {
161 // ++next;
162 // graph_vertex_type v = *vi;
163 // if(visited[(int)v]) continue;
164 // else{
165 // visited[(int)v] = true;
166 // stitch_relation_set[(int)v] = m_stitch_index;
167 // Coloring<GraphType>::depth_first_search_stitch(v,stitch_relation_set,visited,stitch_edge_num,m_stitch_index);
168 // m_stitch_index ++;
169 // }
170 // }
171 std::vector<model_type::variable_type> vBigEdgeBit;
172 vBigEdgeBit.reserve(this->m_big_edge_num);
174 for (uint32_t i = 0; i != this->m_big_edge_num; ++i)
175 {
176 std::ostringstream oss;
177 oss << "big_e" << i;
178 vBigEdgeBit.push_back(opt_model.addVariable(0, 1, limbo::solvers::INTEGER, oss.str()));
179 obj += vBigEdgeBit[i];
180 }
181 // set up the objective
182 vEdgeBit.reserve(stitch_cnt);
183 for (uint32_t i = 0; i != stitch_cnt; ++i)
184 {
185 std::ostringstream oss;
186 oss << "e" << i;
187 vEdgeBit.push_back(opt_model.addVariable(0, 1, limbo::solvers::INTEGER, oss.str()));
188 }
189 for (boost::tie(ei, eie) = edges(this->m_graph); ei != eie; ++ei)
190 {
191 edge_weight_type w = boost::get(boost::edge_weight, this->m_graph, *ei);
192 if (w < 0) // weighted stitch
193 obj += this->m_stitch_weight*(-w)*vEdgeBit[hEdgeIdx[*ei]];
194 }
195 opt_model.setObjective(obj);
197
198 // set up the constraints
199 uint32_t constr_num = 0;
200 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
201 {
202 graph_vertex_type s = boost::source(*ei, this->m_graph);
203 graph_vertex_type t = boost::target(*ei, this->m_graph);
204
205 uint32_t vertex_idx1 = s<<1;
206 uint32_t vertex_idx2 = t<<1;
207 int edge_idx =-1;
208
209 edge_weight_type w = boost::get(boost::edge_weight, this->m_graph, *ei);
210 if(w<0){
211 edge_idx = hEdgeIdx[*ei];
212 }
213
214 char buf[100];
215 string tmpConstr_name;
216 if (w >= 0) // constraints for conflict edges
217 {
218 int big_e_index = this->m_edge_index_vector[(uint32_t)(this->m_stitch_relation_set[(int)s]*this->m_stitch_index + this->m_stitch_relation_set[(int)t])];
219 sprintf(buf, "R%u", constr_num++);
220 opt_model.addConstraint(
221 vVertexBit[vertex_idx1] + vVertexBit[vertex_idx1+1]
222 + vVertexBit[vertex_idx2] + vVertexBit[vertex_idx2+1]
223 + vBigEdgeBit[big_e_index] >= 1
224 , buf);
225
226 sprintf(buf, "R%u", constr_num++);
227 opt_model.addConstraint(
228 - vVertexBit[vertex_idx1] + vVertexBit[vertex_idx1+1]
229 - vVertexBit[vertex_idx2] + vVertexBit[vertex_idx2+1]
230 + vBigEdgeBit[big_e_index] >= -1
231 , buf);
232
233 sprintf(buf, "R%u", constr_num++);
234 opt_model.addConstraint(
235 vVertexBit[vertex_idx1] - vVertexBit[vertex_idx1+1]
236 + vVertexBit[vertex_idx2] - vVertexBit[vertex_idx2+1]
237 + vBigEdgeBit[big_e_index] >= -1
238 , buf);
239
240 sprintf(buf, "R%u", constr_num++);
241 opt_model.addConstraint(
242 - vVertexBit[vertex_idx1] - vVertexBit[vertex_idx1+1]
243 - vVertexBit[vertex_idx2] - vVertexBit[vertex_idx2+1]
244 + vBigEdgeBit[big_e_index] >= -3
245 , buf);
246 //std::cout <<(int)s<<" "<<(int)t<<std::endl;
247
248 }
249 else // constraints for stitch edges
250 {
251 sprintf(buf, "R%u", constr_num++);
252 opt_model.addConstraint(
253 vVertexBit[vertex_idx1] - vVertexBit[vertex_idx2] - vEdgeBit[edge_idx] <= 0
254 , buf);
255
256 sprintf(buf, "R%u", constr_num++);
257 opt_model.addConstraint(
258 vVertexBit[vertex_idx2] - vVertexBit[vertex_idx1] - vEdgeBit[edge_idx] <= 0
259 , buf);
260
261 sprintf(buf, "R%u", constr_num++);
262 opt_model.addConstraint(
263 vVertexBit[vertex_idx1+1] - vVertexBit[vertex_idx2+1] - vEdgeBit[edge_idx] <= 0
264 , buf);
265
266 sprintf(buf, "R%u", constr_num++);
267 opt_model.addConstraint(
268 vVertexBit[vertex_idx2+1] - vVertexBit[vertex_idx1+1] - vEdgeBit[edge_idx] <= 0
269 , buf);
270 }
271 }
272
273 // additional constraints for 3-coloring
274 if (this->m_color_num == base_type::THREE)
275 {
276 char buf[100];
277 for(uint32_t k = 0; k != vertex_variable_num; k += 2)
278 {
279 sprintf(buf, "R%u", constr_num++);
280 opt_model.addConstraint(vVertexBit[k] + vVertexBit[k+1] <= 1, buf);
281 }
282 }
283
284 //optimize model
285 solver_type solver (&opt_model);
286 int32_t opt_status = solver(&gurobiParams);
287#ifdef DEBUG_ILPColoringUpdated
288 opt_model.print("graph.lp");
289 opt_model.printSolution("graph.sol");
290#endif
291 if(opt_status == limbo::solvers::INFEASIBLE)
292 {
293 cout << "ERROR: The model is infeasible... EXIT" << endl;
294 exit(1);
295 }
296
297#ifdef DEBUG_ILPColoringUpdated
298 this->write_graph_sol("graph_sol", opt_model, vVertexBit); // dump solution figure
299#endif
300
301 // collect coloring solution
302 for (uint32_t k = 0; k != vertex_variable_num; k += 2)
303 {
304 int8_t color = (opt_model.variableSolution(vVertexBit[k])*2)+opt_model.variableSolution(vVertexBit[k+1]);
305 uint32_t vertex_idx = (k>>1);
306
307 assert(color >= 0 && color < this->m_color_num);
308 if (this->m_vColor[vertex_idx] >= 0 && this->m_vColor[vertex_idx] < this->m_color_num) // check precolored vertex
309 assert(this->m_vColor[vertex_idx] == color);
310 else // assign color to uncolored vertex
311 this->m_vColor[vertex_idx] = color;
312 }
313
314 // return objective value
315 return opt_model.evaluateObjective();
316}
317
318template <typename GraphType>
319void ILPColoringUpdated<GraphType>::write_graph_sol(string const& filename, typename ILPColoringUpdated<GraphType>::model_type const& opt_model,
320 std::vector<typename ILPColoringUpdated<GraphType>::model_type::variable_type> const& vVertexBit) const
321{
322 std::ofstream out((filename+".gv").c_str());
323 out << "graph D { \n"
324 << " randir = LR\n"
325 << " size=\"4, 3\"\n"
326 << " ratio=\"fill\"\n"
327 << " edge[style=\"bold\",fontsize=200]\n"
328 << " node[shape=\"circle\",fontsize=200]\n";
329
330 //output nodes
331 uint32_t vertex_num = boost::num_vertices(this->m_graph);
332 for(uint32_t k = 0; k < vertex_num; ++k)
333 {
334 out << " " << k << "[shape=\"circle\"";
335 //output coloring label
336 out << ",label=\"" << k << ":(" << opt_model.variableSolution(vVertexBit[(k<<1)]) << "," << opt_model.variableSolution(vVertexBit[(k<<1)+1]) << ")\"";
337 out << "]\n";
338 }//end for
339
340 //output edges
341 edge_iterator_type ei, eie;
342 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
343 {
344 edge_weight_type w = boost::get(boost::edge_weight, this->m_graph, *ei);
345 graph_vertex_type s = boost::source(*ei, this->m_graph);
346 graph_vertex_type t = boost::target(*ei, this->m_graph);
347 if (w >= 0) // conflict edge
348 {
349 bool conflict_flag = (opt_model.variableSolution(vVertexBit[(s<<1)]) == opt_model.variableSolution(vVertexBit[(t<<1)])
350 && opt_model.variableSolution(vVertexBit[(s<<1)+1]) == opt_model.variableSolution(vVertexBit[(t<<1)+1]));
351
352 if(conflict_flag)
353 out << " " << s << "--" << t << "[color=\"red\",style=\"solid\",penwidth=3]\n";
354 else
355 out << " " << s << "--" << t << "[color=\"black\",style=\"solid\",penwidth=3]\n";
356 }
357 else // stitch edge
358 out << " " << s << "--" << t << "[color=\"blue\",style=\"dotted\",penwidth=3]\n";
359 }
360 out << "}";
361 out.close();
362 la::graphviz2pdf(filename);
363}
364
365} // namespace coloring
366} // namespace algorithms
367} // namespace limbo
368
369#endif
base class for all graph coloring algorithms
Gurobi API wrapper using its C API.
Basic utilities such as variables and linear expressions in solvers.
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
int32_t m_threads
control number of threads for ILP solver
Definition Coloring.h:244
double m_stitch_weight
stitch weight
Definition Coloring.h:243
std::vector< int8_t > m_vColor
coloring solutions
Definition Coloring.h:240
ColorNumType m_color_num
number of colors
Definition Coloring.h:242
void write_graph_sol(string const &filename, model_type const &opt_model, std::vector< model_type::variable_type > const &vVertexBit) const
Gurobi API with limbo::solvers::LinearModel.
Definition GurobiApi.h:97
Base class for custom Gurobi parameters.
Definition GurobiApi.h:34
void setNumThreads(int v)
set number of threads
Definition GurobiApi.h:65
void setOutputFlag(int v)
set output flag
Definition GurobiApi.h:62
model to describe an optimization problem
Definition Solvers.h:1161
bool print(std::string const &filename) const
print problem in lp format to file
Definition Solvers.h:1552
Variable< coefficient_value_type > variable_type
Definition Solvers.h:1170
void reserveConstraints(unsigned int n)
reserve space for constraints
Definition Solvers.h:1389
bool addConstraint(constraint_type const &constr, std::string name="")
add a constraint
Definition Solvers.h:1217
void setOptimizeType(SolverProperty optType)
Definition Solvers.h:1310
variable_type addVariable(variable_value_type lb, variable_value_type ub, SolverProperty nt, std::string name="")
add one variable
Definition Solvers.h:1365
bool printSolution(std::string const &filename) const
print solutions to file
Definition Solvers.h:1665
void reserveVariables(unsigned int n)
reserve space for variables
Definition Solvers.h:1382
coefficient_value_type evaluateObjective(std::vector< variable_value_type > const &vVariableSol) const
evaluate objective
Definition Solvers.h:1425
void setObjective(expression_type const &expr)
set objective
Definition Solvers.h:1295
LinearExpression< coefficient_value_type > expression_type
Definition Solvers.h:1174
variable_value_type variableSolution(variable_type const &var) const
Definition Solvers.h:1376
namespace for Limbo.Algorithms.Coloring
namespace for Limbo.algorithms
@ MIN
minimize objective
Definition Solvers.h:31
@ INFEASIBLE
the model is infeasible
Definition Solvers.h:37
@ INTEGER
integer number
Definition Solvers.h:34
namespace for Limbo