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