Limbo 3.5.4
Loading...
Searching...
No Matches
SDPColoringCsdp.h
Go to the documentation of this file.
1
14
15#ifndef LIMBO_ALGORITHMS_COLORING_SDPCOLORINGCSDP
16#define LIMBO_ALGORITHMS_COLORING_SDPCOLORINGCSDP
17
18#include <limbo/string/String.h>
24
25// as the original csdp easy_sdp api is not very flexible to printlevel
26// I made small modification to support that
28
30namespace limbo
31{
33namespace algorithms
34{
36namespace coloring
37{
38
63template <typename GraphType>
64class SDPColoringCsdp : public Coloring<GraphType>
65{
66 public:
68 typedef Coloring<GraphType> base_type;
69 using typename base_type::graph_type;
70 using typename base_type::graph_vertex_type;
71 using typename base_type::graph_edge_type;
72 using typename base_type::vertex_iterator_type;
73 using typename base_type::edge_iterator_type;
74 using typename base_type::edge_weight_type;
75 using typename base_type::ColorNumType;
76 typedef typename base_type::EdgeHashType edge_hash_type;
78
82 {
84 typedef edge_weight_type value_type;
85 graph_type const& graph;
86
87 double m_stitch_weight;
90 FMGainCalcType(graph_type const& g) : graph(g) { }
91
98 edge_weight_type operator()(int32_t v, int8_t origp, int8_t newp, std::vector<int8_t> const& vPartition) const
99 {
100 typedef typename boost::graph_traits<graph_type>::out_edge_iterator out_edge_iterator_type;
101 out_edge_iterator_type ei, eie;
102 // if v is not partitioned, then any partition will have preassigned large gain
103 edge_weight_type gain = (origp >= 0)? 0 : boost::num_edges(graph)*boost::num_vertices(graph);
104 for (boost::tie(ei, eie) = boost::out_edges(v, graph); ei != eie; ++ei)
105 {
106 graph_vertex_type t = boost::target(*ei, graph);
107 int8_t pt = vPartition[t];
108#ifdef DEBUG_SDPCOLORING
109 limboAssert((int32_t)t != v);
110#endif
111 // skip unpartitioned vertex
112 if (pt < 0) continue;
113 edge_weight_type w = boost::get(boost::edge_weight, graph, *ei);
114 // assume origp != newp, pt >= 0
115 // conflict (positive) edges and stitch (negative) edges all follow the same rules
116 gain += (pt == newp)? -w : (pt == origp)? w : 0;
117 //gain += w * ((vPartition[t] == origp && origp >= 0) - (vPartition[t] == newp));
118 }
119 return gain;
120 }
121 };
122
124 SDPColoringCsdp(graph_type const& g);
126 virtual ~SDPColoringCsdp() {}
127
132 void write_sdp_sol(std::string const& filename, struct blockmatrix const& X) const;
136 void print_blockrec(const char* label, blockrec const& block) const;
137 protected:
140 virtual double coloring();
141
148 void construct_objectve_blockrec(blockmatrix& C, int32_t blocknum, int32_t blocksize, blockcat blockcategory) const;
154 struct sparseblock* construct_constraint_sparseblock(int32_t blocknum, int32_t blocksize, int32_t constraintnum, int32_t entrynum) const;
160 void set_sparseblock_entry(struct sparseblock& block, int32_t entryid, int32_t i, int32_t j, double value) const;
165 void round_sol(struct blockmatrix const& X);
169 void coloring_merged_graph(graph_type const& mg, std::vector<int8_t>& vMColor) const;
173 void coloring_algos(graph_type const& g, std::vector<int8_t>& vColor) const;
177 virtual void coloring_by_backtrack(graph_type const& mg, std::vector<int8_t>& vColor) const;
181 virtual void coloring_by_FM(graph_type const& mg, std::vector<int8_t>& vColor) const;
182
185 const static uint32_t max_backtrack_num_vertices = 6;
186};
187
188template <typename GraphType>
189SDPColoringCsdp<GraphType>::SDPColoringCsdp(SDPColoringCsdp<GraphType>::graph_type const& g)
190 : base_type(g)
191{
192 m_rounding_lb = -0.4;
193 m_rounding_ub = 0.93;
194}
195
196template <typename GraphType>
198{
199 std::cout<<"start csdp!";
200 clock_t solve_start = clock();
201 // Since Csdp is written in C, the api here is also in C
202 // Please refer to the documation of Csdp for different notations
203 // basically, X is primal variables, C, b, constraints and pobj are all for primal
204 // y, Z, and dobj are for dual problem
205 //
206 // Csdp has very complex storage structure for matrix
207 // I still do not have a full understanding about the block concept, especially blocks.blocksize
208 // with some reverse engineering, for the coloring problem here, matrices in C, b, and constraints mainly consists of 2 blocks
209 // the first block is for vertex variables, and the second block is for slack variables introduced to resolve '>=' operators in the constraints
210 limboAssertMsg(!this->has_precolored(), "SDP coloring does not support precolored layout yet");
211 // The problem and solution data.
212 struct blockmatrix C; // objective matrix
213 double *b; // right hand side of constraints
214 struct constraintmatrix *constraints; // constraint matrices
215 // Storage for the initial and final solutions.
216 struct blockmatrix X,Z;
217 double *y;
218 double pobj,dobj;
219
220 // iterators used to traverse through the graph
221 vertex_iterator_type vi, vie;
222 edge_iterator_type ei, eie;
223 // compute total number of vertices and edges
224 uint32_t num_vertices = boost::num_vertices(this->m_graph);
225 uint32_t num_edges = boost::num_edges(this->m_graph);
226 // compute total number of conflict edges and stitch edges
227 uint32_t num_conflict_edges = 0;
228 uint32_t num_stitch_edges = 0;
229 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
230 {
231 if (this->edge_weight(*ei) >= 0) // conflict edge
232 num_conflict_edges += 1;
233 else // stitch edge
234 num_stitch_edges += 1;
235 }
236 limboAssertMsg(num_edges > 0 && num_conflict_edges > 0, "no edges or conflict edges found, no need to solve SDP");
237 // compute total number of variables and constraints
238 uint32_t num_variables = num_vertices+num_conflict_edges;
239 uint32_t num_constraints = num_conflict_edges+num_vertices;
240
241 // setup blockmatrix C
242 C.nblocks = 2;
243 C.blocks = (struct blockrec *)malloc((C.nblocks+1)*sizeof(struct blockrec));
244 limboAssertMsg(C.blocks, "Couldn't allocate storage for C");
245 // C.blocks[0] is not used according to the example of Csdp
246 // block 1 for vertex variables
247 construct_objectve_blockrec(C, 1, num_vertices, MATRIX);
248 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
249 {
250 graph_vertex_type s = boost::source(*ei, this->m_graph);
251 graph_vertex_type t = boost::target(*ei, this->m_graph);
252 // 1 for conflict edge, -alpha for stitch edge
253 // add unary negative operator, because Csdp solves maximization problem
254 // but we are solving minimization problem
255 edge_weight_type alpha = (this->edge_weight(*ei) >= 0)? -1 : this->stitch_weight();
256 // variable starts from 1 instead of 0 in Csdp
257 s += 1; t += 1;
258 int32_t idx1 = ijtok(s,t,C.blocks[1].blocksize);
259 int32_t idx2 = ijtok(t,s,C.blocks[1].blocksize);
260 C.blocks[1].data.mat[idx1] = alpha;
261 C.blocks[1].data.mat[idx2] = alpha;
262 }
263 // block 2 for slack variables
264 // this block is all 0s, so we use diagonal format to represent
265 construct_objectve_blockrec(C, 2, num_conflict_edges, DIAG);
266//#ifdef DEBUG_SDPCOLORING
267 print_blockrec("C.blocks[1].data.mat", C.blocks[1]);
268 print_blockrec("C.blocks[2].data.vec", C.blocks[2]);
269//#endif
270
271 // setup right hand side of constraints b
272 // the order is first for conflict edges and then for vertices
273 // the order matters for constraint matrices
274 b = (double *)malloc((num_constraints+1)*sizeof(double));
275 limboAssertMsg(b, "Failed to allocate storage for right hand side of constraints b");
276 // -1/(k-1) according to Bei Yu's DAC2014 paper
277 // consider in the constraints, xij+xji >= beta, so beta should be -2/(k-1)
278 double beta = -2.0/(this->color_num()-1.0); // right hand side of constraints for conflict edges
279 for (uint32_t i = 1, ie = num_constraints+1; i != ie; ++i)
280 {
281 if (i <= num_conflict_edges) // slack for each conflict edge, xij >= -0.5
282 b[i] = beta;
283 else // slack for each vertex, xii = 1
284 b[i] = 1;
285 }
286
287 // setup constraint matrix constraints
288 // the order should be the same as right hand side b
289 constraints=(struct constraintmatrix *)malloc((num_constraints+1)*sizeof(struct constraintmatrix));
290 limboAssertMsg(constraints, "Failed to allocate storage for constraints");
291 // for conflict edges, xij
292 uint32_t cnt = 1;
293 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
294 {
295 if (this->edge_weight(*ei) >= 0) // conflict edge
296 {
297 graph_vertex_type s = boost::source(*ei, this->m_graph);
298 graph_vertex_type t = boost::target(*ei, this->m_graph);
299 if (s > t) // due to symmetry, only need to create constraint matrices for upper-matrix
300 std::swap(s, t);
301 // variable starts from 1 instead of 0 in Csdp
302 s += 1; t += 1;
303 struct constraintmatrix& constr = constraints[cnt];
304 // Terminate the linked list with a NULL pointer.
305 constr.blocks = NULL;
306 // inverse order to initialize blocks, because linked list will reverse the order
307 // first set block 2 for diagonal values and then block 1 for upper-matrix values
308 for (uint32_t i = 2; i != 0; --i)
309 {
310 struct sparseblock* blockptr;
311 if (i == 1) // block 1, vertex variables
312 {
313 blockptr = construct_constraint_sparseblock(i, num_vertices, cnt, 1);
314 set_sparseblock_entry(*blockptr, 1, s, t, 1);
315 }
316 else // block 2, slack variables
317 {
318 blockptr = construct_constraint_sparseblock(i, num_conflict_edges, cnt, 1);
319 set_sparseblock_entry(*blockptr, 1, cnt, cnt, -1);
320 }
321 // insert block to linked list
322 blockptr->next = constr.blocks;
323 constr.blocks = blockptr;
324 }
325 ++cnt;
326 }
327 }
328 // for vertices, xii
329 for (boost::tie(vi, vie) = boost::vertices(this->m_graph); vi != vie; ++vi)
330 {
331 graph_vertex_type v = *vi;
332 v += 1;
333 struct constraintmatrix& constr = constraints[cnt];
334 // Terminate the linked list with a NULL pointer.
335 constr.blocks = NULL;
336 struct sparseblock* blockptr = construct_constraint_sparseblock(1, num_vertices, cnt, 1);
337 set_sparseblock_entry(*blockptr, 1, v, v, 1);
338 // insert block to linked list
339 blockptr->next = constr.blocks;
340 constr.blocks = blockptr;
341 ++cnt;
342 }
343
344#ifdef DEBUG_SDPCOLORING
345 write_prob((char*)"problem.sdpa", num_variables, num_constraints, C, b, constraints);
346#endif
347
348 // after all configuration ready
349 // start solving sdp
350 // set initial solution
351 initsoln(num_variables, num_constraints, C, b, constraints, &X, &y, &Z);
352 // use default params
353 // only set printlevel to zero
354 struct paramstruc params;
355 int printlevel;
356 initparams(&params, &printlevel);
357//#ifndef DEBUG_SDPCOLORING
358 printlevel = 0;
359//#endif
360 // A return code for the call to easy_sdp().
361 // solve sdp
362 // objective value is (dobj+pobj)/2
363 //int ret = easy_sdp(num_variables, num_constraints, C, b, constraints, 0.0, &X, &y, &Z, &pobj, &dobj);
364 int ret = limbo::solvers::easy_sdp_ext<int>(num_variables, num_constraints, C, b, constraints, 0.0, &X, &y, &Z, &pobj, &dobj, params, printlevel);
365 limboAssertMsg(ret == 0, "SDP failed");
366
367// #ifdef DEBUG_LIWEI
368 clock_t solve_end = clock();
369 limboPrint(kDEBUG, "SDP solver takes %g seconds with %u nodes\n", (double)(solve_end - solve_start)/CLOCKS_PER_SEC, num_vertices);
370//#endif
371 // round result to get colors
372 round_sol(X);
373
374 // Free storage allocated for the problem and return.
375 free_prob(num_variables, num_constraints, C, b, constraints, X, y, Z);
376
377#ifdef DEBUG_LPCOLORING
378 this->write_graph("final_output");
379#endif
380 // return objective value
381 //return (dobj+pobj)/2;
382 double final_cost = this->calc_cost(this->m_vColor);
383#ifdef DEBUG_LIWEI
384 limboPrint(kDEBUG, "SDP coloring cost %g\n", final_cost);
385#endif
386 return final_cost;
387}
388
389template <typename GraphType>
390void SDPColoringCsdp<GraphType>::construct_objectve_blockrec(blockmatrix& C, int32_t blocknum, int32_t blocksize, blockcat blockcategory) const
391{
392 struct blockrec& cblock = C.blocks[blocknum];
393 cblock.blocksize = blocksize;
394 cblock.blockcategory = blockcategory;
395 if (blockcategory == MATRIX)
396 {
397 cblock.data.mat = (double *)malloc(blocksize*blocksize*sizeof(double));
398 limboAssertMsg(cblock.data.mat, "Couldn't allocate storage for cblock.data.mat");
399 // initialize to all 0s
400 std::fill(cblock.data.mat, cblock.data.mat+blocksize*blocksize, 0);
401 }
402 else if (blockcategory == DIAG)
403 {
404 cblock.data.vec = (double *)malloc((blocksize+1)*sizeof(double));
405 limboAssertMsg(cblock.data.vec, "Couldn't allocate storage for cblock.data.vec");
406 // initialize to all 0s
407 std::fill(cblock.data.vec, cblock.data.vec+blocksize+1, 0);
408 }
409}
410
411template <typename GraphType>
412struct sparseblock* SDPColoringCsdp<GraphType>::construct_constraint_sparseblock(int32_t blocknum, int32_t blocksize, int32_t constraintnum, int32_t entrynum) const
413{
414 struct sparseblock* blockptr = (struct sparseblock *)malloc(sizeof(struct sparseblock));
415 limboAssertMsg(blockptr, "Allocation of constraint block failed for blockptr");
416 blockptr->blocknum = blocknum;
417 blockptr->blocksize = blocksize;
418 blockptr->constraintnum = constraintnum;
419 blockptr->next = NULL;
420 blockptr->nextbyblock = NULL;
421 blockptr->entries = (double *) malloc((entrynum+1)*sizeof(double));
422 limboAssertMsg(blockptr->entries, "Allocation of constraint block failed for blockptr->entries");
423 blockptr->iindices = (int *) malloc((entrynum+1)*sizeof(int));
424 limboAssertMsg(blockptr->iindices, "Allocation of constraint block failed for blockptr->iindices");
425 blockptr->jindices = (int *) malloc((entrynum+1)*sizeof(int));
426 limboAssertMsg(blockptr->jindices, "Allocation of constraint block failed for blockptr->jindices");
427 blockptr->numentries = entrynum;
428
429 return blockptr;
430}
431
432template <typename GraphType>
433void SDPColoringCsdp<GraphType>::set_sparseblock_entry(struct sparseblock& block, int32_t entryid, int32_t i, int32_t j, double value) const
434{
435 block.iindices[entryid] = i;
436 block.jindices[entryid] = j;
437 block.entries[entryid] = value;
438}
439
440template <typename GraphType>
441void SDPColoringCsdp<GraphType>::round_sol(struct blockmatrix const& X)
442{
443#ifdef DEBUG_SDPCOLORING
444 write_sdp_sol("problem.sol", X);
445#endif
446 // merge vertices with SDP solution with disjoint set
447 std::vector<graph_vertex_type> vParent (boost::num_vertices(this->m_graph));
448 std::vector<uint32_t> vRank (vParent.size());
449 typedef limbo::containers::DisjointSet disjoint_set_type;
450 disjoint_set_type::SubsetHelper<graph_vertex_type, uint32_t> gp (vParent, vRank);
451 // check SDP solution in X
452 // we are only interested in block 1
453 struct blockrec const& block = X.blocks[1];
454 limboAssertMsg(block.blockcategory == MATRIX, "mismatch of block category");
455 for (int32_t i = 1; i <= block.blocksize; ++i)
456 for (int32_t j = i+1; j <= block.blocksize; ++j)
457 {
458 double ent = block.data.mat[ijtok(i, j, block.blocksize)];
459 if (ent > m_rounding_ub) // merge vertices if SDP solution rounded to 1.0
460 disjoint_set_type::union_set(gp, i-1, j-1); // Csdp array starts from 1 instead of 0
461 }
462 // construct merged graph
463 // for vertices in merged graph
464 std::vector<graph_vertex_type> vG2MG (vParent.size(), std::numeric_limits<graph_vertex_type>::max()); // mapping from graph to merged graph
465 uint32_t mg_count = 0; // count number of vertices in merged graph
466 for (uint32_t i = 0, ie = vParent.size(); i != ie; ++i) // check subset elements and compute mg_count
467 if (vParent[i] == i)
468 vG2MG[i] = mg_count++;
469 for (uint32_t i = 0, ie = vParent.size(); i != ie; ++i) // check other elements
470 if (vParent[i] != i)
471 vG2MG[i] = vG2MG.at(disjoint_set_type::find_set(gp, i));
472#ifdef DEBUG_SDPCOLORING
473 limboAssert(mg_count == disjoint_set_type::count_sets(gp));
474#endif
475 graph_type mg (mg_count); // merged graph
476 // for edges in merged graph
477 edge_iterator_type ei, eie;
478 for (boost::tie(ei, eie) = boost::edges(this->m_graph); ei != eie; ++ei)
479 {
480 graph_edge_type const& e = *ei;
481 graph_vertex_type s = boost::source(e, this->m_graph);
482 graph_vertex_type t = boost::target(e, this->m_graph);
483 graph_vertex_type ms = vG2MG.at(s);
484 graph_vertex_type mt = vG2MG.at(t);
485 if(ms == mt) continue;
486 std::pair<graph_edge_type, bool> me = boost::edge(ms, mt, mg);
487 // need to consider if this setting is still reasonable when stitch is on
488 edge_weight_type w = (this->edge_weight(e) >= 0)? 1 : -this->stitch_weight();
489 if (me.second) // already exist, update weight
490 w += boost::get(boost::edge_weight, mg, me.first);
491 else // not exist, add edge
492 me = boost::add_edge(ms, mt, mg);
493 boost::put(boost::edge_weight, mg, me.first, w);
494#ifdef DEBUG_SDPCOLORING
495 limboAssert(boost::get(boost::edge_weight, mg, me.first) != 0);
496#endif
497 }
498#ifdef DEBUG_SDPCOLORING
499 //this->print_edge_weight(this->m_graph);
500 //this->check_edge_weight(this->m_graph, this->stitch_weight()/10, 4);
501 //this->print_edge_weight(mg);
502 //this->check_edge_weight(mg, this->stitch_weight()/10, boost::num_edges(this->m_graph));
503#endif
504 // coloring for merged graph
505 std::vector<int8_t> vMColor (mg_count, -1); // coloring solution for merged graph
506 coloring_merged_graph(mg, vMColor);
507 // apply coloring solution from merged graph to graph
508 // first, map colors to subsets
509 vertex_iterator_type vi, vie;
510 for (boost::tie(vi, vie) = boost::vertices(this->m_graph); vi != vie; ++vi)
511 {
512 graph_vertex_type v = *vi;
513 this->m_vColor[v] = vMColor.at(vG2MG.at(v));
514#ifdef DEBUG_SDPCOLORING
515 limboAssert(this->m_vColor[v] >= 0 && this->m_vColor[v] < this->color_num());
516#endif
517 }
518}
519
520template <typename GraphType>
521void SDPColoringCsdp<GraphType>::coloring_merged_graph(graph_type const& mg, std::vector<int8_t>& vMColor) const
522{
523
524 uint32_t num_vertices = boost::num_vertices(mg);
525#ifdef DEBUG_LIWEI
526 limboPrint(kDEBUG, "SDP merged coloring with %u nodes\n", num_vertices);
527#endif
528 // if small number of vertices or no vertex merged, no need to simplify graph
529 if (num_vertices <= max_backtrack_num_vertices || num_vertices == boost::num_vertices(this->m_graph))
530 {
531 // std::cout << "small size graph." << std::endl;
532 coloring_algos(mg, vMColor);
533 }
534 else
535 {
536 // std::cout << "\n\nlarge size graph.\n\n" << std::endl;
537 // simplify merged graph
538 typedef GraphSimplification<graph_type> graph_simplification_type;
539 graph_simplification_type gs (mg, this->color_num());
540 gs.simplify(graph_simplification_type::HIDE_SMALL_DEGREE);
541
542 // in order to recover color from articulation points
543 // we have to record all components and mappings
544 // but graph is not necessary
545 std::vector<std::vector<int8_t> > mSubColor (gs.num_component());
546 std::vector<std::vector<graph_vertex_type> > mSimpl2Orig (gs.num_component());
547 // std::cout << "component number : " << gs.num_component() << std::endl;
548 for (uint32_t sub_comp_id = 0; sub_comp_id < gs.num_component(); ++sub_comp_id)
549 {
550 // std::cout << "now comp " << sub_comp_id << std::endl;
551 graph_type sg;
552 std::vector<int8_t>& vSubColor = mSubColor[sub_comp_id];
553 std::vector<graph_vertex_type>& vSimpl2Orig = mSimpl2Orig[sub_comp_id];
554
555 gs.simplified_graph_component(sub_comp_id, sg, vSimpl2Orig);
556
557 vSubColor.assign(boost::num_vertices(sg), -1);
558
559#ifdef DEBUG_SDPCOLORING
560 this->write_graph("initial_merged_graph_" + limbo::to_string(sub_comp_id), sg, vSubColor);
561#endif
562 // solve coloring
563 coloring_algos(sg, vSubColor);
564#ifdef DEBUG_SDPCOLORING
565 this->write_graph("final_merged_graph_" + limbo::to_string(sub_comp_id), sg, vSubColor);
566#endif
567 }
568
569#ifdef QDEBUG
570 clock_t recover_start = clock();
571#endif
572 // recover color assignment according to the simplification level set previously
573 // HIDE_SMALL_DEGREE needs to be recovered manually for density balancing
574 gs.recover(vMColor, mSubColor, mSimpl2Orig);
575/*
576 std::cout << "vMColor : " << std::endl;
577 for(uint32_t i = 0; i < vMColor.size(); ++i)
578 std::cout << +unsigned(vMColor[i]) << " ";
579*/
580 // recover colors for simplified vertices without balanced assignment
581 gs.recover_hide_small_degree(vMColor);
582#ifdef QDEBUG
583 clock_t recover_end = clock();
584 std::cout << "Coloring recovery takes " << (double)(recover_end - recover_start)/CLOCKS_PER_SEC << "s." << std::endl;
585 ::cout << "SDP final result : ";
586 for(uint32_t i = 0; i < vMColor.size(); i++)
587 std::cout << unsigned(vMColor[i]) << " ";
588 std::cout << std::endl;
589#endif
590 }
591}
592
593template <typename GraphType>
594void SDPColoringCsdp<GraphType>::coloring_algos(graph_type const& g, std::vector<int8_t>& vColor) const
595{
596 if (boost::num_vertices(g) <= max_backtrack_num_vertices)
597 {
598#ifdef DEBUG_LIWEI
599 limboPrint(kDEBUG, "coloring by backtrack with %lu nodes\n", boost::num_vertices(g));
600#endif
601 coloring_by_backtrack(g, vColor);
602 }
603 else
604 {
605#ifdef DEBUG_LIWEI
606 limboPrint(kDEBUG, "coloring by FM with %lu nodes\n", boost::num_vertices(g));
607#endif
608 coloring_by_FM(g, vColor);
609 }
610#ifdef QDEBUG
611 std::cout << "Coloring algo result : ";
612 for(uint32_t i = 0; i < vColor.size(); i++)
613 std::cout << unsigned(vColor[i]) << " ";
614 std::cout << std::endl;
615#endif
616}
617
618template <typename GraphType>
619void SDPColoringCsdp<GraphType>::coloring_by_backtrack(SDPColoringCsdp<GraphType>::graph_type const& mg, std::vector<int8_t>& vColor) const
620{
621 // currently backtrack coloring is used
622 // TO DO: add faster coloring approach like FM partition based
624 bc.stitch_weight(this->stitch_weight()); // already scaled in edge weights
625 bc.color_num(this->color_num());
626 bc();
627 for (uint32_t i = 0, ie = vColor.size(); i != ie; ++i)
628 vColor[i] = bc.color(i);
629}
630
631template <typename GraphType>
632void SDPColoringCsdp<GraphType>::coloring_by_FM(SDPColoringCsdp<GraphType>::graph_type const& mg, std::vector<int8_t>& vColor) const
633{
634#ifdef DEBUG_LIWEI
635 clock_t fm_start = clock();
636#endif
638 fmp.set_partitions(vColor.begin(), vColor.end());
639 fmp();
640 for (uint32_t i = 0, ie = vColor.size(); i != ie; ++i)
641 vColor[i] = fmp.partition(i);
642#ifdef DEBUG_LIWEI
643 clock_t fm_end = clock();
644 limboPrint(kDEBUG, "FM coloring takes %g seconds\n", (double)(fm_end - fm_start)/CLOCKS_PER_SEC);
645#endif
646}
647
648template <typename GraphType>
649void SDPColoringCsdp<GraphType>::write_sdp_sol(std::string const& filename, struct blockmatrix const& X) const
650{
651 // compute dimensions of matrix
652 uint32_t matrix_size = 0;
653 for (int32_t blk = 1; blk <= X.nblocks; ++blk)
654 matrix_size += X.blocks[blk].blocksize;
655
656 // collect data from X and store to mSol
657 std::vector<std::vector<double> > mSol (matrix_size, std::vector<double>(matrix_size, 0.0));
658 // as i and j starts from 1, set index_offset to -1
659 int32_t index_offset = 0;
660 for (int32_t blk = 1; blk <= X.nblocks; ++blk)
661 {
662 switch (X.blocks[blk].blockcategory)
663 {
664 case DIAG:
665 for (int32_t i = 1; i <= X.blocks[blk].blocksize; ++i)
666 {
667 double ent = X.blocks[blk].data.vec[i];
668 if (ent != 0.0)
669 mSol[index_offset+i-1][index_offset+i-1] = ent;
670 };
671 break;
672 case MATRIX:
673 for (int32_t i = 1; i <= X.blocks[blk].blocksize; ++i)
674 for (int32_t j = i; j <= X.blocks[blk].blocksize; ++j)
675 {
676 double ent = X.blocks[blk].data.mat[ijtok(i, j, X.blocks[blk].blocksize)];
677 if (ent != 0.0)
678 mSol[index_offset+i-1][index_offset+j-1] = ent;
679 };
680 break;
681 case PACKEDMATRIX:
682 default: limboAssertMsg(0, "Invalid Block Type");
683 }
684 index_offset += X.blocks[blk].blocksize;
685 }
686
687 // write to file
688 std::ofstream out (filename.c_str());
689 limboAssertMsg(out.good(), "failed to open file %s for write\n", filename.c_str());
690 for (std::vector<std::vector<double> >::const_iterator it1 = mSol.begin(), it1e = mSol.end(); it1 != it1e; ++it1)
691 {
692 const char* prefix = "";
693 for (std::vector<double>::const_iterator it2 = it1->begin(), it2e = it1->end(); it2 != it2e; ++it2)
694 {
695 out << prefix << *it2;
696 prefix = ",";
697 }
698 out << std::endl;
699 }
700 out.close();
701}
702
703template <typename GraphType>
704void SDPColoringCsdp<GraphType>::print_blockrec(const char* label, blockrec const& block) const
705{
706 printf("%s", label);
707 if (block.blockcategory == MATRIX)
708 {
709 printf("[M]: "); // show it is a matrix
710 for (int32_t i = 0, ie = block.blocksize*block.blocksize; i != ie; ++i)
711 printf("%g ", block.data.mat[i]);
712 }
713 else if (block.blockcategory == DIAG)
714 {
715 printf("[V]: "); // show it is a vector
716 for (int32_t i = 0; i != block.blocksize; ++i)
717 printf("%g ", block.data.vec[i+1]);
718 }
719 printf("\n");
720}
721
722} // namespace coloring
723} // namespace algorithms
724} // namespace limbo
725
726#endif
#define limboAssertMsg(condition, args...)
custom assertion with message
Definition AssertMsg.h:24
#define limboAssert(condition)
custom assertion without message
Definition AssertMsg.h:36
graph coloring by backtracking
base class for all graph coloring algorithms
this file is a modified version of easysdp.c in Csdp package. Original version does not provide con...
A disjoint set structure and union-find utilities.
Implementation of the Multi-way FM partitioning algorithm.
Various graph simplification techniques for graph coloring. Some of them can also be used in other ap...
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
virtual edge_weight_type edge_weight(graph_edge_type const &e) const
Definition Coloring.h:202
virtual double stitch_weight() const
Definition Coloring.h:184
virtual bool has_precolored() const
Definition Coloring.h:181
std::vector< int8_t > m_vColor
coloring solutions
Definition Coloring.h:240
virtual edge_weight_type calc_cost(std::vector< int8_t > const &vColor) const
Definition Coloring.h:397
virtual void color_num(ColorNumType cn)
Definition Coloring.h:168
virtual void coloring_by_FM(graph_type const &mg, std::vector< int8_t > &vColor) const
void write_sdp_sol(std::string const &filename, struct blockmatrix const &X) const
double m_rounding_lb
if SDP solution x < m_rounding_lb, take x as -0.5
void coloring_algos(graph_type const &g, std::vector< int8_t > &vColor) const
double m_rounding_ub
if SDP solution x > m_rounding_ub, take x as 1.0
void round_sol(struct blockmatrix const &X)
static const uint32_t max_backtrack_num_vertices
maximum number of graph size that limbo::algorithms::coloring::BacktrackColoring can handle
virtual void coloring_by_backtrack(graph_type const &mg, std::vector< int8_t > &vColor) const
void print_blockrec(const char *label, blockrec const &block) const
void set_sparseblock_entry(struct sparseblock &block, int32_t entryid, int32_t i, int32_t j, double value) const
void coloring_merged_graph(graph_type const &mg, std::vector< int8_t > &vMColor) const
struct sparseblock * construct_constraint_sparseblock(int32_t blocknum, int32_t blocksize, int32_t constraintnum, int32_t entrynum) const
void construct_objectve_blockrec(blockmatrix &C, int32_t blocknum, int32_t blocksize, blockcat blockcategory) const
void set_partitions(Iterator first, Iterator last)
set partitions
Definition FMMultiWay.h:74
signed char partition(int v) const
get partition of a vertex
Definition FMMultiWay.h:78
namespace for Limbo.Algorithms.Coloring
namespace for Limbo.algorithms
void write_graph(std::ofstream &out, GraphType const &g, VertexLabelType const &vl, EdgeLabelType const &el)
write graph to graphviz format and convert to pdf. Although Boost.Graph has write_graphviz component,...
int easy_sdp_ext(int n, int k, struct blockmatrix C, double *a, struct constraintmatrix *constraints, double constant_offset, struct blockmatrix *pX, double **py, struct blockmatrix *pZ, double *ppobj, double *pdobj, struct paramstruc const &params, int const &printlevel)
API to call Csdp solver.
namespace for Limbo
string to_string(int val)
convert integer to string
Definition ToString.h:24
int limboPrint(MessageType m, const char *format,...)
formatted print with prefix
Definition PrintMsg.h:49
edge_weight_type value_type
define edge_weight_type as value_type
edge_weight_type operator()(int32_t v, int8_t origp, int8_t newp, std::vector< int8_t > const &vPartition) const
simply used for scope control
Definition DisjointSet.h:29