Limbo 3.5.4
Loading...
Searching...
No Matches
ILPColoringLemonCbc.h
Go to the documentation of this file.
1
11
12#ifndef LIMBO_ALGORITHMS_COLORING_ILPCOLORINGLEMONCBC
13#define LIMBO_ALGORITHMS_COLORING_ILPCOLORINGLEMONCBC
14
15#include <iostream>
16#include <vector>
17#include <queue>
18#include <set>
19#include <limits>
20#include <cassert>
21#include <cmath>
22#include <stdlib.h>
23#include <cstdio>
24#include <sstream>
25#include <algorithm>
26#include <boost/cstdint.hpp>
27#include <boost/unordered_map.hpp>
28#include <boost/graph/graph_concepts.hpp>
29#include <boost/graph/subgraph.hpp>
30#include <boost/property_map/property_map.hpp>
31//#include <boost/graph/bipartite.hpp>
32//#include <boost/graph/kruskal_min_spanning_tree.hpp>
33//#include <boost/graph/prim_minimum_spanning_tree.hpp>
34//#include <boost/graph/dijkstra_shortest_paths.hpp>
35#include <limbo/string/String.h>
37#include <lemon/cbc.h>
38#include <lemon/lp.h>
39
41namespace limbo
42{
44namespace algorithms
45{
47namespace coloring
48{
49
50using std::ostringstream;
51using boost::unordered_map;
52
64template <typename GraphType>
65class ILPColoringLemonCbc : public Coloring<GraphType>
66{
67 public:
69 typedef Coloring<GraphType> base_type;
70 using typename base_type::graph_type;
71 using typename base_type::graph_vertex_type;
72 using typename base_type::graph_edge_type;
73 using typename base_type::vertex_iterator_type;
74 using typename base_type::edge_iterator_type;
75 using typename base_type::edge_weight_type;
76 using typename base_type::ColorNumType;
78
80 struct edge_hash_type : std::unary_function<graph_edge_type, std::size_t>
81 {
85 std::size_t operator()(graph_edge_type const& e) const
86 {
87 std::size_t seed = 0;
88 boost::hash_combine(seed, e.m_source);
89 boost::hash_combine(seed, e.m_target);
90 return seed;
91 }
92 };
93
96 ILPColoringLemonCbc(graph_type const& g)
97 : base_type(g)
98 {}
99
101
102 protected:
104 virtual double coloring();
105};
106
107template <typename GraphType>
109{
110 uint32_t vertex_num = boost::num_vertices(this->m_graph);
111 uint32_t edge_num = boost::num_edges(this->m_graph);
112 uint32_t vertex_variable_num = vertex_num<<1;
113
114 unordered_map<graph_vertex_type, uint32_t> hVertexIdx; // vertex index
115 unordered_map<graph_edge_type, uint32_t, edge_hash_type> hEdgeIdx; // edge index
116
117 vertex_iterator_type vi, vie;
118 uint32_t cnt = 0;
119 for (boost::tie(vi, vie) = boost::vertices(this->m_graph); vi != vie; ++vi, ++cnt)
120 hVertexIdx[*vi] = cnt;
121 edge_iterator_type ei, eie;
122 cnt = 0;
123 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei, ++cnt)
124 hEdgeIdx[*ei] = cnt;
125
126 typedef lemon::MipSolver::Row Row; // constraints dimension
127 typedef lemon::MipSolver::Col Col; // variable dimension
128 typedef lemon::MipSolver::Expr Expr; // expression
129
130 // ILP environment
131 lemon::CbcMip opt_model;
132 //mute the log from the LP solver
133 // set threads
134 //set up the ILP variables
135 vector<Col> vVertexBit;
136 vector<Col> vEdgeBit;
137
138 // vertex variables
139 vVertexBit.reserve(vertex_variable_num);
140 for (uint32_t i = 0; i != vertex_variable_num; ++i)
141 {
142 uint32_t vertex_idx = (i>>1);
143 ostringstream oss;
144 oss << "v" << i;
145 if (this->m_vColor[vertex_idx] >= 0 && this->m_vColor[vertex_idx] < this->m_color_num) // precolored
146 {
147 int8_t color_bit;
148 if ((i&1) == 0) color_bit = (this->m_vColor[vertex_idx]>>1)&1;
149 else color_bit = this->m_vColor[vertex_idx]&1;
150 vVertexBit.push_back(opt_model.addCol());
151 Col const& x = vVertexBit.back();
152 opt_model.colBounds(x, color_bit, color_bit);
153 opt_model.colType(x, lemon::MipSolver::INTEGER);
154 opt_model.colName(x, oss.str());
155 }
156 else // uncolored
157 {
158 vVertexBit.push_back(opt_model.addCol());
159 Col const& x = vVertexBit.back();
160 opt_model.colBounds(x, 0, 1);
161 opt_model.colType(x, lemon::MipSolver::INTEGER);
162 opt_model.colName(x, oss.str());
163 }
164 }
165
166 // edge variables
167 vEdgeBit.reserve(edge_num);
168 for (uint32_t i = 0; i != edge_num; ++i)
169 {
170 ostringstream oss;
171 oss << "e" << i;
172 vEdgeBit.push_back(opt_model.addCol());
173 Col const& x = vEdgeBit.back();
174 opt_model.colBounds(x, 0, 1);
175 opt_model.colType(x, lemon::MipSolver::REAL);
176 opt_model.colName(x, oss.str());
177 }
178
179 // update model
180
181 // set up the objective
182 Expr obj;
183 for (boost::tie(ei, eie) = edges(this->m_graph); ei != eie; ++ei)
184 {
185 edge_weight_type w = boost::get(boost::edge_weight, this->m_graph, *ei);
186 if (w > 0) // weighted conflict
187 obj += w*vEdgeBit[hEdgeIdx[*ei]];
188 else if (w < 0) // weighted stitch
189 obj += this->m_stitch_weight*(-w)*vEdgeBit[hEdgeIdx[*ei]];
190 }
191 opt_model.obj(obj);
192 opt_model.min();
193
194 // set up the constraints
195 //uint32_t constr_num = 0;
196 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
197 {
198 graph_vertex_type s = boost::source(*ei, this->m_graph);
199 graph_vertex_type t = boost::target(*ei, this->m_graph);
200 uint32_t sIdx = hVertexIdx[s];
201 uint32_t tIdx = hVertexIdx[t];
202
203 uint32_t vertex_idx1 = sIdx<<1;
204 uint32_t vertex_idx2 = tIdx<<1;
205
206 edge_weight_type w = boost::get(boost::edge_weight, this->m_graph, *ei);
207 uint32_t edge_idx = hEdgeIdx[*ei];
208
209 //char buf[100];
210 if (w >= 0) // constraints for conflict edges
211 {
212 //sprintf(buf, "R%u", constr_num++);
213 opt_model.addRow(
214 vVertexBit[vertex_idx1] + vVertexBit[vertex_idx1+1]
215 + vVertexBit[vertex_idx2] + vVertexBit[vertex_idx2+1]
216 + vEdgeBit[edge_idx] >= 1
217 );
218
219 //sprintf(buf, "R%u", constr_num++);
220 opt_model.addRow(
221 1 - vVertexBit[vertex_idx1] + vVertexBit[vertex_idx1+1]
222 + 1 - vVertexBit[vertex_idx2] + vVertexBit[vertex_idx2+1]
223 + vEdgeBit[edge_idx] >= 1
224 );
225
226 //sprintf(buf, "R%u", constr_num++);
227 opt_model.addRow(
228 vVertexBit[vertex_idx1] + 1 - vVertexBit[vertex_idx1+1]
229 + vVertexBit[vertex_idx2] + 1 - vVertexBit[vertex_idx2+1]
230 + vEdgeBit[edge_idx] >= 1
231 );
232
233 //sprintf(buf, "R%u", constr_num++);
234 opt_model.addRow(
235 1 - vVertexBit[vertex_idx1] + 1 - vVertexBit[vertex_idx1+1]
236 + 1 - vVertexBit[vertex_idx2] + 1 - vVertexBit[vertex_idx2+1]
237 + vEdgeBit[edge_idx] >= 1
238 );
239
240 }
241 else // constraints for stitch edges
242 {
243 //sprintf(buf, "R%u", constr_num++);
244 opt_model.addRow(
245 vVertexBit[vertex_idx1] - vVertexBit[vertex_idx2] - vEdgeBit[edge_idx] <= 0
246 );
247
248 //sprintf(buf, "R%u", constr_num++);
249 opt_model.addRow(
250 vVertexBit[vertex_idx2] - vVertexBit[vertex_idx1] - vEdgeBit[edge_idx] <= 0
251 );
252
253 //sprintf(buf, "R%u", constr_num++);
254 opt_model.addRow(
255 vVertexBit[vertex_idx1+1] - vVertexBit[vertex_idx2+1] - vEdgeBit[edge_idx] <= 0
256 );
257
258 //sprintf(buf, "R%u", constr_num++);
259 opt_model.addRow(
260 vVertexBit[vertex_idx2+1] - vVertexBit[vertex_idx1+1] - vEdgeBit[edge_idx] <= 0
261 );
262 }
263 }
264
265 // additional constraints for 3-coloring
266 if (this->m_color_num == base_type::THREE)
267 {
268 //char buf[100];
269 for(uint32_t k = 0; k != vertex_variable_num; k += 2)
270 {
271 //sprintf(buf, "R%u", constr_num++);
272 opt_model.addRow(vVertexBit[k] + vVertexBit[k+1] <= 1);
273 }
274 }
275
276 //optimize model
277 opt_model.solve();
278 int32_t opt_status = opt_model.type();
279 if (opt_status == lemon::MipSolver::INFEASIBLE)
280 {
281 cout << "ERROR: The model is infeasible... EXIT" << endl;
282 exit(1);
283 }
284
285 // collect coloring solution
286 for (uint32_t k = 0; k != vertex_variable_num; k += 2)
287 {
288 int8_t color = (opt_model.sol(vVertexBit[k])*2) + opt_model.sol(vVertexBit[k+1]);
289 uint32_t vertex_idx = (k>>1);
290
291 assert(color >= 0 && color < this->m_color_num);
292 if (this->m_vColor[vertex_idx] >= 0 && this->m_vColor[vertex_idx] < this->m_color_num) // check precolored vertex
293 assert(this->m_vColor[vertex_idx] == color);
294 else // assign color to uncolored vertex
295 this->m_vColor[vertex_idx] = color;
296 }
297
298 // return objective value
299 return opt_model.solValue();
300}
301
302} // namespace coloring
303} // namespace algorithms
304} // namespace limbo
305
306#endif
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
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
namespace for Limbo.Algorithms.Coloring
namespace for Limbo.algorithms
namespace for Limbo