adjacency_list.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. //=======================================================================
  2. // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
  3. // Copyright 2010 Thomas Claveirole
  4. // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Thomas Claveirole
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See
  7. // accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //=======================================================================
  10. #ifndef BOOST_GRAPH_ADJACENCY_LIST_HPP
  11. #define BOOST_GRAPH_ADJACENCY_LIST_HPP
  12. #include <boost/config.hpp>
  13. #include <vector>
  14. #include <list>
  15. #include <set>
  16. #include <boost/unordered_set.hpp>
  17. #if !defined BOOST_NO_SLIST
  18. # ifdef BOOST_SLIST_HEADER
  19. # include BOOST_SLIST_HEADER
  20. # else
  21. # include <slist>
  22. # endif
  23. #endif
  24. #include <boost/scoped_ptr.hpp>
  25. #include <boost/graph/graph_traits.hpp>
  26. #include <boost/graph/graph_mutability_traits.hpp>
  27. #include <boost/graph/graph_selectors.hpp>
  28. #include <boost/property_map/property_map.hpp>
  29. #include <boost/mpl/if.hpp>
  30. #include <boost/mpl/and.hpp>
  31. #include <boost/mpl/not.hpp>
  32. #include <boost/mpl/bool.hpp>
  33. #include <boost/graph/detail/edge.hpp>
  34. #include <boost/type_traits/is_same.hpp>
  35. #include <boost/detail/workaround.hpp>
  36. #include <boost/graph/properties.hpp>
  37. #include <boost/graph/named_graph.hpp>
  38. namespace boost {
  39. //===========================================================================
  40. // Selectors for the VertexList and EdgeList template parameters of
  41. // adjacency_list, and the container_gen traits class which is used
  42. // to map the selectors to the container type used to implement the
  43. // graph.
  44. #if !defined BOOST_NO_SLIST
  45. struct slistS {};
  46. #endif
  47. struct vecS { };
  48. struct listS { };
  49. struct setS { };
  50. struct mapS { };
  51. struct multisetS { };
  52. struct multimapS { };
  53. struct hash_setS { };
  54. struct hash_mapS { };
  55. struct hash_multisetS { };
  56. struct hash_multimapS { };
  57. template <class Selector, class ValueType>
  58. struct container_gen { };
  59. template <class ValueType>
  60. struct container_gen<listS, ValueType> {
  61. typedef std::list<ValueType> type;
  62. };
  63. #if !defined BOOST_NO_SLIST
  64. template <class ValueType>
  65. struct container_gen<slistS, ValueType> {
  66. typedef BOOST_STD_EXTENSION_NAMESPACE::slist<ValueType> type;
  67. };
  68. #endif
  69. template <class ValueType>
  70. struct container_gen<vecS, ValueType> {
  71. typedef std::vector<ValueType> type;
  72. };
  73. template <class ValueType>
  74. struct container_gen<mapS, ValueType> {
  75. typedef std::set<ValueType> type;
  76. };
  77. template <class ValueType>
  78. struct container_gen<setS, ValueType> {
  79. typedef std::set<ValueType> type;
  80. };
  81. template <class ValueType>
  82. struct container_gen<multisetS, ValueType> {
  83. typedef std::multiset<ValueType> type;
  84. };
  85. template <class ValueType>
  86. struct container_gen<multimapS, ValueType> {
  87. typedef std::multiset<ValueType> type;
  88. };
  89. template <class ValueType>
  90. struct container_gen<hash_setS, ValueType> {
  91. typedef boost::unordered_set<ValueType> type;
  92. };
  93. template <class ValueType>
  94. struct container_gen<hash_mapS, ValueType> {
  95. typedef boost::unordered_set<ValueType> type;
  96. };
  97. template <class ValueType>
  98. struct container_gen<hash_multisetS, ValueType> {
  99. typedef boost::unordered_multiset<ValueType> type;
  100. };
  101. template <class ValueType>
  102. struct container_gen<hash_multimapS, ValueType> {
  103. typedef boost::unordered_multiset<ValueType> type;
  104. };
  105. template <class StorageSelector>
  106. struct parallel_edge_traits { };
  107. template <>
  108. struct parallel_edge_traits<vecS> {
  109. typedef allow_parallel_edge_tag type; };
  110. template <>
  111. struct parallel_edge_traits<listS> {
  112. typedef allow_parallel_edge_tag type; };
  113. #if !defined BOOST_NO_SLIST
  114. template <>
  115. struct parallel_edge_traits<slistS> {
  116. typedef allow_parallel_edge_tag type; };
  117. #endif
  118. template <>
  119. struct parallel_edge_traits<setS> {
  120. typedef disallow_parallel_edge_tag type; };
  121. template <>
  122. struct parallel_edge_traits<multisetS> {
  123. typedef allow_parallel_edge_tag type; };
  124. template <>
  125. struct parallel_edge_traits<hash_setS> {
  126. typedef disallow_parallel_edge_tag type;
  127. };
  128. // mapS is obsolete, replaced with setS
  129. template <>
  130. struct parallel_edge_traits<mapS> {
  131. typedef disallow_parallel_edge_tag type; };
  132. template <>
  133. struct parallel_edge_traits<hash_mapS> {
  134. typedef disallow_parallel_edge_tag type;
  135. };
  136. template <>
  137. struct parallel_edge_traits<hash_multisetS> {
  138. typedef allow_parallel_edge_tag type;
  139. };
  140. template <>
  141. struct parallel_edge_traits<hash_multimapS> {
  142. typedef allow_parallel_edge_tag type;
  143. };
  144. namespace detail {
  145. template <class Directed> struct is_random_access {
  146. enum { value = false};
  147. typedef mpl::false_ type;
  148. };
  149. template <>
  150. struct is_random_access<vecS> {
  151. enum { value = true };
  152. typedef mpl::true_ type;
  153. };
  154. } // namespace detail
  155. template <typename Selector> struct is_distributed_selector: mpl::false_ {};
  156. //===========================================================================
  157. // The adjacency_list_traits class, which provides a way to access
  158. // some of the associated types of an adjacency_list type without
  159. // having to first create the adjacency_list type. This is useful
  160. // when trying to create interior vertex or edge properties who's
  161. // value type is a vertex or edge descriptor.
  162. template <class OutEdgeListS = vecS,
  163. class VertexListS = vecS,
  164. class DirectedS = directedS,
  165. class EdgeListS = listS>
  166. struct adjacency_list_traits
  167. {
  168. typedef typename detail::is_random_access<VertexListS>::type
  169. is_rand_access;
  170. typedef typename DirectedS::is_bidir_t is_bidir;
  171. typedef typename DirectedS::is_directed_t is_directed;
  172. typedef typename mpl::if_<is_bidir,
  173. bidirectional_tag,
  174. typename mpl::if_<is_directed,
  175. directed_tag, undirected_tag
  176. >::type
  177. >::type directed_category;
  178. typedef typename parallel_edge_traits<OutEdgeListS>::type
  179. edge_parallel_category;
  180. typedef std::size_t vertices_size_type;
  181. typedef void* vertex_ptr;
  182. typedef typename mpl::if_<is_rand_access,
  183. vertices_size_type, vertex_ptr>::type vertex_descriptor;
  184. typedef detail::edge_desc_impl<directed_category, vertex_descriptor>
  185. edge_descriptor;
  186. private:
  187. // Logic to figure out the edges_size_type
  188. struct dummy {};
  189. typedef typename container_gen<EdgeListS, dummy>::type EdgeContainer;
  190. typedef typename DirectedS::is_bidir_t BidirectionalT;
  191. typedef typename DirectedS::is_directed_t DirectedT;
  192. typedef typename mpl::and_<DirectedT,
  193. typename mpl::not_<BidirectionalT>::type >::type on_edge_storage;
  194. public:
  195. typedef typename mpl::if_<on_edge_storage,
  196. std::size_t, typename EdgeContainer::size_type
  197. >::type edges_size_type;
  198. };
  199. } // namespace boost
  200. #include <boost/graph/detail/adjacency_list.hpp>
  201. namespace boost {
  202. //===========================================================================
  203. // The adjacency_list class.
  204. //
  205. template <class OutEdgeListS = vecS, // a Sequence or an AssociativeContainer
  206. class VertexListS = vecS, // a Sequence or a RandomAccessContainer
  207. class DirectedS = directedS,
  208. class VertexProperty = no_property,
  209. class EdgeProperty = no_property,
  210. class GraphProperty = no_property,
  211. class EdgeListS = listS>
  212. class adjacency_list
  213. : public detail::adj_list_gen<
  214. adjacency_list<OutEdgeListS,VertexListS,DirectedS,
  215. VertexProperty,EdgeProperty,GraphProperty,EdgeListS>,
  216. VertexListS, OutEdgeListS, DirectedS,
  217. VertexProperty, EdgeProperty,
  218. GraphProperty, EdgeListS>::type,
  219. // Support for named vertices
  220. public graph::maybe_named_graph<
  221. adjacency_list<OutEdgeListS,VertexListS,DirectedS,
  222. VertexProperty,EdgeProperty,GraphProperty,EdgeListS>,
  223. typename adjacency_list_traits<OutEdgeListS, VertexListS, DirectedS,
  224. EdgeListS>::vertex_descriptor,
  225. VertexProperty>
  226. {
  227. public:
  228. typedef GraphProperty graph_property_type;
  229. typedef typename lookup_one_property<GraphProperty, graph_bundle_t>::type graph_bundled;
  230. typedef VertexProperty vertex_property_type;
  231. typedef typename lookup_one_property<VertexProperty, vertex_bundle_t>::type vertex_bundled;
  232. typedef EdgeProperty edge_property_type;
  233. typedef typename lookup_one_property<EdgeProperty, edge_bundle_t>::type edge_bundled;
  234. private:
  235. typedef adjacency_list self;
  236. typedef typename detail::adj_list_gen<
  237. self, VertexListS, OutEdgeListS, DirectedS,
  238. vertex_property_type, edge_property_type, GraphProperty, EdgeListS
  239. >::type Base;
  240. public:
  241. typedef typename Base::stored_vertex stored_vertex;
  242. typedef typename Base::vertices_size_type vertices_size_type;
  243. typedef typename Base::edges_size_type edges_size_type;
  244. typedef typename Base::degree_size_type degree_size_type;
  245. typedef typename Base::vertex_descriptor vertex_descriptor;
  246. typedef typename Base::edge_descriptor edge_descriptor;
  247. typedef OutEdgeListS out_edge_list_selector;
  248. typedef VertexListS vertex_list_selector;
  249. typedef DirectedS directed_selector;
  250. typedef EdgeListS edge_list_selector;
  251. adjacency_list(const GraphProperty& p = GraphProperty())
  252. : m_property(new graph_property_type(p))
  253. { }
  254. adjacency_list(const adjacency_list& x)
  255. : Base(x), m_property(new graph_property_type(*x.m_property))
  256. { }
  257. adjacency_list& operator=(const adjacency_list& x) {
  258. // TBD: probably should give the strong guarantee
  259. if (&x != this) {
  260. Base::operator=(x);
  261. // Copy/swap the ptr since we can't just assign it...
  262. property_ptr p(new graph_property_type(*x.m_property));
  263. m_property.swap(p);
  264. }
  265. return *this;
  266. }
  267. // Required by Mutable Graph
  268. adjacency_list(vertices_size_type num_vertices,
  269. const GraphProperty& p = GraphProperty())
  270. : Base(num_vertices), m_property(new graph_property_type(p))
  271. { }
  272. #if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300
  273. // Required by Iterator Constructible Graph
  274. template <class EdgeIterator>
  275. adjacency_list(EdgeIterator first, EdgeIterator last,
  276. vertices_size_type n,
  277. edges_size_type = 0,
  278. const GraphProperty& p = GraphProperty())
  279. : Base(n, first, last), m_property(new graph_property_type(p))
  280. { }
  281. template <class EdgeIterator, class EdgePropertyIterator>
  282. adjacency_list(EdgeIterator first, EdgeIterator last,
  283. EdgePropertyIterator ep_iter,
  284. vertices_size_type n,
  285. edges_size_type = 0,
  286. const GraphProperty& p = GraphProperty())
  287. : Base(n, first, last, ep_iter), m_property(new graph_property_type(p))
  288. { }
  289. #endif
  290. void swap(adjacency_list& x) {
  291. // Is there a more efficient way to do this?
  292. adjacency_list tmp(x);
  293. x = *this;
  294. *this = tmp;
  295. }
  296. void clear()
  297. {
  298. this->clearing_graph();
  299. Base::clear();
  300. }
  301. #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
  302. // Directly access a vertex or edge bundle
  303. vertex_bundled& operator[](vertex_descriptor v)
  304. { return get(vertex_bundle, *this)[v]; }
  305. const vertex_bundled& operator[](vertex_descriptor v) const
  306. { return get(vertex_bundle, *this)[v]; }
  307. edge_bundled& operator[](edge_descriptor e)
  308. { return get(edge_bundle, *this)[e]; }
  309. const edge_bundled& operator[](edge_descriptor e) const
  310. { return get(edge_bundle, *this)[e]; }
  311. graph_bundled& operator[](graph_bundle_t)
  312. { return get_property(*this); }
  313. graph_bundled const& operator[](graph_bundle_t) const
  314. { return get_property(*this); }
  315. #endif
  316. // protected: (would be protected if friends were more portable)
  317. typedef scoped_ptr<graph_property_type> property_ptr;
  318. property_ptr m_property;
  319. };
  320. #define ADJLIST_PARAMS \
  321. typename OEL, typename VL, typename D, typename VP, typename EP, \
  322. typename GP, typename EL
  323. #define ADJLIST adjacency_list<OEL,VL,D,VP,EP,GP,EL>
  324. template<ADJLIST_PARAMS, typename Tag, typename Value>
  325. inline void set_property(ADJLIST& g, Tag tag, Value const& value) {
  326. get_property_value(*g.m_property, tag) = value;
  327. }
  328. template<ADJLIST_PARAMS, typename Tag>
  329. inline typename graph_property<ADJLIST, Tag>::type&
  330. get_property(ADJLIST& g, Tag tag) {
  331. return get_property_value(*g.m_property, tag);
  332. }
  333. template<ADJLIST_PARAMS, typename Tag>
  334. inline typename graph_property<ADJLIST, Tag>::type const&
  335. get_property(ADJLIST const& g, Tag tag) {
  336. return get_property_value(*g.m_property, tag);
  337. }
  338. // dwa 09/25/00 - needed to be more explicit so reverse_graph would work.
  339. template <class Directed, class Vertex,
  340. class OutEdgeListS,
  341. class VertexListS,
  342. class DirectedS,
  343. class VertexProperty,
  344. class EdgeProperty,
  345. class GraphProperty, class EdgeListS>
  346. inline Vertex
  347. source(const detail::edge_base<Directed,Vertex>& e,
  348. const adjacency_list<OutEdgeListS, VertexListS, DirectedS,
  349. VertexProperty, EdgeProperty, GraphProperty, EdgeListS>&)
  350. {
  351. return e.m_source;
  352. }
  353. template <class Directed, class Vertex, class OutEdgeListS,
  354. class VertexListS, class DirectedS, class VertexProperty,
  355. class EdgeProperty, class GraphProperty, class EdgeListS>
  356. inline Vertex
  357. target(const detail::edge_base<Directed,Vertex>& e,
  358. const adjacency_list<OutEdgeListS, VertexListS, DirectedS,
  359. VertexProperty, EdgeProperty, GraphProperty, EdgeListS>&)
  360. {
  361. return e.m_target;
  362. }
  363. // Mutability Traits
  364. template <ADJLIST_PARAMS>
  365. struct graph_mutability_traits<ADJLIST> {
  366. typedef mutable_property_graph_tag category;
  367. };
  368. // Can't remove vertices from adjacency lists with VL==vecS
  369. template <typename OEL, typename D, typename VP, typename EP, typename GP, typename EL>
  370. struct graph_mutability_traits< adjacency_list<OEL,vecS,D,VP,EP,GP,EL> > {
  371. typedef add_only_property_graph_tag category;
  372. };
  373. #undef ADJLIST_PARAMS
  374. #undef ADJLIST
  375. } // namespace boost
  376. #endif // BOOST_GRAPH_ADJACENCY_LIST_HPP