6 #ifndef LIMBO_ALGORITHMS_COLORING_MISCOLORING
7 #define LIMBO_ALGORITHMS_COLORING_MISCOLORING
20 #include <boost/cstdint.hpp>
21 #include <boost/unordered_map.hpp>
22 #include <boost/graph/graph_concepts.hpp>
23 #include <boost/graph/subgraph.hpp>
24 #include <boost/property_map/property_map.hpp>
53 template <
typename GraphType>
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;
90 void write_graph_sol(
string const& filename, std::vector<int8_t>
const& vVertexExcludeMark, std::vector<graph_vertex_type>
const& vMISVertex)
const
92 std::ofstream out((filename+
".gv").c_str());
96 <<
" ratio=\"fill\"\n"
97 <<
" edge[style=\"bold\",fontsize=200]\n"
98 <<
" node[shape=\"circle\",fontsize=200]\n";
101 uint32_t vertex_num = boost::num_vertices(this->
m_graph);
102 for(uint32_t k = 0; k < vertex_num; ++k)
104 out <<
" " << k <<
"[shape=\"circle\"";
106 if (vVertexExcludeMark[k])
107 out <<
",label=\"" << k <<
"\",style=filled,fillcolor=\"grey\"";
108 else if (std::find(vMISVertex.begin(), vMISVertex.end(), k) != vMISVertex.end())
109 out <<
",label=\"" << k <<
"\",style=filled,fillcolor=\"red\"";
111 out <<
",label=\"" << k <<
"\"";
116 edge_iterator_type ei, eie;
117 for (boost::tie(ei, eie) = boost::edges(this->
m_graph); ei != eie; ++ei)
119 edge_weight_type w = boost::get(boost::edge_weight, this->
m_graph, *ei);
120 graph_vertex_type s = boost::source(*ei, this->
m_graph);
121 graph_vertex_type t = boost::target(*ei, this->
m_graph);
124 if (vVertexExcludeMark[s] || vVertexExcludeMark[t])
125 out <<
" " << s <<
"--" << t <<
"[color=\"grey\",style=\"solid\",penwidth=3]\n";
127 out <<
" " << s <<
"--" << t <<
"[color=\"black\",style=\"solid\",penwidth=3]\n";
130 out <<
" " << s <<
"--" << t <<
"[color=\"blue\",style=\"dotted\",penwidth=3]\n";
142 std::vector<int8_t> vVertexExcludeMark (boost::num_vertices(this->
m_graph), 0);
143 std::vector<graph_vertex_type> vMISVertex;
145 for (int8_t c = 0; c < this->
color_num(); ++c)
151 computeMWISILP(vVertexExcludeMark, vMISVertex);
157 for (
typename std::vector<graph_vertex_type>::const_iterator vi = vMISVertex.begin(); vi != vMISVertex.end(); ++vi)
160 vVertexExcludeMark[*vi] =
true;
165 vertex_iterator_type vi, vie;
166 for (boost::tie(vi, vie) = boost::vertices(this->
m_graph); vi != vie; ++vi)
168 graph_vertex_type v = *vi;
169 if (!vVertexExcludeMark[v])
171 int8_t bestColor = 0;
173 for (int8_t c = 0; c < this->
color_num(); ++c)
175 edge_weight_type curCost = 0;
176 typename boost::graph_traits<graph_type>::adjacency_iterator ui, uie;
177 for (boost::tie(ui, uie) = boost::adjacent_vertices(v, this->
m_graph); ui != uie; ++ui)
179 graph_vertex_type u = *ui;
184 std::pair<graph_edge_type, bool> eU2v = boost::edge(v, u, this->
m_graph);
185 #ifdef DEBUG_MISCOLORING
190 curCost +=
std::max((edge_weight_type)1, boost::get(boost::edge_weight, this->
m_graph, eU2v.first));
194 if (curCost < bestCost)
204 #ifdef DEBUG_MISCOLORING
211 double computeMWISILP(std::vector<int8_t>
const& vVertexExcludeMark, std::vector<graph_vertex_type>& vMISVertex)
219 uint32_t vertex_num = boost::num_vertices(this->
m_graph);
220 uint32_t edge_num = boost::num_edges(this->
m_graph);
221 uint32_t exclude_vertex_num = std::count(vVertexExcludeMark.begin(), vVertexExcludeMark.end(), 1);
224 model_type opt_model;
230 std::vector<model_type::variable_type> vVertex2Var (vertex_num);
231 boost::unordered_map<graph_edge_type, model_type::variable_type, edge_hash_type> hEdge2Var;
234 opt_model.reserveVariables(vertex_num-exclude_vertex_num+edge_num);
235 vertex_iterator_type vi, vie;
236 for (boost::tie(vi, vie) = boost::vertices(this->
m_graph); vi != vie; ++vi)
238 graph_vertex_type v = *vi;
239 if (!vVertexExcludeMark[v])
241 std::ostringstream oss;
247 edge_iterator_type ei, eie;
248 for (boost::tie(ei, eie) = boost::edges(this->
m_graph); ei != eie; ++ei)
250 graph_vertex_type s = boost::source(*ei, this->
m_graph);
251 graph_vertex_type t = boost::target(*ei, this->
m_graph);
253 if (!vVertexExcludeMark[s] && !vVertexExcludeMark[t])
255 std::ostringstream oss;
256 oss <<
"e" << s <<
"_" << t;
264 model_type::expression_type obj;
265 for (
typename boost::unordered_map<graph_edge_type, model_type::variable_type, edge_hash_type>::const_iterator it = hEdge2Var.begin(); it != hEdge2Var.end(); ++it)
267 opt_model.setObjective(obj);
272 uint32_t constr_num = 0;
273 for (boost::tie(ei, eie) = boost::edges(this->
m_graph); ei != eie; ++ei)
275 graph_vertex_type s = boost::source(*ei, this->
m_graph);
276 graph_vertex_type t = boost::target(*ei, this->
m_graph);
278 if (!vVertexExcludeMark[s] && !vVertexExcludeMark[t])
280 sprintf(buf,
"R%u", constr_num++);
281 opt_model.addConstraint(
282 vVertex2Var[s] + vVertex2Var[t] <= 1
292 for (
typename boost::unordered_map<graph_edge_type, model_type::variable_type, edge_hash_type>::const_iterator it = hEdge2Var.begin(); it != hEdge2Var.end(); ++it)
294 graph_edge_type
const& e = it->first;
295 graph_vertex_type s = boost::source(e, this->
m_graph);
296 graph_vertex_type t = boost::target(e, this->
m_graph);
298 sprintf(buf,
"E%u", constr_num++);
299 opt_model.addConstraint(
300 it->second - vVertex2Var[s] - vVertex2Var[t] <= 0
305 solver_type solver (&opt_model);
306 int32_t opt_status = solver(&gurobiParams);
307 #ifdef DEBUG_MISCOLORING
308 opt_model.print(
"graph.lp");
309 opt_model.printSolution(
"graph.sol");
313 cout <<
"ERROR: The model is infeasible... EXIT" << endl;
318 for (boost::tie(vi, vie) = boost::vertices(this->
m_graph); vi != vie; ++vi)
320 graph_vertex_type v = *vi;
321 if (!vVertexExcludeMark[v])
323 int8_t value = opt_model.variableSolution(vVertex2Var[v]);
325 vMISVertex.push_back(v);
329 #ifdef DEBUG_MISCOLORING
334 return opt_model.evaluateObjective();
342 double computeMIS(std::vector<int8_t>
const& vVertexExcludeMark, std::vector<graph_vertex_type>& vMISVertex)
344 uint32_t vertex_num = boost::num_vertices(this->
m_graph);
347 std::set<graph_vertex_type> sVertex;
349 for (uint32_t i = 0; i < vertex_num; ++i)
351 if (!vVertexExcludeMark[i])
359 while (!sVertex.empty())
361 graph_vertex_type v = *sVertex.begin();
362 vMISVertex.push_back(v);
365 typename boost::graph_traits<graph_type>::adjacency_iterator ui, uie;
366 for (boost::tie(ui, uie) = boost::adjacent_vertices(v, this->
m_graph); ui != uie; ++ui)
368 graph_vertex_type u = *ui;
373 #ifdef DEBUG_MISCOLORING
378 return vMISVertex.size();
hasher class for graph_edge_type
Gurobi API with limbo::solvers::LinearModel.
void setNumThreads(int v)
set number of threads
Base class for custom Gurobi parameters.
virtual edge_weight_type calc_cost(std::vector< int8_t > const &vColor) const
ColorNumType
number of colors
int32_t m_threads
control number of threads for ILP solver
Basic utilities such as variables and linear expressions in solvers.
Gurobi API wrapper using its C API.
void setOutputFlag(int v)
set output flag
virtual void precolor(graph_vertex_type, int8_t)
virtual ~MISColoring()
destructor
double computeMIS(std::vector< int8_t > const &vVertexExcludeMark, std::vector< graph_vertex_type > &vMISVertex)
compute maximum independent set, weight is not supported yet
std::vector< int8_t > m_vColor
coloring solutions
std::iterator_traits< Iterator >::value_type max(Iterator first, Iterator last)
get max of an array
graph_type const & m_graph
initial graph
virtual void write_graph(std::string const &filename) const
base class for all graph coloring algorithms
MISColoring(graph_type const &g)
virtual ColorNumType color_num() const
#define limboAssert(condition)
custom assertion without message
virtual double coloring()
Check string is integer, floating point, number... Convert string to upper/lower cases.
model to describe an optimization problem
void write_graph_sol(string const &filename, std::vector< int8_t > const &vVertexExcludeMark, std::vector< graph_vertex_type > const &vMISVertex) const
void graphviz2pdf(std::string const &filename, const char *suffix=".gv")
convert graphviz format to pdf. The input filename should be filename+suffix