edge_list.hpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. //=======================================================================
  2. // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
  3. // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
  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. //
  10. #ifndef BOOST_GRAPH_EDGE_LIST_HPP
  11. #define BOOST_GRAPH_EDGE_LIST_HPP
  12. #include <iterator>
  13. #include <boost/config.hpp>
  14. #include <boost/mpl/if.hpp>
  15. #include <boost/mpl/bool.hpp>
  16. #include <boost/range/irange.hpp>
  17. #include <boost/graph/graph_traits.hpp>
  18. #include <boost/graph/properties.hpp>
  19. namespace boost {
  20. //
  21. // The edge_list class is an EdgeListGraph module that is constructed
  22. // from a pair of iterators whose value type is a pair of vertex
  23. // descriptors.
  24. //
  25. // For example:
  26. //
  27. // typedef std::pair<int,int> E;
  28. // list<E> elist;
  29. // ...
  30. // typedef edge_list<list<E>::iterator> Graph;
  31. // Graph g(elist.begin(), elist.end());
  32. //
  33. // If the iterators are random access, then Graph::edge_descriptor
  34. // is of Integral type, otherwise it is a struct, though it is
  35. // convertible to an Integral type.
  36. //
  37. struct edge_list_tag { };
  38. // The implementation class for edge_list.
  39. template <class G, class EdgeIter, class T, class D>
  40. class edge_list_impl
  41. {
  42. public:
  43. typedef D edge_id;
  44. typedef T Vpair;
  45. typedef typename Vpair::first_type V;
  46. typedef V vertex_descriptor;
  47. typedef edge_list_tag graph_tag;
  48. typedef void edge_property_type;
  49. struct edge_descriptor
  50. {
  51. edge_descriptor() { }
  52. edge_descriptor(EdgeIter p, edge_id id) : _ptr(p), _id(id) { }
  53. operator edge_id() { return _id; }
  54. EdgeIter _ptr;
  55. edge_id _id;
  56. };
  57. typedef edge_descriptor E;
  58. struct edge_iterator
  59. {
  60. typedef edge_iterator self;
  61. typedef E value_type;
  62. typedef E& reference;
  63. typedef E* pointer;
  64. typedef std::ptrdiff_t difference_type;
  65. typedef std::input_iterator_tag iterator_category;
  66. edge_iterator() { }
  67. edge_iterator(EdgeIter iter) : _iter(iter), _i(0) { }
  68. E operator*() { return E(_iter, _i); }
  69. self& operator++() { ++_iter; ++_i; return *this; }
  70. self operator++(int) { self t = *this; ++(*this); return t; }
  71. bool operator==(const self& x) { return _iter == x._iter; }
  72. bool operator!=(const self& x) { return _iter != x._iter; }
  73. EdgeIter _iter;
  74. edge_id _i;
  75. };
  76. typedef void out_edge_iterator;
  77. typedef void in_edge_iterator;
  78. typedef void adjacency_iterator;
  79. typedef void vertex_iterator;
  80. };
  81. template <class G, class EI, class T, class D>
  82. std::pair<typename edge_list_impl<G,EI,T,D>::edge_iterator,
  83. typename edge_list_impl<G,EI,T,D>::edge_iterator>
  84. edges(const edge_list_impl<G,EI,T,D>& g_) {
  85. const G& g = static_cast<const G&>(g_);
  86. typedef typename edge_list_impl<G,EI,T,D>::edge_iterator edge_iterator;
  87. return std::make_pair(edge_iterator(g._first), edge_iterator(g._last));
  88. }
  89. template <class G, class EI, class T, class D>
  90. typename edge_list_impl<G,EI,T,D>::vertex_descriptor
  91. source(typename edge_list_impl<G,EI,T,D>::edge_descriptor e,
  92. const edge_list_impl<G,EI,T,D>&) {
  93. return (*e._ptr).first;
  94. }
  95. template <class G, class EI, class T, class D>
  96. typename edge_list_impl<G,EI,T,D>::vertex_descriptor
  97. target(typename edge_list_impl<G,EI,T,D>::edge_descriptor e,
  98. const edge_list_impl<G,EI,T,D>&) {
  99. return (*e._ptr).second;
  100. }
  101. template <class D, class E>
  102. class el_edge_property_map
  103. : public put_get_helper<D, el_edge_property_map<D,E> >{
  104. public:
  105. typedef E key_type;
  106. typedef D value_type;
  107. typedef D reference;
  108. typedef readable_property_map_tag category;
  109. value_type operator[](key_type e) const {
  110. return e._i;
  111. }
  112. };
  113. struct edge_list_edge_property_selector {
  114. template <class Graph, class Property, class Tag>
  115. struct bind_ {
  116. typedef el_edge_property_map<typename Graph::edge_id,
  117. typename Graph::edge_descriptor> type;
  118. typedef type const_type;
  119. };
  120. };
  121. template <>
  122. struct edge_property_selector<edge_list_tag> {
  123. typedef edge_list_edge_property_selector type;
  124. };
  125. template <class G, class EI, class T, class D>
  126. typename property_map< edge_list_impl<G,EI,T,D>, edge_index_t>::type
  127. get(edge_index_t, const edge_list_impl<G,EI,T,D>&) {
  128. typedef typename property_map< edge_list_impl<G,EI,T,D>,
  129. edge_index_t>::type EdgeIndexMap;
  130. return EdgeIndexMap();
  131. }
  132. template <class G, class EI, class T, class D>
  133. inline D
  134. get(edge_index_t, const edge_list_impl<G,EI,T,D>&,
  135. typename edge_list_impl<G,EI,T,D>::edge_descriptor e) {
  136. return e._i;
  137. }
  138. // A specialized implementation for when the iterators are random access.
  139. struct edge_list_ra_tag { };
  140. template <class G, class EdgeIter, class T, class D>
  141. class edge_list_impl_ra
  142. {
  143. public:
  144. typedef D edge_id;
  145. typedef T Vpair;
  146. typedef typename Vpair::first_type V;
  147. typedef edge_list_ra_tag graph_tag;
  148. typedef void edge_property_type;
  149. typedef edge_id edge_descriptor;
  150. typedef V vertex_descriptor;
  151. typedef typename boost::integer_range<edge_id>::iterator edge_iterator;
  152. typedef void out_edge_iterator;
  153. typedef void in_edge_iterator;
  154. typedef void adjacency_iterator;
  155. typedef void vertex_iterator;
  156. };
  157. template <class G, class EI, class T, class D>
  158. std::pair<typename edge_list_impl_ra<G,EI,T,D>::edge_iterator,
  159. typename edge_list_impl_ra<G,EI,T,D>::edge_iterator>
  160. edges(const edge_list_impl_ra<G,EI,T,D>& g_)
  161. {
  162. const G& g = static_cast<const G&>(g_);
  163. typedef typename edge_list_impl_ra<G,EI,T,D>::edge_iterator edge_iterator;
  164. return std::make_pair(edge_iterator(0), edge_iterator(g._last - g._first));
  165. }
  166. template <class G, class EI, class T, class D>
  167. typename edge_list_impl_ra<G,EI,T,D>::vertex_descriptor
  168. source(typename edge_list_impl_ra<G,EI,T,D>::edge_descriptor e,
  169. const edge_list_impl_ra<G,EI,T,D>& g_)
  170. {
  171. const G& g = static_cast<const G&>(g_);
  172. return g._first[e].first;
  173. }
  174. template <class G, class EI, class T, class D>
  175. typename edge_list_impl_ra<G,EI,T,D>::vertex_descriptor
  176. target(typename edge_list_impl_ra<G,EI,T,D>::edge_descriptor e,
  177. const edge_list_impl_ra<G,EI,T,D>& g_)
  178. {
  179. const G& g = static_cast<const G&>(g_);
  180. return g._first[e].second;
  181. }
  182. template <class E>
  183. class el_ra_edge_property_map
  184. : public put_get_helper<E, el_ra_edge_property_map<E> >{
  185. public:
  186. typedef E key_type;
  187. typedef E value_type;
  188. typedef E reference;
  189. typedef readable_property_map_tag category;
  190. value_type operator[](key_type e) const {
  191. return e;
  192. }
  193. };
  194. struct edge_list_ra_edge_property_selector {
  195. template <class Graph, class Property, class Tag>
  196. struct bind_ {
  197. typedef el_ra_edge_property_map<typename Graph::edge_descriptor> type;
  198. typedef type const_type;
  199. };
  200. };
  201. template <>
  202. struct edge_property_selector<edge_list_ra_tag> {
  203. typedef edge_list_ra_edge_property_selector type;
  204. };
  205. template <class G, class EI, class T, class D>
  206. inline
  207. typename property_map< edge_list_impl_ra<G,EI,T,D>, edge_index_t>::type
  208. get(edge_index_t, const edge_list_impl_ra<G,EI,T,D>&) {
  209. typedef typename property_map< edge_list_impl_ra<G,EI,T,D>,
  210. edge_index_t>::type EdgeIndexMap;
  211. return EdgeIndexMap();
  212. }
  213. template <class G, class EI, class T, class D>
  214. inline D
  215. get(edge_index_t, const edge_list_impl_ra<G,EI,T,D>&,
  216. typename edge_list_impl_ra<G,EI,T,D>::edge_descriptor e) {
  217. return e;
  218. }
  219. // Some helper classes for determining if the iterators are random access
  220. template <class Cat>
  221. struct is_random {
  222. enum { RET = false };
  223. typedef mpl::false_ type;
  224. };
  225. template <>
  226. struct is_random<std::random_access_iterator_tag> {
  227. enum { RET = true }; typedef mpl::true_ type;
  228. };
  229. // The edge_list class conditionally inherits from one of the
  230. // above two classes.
  231. template <class EdgeIter,
  232. #if !defined BOOST_NO_STD_ITERATOR_TRAITS
  233. class T = typename std::iterator_traits<EdgeIter>::value_type,
  234. class D = typename std::iterator_traits<EdgeIter>::difference_type,
  235. class Cat = typename std::iterator_traits<EdgeIter>::iterator_category>
  236. #else
  237. class T,
  238. class D,
  239. class Cat>
  240. #endif
  241. class edge_list
  242. : public mpl::if_< typename is_random<Cat>::type,
  243. edge_list_impl_ra< edge_list<EdgeIter,T,D,Cat>, EdgeIter,T,D>,
  244. edge_list_impl< edge_list<EdgeIter,T,D,Cat>, EdgeIter,T,D>
  245. >::type
  246. {
  247. public:
  248. typedef directed_tag directed_category;
  249. typedef allow_parallel_edge_tag edge_parallel_category;
  250. typedef edge_list_graph_tag traversal_category;
  251. typedef std::size_t edges_size_type;
  252. typedef std::size_t vertices_size_type;
  253. typedef std::size_t degree_size_type;
  254. edge_list(EdgeIter first, EdgeIter last) : _first(first), _last(last) {
  255. m_num_edges = std::distance(first, last);
  256. }
  257. edge_list(EdgeIter first, EdgeIter last, edges_size_type E)
  258. : _first(first), _last(last), m_num_edges(E) { }
  259. EdgeIter _first, _last;
  260. edges_size_type m_num_edges;
  261. };
  262. template <class EdgeIter, class T, class D, class Cat>
  263. std::size_t num_edges(const edge_list<EdgeIter, T, D, Cat>& el) {
  264. return el.m_num_edges;
  265. }
  266. #ifndef BOOST_NO_STD_ITERATOR_TRAITS
  267. template <class EdgeIter>
  268. inline edge_list<EdgeIter>
  269. make_edge_list(EdgeIter first, EdgeIter last)
  270. {
  271. return edge_list<EdgeIter>(first, last);
  272. }
  273. #endif
  274. } /* namespace boost */
  275. #endif /* BOOST_GRAPH_EDGE_LIST_HPP */