| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199 |
- //=======================================================================
- // Copyright 2001 University of Notre Dame.
- // Authors: Jeremy G. Siek and Lie-Quan Lee
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //=======================================================================
- #ifndef BOOST_SUBGRAPH_HPP
- #define BOOST_SUBGRAPH_HPP
- // UNDER CONSTRUCTION
- #include <boost/config.hpp>
- #include <list>
- #include <vector>
- #include <map>
- #include <boost/assert.hpp>
- #include <boost/graph/graph_traits.hpp>
- #include <boost/graph/graph_mutability_traits.hpp>
- #include <boost/graph/properties.hpp>
- #include <boost/iterator/indirect_iterator.hpp>
- #include <boost/static_assert.hpp>
- #include <boost/assert.hpp>
- #include <boost/type_traits.hpp>
- #include <boost/mpl/if.hpp>
- #include <boost/mpl/or.hpp>
- namespace boost
- {
- struct subgraph_tag
- {
- };
- /** @name Property Lookup
- * The local_property and global_property functions are used to create
- * structures that determine the lookup strategy for properties in subgraphs.
- * Note that the nested kind member is used to help interoperate with actual
- * Property types.
- */
- //@{
- template < typename T > struct local_property
- {
- typedef T kind;
- local_property(T x) : value(x) {}
- T value;
- };
- template < typename T > inline local_property< T > local(T x)
- {
- return local_property< T >(x);
- }
- template < typename T > struct global_property
- {
- typedef T kind;
- global_property(T x) : value(x) {}
- T value;
- };
- template < typename T > inline global_property< T > global(T x)
- {
- return global_property< T >(x);
- }
- //@}
- // Invariants of an induced subgraph:
- // - If vertex u is in subgraph g, then u must be in g.parent().
- // - If edge e is in subgraph g, then e must be in g.parent().
- // - If edge e=(u,v) is in the root graph, then edge e
- // is also in any subgraph that contains both vertex u and v.
- // The Graph template parameter must have a vertex_index and edge_index
- // internal property. It is assumed that the vertex indices are assigned
- // automatically by the graph during a call to add_vertex(). It is not
- // assumed that the edge vertices are assigned automatically, they are
- // explicitly assigned here.
- template < typename Graph > class subgraph
- {
- typedef graph_traits< Graph > Traits;
- typedef std::list< subgraph< Graph >* > ChildrenList;
- public:
- // Graph requirements
- typedef typename Traits::vertex_descriptor vertex_descriptor;
- typedef typename Traits::edge_descriptor edge_descriptor;
- typedef typename Traits::directed_category directed_category;
- typedef typename Traits::edge_parallel_category edge_parallel_category;
- typedef typename Traits::traversal_category traversal_category;
- // IncidenceGraph requirements
- typedef typename Traits::out_edge_iterator out_edge_iterator;
- typedef typename Traits::degree_size_type degree_size_type;
- // AdjacencyGraph requirements
- typedef typename Traits::adjacency_iterator adjacency_iterator;
- // VertexListGraph requirements
- typedef typename Traits::vertex_iterator vertex_iterator;
- typedef typename Traits::vertices_size_type vertices_size_type;
- // EdgeListGraph requirements
- typedef typename Traits::edge_iterator edge_iterator;
- typedef typename Traits::edges_size_type edges_size_type;
- typedef typename Traits::in_edge_iterator in_edge_iterator;
- typedef typename edge_property_type< Graph >::type edge_property_type;
- typedef typename vertex_property_type< Graph >::type vertex_property_type;
- typedef subgraph_tag graph_tag;
- typedef Graph graph_type;
- typedef typename graph_property_type< Graph >::type graph_property_type;
- // Create the main graph, the root of the subgraph tree
- subgraph() : m_parent(0), m_edge_counter(0) {}
- subgraph(const graph_property_type& p)
- : m_graph(p), m_parent(0), m_edge_counter(0)
- {
- }
- subgraph(vertices_size_type n,
- const graph_property_type& p = graph_property_type())
- : m_graph(n, p), m_parent(0), m_edge_counter(0), m_global_vertex(n)
- {
- typename Graph::vertex_iterator v, v_end;
- vertices_size_type i = 0;
- for (boost::tie(v, v_end) = vertices(m_graph); v != v_end; ++v)
- m_global_vertex[i++] = *v;
- }
- // copy constructor
- subgraph(const subgraph& x) : m_parent(x.m_parent), m_edge_counter(0)
- {
- if (x.is_root())
- {
- m_graph = x.m_graph;
- m_edge_counter = x.m_edge_counter;
- m_global_vertex = x.m_global_vertex;
- m_global_edge = x.m_global_edge;
- }
- else
- {
- get_property(*this) = get_property(x);
- typename subgraph< Graph >::vertex_iterator vi, vi_end;
- boost::tie(vi, vi_end) = vertices(x);
- for (; vi != vi_end; ++vi)
- {
- add_vertex(x.local_to_global(*vi), *this);
- }
- }
- // Do a deep copy (recursive).
- // Only the root graph is copied, the subgraphs contain
- // only references to the global vertices they own.
- typename subgraph< Graph >::children_iterator i, i_end;
- boost::tie(i, i_end) = x.children();
- for (; i != i_end; ++i)
- {
- m_children.push_back(new subgraph< Graph >(*i));
- m_children.back()->m_parent = this;
- }
- }
- ~subgraph()
- {
- for (typename ChildrenList::iterator i = m_children.begin();
- i != m_children.end(); ++i)
- {
- delete *i;
- }
- }
- // Return a null vertex descriptor for the graph.
- static vertex_descriptor null_vertex() { return Traits::null_vertex(); }
- // Create a subgraph
- subgraph< Graph >& create_subgraph()
- {
- m_children.push_back(new subgraph< Graph >());
- m_children.back()->m_parent = this;
- return *m_children.back();
- }
- // Create a subgraph with the specified vertex set.
- template < typename VertexIterator >
- subgraph< Graph >& create_subgraph(
- VertexIterator first, VertexIterator last)
- {
- m_children.push_back(new subgraph< Graph >());
- m_children.back()->m_parent = this;
- for (; first != last; ++first)
- {
- add_vertex(*first, *m_children.back());
- }
- return *m_children.back();
- }
- // local <-> global descriptor conversion functions
- vertex_descriptor local_to_global(vertex_descriptor u_local) const
- {
- return is_root() ? u_local : m_global_vertex[u_local];
- }
- vertex_descriptor global_to_local(vertex_descriptor u_global) const
- {
- vertex_descriptor u_local;
- bool in_subgraph;
- if (is_root())
- return u_global;
- boost::tie(u_local, in_subgraph) = this->find_vertex(u_global);
- BOOST_ASSERT(in_subgraph == true);
- return u_local;
- }
- edge_descriptor local_to_global(edge_descriptor e_local) const
- {
- return is_root()
- ? e_local
- : m_global_edge[get(get(edge_index, m_graph), e_local)];
- }
- edge_descriptor global_to_local(edge_descriptor e_global) const
- {
- return is_root() ? e_global
- : (*m_local_edge.find(
- get(get(edge_index, root().m_graph), e_global)))
- .second;
- }
- // Is vertex u (of the root graph) contained in this subgraph?
- // If so, return the matching local vertex.
- std::pair< vertex_descriptor, bool > find_vertex(
- vertex_descriptor u_global) const
- {
- if (is_root())
- return std::make_pair(u_global, true);
- typename LocalVertexMap::const_iterator i
- = m_local_vertex.find(u_global);
- bool valid = i != m_local_vertex.end();
- return std::make_pair((valid ? (*i).second : null_vertex()), valid);
- }
- // Is edge e (of the root graph) contained in this subgraph?
- // If so, return the matching local edge.
- std::pair< edge_descriptor, bool > find_edge(edge_descriptor e_global) const
- {
- if (is_root())
- return std::make_pair(e_global, true);
- typename LocalEdgeMap::const_iterator i
- = m_local_edge.find(get(get(edge_index, root().m_graph), e_global));
- bool valid = i != m_local_edge.end();
- return std::make_pair((valid ? (*i).second : edge_descriptor()), valid);
- }
- // Return the parent graph.
- subgraph& parent() { return *m_parent; }
- const subgraph& parent() const { return *m_parent; }
- // Return true if this is the root subgraph
- bool is_root() const { return m_parent == 0; }
- // Return the root graph of the subgraph tree.
- subgraph& root() { return is_root() ? *this : m_parent->root(); }
- const subgraph& root() const
- {
- return is_root() ? *this : m_parent->root();
- }
- // Return the children subgraphs of this graph/subgraph.
- // Use a list of pointers because the VC++ std::list doesn't like
- // storing incomplete type.
- typedef indirect_iterator< typename ChildrenList::const_iterator,
- subgraph< Graph >, std::bidirectional_iterator_tag >
- children_iterator;
- typedef indirect_iterator< typename ChildrenList::const_iterator,
- subgraph< Graph > const, std::bidirectional_iterator_tag >
- const_children_iterator;
- std::pair< const_children_iterator, const_children_iterator >
- children() const
- {
- return std::make_pair(const_children_iterator(m_children.begin()),
- const_children_iterator(m_children.end()));
- }
- std::pair< children_iterator, children_iterator > children()
- {
- return std::make_pair(children_iterator(m_children.begin()),
- children_iterator(m_children.end()));
- }
- std::size_t num_children() const { return m_children.size(); }
- #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
- // Defualt property access delegates the lookup to global properties.
- template < typename Descriptor >
- typename graph::detail::bundled_result< Graph, Descriptor >::type&
- operator[](Descriptor x)
- {
- return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)];
- }
- template < typename Descriptor >
- typename graph::detail::bundled_result< Graph, Descriptor >::type const&
- operator[](Descriptor x) const
- {
- return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)];
- }
- // Local property access returns the local property of the given descripor.
- template < typename Descriptor >
- typename graph::detail::bundled_result< Graph, Descriptor >::type&
- operator[](local_property< Descriptor > x)
- {
- return m_graph[x.value];
- }
- template < typename Descriptor >
- typename graph::detail::bundled_result< Graph, Descriptor >::type const&
- operator[](local_property< Descriptor > x) const
- {
- return m_graph[x.value];
- }
- // Global property access returns the global property associated with the
- // given descriptor. This is an alias for the default bundled property
- // access operations.
- template < typename Descriptor >
- typename graph::detail::bundled_result< Graph, Descriptor >::type&
- operator[](global_property< Descriptor > x)
- {
- return (*this)[x.value];
- }
- template < typename Descriptor >
- typename graph::detail::bundled_result< Graph, Descriptor >::type const&
- operator[](global_property< Descriptor > x) const
- {
- return (*this)[x.value];
- }
- #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
- // private:
- typedef typename property_map< Graph, edge_index_t >::type EdgeIndexMap;
- typedef
- typename property_traits< EdgeIndexMap >::value_type edge_index_type;
- BOOST_STATIC_ASSERT((!is_same< edge_index_type,
- boost::detail::error_property_not_found >::value));
- private:
- typedef std::vector< vertex_descriptor > GlobalVertexList;
- typedef std::vector< edge_descriptor > GlobalEdgeList;
- typedef std::map< vertex_descriptor, vertex_descriptor > LocalVertexMap;
- typedef std::map< edge_index_type, edge_descriptor > LocalEdgeMap;
- // TODO: Should the LocalVertexMap be: map<index_type, descriptor>?
- // TODO: Can we relax the indexing requirement if both descriptors are
- // LessThanComparable?
- // TODO: Should we really be using unorderd_map for improved lookup times?
- public: // Probably shouldn't be public....
- Graph m_graph;
- subgraph< Graph >* m_parent;
- edge_index_type m_edge_counter; // for generating unique edge indices
- ChildrenList m_children;
- GlobalVertexList m_global_vertex; // local -> global
- LocalVertexMap m_local_vertex; // global -> local
- GlobalEdgeList m_global_edge; // local -> global
- LocalEdgeMap m_local_edge; // global -> local
- edge_descriptor local_add_edge(vertex_descriptor u_local,
- vertex_descriptor v_local, edge_descriptor e_global)
- {
- edge_descriptor e_local;
- bool inserted;
- boost::tie(e_local, inserted) = add_edge(u_local, v_local, m_graph);
- put(edge_index, m_graph, e_local, m_edge_counter++);
- m_global_edge.push_back(e_global);
- m_local_edge[get(get(edge_index, this->root()), e_global)] = e_local;
- return e_local;
- }
- };
- template < typename Graph >
- struct vertex_bundle_type< subgraph< Graph > > : vertex_bundle_type< Graph >
- {
- };
- template < typename Graph >
- struct edge_bundle_type< subgraph< Graph > > : edge_bundle_type< Graph >
- {
- };
- template < typename Graph >
- struct graph_bundle_type< subgraph< Graph > > : graph_bundle_type< Graph >
- {
- };
- //===========================================================================
- // Functions special to the Subgraph Class
- template < typename G >
- typename subgraph< G >::vertex_descriptor add_vertex(
- typename subgraph< G >::vertex_descriptor u_global, subgraph< G >& g)
- {
- BOOST_ASSERT(!g.is_root());
- typename subgraph< G >::vertex_descriptor u_local;
- bool exists_local;
- boost::tie(u_local, exists_local) = g.find_vertex(u_global);
- if (!exists_local)
- {
- typename subgraph< G >::vertex_descriptor v_global;
- typename subgraph< G >::edge_descriptor e_global;
- // call recursion for parent subgraph
- if (!g.parent().is_root())
- add_vertex(u_global, g.parent());
- u_local = add_vertex(g.m_graph);
- g.m_global_vertex.push_back(u_global);
- g.m_local_vertex[u_global] = u_local;
- subgraph< G >& r = g.root();
- // remember edge global and local maps
- {
- typename subgraph< G >::out_edge_iterator ei, ei_end;
- for (boost::tie(ei, ei_end) = out_edges(u_global, r); ei != ei_end;
- ++ei)
- {
- e_global = *ei;
- v_global = target(e_global, r);
- if (g.find_vertex(v_global).second == true)
- g.local_add_edge(
- u_local, g.global_to_local(v_global), e_global);
- }
- }
- if (is_directed(g))
- { // not necessary for undirected graph
- typename subgraph< G >::vertex_iterator vi, vi_end;
- typename subgraph< G >::out_edge_iterator ei, ei_end;
- for (boost::tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi)
- {
- v_global = *vi;
- if (v_global == u_global)
- continue; // don't insert self loops twice!
- if (!g.find_vertex(v_global).second)
- continue; // not a subgraph vertex => try next one
- for (boost::tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end;
- ++ei)
- {
- e_global = *ei;
- if (target(e_global, r) == u_global)
- {
- g.local_add_edge(
- g.global_to_local(v_global), u_local, e_global);
- }
- }
- }
- }
- }
- return u_local;
- }
- // NOTE: Descriptors are local unless otherwise noted.
- //===========================================================================
- // Functions required by the IncidenceGraph concept
- template < typename G >
- std::pair< typename graph_traits< G >::out_edge_iterator,
- typename graph_traits< G >::out_edge_iterator >
- out_edges(
- typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
- {
- return out_edges(v, g.m_graph);
- }
- template < typename G >
- typename graph_traits< G >::degree_size_type out_degree(
- typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
- {
- return out_degree(v, g.m_graph);
- }
- template < typename G >
- typename graph_traits< G >::vertex_descriptor source(
- typename graph_traits< G >::edge_descriptor e, const subgraph< G >& g)
- {
- return source(e, g.m_graph);
- }
- template < typename G >
- typename graph_traits< G >::vertex_descriptor target(
- typename graph_traits< G >::edge_descriptor e, const subgraph< G >& g)
- {
- return target(e, g.m_graph);
- }
- //===========================================================================
- // Functions required by the BidirectionalGraph concept
- template < typename G >
- std::pair< typename graph_traits< G >::in_edge_iterator,
- typename graph_traits< G >::in_edge_iterator >
- in_edges(
- typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
- {
- return in_edges(v, g.m_graph);
- }
- template < typename G >
- typename graph_traits< G >::degree_size_type in_degree(
- typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
- {
- return in_degree(v, g.m_graph);
- }
- template < typename G >
- typename graph_traits< G >::degree_size_type degree(
- typename graph_traits< G >::vertex_descriptor v, const subgraph< G >& g)
- {
- return degree(v, g.m_graph);
- }
- //===========================================================================
- // Functions required by the AdjacencyGraph concept
- template < typename G >
- std::pair< typename subgraph< G >::adjacency_iterator,
- typename subgraph< G >::adjacency_iterator >
- adjacent_vertices(
- typename subgraph< G >::vertex_descriptor v, const subgraph< G >& g)
- {
- return adjacent_vertices(v, g.m_graph);
- }
- //===========================================================================
- // Functions required by the VertexListGraph concept
- template < typename G >
- std::pair< typename subgraph< G >::vertex_iterator,
- typename subgraph< G >::vertex_iterator >
- vertices(const subgraph< G >& g)
- {
- return vertices(g.m_graph);
- }
- template < typename G >
- typename subgraph< G >::vertices_size_type num_vertices(const subgraph< G >& g)
- {
- return num_vertices(g.m_graph);
- }
- //===========================================================================
- // Functions required by the EdgeListGraph concept
- template < typename G >
- std::pair< typename subgraph< G >::edge_iterator,
- typename subgraph< G >::edge_iterator >
- edges(const subgraph< G >& g)
- {
- return edges(g.m_graph);
- }
- template < typename G >
- typename subgraph< G >::edges_size_type num_edges(const subgraph< G >& g)
- {
- return num_edges(g.m_graph);
- }
- //===========================================================================
- // Functions required by the AdjacencyMatrix concept
- template < typename G >
- 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)
- {
- return edge(u, v, g.m_graph);
- }
- //===========================================================================
- // Functions required by the MutableGraph concept
- namespace detail
- {
- template < typename Vertex, typename Edge, typename Graph >
- void add_edge_recur_down(
- Vertex u_global, Vertex v_global, Edge e_global, subgraph< Graph >& g);
- template < typename Vertex, typename Edge, typename Children, typename G >
- void children_add_edge(Vertex u_global, Vertex v_global, Edge e_global,
- Children& c, subgraph< G >* orig)
- {
- for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
- {
- if ((*i)->find_vertex(u_global).second
- && (*i)->find_vertex(v_global).second)
- {
- add_edge_recur_down(u_global, v_global, e_global, **i, orig);
- }
- }
- }
- template < typename Vertex, typename Edge, typename Graph >
- void add_edge_recur_down(Vertex u_global, Vertex v_global, Edge e_global,
- subgraph< Graph >& g, subgraph< Graph >* orig)
- {
- if (&g != orig)
- {
- // add local edge only if u_global and v_global are in subgraph g
- Vertex u_local, v_local;
- bool u_in_subgraph, v_in_subgraph;
- boost::tie(u_local, u_in_subgraph) = g.find_vertex(u_global);
- boost::tie(v_local, v_in_subgraph) = g.find_vertex(v_global);
- if (u_in_subgraph && v_in_subgraph)
- {
- g.local_add_edge(u_local, v_local, e_global);
- }
- }
- children_add_edge(u_global, v_global, e_global, g.m_children, orig);
- }
- template < typename Vertex, typename Graph >
- 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)
- {
- if (g.is_root())
- {
- typename subgraph< Graph >::edge_descriptor e_global;
- bool inserted;
- boost::tie(e_global, inserted)
- = add_edge(u_global, v_global, ep, g.m_graph);
- put(edge_index, g.m_graph, e_global, g.m_edge_counter++);
- g.m_global_edge.push_back(e_global);
- children_add_edge(u_global, v_global, e_global, g.m_children, orig);
- return std::make_pair(e_global, inserted);
- }
- else
- {
- return add_edge_recur_up(u_global, v_global, ep, *g.m_parent, orig);
- }
- }
- } // namespace detail
- // Add an edge to the subgraph g, specified by the local vertex descriptors u
- // and v. In addition, the edge will be added to any (all) other subgraphs that
- // contain vertex descriptors u and v.
- template < typename G >
- 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)
- {
- if (g.is_root())
- {
- // u and v are really global
- return detail::add_edge_recur_up(u, v, ep, g, &g);
- }
- else
- {
- typename subgraph< G >::edge_descriptor e_local, e_global;
- bool inserted;
- boost::tie(e_global, inserted) = detail::add_edge_recur_up(
- g.local_to_global(u), g.local_to_global(v), ep, g, &g);
- e_local = g.local_add_edge(u, v, e_global);
- return std::make_pair(e_local, inserted);
- }
- }
- template < typename G >
- 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)
- {
- return add_edge(u, v, typename G::edge_property_type(), g);
- }
- namespace detail
- {
- //-------------------------------------------------------------------------
- // implementation of remove_edge(u,v,g)
- template < typename Vertex, typename Graph >
- void remove_edge_recur_down(
- Vertex u_global, Vertex v_global, subgraph< Graph >& g);
- template < typename Vertex, typename Children >
- void children_remove_edge(Vertex u_global, Vertex v_global, Children& c)
- {
- for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
- {
- if ((*i)->find_vertex(u_global).second
- && (*i)->find_vertex(v_global).second)
- {
- remove_edge_recur_down(u_global, v_global, **i);
- }
- }
- }
- template < typename Vertex, typename Graph >
- void remove_edge_recur_down(
- Vertex u_global, Vertex v_global, subgraph< Graph >& g)
- {
- Vertex u_local, v_local;
- u_local = g.m_local_vertex[u_global];
- v_local = g.m_local_vertex[v_global];
- remove_edge(u_local, v_local, g.m_graph);
- children_remove_edge(u_global, v_global, g.m_children);
- }
- template < typename Vertex, typename Graph >
- void remove_edge_recur_up(
- Vertex u_global, Vertex v_global, subgraph< Graph >& g)
- {
- if (g.is_root())
- {
- remove_edge(u_global, v_global, g.m_graph);
- children_remove_edge(u_global, v_global, g.m_children);
- }
- else
- {
- remove_edge_recur_up(u_global, v_global, *g.m_parent);
- }
- }
- //-------------------------------------------------------------------------
- // implementation of remove_edge(e,g)
- template < typename G, typename Edge, typename Children >
- void children_remove_edge(Edge e_global, Children& c)
- {
- for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
- {
- std::pair< typename subgraph< G >::edge_descriptor, bool > found
- = (*i)->find_edge(e_global);
- if (!found.second)
- {
- continue;
- }
- children_remove_edge< G >(e_global, (*i)->m_children);
- remove_edge(found.first, (*i)->m_graph);
- }
- }
- } // namespace detail
- template < typename G >
- void remove_edge(typename subgraph< G >::vertex_descriptor u,
- typename subgraph< G >::vertex_descriptor v, subgraph< G >& g)
- {
- if (g.is_root())
- {
- detail::remove_edge_recur_up(u, v, g);
- }
- else
- {
- detail::remove_edge_recur_up(
- g.local_to_global(u), g.local_to_global(v), g);
- }
- }
- template < typename G >
- void remove_edge(typename subgraph< G >::edge_descriptor e, subgraph< G >& g)
- {
- typename subgraph< G >::edge_descriptor e_global = g.local_to_global(e);
- #ifndef NDEBUG
- std::pair< typename subgraph< G >::edge_descriptor, bool > fe
- = g.find_edge(e_global);
- BOOST_ASSERT(fe.second && fe.first == e);
- #endif // NDEBUG
- subgraph< G >& root = g.root(); // chase to root
- detail::children_remove_edge< G >(e_global, root.m_children);
- remove_edge(e_global, root.m_graph); // kick edge from root
- }
- // This is slow, but there may not be a good way to do it safely otherwise
- template < typename Predicate, typename G >
- void remove_edge_if(Predicate p, subgraph< G >& g)
- {
- while (true)
- {
- bool any_removed = false;
- typedef typename subgraph< G >::edge_iterator ei_type;
- for (std::pair< ei_type, ei_type > ep = edges(g); ep.first != ep.second;
- ++ep.first)
- {
- if (p(*ep.first))
- {
- any_removed = true;
- remove_edge(*ep.first, g);
- break; /* Since iterators may be invalidated */
- }
- }
- if (!any_removed)
- break;
- }
- }
- template < typename G >
- void clear_vertex(typename subgraph< G >::vertex_descriptor v, subgraph< G >& g)
- {
- while (true)
- {
- typedef typename subgraph< G >::out_edge_iterator oei_type;
- std::pair< oei_type, oei_type > p = out_edges(v, g);
- if (p.first == p.second)
- break;
- remove_edge(*p.first, g);
- }
- }
- namespace detail
- {
- template < typename G >
- typename subgraph< G >::vertex_descriptor add_vertex_recur_up(
- subgraph< G >& g)
- {
- typename subgraph< G >::vertex_descriptor u_local, u_global;
- if (g.is_root())
- {
- u_global = add_vertex(g.m_graph);
- g.m_global_vertex.push_back(u_global);
- }
- else
- {
- u_global = add_vertex_recur_up(*g.m_parent);
- u_local = add_vertex(g.m_graph);
- g.m_global_vertex.push_back(u_global);
- g.m_local_vertex[u_global] = u_local;
- }
- return u_global;
- }
- } // namespace detail
- template < typename G >
- typename subgraph< G >::vertex_descriptor add_vertex(subgraph< G >& g)
- {
- typename subgraph< G >::vertex_descriptor u_local, u_global;
- if (g.is_root())
- {
- u_global = add_vertex(g.m_graph);
- g.m_global_vertex.push_back(u_global);
- u_local = u_global;
- }
- else
- {
- u_global = detail::add_vertex_recur_up(g.parent());
- u_local = add_vertex(g.m_graph);
- g.m_global_vertex.push_back(u_global);
- g.m_local_vertex[u_global] = u_local;
- }
- return u_local;
- }
- #if 0
- // TODO: Under Construction
- template <typename G>
- void remove_vertex(typename subgraph<G>::vertex_descriptor u, subgraph<G>& g)
- { BOOST_ASSERT(false); }
- #endif
- //===========================================================================
- // Functions required by the PropertyGraph concept
- /**
- * The global property map returns the global properties associated with local
- * descriptors.
- */
- template < typename GraphPtr, typename PropertyMap, typename Tag >
- class subgraph_global_property_map
- : public put_get_helper< typename property_traits< PropertyMap >::reference,
- subgraph_global_property_map< GraphPtr, PropertyMap, Tag > >
- {
- typedef property_traits< PropertyMap > Traits;
- public:
- typedef typename mpl::if_<
- is_const< typename remove_pointer< GraphPtr >::type >,
- readable_property_map_tag, typename Traits::category >::type category;
- typedef typename Traits::value_type value_type;
- typedef typename Traits::key_type key_type;
- typedef typename Traits::reference reference;
- subgraph_global_property_map() {}
- subgraph_global_property_map(GraphPtr g, Tag tag) : m_g(g), m_tag(tag) {}
- reference operator[](key_type e) const
- {
- PropertyMap pmap = get(m_tag, m_g->root().m_graph);
- return m_g->is_root() ? pmap[e] : pmap[m_g->local_to_global(e)];
- }
- GraphPtr m_g;
- Tag m_tag;
- };
- /**
- * The local property map returns the local property associated with the local
- * descriptors.
- */
- template < typename GraphPtr, typename PropertyMap, typename Tag >
- class subgraph_local_property_map
- : public put_get_helper< typename property_traits< PropertyMap >::reference,
- subgraph_local_property_map< GraphPtr, PropertyMap, Tag > >
- {
- typedef property_traits< PropertyMap > Traits;
- public:
- typedef typename mpl::if_<
- is_const< typename remove_pointer< GraphPtr >::type >,
- readable_property_map_tag, typename Traits::category >::type category;
- typedef typename Traits::value_type value_type;
- typedef typename Traits::key_type key_type;
- typedef typename Traits::reference reference;
- typedef Tag tag;
- typedef PropertyMap pmap;
- subgraph_local_property_map() {}
- subgraph_local_property_map(GraphPtr g, Tag tag) : m_g(g), m_tag(tag) {}
- reference operator[](key_type e) const
- {
- // Get property map on the underlying graph.
- PropertyMap pmap = get(m_tag, m_g->m_graph);
- return pmap[e];
- }
- GraphPtr m_g;
- Tag m_tag;
- };
- namespace detail
- {
- // Extract the actual tags from local or global property maps so we don't
- // try to find non-properties.
- template < typename P > struct extract_lg_tag
- {
- typedef P type;
- };
- template < typename P > struct extract_lg_tag< local_property< P > >
- {
- typedef P type;
- };
- template < typename P > struct extract_lg_tag< global_property< P > >
- {
- typedef P type;
- };
- // NOTE: Mysterious Property template parameter unused in both metafunction
- // classes.
- struct subgraph_global_pmap
- {
- template < class Tag, class SubGraph, class Property > struct bind_
- {
- typedef typename SubGraph::graph_type Graph;
- typedef SubGraph* SubGraphPtr;
- typedef const SubGraph* const_SubGraphPtr;
- typedef typename extract_lg_tag< Tag >::type TagType;
- typedef typename property_map< Graph, TagType >::type PMap;
- typedef
- typename property_map< Graph, TagType >::const_type const_PMap;
- public:
- typedef subgraph_global_property_map< SubGraphPtr, PMap, TagType >
- type;
- typedef subgraph_global_property_map< const_SubGraphPtr, const_PMap,
- TagType >
- const_type;
- };
- };
- struct subgraph_local_pmap
- {
- template < class Tag, class SubGraph, class Property > struct bind_
- {
- typedef typename SubGraph::graph_type Graph;
- typedef SubGraph* SubGraphPtr;
- typedef const SubGraph* const_SubGraphPtr;
- typedef typename extract_lg_tag< Tag >::type TagType;
- typedef typename property_map< Graph, TagType >::type PMap;
- typedef
- typename property_map< Graph, TagType >::const_type const_PMap;
- public:
- typedef subgraph_local_property_map< SubGraphPtr, PMap, TagType >
- type;
- typedef subgraph_local_property_map< const_SubGraphPtr, const_PMap,
- TagType >
- const_type;
- };
- };
- // These metafunctions select the corresponding metafunctions above, and
- // are used by the choose_pmap metafunction below to specialize the choice
- // of local/global property map. By default, we defer to the global
- // property.
- template < class Tag > struct subgraph_choose_pmap_helper
- {
- typedef subgraph_global_pmap type;
- };
- template < class Tag >
- struct subgraph_choose_pmap_helper< local_property< Tag > >
- {
- typedef subgraph_local_pmap type;
- };
- template < class Tag >
- struct subgraph_choose_pmap_helper< global_property< Tag > >
- {
- typedef subgraph_global_pmap type;
- };
- // As above, unless we're requesting vertex_index_t. Then it's always a
- // local property map. This enables the correct translation of descriptors
- // between local and global layers.
- template <> struct subgraph_choose_pmap_helper< vertex_index_t >
- {
- typedef subgraph_local_pmap type;
- };
- template <>
- struct subgraph_choose_pmap_helper< local_property< vertex_index_t > >
- {
- typedef subgraph_local_pmap type;
- };
- template <>
- struct subgraph_choose_pmap_helper< global_property< vertex_index_t > >
- {
- typedef subgraph_local_pmap type;
- };
- // Determine the kind of property. If SameType<Tag, vertex_index_t>, then
- // the property lookup is always local. Otherwise, the lookup is global.
- // NOTE: Property parameter is basically unused.
- template < class Tag, class Graph, class Property >
- struct subgraph_choose_pmap
- {
- typedef typename subgraph_choose_pmap_helper< Tag >::type Helper;
- typedef typename Helper::template bind_< Tag, Graph, Property > Bind;
- typedef typename Bind::type type;
- typedef typename Bind::const_type const_type;
- };
- // Used by the vertex/edge property selectors to determine the kind(s) of
- // property maps used by the property_map type generator.
- struct subgraph_property_generator
- {
- template < class SubGraph, class Property, class Tag > struct bind_
- {
- typedef subgraph_choose_pmap< Tag, SubGraph, Property > Choice;
- typedef typename Choice::type type;
- typedef typename Choice::const_type const_type;
- };
- };
- } // namespace detail
- template <> struct vertex_property_selector< subgraph_tag >
- {
- typedef detail::subgraph_property_generator type;
- };
- template <> struct edge_property_selector< subgraph_tag >
- {
- typedef detail::subgraph_property_generator type;
- };
- // ==================================================
- // get(p, g), get(p, g, k), and put(p, g, k, v)
- // ==================================================
- template < typename G, typename Property >
- typename property_map< subgraph< G >, Property >::type get(
- Property p, subgraph< G >& g)
- {
- typedef typename property_map< subgraph< G >, Property >::type PMap;
- return PMap(&g, p);
- }
- template < typename G, typename Property >
- typename property_map< subgraph< G >, Property >::const_type get(
- Property p, const subgraph< G >& g)
- {
- typedef typename property_map< subgraph< G >, Property >::const_type PMap;
- return PMap(&g, p);
- }
- template < typename G, typename Property, typename Key >
- typename property_traits<
- typename property_map< subgraph< G >, Property >::const_type >::value_type
- get(Property p, const subgraph< G >& g, const Key& k)
- {
- typedef typename property_map< subgraph< G >, Property >::const_type PMap;
- PMap pmap(&g, p);
- return pmap[k];
- }
- template < typename G, typename Property, typename Key, typename Value >
- void put(Property p, subgraph< G >& g, const Key& k, const Value& val)
- {
- typedef typename property_map< subgraph< G >, Property >::type PMap;
- PMap pmap(&g, p);
- pmap[k] = val;
- }
- // ==================================================
- // get(global(p), g)
- // NOTE: get(global(p), g, k) and put(global(p), g, k, v) not supported
- // ==================================================
- template < typename G, typename Property >
- typename property_map< subgraph< G >, global_property< Property > >::type get(
- global_property< Property > p, subgraph< G >& g)
- {
- typedef typename property_map< subgraph< G >,
- global_property< Property > >::type Map;
- return Map(&g, p.value);
- }
- template < typename G, typename Property >
- typename property_map< subgraph< G >, global_property< Property > >::const_type
- get(global_property< Property > p, const subgraph< G >& g)
- {
- typedef typename property_map< subgraph< G >,
- global_property< Property > >::const_type Map;
- return Map(&g, p.value);
- }
- // ==================================================
- // get(local(p), g)
- // NOTE: get(local(p), g, k) and put(local(p), g, k, v) not supported
- // ==================================================
- template < typename G, typename Property >
- typename property_map< subgraph< G >, local_property< Property > >::type get(
- local_property< Property > p, subgraph< G >& g)
- {
- typedef
- typename property_map< subgraph< G >, local_property< Property > >::type
- Map;
- return Map(&g, p.value);
- }
- template < typename G, typename Property >
- typename property_map< subgraph< G >, local_property< Property > >::const_type
- get(local_property< Property > p, const subgraph< G >& g)
- {
- typedef typename property_map< subgraph< G >,
- local_property< Property > >::const_type Map;
- return Map(&g, p.value);
- }
- template < typename G, typename Tag >
- inline typename graph_property< G, Tag >::type& get_property(
- subgraph< G >& g, Tag tag)
- {
- return get_property(g.m_graph, tag);
- }
- template < typename G, typename Tag >
- inline const typename graph_property< G, Tag >::type& get_property(
- const subgraph< G >& g, Tag tag)
- {
- return get_property(g.m_graph, tag);
- }
- //===========================================================================
- // Miscellaneous Functions
- template < typename G >
- typename subgraph< G >::vertex_descriptor vertex(
- typename subgraph< G >::vertices_size_type n, const subgraph< G >& g)
- {
- return vertex(n, g.m_graph);
- }
- //===========================================================================
- // Mutability Traits
- // Just pull the mutability traits form the underlying graph. Note that this
- // will probably fail (badly) for labeled graphs.
- template < typename G > struct graph_mutability_traits< subgraph< G > >
- {
- typedef typename graph_mutability_traits< G >::category category;
- };
- } // namespace boost
- #endif // BOOST_SUBGRAPH_HPP
|