adjacency_list.hpp 14 KB

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