subgraph.hpp 43 KB

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