1 //=======================================================================
2 // Copyright 2001 University of Notre Dame.
3 // Authors: Jeremy G. Siek and Lie-Quan Lee
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //=======================================================================
9 
10 #ifndef BOOST_SUBGRAPH_HPP
11 #define BOOST_SUBGRAPH_HPP
12 
13 // UNDER CONSTRUCTION
14 
15 #include <boost/config.hpp>
16 #include <list>
17 #include <vector>
18 #include <map>
19 #include <boost/assert.hpp>
20 #include <boost/graph/graph_traits.hpp>
21 #include <boost/graph/graph_mutability_traits.hpp>
22 #include <boost/graph/properties.hpp>
23 #include <boost/iterator/indirect_iterator.hpp>
24 
25 #include <boost/static_assert.hpp>
26 #include <boost/assert.hpp>
27 #include <boost/type_traits.hpp>
28 #include <boost/mpl/if.hpp>
29 #include <boost/mpl/or.hpp>
30 
31 namespace boost
32 {
33 
34 struct subgraph_tag
35 {
36 };
37 
38 /** @name Property Lookup
39  * The local_property and global_property functions are used to create
40  * structures that determine the lookup strategy for properties in subgraphs.
41  * Note that the nested kind member is used to help interoperate with actual
42  * Property types.
43  */
44 //@{
45 template < typename T > struct local_property
46 {
47     typedef T kind;
local_propertyboost::local_property48     local_property(T x) : value(x) {}
49     T value;
50 };
51 
local(T x)52 template < typename T > inline local_property< T > local(T x)
53 {
54     return local_property< T >(x);
55 }
56 
57 template < typename T > struct global_property
58 {
59     typedef T kind;
global_propertyboost::global_property60     global_property(T x) : value(x) {}
61     T value;
62 };
63 
global(T x)64 template < typename T > inline global_property< T > global(T x)
65 {
66     return global_property< T >(x);
67 }
68 //@}
69 
70 // Invariants of an induced subgraph:
71 //   - If vertex u is in subgraph g, then u must be in g.parent().
72 //   - If edge e is in subgraph g, then e must be in g.parent().
73 //   - If edge e=(u,v) is in the root graph, then edge e
74 //     is also in any subgraph that contains both vertex u and v.
75 
76 // The Graph template parameter must have a vertex_index and edge_index
77 // internal property. It is assumed that the vertex indices are assigned
78 // automatically by the graph during a call to add_vertex(). It is not
79 // assumed that the edge vertices are assigned automatically, they are
80 // explicitly assigned here.
81 
82 template < typename Graph > class subgraph
83 {
84     typedef graph_traits< Graph > Traits;
85     typedef std::list< subgraph< Graph >* > ChildrenList;
86 
87 public:
88     // Graph requirements
89     typedef typename Traits::vertex_descriptor vertex_descriptor;
90     typedef typename Traits::edge_descriptor edge_descriptor;
91     typedef typename Traits::directed_category directed_category;
92     typedef typename Traits::edge_parallel_category edge_parallel_category;
93     typedef typename Traits::traversal_category traversal_category;
94 
95     // IncidenceGraph requirements
96     typedef typename Traits::out_edge_iterator out_edge_iterator;
97     typedef typename Traits::degree_size_type degree_size_type;
98 
99     // AdjacencyGraph requirements
100     typedef typename Traits::adjacency_iterator adjacency_iterator;
101 
102     // VertexListGraph requirements
103     typedef typename Traits::vertex_iterator vertex_iterator;
104     typedef typename Traits::vertices_size_type vertices_size_type;
105 
106     // EdgeListGraph requirements
107     typedef typename Traits::edge_iterator edge_iterator;
108     typedef typename Traits::edges_size_type edges_size_type;
109 
110     typedef typename Traits::in_edge_iterator in_edge_iterator;
111 
112     typedef typename edge_property_type< Graph >::type edge_property_type;
113     typedef typename vertex_property_type< Graph >::type vertex_property_type;
114     typedef subgraph_tag graph_tag;
115     typedef Graph graph_type;
116     typedef typename graph_property_type< Graph >::type graph_property_type;
117 
118     // Create the main graph, the root of the subgraph tree
subgraph()119     subgraph() : m_parent(0), m_edge_counter(0) {}
120 
subgraph(const graph_property_type & p)121     subgraph(const graph_property_type& p)
122     : m_graph(p), m_parent(0), m_edge_counter(0)
123     {
124     }
125 
subgraph(vertices_size_type n,const graph_property_type & p=graph_property_type ())126     subgraph(vertices_size_type n,
127         const graph_property_type& p = graph_property_type())
128     : m_graph(n, p), m_parent(0), m_edge_counter(0), m_global_vertex(n)
129     {
130         typename Graph::vertex_iterator v, v_end;
131         vertices_size_type i = 0;
132         for (boost::tie(v, v_end) = vertices(m_graph); v != v_end; ++v)
133             m_global_vertex[i++] = *v;
134     }
135 
136     // copy constructor
subgraph(const subgraph & x)137     subgraph(const subgraph& x) : m_parent(x.m_parent), m_edge_counter(0)
138     {
139         if (x.is_root())
140         {
141             m_graph = x.m_graph;
142             m_edge_counter = x.m_edge_counter;
143             m_global_vertex = x.m_global_vertex;
144             m_global_edge = x.m_global_edge;
145         }
146         else
147         {
148             get_property(*this) = get_property(x);
149             typename subgraph< Graph >::vertex_iterator vi, vi_end;
150             boost::tie(vi, vi_end) = vertices(x);
151             for (; vi != vi_end; ++vi)
152             {
153                 add_vertex(x.local_to_global(*vi), *this);
154             }
155         }
156         // Do a deep copy (recursive).
157         // Only the root graph is copied, the subgraphs contain
158         // only references to the global vertices they own.
159         typename subgraph< Graph >::children_iterator i, i_end;
160         boost::tie(i, i_end) = x.children();
161         for (; i != i_end; ++i)
162         {
163             m_children.push_back(new subgraph< Graph >(*i));
164             m_children.back()->m_parent = this;
165         }
166     }
167 
~subgraph()168     ~subgraph()
169     {
170         for (typename ChildrenList::iterator i = m_children.begin();
171              i != m_children.end(); ++i)
172         {
173             delete *i;
174         }
175     }
176 
177     // Return a null vertex descriptor for the graph.
null_vertex()178     static vertex_descriptor null_vertex() { return Traits::null_vertex(); }
179 
180     // Create a subgraph
create_subgraph()181     subgraph< Graph >& create_subgraph()
182     {
183         m_children.push_back(new subgraph< Graph >());
184         m_children.back()->m_parent = this;
185         return *m_children.back();
186     }
187 
188     // Create a subgraph with the specified vertex set.
189     template < typename VertexIterator >
create_subgraph(VertexIterator first,VertexIterator last)190     subgraph< Graph >& create_subgraph(
191         VertexIterator first, VertexIterator last)
192     {
193         m_children.push_back(new subgraph< Graph >());
194         m_children.back()->m_parent = this;
195         for (; first != last; ++first)
196         {
197             add_vertex(*first, *m_children.back());
198         }
199         return *m_children.back();
200     }
201 
202     // local <-> global descriptor conversion functions
local_to_global(vertex_descriptor u_local) const203     vertex_descriptor local_to_global(vertex_descriptor u_local) const
204     {
205         return is_root() ? u_local : m_global_vertex[u_local];
206     }
207 
global_to_local(vertex_descriptor u_global) const208     vertex_descriptor global_to_local(vertex_descriptor u_global) const
209     {
210         vertex_descriptor u_local;
211         bool in_subgraph;
212         if (is_root())
213             return u_global;
214         boost::tie(u_local, in_subgraph) = this->find_vertex(u_global);
215         BOOST_ASSERT(in_subgraph == true);
216         return u_local;
217     }
218 
local_to_global(edge_descriptor e_local) const219     edge_descriptor local_to_global(edge_descriptor e_local) const
220     {
221         return is_root()
222             ? e_local
223             : m_global_edge[get(get(edge_index, m_graph), e_local)];
224     }
225 
global_to_local(edge_descriptor e_global) const226     edge_descriptor global_to_local(edge_descriptor e_global) const
227     {
228         return is_root() ? e_global
229                          : (*m_local_edge.find(
230                                 get(get(edge_index, root().m_graph), e_global)))
231                                .second;
232     }
233 
234     // Is vertex u (of the root graph) contained in this subgraph?
235     // If so, return the matching local vertex.
find_vertex(vertex_descriptor u_global) const236     std::pair< vertex_descriptor, bool > find_vertex(
237         vertex_descriptor u_global) const
238     {
239         if (is_root())
240             return std::make_pair(u_global, true);
241         typename LocalVertexMap::const_iterator i
242             = m_local_vertex.find(u_global);
243         bool valid = i != m_local_vertex.end();
244         return std::make_pair((valid ? (*i).second : null_vertex()), valid);
245     }
246 
247     // Is edge e (of the root graph) contained in this subgraph?
248     // If so, return the matching local edge.
find_edge(edge_descriptor e_global) const249     std::pair< edge_descriptor, bool > find_edge(edge_descriptor e_global) const
250     {
251         if (is_root())
252             return std::make_pair(e_global, true);
253         typename LocalEdgeMap::const_iterator i
254             = m_local_edge.find(get(get(edge_index, root().m_graph), e_global));
255         bool valid = i != m_local_edge.end();
256         return std::make_pair((valid ? (*i).second : edge_descriptor()), valid);
257     }
258 
259     // Return the parent graph.
parent()260     subgraph& parent() { return *m_parent; }
parent() const261     const subgraph& parent() const { return *m_parent; }
262 
263     // Return true if this is the root subgraph
is_root() const264     bool is_root() const { return m_parent == 0; }
265 
266     // Return the root graph of the subgraph tree.
root()267     subgraph& root() { return is_root() ? *this : m_parent->root(); }
268 
root() const269     const subgraph& root() const
270     {
271         return is_root() ? *this : m_parent->root();
272     }
273 
274     // Return the children subgraphs of this graph/subgraph.
275     // Use a list of pointers because the VC++ std::list doesn't like
276     // storing incomplete type.
277     typedef indirect_iterator< typename ChildrenList::const_iterator,
278         subgraph< Graph >, std::bidirectional_iterator_tag >
279         children_iterator;
280 
281     typedef indirect_iterator< typename ChildrenList::const_iterator,
282         subgraph< Graph > const, std::bidirectional_iterator_tag >
283         const_children_iterator;
284 
285     std::pair< const_children_iterator, const_children_iterator >
children() const286     children() const
287     {
288         return std::make_pair(const_children_iterator(m_children.begin()),
289             const_children_iterator(m_children.end()));
290     }
291 
children()292     std::pair< children_iterator, children_iterator > children()
293     {
294         return std::make_pair(children_iterator(m_children.begin()),
295             children_iterator(m_children.end()));
296     }
297 
num_children() const298     std::size_t num_children() const { return m_children.size(); }
299 
300 #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
301     // Defualt property access delegates the lookup to global properties.
302     template < typename Descriptor >
303     typename graph::detail::bundled_result< Graph, Descriptor >::type&
operator [](Descriptor x)304     operator[](Descriptor x)
305     {
306         return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)];
307     }
308 
309     template < typename Descriptor >
310     typename graph::detail::bundled_result< Graph, Descriptor >::type const&
operator [](Descriptor x) const311     operator[](Descriptor x) const
312     {
313         return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)];
314     }
315 
316     // Local property access returns the local property of the given descripor.
317     template < typename Descriptor >
318     typename graph::detail::bundled_result< Graph, Descriptor >::type&
operator [](local_property<Descriptor> x)319     operator[](local_property< Descriptor > x)
320     {
321         return m_graph[x.value];
322     }
323 
324     template < typename Descriptor >
325     typename graph::detail::bundled_result< Graph, Descriptor >::type const&
operator [](local_property<Descriptor> x) const326     operator[](local_property< Descriptor > x) const
327     {
328         return m_graph[x.value];
329     }
330 
331     // Global property access returns the global property associated with the
332     // given descriptor. This is an alias for the default bundled property
333     // access operations.
334     template < typename Descriptor >
335     typename graph::detail::bundled_result< Graph, Descriptor >::type&
operator [](global_property<Descriptor> x)336     operator[](global_property< Descriptor > x)
337     {
338         return (*this)[x.value];
339     }
340 
341     template < typename Descriptor >
342     typename graph::detail::bundled_result< Graph, Descriptor >::type const&
operator [](global_property<Descriptor> x) const343     operator[](global_property< Descriptor > x) const
344     {
345         return (*this)[x.value];
346     }
347 
348 #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
349 
350     //  private:
351     typedef typename property_map< Graph, edge_index_t >::type EdgeIndexMap;
352     typedef
353         typename property_traits< EdgeIndexMap >::value_type edge_index_type;
354     BOOST_STATIC_ASSERT((!is_same< edge_index_type,
355                          boost::detail::error_property_not_found >::value));
356 
357 private:
358     typedef std::vector< vertex_descriptor > GlobalVertexList;
359     typedef std::vector< edge_descriptor > GlobalEdgeList;
360     typedef std::map< vertex_descriptor, vertex_descriptor > LocalVertexMap;
361     typedef std::map< edge_index_type, edge_descriptor > LocalEdgeMap;
362     // TODO: Should the LocalVertexMap be: map<index_type, descriptor>?
363     // TODO: Can we relax the indexing requirement if both descriptors are
364     // LessThanComparable?
365     // TODO: Should we really be using unorderd_map for improved lookup times?
366 
367 public: // Probably shouldn't be public....
368     Graph m_graph;
369     subgraph< Graph >* m_parent;
370     edge_index_type m_edge_counter; // for generating unique edge indices
371     ChildrenList m_children;
372     GlobalVertexList m_global_vertex; // local -> global
373     LocalVertexMap m_local_vertex; // global -> local
374     GlobalEdgeList m_global_edge; // local -> global
375     LocalEdgeMap m_local_edge; // global -> local
376 
local_add_edge(vertex_descriptor u_local,vertex_descriptor v_local,edge_descriptor e_global)377     edge_descriptor local_add_edge(vertex_descriptor u_local,
378         vertex_descriptor v_local, edge_descriptor e_global)
379     {
380         edge_descriptor e_local;
381         bool inserted;
382         boost::tie(e_local, inserted) = add_edge(u_local, v_local, m_graph);
383         put(edge_index, m_graph, e_local, m_edge_counter++);
384         m_global_edge.push_back(e_global);
385         m_local_edge[get(get(edge_index, this->root()), e_global)] = e_local;
386         return e_local;
387     }
388 };
389 
390 template < typename Graph >
391 struct vertex_bundle_type< subgraph< Graph > > : vertex_bundle_type< Graph >
392 {
393 };
394 
395 template < typename Graph >
396 struct edge_bundle_type< subgraph< Graph > > : edge_bundle_type< Graph >
397 {
398 };
399 
400 template < typename Graph >
401 struct graph_bundle_type< subgraph< Graph > > : graph_bundle_type< Graph >
402 {
403 };
404 
405 //===========================================================================
406 // Functions special to the Subgraph Class
407 
408 template < typename G >
add_vertex(typename subgraph<G>::vertex_descriptor u_global,subgraph<G> & g)409 typename subgraph< G >::vertex_descriptor add_vertex(
410     typename subgraph< G >::vertex_descriptor u_global, subgraph< G >& g)
411 {
412     BOOST_ASSERT(!g.is_root());
413     typename subgraph< G >::vertex_descriptor u_local;
414     bool exists_local;
415     boost::tie(u_local, exists_local) = g.find_vertex(u_global);
416 
417     if (!exists_local)
418     {
419         typename subgraph< G >::vertex_descriptor v_global;
420         typename subgraph< G >::edge_descriptor e_global;
421         // call recursion for parent subgraph
422         if (!g.parent().is_root())
423             add_vertex(u_global, g.parent());
424 
425         u_local = add_vertex(g.m_graph);
426         g.m_global_vertex.push_back(u_global);
427         g.m_local_vertex[u_global] = u_local;
428 
429         subgraph< G >& r = g.root();
430 
431         // remember edge global and local maps
432         {
433             typename subgraph< G >::out_edge_iterator ei, ei_end;
434             for (boost::tie(ei, ei_end) = out_edges(u_global, r); ei != ei_end;
435                  ++ei)
436             {
437                 e_global = *ei;
438                 v_global = target(e_global, r);
439                 if (g.find_vertex(v_global).second == true)
440                     g.local_add_edge(
441                         u_local, g.global_to_local(v_global), e_global);
442             }
443         }
444         if (is_directed(g))
445         { // not necessary for undirected graph
446             typename subgraph< G >::vertex_iterator vi, vi_end;
447             typename subgraph< G >::out_edge_iterator ei, ei_end;
448             for (boost::tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi)
449             {
450                 v_global = *vi;
451                 if (v_global == u_global)
452                     continue; // don't insert self loops twice!
453                 if (!g.find_vertex(v_global).second)
454                     continue; // not a subgraph vertex => try next one
455                 for (boost::tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end;
456                      ++ei)
457                 {
458                     e_global = *ei;
459                     if (target(e_global, r) == u_global)
460                     {
461                         g.local_add_edge(
462                             g.global_to_local(v_global), u_local, e_global);
463                     }
464                 }
465             }
466         }
467     }
468     return u_local;
469 }
470 
471 // NOTE: Descriptors are local unless otherwise noted.
472 
473 //===========================================================================
474 // Functions required by the IncidenceGraph concept
475 
476 template < typename G >
477 std::pair< typename graph_traits< G >::out_edge_iterator,
478     typename graph_traits< G >::out_edge_iterator >
out_edges(typename graph_traits<G>::vertex_descriptor v,const subgraph<G> & g)479 out_edges(
480     typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
481 {
482     return out_edges(v, g.m_graph);
483 }
484 
485 template < typename G >
out_degree(typename graph_traits<G>::vertex_descriptor v,const subgraph<G> & g)486 typename graph_traits< G >::degree_size_type out_degree(
487     typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
488 {
489     return out_degree(v, g.m_graph);
490 }
491 
492 template < typename G >
source(typename graph_traits<G>::edge_descriptor e,const subgraph<G> & g)493 typename graph_traits< G >::vertex_descriptor source(
494     typename graph_traits< G >::edge_descriptor e, const subgraph< G >& g)
495 {
496     return source(e, g.m_graph);
497 }
498 
499 template < typename G >
target(typename graph_traits<G>::edge_descriptor e,const subgraph<G> & g)500 typename graph_traits< G >::vertex_descriptor target(
501     typename graph_traits< G >::edge_descriptor e, const subgraph< G >& g)
502 {
503     return target(e, g.m_graph);
504 }
505 
506 //===========================================================================
507 // Functions required by the BidirectionalGraph concept
508 
509 template < typename G >
510 std::pair< typename graph_traits< G >::in_edge_iterator,
511     typename graph_traits< G >::in_edge_iterator >
in_edges(typename graph_traits<G>::vertex_descriptor v,const subgraph<G> & g)512 in_edges(
513     typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
514 {
515     return in_edges(v, g.m_graph);
516 }
517 
518 template < typename G >
in_degree(typename graph_traits<G>::vertex_descriptor v,const subgraph<G> & g)519 typename graph_traits< G >::degree_size_type in_degree(
520     typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
521 {
522     return in_degree(v, g.m_graph);
523 }
524 
525 template < typename G >
degree(typename graph_traits<G>::vertex_descriptor v,const subgraph<G> & g)526 typename graph_traits< G >::degree_size_type degree(
527     typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
528 {
529     return degree(v, g.m_graph);
530 }
531 
532 //===========================================================================
533 // Functions required by the AdjacencyGraph concept
534 
535 template < typename G >
536 std::pair< typename subgraph< G >::adjacency_iterator,
537     typename subgraph< G >::adjacency_iterator >
adjacent_vertices(typename subgraph<G>::vertex_descriptor v,const subgraph<G> & g)538 adjacent_vertices(
539     typename subgraph< G >::vertex_descriptor v, const subgraph< G >& g)
540 {
541     return adjacent_vertices(v, g.m_graph);
542 }
543 
544 //===========================================================================
545 // Functions required by the VertexListGraph concept
546 
547 template < typename G >
548 std::pair< typename subgraph< G >::vertex_iterator,
549     typename subgraph< G >::vertex_iterator >
vertices(const subgraph<G> & g)550 vertices(const subgraph< G >& g)
551 {
552     return vertices(g.m_graph);
553 }
554 
555 template < typename G >
num_vertices(const subgraph<G> & g)556 typename subgraph< G >::vertices_size_type num_vertices(const subgraph< G >& g)
557 {
558     return num_vertices(g.m_graph);
559 }
560 
561 //===========================================================================
562 // Functions required by the EdgeListGraph concept
563 
564 template < typename G >
565 std::pair< typename subgraph< G >::edge_iterator,
566     typename subgraph< G >::edge_iterator >
edges(const subgraph<G> & g)567 edges(const subgraph< G >& g)
568 {
569     return edges(g.m_graph);
570 }
571 
572 template < typename G >
num_edges(const subgraph<G> & g)573 typename subgraph< G >::edges_size_type num_edges(const subgraph< G >& g)
574 {
575     return num_edges(g.m_graph);
576 }
577 
578 //===========================================================================
579 // Functions required by the AdjacencyMatrix concept
580 
581 template < typename G >
edge(typename subgraph<G>::vertex_descriptor u,typename subgraph<G>::vertex_descriptor v,const subgraph<G> & g)582 std::pair< typename subgraph< G >::edge_descriptor, bool > edge(
583     typename subgraph< G >::vertex_descriptor u,
584     typename subgraph< G >::vertex_descriptor v, const subgraph< G >& g)
585 {
586     return edge(u, v, g.m_graph);
587 }
588 
589 //===========================================================================
590 // Functions required by the MutableGraph concept
591 
592 namespace detail
593 {
594 
595     template < typename Vertex, typename Edge, typename Graph >
596     void add_edge_recur_down(
597         Vertex u_global, Vertex v_global, Edge e_global, subgraph< Graph >& g);
598 
599     template < typename Vertex, typename Edge, typename Children, typename G >
children_add_edge(Vertex u_global,Vertex v_global,Edge e_global,Children & c,subgraph<G> * orig)600     void children_add_edge(Vertex u_global, Vertex v_global, Edge e_global,
601         Children& c, subgraph< G >* orig)
602     {
603         for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
604         {
605             if ((*i)->find_vertex(u_global).second
606                 && (*i)->find_vertex(v_global).second)
607             {
608                 add_edge_recur_down(u_global, v_global, e_global, **i, orig);
609             }
610         }
611     }
612 
613     template < typename Vertex, typename Edge, typename Graph >
add_edge_recur_down(Vertex u_global,Vertex v_global,Edge e_global,subgraph<Graph> & g,subgraph<Graph> * orig)614     void add_edge_recur_down(Vertex u_global, Vertex v_global, Edge e_global,
615         subgraph< Graph >& g, subgraph< Graph >* orig)
616     {
617         if (&g != orig)
618         {
619             // add local edge only if u_global and v_global are in subgraph g
620             Vertex u_local, v_local;
621             bool u_in_subgraph, v_in_subgraph;
622             boost::tie(u_local, u_in_subgraph) = g.find_vertex(u_global);
623             boost::tie(v_local, v_in_subgraph) = g.find_vertex(v_global);
624             if (u_in_subgraph && v_in_subgraph)
625             {
626                 g.local_add_edge(u_local, v_local, e_global);
627             }
628         }
629         children_add_edge(u_global, v_global, e_global, g.m_children, orig);
630     }
631 
632     template < typename Vertex, typename Graph >
633     std::pair< typename subgraph< Graph >::edge_descriptor, bool >
add_edge_recur_up(Vertex u_global,Vertex v_global,const typename Graph::edge_property_type & ep,subgraph<Graph> & g,subgraph<Graph> * orig)634     add_edge_recur_up(Vertex u_global, Vertex v_global,
635         const typename Graph::edge_property_type& ep, subgraph< Graph >& g,
636         subgraph< Graph >* orig)
637     {
638         if (g.is_root())
639         {
640             typename subgraph< Graph >::edge_descriptor e_global;
641             bool inserted;
642             boost::tie(e_global, inserted)
643                 = add_edge(u_global, v_global, ep, g.m_graph);
644             put(edge_index, g.m_graph, e_global, g.m_edge_counter++);
645             g.m_global_edge.push_back(e_global);
646             children_add_edge(u_global, v_global, e_global, g.m_children, orig);
647             return std::make_pair(e_global, inserted);
648         }
649         else
650         {
651             return add_edge_recur_up(u_global, v_global, ep, *g.m_parent, orig);
652         }
653     }
654 
655 } // namespace detail
656 
657 // Add an edge to the subgraph g, specified by the local vertex descriptors u
658 // and v. In addition, the edge will be added to any (all) other subgraphs that
659 // contain vertex descriptors u and v.
660 
661 template < typename G >
add_edge(typename subgraph<G>::vertex_descriptor u,typename subgraph<G>::vertex_descriptor v,const typename G::edge_property_type & ep,subgraph<G> & g)662 std::pair< typename subgraph< G >::edge_descriptor, bool > add_edge(
663     typename subgraph< G >::vertex_descriptor u,
664     typename subgraph< G >::vertex_descriptor v,
665     const typename G::edge_property_type& ep, subgraph< G >& g)
666 {
667     if (g.is_root())
668     {
669         // u and v are really global
670         return detail::add_edge_recur_up(u, v, ep, g, &g);
671     }
672     else
673     {
674         typename subgraph< G >::edge_descriptor e_local, e_global;
675         bool inserted;
676         boost::tie(e_global, inserted) = detail::add_edge_recur_up(
677             g.local_to_global(u), g.local_to_global(v), ep, g, &g);
678         e_local = g.local_add_edge(u, v, e_global);
679         return std::make_pair(e_local, inserted);
680     }
681 }
682 
683 template < typename G >
add_edge(typename subgraph<G>::vertex_descriptor u,typename subgraph<G>::vertex_descriptor v,subgraph<G> & g)684 std::pair< typename subgraph< G >::edge_descriptor, bool > add_edge(
685     typename subgraph< G >::vertex_descriptor u,
686     typename subgraph< G >::vertex_descriptor v, subgraph< G >& g)
687 {
688     return add_edge(u, v, typename G::edge_property_type(), g);
689 }
690 
691 namespace detail
692 {
693     //-------------------------------------------------------------------------
694     // implementation of remove_edge(u,v,g)
695     template < typename Vertex, typename Graph >
696     void remove_edge_recur_down(
697         Vertex u_global, Vertex v_global, subgraph< Graph >& g);
698 
699     template < typename Vertex, typename Children >
children_remove_edge(Vertex u_global,Vertex v_global,Children & c)700     void children_remove_edge(Vertex u_global, Vertex v_global, Children& c)
701     {
702         for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
703         {
704             if ((*i)->find_vertex(u_global).second
705                 && (*i)->find_vertex(v_global).second)
706             {
707                 remove_edge_recur_down(u_global, v_global, **i);
708             }
709         }
710     }
711 
712     template < typename Vertex, typename Graph >
remove_edge_recur_down(Vertex u_global,Vertex v_global,subgraph<Graph> & g)713     void remove_edge_recur_down(
714         Vertex u_global, Vertex v_global, subgraph< Graph >& g)
715     {
716         Vertex u_local, v_local;
717         u_local = g.m_local_vertex[u_global];
718         v_local = g.m_local_vertex[v_global];
719         remove_edge(u_local, v_local, g.m_graph);
720         children_remove_edge(u_global, v_global, g.m_children);
721     }
722 
723     template < typename Vertex, typename Graph >
remove_edge_recur_up(Vertex u_global,Vertex v_global,subgraph<Graph> & g)724     void remove_edge_recur_up(
725         Vertex u_global, Vertex v_global, subgraph< Graph >& g)
726     {
727         if (g.is_root())
728         {
729             remove_edge(u_global, v_global, g.m_graph);
730             children_remove_edge(u_global, v_global, g.m_children);
731         }
732         else
733         {
734             remove_edge_recur_up(u_global, v_global, *g.m_parent);
735         }
736     }
737 
738     //-------------------------------------------------------------------------
739     // implementation of remove_edge(e,g)
740 
741     template < typename G, typename Edge, typename Children >
children_remove_edge(Edge e_global,Children & c)742     void children_remove_edge(Edge e_global, Children& c)
743     {
744         for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
745         {
746             std::pair< typename subgraph< G >::edge_descriptor, bool > found
747                 = (*i)->find_edge(e_global);
748             if (!found.second)
749             {
750                 continue;
751             }
752             children_remove_edge< G >(e_global, (*i)->m_children);
753             remove_edge(found.first, (*i)->m_graph);
754         }
755     }
756 
757 } // namespace detail
758 
759 template < typename G >
remove_edge(typename subgraph<G>::vertex_descriptor u,typename subgraph<G>::vertex_descriptor v,subgraph<G> & g)760 void remove_edge(typename subgraph< G >::vertex_descriptor u,
761     typename subgraph< G >::vertex_descriptor v, subgraph< G >& g)
762 {
763     if (g.is_root())
764     {
765         detail::remove_edge_recur_up(u, v, g);
766     }
767     else
768     {
769         detail::remove_edge_recur_up(
770             g.local_to_global(u), g.local_to_global(v), g);
771     }
772 }
773 
774 template < typename G >
remove_edge(typename subgraph<G>::edge_descriptor e,subgraph<G> & g)775 void remove_edge(typename subgraph< G >::edge_descriptor e, subgraph< G >& g)
776 {
777     typename subgraph< G >::edge_descriptor e_global = g.local_to_global(e);
778 #ifndef NDEBUG
779     std::pair< typename subgraph< G >::edge_descriptor, bool > fe
780         = g.find_edge(e_global);
781     BOOST_ASSERT(fe.second && fe.first == e);
782 #endif // NDEBUG
783     subgraph< G >& root = g.root(); // chase to root
784     detail::children_remove_edge< G >(e_global, root.m_children);
785     remove_edge(e_global, root.m_graph); // kick edge from root
786 }
787 
788 // This is slow, but there may not be a good way to do it safely otherwise
789 template < typename Predicate, typename G >
remove_edge_if(Predicate p,subgraph<G> & g)790 void remove_edge_if(Predicate p, subgraph< G >& g)
791 {
792     while (true)
793     {
794         bool any_removed = false;
795         typedef typename subgraph< G >::edge_iterator ei_type;
796         for (std::pair< ei_type, ei_type > ep = edges(g); ep.first != ep.second;
797              ++ep.first)
798         {
799             if (p(*ep.first))
800             {
801                 any_removed = true;
802                 remove_edge(*ep.first, g);
803                 break; /* Since iterators may be invalidated */
804             }
805         }
806         if (!any_removed)
807             break;
808     }
809 }
810 
811 template < typename G >
clear_vertex(typename subgraph<G>::vertex_descriptor v,subgraph<G> & g)812 void clear_vertex(typename subgraph< G >::vertex_descriptor v, subgraph< G >& g)
813 {
814     while (true)
815     {
816         typedef typename subgraph< G >::out_edge_iterator oei_type;
817         std::pair< oei_type, oei_type > p = out_edges(v, g);
818         if (p.first == p.second)
819             break;
820         remove_edge(*p.first, g);
821     }
822 }
823 
824 namespace detail
825 {
826     template < typename G >
add_vertex_recur_up(subgraph<G> & g)827     typename subgraph< G >::vertex_descriptor add_vertex_recur_up(
828         subgraph< G >& g)
829     {
830         typename subgraph< G >::vertex_descriptor u_local, u_global;
831         if (g.is_root())
832         {
833             u_global = add_vertex(g.m_graph);
834             g.m_global_vertex.push_back(u_global);
835         }
836         else
837         {
838             u_global = add_vertex_recur_up(*g.m_parent);
839             u_local = add_vertex(g.m_graph);
840             g.m_global_vertex.push_back(u_global);
841             g.m_local_vertex[u_global] = u_local;
842         }
843         return u_global;
844     }
845 } // namespace detail
846 
847 template < typename G >
add_vertex(subgraph<G> & g)848 typename subgraph< G >::vertex_descriptor add_vertex(subgraph< G >& g)
849 {
850     typename subgraph< G >::vertex_descriptor u_local, u_global;
851     if (g.is_root())
852     {
853         u_global = add_vertex(g.m_graph);
854         g.m_global_vertex.push_back(u_global);
855         u_local = u_global;
856     }
857     else
858     {
859         u_global = detail::add_vertex_recur_up(g.parent());
860         u_local = add_vertex(g.m_graph);
861         g.m_global_vertex.push_back(u_global);
862         g.m_local_vertex[u_global] = u_local;
863     }
864     return u_local;
865 }
866 
867 #if 0
868 // TODO: Under Construction
869 template <typename G>
870 void remove_vertex(typename subgraph<G>::vertex_descriptor u, subgraph<G>& g)
871 { BOOST_ASSERT(false); }
872 #endif
873 
874 //===========================================================================
875 // Functions required by the PropertyGraph concept
876 
877 /**
878  * The global property map returns the global properties associated with local
879  * descriptors.
880  */
881 template < typename GraphPtr, typename PropertyMap, typename Tag >
882 class subgraph_global_property_map
883 : public put_get_helper< typename property_traits< PropertyMap >::reference,
884       subgraph_global_property_map< GraphPtr, PropertyMap, Tag > >
885 {
886     typedef property_traits< PropertyMap > Traits;
887 
888 public:
889     typedef typename mpl::if_<
890         is_const< typename remove_pointer< GraphPtr >::type >,
891         readable_property_map_tag, typename Traits::category >::type category;
892     typedef typename Traits::value_type value_type;
893     typedef typename Traits::key_type key_type;
894     typedef typename Traits::reference reference;
895 
subgraph_global_property_map()896     subgraph_global_property_map() {}
897 
subgraph_global_property_map(GraphPtr g,Tag tag)898     subgraph_global_property_map(GraphPtr g, Tag tag) : m_g(g), m_tag(tag) {}
899 
operator [](key_type e) const900     reference operator[](key_type e) const
901     {
902         PropertyMap pmap = get(m_tag, m_g->root().m_graph);
903         return m_g->is_root() ? pmap[e] : pmap[m_g->local_to_global(e)];
904     }
905 
906     GraphPtr m_g;
907     Tag m_tag;
908 };
909 
910 /**
911  * The local property map returns the local property associated with the local
912  * descriptors.
913  */
914 template < typename GraphPtr, typename PropertyMap, typename Tag >
915 class subgraph_local_property_map
916 : public put_get_helper< typename property_traits< PropertyMap >::reference,
917       subgraph_local_property_map< GraphPtr, PropertyMap, Tag > >
918 {
919     typedef property_traits< PropertyMap > Traits;
920 
921 public:
922     typedef typename mpl::if_<
923         is_const< typename remove_pointer< GraphPtr >::type >,
924         readable_property_map_tag, typename Traits::category >::type category;
925     typedef typename Traits::value_type value_type;
926     typedef typename Traits::key_type key_type;
927     typedef typename Traits::reference reference;
928 
929     typedef Tag tag;
930     typedef PropertyMap pmap;
931 
subgraph_local_property_map()932     subgraph_local_property_map() {}
933 
subgraph_local_property_map(GraphPtr g,Tag tag)934     subgraph_local_property_map(GraphPtr g, Tag tag) : m_g(g), m_tag(tag) {}
935 
operator [](key_type e) const936     reference operator[](key_type e) const
937     {
938         // Get property map on the underlying graph.
939         PropertyMap pmap = get(m_tag, m_g->m_graph);
940         return pmap[e];
941     }
942 
943     GraphPtr m_g;
944     Tag m_tag;
945 };
946 
947 namespace detail
948 {
949     // Extract the actual tags from local or global property maps so we don't
950     // try to find non-properties.
951     template < typename P > struct extract_lg_tag
952     {
953         typedef P type;
954     };
955     template < typename P > struct extract_lg_tag< local_property< P > >
956     {
957         typedef P type;
958     };
959     template < typename P > struct extract_lg_tag< global_property< P > >
960     {
961         typedef P type;
962     };
963 
964     // NOTE: Mysterious Property template parameter unused in both metafunction
965     // classes.
966     struct subgraph_global_pmap
967     {
968         template < class Tag, class SubGraph, class Property > struct bind_
969         {
970             typedef typename SubGraph::graph_type Graph;
971             typedef SubGraph* SubGraphPtr;
972             typedef const SubGraph* const_SubGraphPtr;
973             typedef typename extract_lg_tag< Tag >::type TagType;
974             typedef typename property_map< Graph, TagType >::type PMap;
975             typedef
976                 typename property_map< Graph, TagType >::const_type const_PMap;
977 
978         public:
979             typedef subgraph_global_property_map< SubGraphPtr, PMap, TagType >
980                 type;
981             typedef subgraph_global_property_map< const_SubGraphPtr, const_PMap,
982                 TagType >
983                 const_type;
984         };
985     };
986 
987     struct subgraph_local_pmap
988     {
989         template < class Tag, class SubGraph, class Property > struct bind_
990         {
991             typedef typename SubGraph::graph_type Graph;
992             typedef SubGraph* SubGraphPtr;
993             typedef const SubGraph* const_SubGraphPtr;
994             typedef typename extract_lg_tag< Tag >::type TagType;
995             typedef typename property_map< Graph, TagType >::type PMap;
996             typedef
997                 typename property_map< Graph, TagType >::const_type const_PMap;
998 
999         public:
1000             typedef subgraph_local_property_map< SubGraphPtr, PMap, TagType >
1001                 type;
1002             typedef subgraph_local_property_map< const_SubGraphPtr, const_PMap,
1003                 TagType >
1004                 const_type;
1005         };
1006     };
1007 
1008     // These metafunctions select the corresponding metafunctions above, and
1009     // are used by the choose_pmap metafunction below to specialize the choice
1010     // of local/global property map. By default, we defer to the global
1011     // property.
1012     template < class Tag > struct subgraph_choose_pmap_helper
1013     {
1014         typedef subgraph_global_pmap type;
1015     };
1016     template < class Tag >
1017     struct subgraph_choose_pmap_helper< local_property< Tag > >
1018     {
1019         typedef subgraph_local_pmap type;
1020     };
1021     template < class Tag >
1022     struct subgraph_choose_pmap_helper< global_property< Tag > >
1023     {
1024         typedef subgraph_global_pmap type;
1025     };
1026 
1027     // As above, unless we're requesting vertex_index_t. Then it's always a
1028     // local property map. This enables the correct translation of descriptors
1029     // between local and global layers.
1030     template <> struct subgraph_choose_pmap_helper< vertex_index_t >
1031     {
1032         typedef subgraph_local_pmap type;
1033     };
1034     template <>
1035     struct subgraph_choose_pmap_helper< local_property< vertex_index_t > >
1036     {
1037         typedef subgraph_local_pmap type;
1038     };
1039     template <>
1040     struct subgraph_choose_pmap_helper< global_property< vertex_index_t > >
1041     {
1042         typedef subgraph_local_pmap type;
1043     };
1044 
1045     // Determine the kind of property. If SameType<Tag, vertex_index_t>, then
1046     // the property lookup is always local. Otherwise, the lookup is global.
1047     // NOTE: Property parameter is basically unused.
1048     template < class Tag, class Graph, class Property >
1049     struct subgraph_choose_pmap
1050     {
1051         typedef typename subgraph_choose_pmap_helper< Tag >::type Helper;
1052         typedef typename Helper::template bind_< Tag, Graph, Property > Bind;
1053         typedef typename Bind::type type;
1054         typedef typename Bind::const_type const_type;
1055     };
1056 
1057     // Used by the vertex/edge property selectors to determine the kind(s) of
1058     // property maps used by the property_map type generator.
1059     struct subgraph_property_generator
1060     {
1061         template < class SubGraph, class Property, class Tag > struct bind_
1062         {
1063             typedef subgraph_choose_pmap< Tag, SubGraph, Property > Choice;
1064             typedef typename Choice::type type;
1065             typedef typename Choice::const_type const_type;
1066         };
1067     };
1068 
1069 } // namespace detail
1070 
1071 template <> struct vertex_property_selector< subgraph_tag >
1072 {
1073     typedef detail::subgraph_property_generator type;
1074 };
1075 
1076 template <> struct edge_property_selector< subgraph_tag >
1077 {
1078     typedef detail::subgraph_property_generator type;
1079 };
1080 
1081 // ==================================================
1082 // get(p, g), get(p, g, k), and put(p, g, k, v)
1083 // ==================================================
1084 template < typename G, typename Property >
get(Property p,subgraph<G> & g)1085 typename property_map< subgraph< G >, Property >::type get(
1086     Property p, subgraph< G >& g)
1087 {
1088     typedef typename property_map< subgraph< G >, Property >::type PMap;
1089     return PMap(&g, p);
1090 }
1091 
1092 template < typename G, typename Property >
get(Property p,const subgraph<G> & g)1093 typename property_map< subgraph< G >, Property >::const_type get(
1094     Property p, const subgraph< G >& g)
1095 {
1096     typedef typename property_map< subgraph< G >, Property >::const_type PMap;
1097     return PMap(&g, p);
1098 }
1099 
1100 template < typename G, typename Property, typename Key >
1101 typename property_traits<
1102     typename property_map< subgraph< G >, Property >::const_type >::value_type
get(Property p,const subgraph<G> & g,const Key & k)1103 get(Property p, const subgraph< G >& g, const Key& k)
1104 {
1105     typedef typename property_map< subgraph< G >, Property >::const_type PMap;
1106     PMap pmap(&g, p);
1107     return pmap[k];
1108 }
1109 
1110 template < typename G, typename Property, typename Key, typename Value >
put(Property p,subgraph<G> & g,const Key & k,const Value & val)1111 void put(Property p, subgraph< G >& g, const Key& k, const Value& val)
1112 {
1113     typedef typename property_map< subgraph< G >, Property >::type PMap;
1114     PMap pmap(&g, p);
1115     pmap[k] = val;
1116 }
1117 
1118 // ==================================================
1119 // get(global(p), g)
1120 // NOTE: get(global(p), g, k) and put(global(p), g, k, v) not supported
1121 // ==================================================
1122 template < typename G, typename Property >
get(global_property<Property> p,subgraph<G> & g)1123 typename property_map< subgraph< G >, global_property< Property > >::type get(
1124     global_property< Property > p, subgraph< G >& g)
1125 {
1126     typedef typename property_map< subgraph< G >,
1127         global_property< Property > >::type Map;
1128     return Map(&g, p.value);
1129 }
1130 
1131 template < typename G, typename Property >
1132 typename property_map< subgraph< G >, global_property< Property > >::const_type
get(global_property<Property> p,const subgraph<G> & g)1133 get(global_property< Property > p, const subgraph< G >& g)
1134 {
1135     typedef typename property_map< subgraph< G >,
1136         global_property< Property > >::const_type Map;
1137     return Map(&g, p.value);
1138 }
1139 
1140 // ==================================================
1141 // get(local(p), g)
1142 // NOTE: get(local(p), g, k) and put(local(p), g, k, v) not supported
1143 // ==================================================
1144 template < typename G, typename Property >
get(local_property<Property> p,subgraph<G> & g)1145 typename property_map< subgraph< G >, local_property< Property > >::type get(
1146     local_property< Property > p, subgraph< G >& g)
1147 {
1148     typedef
1149         typename property_map< subgraph< G >, local_property< Property > >::type
1150             Map;
1151     return Map(&g, p.value);
1152 }
1153 
1154 template < typename G, typename Property >
1155 typename property_map< subgraph< G >, local_property< Property > >::const_type
get(local_property<Property> p,const subgraph<G> & g)1156 get(local_property< Property > p, const subgraph< G >& g)
1157 {
1158     typedef typename property_map< subgraph< G >,
1159         local_property< Property > >::const_type Map;
1160     return Map(&g, p.value);
1161 }
1162 
1163 template < typename G, typename Tag >
get_property(subgraph<G> & g,Tag tag)1164 inline typename graph_property< G, Tag >::type& get_property(
1165     subgraph< G >& g, Tag tag)
1166 {
1167     return get_property(g.m_graph, tag);
1168 }
1169 
1170 template < typename G, typename Tag >
get_property(const subgraph<G> & g,Tag tag)1171 inline const typename graph_property< G, Tag >::type& get_property(
1172     const subgraph< G >& g, Tag tag)
1173 {
1174     return get_property(g.m_graph, tag);
1175 }
1176 
1177 //===========================================================================
1178 // Miscellaneous Functions
1179 
1180 template < typename G >
vertex(typename subgraph<G>::vertices_size_type n,const subgraph<G> & g)1181 typename subgraph< G >::vertex_descriptor vertex(
1182     typename subgraph< G >::vertices_size_type n, const subgraph< G >& g)
1183 {
1184     return vertex(n, g.m_graph);
1185 }
1186 
1187 //===========================================================================
1188 // Mutability Traits
1189 // Just pull the mutability traits form the underlying graph. Note that this
1190 // will probably fail (badly) for labeled graphs.
1191 template < typename G > struct graph_mutability_traits< subgraph< G > >
1192 {
1193     typedef typename graph_mutability_traits< G >::category category;
1194 };
1195 
1196 } // namespace boost
1197 
1198 #endif // BOOST_SUBGRAPH_HPP
1199