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