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