Limbo 3.5.4
Loading...
Searching...
No Matches
ILPColoring.h
Go to the documentation of this file.
1
7
8#ifndef LIMBO_ALGORITHMS_COLORING_ILPCOLORING
9#define LIMBO_ALGORITHMS_COLORING_ILPCOLORING
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 ILPColoring : 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 ILPColoring(graph_type const& g)
74 : base_type(g)
75 {}
76
77 virtual ~ILPColoring() {}
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 cnt = 0;
101 edge_iterator_type ei, eie;
102 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei, ++cnt)
103 hEdgeIdx[*ei] = cnt;
104
106 model_type opt_model;
108 gurobiParams.setOutputFlag(0);
109 gurobiParams.setNumThreads(this->m_threads);
110 //set up the ILP variables
111 std::vector<model_type::variable_type> vVertexBit;
112 std::vector<model_type::variable_type> vEdgeBit;
113
114 opt_model.reserveVariables(vertex_variable_num+edge_num);
115 if (this->m_color_num == base_type::THREE)
116 opt_model.reserveConstraints(edge_num*4+vertex_num);
117 else
118 opt_model.reserveConstraints(edge_num*4);
119
120 // vertex variables
121 vVertexBit.reserve(vertex_variable_num);
122 for (uint32_t i = 0; i != vertex_variable_num; ++i)
123 {
124 uint32_t vertex_idx = (i>>1);
125 std::ostringstream oss;
126 oss << "v" << i;
127 if (this->m_vColor[vertex_idx] >= 0 && this->m_vColor[vertex_idx] < this->m_color_num) // precolored
128 {
129 int8_t color_bit;
130 if ((i&1) == 0) color_bit = (this->m_vColor[vertex_idx]>>1)&1;
131 else color_bit = this->m_vColor[vertex_idx]&1;
132 vVertexBit.push_back(opt_model.addVariable(color_bit, color_bit, limbo::solvers::INTEGER, oss.str()));
133 }
134 else // uncolored
135 vVertexBit.push_back(opt_model.addVariable(0, 1, limbo::solvers::INTEGER, oss.str()));
136 }
137
138 // edge variables
139 vEdgeBit.reserve(edge_num);
140 for (uint32_t i = 0; i != edge_num; ++i)
141 {
142 std::ostringstream oss;
143 oss << "e" << i;
144 vEdgeBit.push_back(opt_model.addVariable(0, 1, limbo::solvers::INTEGER, oss.str()));
145 }
146
147 // set up the objective
149 for (boost::tie(ei, eie) = edges(this->m_graph); ei != eie; ++ei)
150 {
151 edge_weight_type w = boost::get(boost::edge_weight, this->m_graph, *ei);
152 if (w > 0) // weighted conflict
153 obj += w*vEdgeBit[hEdgeIdx[*ei]];
154 else if (w < 0) // weighted stitch
155 obj += this->m_stitch_weight*(-w)*vEdgeBit[hEdgeIdx[*ei]];
156 }
157 opt_model.setObjective(obj);
159
160 // set up the constraints
161 uint32_t constr_num = 0;
162 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
163 {
164 graph_vertex_type s = boost::source(*ei, this->m_graph);
165 graph_vertex_type t = boost::target(*ei, this->m_graph);
166
167 uint32_t vertex_idx1 = s<<1;
168 uint32_t vertex_idx2 = t<<1;
169
170 edge_weight_type w = boost::get(boost::edge_weight, this->m_graph, *ei);
171 uint32_t edge_idx = hEdgeIdx[*ei];
172
173 char buf[100];
174 string tmpConstr_name;
175 if (w >= 0) // constraints for conflict edges
176 {
177 sprintf(buf, "R%u", constr_num++);
178 opt_model.addConstraint(
179 vVertexBit[vertex_idx1] + vVertexBit[vertex_idx1+1]
180 + vVertexBit[vertex_idx2] + vVertexBit[vertex_idx2+1]
181 + vEdgeBit[edge_idx] >= 1
182 , buf);
183
184 sprintf(buf, "R%u", constr_num++);
185 opt_model.addConstraint(
186 - vVertexBit[vertex_idx1] + vVertexBit[vertex_idx1+1]
187 - vVertexBit[vertex_idx2] + vVertexBit[vertex_idx2+1]
188 + vEdgeBit[edge_idx] >= -1
189 , buf);
190
191 sprintf(buf, "R%u", constr_num++);
192 opt_model.addConstraint(
193 vVertexBit[vertex_idx1] - vVertexBit[vertex_idx1+1]
194 + vVertexBit[vertex_idx2] - vVertexBit[vertex_idx2+1]
195 + vEdgeBit[edge_idx] >= -1
196 , buf);
197
198 sprintf(buf, "R%u", constr_num++);
199 opt_model.addConstraint(
200 - vVertexBit[vertex_idx1] - vVertexBit[vertex_idx1+1]
201 - vVertexBit[vertex_idx2] - vVertexBit[vertex_idx2+1]
202 + vEdgeBit[edge_idx] >= -3
203 , buf);
204
205 }
206 else // constraints for stitch edges
207 {
208 sprintf(buf, "R%u", constr_num++);
209 opt_model.addConstraint(
210 vVertexBit[vertex_idx1] - vVertexBit[vertex_idx2] - vEdgeBit[edge_idx] <= 0
211 , buf);
212
213 sprintf(buf, "R%u", constr_num++);
214 opt_model.addConstraint(
215 vVertexBit[vertex_idx2] - vVertexBit[vertex_idx1] - vEdgeBit[edge_idx] <= 0
216 , buf);
217
218 sprintf(buf, "R%u", constr_num++);
219 opt_model.addConstraint(
220 vVertexBit[vertex_idx1+1] - vVertexBit[vertex_idx2+1] - vEdgeBit[edge_idx] <= 0
221 , buf);
222
223 sprintf(buf, "R%u", constr_num++);
224 opt_model.addConstraint(
225 vVertexBit[vertex_idx2+1] - vVertexBit[vertex_idx1+1] - vEdgeBit[edge_idx] <= 0
226 , buf);
227 }
228 }
229
230 // additional constraints for 3-coloring
231 if (this->m_color_num == base_type::THREE)
232 {
233 char buf[100];
234 for(uint32_t k = 0; k != vertex_variable_num; k += 2)
235 {
236 sprintf(buf, "R%u", constr_num++);
237 opt_model.addConstraint(vVertexBit[k] + vVertexBit[k+1] <= 1, buf);
238 }
239 }
240
241 //optimize model
242 solver_type solver (&opt_model);
243 int32_t opt_status = solver(&gurobiParams);
244#ifdef DEBUG_ILPCOLORING
245 opt_model.print("graph.lp");
246 opt_model.printSolution("graph.sol");
247#endif
248 if(opt_status == limbo::solvers::INFEASIBLE)
249 {
250 cout << "ERROR: The model is infeasible... EXIT" << endl;
251 exit(1);
252 }
253
254#ifdef DEBUG_ILPCOLORING
255 this->write_graph_sol("graph_sol", opt_model, vVertexBit); // dump solution figure
256#endif
257
258 // collect coloring solution
259 for (uint32_t k = 0; k != vertex_variable_num; k += 2)
260 {
261 int8_t color = (opt_model.variableSolution(vVertexBit[k])*2)+opt_model.variableSolution(vVertexBit[k+1]);
262 uint32_t vertex_idx = (k>>1);
263
264 assert(color >= 0 && color < this->m_color_num);
265 if (this->m_vColor[vertex_idx] >= 0 && this->m_vColor[vertex_idx] < this->m_color_num) // check precolored vertex
266 assert(this->m_vColor[vertex_idx] == color);
267 else // assign color to uncolored vertex
268 this->m_vColor[vertex_idx] = color;
269 }
270
271 // return objective value
272 return opt_model.evaluateObjective();
273}
274
275template <typename GraphType>
276void ILPColoring<GraphType>::write_graph_sol(string const& filename, typename ILPColoring<GraphType>::model_type const& opt_model,
277 std::vector<typename ILPColoring<GraphType>::model_type::variable_type> const& vVertexBit) const
278{
279 std::ofstream out((filename+".gv").c_str());
280 out << "graph D { \n"
281 << " randir = LR\n"
282 << " size=\"4, 3\"\n"
283 << " ratio=\"fill\"\n"
284 << " edge[style=\"bold\",fontsize=200]\n"
285 << " node[shape=\"circle\",fontsize=200]\n";
286
287 //output nodes
288 uint32_t vertex_num = boost::num_vertices(this->m_graph);
289 for(uint32_t k = 0; k < vertex_num; ++k)
290 {
291 out << " " << k << "[shape=\"circle\"";
292 //output coloring label
293 out << ",label=\"" << k << ":(" << opt_model.variableSolution(vVertexBit[(k<<1)]) << "," << opt_model.variableSolution(vVertexBit[(k<<1)+1]) << ")\"";
294 out << "]\n";
295 }//end for
296
297 //output edges
298 edge_iterator_type ei, eie;
299 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
300 {
301 edge_weight_type w = boost::get(boost::edge_weight, this->m_graph, *ei);
302 graph_vertex_type s = boost::source(*ei, this->m_graph);
303 graph_vertex_type t = boost::target(*ei, this->m_graph);
304 if (w >= 0) // conflict edge
305 {
306 bool conflict_flag = (opt_model.variableSolution(vVertexBit[(s<<1)]) == opt_model.variableSolution(vVertexBit[(t<<1)])
307 && opt_model.variableSolution(vVertexBit[(s<<1)+1]) == opt_model.variableSolution(vVertexBit[(t<<1)+1]));
308
309 if(conflict_flag)
310 out << " " << s << "--" << t << "[color=\"red\",style=\"solid\",penwidth=3]\n";
311 else
312 out << " " << s << "--" << t << "[color=\"black\",style=\"solid\",penwidth=3]\n";
313 }
314 else // stitch edge
315 out << " " << s << "--" << t << "[color=\"blue\",style=\"dotted\",penwidth=3]\n";
316 }
317 out << "}";
318 out.close();
319 la::graphviz2pdf(filename);
320}
321
322} // namespace coloring
323} // namespace algorithms
324} // namespace limbo
325
326#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