1 //=======================================================================
2 // Copyright 2001 University of Notre Dame.
3 // Authors: Jeremy G. Siek and Lie-Quan Lee
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 //=======================================================================
10 #ifndef BOOST_SUBGRAPH_HPP
11 #define BOOST_SUBGRAPH_HPP
15 #include <boost/config.hpp>
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>
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>
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
45 template < typename T > struct local_property
48 local_property(T x) : value(x) {}
52 template < typename T > inline local_property< T > local(T x)
54 return local_property< T >(x);
57 template < typename T > struct global_property
60 global_property(T x) : value(x) {}
64 template < typename T > inline global_property< T > global(T x)
66 return global_property< T >(x);
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.
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.
82 template < typename Graph > class subgraph
84 typedef graph_traits< Graph > Traits;
85 typedef std::list< subgraph< Graph >* > ChildrenList;
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;
95 // IncidenceGraph requirements
96 typedef typename Traits::out_edge_iterator out_edge_iterator;
97 typedef typename Traits::degree_size_type degree_size_type;
99 // AdjacencyGraph requirements
100 typedef typename Traits::adjacency_iterator adjacency_iterator;
102 // VertexListGraph requirements
103 typedef typename Traits::vertex_iterator vertex_iterator;
104 typedef typename Traits::vertices_size_type vertices_size_type;
106 // EdgeListGraph requirements
107 typedef typename Traits::edge_iterator edge_iterator;
108 typedef typename Traits::edges_size_type edges_size_type;
110 typedef typename Traits::in_edge_iterator in_edge_iterator;
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;
118 // Create the main graph, the root of the subgraph tree
119 subgraph() : m_parent(0), m_edge_counter(0) {}
121 subgraph(const graph_property_type& p)
122 : m_graph(p), m_parent(0), m_edge_counter(0)
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)
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;
137 subgraph(const subgraph& x) : m_parent(x.m_parent), m_edge_counter(0)
142 m_edge_counter = x.m_edge_counter;
143 m_global_vertex = x.m_global_vertex;
144 m_global_edge = x.m_global_edge;
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)
153 add_vertex(x.local_to_global(*vi), *this);
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)
163 m_children.push_back(new subgraph< Graph >(*i));
164 m_children.back()->m_parent = this;
170 for (typename ChildrenList::iterator i = m_children.begin();
171 i != m_children.end(); ++i)
177 // Return a null vertex descriptor for the graph.
178 static vertex_descriptor null_vertex() { return Traits::null_vertex(); }
181 subgraph< Graph >& create_subgraph()
183 m_children.push_back(new subgraph< Graph >());
184 m_children.back()->m_parent = this;
185 return *m_children.back();
188 // Create a subgraph with the specified vertex set.
189 template < typename VertexIterator >
190 subgraph< Graph >& create_subgraph(
191 VertexIterator first, VertexIterator last)
193 m_children.push_back(new subgraph< Graph >());
194 m_children.back()->m_parent = this;
195 for (; first != last; ++first)
197 add_vertex(*first, *m_children.back());
199 return *m_children.back();
202 // local <-> global descriptor conversion functions
203 vertex_descriptor local_to_global(vertex_descriptor u_local) const
205 return is_root() ? u_local : m_global_vertex[u_local];
208 vertex_descriptor global_to_local(vertex_descriptor u_global) const
210 vertex_descriptor u_local;
214 boost::tie(u_local, in_subgraph) = this->find_vertex(u_global);
215 BOOST_ASSERT(in_subgraph == true);
219 edge_descriptor local_to_global(edge_descriptor e_local) const
223 : m_global_edge[get(get(edge_index, m_graph), e_local)];
226 edge_descriptor global_to_local(edge_descriptor e_global) const
228 return is_root() ? e_global
229 : (*m_local_edge.find(
230 get(get(edge_index, root().m_graph), e_global)))
234 // Is vertex u (of the root graph) contained in this subgraph?
235 // If so, return the matching local vertex.
236 std::pair< vertex_descriptor, bool > find_vertex(
237 vertex_descriptor u_global) const
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);
247 // Is edge e (of the root graph) contained in this subgraph?
248 // If so, return the matching local edge.
249 std::pair< edge_descriptor, bool > find_edge(edge_descriptor e_global) const
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);
259 // Return the parent graph.
260 subgraph& parent() { return *m_parent; }
261 const subgraph& parent() const { return *m_parent; }
263 // Return true if this is the root subgraph
264 bool is_root() const { return m_parent == 0; }
266 // Return the root graph of the subgraph tree.
267 subgraph& root() { return is_root() ? *this : m_parent->root(); }
269 const subgraph& root() const
271 return is_root() ? *this : m_parent->root();
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 >
281 typedef indirect_iterator< typename ChildrenList::const_iterator,
282 subgraph< Graph > const, std::bidirectional_iterator_tag >
283 const_children_iterator;
285 std::pair< const_children_iterator, const_children_iterator >
288 return std::make_pair(const_children_iterator(m_children.begin()),
289 const_children_iterator(m_children.end()));
292 std::pair< children_iterator, children_iterator > children()
294 return std::make_pair(children_iterator(m_children.begin()),
295 children_iterator(m_children.end()));
298 std::size_t num_children() const { return m_children.size(); }
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&
304 operator[](Descriptor x)
306 return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)];
309 template < typename Descriptor >
310 typename graph::detail::bundled_result< Graph, Descriptor >::type const&
311 operator[](Descriptor x) const
313 return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)];
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&
319 operator[](local_property< Descriptor > x)
321 return m_graph[x.value];
324 template < typename Descriptor >
325 typename graph::detail::bundled_result< Graph, Descriptor >::type const&
326 operator[](local_property< Descriptor > x) const
328 return m_graph[x.value];
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&
336 operator[](global_property< Descriptor > x)
338 return (*this)[x.value];
341 template < typename Descriptor >
342 typename graph::detail::bundled_result< Graph, Descriptor >::type const&
343 operator[](global_property< Descriptor > x) const
345 return (*this)[x.value];
348 #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
351 typedef typename property_map< Graph, edge_index_t >::type EdgeIndexMap;
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));
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?
367 public: // Probably shouldn't be public....
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
377 edge_descriptor local_add_edge(vertex_descriptor u_local,
378 vertex_descriptor v_local, edge_descriptor e_global)
380 edge_descriptor e_local;
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;
390 template < typename Graph >
391 struct vertex_bundle_type< subgraph< Graph > > : vertex_bundle_type< Graph >
395 template < typename Graph >
396 struct edge_bundle_type< subgraph< Graph > > : edge_bundle_type< Graph >
400 template < typename Graph >
401 struct graph_bundle_type< subgraph< Graph > > : graph_bundle_type< Graph >
405 //===========================================================================
406 // Functions special to the Subgraph Class
408 template < typename G >
409 typename subgraph< G >::vertex_descriptor add_vertex(
410 typename subgraph< G >::vertex_descriptor u_global, subgraph< G >& g)
412 BOOST_ASSERT(!g.is_root());
413 typename subgraph< G >::vertex_descriptor u_local;
415 boost::tie(u_local, exists_local) = g.find_vertex(u_global);
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());
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;
429 subgraph< G >& r = g.root();
431 // remember edge global and local maps
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;
438 v_global = target(e_global, r);
439 if (g.find_vertex(v_global).second == true)
441 u_local, g.global_to_local(v_global), e_global);
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)
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;
459 if (target(e_global, r) == u_global)
462 g.global_to_local(v_global), u_local, e_global);
471 // NOTE: Descriptors are local unless otherwise noted.
473 //===========================================================================
474 // Functions required by the IncidenceGraph concept
476 template < typename G >
477 std::pair< typename graph_traits< G >::out_edge_iterator,
478 typename graph_traits< G >::out_edge_iterator >
480 typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
482 return out_edges(v, g.m_graph);
485 template < typename G >
486 typename graph_traits< G >::degree_size_type out_degree(
487 typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
489 return out_degree(v, g.m_graph);
492 template < typename G >
493 typename graph_traits< G >::vertex_descriptor source(
494 typename graph_traits< G >::edge_descriptor e, const subgraph< G >& g)
496 return source(e, g.m_graph);
499 template < typename G >
500 typename graph_traits< G >::vertex_descriptor target(
501 typename graph_traits< G >::edge_descriptor e, const subgraph< G >& g)
503 return target(e, g.m_graph);
506 //===========================================================================
507 // Functions required by the BidirectionalGraph concept
509 template < typename G >
510 std::pair< typename graph_traits< G >::in_edge_iterator,
511 typename graph_traits< G >::in_edge_iterator >
513 typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
515 return in_edges(v, g.m_graph);
518 template < typename G >
519 typename graph_traits< G >::degree_size_type in_degree(
520 typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
522 return in_degree(v, g.m_graph);
525 template < typename G >
526 typename graph_traits< G >::degree_size_type degree(
527 typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
529 return degree(v, g.m_graph);
532 //===========================================================================
533 // Functions required by the AdjacencyGraph concept
535 template < typename G >
536 std::pair< typename subgraph< G >::adjacency_iterator,
537 typename subgraph< G >::adjacency_iterator >
539 typename subgraph< G >::vertex_descriptor v, const subgraph< G >& g)
541 return adjacent_vertices(v, g.m_graph);
544 //===========================================================================
545 // Functions required by the VertexListGraph concept
547 template < typename G >
548 std::pair< typename subgraph< G >::vertex_iterator,
549 typename subgraph< G >::vertex_iterator >
550 vertices(const subgraph< G >& g)
552 return vertices(g.m_graph);
555 template < typename G >
556 typename subgraph< G >::vertices_size_type num_vertices(const subgraph< G >& g)
558 return num_vertices(g.m_graph);
561 //===========================================================================
562 // Functions required by the EdgeListGraph concept
564 template < typename G >
565 std::pair< typename subgraph< G >::edge_iterator,
566 typename subgraph< G >::edge_iterator >
567 edges(const subgraph< G >& g)
569 return edges(g.m_graph);
572 template < typename G >
573 typename subgraph< G >::edges_size_type num_edges(const subgraph< G >& g)
575 return num_edges(g.m_graph);
578 //===========================================================================
579 // Functions required by the AdjacencyMatrix concept
581 template < typename 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)
586 return edge(u, v, g.m_graph);
589 //===========================================================================
590 // Functions required by the MutableGraph concept
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);
599 template < typename Vertex, typename Edge, typename Children, typename G >
600 void children_add_edge(Vertex u_global, Vertex v_global, Edge e_global,
601 Children& c, subgraph< G >* orig)
603 for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
605 if ((*i)->find_vertex(u_global).second
606 && (*i)->find_vertex(v_global).second)
608 add_edge_recur_down(u_global, v_global, e_global, **i, orig);
613 template < typename Vertex, typename Edge, typename Graph >
614 void add_edge_recur_down(Vertex u_global, Vertex v_global, Edge e_global,
615 subgraph< Graph >& g, subgraph< Graph >* orig)
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)
626 g.local_add_edge(u_local, v_local, e_global);
629 children_add_edge(u_global, v_global, e_global, g.m_children, orig);
632 template < typename Vertex, typename Graph >
633 std::pair< typename subgraph< Graph >::edge_descriptor, bool >
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)
640 typename subgraph< Graph >::edge_descriptor e_global;
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);
651 return add_edge_recur_up(u_global, v_global, ep, *g.m_parent, orig);
655 } // namespace detail
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.
661 template < typename 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)
669 // u and v are really global
670 return detail::add_edge_recur_up(u, v, ep, g, &g);
674 typename subgraph< G >::edge_descriptor e_local, e_global;
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);
683 template < typename 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)
688 return add_edge(u, v, typename G::edge_property_type(), g);
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);
699 template < typename Vertex, typename Children >
700 void children_remove_edge(Vertex u_global, Vertex v_global, Children& c)
702 for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
704 if ((*i)->find_vertex(u_global).second
705 && (*i)->find_vertex(v_global).second)
707 remove_edge_recur_down(u_global, v_global, **i);
712 template < typename Vertex, typename Graph >
713 void remove_edge_recur_down(
714 Vertex u_global, Vertex v_global, subgraph< Graph >& g)
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);
723 template < typename Vertex, typename Graph >
724 void remove_edge_recur_up(
725 Vertex u_global, Vertex v_global, subgraph< Graph >& g)
729 remove_edge(u_global, v_global, g.m_graph);
730 children_remove_edge(u_global, v_global, g.m_children);
734 remove_edge_recur_up(u_global, v_global, *g.m_parent);
738 //-------------------------------------------------------------------------
739 // implementation of remove_edge(e,g)
741 template < typename G, typename Edge, typename Children >
742 void children_remove_edge(Edge e_global, Children& c)
744 for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
746 std::pair< typename subgraph< G >::edge_descriptor, bool > found
747 = (*i)->find_edge(e_global);
752 children_remove_edge< G >(e_global, (*i)->m_children);
753 remove_edge(found.first, (*i)->m_graph);
757 } // namespace detail
759 template < typename G >
760 void remove_edge(typename subgraph< G >::vertex_descriptor u,
761 typename subgraph< G >::vertex_descriptor v, subgraph< G >& g)
765 detail::remove_edge_recur_up(u, v, g);
769 detail::remove_edge_recur_up(
770 g.local_to_global(u), g.local_to_global(v), g);
774 template < typename G >
775 void remove_edge(typename subgraph< G >::edge_descriptor e, subgraph< G >& g)
777 typename subgraph< G >::edge_descriptor e_global = g.local_to_global(e);
779 std::pair< typename subgraph< G >::edge_descriptor, bool > fe
780 = g.find_edge(e_global);
781 BOOST_ASSERT(fe.second && fe.first == e);
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
788 // This is slow, but there may not be a good way to do it safely otherwise
789 template < typename Predicate, typename G >
790 void remove_edge_if(Predicate p, subgraph< G >& g)
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;
802 remove_edge(*ep.first, g);
803 break; /* Since iterators may be invalidated */
811 template < typename G >
812 void clear_vertex(typename subgraph< G >::vertex_descriptor v, subgraph< G >& g)
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)
820 remove_edge(*p.first, g);
826 template < typename G >
827 typename subgraph< G >::vertex_descriptor add_vertex_recur_up(
830 typename subgraph< G >::vertex_descriptor u_local, u_global;
833 u_global = add_vertex(g.m_graph);
834 g.m_global_vertex.push_back(u_global);
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;
845 } // namespace detail
847 template < typename G >
848 typename subgraph< G >::vertex_descriptor add_vertex(subgraph< G >& g)
850 typename subgraph< G >::vertex_descriptor u_local, u_global;
853 u_global = add_vertex(g.m_graph);
854 g.m_global_vertex.push_back(u_global);
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;
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); }
874 //===========================================================================
875 // Functions required by the PropertyGraph concept
878 * The global property map returns the global properties associated with local
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 > >
886 typedef property_traits< PropertyMap > Traits;
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;
896 subgraph_global_property_map() {}
898 subgraph_global_property_map(GraphPtr g, Tag tag) : m_g(g), m_tag(tag) {}
900 reference operator[](key_type e) const
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)];
911 * The local property map returns the local property associated with the local
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 > >
919 typedef property_traits< PropertyMap > Traits;
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;
930 typedef PropertyMap pmap;
932 subgraph_local_property_map() {}
934 subgraph_local_property_map(GraphPtr g, Tag tag) : m_g(g), m_tag(tag) {}
936 reference operator[](key_type e) const
938 // Get property map on the underlying graph.
939 PropertyMap pmap = get(m_tag, m_g->m_graph);
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
955 template < typename P > struct extract_lg_tag< local_property< P > >
959 template < typename P > struct extract_lg_tag< global_property< P > >
964 // NOTE: Mysterious Property template parameter unused in both metafunction
966 struct subgraph_global_pmap
968 template < class Tag, class SubGraph, class Property > struct bind_
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;
976 typename property_map< Graph, TagType >::const_type const_PMap;
979 typedef subgraph_global_property_map< SubGraphPtr, PMap, TagType >
981 typedef subgraph_global_property_map< const_SubGraphPtr, const_PMap,
987 struct subgraph_local_pmap
989 template < class Tag, class SubGraph, class Property > struct bind_
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;
997 typename property_map< Graph, TagType >::const_type const_PMap;
1000 typedef subgraph_local_property_map< SubGraphPtr, PMap, TagType >
1002 typedef subgraph_local_property_map< const_SubGraphPtr, const_PMap,
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
1012 template < class Tag > struct subgraph_choose_pmap_helper
1014 typedef subgraph_global_pmap type;
1016 template < class Tag >
1017 struct subgraph_choose_pmap_helper< local_property< Tag > >
1019 typedef subgraph_local_pmap type;
1021 template < class Tag >
1022 struct subgraph_choose_pmap_helper< global_property< Tag > >
1024 typedef subgraph_global_pmap type;
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 >
1032 typedef subgraph_local_pmap type;
1035 struct subgraph_choose_pmap_helper< local_property< vertex_index_t > >
1037 typedef subgraph_local_pmap type;
1040 struct subgraph_choose_pmap_helper< global_property< vertex_index_t > >
1042 typedef subgraph_local_pmap type;
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
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;
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
1061 template < class SubGraph, class Property, class Tag > struct bind_
1063 typedef subgraph_choose_pmap< Tag, SubGraph, Property > Choice;
1064 typedef typename Choice::type type;
1065 typedef typename Choice::const_type const_type;
1069 } // namespace detail
1071 template <> struct vertex_property_selector< subgraph_tag >
1073 typedef detail::subgraph_property_generator type;
1076 template <> struct edge_property_selector< subgraph_tag >
1078 typedef detail::subgraph_property_generator type;
1081 // ==================================================
1082 // get(p, g), get(p, g, k), and put(p, g, k, v)
1083 // ==================================================
1084 template < typename G, typename Property >
1085 typename property_map< subgraph< G >, Property >::type get(
1086 Property p, subgraph< G >& g)
1088 typedef typename property_map< subgraph< G >, Property >::type PMap;
1092 template < typename G, typename Property >
1093 typename property_map< subgraph< G >, Property >::const_type get(
1094 Property p, const subgraph< G >& g)
1096 typedef typename property_map< subgraph< G >, Property >::const_type PMap;
1100 template < typename G, typename Property, typename Key >
1101 typename property_traits<
1102 typename property_map< subgraph< G >, Property >::const_type >::value_type
1103 get(Property p, const subgraph< G >& g, const Key& k)
1105 typedef typename property_map< subgraph< G >, Property >::const_type PMap;
1110 template < typename G, typename Property, typename Key, typename Value >
1111 void put(Property p, subgraph< G >& g, const Key& k, const Value& val)
1113 typedef typename property_map< subgraph< G >, Property >::type PMap;
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 >
1123 typename property_map< subgraph< G >, global_property< Property > >::type get(
1124 global_property< Property > p, subgraph< G >& g)
1126 typedef typename property_map< subgraph< G >,
1127 global_property< Property > >::type Map;
1128 return Map(&g, p.value);
1131 template < typename G, typename Property >
1132 typename property_map< subgraph< G >, global_property< Property > >::const_type
1133 get(global_property< Property > p, const subgraph< G >& g)
1135 typedef typename property_map< subgraph< G >,
1136 global_property< Property > >::const_type Map;
1137 return Map(&g, p.value);
1140 // ==================================================
1142 // NOTE: get(local(p), g, k) and put(local(p), g, k, v) not supported
1143 // ==================================================
1144 template < typename G, typename Property >
1145 typename property_map< subgraph< G >, local_property< Property > >::type get(
1146 local_property< Property > p, subgraph< G >& g)
1149 typename property_map< subgraph< G >, local_property< Property > >::type
1151 return Map(&g, p.value);
1154 template < typename G, typename Property >
1155 typename property_map< subgraph< G >, local_property< Property > >::const_type
1156 get(local_property< Property > p, const subgraph< G >& g)
1158 typedef typename property_map< subgraph< G >,
1159 local_property< Property > >::const_type Map;
1160 return Map(&g, p.value);
1163 template < typename G, typename Tag >
1164 inline typename graph_property< G, Tag >::type& get_property(
1165 subgraph< G >& g, Tag tag)
1167 return get_property(g.m_graph, tag);
1170 template < typename G, typename Tag >
1171 inline const typename graph_property< G, Tag >::type& get_property(
1172 const subgraph< G >& g, Tag tag)
1174 return get_property(g.m_graph, tag);
1177 //===========================================================================
1178 // Miscellaneous Functions
1180 template < typename G >
1181 typename subgraph< G >::vertex_descriptor vertex(
1182 typename subgraph< G >::vertices_size_type n, const subgraph< G >& g)
1184 return vertex(n, g.m_graph);
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 > >
1193 typedef typename graph_mutability_traits< G >::category category;
1196 } // namespace boost
1198 #endif // BOOST_SUBGRAPH_HPP