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