Limbo 3.5.4
Loading...
Searching...
No Matches
GraphSimplification.h
Go to the documentation of this file.
1
12
13#ifndef LIMBO_ALGORITHMS_GRAPHSIMPLIFICATION_H
14#define LIMBO_ALGORITHMS_GRAPHSIMPLIFICATION_H
15#include <iostream>
16#include <fstream>
17#include <vector>
18#include <stack>
19#include <list>
20#include <string>
21#include <map>
22#include <set>
23#include <deque>
24#include <boost/graph/graph_concepts.hpp>
25#include <boost/graph/graph_utility.hpp>
26#include <boost/graph/adjacency_list.hpp>
27#include <boost/graph/undirected_graph.hpp>
28#include <boost/property_map/property_map.hpp>
30#include <limbo/math/Math.h>
32
34namespace limbo
35{
37namespace algorithms
38{
40namespace coloring
41{
42
43namespace la = ::limbo::algorithms;
44
49template <typename GraphType>
51{
52 public:
54 typedef GraphType graph_type;
55 typedef typename boost::graph_traits<graph_type>::vertex_descriptor graph_vertex_type;
56 typedef typename boost::graph_traits<graph_type>::edge_descriptor graph_edge_type;
57 typedef typename boost::graph_traits<graph_type>::vertex_iterator vertex_iterator;
58 typedef typename boost::graph_traits<graph_type>::adjacency_iterator adjacency_iterator;
59 typedef typename boost::graph_traits<graph_type>::edge_iterator edge_iterator;
61
68
78
81 GraphSimplification(graph_type const& g, uint32_t color_num)
82 : m_graph (g)
83 , m_color_num (color_num)
84 , m_level (NONE)
85 , m_max_merge_level(std::numeric_limits<uint32_t>::max())
86 , m_vStatus(boost::num_vertices(g), GOOD)
87 , m_vParent(boost::num_vertices(g))
88 , m_vChildren(boost::num_vertices(g))
91// , m_vComponent(boost::num_vertices(g), std::numeric_limits<uint32_t>::max())
92// , m_sBridgeEdge()
93 , m_mArtiPoint()
94 , m_vPrecolor(boost::num_vertices(g), -1)
95 , m_isVDDGND(boost::num_vertices(g), false) // added by Qi Sun, represent whethe this vertex is VDDGND, used in IVR
96 {
97 graph_vertex_type v = 0;
98 for (typename std::vector<graph_vertex_type>::iterator it = m_vParent.begin(), ite = m_vParent.end(); it != ite; ++it, ++v)
99 (*it) = v;
100 v = 0;
101 for (typename std::vector<std::vector<graph_vertex_type> >::iterator it = m_vChildren.begin(), ite = m_vChildren.end(); it != ite; ++it, ++v)
102 it->push_back(v);
103#ifdef DEBUG_GRAPHSIMPLIFICATION
104 limboAssert(m_vParent.size() == boost::num_vertices(m_graph));
105 limboAssert(m_vChildren.size() == boost::num_vertices(m_graph));
106#endif
107 }
108
111
115 template <typename Iterator>
116 void precolor(Iterator first, Iterator last)
117 {
118 m_vPrecolor.assign(first, last);
119#ifdef DEBUG_GRAPHSIMPLIFICATION
120 limboAssert(m_vPrecolor.size() == boost::num_vertices(m_graph));
121#endif
122 }
123
125 std::vector<vertex_status_type> const& status() const {return m_vStatus;}
127 std::vector<graph_vertex_type> const& parents() const {return m_vParent;}
129 std::vector<std::vector<graph_vertex_type> > const& children() const {return m_vChildren;}
131 std::stack<graph_vertex_type> const& hidden_vertices() const {return m_vHiddenVertex;}
132
134 std::pair<graph_type, std::map<graph_vertex_type, graph_vertex_type> > simplified_graph() const;
140 bool simplified_graph_component(uint32_t comp_id, graph_type& sg, std::vector<graph_vertex_type>& vSimpl2Orig) const;
141
143 // bool simplified_graph_component(uint32_t comp_id, graph_type& sg, std::vector<graph_vertex_type>& vSimpl2Orig, std::map<graph_vertex_type, std::vector<graph_vertex_type> >& s_graph_edges) const;
144
146 uint32_t num_component() const {return m_mCompVertex.size();}
147
149 void get_CompVertex(std::vector<std::vector<graph_vertex_type> >& CompVertex);
150
153 void max_merge_level(int32_t l) {m_max_merge_level = l;}
154
157 void simplify(uint32_t level);
162 void recover(std::vector<int8_t>& vColorFlat, std::vector<std::vector<int8_t> >& mColor, std::vector<std::vector<graph_vertex_type> > const& mSimpl2Orig) const;
163
165 void set_isVDDGND(std::set<graph_vertex_type> vdd_set);
166 void set_isHiden(std::set<graph_vertex_type> is_hidens);
167
169 bool whether_VDDGND(graph_vertex_type id);
177 void merge_subK4();
178
180 void hide_small_degree();
181 // find all bridge edges and divided graph into components
182 //void remove_bridge();
185
187 void mergeVDD(std::set<graph_vertex_type> vdd_set);
188
191 void recover_merge_subK4(std::vector<int8_t>& vColor) const;
192 // recover color for bridges
193 // @param vColor must be partially assigned colors except simplified vertices
194 //void recover_bridge(std::vector<int8_t>& vColor) const;
195
199 void recover_biconnected_component(std::vector<std::vector<int8_t> >& mColor, std::vector<std::vector<graph_vertex_type> > const& mSimpl2Orig) const;
204 void recover_hide_small_degree(std::vector<int8_t>& vColor);
205
208 void write_graph_dot(std::string const& filename) const;
211 void write_simplified_graph_dot(std::string const& filename) const;
214 bool articulation_point(graph_vertex_type v) const
215 {
216 return m_mArtiPoint.count(v);
217 }
218 void get_articulations(std::vector<graph_vertex_type> &art_vec)
219 {
220 std::vector<graph_vertex_type>().swap(art_vec);
221 typename std::map<graph_vertex_type, std::set<uint32_t> >::iterator it = m_mArtiPoint.begin();
222 while (it != m_mArtiPoint.end())
223 {
224 art_vec.push_back(it->first);
225 it++;
226 }
227 }
228
229 protected:
239 void biconnected_component_recursion(graph_vertex_type v, std::deque<bool>& vVisited, std::vector<uint32_t>& vDisc,
240 std::vector<uint32_t>& vLow, std::vector<graph_vertex_type>& vParent, uint32_t& visit_time,
241 std::stack<std::pair<graph_vertex_type, graph_vertex_type> >& vEdge,
242 std::list<std::pair<graph_vertex_type, std::set<graph_vertex_type> > >& mCompVertex) const;
244 void connected_component();
248 graph_vertex_type parent(graph_vertex_type v) const
249 {
250#ifdef DEBUG_GRAPHSIMPLIFICATION
251 limboAssert(!this->hidden(v));
252#endif
253 while (v != m_vParent.at(v))
254 v = m_vParent.at(v);
255 return v;
256 }
257
261 graph_vertex_type parent(uint32_t v, std::vector<uint32_t> const& vParent) const
262 {
263 while (v != vParent.at(v))
264 v = vParent.at(v);
265 return v;
266 }
267
270 bool connected_conflict(graph_vertex_type v1, graph_vertex_type v2) const
271 {
272 graph_vertex_type vp1 = this->parent(v1);
273 graph_vertex_type vp2 = this->parent(v2);
274 std::vector<graph_vertex_type> const& vChildren1 = m_vChildren.at(vp1);
275 std::vector<graph_vertex_type> const& vChildren2 = m_vChildren.at(vp2);
276 for (typename std::vector<graph_vertex_type>::const_iterator vic1 = vChildren1.begin(); vic1 != vChildren1.end(); ++vic1)
277 for (typename std::vector<graph_vertex_type>::const_iterator vic2 = vChildren2.begin(); vic2 != vChildren2.end(); ++vic2)
278 {
279 std::pair<graph_edge_type, bool> e12 = boost::edge(*vic1, *vic2, m_graph);
280 // only count conflict edge
281 if (e12.second && boost::get(boost::edge_weight, m_graph, e12.first) >= 0) return true;
282 }
283 return false;
284 }
285
288 bool connected_stitch(graph_vertex_type v1, graph_vertex_type v2) const
289 {
290 graph_vertex_type vp1 = this->parent(v1);
291 graph_vertex_type vp2 = this->parent(v2);
292 std::vector<graph_vertex_type> const& vChildren1 = m_vChildren.at(vp1);
293 std::vector<graph_vertex_type> const& vChildren2 = m_vChildren.at(vp2);
294 for (typename std::vector<graph_vertex_type>::const_iterator vic1 = vChildren1.begin(); vic1 != vChildren1.end(); ++vic1)
295 for (typename std::vector<graph_vertex_type>::const_iterator vic2 = vChildren2.begin(); vic2 != vChildren2.end(); ++vic2)
296 {
297 std::pair<graph_edge_type, bool> e12 = boost::edge(*vic1, *vic2, m_graph);
298 // only count conflict edge
299 if (e12.second && boost::get(boost::edge_weight, m_graph, e12.first) < 0) return true;
300 }
301 return false;
302 }
303
306 std::pair<graph_edge_type, bool> connected_edge(graph_vertex_type v1, graph_vertex_type v2) const
307 {
308 graph_vertex_type vp1 = this->parent(v1);
309 graph_vertex_type vp2 = this->parent(v2);
310 std::vector<graph_vertex_type> const& vChildren1 = m_vChildren.at(vp1);
311 std::vector<graph_vertex_type> const& vChildren2 = m_vChildren.at(vp2);
312 for (typename std::vector<graph_vertex_type>::const_iterator vic1 = vChildren1.begin(); vic1 != vChildren1.end(); ++vic1)
313 for (typename std::vector<graph_vertex_type>::const_iterator vic2 = vChildren2.begin(); vic2 != vChildren2.end(); ++vic2)
314 {
315 std::pair<graph_edge_type, bool> e12 = boost::edge(*vic1, *vic2, m_graph);
316 if (e12.second) return e12;
317 }
318 return std::make_pair(graph_edge_type(), false);
319 }
320
322 bool merged(graph_vertex_type v1) const
323 {
324 bool flag = (m_vStatus.at(v1) == MERGED);
325#ifdef DEBUG_GRAPHSIMPLIFICATION
326 limboAssert(flag == m_vChildren.at(v1).empty());
327 if (!flag) limboAssert(v1 == m_vParent.at(v1));
328 else limboAssert(v1 != m_vParent.at(v1));
329#endif
330 return flag;
331 }
332
334 bool good(graph_vertex_type v1) const
335 {
336 return (m_vStatus.at(v1) == GOOD);
337 }
338
340 bool hidden(graph_vertex_type v1) const
341 {
342 return (m_vStatus.at(v1) == HIDDEN);
343 }
344
346 bool precolored(graph_vertex_type v1) const
347 {
348 return (m_vPrecolor.at(v1) >= 0);
349 }
350
351 bool has_precolored() const
352 {
353 for (std::vector<int8_t>::const_iterator it = m_vPrecolor.begin(); it != m_vPrecolor.end(); ++it)
354 {
355 if (*it >= 0)
356 return true;
357 }
358 return false;
359 }
360
362 bool check_max_merge_level(uint32_t l) const
363 {
364 return l <= m_max_merge_level;
365 }
366 graph_type const& m_graph;
367 uint32_t m_color_num;
368 uint32_t m_level;
370 std::vector<vertex_status_type> m_vStatus;
371
372 std::vector<graph_vertex_type> m_vParent;
373 std::vector<std::vector<graph_vertex_type> > m_vChildren;
374
375 std::stack<graph_vertex_type> m_vHiddenVertex;
376
377 std::vector<std::vector<graph_vertex_type> > m_mCompVertex;
378// std::vector<uint32_t> m_vComponent; ///< component id for each vertex
379
380// std::set<graph_edge_type> m_sBridgeEdge; ///< bridge edges that are removed during graph division
381 std::map<graph_vertex_type, std::set<uint32_t> > m_mArtiPoint;
382
383 std::vector<int8_t> m_vPrecolor;
384
385 std::vector<bool> m_isVDDGND;
386};
387
389template <typename GraphType>
390std::pair<typename GraphSimplification<GraphType>::graph_type, std::map<typename GraphSimplification<GraphType>::graph_vertex_type, typename GraphSimplification<GraphType>::graph_vertex_type> >
392{
393 size_t vertex_cnt = 0;
394 std::map<graph_vertex_type, graph_vertex_type> mG2MG;
395 std::map<graph_vertex_type, graph_vertex_type> mMG2G;
396 vertex_iterator vi1, vie1;
397 for (boost::tie(vi1, vie1) = boost::vertices(m_graph); vi1 != vie1; ++vi1)
398 {
399 graph_vertex_type v1 = *vi1;
400 if (this->good(v1))
401 {
402 mG2MG[*vi1] = vertex_cnt;
403 mMG2G[vertex_cnt] = v1;
404 vertex_cnt += 1;
405 }
406 }
407 graph_type mg (vertex_cnt);
408
409 edge_iterator ei, eie;
410 for (boost::tie(ei, eie) = boost::edges(m_graph); ei != eie; ++ei)
411 {
412 graph_edge_type e = *ei;
413 graph_vertex_type s = boost::source(e, m_graph);
414 graph_vertex_type t = boost::target(e, m_graph);
415 // skip edge with hidden vertices
416 if (this->hidden(s) || this->hidden(t)) continue;
417
418 graph_vertex_type sp = this->parent(s);
419 graph_vertex_type tp = this->parent(t);
420
421#ifdef DEBUG_GRAPHSIMPLIFICATION
422 limboAssert(mG2MG.count(sp));
423 limboAssert(mG2MG.count(tp));
424#endif
425 graph_vertex_type msp = mG2MG[sp];
426 graph_vertex_type mtp = mG2MG[tp];
427 std::pair<graph_edge_type, bool> emg = boost::edge(msp, mtp, mg);
428 if (!emg.second)
429 {
430 emg = boost::add_edge(msp, mtp, mg);
431 limboAssert(emg.second);
432 boost::put(boost::edge_weight, mg, emg.first, boost::get(boost::edge_weight, m_graph, e));
433 }
434 else
435 {
436 // use cumulative weight
437 // this is to make sure we can still achieve small conflict number in the simplified graph
438 // no longer optimal if merge_subK4() is called
439 boost::put(
440 boost::edge_weight, mg, emg.first,
441 boost::get(boost::edge_weight, mg, emg.first) + boost::get(boost::edge_weight, m_graph, e)
442 );
443 }
444 }
445 return std::make_pair(mg, mMG2G);
446}
447
448template <typename GraphType>
449void GraphSimplification<GraphType>::get_CompVertex(std::vector<std::vector<typename GraphSimplification<GraphType>::graph_vertex_type> >& CompVertex)
450{
451 for (typename std::vector<std::vector<graph_vertex_type> >::iterator it = m_mCompVertex.begin(); it != m_mCompVertex.end(); it++)
452 {
453 CompVertex.push_back(*it);
454 }
455}
456
457template <typename GraphType>
458bool GraphSimplification<GraphType>::whether_VDDGND(typename GraphSimplification<GraphType>::graph_vertex_type id)
459{
460 return m_isVDDGND[id];
461}
462
463template <typename GraphType>
464bool GraphSimplification<GraphType>::simplified_graph_component(uint32_t comp_id, typename GraphSimplification<GraphType>::graph_type& simplG,
465 std::vector<typename GraphSimplification<GraphType>::graph_vertex_type>& vSimpl2Orig) const
466{
467 if (comp_id >= m_mCompVertex.size()) return false;
468
469 std::vector<graph_vertex_type> const& vCompVertex = m_mCompVertex[comp_id];
470
471 graph_type sg (vCompVertex.size());
472 std::map<graph_vertex_type, graph_vertex_type> mOrig2Simpl;
473 vSimpl2Orig.assign(vCompVertex.begin(), vCompVertex.end());
474 for (uint32_t i = 0; i != vCompVertex.size(); ++i)
475 mOrig2Simpl[vCompVertex[i]] = i;
476#ifdef DEBUG_GRAPHSIMPLIFICATION
477 std::cout << "Comp " << comp_id << ": ";
478 for (uint32_t i = 0; i != vCompVertex.size(); ++i)
479 std::cout << vCompVertex[i] << " ";
480 std::cout << std::endl;
481#endif
482#ifdef DEBUG_LIWEI
483 bool flag = false;
484 std::cout << "\nSimplified Comp " << comp_id << " : \n";
485 for (uint32_t i = 0; i != vCompVertex.size(); ++i)
486 std::cout << i << " : " << vCompVertex[i] << std::endl;
487 std::cout << std::endl;
488 //std::cout << "Original to Simplified : " << std::endl;
489 for (uint32_t i = 0; i != vCompVertex.size(); ++i)
490 {
491 std::cout << vCompVertex[i] << " : " << i << std::endl;
492 mOrig2Simpl[vCompVertex[i]] = i;
493 }
494 std::cout << std::endl;
495 if (vCompVertex[0] == 1 && vCompVertex[1] == 42)
496 flag = true;
497#endif
498 for (typename std::vector<graph_vertex_type>::const_iterator vi = vCompVertex.begin(); vi != vCompVertex.end(); ++vi)
499 {
500 graph_vertex_type v = *vi;
501
502 graph_vertex_type vsg = mOrig2Simpl[v];
503 limboAssert(this->good(v));
504 bool ap = this->articulation_point(v);
505
506#ifdef DEBUG_LIWEI
507 if (flag)
508 {
509 limboPrint(kDEBUG, "v : %u ap : %d\n", (uint32_t)v, (int)ap);
510 }
511#endif
512 std::vector<graph_vertex_type> const& vChildren = m_vChildren.at(v);
513 for (typename std::vector<graph_vertex_type>::const_iterator vic = vChildren.begin(); vic != vChildren.end(); ++vic)
514 {
515 graph_vertex_type vc = *vic;
516#ifdef DEBUG_LIWEI
517 if (flag)
518 {
519 std::cout << "vc : " << vc << std::endl;
520 }
521#endif
522 typename boost::graph_traits<graph_type>::adjacency_iterator ui, uie;
523 for (boost::tie(ui, uie) = boost::adjacent_vertices(vc, m_graph); ui != uie; ++ui)
524 {
525 graph_vertex_type uc = *ui;
526 // skip hidden
527 if (this->hidden(uc)) continue;
528 graph_vertex_type u = this->parent(uc);
529#ifdef DEBUG_LIWEI
530 if (flag)
531 {
532 std::cout << "uc : " << uc << " parent u : " << u << std::endl;
533 }
534#endif
535 // skip non-good
536 if (!this->good(u)) continue;
537 else if (v >= u) continue; // avoid duplicate
538 else if (ap && !mOrig2Simpl.count(u)) continue; // skip vertex that is not in component
539 //else if (u == v) continue;
540 limboAssertMsg(u != v, "%u == %u", u, v);
541
542 std::pair<graph_edge_type, bool> e = boost::edge(vc, uc, m_graph);
543 limboAssert(e.second);
544 // skip bridge
545 //if (m_sBridgeEdge.count(e.first)) continue;
546 graph_vertex_type usg = mOrig2Simpl[u];
547#ifdef DEBUG_LIWEI
548 if (flag)
549 {
550 std::cout << "usg : " << usg << " vsg : " << vsg << std::endl;
551 }
552#endif
553 limboAssertMsg(usg != vsg, "%u==%u: %u == %u", u, v, usg, vsg);
554
555 std::pair<graph_edge_type, bool> esg = boost::edge(vsg, usg, sg);
556 if (!esg.second)
557 {
558 esg = boost::add_edge(vsg, usg, sg);
559 limboAssert(esg.second);
560 boost::put(boost::edge_weight, sg, esg.first, boost::get(boost::edge_weight, m_graph, e.first));
561 }
562 else
563 {
564 // use cumulative weight
565 // this is to make sure we can still achieve small conflict number in the simplified graph
566 // no longer optimal if merge_subK4() is called
567 boost::put(
568 boost::edge_weight, sg, esg.first,
569 boost::get(boost::edge_weight, sg, esg.first) + boost::get(boost::edge_weight, m_graph, e.first)
570 );
571 }
572 }
573 }
574 }
575 simplG.swap(sg);
576
577 vertex_iterator vi1, vie1;
578 int count = 0;
579 //std::cout << "Simplified comp " << comp_id << " has " << boost::num_vertices(simplG) << " nodes : " << std::endl;
580 for (boost::tie(vi1, vie1) = boost::vertices(simplG); vi1 != vie1; ++vi1)
581 {
582 count++;
583 }
584 return true;
585}
586
587template <typename GraphType>
588void GraphSimplification<GraphType>::set_isVDDGND(std::set<typename GraphSimplification<GraphType>::graph_vertex_type> vdd_set)
589{
590 for(typename std::set<graph_vertex_type>::iterator it = vdd_set.begin(); it != vdd_set.end(); it++)
591 m_isVDDGND[*it] = true;
592}
593
594template <typename GraphType>
595void GraphSimplification<GraphType>::set_isHiden(std::set<typename GraphSimplification<GraphType>::graph_vertex_type> is_hidens)
596{
597 for(typename std::set<graph_vertex_type>::iterator it = is_hidens.begin(); it != is_hidens.end(); it++)
598 m_vStatus[*it] = HIDDEN;
599}
600
601template <typename GraphType>
602void GraphSimplification<GraphType>::mergeVDD(std::set<typename GraphSimplification<GraphType>::graph_vertex_type> vdd_set)
603{
604 typename std::set<graph_vertex_type>::iterator it = vdd_set.begin();
605
606 graph_vertex_type parent = *it;
607 it++;
608 for (; it != vdd_set.end(); it++)
609 {
610 m_vParent[*it] = parent;
611 m_vStatus[*it] = MERGED;
612 }
613 it = vdd_set.begin();
614 it++;
615 for (; it != vdd_set.end(); it++)
616 {
617 m_vChildren[parent].push_back(*it);
618 }
619
620}
621
622template <typename GraphType>
624{
625 m_level = level; // record level for recover()
626 if (this->has_precolored()) // this step does not support precolored graph yet
628
629 bool reconstruct = true; // whether needs to reconstruct m_mCompVertex
630
632 {
633 this->hide_small_degree(); // connected components are computed inside
634 reconstruct = false;
635 }
636 if (m_level & MERGE_SUBK4)
637 {
638 this->merge_subK4();
639 }
641 {
642 this->biconnected_component();
643 reconstruct = false;
644#ifdef DEBUG_LIWEI
645 uint32_t comp_id = 0;
646 for (typename std::vector<std::vector<graph_vertex_type> >::iterator it = m_mCompVertex.begin(); it != m_mCompVertex.end(); it++, comp_id++)
647 {
648 for (typename std::vector<graph_vertex_type>::iterator its = it->begin(); its != it->end(); its++)
649 {
650 if (m_isVDDGND[*its])
651 {
652 limboPrint(kDEBUG, "comp %u has VDD %u\n", comp_id, (uint32_t)*its);
653 }
654 }
655 }
656#endif
657 }
658 if (reconstruct) // if BICONNECTED_COMPONENT or HIDE_SMALL_DEGREE is not on, we need to construct m_mCompVertex with size 1
659 {
660 m_mCompVertex.assign(1, std::vector<graph_vertex_type>());
661 for (graph_vertex_type v = 0, ve = boost::num_vertices(m_graph); v != ve; ++v)
662 if (this->good(v))
663 m_mCompVertex[0].push_back(v);
664 }
665}
666
667template <typename GraphType>
668void GraphSimplification<GraphType>::recover(std::vector<int8_t>& vColorFlat, std::vector<std::vector<int8_t> >& mColor, std::vector<std::vector<graph_vertex_type> > const& mSimpl2Orig) const
669{
670 // reverse order w.r.t simplify()
672 this->recover_biconnected_component(mColor, mSimpl2Orig);
673
674 // std::map mColor to vColorFlat
675 for (uint32_t sub_comp_id = 0; sub_comp_id < mColor.size(); ++sub_comp_id)
676 {
677 std::vector<int8_t> const& vColor = mColor[sub_comp_id];
678 std::vector<graph_vertex_type> const& vSimpl2Orig = mSimpl2Orig[sub_comp_id];
679 for (uint32_t subv = 0; subv < vColor.size(); ++subv)
680 {
681 graph_vertex_type v = vSimpl2Orig[subv];
682 if (vColorFlat[v] >= 0)
683 limboAssert(vColorFlat[v] == vColor[subv]);
684 else
685 vColorFlat[v] = vColor[subv];
686 }
687 }
688
689 if (m_level & MERGE_SUBK4)
690 {
691 this->recover_merge_subK4(vColorFlat);
692 }
694 {
695 // TO DO: this part has custom requirement, such as density balancing
696 // so now it is recovered manually
697 }
698}
699
706template <typename GraphType>
708{
709 // when applying this function, be aware that other merging strategies may have already been applied
710 // so m_vParent is valid
711 //
712 // merge iteratively
713 bool merge_flag; // true if merge occurs
714 do
715 {
716 merge_flag = false;
717 // traverse the neighbors of vertex 1 to find connected vertex 2 and 3
718 vertex_iterator vi1, vie1;
719 for (boost::tie(vi1, vie1) = boost::vertices(m_graph); vi1 != vie1; ++vi1)
720 {
721 graph_vertex_type v1 = *vi1;
722 // only track good vertices
723 if (!this->good(v1)) continue;
724 // find vertex 2 by searching the neighbors of vertex 1
725 std::vector<graph_vertex_type> const& vChildren1 = m_vChildren.at(v1);
726 for (typename std::vector<graph_vertex_type>::const_iterator vic1 = vChildren1.begin(); vic1 != vChildren1.end(); ++vic1)
727 {
728#ifdef DEBUG_GRAPHSIMPLIFICATION
729 limboAssert(vic1-vChildren1.begin() >= 0);
730#endif
731 graph_vertex_type vc1 = *vic1;
732 adjacency_iterator vi2, vie2;
733 for (boost::tie(vi2, vie2) = boost::adjacent_vertices(vc1, m_graph); vi2 != vie2; ++vi2)
734 {
735 // skip hidden vertex
736 if (this->hidden(*vi2)) continue;
737 // skip stitch edges
738 std::pair<graph_edge_type, bool> e12 = boost::edge(vc1, *vi2, m_graph);
739 limboAssert(e12.second);
740 if (boost::get(boost::edge_weight, m_graph, e12.first) < 0) continue;
741
742 graph_vertex_type v2 = this->parent(*vi2);
743 // find vertex 3 by searching the neighbors of vertex 2
744 std::vector<graph_vertex_type> const& vChildren2 = m_vChildren.at(v2);
745 for (typename std::vector<graph_vertex_type>::const_iterator vic2 = vChildren2.begin(); vic2 != vChildren2.end(); ++vic2)
746 {
747 graph_vertex_type vc2 = *vic2;
748 adjacency_iterator vi3, vie3;
749 for (boost::tie(vi3, vie3) = boost::adjacent_vertices(vc2, m_graph); vi3 != vie3; ++vi3)
750 {
751 // skip hidden vertex
752 if (this->hidden(*vi3)) continue;
753 // skip stitch edges
754 std::pair<graph_edge_type, bool> e23 = boost::edge(vc2, *vi3, m_graph);
755 limboAssert(e23.second);
756 if (boost::get(boost::edge_weight, m_graph, e23.first) < 0) continue;
757
758 graph_vertex_type v3 = this->parent(*vi3);
759 // skip v1, v1 must be a parent
760 if (v3 == v1) continue;
761 // only connected 1 and 3 are considered
762 if (!this->connected_conflict(v1, v3)) continue;
763
764 // find vertex 4 by searching the neighbors of vertex 3
765 std::vector<graph_vertex_type> const& vChildren3 = m_vChildren.at(v3);
766 for (typename std::vector<graph_vertex_type>::const_iterator vic3 = vChildren3.begin(); vic3 != vChildren3.end(); ++vic3)
767 {
768 graph_vertex_type vc3 = *vic3;
769 adjacency_iterator vi4, vie4;
770 for (boost::tie(vi4, vie4) = boost::adjacent_vertices(vc3, m_graph); vi4 != vie4; ++vi4)
771 {
772 // skip hidden vertex and skip precolored vertex
773 if (this->hidden(*vi4) || this->precolored(*vi4)) continue;
774 // skip stitch edges
775 std::pair<graph_edge_type, bool> e34 = boost::edge(vc3, *vi4, m_graph);
776 limboAssert(e34.second);
777 if (boost::get(boost::edge_weight, m_graph, e34.first) < 0) continue;
778
779 graph_vertex_type v4 = this->parent(*vi4);
780 // skip v1 or v2, v1 and v2 must be parent, and v4 must not be precolored
781 if (v4 == v1 || v4 == v2 || this->precolored(v4)) continue;
782 // vertex 2 and vertex 4 must be connected
783 // vertex 1 and vertex 4 must not be connected (K4)
784 if (!this->connected_conflict(v2, v4) || this->connected_conflict(v1, v4)) continue;
785 // check max merge level
786 if (!this->check_max_merge_level(m_vChildren[v1].size()+m_vChildren[v4].size())) continue;
787 // merge vertex 4 to vertex 1
788 m_vStatus[v4] = MERGED;
789 m_vChildren[v1].insert(m_vChildren[v1].end(), m_vChildren[v4].begin(), m_vChildren[v4].end());
790 m_vChildren[v4].resize(0); // clear and shrink to fit
791 m_vParent[v4] = v1;
792 merge_flag = true;
793#ifdef DEBUG_GRAPHSIMPLIFICATION
794 limboAssert(m_vStatus[v1] == GOOD);
795 //this->write_graph_dot("graph_simpl");
796#endif
797 break;
798 }
799 if (merge_flag) break;
800 }
801 if (merge_flag) break;
802 }
803 if (merge_flag) break;
804 }
805 if (merge_flag) break;
806 }
807 if (merge_flag) break;
808 }
809 if (merge_flag) break;
810 }
811 } while (merge_flag);
812}
813
815template <typename GraphType>
817{
818 // when applying this function, be aware that other strategies may have already been applied
819 // make sure it is compatible
820
821 bool hide_flag;
822 do
823 {
824 hide_flag = false;
825 // traverse the neighbors of vertex 1 to find connected vertex 2 and 3
826 vertex_iterator vi1, vie1;
827 for (boost::tie(vi1, vie1) = boost::vertices(m_graph); vi1 != vie1; ++vi1)
828 {
829 graph_vertex_type v1 = *vi1;
830 // only track good and uncolored vertices
831 if (!this->good(v1) || this->precolored(v1)) continue;
832 size_t conflictPreVDD_degree = 0;
833 size_t stitchPreVDD_degree = 0;
834 // find vertex 2 by searching the neighbors of vertex 1
835 std::vector<graph_vertex_type> const& vChildren1 = m_vChildren.at(v1);
836 bool bFind = false;
837 for (typename std::vector<graph_vertex_type>::const_iterator vic1 = vChildren1.begin(); vic1 != vChildren1.end(); ++vic1)
838 {
839#ifdef DEBUG_GRAPHSIMPLIFICATION
840 limboAssert(vic1-vChildren1.begin() >= 0);
841#endif
842 graph_vertex_type vc1 = *vic1;
843 adjacency_iterator vi2, vie2;
844 for (boost::tie(vi2, vie2) = boost::adjacent_vertices(vc1, m_graph); vi2 != vie2; ++vi2)
845 {
846 // skip hidden vertex
847 if (this->hidden(*vi2)) continue;
848 // skip stitch edges
849 std::pair<graph_edge_type, bool> e12 = boost::edge(vc1, *vi2, m_graph);
850 limboAssert(e12.second);
851 if (boost::get(boost::edge_weight, m_graph, e12.first) < 0)
852 {
853 stitchPreVDD_degree += 1;
854 continue;
855 }
856 // not exactly the number of conflict edge
857 bool isVdd = m_isVDDGND[*vi2];
858 if (isVdd && bFind) continue;
859 if (isVdd) bFind = true;
860
861 conflictPreVDD_degree += 1;
862 }
863 }
864 if (conflictPreVDD_degree < m_color_num && stitchPreVDD_degree ==0) // hide v1
865 {
866 //m_vStatus[v1] = HIDDEN;
867 m_vHiddenVertex.push(v1);
868 hide_flag = true;
869 // hide all the children of v1
870 // but no need to push them to the std::stack m_vHiddenVertex
871 // v1 is also in its children
872 std::vector<graph_vertex_type> const& vChildren1 = m_vChildren.at(v1);
873 for (typename std::vector<graph_vertex_type>::const_iterator vic1 = vChildren1.begin(); vic1 != vChildren1.end(); ++vic1)
874 m_vStatus[*vic1] = HIDDEN;
875#ifdef DEBUG_GRAPHSIMPLIFICATION
876 std::cout << "std::stack +" << v1 << std::endl;
878#endif
879 break;
880 }
881 }
882 } while (hide_flag);
883
884 this->connected_component();
885}
886
887// refer to http://www.geeksforgeeks.org/articulation-points-or-cut-vertices-in-a-graph/
888// for the recursive implementation
889template <typename GraphType>
891{
892 uint32_t vertex_num = boost::num_vertices(m_graph);
893 std::stack<graph_vertex_type> vStack; // std::stack for dfs
894 // for speed instead of memory (no bool)
895 std::deque<bool> vVisited (vertex_num, false);
896 std::vector<graph_vertex_type> vParent (vertex_num);
897 std::vector<uint32_t> vChildrenCnt (vertex_num, 0);
898 // vLow[u] = min(vDisc[u], vDisc[w]), where w is an ancestor of u
899 // there is a back edge from some descendant of u to w
900 std::vector<uint32_t> vLow (vertex_num, std::numeric_limits<uint32_t>::max()); // lowest vertex reachable from subtree under v
901 std::vector<uint32_t> vDisc(vertex_num, std::numeric_limits<uint32_t>::max()); // discovery time
902 std::deque<bool> vArtiPoint (vertex_num, false); // true if it is articulation point
903 std::stack<std::pair<graph_vertex_type, graph_vertex_type> > vEdge; // virtual edge, it can be connection between parents
904 std::list<std::pair<graph_vertex_type, std::set<graph_vertex_type> > > mCompVertex; // save bi-connected components
905 uint32_t visit_time = 0;
906
907 // set initial parent of current vertex to itself
908 vertex_iterator vi, vie;
909 for (boost::tie(vi, vie) = boost::vertices(m_graph); vi != vie; ++vi)
910 vParent[*vi] = *vi;
911
912 for (boost::tie(vi, vie) = boost::vertices(m_graph); vi != vie; ++vi)
913 {
914 graph_vertex_type source = *vi;
915 if (!vVisited[source])
916 {
917 biconnected_component_recursion(source, vVisited, vDisc, vLow, vParent, visit_time, vEdge, mCompVertex);
918 }
919 // if stack is not empty, pop all edges from stack
920 if (!vEdge.empty())
921 {
922 mCompVertex.push_back(std::make_pair(std::numeric_limits<graph_vertex_type>::max(), std::set<graph_vertex_type>()));
923 do
924 {
925 mCompVertex.back().second.insert(vEdge.top().first);
926 mCompVertex.back().second.insert(vEdge.top().second);
927 vEdge.pop();
928 } while (!vEdge.empty());
929 }
930 }
931 // collect articulation points
932 uint32_t comp_id = 0;
933 // reset members
934 m_mArtiPoint.clear();
935 m_mCompVertex.assign(mCompVertex.size(), std::vector<graph_vertex_type>());
936 for (typename std::list<std::pair<graph_vertex_type, std::set<graph_vertex_type> > >::const_iterator it = mCompVertex.begin(); it != mCompVertex.end(); ++it, ++comp_id)
937 {
938 graph_vertex_type vap = it->first;
939 std::set<graph_vertex_type> const& sComp = it->second;
940 if (vap < std::numeric_limits<graph_vertex_type>::max()) // valid
941 m_mArtiPoint.insert(std::make_pair(vap, std::set<uint32_t>()));
942 m_mCompVertex[comp_id].assign(sComp.begin(), sComp.end());
943 }
944 comp_id = 0;
945 for (typename std::list<std::pair<graph_vertex_type, std::set<graph_vertex_type> > >::const_iterator it = mCompVertex.begin(); it != mCompVertex.end(); ++it, ++comp_id)
946 {
947 //graph_vertex_type vap = it->first;
948 std::set<graph_vertex_type> const& sComp = it->second;
949 for (typename std::set<graph_vertex_type>::const_iterator itc = sComp.begin(); itc != sComp.end(); ++itc)
950 {
951 graph_vertex_type v = *itc;
952 if (this->articulation_point(v))
953 m_mArtiPoint[v].insert(comp_id);
954 }
955 }
956
957#ifdef DEBUG_LIWEI
958 for (typename std::map<graph_vertex_type, std::set<uint32_t> >::iterator it = m_mArtiPoint.begin(); it != m_mArtiPoint.end(); it++)
959 {
960 if (m_isVDDGND[it->first])
961 limboPrint(kNONE, "VDD__");
962 limboPrint(kNONE, "AP : %u\nwith comps : ", (uint32_t)it->first);
963 for (typename std::set<uint32_t>::iterator its = it->second.begin(); its != it->second.end(); its++)
964 limboPrint(kNONE, "%u, ", (uint32_t)*its);
965 limboPrint(kNONE, "\n");
966 }
967 comp_id = 0;
968 for (typename std::vector<std::vector<graph_vertex_type> >::iterator it = m_mCompVertex.begin(); it != m_mCompVertex.end(); it++, comp_id++)
969 {
970 limboPrint(kNONE, "comp %u\n", comp_id);
971 for (typename std::vector<graph_vertex_type>::iterator its = it->begin(); its != it->end(); its++)
972 {
973 if(m_isVDDGND[*its])
974 limboPrint(kNONE, "vdd_");
975 limboPrint(kNONE, "%u ", (uint32_t)*its);
976 }
977 limboPrint(kNONE, "\n\n");
978 }
979#endif
980
981#ifdef DEBUG_GRAPHSIMPLIFICATION
982 comp_id = 0;
983 for (typename std::list<std::pair<graph_vertex_type, std::set<graph_vertex_type> > >::const_iterator it = mCompVertex.begin(); it != mCompVertex.end(); ++it, ++comp_id)
984 {
985 graph_vertex_type vap = it->first;
986 std::set<graph_vertex_type> const& sComp = it->second;
987 std::cout << "+ articulation point " << vap << " --> comp " << comp_id << ": ";
988 for (typename std::set<graph_vertex_type>::const_iterator itc = sComp.begin(); itc != sComp.end(); ++itc)
989 std::cout << *itc << " ";
990 std::cout << std::endl;
991 }
992 for (typename std::map<graph_vertex_type, std::set<uint32_t> >::const_iterator it = m_mArtiPoint.begin(); it != m_mArtiPoint.end(); ++it)
993 {
994 graph_vertex_type vap = it->first;
995 std::set<uint32_t> const& sComp = it->second;
996 std::cout << "ap " << vap << ": ";
997 for (typename std::set<uint32_t>::const_iterator itc = sComp.begin(); itc != sComp.end(); ++itc)
998 std::cout << *itc << " ";
999 std::cout << std::endl;
1000 }
1001#endif
1002}
1003
1004template <typename GraphType>
1005void GraphSimplification<GraphType>::biconnected_component_recursion(graph_vertex_type v, std::deque<bool>& vVisited, std::vector<uint32_t>& vDisc,
1006 std::vector<uint32_t>& vLow, std::vector<graph_vertex_type>& vParent, uint32_t& visit_time,
1007 std::stack<std::pair<graph_vertex_type, graph_vertex_type> >& vEdge,
1008 std::list<std::pair<graph_vertex_type, std::set<graph_vertex_type> > >& mCompVertex) const
1009{
1010 // Count of children in DFS Tree
1011 uint32_t children = 0;
1012
1013 // Mark the current node as visited
1014 vVisited[v] = true;
1015
1016 // Initialize discovery time and low value
1017 vDisc[v] = vLow[v] = visit_time++;
1018
1019 // Go through all vertices adjacent to this
1020 // GOOD : if this node is still in graph
1021 if (!this->good(v)) return;
1022
1023 bool isolate = true;
1024 // find neighbors of all merged vertices
1025 std::vector<graph_vertex_type> const& vChildren = m_vChildren.at(v);
1026 for (typename std::vector<graph_vertex_type>::const_iterator vic = vChildren.begin(); vic != vChildren.end(); ++vic)
1027 {
1028 graph_vertex_type vc = *vic;
1029 limboAssertMsg(vc < m_vStatus.size(), "m_vStatus ERROR: %u vs %u", (uint32_t)v, (uint32_t)vc);
1030 // skip hidden vertex
1031 if (this->hidden(vc)) continue;
1032
1033 adjacency_iterator ui, uie;
1034 for (boost::tie(ui, uie) = boost::adjacent_vertices(vc, m_graph); ui != uie; ++ui)
1035 {
1036 graph_vertex_type uc = *ui;
1037 // skip hidden vertex
1038 if (this->hidden(uc)) continue;
1039
1040 isolate = false;
1041 graph_vertex_type u = this->parent(uc);
1042 limboAssert(this->good(u));
1043
1044 // If v is not visited yet, then make it a child of u
1045 // in DFS tree and recur for it
1046 if (!vVisited[u])
1047 {
1048 ++children;
1049 vParent[u] = v;
1050 vEdge.push(std::make_pair(std::min(v, u), std::max(v, u)));
1051 biconnected_component_recursion(u, vVisited, vDisc, vLow, vParent, visit_time, vEdge, mCompVertex);
1052
1053 // Check if the subtree rooted with v has a connection to
1054 // one of the ancestors of u
1055 vLow[v] = std::min(vLow[v], vLow[u]);
1056
1057 // u is an articulation point in following cases
1058
1059 // (1) u is root of DFS tree and has two or more chilren.
1060 // (2) If u is not root and low value of one of its child is more
1061 // than discovery value of u.
1062 if ((vParent[v] == v && children > 1)
1063 || (vParent[v] != v && vLow[u] >= vDisc[v]))
1064 {
1065 mCompVertex.push_back(std::make_pair(v, std::set<graph_vertex_type>()));
1066 while (vEdge.top().first != std::min(v, u) || vEdge.top().second != std::max(v, u))
1067 {
1068 mCompVertex.back().second.insert(vEdge.top().first);
1069 mCompVertex.back().second.insert(vEdge.top().second);
1070 vEdge.pop();
1071 }
1072 mCompVertex.back().second.insert(vEdge.top().first);
1073 mCompVertex.back().second.insert(vEdge.top().second);
1074 vEdge.pop();
1075 }
1076
1077 }
1078 else if (u != vParent[v] && vDisc[u] < vLow[v])
1079 {
1080 vLow[v] = std::min(vLow[v], vDisc[u]);
1081 vEdge.push(std::make_pair(std::min(v, u), std::max(v, u)));
1082 }
1083 }
1084 }
1085 // for isolated vertex, create a component
1086 if (isolate)
1087 {
1088 mCompVertex.push_back(std::make_pair(std::numeric_limits<graph_vertex_type>::max(), std::set<graph_vertex_type>()));
1089 mCompVertex.back().second.insert(v);
1090 }
1091}
1092
1093template <typename GraphType>
1095{
1096 // we only need to filter out hidden vertices and bridges
1097 // merged vertices are not a problem because they are initially connected with their parents
1098
1099 uint32_t vertex_num = boost::num_vertices(m_graph);
1100 std::stack<graph_vertex_type> vStack; // std::stack for dfs
1101 // for speed instead of memory (no bool)
1102 std::deque<bool> vVisited (vertex_num, false);
1103 uint32_t comp_id = 0;
1104 std::vector<uint32_t> vComponent (vertex_num, std::numeric_limits<uint32_t>::max());
1105
1106 // std::set initial parent of current vertex to itself
1107 vertex_iterator vi, vie;
1108 for (boost::tie(vi, vie) = boost::vertices(m_graph); vi != vie; ++vi)
1109 {
1110 graph_vertex_type source = *vi;
1111 if (this->hidden(source)) continue;
1112 if (this->articulation_point(source)) continue;
1113 // skip visited vertex
1114 if (vVisited[source]) continue;
1115 vStack.push(source);
1116 vVisited[source] = true;
1117 while (!vStack.empty())
1118 {
1119 graph_vertex_type v = vStack.top();
1120 vStack.pop();
1121#ifdef DEBUG_GRAPHSIMPLIFICATION
1122 std::cout << v << " ";
1123#endif
1124
1125 vComponent[v] = comp_id; // std::set component id
1126
1127 // for a articulation point, do not explore the neighbors
1128 if (this->articulation_point(v))
1129 {
1130 m_mArtiPoint[v].insert(comp_id);
1131 vVisited[v] = false;
1132 continue;
1133 }
1134
1135 adjacency_iterator ui, uie;
1136 for (boost::tie(ui, uie) = boost::adjacent_vertices(v, m_graph); ui != uie; ++ui)
1137 {
1138 graph_vertex_type u = *ui;
1139 if (this->hidden(u)) continue;
1140
1141#ifdef DEBUG_GRAPHSIMPLIFICATION
1142 std::pair<graph_edge_type, bool> e = boost::edge(u, v, m_graph);
1143 limboAssert(e.second);
1144#endif
1145
1146 if (!vVisited[u]) // non-visited vertex
1147 {
1148 vStack.push(u);
1149 vVisited[u] = true;
1150 }
1151 }
1152 }
1153 comp_id += 1;
1154 }
1155#ifdef DEBUG_GRAPHSIMPLIFICATION
1156 std::cout << std::endl;
1157#endif
1158 // explore the connection between articulation points
1159 // create additional components for connected articulation pairs
1160 for (typename std::map<graph_vertex_type, std::set<uint32_t> >::const_iterator vapi = m_mArtiPoint.begin(); vapi != m_mArtiPoint.end(); ++vapi)
1161 {
1162 graph_vertex_type v = vapi->first;
1163 if (!vVisited[v])
1164 {
1165 adjacency_iterator ui, uie;
1166 for (boost::tie(ui, uie) = boost::adjacent_vertices(v, m_graph); ui != uie; ++ui)
1167 {
1168 graph_vertex_type u = *ui;
1169 if (this->hidden(u)) continue;
1170 if (!vVisited[u] && this->articulation_point(u))
1171 {
1172 m_mArtiPoint[v].insert(comp_id);
1173 m_mArtiPoint[u].insert(comp_id);
1174
1175#ifdef DEBUG_GRAPHSIMPLIFICATION
1176 std::cout << "detect " << v << ", " << u << " ==> comp " << comp_id << std::endl;
1177#endif
1178
1179 comp_id += 1;
1180 }
1181 }
1182 vVisited[v] = true;
1183 }
1184 }
1185
1186 // std::set m_mCompVertex
1187 m_mCompVertex.assign(comp_id, std::vector<graph_vertex_type>());
1188 for (boost::tie(vi, vie) = boost::vertices(m_graph); vi != vie; ++vi)
1189 {
1190 graph_vertex_type v = *vi;
1191 // consider good vertices only
1192 // skip articulation_point
1193 if (this->good(v) && !this->articulation_point(v))
1194 m_mCompVertex[vComponent[v]].push_back(v);
1195 }
1196 for (typename std::map<graph_vertex_type, std::set<uint32_t> >::const_iterator vapi = m_mArtiPoint.begin(); vapi != m_mArtiPoint.end(); ++vapi)
1197 {
1198 graph_vertex_type vap = vapi->first;
1199 std::set<uint32_t> const& sComp = vapi->second;
1200 for (typename std::set<uint32_t>::const_iterator itc = sComp.begin(); itc != sComp.end(); ++itc)
1201 m_mCompVertex[*itc].push_back(vap);
1202 }
1203}
1204
1207template <typename GraphType>
1208void GraphSimplification<GraphType>::recover_merge_subK4(std::vector<int8_t>& vColor) const
1209{
1210 vertex_iterator vi, vie;
1211 for (boost::tie(vi, vie) = boost::vertices(m_graph); vi != vie; ++vi)
1212 {
1213 graph_vertex_type v = *vi;
1214 if (this->good(v))
1215 {
1216 limboAssert(vColor[v] >= 0 && vColor[v] < (int8_t)this->m_color_num);
1217 for (uint32_t j = 0; j != m_vChildren[v].size(); ++j)
1218 {
1219 graph_vertex_type u = m_vChildren[v][j];
1220 if (v != u)
1221 vColor[u] = vColor[v];
1222 }
1223 }
1224 }
1225}
1226
1228template <typename GraphType>
1229void GraphSimplification<GraphType>::recover_biconnected_component(std::vector<std::vector<int8_t> >& mColor, std::vector<std::vector<graph_vertex_type> > const& mSimpl2Orig) const
1230{
1231 // a single articulation point must correspond to two components
1232 // std::map<graph_vertex_type, std::pair<uint32_t, uint32_t> > m_mArtiPoint
1233 // std::vector<std::vector<graph_vertex_type> > m_mCompVertex
1234
1235 // only contain mapping for articulation points
1236 std::vector<std::map<graph_vertex_type, graph_vertex_type> > mApOrig2Simpl (mSimpl2Orig.size());
1237 for (uint32_t i = 0; i < mSimpl2Orig.size(); ++i)
1238 {
1239 std::vector<graph_vertex_type> const& vSimpl2Orig = mSimpl2Orig[i];
1240 std::map<graph_vertex_type, graph_vertex_type>& vApOrig2Simpl = mApOrig2Simpl[i];
1241
1242 for (uint32_t j = 0; j < vSimpl2Orig.size(); ++j)
1243 {
1244 if (m_mArtiPoint.count(vSimpl2Orig[j]))
1245 vApOrig2Simpl[vSimpl2Orig[j]] = j;
1246 }
1247 }
1248
1249 std::vector<int32_t> vRotation (m_mCompVertex.size(), 0); // rotation amount for each component
1250 std::deque<bool> vVisited (m_mCompVertex.size(), false); // visited flag
1251 std::vector<std::set<graph_vertex_type> > vCompAp (m_mCompVertex.size()); // articulation points for each component
1252
1253 for (typename std::map<graph_vertex_type, std::set<uint32_t> >::const_iterator vapi = m_mArtiPoint.begin(); vapi != m_mArtiPoint.end(); ++vapi)
1254 {
1255 graph_vertex_type vap = vapi->first;
1256 std::set<uint32_t> const& sComp = vapi->second;
1257 for (typename std::set<uint32_t>::const_iterator itc = sComp.begin(); itc != sComp.end(); ++itc)
1258 {
1259 uint32_t comp = *itc;
1260 vCompAp[comp].insert(vap);
1261 //limboAssert(vCompAp[comp].size() < 3);
1262 }
1263 }
1264
1265 // dfs based approach to propagate rotation
1266 for (uint32_t comp_id = 0; comp_id < vCompAp.size(); ++comp_id)
1267 {
1268 if (!vVisited[comp_id])
1269 {
1270 std::stack<uint32_t> vStack;
1271 vStack.push(comp_id);
1272 vVisited[comp_id] = true;
1273 while (!vStack.empty())
1274 {
1275 uint32_t c = vStack.top(); // current component
1276 vStack.pop();
1277
1278 for (typename std::set<graph_vertex_type>::const_iterator vapi = vCompAp[c].begin(); vapi != vCompAp[c].end(); ++vapi)
1279 {
1280 graph_vertex_type vap = *vapi;
1281 std::set<uint32_t> const& sComp = m_mArtiPoint.at(vap);
1282
1283 for (typename std::set<uint32_t>::const_iterator itcc = sComp.begin(); itcc != sComp.end(); ++itcc)
1284 {
1285 uint32_t cc = *itcc; // child component
1286 if (!vVisited[cc])
1287 {
1288 vStack.push(cc);
1289 vVisited[cc] = true;
1290 int8_t color_c = mColor[c][mApOrig2Simpl[c][vap]];
1291 int8_t color_cc = mColor[cc][mApOrig2Simpl[cc][vap]];
1292 vRotation[cc] += vRotation[c] + color_c - color_cc;
1293 }
1294 }
1295 }
1296 }
1297 }
1298 }
1299
1300 // apply color rotation
1301 for (uint32_t comp_id = 0; comp_id < mColor.size(); ++comp_id)
1302 {
1303 int32_t Non_color_count = 0;
1304 std::vector<int8_t>& vColor = mColor[comp_id];
1305 int32_t rotation = vRotation[comp_id];
1306 if (rotation < 0) // add a large enough K*m to achieve positive value
1307 rotation += (limbo::abs(rotation)/m_color_num+1)*m_color_num;
1308 limboAssert(rotation >= 0);
1309 rotation %= (int32_t)m_color_num;
1310 for (uint32_t v = 0; v < vColor.size(); ++v)
1311 {
1312 #ifdef DEBUG_LIWEI
1313 if(vColor[v] >= 0)
1314 vColor[v] = (vColor[v] + rotation) % (int32_t)m_color_num;
1315 else
1316 Non_color_count++;
1317 #else
1318 limboAssert(vColor[v] >= 0);
1319 vColor[v] = (vColor[v] + rotation) % (int32_t)m_color_num;
1320 #endif
1321
1322 }
1323 }
1324
1325#ifdef DEBUG_GRAPHSIMPLIFICATION
1326 for (typename std::map<graph_vertex_type, std::set<uint32_t> >::const_iterator vapi = m_mArtiPoint.begin(); vapi != m_mArtiPoint.end(); ++vapi)
1327 {
1328 graph_vertex_type vap = vapi->first;
1329 std::set<uint32_t> const& sComp = vapi->second;
1330
1331 int8_t prev_color = -1;
1332 for (typename std::set<uint32_t>::const_iterator itc = sComp.begin(); itc != sComp.end(); ++itc)
1333 {
1334 uint32_t comp = *itc;
1335 int8_t color = mColor[comp][mApOrig2Simpl[comp][vap]];
1336 if (itc == sComp.begin())
1337 prev_color = color;
1338 else limboAssertMsg(prev_color == color,
1339 "%u: comp %u, c[%u] = %u; prev_color = %u", vap, comp, mApOrig2Simpl[comp][vap], color, prev_color);
1340 }
1341 }
1342#endif
1343}
1344
1345template <typename GraphType>
1347{
1348 while (!m_vHiddenVertex.empty())
1349 {
1350 graph_vertex_type v = m_vHiddenVertex.top();
1351 m_vHiddenVertex.pop();
1352
1353 // find available colors
1354 std::vector<char> vUnusedColor (m_color_num, true);
1355 std::vector<char> vStitchColor (m_color_num, false);
1356 typename boost::graph_traits<graph_type>::adjacency_iterator vi, vie;
1357 for (boost::tie(vi, vie) = boost::adjacent_vertices(v, this->m_graph); vi != vie; ++vi)
1358 {
1359 graph_vertex_type u = *vi;
1360 if (vColor[u] >= 0)
1361 {
1362 limboAssert(vColor[u] < (int32_t)m_color_num);
1363 std::pair<graph_edge_type, bool> e12 = boost::edge(v, u, this->m_graph);
1364 limboAssert(e12.second);
1365 if (boost::get(boost::edge_weight, this->m_graph, e12.first) < 0)
1366 {
1367 vStitchColor[vColor[u]] = true;
1368 }
1369 else
1370 {
1371 vUnusedColor[vColor[u]] = false;
1372 }
1373 }
1374 }
1375 bool find_flag = false;
1376 // choose the first available color
1377 for (int8_t i = 0; i != (int8_t)m_color_num; ++i)
1378 {
1379 if (vUnusedColor[i] && vStitchColor[i])
1380 {
1381 vColor[v] = i;
1382 find_flag = true;
1383 break;
1384 }
1385 }
1386 if(!find_flag)
1387 {
1388 // choose the first available color
1389 for (int8_t i = 0; i != (int8_t)m_color_num; ++i)
1390 {
1391 if (vUnusedColor[i])
1392 {
1393 vColor[v] = i;
1394 break;
1395 }
1396 }
1397 }
1398 limboAssert(vColor[v] >= 0 && vColor[v] < (int8_t)m_color_num);
1399 }
1400}
1401
1402template <typename GraphType>
1403void GraphSimplification<GraphType>::write_graph_dot(std::string const& filename) const
1404{
1405 std::ofstream out((filename+".gv").c_str());
1406 out << "graph D { \n"
1407 << " randir = LR\n"
1408 << " size=\"4, 3\"\n"
1409 << " ratio=\"fill\"\n"
1410 << " edge[style=\"bold\",fontsize=200]\n"
1411 << " node[shape=\"circle\",fontsize=200]\n";
1412
1413 //output nodes
1414 vertex_iterator vi1, vie1;
1415 for (boost::tie(vi1, vie1) = boost::vertices(m_graph); vi1 != vie1; ++vi1)
1416 {
1417 graph_vertex_type v1 = *vi1;
1418 if (!this->good(v1)) continue;
1419
1420 out << " " << v1 << "[shape=\"circle\"";
1421 //output coloring label
1422 out << ",label=\"" << v1 << ":(";
1423 for (typename std::vector<graph_vertex_type>::const_iterator it1 = m_vChildren[v1].begin(); it1 != m_vChildren[v1].end(); ++it1)
1424 {
1425 if (it1 != m_vChildren[v1].begin())
1426 out << ",";
1427 out << *it1;
1428 }
1429 out << ")\"]\n";
1430 }
1431
1432 //output edges
1433 for (boost::tie(vi1, vie1) = boost::vertices(m_graph); vi1 != vie1; ++vi1)
1434 {
1435 graph_vertex_type v1 = *vi1;
1436 if (!this->good(v1)) continue;
1437
1438 vertex_iterator vi2, vie2;
1439 for (boost::tie(vi2, vie2) = boost::vertices(m_graph); vi2 != vie2; ++vi2)
1440 {
1441 graph_vertex_type v2 = *vi2;
1442 if (!this->good(v2)) continue;
1443 if (v1 >= v2) continue;
1444
1445 std::pair<graph_edge_type, bool> e = this->connected_edge(v1, v2);
1446 if (e.second)
1447 {
1448 // if two hyper vertices are connected by conflict edges,
1449 // there is no need to consider stitch edges
1450 if (this->connected_conflict(v1, v2))
1451 out << " " << v1 << "--" << v2 << "[color=\"black\",style=\"solid\",penwidth=3]\n";
1452 else if (this->connected_stitch(v1, v2))
1453 out << " " << v1 << "--" << v2 << "[color=\"black\",style=\"dashed\",penwidth=3]\n";
1454 // virtual connection showing that a bridge exists
1455 out << " " << v1 << "--" << v2 << "[color=\"black\",style=\"dotted\",penwidth=1]\n";
1456 }
1457 }
1458 }
1459 out << "}";
1460 out.close();
1461
1462 la::graphviz2pdf(filename);
1463}
1464template <typename GraphType>
1466{
1467 std::ofstream out((filename+".gv").c_str());
1468 out << "graph D { \n"
1469 << " randir = LR\n"
1470 << " size=\"4, 3\"\n"
1471 << " ratio=\"fill\"\n"
1472 << " edge[style=\"bold\",fontsize=200]\n"
1473 << " node[shape=\"circle\",fontsize=200]\n";
1474
1475 uint32_t offset = 0;
1476 // component by component
1477 for (uint32_t comp_id = 0; comp_id != m_mCompVertex.size(); ++comp_id)
1478 {
1479 graph_type sg;
1480 std::vector<graph_vertex_type> vSimpl2Orig;
1481 bool flag = this->simplified_graph_component(comp_id, sg, vSimpl2Orig);
1482 if (flag)
1483 {
1484 //output nodes
1485 vertex_iterator vi1, vie1;
1486 for (boost::tie(vi1, vie1) = boost::vertices(sg); vi1 != vie1; ++vi1)
1487 {
1488 graph_vertex_type mv1 = *vi1;
1489 graph_vertex_type v1 = vSimpl2Orig[mv1];
1490 if (m_vChildren[v1].empty()) continue;
1491
1492 out << " " << offset+mv1 << "[shape=\"circle\"";
1493 //output coloring label
1494 out << ",label=\"" << mv1 << ":(";
1495 for (typename std::vector<graph_vertex_type>::const_iterator it1 = m_vChildren[v1].begin(); it1 != m_vChildren[v1].end(); ++it1)
1496 {
1497 if (it1 != m_vChildren[v1].begin())
1498 out << ",";
1499 out << *it1;
1500 }
1501 out << "):" << comp_id << "\"]\n";
1502 }
1503 //output edges
1504 edge_iterator ei, eie;
1505 for (boost::tie(ei, eie) = boost::edges(sg); ei != eie; ++ei)
1506 {
1507 graph_edge_type e = *ei;
1508 graph_vertex_type mv1 = boost::source(e, sg);
1509 graph_vertex_type mv2 = boost::target(e, sg);
1510 int32_t w = boost::get(boost::edge_weight, sg, e);
1511 limboAssertMsg(mv1 != mv2, "%u == %u", mv1, mv2);
1512
1513 char buf[256];
1514 if (w >= 0)
1515 sprintf(buf, " %lu--%lu[label=%d,color=\"black\",style=\"solid\",penwidth=3]", offset+mv1, offset+mv2, w);
1516 else
1517 sprintf(buf, " %lu--%lu[label=%d,color=\"black\",style=\"dashed\",penwidth=3]", offset+mv1, offset+mv2, w);
1518 out << buf << std::endl;
1519 }
1520 offset += boost::num_vertices(sg);
1521 }
1522 }
1523
1524 out << "}";
1525 out.close();
1526
1527 la::graphviz2pdf(filename);
1528}
1529
1530} // namespace coloring
1531} // namespace algorithms
1532} // namespace limbo
1533
1534#endif
1535
assertion with message
#define limboAssertMsg(condition, args...)
custom assertion with message
Definition AssertMsg.h:24
#define limboAssert(condition)
custom assertion without message
Definition AssertMsg.h:36
some graph utilities such as compute complement graph and graphviz writer.
mathematical utilities such as abs
void mergeVDD(std::set< graph_vertex_type > vdd_set)
added by Qi Sun, used to merge VDD nodes
void recover_biconnected_component(std::vector< std::vector< int8_t > > &mColor, std::vector< std::vector< graph_vertex_type > > const &mSimpl2Orig) const
recover color for biconnected components
void recover_hide_small_degree(std::vector< int8_t > &vColor)
bool whether_VDDGND(graph_vertex_type id)
return whether vertex with 'id' is VDDGND
graph_vertex_type parent(graph_vertex_type v) const
void get_CompVertex(std::vector< std::vector< graph_vertex_type > > &CompVertex)
added by Qi Sun, to get m_mCompVertex
uint32_t num_component() const
added by Qi Sun, also get the original edge relationships
std::vector< vertex_status_type > m_vStatus
status of each vertex
void write_graph_dot(std::string const &filename) const
strategy_type
simplification strategies available. These strategies are order-sensitive. It is recommended to cal...
@ MERGE_SUBK4
merge 4-clique structures, no longer optimal
@ BICONNECTED_COMPONENT
divide graph by biconnected components
@ HIDE_SMALL_DEGREE
hide vertices whose degree is smaller than number of colors available
std::map< graph_vertex_type, std::set< uint32_t > > m_mArtiPoint
map of (vertex of articulation point, set of components split by the vertex)
std::stack< graph_vertex_type > const & hidden_vertices() const
GraphSimplification(graph_type const &g, uint32_t color_num)
std::vector< vertex_status_type > const & status() const
void connected_component()
compute connected components
void recover(std::vector< int8_t > &vColorFlat, std::vector< std::vector< int8_t > > &mColor, std::vector< std::vector< graph_vertex_type > > const &mSimpl2Orig) const
void biconnected_component_recursion(graph_vertex_type v, std::deque< bool > &vVisited, std::vector< uint32_t > &vDisc, std::vector< uint32_t > &vLow, std::vector< graph_vertex_type > &vParent, uint32_t &visit_time, std::stack< std::pair< graph_vertex_type, graph_vertex_type > > &vEdge, std::list< std::pair< graph_vertex_type, std::set< graph_vertex_type > > > &mCompVertex) const
std::vector< std::vector< graph_vertex_type > > m_vChildren
children verices of current vertex, a vertex is the child of itself if it is not merged
void write_simplified_graph_dot(std::string const &filename) const
bool connected_conflict(graph_vertex_type v1, graph_vertex_type v2) const
std::vector< std::vector< graph_vertex_type > > const & children() const
graph_vertex_type parent(uint32_t v, std::vector< uint32_t > const &vParent) const
bool connected_stitch(graph_vertex_type v1, graph_vertex_type v2) const
std::pair< graph_edge_type, bool > connected_edge(graph_vertex_type v1, graph_vertex_type v2) const
void hide_small_degree()
hide vertices whose degree is no larger than number of colors - 1
std::vector< graph_vertex_type > const & parents() const
bool simplified_graph_component(uint32_t comp_id, graph_type &sg, std::vector< graph_vertex_type > &vSimpl2Orig) const
std::vector< int8_t > m_vPrecolor
precolor information, if uncolored, std::set to -1
void biconnected_component()
find all articulation points and biconnected components
std::vector< bool > m_isVDDGND
used in graph simplification, whether it's VDDGND, added by Qi Sun
void set_isVDDGND(std::set< graph_vertex_type > vdd_set)
construct m_isVDDGND
std::vector< graph_vertex_type > m_vParent
parent vertex of current vertex
void recover_merge_subK4(std::vector< int8_t > &vColor) const
GraphSimplification(GraphSimplification const &rhs)
uint32_t m_max_merge_level
in MERGE_SUBK4, any merge that results in the children number of a vertex larger than m_max_merge_lev...
std::pair< graph_type, std::map< graph_vertex_type, graph_vertex_type > > simplified_graph() const
std::vector< std::vector< graph_vertex_type > > m_mCompVertex
group vertices by components
std::stack< graph_vertex_type > m_vHiddenVertex
a std::stack that keeps a reverse order of vertices hidden, useful for color recovery
Boost.Geometry.
Definition GdsObjects.h:740
namespace for Limbo.Algorithms.Coloring
namespace for Limbo.algorithms
namespace for Limbo
std::iterator_traits< Iterator >::value_type max(Iterator first, Iterator last)
get max of an array
Definition Math.h:61
int limboPrint(MessageType m, const char *format,...)
formatted print with prefix
Definition PrintMsg.h:49
T abs(T const &t)
generalized api can handle both integer and floating points
Definition Math.h:21