3 #ifndef GRAPH_UTILS_HPP
4 #define GRAPH_UTILS_HPP
8 #include <boost/unordered_set.hpp>
9 #include <boost/graph/max_cardinality_matching.hpp>
11 #include "utils/copy.hpp"
14 #include "graph_typedefs.hpp"
16 using namespace boost;
20 template<
class Graph,
typename EPred,
typename VPred>
21 size_t degree(
const Vertex<filtered_graph<Graph,EPred,VPred> >& v,
const filtered_graph<Graph,EPred,VPred>& g){
22 return out_degree(v, g);
31 bool remove_matching_pair(
const Vertex<Graph>& u, Matching<Graph>& match){
32 const typename Matching<Graph>::iterator uv = match.find(u);
33 if(uv != match.end()){
34 const typename Matching<Graph>::iterator vu = match.find(uv->second);
44 void setup_vertex_indices(Graph& g,
unsigned first_index = 0){
45 for(VertexIterRange<Graph> r = boost::vertices(g); r.first != r.second;++r.first)
46 g[*r.first].index = first_index++;
50 size_t compute_FES(
const size_t v,
const size_t e,
const size_t cc){
58 Graph* split_off_component(Graph& g, Matching<Graph>* _translate = NULL, Matching<Graph>* _translate_back = NULL){
59 typedef typename Graph::vertex_bundled VertexInfo;
60 Matching<Graph>* translate = _translate ? _translate :
new Matching<Graph>();
61 Matching<Graph>* translate_back = _translate_back ? _translate_back :
new Matching<Graph>();
63 assert(boost::num_vertices(g));
64 const Vertex<Graph> source = *boost::vertices(g).first;
68 DEBUG4(std::cout <<
"copying component of "<< VertexAndGraph<Graph>(source, g)<<std::endl);
69 boost::copy_component(g, source, *h, orig_to_copy(boost::associative_property_map<Matching<Graph> >(*translate)).vertex_index_map(boost::get(&VertexInfo::index, g)));
71 if(boost::num_vertices(g) == boost::num_vertices(*h)){
delete h;
return NULL;}
73 for(
auto& i : *translate) translate_back->emplace(i.second, i.first);
75 for(VertexIterRange<Graph> r = vertices(*h); r.first != r.second; ++r.first){
76 const Vertex<Graph> u = translate_back->at(*r.first);
77 boost::clear_vertex(u, g);
78 boost::remove_vertex(u, g);
80 if(!_translate)
delete translate;
81 if(!_translate_back)
delete translate_back;
83 setup_vertex_indices(g);
84 setup_vertex_indices(*h);
93 void mark_bridges(
const Graph& g, BridgeMap<Graph>& bridge_map){
100 const Vertex<Graph> parent;
102 TarjanInfos(
const size_t _index,
const Vertex<Graph>& _parent):
103 index(_index), lowest_seen_index(_index), subtree_size(1), subtree_edges(0), parent(_parent) {}
106 struct StackElement {
108 AdjIterRange<Graph> adj;
110 StackElement(
const Vertex<Graph>& _v,
const AdjIterRange<Graph>& _adj):
116 unordered_map<Vertex<Graph>, TarjanInfos> tarjan_infos;
118 if(!num_edges(g))
return;
120 VertexIter<Graph> root = vertices(g).first;
121 std::stack<StackElement > adj_stack;
123 tarjan_infos.emplace(std::piecewise_construct, std::make_tuple(*root), std::make_tuple(0, *root));
126 adj_stack.emplace(*root, adjacent_vertices(*root, g));
128 assert(adj_stack.top().adj.first != adj_stack.top().adj.second);
131 size_t current_index = 0;
132 while(!adj_stack.empty()){
134 StackElement& e = adj_stack.top();
135 const Vertex<Graph>& v = e.v;
136 AdjIterRange<Graph>& r = e.adj;
137 TarjanInfos& v_infos(tarjan_infos.at(v));
140 if(
contains(tarjan_infos, *r.first)){
141 const TarjanInfos& u_infos(tarjan_infos.at(*r.first));
143 DEBUG5(std::cout <<
"coming up from "<<VertexAndGraph<Graph>(*r.first,g)<<
" who has seen "<<u_infos.lowest_seen_index<<
" and his subtree has "<<u_infos.subtree_size<<
" verts and "<<u_infos.subtree_edges<<
" edges (we are at "<<VertexAndGraph<Graph>(v,g)<<
" with index "<<v_infos.index<<
")"<<std::endl);
145 if(u_infos.lowest_seen_index > v_infos.index){
147 const size_t FES = compute_FES(u_infos.subtree_size, u_infos.subtree_edges, 1);
149 bridge_map.emplace(std::piecewise_construct, std::make_tuple(v, *r.first), std::make_tuple(FES));
150 DEBUG5(std::cout<<
"found bridge ("<<VertexAndGraph<Graph>(v,g)<<
","<<VertexAndGraph<Graph>(*r.first,g)<<
") splitting away "<<u_infos.subtree_size<<
" vertices and "<<u_infos.subtree_edges<<
" edges (FES "<<FES<<
")"<<std::endl);
152 v_infos.lowest_seen_index = std::min(v_infos.lowest_seen_index, u_infos.lowest_seen_index);
154 v_infos.subtree_size += u_infos.subtree_size;
155 v_infos.subtree_edges += u_infos.subtree_edges + 1;
158 for( ; (r.first != r.second) &&
contains(tarjan_infos, *r.first); ++r.first){
159 const TarjanInfos& w_infos(tarjan_infos.at(*r.first));
161 if((*r.first != v_infos.parent) && (w_infos.index < v_infos.index))
162 v_infos.lowest_seen_index = std::min(v_infos.lowest_seen_index, w_infos.index);
164 if(w_infos.index > v_infos.index) ++v_infos.subtree_edges;
167 if(r.first != r.second){
169 const Vertex<Graph>& u = *r.first;
170 DEBUG5(std::cout <<
"going down to unvisited "<<VertexAndGraph<Graph>(u,g)<<
" from "<<VertexAndGraph<Graph>(v,g)<<std::endl);
172 TarjanInfos& u_infos = tarjan_infos.emplace(std::piecewise_construct, std::make_tuple(u), std::make_tuple(++current_index, v)).first->second;
174 AdjIterRange<Graph> u_adj = adjacent_vertices(u, g);
175 for( ; (u_adj.first != u_adj.second) ?
contains(tarjan_infos, *u_adj.first) :
false; ++u_adj.first)
176 if(*u_adj.first != v)
177 u_infos.lowest_seen_index = std::min(u_infos.lowest_seen_index, tarjan_infos.at(*u_adj.first).index);
179 if(u_adj.first != u_adj.second) adj_stack.push(StackElement(u, u_adj));
180 }
else adj_stack.pop();
182 DEBUG4(std::cout <<
"done finding "<<bridge_map.size()<<
" bridges"<<std::endl);
187 template<
class Graph>
191 VertexSet<Graph> marked;
194 for(VertexIterRange<Graph> i = vertices(g); i.first != i.second; ++i.first){
195 const Vertex<Graph>& v = *(i.first);
196 if(degree(v, g) <= 1 && !
contains(marked, v)){
201 if(degree(v, g) == 1) {
204 Vertex<Graph> last = u;
206 AdjIter<Graph> nxt = adjacent_vertices(u, g).first;
207 if(*nxt == last) ++nxt;
211 }
while(degree(u, g) == 2);
212 DEBUG5(std::cout <<
"finished path at "<<VertexAndGraph<Graph>(u,g)<<
" with degree "<<degree(u, g)<<std::endl);
213 assert(degree(u, g) == 1);
219 for(VertexIterRange<Graph> i = vertices(g); i.first != i.second; ++i.first)
if(!
contains(marked, *(i.first))){
221 Vertex<Graph> u = *(i.first);
222 Vertex<Graph> last = u;
223 DEBUG3(std::cout <<
"found cycle starting at "<<VertexAndGraph<Graph>(u, g)<<
":");
225 assert(degree(u, g) == 2);
228 AdjIter<Graph> nxt = adjacent_vertices(u, g).first;
229 if(*nxt == last) ++nxt;
232 DEBUG3(std::cout << VertexAndGraph<Graph>(u, g)<<
" ");
234 DEBUG3(std::cout << std::endl);
241 template<
class Graph>
242 void remove_treelike(Graph& g, unordered_set<Vertex<Graph> >*
const pending){
244 unordered_set<Vertex<Graph> > *old_batch = pending;
245 unordered_set<Vertex<Graph> > *new_batch =
new unordered_set<Vertex<Graph> >;
246 unordered_set<Vertex<Graph> >*
const delete_me = new_batch;
248 while(!new_batch->empty() && !old_batch->empty()){
250 if(old_batch->empty()) swap(new_batch, old_batch);
252 const Vertex<Graph> v = *(old_batch->begin());
253 old_batch->erase(old_batch->begin());
255 if(degree(v, g) == 1){
256 const Vertex<Graph> u = *(adjacent_vertices(v, g).first);
257 if(!
contains(*old_batch, u)) new_batch->insert(u);
267 template<
class Graph>
268 void remove_treelike(Graph& g){
270 unordered_set<Vertex<Graph> > leaves;
271 for(VertexIterRange<Graph> r = vertices(g); r.first != r.second; ++r.first)
272 if(degree(*r.first) == 1)
273 leaves.insert(*r.first);
274 remove_treelike(g, &leaves);
279 template<
class Graph>
280 void copy_matching(
const Matching<Graph>& from, Matching<Graph>& to,
const VTranslateMap<Graph,Graph>& translate)
282 for(
auto i : from) to[translate.at(i.first)] = translate.at(i.second);
287 template<
class Graph>
288 bool is_equal(
const VertexPair<Graph>& p,
const Edge<Graph>& e,
const Graph& g)
290 const Vertex<Graph>& u = source(e, g);
291 const Vertex<Graph>& v = target(e, g);
292 return ((u == p.first) && (v == p.second)) || ((u == p.second) && (v == p.first));
296 template<
class Graph,
class Container>
297 void remove_reachable(Graph& g,
const Container& U,
const Direction d)
299 VertexSet<Graph> pending(U.begin(), U.end());
300 while(!pending.empty()){
301 const Vertex<Graph> u = *(pending.begin());
302 pending.erase(pending.begin());
304 if((d == dir_fwd) || (d == dir_fwdrev))
305 for(OEdgeIterRange<Graph> r = boost::out_edges(u, g); r.first != r.second; ++r.first)
306 pending.insert(boost::target(*r.first, g));
307 if((d == dir_rev) || (d == dir_fwdrev))
308 for(IEdgeIterRange<Graph> r = boost::in_edges(u, g); r.first != r.second; ++r.first)
309 pending.insert(boost::source(*r.first, g));
311 boost::clear_vertex(u, g);
312 boost::remove_vertex(u, g);
Definition: graph_utils.hpp:18
Definition: read_adj_list.hpp:22
bool contains(const Set &s, const Element &el)
a more readable containment check
Definition: utils.hpp:171
Definition: graph_typedefs.hpp:26