Chris@16
|
1 // -*- c++ -*-
|
Chris@16
|
2 //=======================================================================
|
Chris@16
|
3 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
Chris@16
|
4 // Copyright 2010 Thomas Claveirole
|
Chris@16
|
5 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Thomas Claveirole
|
Chris@16
|
6 //
|
Chris@16
|
7 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
8 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
9 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
10 //=======================================================================
|
Chris@16
|
11
|
Chris@16
|
12 #ifndef BOOST_GRAPH_DETAIL_ADJACENCY_LIST_HPP
|
Chris@16
|
13 #define BOOST_GRAPH_DETAIL_ADJACENCY_LIST_HPP
|
Chris@16
|
14
|
Chris@16
|
15 #include <map> // for vertex_map in copy_impl
|
Chris@16
|
16 #include <boost/config.hpp>
|
Chris@16
|
17 #include <boost/detail/workaround.hpp>
|
Chris@16
|
18 #include <boost/operators.hpp>
|
Chris@16
|
19 #include <boost/property_map/property_map.hpp>
|
Chris@16
|
20 #include <boost/pending/container_traits.hpp>
|
Chris@16
|
21 #include <boost/range/irange.hpp>
|
Chris@16
|
22 #include <boost/graph/graph_traits.hpp>
|
Chris@16
|
23 #include <memory>
|
Chris@16
|
24 #include <algorithm>
|
Chris@16
|
25 #include <boost/limits.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 #include <boost/iterator/iterator_adaptor.hpp>
|
Chris@16
|
28
|
Chris@16
|
29 #include <boost/mpl/if.hpp>
|
Chris@16
|
30 #include <boost/mpl/not.hpp>
|
Chris@16
|
31 #include <boost/mpl/and.hpp>
|
Chris@16
|
32 #include <boost/graph/graph_concepts.hpp>
|
Chris@16
|
33 #include <boost/pending/container_traits.hpp>
|
Chris@16
|
34 #include <boost/graph/detail/adj_list_edge_iterator.hpp>
|
Chris@16
|
35 #include <boost/graph/properties.hpp>
|
Chris@16
|
36 #include <boost/pending/property.hpp>
|
Chris@16
|
37 #include <boost/graph/adjacency_iterator.hpp>
|
Chris@16
|
38 #include <boost/static_assert.hpp>
|
Chris@16
|
39 #include <boost/assert.hpp>
|
Chris@16
|
40
|
Chris@101
|
41 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@101
|
42 #define BOOST_GRAPH_MOVE_IF_POSSIBLE(x) (x)
|
Chris@101
|
43 #else
|
Chris@101
|
44 #include <utility>
|
Chris@101
|
45 #define BOOST_GRAPH_MOVE_IF_POSSIBLE(x) (std::move((x)))
|
Chris@101
|
46 #endif
|
Chris@101
|
47
|
Chris@16
|
48 /*
|
Chris@16
|
49 Outline for this file:
|
Chris@16
|
50
|
Chris@16
|
51 out_edge_iterator and in_edge_iterator implementation
|
Chris@16
|
52 edge_iterator for undirected graph
|
Chris@16
|
53 stored edge types (these object live in the out-edge/in-edge lists)
|
Chris@16
|
54 directed edges helper class
|
Chris@16
|
55 directed graph helper class
|
Chris@16
|
56 undirected graph helper class
|
Chris@16
|
57 bidirectional graph helper class
|
Chris@16
|
58 bidirectional graph helper class (without edge properties)
|
Chris@16
|
59 bidirectional graph helper class (with edge properties)
|
Chris@16
|
60 adjacency_list helper class
|
Chris@16
|
61 adj_list_impl class
|
Chris@16
|
62 vec_adj_list_impl class
|
Chris@16
|
63 adj_list_gen class
|
Chris@16
|
64 vertex property map
|
Chris@16
|
65 edge property map
|
Chris@16
|
66
|
Chris@16
|
67
|
Chris@16
|
68 Note: it would be nice to merge some of the undirected and
|
Chris@16
|
69 bidirectional code... it is awful similar.
|
Chris@16
|
70 */
|
Chris@16
|
71
|
Chris@16
|
72
|
Chris@16
|
73 namespace boost {
|
Chris@16
|
74
|
Chris@16
|
75 namespace detail {
|
Chris@16
|
76
|
Chris@16
|
77 template <typename DirectedS>
|
Chris@16
|
78 struct directed_category_traits {
|
Chris@16
|
79 typedef directed_tag directed_category;
|
Chris@16
|
80 };
|
Chris@16
|
81
|
Chris@16
|
82 template <>
|
Chris@16
|
83 struct directed_category_traits<directedS> {
|
Chris@16
|
84 typedef directed_tag directed_category;
|
Chris@16
|
85 };
|
Chris@16
|
86 template <>
|
Chris@16
|
87 struct directed_category_traits<undirectedS> {
|
Chris@16
|
88 typedef undirected_tag directed_category;
|
Chris@16
|
89 };
|
Chris@16
|
90 template <>
|
Chris@16
|
91 struct directed_category_traits<bidirectionalS> {
|
Chris@16
|
92 typedef bidirectional_tag directed_category;
|
Chris@16
|
93 };
|
Chris@16
|
94
|
Chris@16
|
95 template <class Vertex>
|
Chris@16
|
96 struct target_is {
|
Chris@16
|
97 target_is(const Vertex& v) : m_target(v) { }
|
Chris@16
|
98 template <class StoredEdge>
|
Chris@16
|
99 bool operator()(const StoredEdge& e) const {
|
Chris@16
|
100 return e.get_target() == m_target;
|
Chris@16
|
101 }
|
Chris@16
|
102 Vertex m_target;
|
Chris@16
|
103 };
|
Chris@16
|
104
|
Chris@16
|
105 // O(E/V)
|
Chris@16
|
106 template <class EdgeList, class vertex_descriptor>
|
Chris@16
|
107 void erase_from_incidence_list(EdgeList& el, vertex_descriptor v,
|
Chris@16
|
108 allow_parallel_edge_tag)
|
Chris@16
|
109 {
|
Chris@16
|
110 boost::graph_detail::erase_if(el, detail::target_is<vertex_descriptor>(v));
|
Chris@16
|
111 }
|
Chris@16
|
112 // O(log(E/V))
|
Chris@16
|
113 template <class EdgeList, class vertex_descriptor>
|
Chris@16
|
114 void erase_from_incidence_list(EdgeList& el, vertex_descriptor v,
|
Chris@16
|
115 disallow_parallel_edge_tag)
|
Chris@16
|
116 {
|
Chris@16
|
117 typedef typename EdgeList::value_type StoredEdge;
|
Chris@16
|
118 el.erase(StoredEdge(v));
|
Chris@16
|
119 }
|
Chris@16
|
120
|
Chris@16
|
121 //=========================================================================
|
Chris@16
|
122 // Out-Edge and In-Edge Iterator Implementation
|
Chris@16
|
123
|
Chris@16
|
124 template <class BaseIter, class VertexDescriptor, class EdgeDescriptor, class Difference>
|
Chris@16
|
125 struct out_edge_iter
|
Chris@16
|
126 : iterator_adaptor<
|
Chris@16
|
127 out_edge_iter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>
|
Chris@16
|
128 , BaseIter
|
Chris@16
|
129 , EdgeDescriptor
|
Chris@16
|
130 , use_default
|
Chris@16
|
131 , EdgeDescriptor
|
Chris@16
|
132 , Difference
|
Chris@16
|
133 >
|
Chris@16
|
134 {
|
Chris@16
|
135 typedef iterator_adaptor<
|
Chris@16
|
136 out_edge_iter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>
|
Chris@16
|
137 , BaseIter
|
Chris@16
|
138 , EdgeDescriptor
|
Chris@16
|
139 , use_default
|
Chris@16
|
140 , EdgeDescriptor
|
Chris@16
|
141 , Difference
|
Chris@16
|
142 > super_t;
|
Chris@16
|
143
|
Chris@16
|
144 inline out_edge_iter() { }
|
Chris@16
|
145 inline out_edge_iter(const BaseIter& i, const VertexDescriptor& src)
|
Chris@16
|
146 : super_t(i), m_src(src) { }
|
Chris@16
|
147
|
Chris@16
|
148 inline EdgeDescriptor
|
Chris@16
|
149 dereference() const
|
Chris@16
|
150 {
|
Chris@16
|
151 return EdgeDescriptor(m_src, (*this->base()).get_target(),
|
Chris@16
|
152 &(*this->base()).get_property());
|
Chris@16
|
153 }
|
Chris@16
|
154 VertexDescriptor m_src;
|
Chris@16
|
155 };
|
Chris@16
|
156
|
Chris@16
|
157 template <class BaseIter, class VertexDescriptor, class EdgeDescriptor, class Difference>
|
Chris@16
|
158 struct in_edge_iter
|
Chris@16
|
159 : iterator_adaptor<
|
Chris@16
|
160 in_edge_iter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>
|
Chris@16
|
161 , BaseIter
|
Chris@16
|
162 , EdgeDescriptor
|
Chris@16
|
163 , use_default
|
Chris@16
|
164 , EdgeDescriptor
|
Chris@16
|
165 , Difference
|
Chris@16
|
166 >
|
Chris@16
|
167 {
|
Chris@16
|
168 typedef iterator_adaptor<
|
Chris@16
|
169 in_edge_iter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>
|
Chris@16
|
170 , BaseIter
|
Chris@16
|
171 , EdgeDescriptor
|
Chris@16
|
172 , use_default
|
Chris@16
|
173 , EdgeDescriptor
|
Chris@16
|
174 , Difference
|
Chris@16
|
175 > super_t;
|
Chris@16
|
176
|
Chris@16
|
177 inline in_edge_iter() { }
|
Chris@16
|
178 inline in_edge_iter(const BaseIter& i, const VertexDescriptor& src)
|
Chris@16
|
179 : super_t(i), m_src(src) { }
|
Chris@16
|
180
|
Chris@16
|
181 inline EdgeDescriptor
|
Chris@16
|
182 dereference() const
|
Chris@16
|
183 {
|
Chris@16
|
184 return EdgeDescriptor((*this->base()).get_target(), m_src,
|
Chris@16
|
185 &this->base()->get_property());
|
Chris@16
|
186 }
|
Chris@16
|
187 VertexDescriptor m_src;
|
Chris@16
|
188 };
|
Chris@16
|
189
|
Chris@16
|
190 //=========================================================================
|
Chris@16
|
191 // Undirected Edge Iterator Implementation
|
Chris@16
|
192
|
Chris@16
|
193 template <class EdgeIter, class EdgeDescriptor, class Difference>
|
Chris@16
|
194 struct undirected_edge_iter
|
Chris@16
|
195 : iterator_adaptor<
|
Chris@16
|
196 undirected_edge_iter<EdgeIter, EdgeDescriptor, Difference>
|
Chris@16
|
197 , EdgeIter
|
Chris@16
|
198 , EdgeDescriptor
|
Chris@16
|
199 , use_default
|
Chris@16
|
200 , EdgeDescriptor
|
Chris@16
|
201 , Difference
|
Chris@16
|
202 >
|
Chris@16
|
203 {
|
Chris@16
|
204 typedef iterator_adaptor<
|
Chris@16
|
205 undirected_edge_iter<EdgeIter, EdgeDescriptor, Difference>
|
Chris@16
|
206 , EdgeIter
|
Chris@16
|
207 , EdgeDescriptor
|
Chris@16
|
208 , use_default
|
Chris@16
|
209 , EdgeDescriptor
|
Chris@16
|
210 , Difference
|
Chris@16
|
211 > super_t;
|
Chris@16
|
212
|
Chris@16
|
213 undirected_edge_iter() {}
|
Chris@16
|
214
|
Chris@16
|
215 explicit undirected_edge_iter(EdgeIter i)
|
Chris@16
|
216 : super_t(i) {}
|
Chris@16
|
217
|
Chris@16
|
218 inline EdgeDescriptor
|
Chris@16
|
219 dereference() const {
|
Chris@16
|
220 return EdgeDescriptor(
|
Chris@16
|
221 (*this->base()).m_source
|
Chris@16
|
222 , (*this->base()).m_target
|
Chris@16
|
223 , &this->base()->get_property());
|
Chris@16
|
224 }
|
Chris@16
|
225 };
|
Chris@16
|
226
|
Chris@16
|
227 //=========================================================================
|
Chris@16
|
228 // Edge Storage Types (stored in the out-edge/in-edge lists)
|
Chris@16
|
229
|
Chris@16
|
230 template <class Vertex>
|
Chris@16
|
231 class stored_edge
|
Chris@16
|
232 : public boost::equality_comparable1< stored_edge<Vertex>,
|
Chris@16
|
233 boost::less_than_comparable1< stored_edge<Vertex> > >
|
Chris@16
|
234 {
|
Chris@16
|
235 public:
|
Chris@16
|
236 typedef no_property property_type;
|
Chris@16
|
237 inline stored_edge() { }
|
Chris@16
|
238 inline stored_edge(Vertex target, const no_property& = no_property())
|
Chris@16
|
239 : m_target(target) { }
|
Chris@16
|
240 // Need to write this explicitly so stored_edge_property can
|
Chris@16
|
241 // invoke Base::operator= (at least, for SGI MIPSPro compiler)
|
Chris@16
|
242 inline stored_edge& operator=(const stored_edge& x) {
|
Chris@16
|
243 m_target = x.m_target;
|
Chris@16
|
244 return *this;
|
Chris@16
|
245 }
|
Chris@16
|
246 inline Vertex& get_target() const { return m_target; }
|
Chris@16
|
247 inline const no_property& get_property() const { return s_prop; }
|
Chris@16
|
248 inline bool operator==(const stored_edge& x) const
|
Chris@16
|
249 { return m_target == x.get_target(); }
|
Chris@16
|
250 inline bool operator<(const stored_edge& x) const
|
Chris@16
|
251 { return m_target < x.get_target(); }
|
Chris@16
|
252 //protected: need to add hash<> as a friend
|
Chris@16
|
253 static no_property s_prop;
|
Chris@16
|
254 // Sometimes target not used as key in the set, and in that case
|
Chris@16
|
255 // it is ok to change the target.
|
Chris@16
|
256 mutable Vertex m_target;
|
Chris@16
|
257 };
|
Chris@16
|
258 template <class Vertex>
|
Chris@16
|
259 no_property stored_edge<Vertex>::s_prop;
|
Chris@16
|
260
|
Chris@101
|
261 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
|
Chris@16
|
262 template <class Vertex, class Property>
|
Chris@16
|
263 class stored_edge_property : public stored_edge<Vertex> {
|
Chris@16
|
264 typedef stored_edge_property self;
|
Chris@16
|
265 typedef stored_edge<Vertex> Base;
|
Chris@16
|
266 public:
|
Chris@16
|
267 typedef Property property_type;
|
Chris@16
|
268 inline stored_edge_property() { }
|
Chris@16
|
269 inline stored_edge_property(Vertex target,
|
Chris@16
|
270 const Property& p = Property())
|
Chris@16
|
271 : stored_edge<Vertex>(target), m_property(new Property(p)) { }
|
Chris@16
|
272 stored_edge_property(const self& x)
|
Chris@16
|
273 : Base(x), m_property(const_cast<self&>(x).m_property) { }
|
Chris@16
|
274 self& operator=(const self& x) {
|
Chris@16
|
275 Base::operator=(x);
|
Chris@16
|
276 m_property = const_cast<self&>(x).m_property;
|
Chris@16
|
277 return *this;
|
Chris@16
|
278 }
|
Chris@16
|
279 inline Property& get_property() { return *m_property; }
|
Chris@16
|
280 inline const Property& get_property() const { return *m_property; }
|
Chris@16
|
281 protected:
|
Chris@16
|
282 // Holding the property by-value causes edge-descriptor
|
Chris@16
|
283 // invalidation for add_edge() with EdgeList=vecS. Instead we
|
Chris@16
|
284 // hold a pointer to the property. std::auto_ptr is not
|
Chris@16
|
285 // a perfect fit for the job, but it is darn close.
|
Chris@16
|
286 std::auto_ptr<Property> m_property;
|
Chris@16
|
287 };
|
Chris@101
|
288 #else
|
Chris@101
|
289 template <class Vertex, class Property>
|
Chris@101
|
290 class stored_edge_property : public stored_edge<Vertex> {
|
Chris@101
|
291 typedef stored_edge_property self;
|
Chris@101
|
292 typedef stored_edge<Vertex> Base;
|
Chris@101
|
293 public:
|
Chris@101
|
294 typedef Property property_type;
|
Chris@101
|
295 inline stored_edge_property() { }
|
Chris@101
|
296 inline stored_edge_property(Vertex target,
|
Chris@101
|
297 const Property& p = Property())
|
Chris@101
|
298 : stored_edge<Vertex>(target), m_property(new Property(p)) { }
|
Chris@101
|
299 #if defined(BOOST_MSVC) || (defined(BOOST_GCC) && (BOOST_GCC / 100) < 406)
|
Chris@101
|
300 stored_edge_property(self&& x) : Base(static_cast< Base const& >(x)) {
|
Chris@101
|
301 m_property.swap(x.m_property);
|
Chris@101
|
302 }
|
Chris@101
|
303 stored_edge_property(self const& x) : Base(static_cast< Base const& >(x)) {
|
Chris@101
|
304 m_property.swap(const_cast<self&>(x).m_property);
|
Chris@101
|
305 }
|
Chris@101
|
306 self& operator=(self&& x) {
|
Chris@101
|
307 Base::operator=(static_cast< Base const& >(x));
|
Chris@101
|
308 m_property = std::move(x.m_property);
|
Chris@101
|
309 return *this;
|
Chris@101
|
310 }
|
Chris@101
|
311 self& operator=(self const& x) {
|
Chris@101
|
312 Base::operator=(static_cast< Base const& >(x));
|
Chris@101
|
313 m_property = std::move(const_cast<self&>(x).m_property);
|
Chris@101
|
314 return *this;
|
Chris@101
|
315 }
|
Chris@101
|
316 #else
|
Chris@101
|
317 stored_edge_property(self&& x) = default;
|
Chris@101
|
318 self& operator=(self&& x) = default;
|
Chris@101
|
319 #endif
|
Chris@101
|
320 inline Property& get_property() { return *m_property; }
|
Chris@101
|
321 inline const Property& get_property() const { return *m_property; }
|
Chris@101
|
322 protected:
|
Chris@101
|
323 std::unique_ptr<Property> m_property;
|
Chris@101
|
324 };
|
Chris@101
|
325 #endif
|
Chris@16
|
326
|
Chris@16
|
327
|
Chris@16
|
328 template <class Vertex, class Iter, class Property>
|
Chris@16
|
329 class stored_edge_iter
|
Chris@16
|
330 : public stored_edge<Vertex>
|
Chris@16
|
331 {
|
Chris@16
|
332 public:
|
Chris@16
|
333 typedef Property property_type;
|
Chris@16
|
334 inline stored_edge_iter() { }
|
Chris@16
|
335 inline stored_edge_iter(Vertex v)
|
Chris@16
|
336 : stored_edge<Vertex>(v) { }
|
Chris@16
|
337 inline stored_edge_iter(Vertex v, Iter i, void* = 0)
|
Chris@16
|
338 : stored_edge<Vertex>(v), m_iter(i) { }
|
Chris@16
|
339 inline Property& get_property() { return m_iter->get_property(); }
|
Chris@16
|
340 inline const Property& get_property() const {
|
Chris@16
|
341 return m_iter->get_property();
|
Chris@16
|
342 }
|
Chris@16
|
343 inline Iter get_iter() const { return m_iter; }
|
Chris@16
|
344 protected:
|
Chris@16
|
345 Iter m_iter;
|
Chris@16
|
346 };
|
Chris@16
|
347
|
Chris@16
|
348 // For when the EdgeList is a std::vector.
|
Chris@16
|
349 // Want to make the iterator stable, so use an offset
|
Chris@16
|
350 // instead of an iterator into a std::vector
|
Chris@16
|
351 template <class Vertex, class EdgeVec, class Property>
|
Chris@16
|
352 class stored_ra_edge_iter
|
Chris@16
|
353 : public stored_edge<Vertex>
|
Chris@16
|
354 {
|
Chris@16
|
355 typedef typename EdgeVec::iterator Iter;
|
Chris@16
|
356 public:
|
Chris@16
|
357 typedef Property property_type;
|
Chris@16
|
358 inline stored_ra_edge_iter() { }
|
Chris@16
|
359 inline explicit stored_ra_edge_iter(Vertex v) // Only used for comparisons
|
Chris@16
|
360 : stored_edge<Vertex>(v), m_i(0), m_vec(0){ }
|
Chris@16
|
361 inline stored_ra_edge_iter(Vertex v, Iter i, EdgeVec* edge_vec)
|
Chris@16
|
362 : stored_edge<Vertex>(v), m_i(i - edge_vec->begin()), m_vec(edge_vec){ }
|
Chris@16
|
363 inline Property& get_property() { BOOST_ASSERT ((m_vec != 0)); return (*m_vec)[m_i].get_property(); }
|
Chris@16
|
364 inline const Property& get_property() const {
|
Chris@16
|
365 BOOST_ASSERT ((m_vec != 0));
|
Chris@16
|
366 return (*m_vec)[m_i].get_property();
|
Chris@16
|
367 }
|
Chris@16
|
368 inline Iter get_iter() const { BOOST_ASSERT ((m_vec != 0)); return m_vec->begin() + m_i; }
|
Chris@16
|
369 protected:
|
Chris@16
|
370 std::size_t m_i;
|
Chris@16
|
371 EdgeVec* m_vec;
|
Chris@16
|
372 };
|
Chris@16
|
373
|
Chris@16
|
374 } // namespace detail
|
Chris@16
|
375
|
Chris@16
|
376 template <class Tag, class Vertex, class Property>
|
Chris@16
|
377 const typename property_value<Property,Tag>::type&
|
Chris@16
|
378 get(Tag property_tag,
|
Chris@16
|
379 const detail::stored_edge_property<Vertex, Property>& e)
|
Chris@16
|
380 {
|
Chris@16
|
381 return get_property_value(e.get_property(), property_tag);
|
Chris@16
|
382 }
|
Chris@16
|
383
|
Chris@16
|
384 template <class Tag, class Vertex, class Iter, class Property>
|
Chris@16
|
385 const typename property_value<Property,Tag>::type&
|
Chris@16
|
386 get(Tag property_tag,
|
Chris@16
|
387 const detail::stored_edge_iter<Vertex, Iter, Property>& e)
|
Chris@16
|
388 {
|
Chris@16
|
389 return get_property_value(e.get_property(), property_tag);
|
Chris@16
|
390 }
|
Chris@16
|
391
|
Chris@16
|
392 template <class Tag, class Vertex, class EdgeVec, class Property>
|
Chris@16
|
393 const typename property_value<Property,Tag>::type&
|
Chris@16
|
394 get(Tag property_tag,
|
Chris@16
|
395 const detail::stored_ra_edge_iter<Vertex, EdgeVec, Property>& e)
|
Chris@16
|
396 {
|
Chris@16
|
397 return get_property_value(e.get_property(), property_tag);
|
Chris@16
|
398 }
|
Chris@16
|
399
|
Chris@16
|
400 //=========================================================================
|
Chris@16
|
401 // Directed Edges Helper Class
|
Chris@16
|
402
|
Chris@16
|
403 namespace detail {
|
Chris@16
|
404
|
Chris@16
|
405 // O(E/V)
|
Chris@16
|
406 template <class edge_descriptor, class EdgeList, class StoredProperty>
|
Chris@16
|
407 inline void
|
Chris@16
|
408 remove_directed_edge_dispatch(edge_descriptor, EdgeList& el,
|
Chris@16
|
409 StoredProperty& p)
|
Chris@16
|
410 {
|
Chris@16
|
411 for (typename EdgeList::iterator i = el.begin();
|
Chris@16
|
412 i != el.end(); ++i)
|
Chris@16
|
413 if (&(*i).get_property() == &p) {
|
Chris@16
|
414 el.erase(i);
|
Chris@16
|
415 return;
|
Chris@16
|
416 }
|
Chris@16
|
417 }
|
Chris@16
|
418
|
Chris@16
|
419 template <class incidence_iterator, class EdgeList, class Predicate>
|
Chris@16
|
420 inline void
|
Chris@16
|
421 remove_directed_edge_if_dispatch(incidence_iterator first,
|
Chris@16
|
422 incidence_iterator last,
|
Chris@16
|
423 EdgeList& el, Predicate pred,
|
Chris@16
|
424 boost::allow_parallel_edge_tag)
|
Chris@16
|
425 {
|
Chris@16
|
426 // remove_if
|
Chris@16
|
427 while (first != last && !pred(*first))
|
Chris@16
|
428 ++first;
|
Chris@16
|
429 incidence_iterator i = first;
|
Chris@16
|
430 if (first != last)
|
Chris@16
|
431 for (++i; i != last; ++i)
|
Chris@16
|
432 if (!pred(*i)) {
|
Chris@101
|
433 *first.base() = BOOST_GRAPH_MOVE_IF_POSSIBLE(*i.base());
|
Chris@16
|
434 ++first;
|
Chris@16
|
435 }
|
Chris@16
|
436 el.erase(first.base(), el.end());
|
Chris@16
|
437 }
|
Chris@16
|
438 template <class incidence_iterator, class EdgeList, class Predicate>
|
Chris@16
|
439 inline void
|
Chris@16
|
440 remove_directed_edge_if_dispatch(incidence_iterator first,
|
Chris@16
|
441 incidence_iterator last,
|
Chris@16
|
442 EdgeList& el,
|
Chris@16
|
443 Predicate pred,
|
Chris@16
|
444 boost::disallow_parallel_edge_tag)
|
Chris@16
|
445 {
|
Chris@16
|
446 for (incidence_iterator next = first;
|
Chris@16
|
447 first != last; first = next) {
|
Chris@16
|
448 ++next;
|
Chris@16
|
449 if (pred(*first))
|
Chris@16
|
450 el.erase( first.base() );
|
Chris@16
|
451 }
|
Chris@16
|
452 }
|
Chris@16
|
453
|
Chris@16
|
454 template <class PropT, class Graph, class incidence_iterator,
|
Chris@16
|
455 class EdgeList, class Predicate>
|
Chris@16
|
456 inline void
|
Chris@16
|
457 undirected_remove_out_edge_if_dispatch(Graph& g,
|
Chris@16
|
458 incidence_iterator first,
|
Chris@16
|
459 incidence_iterator last,
|
Chris@16
|
460 EdgeList& el, Predicate pred,
|
Chris@16
|
461 boost::allow_parallel_edge_tag)
|
Chris@16
|
462 {
|
Chris@16
|
463 typedef typename Graph::global_edgelist_selector EdgeListS;
|
Chris@16
|
464 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
465
|
Chris@16
|
466 // remove_if
|
Chris@16
|
467 while (first != last && !pred(*first))
|
Chris@16
|
468 ++first;
|
Chris@16
|
469 incidence_iterator i = first;
|
Chris@16
|
470 bool self_loop_removed = false;
|
Chris@16
|
471 if (first != last)
|
Chris@16
|
472 for (; i != last; ++i) {
|
Chris@16
|
473 if (self_loop_removed) {
|
Chris@16
|
474 /* With self loops, the descriptor will show up
|
Chris@16
|
475 * twice. The first time it will be removed, and now it
|
Chris@16
|
476 * will be skipped.
|
Chris@16
|
477 */
|
Chris@16
|
478 self_loop_removed = false;
|
Chris@16
|
479 }
|
Chris@16
|
480 else if (!pred(*i)) {
|
Chris@101
|
481 *first.base() = BOOST_GRAPH_MOVE_IF_POSSIBLE(*i.base());
|
Chris@16
|
482 ++first;
|
Chris@16
|
483 } else {
|
Chris@16
|
484 if (source(*i, g) == target(*i, g)) self_loop_removed = true;
|
Chris@16
|
485 else {
|
Chris@16
|
486 // Remove the edge from the target
|
Chris@16
|
487 detail::remove_directed_edge_dispatch
|
Chris@16
|
488 (*i,
|
Chris@16
|
489 g.out_edge_list(target(*i, g)),
|
Chris@16
|
490 *(PropT*)(*i).get_property());
|
Chris@16
|
491 }
|
Chris@16
|
492
|
Chris@16
|
493 // Erase the edge property
|
Chris@16
|
494 g.m_edges.erase( (*i.base()).get_iter() );
|
Chris@16
|
495 }
|
Chris@16
|
496 }
|
Chris@16
|
497 el.erase(first.base(), el.end());
|
Chris@16
|
498 }
|
Chris@16
|
499 template <class PropT, class Graph, class incidence_iterator,
|
Chris@16
|
500 class EdgeList, class Predicate>
|
Chris@16
|
501 inline void
|
Chris@16
|
502 undirected_remove_out_edge_if_dispatch(Graph& g,
|
Chris@16
|
503 incidence_iterator first,
|
Chris@16
|
504 incidence_iterator last,
|
Chris@16
|
505 EdgeList& el,
|
Chris@16
|
506 Predicate pred,
|
Chris@16
|
507 boost::disallow_parallel_edge_tag)
|
Chris@16
|
508 {
|
Chris@16
|
509 typedef typename Graph::global_edgelist_selector EdgeListS;
|
Chris@16
|
510 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
511
|
Chris@16
|
512 for (incidence_iterator next = first;
|
Chris@16
|
513 first != last; first = next) {
|
Chris@16
|
514 ++next;
|
Chris@16
|
515 if (pred(*first)) {
|
Chris@16
|
516 if (source(*first, g) != target(*first, g)) {
|
Chris@16
|
517 // Remove the edge from the target
|
Chris@16
|
518 detail::remove_directed_edge_dispatch
|
Chris@16
|
519 (*first,
|
Chris@16
|
520 g.out_edge_list(target(*first, g)),
|
Chris@16
|
521 *(PropT*)(*first).get_property());
|
Chris@16
|
522 }
|
Chris@16
|
523
|
Chris@16
|
524 // Erase the edge property
|
Chris@16
|
525 g.m_edges.erase( (*first.base()).get_iter() );
|
Chris@16
|
526
|
Chris@16
|
527 // Erase the edge in the source
|
Chris@16
|
528 el.erase( first.base() );
|
Chris@16
|
529 }
|
Chris@16
|
530 }
|
Chris@16
|
531 }
|
Chris@16
|
532
|
Chris@16
|
533 // O(E/V)
|
Chris@16
|
534 template <class edge_descriptor, class EdgeList, class StoredProperty>
|
Chris@16
|
535 inline void
|
Chris@16
|
536 remove_directed_edge_dispatch(edge_descriptor e, EdgeList& el,
|
Chris@16
|
537 no_property&)
|
Chris@16
|
538 {
|
Chris@16
|
539 for (typename EdgeList::iterator i = el.begin();
|
Chris@16
|
540 i != el.end(); ++i)
|
Chris@16
|
541 if ((*i).get_target() == e.m_target) {
|
Chris@16
|
542 el.erase(i);
|
Chris@16
|
543 return;
|
Chris@16
|
544 }
|
Chris@16
|
545 }
|
Chris@16
|
546
|
Chris@16
|
547 } // namespace detail
|
Chris@16
|
548
|
Chris@16
|
549 template <class Config>
|
Chris@16
|
550 struct directed_edges_helper {
|
Chris@16
|
551
|
Chris@16
|
552 // Placement of these overloaded remove_edge() functions
|
Chris@16
|
553 // inside the class avoids a VC++ bug.
|
Chris@16
|
554
|
Chris@16
|
555 // O(E/V)
|
Chris@16
|
556 inline void
|
Chris@16
|
557 remove_edge(typename Config::edge_descriptor e)
|
Chris@16
|
558 {
|
Chris@16
|
559 typedef typename Config::graph_type graph_type;
|
Chris@16
|
560 graph_type& g = static_cast<graph_type&>(*this);
|
Chris@16
|
561 typename Config::OutEdgeList& el = g.out_edge_list(source(e, g));
|
Chris@16
|
562 typedef typename Config::OutEdgeList::value_type::property_type PType;
|
Chris@16
|
563 detail::remove_directed_edge_dispatch(e, el,
|
Chris@16
|
564 *(PType*)e.get_property());
|
Chris@16
|
565 }
|
Chris@16
|
566
|
Chris@16
|
567 // O(1)
|
Chris@16
|
568 inline void
|
Chris@16
|
569 remove_edge(typename Config::out_edge_iterator iter)
|
Chris@16
|
570 {
|
Chris@16
|
571 typedef typename Config::graph_type graph_type;
|
Chris@16
|
572 graph_type& g = static_cast<graph_type&>(*this);
|
Chris@16
|
573 typename Config::edge_descriptor e = *iter;
|
Chris@16
|
574 typename Config::OutEdgeList& el = g.out_edge_list(source(e, g));
|
Chris@16
|
575 el.erase(iter.base());
|
Chris@16
|
576 }
|
Chris@16
|
577
|
Chris@16
|
578 };
|
Chris@16
|
579
|
Chris@16
|
580 // O(1)
|
Chris@16
|
581 template <class Config>
|
Chris@16
|
582 inline std::pair<typename Config::edge_iterator,
|
Chris@16
|
583 typename Config::edge_iterator>
|
Chris@16
|
584 edges(const directed_edges_helper<Config>& g_)
|
Chris@16
|
585 {
|
Chris@16
|
586 typedef typename Config::graph_type graph_type;
|
Chris@16
|
587 typedef typename Config::edge_iterator edge_iterator;
|
Chris@16
|
588 const graph_type& cg = static_cast<const graph_type&>(g_);
|
Chris@16
|
589 graph_type& g = const_cast<graph_type&>(cg);
|
Chris@16
|
590 return std::make_pair( edge_iterator(g.vertex_set().begin(),
|
Chris@16
|
591 g.vertex_set().begin(),
|
Chris@16
|
592 g.vertex_set().end(), g),
|
Chris@16
|
593 edge_iterator(g.vertex_set().begin(),
|
Chris@16
|
594 g.vertex_set().end(),
|
Chris@16
|
595 g.vertex_set().end(), g) );
|
Chris@16
|
596 }
|
Chris@16
|
597
|
Chris@16
|
598 //=========================================================================
|
Chris@16
|
599 // Directed Graph Helper Class
|
Chris@16
|
600
|
Chris@16
|
601 struct adj_list_dir_traversal_tag :
|
Chris@16
|
602 public virtual vertex_list_graph_tag,
|
Chris@16
|
603 public virtual incidence_graph_tag,
|
Chris@16
|
604 public virtual adjacency_graph_tag,
|
Chris@16
|
605 public virtual edge_list_graph_tag { };
|
Chris@16
|
606
|
Chris@16
|
607 template <class Config>
|
Chris@16
|
608 struct directed_graph_helper
|
Chris@16
|
609 : public directed_edges_helper<Config> {
|
Chris@16
|
610 typedef typename Config::edge_descriptor edge_descriptor;
|
Chris@16
|
611 typedef adj_list_dir_traversal_tag traversal_category;
|
Chris@16
|
612 };
|
Chris@16
|
613
|
Chris@16
|
614 // O(E/V)
|
Chris@16
|
615 template <class Config>
|
Chris@16
|
616 inline void
|
Chris@16
|
617 remove_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
618 typename Config::vertex_descriptor v,
|
Chris@16
|
619 directed_graph_helper<Config>& g_)
|
Chris@16
|
620 {
|
Chris@16
|
621 typedef typename Config::graph_type graph_type;
|
Chris@16
|
622 typedef typename Config::edge_parallel_category Cat;
|
Chris@16
|
623 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
624 detail::erase_from_incidence_list(g.out_edge_list(u), v, Cat());
|
Chris@16
|
625 }
|
Chris@16
|
626
|
Chris@16
|
627 template <class Config, class Predicate>
|
Chris@16
|
628 inline void
|
Chris@16
|
629 remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred,
|
Chris@16
|
630 directed_graph_helper<Config>& g_)
|
Chris@16
|
631 {
|
Chris@16
|
632 typedef typename Config::graph_type graph_type;
|
Chris@16
|
633 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
634 typename Config::out_edge_iterator first, last;
|
Chris@16
|
635 boost::tie(first, last) = out_edges(u, g);
|
Chris@16
|
636 typedef typename Config::edge_parallel_category edge_parallel_category;
|
Chris@16
|
637 detail::remove_directed_edge_if_dispatch
|
Chris@16
|
638 (first, last, g.out_edge_list(u), pred, edge_parallel_category());
|
Chris@16
|
639 }
|
Chris@16
|
640
|
Chris@16
|
641 template <class Config, class Predicate>
|
Chris@16
|
642 inline void
|
Chris@16
|
643 remove_edge_if(Predicate pred, directed_graph_helper<Config>& g_)
|
Chris@16
|
644 {
|
Chris@16
|
645 typedef typename Config::graph_type graph_type;
|
Chris@16
|
646 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
647
|
Chris@16
|
648 typename Config::vertex_iterator vi, vi_end;
|
Chris@16
|
649 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
|
Chris@16
|
650 remove_out_edge_if(*vi, pred, g);
|
Chris@16
|
651 }
|
Chris@16
|
652
|
Chris@16
|
653 template <class EdgeOrIter, class Config>
|
Chris@16
|
654 inline void
|
Chris@16
|
655 remove_edge(EdgeOrIter e_or_iter, directed_graph_helper<Config>& g_)
|
Chris@16
|
656 {
|
Chris@16
|
657 g_.remove_edge(e_or_iter);
|
Chris@16
|
658 }
|
Chris@16
|
659
|
Chris@16
|
660 // O(V + E) for allow_parallel_edges
|
Chris@16
|
661 // O(V * log(E/V)) for disallow_parallel_edges
|
Chris@16
|
662 template <class Config>
|
Chris@16
|
663 inline void
|
Chris@16
|
664 clear_vertex(typename Config::vertex_descriptor u,
|
Chris@16
|
665 directed_graph_helper<Config>& g_)
|
Chris@16
|
666 {
|
Chris@16
|
667 typedef typename Config::graph_type graph_type;
|
Chris@16
|
668 typedef typename Config::edge_parallel_category Cat;
|
Chris@16
|
669 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
670 typename Config::vertex_iterator vi, viend;
|
Chris@16
|
671 for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi)
|
Chris@16
|
672 detail::erase_from_incidence_list(g.out_edge_list(*vi), u, Cat());
|
Chris@16
|
673 g.out_edge_list(u).clear();
|
Chris@16
|
674 // clear() should be a req of Sequence and AssociativeContainer,
|
Chris@16
|
675 // or maybe just Container
|
Chris@16
|
676 }
|
Chris@16
|
677
|
Chris@16
|
678 template <class Config>
|
Chris@16
|
679 inline void
|
Chris@16
|
680 clear_out_edges(typename Config::vertex_descriptor u,
|
Chris@16
|
681 directed_graph_helper<Config>& g_)
|
Chris@16
|
682 {
|
Chris@16
|
683 typedef typename Config::graph_type graph_type;
|
Chris@16
|
684 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
685 g.out_edge_list(u).clear();
|
Chris@16
|
686 // clear() should be a req of Sequence and AssociativeContainer,
|
Chris@16
|
687 // or maybe just Container
|
Chris@16
|
688 }
|
Chris@16
|
689
|
Chris@16
|
690 // O(V), could do better...
|
Chris@16
|
691 template <class Config>
|
Chris@16
|
692 inline typename Config::edges_size_type
|
Chris@16
|
693 num_edges(const directed_graph_helper<Config>& g_)
|
Chris@16
|
694 {
|
Chris@16
|
695 typedef typename Config::graph_type graph_type;
|
Chris@16
|
696 const graph_type& g = static_cast<const graph_type&>(g_);
|
Chris@16
|
697 typename Config::edges_size_type num_e = 0;
|
Chris@16
|
698 typename Config::vertex_iterator vi, vi_end;
|
Chris@16
|
699 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
|
Chris@16
|
700 num_e += out_degree(*vi, g);
|
Chris@16
|
701 return num_e;
|
Chris@16
|
702 }
|
Chris@16
|
703 // O(1) for allow_parallel_edge_tag
|
Chris@16
|
704 // O(log(E/V)) for disallow_parallel_edge_tag
|
Chris@16
|
705 template <class Config>
|
Chris@16
|
706 inline std::pair<typename directed_graph_helper<Config>::edge_descriptor, bool>
|
Chris@16
|
707 add_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
708 typename Config::vertex_descriptor v,
|
Chris@16
|
709 const typename Config::edge_property_type& p,
|
Chris@16
|
710 directed_graph_helper<Config>& g_)
|
Chris@16
|
711 {
|
Chris@16
|
712 typedef typename Config::edge_descriptor edge_descriptor;
|
Chris@16
|
713 typedef typename Config::graph_type graph_type;
|
Chris@16
|
714 typedef typename Config::StoredEdge StoredEdge;
|
Chris@16
|
715 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
716 typename Config::OutEdgeList::iterator i;
|
Chris@16
|
717 bool inserted;
|
Chris@16
|
718 boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u),
|
Chris@16
|
719 StoredEdge(v, p));
|
Chris@16
|
720 return std::make_pair(edge_descriptor(u, v, &(*i).get_property()),
|
Chris@16
|
721 inserted);
|
Chris@16
|
722 }
|
Chris@16
|
723 // Did not use default argument here because that
|
Chris@16
|
724 // causes Visual C++ to get confused.
|
Chris@16
|
725 template <class Config>
|
Chris@16
|
726 inline std::pair<typename Config::edge_descriptor, bool>
|
Chris@16
|
727 add_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
728 typename Config::vertex_descriptor v,
|
Chris@16
|
729 directed_graph_helper<Config>& g_)
|
Chris@16
|
730 {
|
Chris@16
|
731 typename Config::edge_property_type p;
|
Chris@16
|
732 return add_edge(u, v, p, g_);
|
Chris@16
|
733 }
|
Chris@16
|
734 //=========================================================================
|
Chris@16
|
735 // Undirected Graph Helper Class
|
Chris@16
|
736
|
Chris@16
|
737 template <class Config>
|
Chris@16
|
738 struct undirected_graph_helper;
|
Chris@16
|
739
|
Chris@16
|
740 struct undir_adj_list_traversal_tag :
|
Chris@16
|
741 public virtual vertex_list_graph_tag,
|
Chris@16
|
742 public virtual incidence_graph_tag,
|
Chris@16
|
743 public virtual adjacency_graph_tag,
|
Chris@16
|
744 public virtual edge_list_graph_tag,
|
Chris@16
|
745 public virtual bidirectional_graph_tag { };
|
Chris@16
|
746
|
Chris@16
|
747 namespace detail {
|
Chris@16
|
748
|
Chris@16
|
749 // using class with specialization for dispatch is a VC++ workaround.
|
Chris@16
|
750 template <class StoredProperty>
|
Chris@16
|
751 struct remove_undirected_edge_dispatch {
|
Chris@16
|
752
|
Chris@16
|
753 // O(E/V)
|
Chris@16
|
754 template <class edge_descriptor, class Config>
|
Chris@16
|
755 static void
|
Chris@16
|
756 apply(edge_descriptor e,
|
Chris@16
|
757 undirected_graph_helper<Config>& g_,
|
Chris@16
|
758 StoredProperty& p)
|
Chris@16
|
759 {
|
Chris@16
|
760 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
761 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
762
|
Chris@16
|
763 typedef typename Config::graph_type graph_type;
|
Chris@16
|
764 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
765
|
Chris@16
|
766 typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g));
|
Chris@16
|
767 typename Config::OutEdgeList::iterator out_i = out_el.begin();
|
Chris@16
|
768 typename Config::EdgeIter edge_iter_to_erase;
|
Chris@16
|
769 for (; out_i != out_el.end(); ++out_i)
|
Chris@16
|
770 if (&(*out_i).get_property() == &p) {
|
Chris@16
|
771 edge_iter_to_erase = (*out_i).get_iter();
|
Chris@16
|
772 out_el.erase(out_i);
|
Chris@16
|
773 break;
|
Chris@16
|
774 }
|
Chris@16
|
775 typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g));
|
Chris@16
|
776 typename Config::OutEdgeList::iterator in_i = in_el.begin();
|
Chris@16
|
777 for (; in_i != in_el.end(); ++in_i)
|
Chris@16
|
778 if (&(*in_i).get_property() == &p) {
|
Chris@16
|
779 in_el.erase(in_i);
|
Chris@16
|
780 break;
|
Chris@16
|
781 }
|
Chris@16
|
782 g.m_edges.erase(edge_iter_to_erase);
|
Chris@16
|
783 }
|
Chris@16
|
784 };
|
Chris@16
|
785
|
Chris@16
|
786 template <>
|
Chris@16
|
787 struct remove_undirected_edge_dispatch<no_property> {
|
Chris@16
|
788 // O(E/V)
|
Chris@16
|
789 template <class edge_descriptor, class Config>
|
Chris@16
|
790 static void
|
Chris@16
|
791 apply(edge_descriptor e,
|
Chris@16
|
792 undirected_graph_helper<Config>& g_,
|
Chris@16
|
793 no_property&)
|
Chris@16
|
794 {
|
Chris@16
|
795 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
796 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
797
|
Chris@16
|
798 typedef typename Config::graph_type graph_type;
|
Chris@16
|
799 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
800 no_property* p = (no_property*)e.get_property();
|
Chris@16
|
801 typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g));
|
Chris@16
|
802 typename Config::OutEdgeList::iterator out_i = out_el.begin();
|
Chris@16
|
803 typename Config::EdgeIter edge_iter_to_erase;
|
Chris@16
|
804 for (; out_i != out_el.end(); ++out_i)
|
Chris@16
|
805 if (&(*out_i).get_property() == p) {
|
Chris@16
|
806 edge_iter_to_erase = (*out_i).get_iter();
|
Chris@16
|
807 out_el.erase(out_i);
|
Chris@16
|
808 break;
|
Chris@16
|
809 }
|
Chris@16
|
810 typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g));
|
Chris@16
|
811 typename Config::OutEdgeList::iterator in_i = in_el.begin();
|
Chris@16
|
812 for (; in_i != in_el.end(); ++in_i)
|
Chris@16
|
813 if (&(*in_i).get_property() == p) {
|
Chris@16
|
814 in_el.erase(in_i);
|
Chris@16
|
815 break;
|
Chris@16
|
816 }
|
Chris@16
|
817 g.m_edges.erase(edge_iter_to_erase);
|
Chris@16
|
818 }
|
Chris@16
|
819 };
|
Chris@16
|
820
|
Chris@16
|
821 // O(E/V)
|
Chris@16
|
822 template <class Graph, class EdgeList, class Vertex>
|
Chris@16
|
823 inline void
|
Chris@16
|
824 remove_edge_and_property(Graph& g, EdgeList& el, Vertex v,
|
Chris@16
|
825 boost::allow_parallel_edge_tag cat)
|
Chris@16
|
826 {
|
Chris@16
|
827 typedef typename Graph::global_edgelist_selector EdgeListS;
|
Chris@16
|
828 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
829
|
Chris@16
|
830 typename EdgeList::iterator i = el.begin(), end = el.end();
|
Chris@16
|
831 for (; i != end; ++i) {
|
Chris@16
|
832 if ((*i).get_target() == v) {
|
Chris@16
|
833 // NOTE: Wihtout this skip, this loop will double-delete properties
|
Chris@16
|
834 // of loop edges. This solution is based on the observation that
|
Chris@16
|
835 // the incidence edges of a vertex with a loop are adjacent in the
|
Chris@16
|
836 // out edge list. This *may* actually hold for multisets also.
|
Chris@16
|
837 bool skip = (boost::next(i) != end && i->get_iter() == boost::next(i)->get_iter());
|
Chris@16
|
838 g.m_edges.erase((*i).get_iter());
|
Chris@16
|
839 if (skip) ++i;
|
Chris@16
|
840 }
|
Chris@16
|
841 }
|
Chris@16
|
842 detail::erase_from_incidence_list(el, v, cat);
|
Chris@16
|
843 }
|
Chris@16
|
844 // O(log(E/V))
|
Chris@16
|
845 template <class Graph, class EdgeList, class Vertex>
|
Chris@16
|
846 inline void
|
Chris@16
|
847 remove_edge_and_property(Graph& g, EdgeList& el, Vertex v,
|
Chris@16
|
848 boost::disallow_parallel_edge_tag)
|
Chris@16
|
849 {
|
Chris@16
|
850 typedef typename Graph::global_edgelist_selector EdgeListS;
|
Chris@16
|
851 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
852
|
Chris@16
|
853 typedef typename EdgeList::value_type StoredEdge;
|
Chris@16
|
854 typename EdgeList::iterator i = el.find(StoredEdge(v)), end = el.end();
|
Chris@16
|
855 if (i != end) {
|
Chris@16
|
856 g.m_edges.erase((*i).get_iter());
|
Chris@16
|
857 el.erase(i);
|
Chris@16
|
858 }
|
Chris@16
|
859 }
|
Chris@16
|
860
|
Chris@16
|
861 } // namespace detail
|
Chris@16
|
862
|
Chris@16
|
863 template <class Vertex, class EdgeProperty>
|
Chris@16
|
864 struct list_edge // short name due to VC++ truncation and linker problems
|
Chris@16
|
865 : public boost::detail::edge_base<boost::undirected_tag, Vertex>
|
Chris@16
|
866 {
|
Chris@16
|
867 typedef EdgeProperty property_type;
|
Chris@16
|
868 typedef boost::detail::edge_base<boost::undirected_tag, Vertex> Base;
|
Chris@16
|
869 list_edge(Vertex u, Vertex v, const EdgeProperty& p = EdgeProperty())
|
Chris@16
|
870 : Base(u, v), m_property(p) { }
|
Chris@16
|
871 EdgeProperty& get_property() { return m_property; }
|
Chris@16
|
872 const EdgeProperty& get_property() const { return m_property; }
|
Chris@16
|
873 // the following methods should never be used, but are needed
|
Chris@16
|
874 // to make SGI MIPSpro C++ happy
|
Chris@16
|
875 list_edge() { }
|
Chris@16
|
876 bool operator==(const list_edge&) const { return false; }
|
Chris@16
|
877 bool operator<(const list_edge&) const { return false; }
|
Chris@16
|
878 EdgeProperty m_property;
|
Chris@16
|
879 };
|
Chris@16
|
880
|
Chris@16
|
881 template <class Config>
|
Chris@16
|
882 struct undirected_graph_helper {
|
Chris@16
|
883
|
Chris@16
|
884 typedef undir_adj_list_traversal_tag traversal_category;
|
Chris@16
|
885
|
Chris@16
|
886 // Placement of these overloaded remove_edge() functions
|
Chris@16
|
887 // inside the class avoids a VC++ bug.
|
Chris@16
|
888
|
Chris@16
|
889 // O(E/V)
|
Chris@16
|
890 inline void
|
Chris@16
|
891 remove_edge(typename Config::edge_descriptor e)
|
Chris@16
|
892 {
|
Chris@16
|
893 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
894 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
895
|
Chris@16
|
896 typedef typename Config::OutEdgeList::value_type::property_type PType;
|
Chris@16
|
897 detail::remove_undirected_edge_dispatch<PType>::apply
|
Chris@16
|
898 (e, *this, *(PType*)e.get_property());
|
Chris@16
|
899 }
|
Chris@16
|
900 // O(E/V)
|
Chris@16
|
901 inline void
|
Chris@16
|
902 remove_edge(typename Config::out_edge_iterator iter)
|
Chris@16
|
903 {
|
Chris@16
|
904 this->remove_edge(*iter);
|
Chris@16
|
905 }
|
Chris@16
|
906 };
|
Chris@16
|
907
|
Chris@16
|
908 // Had to make these non-members to avoid accidental instantiation
|
Chris@16
|
909 // on SGI MIPSpro C++
|
Chris@16
|
910 template <class C>
|
Chris@16
|
911 inline typename C::InEdgeList&
|
Chris@16
|
912 in_edge_list(undirected_graph_helper<C>&,
|
Chris@16
|
913 typename C::vertex_descriptor v)
|
Chris@16
|
914 {
|
Chris@16
|
915 typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
|
Chris@16
|
916 return sv->m_out_edges;
|
Chris@16
|
917 }
|
Chris@16
|
918 template <class C>
|
Chris@16
|
919 inline const typename C::InEdgeList&
|
Chris@16
|
920 in_edge_list(const undirected_graph_helper<C>&,
|
Chris@16
|
921 typename C::vertex_descriptor v) {
|
Chris@16
|
922 typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
|
Chris@16
|
923 return sv->m_out_edges;
|
Chris@16
|
924 }
|
Chris@16
|
925
|
Chris@16
|
926 // O(E/V)
|
Chris@16
|
927 template <class EdgeOrIter, class Config>
|
Chris@16
|
928 inline void
|
Chris@16
|
929 remove_edge(EdgeOrIter e, undirected_graph_helper<Config>& g_)
|
Chris@16
|
930 {
|
Chris@16
|
931 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
932 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
933
|
Chris@16
|
934 g_.remove_edge(e);
|
Chris@16
|
935 }
|
Chris@16
|
936
|
Chris@16
|
937 // O(E/V) or O(log(E/V))
|
Chris@16
|
938 template <class Config>
|
Chris@16
|
939 void
|
Chris@16
|
940 remove_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
941 typename Config::vertex_descriptor v,
|
Chris@16
|
942 undirected_graph_helper<Config>& g_)
|
Chris@16
|
943 {
|
Chris@16
|
944 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
945 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
946
|
Chris@16
|
947 typedef typename Config::graph_type graph_type;
|
Chris@16
|
948 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
949 typedef typename Config::edge_parallel_category Cat;
|
Chris@16
|
950 detail::remove_edge_and_property(g, g.out_edge_list(u), v, Cat());
|
Chris@16
|
951 detail::erase_from_incidence_list(g.out_edge_list(v), u, Cat());
|
Chris@16
|
952 }
|
Chris@16
|
953
|
Chris@16
|
954 template <class Config, class Predicate>
|
Chris@16
|
955 void
|
Chris@16
|
956 remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred,
|
Chris@16
|
957 undirected_graph_helper<Config>& g_)
|
Chris@16
|
958 {
|
Chris@16
|
959 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
960 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
961
|
Chris@16
|
962 typedef typename Config::graph_type graph_type;
|
Chris@16
|
963 typedef typename Config::OutEdgeList::value_type::property_type PropT;
|
Chris@16
|
964 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
965 typename Config::out_edge_iterator first, last;
|
Chris@16
|
966 boost::tie(first, last) = out_edges(u, g);
|
Chris@16
|
967 typedef typename Config::edge_parallel_category Cat;
|
Chris@16
|
968 detail::undirected_remove_out_edge_if_dispatch<PropT>
|
Chris@16
|
969 (g, first, last, g.out_edge_list(u), pred, Cat());
|
Chris@16
|
970 }
|
Chris@16
|
971 template <class Config, class Predicate>
|
Chris@16
|
972 void
|
Chris@16
|
973 remove_in_edge_if(typename Config::vertex_descriptor u, Predicate pred,
|
Chris@16
|
974 undirected_graph_helper<Config>& g_)
|
Chris@16
|
975 {
|
Chris@16
|
976 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
977 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
978
|
Chris@16
|
979 remove_out_edge_if(u, pred, g_);
|
Chris@16
|
980 }
|
Chris@16
|
981
|
Chris@16
|
982 // O(E/V * E) or O(log(E/V) * E)
|
Chris@16
|
983 template <class Predicate, class Config>
|
Chris@16
|
984 void
|
Chris@16
|
985 remove_edge_if(Predicate pred, undirected_graph_helper<Config>& g_)
|
Chris@16
|
986 {
|
Chris@16
|
987 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
988 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
989
|
Chris@16
|
990 typedef typename Config::graph_type graph_type;
|
Chris@16
|
991 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
992 typename Config::edge_iterator ei, ei_end, next;
|
Chris@16
|
993 boost::tie(ei, ei_end) = edges(g);
|
Chris@16
|
994 for (next = ei; ei != ei_end; ei = next) {
|
Chris@16
|
995 ++next;
|
Chris@16
|
996 if (pred(*ei))
|
Chris@16
|
997 remove_edge(*ei, g);
|
Chris@16
|
998 }
|
Chris@16
|
999 }
|
Chris@16
|
1000
|
Chris@16
|
1001 // O(1)
|
Chris@16
|
1002 template <class Config>
|
Chris@16
|
1003 inline std::pair<typename Config::edge_iterator,
|
Chris@16
|
1004 typename Config::edge_iterator>
|
Chris@16
|
1005 edges(const undirected_graph_helper<Config>& g_)
|
Chris@16
|
1006 {
|
Chris@16
|
1007 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1008 typedef typename Config::edge_iterator edge_iterator;
|
Chris@16
|
1009 const graph_type& cg = static_cast<const graph_type&>(g_);
|
Chris@16
|
1010 graph_type& g = const_cast<graph_type&>(cg);
|
Chris@16
|
1011 return std::make_pair( edge_iterator(g.m_edges.begin()),
|
Chris@16
|
1012 edge_iterator(g.m_edges.end()) );
|
Chris@16
|
1013 }
|
Chris@16
|
1014 // O(1)
|
Chris@16
|
1015 template <class Config>
|
Chris@16
|
1016 inline typename Config::edges_size_type
|
Chris@16
|
1017 num_edges(const undirected_graph_helper<Config>& g_)
|
Chris@16
|
1018 {
|
Chris@16
|
1019 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1020 const graph_type& g = static_cast<const graph_type&>(g_);
|
Chris@16
|
1021 return g.m_edges.size();
|
Chris@16
|
1022 }
|
Chris@16
|
1023 // O(E/V * E/V)
|
Chris@16
|
1024 template <class Config>
|
Chris@16
|
1025 inline void
|
Chris@16
|
1026 clear_vertex(typename Config::vertex_descriptor u,
|
Chris@16
|
1027 undirected_graph_helper<Config>& g_)
|
Chris@16
|
1028 {
|
Chris@16
|
1029 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
1030 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1031
|
Chris@16
|
1032 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1033 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
1034 while (true) {
|
Chris@16
|
1035 typename Config::out_edge_iterator ei, ei_end;
|
Chris@16
|
1036 boost::tie(ei, ei_end) = out_edges(u, g);
|
Chris@16
|
1037 if (ei == ei_end) break;
|
Chris@16
|
1038 remove_edge(*ei, g);
|
Chris@16
|
1039 }
|
Chris@16
|
1040 }
|
Chris@16
|
1041 // O(1) for allow_parallel_edge_tag
|
Chris@16
|
1042 // O(log(E/V)) for disallow_parallel_edge_tag
|
Chris@16
|
1043 template <class Config>
|
Chris@16
|
1044 inline std::pair<typename Config::edge_descriptor, bool>
|
Chris@16
|
1045 add_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
1046 typename Config::vertex_descriptor v,
|
Chris@16
|
1047 const typename Config::edge_property_type& p,
|
Chris@16
|
1048 undirected_graph_helper<Config>& g_)
|
Chris@16
|
1049 {
|
Chris@16
|
1050 typedef typename Config::StoredEdge StoredEdge;
|
Chris@16
|
1051 typedef typename Config::edge_descriptor edge_descriptor;
|
Chris@16
|
1052 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1053 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
1054
|
Chris@16
|
1055 bool inserted;
|
Chris@16
|
1056 typename Config::EdgeContainer::value_type e(u, v, p);
|
Chris@16
|
1057 typename Config::EdgeContainer::iterator p_iter
|
Chris@16
|
1058 = graph_detail::push(g.m_edges, e).first;
|
Chris@16
|
1059
|
Chris@16
|
1060 typename Config::OutEdgeList::iterator i;
|
Chris@16
|
1061 boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u),
|
Chris@16
|
1062 StoredEdge(v, p_iter, &g.m_edges));
|
Chris@16
|
1063 if (inserted) {
|
Chris@16
|
1064 boost::graph_detail::push(g.out_edge_list(v), StoredEdge(u, p_iter, &g.m_edges));
|
Chris@16
|
1065 return std::make_pair(edge_descriptor(u, v, &p_iter->get_property()),
|
Chris@16
|
1066 true);
|
Chris@16
|
1067 } else {
|
Chris@16
|
1068 g.m_edges.erase(p_iter);
|
Chris@16
|
1069 return std::make_pair
|
Chris@16
|
1070 (edge_descriptor(u, v, &i->get_iter()->get_property()), false);
|
Chris@16
|
1071 }
|
Chris@16
|
1072 }
|
Chris@16
|
1073 template <class Config>
|
Chris@16
|
1074 inline std::pair<typename Config::edge_descriptor, bool>
|
Chris@16
|
1075 add_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
1076 typename Config::vertex_descriptor v,
|
Chris@16
|
1077 undirected_graph_helper<Config>& g_)
|
Chris@16
|
1078 {
|
Chris@16
|
1079 typename Config::edge_property_type p;
|
Chris@16
|
1080 return add_edge(u, v, p, g_);
|
Chris@16
|
1081 }
|
Chris@16
|
1082
|
Chris@16
|
1083 // O(1)
|
Chris@16
|
1084 template <class Config>
|
Chris@16
|
1085 inline typename Config::degree_size_type
|
Chris@16
|
1086 degree(typename Config::vertex_descriptor u,
|
Chris@16
|
1087 const undirected_graph_helper<Config>& g_)
|
Chris@16
|
1088 {
|
Chris@16
|
1089 typedef typename Config::graph_type Graph;
|
Chris@16
|
1090 const Graph& g = static_cast<const Graph&>(g_);
|
Chris@16
|
1091 return out_degree(u, g);
|
Chris@16
|
1092 }
|
Chris@16
|
1093
|
Chris@16
|
1094 template <class Config>
|
Chris@16
|
1095 inline std::pair<typename Config::in_edge_iterator,
|
Chris@16
|
1096 typename Config::in_edge_iterator>
|
Chris@16
|
1097 in_edges(typename Config::vertex_descriptor u,
|
Chris@16
|
1098 const undirected_graph_helper<Config>& g_)
|
Chris@16
|
1099 {
|
Chris@16
|
1100 typedef typename Config::graph_type Graph;
|
Chris@16
|
1101 const Graph& cg = static_cast<const Graph&>(g_);
|
Chris@16
|
1102 Graph& g = const_cast<Graph&>(cg);
|
Chris@16
|
1103 typedef typename Config::in_edge_iterator in_edge_iterator;
|
Chris@16
|
1104 return
|
Chris@16
|
1105 std::make_pair(in_edge_iterator(g.out_edge_list(u).begin(), u),
|
Chris@16
|
1106 in_edge_iterator(g.out_edge_list(u).end(), u));
|
Chris@16
|
1107 }
|
Chris@16
|
1108
|
Chris@16
|
1109 template <class Config>
|
Chris@16
|
1110 inline typename Config::degree_size_type
|
Chris@16
|
1111 in_degree(typename Config::vertex_descriptor u,
|
Chris@16
|
1112 const undirected_graph_helper<Config>& g_)
|
Chris@16
|
1113 { return degree(u, g_); }
|
Chris@16
|
1114
|
Chris@16
|
1115 //=========================================================================
|
Chris@16
|
1116 // Bidirectional Graph Helper Class
|
Chris@16
|
1117
|
Chris@16
|
1118 struct bidir_adj_list_traversal_tag :
|
Chris@16
|
1119 public virtual vertex_list_graph_tag,
|
Chris@16
|
1120 public virtual incidence_graph_tag,
|
Chris@16
|
1121 public virtual adjacency_graph_tag,
|
Chris@16
|
1122 public virtual edge_list_graph_tag,
|
Chris@16
|
1123 public virtual bidirectional_graph_tag { };
|
Chris@16
|
1124
|
Chris@16
|
1125 template <class Config>
|
Chris@16
|
1126 struct bidirectional_graph_helper
|
Chris@16
|
1127 : public directed_edges_helper<Config> {
|
Chris@16
|
1128 typedef bidir_adj_list_traversal_tag traversal_category;
|
Chris@16
|
1129 };
|
Chris@16
|
1130
|
Chris@16
|
1131 // Had to make these non-members to avoid accidental instantiation
|
Chris@16
|
1132 // on SGI MIPSpro C++
|
Chris@16
|
1133 template <class C>
|
Chris@16
|
1134 inline typename C::InEdgeList&
|
Chris@16
|
1135 in_edge_list(bidirectional_graph_helper<C>&,
|
Chris@16
|
1136 typename C::vertex_descriptor v)
|
Chris@16
|
1137 {
|
Chris@16
|
1138 typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
|
Chris@16
|
1139 return sv->m_in_edges;
|
Chris@16
|
1140 }
|
Chris@16
|
1141 template <class C>
|
Chris@16
|
1142 inline const typename C::InEdgeList&
|
Chris@16
|
1143 in_edge_list(const bidirectional_graph_helper<C>&,
|
Chris@16
|
1144 typename C::vertex_descriptor v) {
|
Chris@16
|
1145 typename C::stored_vertex* sv = (typename C::stored_vertex*)v;
|
Chris@16
|
1146 return sv->m_in_edges;
|
Chris@16
|
1147 }
|
Chris@16
|
1148
|
Chris@16
|
1149 template <class Predicate, class Config>
|
Chris@16
|
1150 inline void
|
Chris@16
|
1151 remove_edge_if(Predicate pred, bidirectional_graph_helper<Config>& g_)
|
Chris@16
|
1152 {
|
Chris@16
|
1153 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
1154 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1155
|
Chris@16
|
1156 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1157 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
1158 typename Config::edge_iterator ei, ei_end, next;
|
Chris@16
|
1159 boost::tie(ei, ei_end) = edges(g);
|
Chris@16
|
1160 for (next = ei; ei != ei_end; ei = next) {
|
Chris@16
|
1161 ++next;
|
Chris@16
|
1162 if (pred(*ei))
|
Chris@16
|
1163 remove_edge(*ei, g);
|
Chris@16
|
1164 }
|
Chris@16
|
1165 }
|
Chris@16
|
1166
|
Chris@16
|
1167 template <class Config>
|
Chris@16
|
1168 inline std::pair<typename Config::in_edge_iterator,
|
Chris@16
|
1169 typename Config::in_edge_iterator>
|
Chris@16
|
1170 in_edges(typename Config::vertex_descriptor u,
|
Chris@16
|
1171 const bidirectional_graph_helper<Config>& g_)
|
Chris@16
|
1172 {
|
Chris@16
|
1173 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1174 const graph_type& cg = static_cast<const graph_type&>(g_);
|
Chris@16
|
1175 graph_type& g = const_cast<graph_type&>(cg);
|
Chris@16
|
1176 typedef typename Config::in_edge_iterator in_edge_iterator;
|
Chris@16
|
1177 return
|
Chris@16
|
1178 std::make_pair(in_edge_iterator(in_edge_list(g, u).begin(), u),
|
Chris@16
|
1179 in_edge_iterator(in_edge_list(g, u).end(), u));
|
Chris@16
|
1180 }
|
Chris@16
|
1181
|
Chris@16
|
1182 // O(1)
|
Chris@16
|
1183 template <class Config>
|
Chris@16
|
1184 inline std::pair<typename Config::edge_iterator,
|
Chris@16
|
1185 typename Config::edge_iterator>
|
Chris@16
|
1186 edges(const bidirectional_graph_helper<Config>& g_)
|
Chris@16
|
1187 {
|
Chris@16
|
1188 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1189 typedef typename Config::edge_iterator edge_iterator;
|
Chris@16
|
1190 const graph_type& cg = static_cast<const graph_type&>(g_);
|
Chris@16
|
1191 graph_type& g = const_cast<graph_type&>(cg);
|
Chris@16
|
1192 return std::make_pair( edge_iterator(g.m_edges.begin()),
|
Chris@16
|
1193 edge_iterator(g.m_edges.end()) );
|
Chris@16
|
1194 }
|
Chris@16
|
1195
|
Chris@16
|
1196 //=========================================================================
|
Chris@16
|
1197 // Bidirectional Graph Helper Class (with edge properties)
|
Chris@16
|
1198
|
Chris@16
|
1199
|
Chris@16
|
1200 template <class Config>
|
Chris@16
|
1201 struct bidirectional_graph_helper_with_property
|
Chris@16
|
1202 : public bidirectional_graph_helper<Config>
|
Chris@16
|
1203 {
|
Chris@16
|
1204 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1205 typedef typename Config::out_edge_iterator out_edge_iterator;
|
Chris@16
|
1206
|
Chris@16
|
1207 std::pair<out_edge_iterator, out_edge_iterator>
|
Chris@16
|
1208 get_parallel_edge_sublist(typename Config::edge_descriptor e,
|
Chris@16
|
1209 const graph_type& g,
|
Chris@16
|
1210 void*)
|
Chris@16
|
1211 { return out_edges(source(e, g), g); }
|
Chris@16
|
1212
|
Chris@16
|
1213 std::pair<out_edge_iterator, out_edge_iterator>
|
Chris@16
|
1214 get_parallel_edge_sublist(typename Config::edge_descriptor e,
|
Chris@16
|
1215 const graph_type& g,
|
Chris@16
|
1216 setS*)
|
Chris@16
|
1217 { return edge_range(source(e, g), target(e, g), g); }
|
Chris@16
|
1218
|
Chris@16
|
1219 std::pair<out_edge_iterator, out_edge_iterator>
|
Chris@16
|
1220 get_parallel_edge_sublist(typename Config::edge_descriptor e,
|
Chris@16
|
1221 const graph_type& g,
|
Chris@16
|
1222 multisetS*)
|
Chris@16
|
1223 { return edge_range(source(e, g), target(e, g), g); }
|
Chris@16
|
1224
|
Chris@16
|
1225 std::pair<out_edge_iterator, out_edge_iterator>
|
Chris@16
|
1226 get_parallel_edge_sublist(typename Config::edge_descriptor e,
|
Chris@16
|
1227 const graph_type& g,
|
Chris@16
|
1228 hash_setS*)
|
Chris@16
|
1229 { return edge_range(source(e, g), target(e, g), g); }
|
Chris@16
|
1230
|
Chris@16
|
1231 // Placement of these overloaded remove_edge() functions
|
Chris@16
|
1232 // inside the class avoids a VC++ bug.
|
Chris@16
|
1233
|
Chris@16
|
1234 // O(E/V) or O(log(E/V))
|
Chris@16
|
1235 void
|
Chris@16
|
1236 remove_edge(typename Config::edge_descriptor e)
|
Chris@16
|
1237 {
|
Chris@16
|
1238 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
1239 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1240
|
Chris@16
|
1241 graph_type& g = static_cast<graph_type&>(*this);
|
Chris@16
|
1242
|
Chris@16
|
1243 typedef typename Config::edgelist_selector OutEdgeListS;
|
Chris@16
|
1244
|
Chris@16
|
1245 std::pair<out_edge_iterator, out_edge_iterator> rng =
|
Chris@16
|
1246 get_parallel_edge_sublist(e, g, (OutEdgeListS*)(0));
|
Chris@16
|
1247 rng.first = std::find(rng.first, rng.second, e);
|
Chris@16
|
1248 BOOST_ASSERT(rng.first != rng.second);
|
Chris@16
|
1249 remove_edge(rng.first);
|
Chris@16
|
1250 }
|
Chris@16
|
1251
|
Chris@16
|
1252 inline void
|
Chris@16
|
1253 remove_edge(typename Config::out_edge_iterator iter)
|
Chris@16
|
1254 {
|
Chris@16
|
1255 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
1256 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1257
|
Chris@16
|
1258 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1259 graph_type& g = static_cast<graph_type&>(*this);
|
Chris@16
|
1260 typename Config::edge_descriptor e = *iter;
|
Chris@16
|
1261 typename Config::OutEdgeList& oel = g.out_edge_list(source(e, g));
|
Chris@16
|
1262 typename Config::InEdgeList& iel = in_edge_list(g, target(e, g));
|
Chris@16
|
1263 typedef typename Config::OutEdgeList::value_type::property_type PType;
|
Chris@16
|
1264 PType& p = *(PType*)e.get_property();
|
Chris@16
|
1265 detail::remove_directed_edge_dispatch(*iter, iel, p);
|
Chris@16
|
1266 g.m_edges.erase(iter.base()->get_iter());
|
Chris@16
|
1267 oel.erase(iter.base());
|
Chris@16
|
1268 }
|
Chris@16
|
1269 };
|
Chris@16
|
1270
|
Chris@16
|
1271 // O(E/V) for allow_parallel_edge_tag
|
Chris@16
|
1272 // O(log(E/V)) for disallow_parallel_edge_tag
|
Chris@16
|
1273 template <class Config>
|
Chris@16
|
1274 inline void
|
Chris@16
|
1275 remove_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
1276 typename Config::vertex_descriptor v,
|
Chris@16
|
1277 bidirectional_graph_helper_with_property<Config>& g_)
|
Chris@16
|
1278 {
|
Chris@16
|
1279 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
1280 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1281
|
Chris@16
|
1282 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1283 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
1284 typedef typename Config::edge_parallel_category Cat;
|
Chris@16
|
1285 detail::remove_edge_and_property(g, g.out_edge_list(u), v, Cat());
|
Chris@16
|
1286 detail::erase_from_incidence_list(in_edge_list(g, v), u, Cat());
|
Chris@16
|
1287 }
|
Chris@16
|
1288
|
Chris@16
|
1289 // O(E/V) or O(log(E/V))
|
Chris@16
|
1290 template <class EdgeOrIter, class Config>
|
Chris@16
|
1291 inline void
|
Chris@16
|
1292 remove_edge(EdgeOrIter e,
|
Chris@16
|
1293 bidirectional_graph_helper_with_property<Config>& g_)
|
Chris@16
|
1294 {
|
Chris@16
|
1295 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
1296 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1297
|
Chris@16
|
1298 g_.remove_edge(e);
|
Chris@16
|
1299 }
|
Chris@16
|
1300
|
Chris@16
|
1301 template <class Config, class Predicate>
|
Chris@16
|
1302 inline void
|
Chris@16
|
1303 remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred,
|
Chris@16
|
1304 bidirectional_graph_helper_with_property<Config>& g_)
|
Chris@16
|
1305 {
|
Chris@16
|
1306 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
1307 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1308
|
Chris@16
|
1309 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1310 typedef typename Config::OutEdgeList::value_type::property_type PropT;
|
Chris@16
|
1311 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
1312
|
Chris@16
|
1313 typedef typename Config::EdgeIter EdgeIter;
|
Chris@16
|
1314 typedef std::vector<EdgeIter> Garbage;
|
Chris@16
|
1315 Garbage garbage;
|
Chris@16
|
1316
|
Chris@16
|
1317 // First remove the edges from the targets' in-edge lists and
|
Chris@16
|
1318 // from the graph's edge set list.
|
Chris@16
|
1319 typename Config::out_edge_iterator out_i, out_end;
|
Chris@16
|
1320 for (boost::tie(out_i, out_end) = out_edges(u, g); out_i != out_end; ++out_i)
|
Chris@16
|
1321 if (pred(*out_i)) {
|
Chris@16
|
1322 detail::remove_directed_edge_dispatch
|
Chris@16
|
1323 (*out_i, in_edge_list(g, target(*out_i, g)),
|
Chris@16
|
1324 *(PropT*)(*out_i).get_property());
|
Chris@16
|
1325 // Put in garbage to delete later. Will need the properties
|
Chris@16
|
1326 // for the remove_if of the out-edges.
|
Chris@16
|
1327 garbage.push_back((*out_i.base()).get_iter());
|
Chris@16
|
1328 }
|
Chris@16
|
1329
|
Chris@16
|
1330 // Now remove the edges from this out-edge list.
|
Chris@16
|
1331 typename Config::out_edge_iterator first, last;
|
Chris@16
|
1332 boost::tie(first, last) = out_edges(u, g);
|
Chris@16
|
1333 typedef typename Config::edge_parallel_category Cat;
|
Chris@16
|
1334 detail::remove_directed_edge_if_dispatch
|
Chris@16
|
1335 (first, last, g.out_edge_list(u), pred, Cat());
|
Chris@16
|
1336
|
Chris@16
|
1337 // Now delete the edge properties from the g.m_edges list
|
Chris@16
|
1338 for (typename Garbage::iterator i = garbage.begin();
|
Chris@16
|
1339 i != garbage.end(); ++i)
|
Chris@16
|
1340 g.m_edges.erase(*i);
|
Chris@16
|
1341 }
|
Chris@16
|
1342 template <class Config, class Predicate>
|
Chris@16
|
1343 inline void
|
Chris@16
|
1344 remove_in_edge_if(typename Config::vertex_descriptor v, Predicate pred,
|
Chris@16
|
1345 bidirectional_graph_helper_with_property<Config>& g_)
|
Chris@16
|
1346 {
|
Chris@16
|
1347 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
1348 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1349
|
Chris@16
|
1350 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1351 typedef typename Config::OutEdgeList::value_type::property_type PropT;
|
Chris@16
|
1352 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
1353
|
Chris@16
|
1354 typedef typename Config::EdgeIter EdgeIter;
|
Chris@16
|
1355 typedef std::vector<EdgeIter> Garbage;
|
Chris@16
|
1356 Garbage garbage;
|
Chris@16
|
1357
|
Chris@16
|
1358 // First remove the edges from the sources' out-edge lists and
|
Chris@16
|
1359 // from the graph's edge set list.
|
Chris@16
|
1360 typename Config::in_edge_iterator in_i, in_end;
|
Chris@16
|
1361 for (boost::tie(in_i, in_end) = in_edges(v, g); in_i != in_end; ++in_i)
|
Chris@16
|
1362 if (pred(*in_i)) {
|
Chris@16
|
1363 typename Config::vertex_descriptor u = source(*in_i, g);
|
Chris@16
|
1364 detail::remove_directed_edge_dispatch
|
Chris@16
|
1365 (*in_i, g.out_edge_list(u), *(PropT*)(*in_i).get_property());
|
Chris@16
|
1366 // Put in garbage to delete later. Will need the properties
|
Chris@16
|
1367 // for the remove_if of the out-edges.
|
Chris@16
|
1368 garbage.push_back((*in_i.base()).get_iter());
|
Chris@16
|
1369 }
|
Chris@16
|
1370 // Now remove the edges from this in-edge list.
|
Chris@16
|
1371 typename Config::in_edge_iterator first, last;
|
Chris@16
|
1372 boost::tie(first, last) = in_edges(v, g);
|
Chris@16
|
1373 typedef typename Config::edge_parallel_category Cat;
|
Chris@16
|
1374 detail::remove_directed_edge_if_dispatch
|
Chris@16
|
1375 (first, last, in_edge_list(g, v), pred, Cat());
|
Chris@16
|
1376
|
Chris@16
|
1377 // Now delete the edge properties from the g.m_edges list
|
Chris@16
|
1378 for (typename Garbage::iterator i = garbage.begin();
|
Chris@16
|
1379 i != garbage.end(); ++i)
|
Chris@16
|
1380 g.m_edges.erase(*i);
|
Chris@16
|
1381 }
|
Chris@16
|
1382
|
Chris@16
|
1383 // O(1)
|
Chris@16
|
1384 template <class Config>
|
Chris@16
|
1385 inline typename Config::edges_size_type
|
Chris@16
|
1386 num_edges(const bidirectional_graph_helper_with_property<Config>& g_)
|
Chris@16
|
1387 {
|
Chris@16
|
1388 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1389 const graph_type& g = static_cast<const graph_type&>(g_);
|
Chris@16
|
1390 return g.m_edges.size();
|
Chris@16
|
1391 }
|
Chris@16
|
1392 // O(E/V * E/V) for allow_parallel_edge_tag
|
Chris@16
|
1393 // O(E/V * log(E/V)) for disallow_parallel_edge_tag
|
Chris@16
|
1394 template <class Config>
|
Chris@16
|
1395 inline void
|
Chris@16
|
1396 clear_vertex(typename Config::vertex_descriptor u,
|
Chris@16
|
1397 bidirectional_graph_helper_with_property<Config>& g_)
|
Chris@16
|
1398 {
|
Chris@16
|
1399 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
1400 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1401
|
Chris@16
|
1402 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1403 typedef typename Config::edge_parallel_category Cat;
|
Chris@16
|
1404 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
1405 typename Config::OutEdgeList& el = g.out_edge_list(u);
|
Chris@16
|
1406 typename Config::OutEdgeList::iterator
|
Chris@16
|
1407 ei = el.begin(), ei_end = el.end();
|
Chris@16
|
1408 for (; ei != ei_end; ++ei) {
|
Chris@16
|
1409 detail::erase_from_incidence_list
|
Chris@16
|
1410 (in_edge_list(g, (*ei).get_target()), u, Cat());
|
Chris@16
|
1411 g.m_edges.erase((*ei).get_iter());
|
Chris@16
|
1412 }
|
Chris@16
|
1413 typename Config::InEdgeList& in_el = in_edge_list(g, u);
|
Chris@16
|
1414 typename Config::InEdgeList::iterator
|
Chris@16
|
1415 in_ei = in_el.begin(), in_ei_end = in_el.end();
|
Chris@16
|
1416 for (; in_ei != in_ei_end; ++in_ei) {
|
Chris@16
|
1417 detail::erase_from_incidence_list
|
Chris@16
|
1418 (g.out_edge_list((*in_ei).get_target()), u, Cat());
|
Chris@16
|
1419 g.m_edges.erase((*in_ei).get_iter());
|
Chris@16
|
1420 }
|
Chris@16
|
1421 g.out_edge_list(u).clear();
|
Chris@16
|
1422 in_edge_list(g, u).clear();
|
Chris@16
|
1423 }
|
Chris@16
|
1424
|
Chris@16
|
1425 template <class Config>
|
Chris@16
|
1426 inline void
|
Chris@16
|
1427 clear_out_edges(typename Config::vertex_descriptor u,
|
Chris@16
|
1428 bidirectional_graph_helper_with_property<Config>& g_)
|
Chris@16
|
1429 {
|
Chris@16
|
1430 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
1431 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1432
|
Chris@16
|
1433 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1434 typedef typename Config::edge_parallel_category Cat;
|
Chris@16
|
1435 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
1436 typename Config::OutEdgeList& el = g.out_edge_list(u);
|
Chris@16
|
1437 typename Config::OutEdgeList::iterator
|
Chris@16
|
1438 ei = el.begin(), ei_end = el.end();
|
Chris@16
|
1439 for (; ei != ei_end; ++ei) {
|
Chris@16
|
1440 detail::erase_from_incidence_list
|
Chris@16
|
1441 (in_edge_list(g, (*ei).get_target()), u, Cat());
|
Chris@16
|
1442 g.m_edges.erase((*ei).get_iter());
|
Chris@16
|
1443 }
|
Chris@16
|
1444 g.out_edge_list(u).clear();
|
Chris@16
|
1445 }
|
Chris@16
|
1446
|
Chris@16
|
1447 template <class Config>
|
Chris@16
|
1448 inline void
|
Chris@16
|
1449 clear_in_edges(typename Config::vertex_descriptor u,
|
Chris@16
|
1450 bidirectional_graph_helper_with_property<Config>& g_)
|
Chris@16
|
1451 {
|
Chris@16
|
1452 typedef typename Config::global_edgelist_selector EdgeListS;
|
Chris@16
|
1453 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1454
|
Chris@16
|
1455 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1456 typedef typename Config::edge_parallel_category Cat;
|
Chris@16
|
1457 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
1458 typename Config::InEdgeList& in_el = in_edge_list(g, u);
|
Chris@16
|
1459 typename Config::InEdgeList::iterator
|
Chris@16
|
1460 in_ei = in_el.begin(), in_ei_end = in_el.end();
|
Chris@16
|
1461 for (; in_ei != in_ei_end; ++in_ei) {
|
Chris@16
|
1462 detail::erase_from_incidence_list
|
Chris@16
|
1463 (g.out_edge_list((*in_ei).get_target()), u, Cat());
|
Chris@16
|
1464 g.m_edges.erase((*in_ei).get_iter());
|
Chris@16
|
1465 }
|
Chris@16
|
1466 in_edge_list(g, u).clear();
|
Chris@16
|
1467 }
|
Chris@16
|
1468
|
Chris@16
|
1469 // O(1) for allow_parallel_edge_tag
|
Chris@16
|
1470 // O(log(E/V)) for disallow_parallel_edge_tag
|
Chris@16
|
1471 template <class Config>
|
Chris@16
|
1472 inline std::pair<typename Config::edge_descriptor, bool>
|
Chris@16
|
1473 add_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
1474 typename Config::vertex_descriptor v,
|
Chris@16
|
1475 const typename Config::edge_property_type& p,
|
Chris@16
|
1476 bidirectional_graph_helper_with_property<Config>& g_)
|
Chris@16
|
1477 {
|
Chris@16
|
1478 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1479 graph_type& g = static_cast<graph_type&>(g_);
|
Chris@16
|
1480 typedef typename Config::edge_descriptor edge_descriptor;
|
Chris@16
|
1481 typedef typename Config::StoredEdge StoredEdge;
|
Chris@16
|
1482 bool inserted;
|
Chris@16
|
1483 typename Config::EdgeContainer::value_type e(u, v, p);
|
Chris@16
|
1484 typename Config::EdgeContainer::iterator p_iter
|
Chris@16
|
1485 = graph_detail::push(g.m_edges, e).first;
|
Chris@16
|
1486 typename Config::OutEdgeList::iterator i;
|
Chris@16
|
1487 boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u),
|
Chris@16
|
1488 StoredEdge(v, p_iter, &g.m_edges));
|
Chris@16
|
1489 if (inserted) {
|
Chris@16
|
1490 boost::graph_detail::push(in_edge_list(g, v), StoredEdge(u, p_iter, &g.m_edges));
|
Chris@16
|
1491 return std::make_pair(edge_descriptor(u, v, &p_iter->m_property),
|
Chris@16
|
1492 true);
|
Chris@16
|
1493 } else {
|
Chris@16
|
1494 g.m_edges.erase(p_iter);
|
Chris@16
|
1495 return std::make_pair(edge_descriptor(u, v,
|
Chris@16
|
1496 &i->get_iter()->get_property()),
|
Chris@16
|
1497 false);
|
Chris@16
|
1498 }
|
Chris@16
|
1499 }
|
Chris@16
|
1500
|
Chris@16
|
1501 template <class Config>
|
Chris@16
|
1502 inline std::pair<typename Config::edge_descriptor, bool>
|
Chris@16
|
1503 add_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
1504 typename Config::vertex_descriptor v,
|
Chris@16
|
1505 bidirectional_graph_helper_with_property<Config>& g_)
|
Chris@16
|
1506 {
|
Chris@16
|
1507 typename Config::edge_property_type p;
|
Chris@16
|
1508 return add_edge(u, v, p, g_);
|
Chris@16
|
1509 }
|
Chris@16
|
1510 // O(1)
|
Chris@16
|
1511 template <class Config>
|
Chris@16
|
1512 inline typename Config::degree_size_type
|
Chris@16
|
1513 degree(typename Config::vertex_descriptor u,
|
Chris@16
|
1514 const bidirectional_graph_helper_with_property<Config>& g_)
|
Chris@16
|
1515 {
|
Chris@16
|
1516 typedef typename Config::graph_type graph_type;
|
Chris@16
|
1517 const graph_type& g = static_cast<const graph_type&>(g_);
|
Chris@16
|
1518 return in_degree(u, g) + out_degree(u, g);
|
Chris@16
|
1519 }
|
Chris@16
|
1520
|
Chris@16
|
1521 //=========================================================================
|
Chris@16
|
1522 // Adjacency List Helper Class
|
Chris@16
|
1523
|
Chris@16
|
1524 template <class Config, class Base>
|
Chris@16
|
1525 struct adj_list_helper : public Base
|
Chris@16
|
1526 {
|
Chris@16
|
1527 typedef typename Config::graph_type AdjList;
|
Chris@16
|
1528 typedef typename Config::vertex_descriptor vertex_descriptor;
|
Chris@16
|
1529 typedef typename Config::edge_descriptor edge_descriptor;
|
Chris@16
|
1530 typedef typename Config::out_edge_iterator out_edge_iterator;
|
Chris@16
|
1531 typedef typename Config::in_edge_iterator in_edge_iterator;
|
Chris@16
|
1532 typedef typename Config::adjacency_iterator adjacency_iterator;
|
Chris@16
|
1533 typedef typename Config::inv_adjacency_iterator inv_adjacency_iterator;
|
Chris@16
|
1534 typedef typename Config::vertex_iterator vertex_iterator;
|
Chris@16
|
1535 typedef typename Config::edge_iterator edge_iterator;
|
Chris@16
|
1536 typedef typename Config::directed_category directed_category;
|
Chris@16
|
1537 typedef typename Config::edge_parallel_category edge_parallel_category;
|
Chris@16
|
1538 typedef typename Config::vertices_size_type vertices_size_type;
|
Chris@16
|
1539 typedef typename Config::edges_size_type edges_size_type;
|
Chris@16
|
1540 typedef typename Config::degree_size_type degree_size_type;
|
Chris@16
|
1541 typedef typename Config::StoredEdge StoredEdge;
|
Chris@16
|
1542 typedef typename Config::vertex_property_type vertex_property_type;
|
Chris@16
|
1543 typedef typename Config::edge_property_type edge_property_type;
|
Chris@16
|
1544 typedef typename Config::graph_property_type graph_property_type;
|
Chris@16
|
1545
|
Chris@16
|
1546 typedef typename Config::global_edgelist_selector
|
Chris@16
|
1547 global_edgelist_selector;
|
Chris@16
|
1548
|
Chris@16
|
1549 typedef typename lookup_one_property<vertex_property_type, vertex_bundle_t>::type vertex_bundled;
|
Chris@16
|
1550 typedef typename lookup_one_property<edge_property_type, edge_bundle_t>::type edge_bundled;
|
Chris@16
|
1551 typedef typename lookup_one_property<graph_property_type, graph_bundle_t>::type graph_bundled;
|
Chris@16
|
1552 };
|
Chris@16
|
1553
|
Chris@16
|
1554 template <class Config, class Base>
|
Chris@16
|
1555 inline std::pair<typename Config::adjacency_iterator,
|
Chris@16
|
1556 typename Config::adjacency_iterator>
|
Chris@16
|
1557 adjacent_vertices(typename Config::vertex_descriptor u,
|
Chris@16
|
1558 const adj_list_helper<Config, Base>& g_)
|
Chris@16
|
1559 {
|
Chris@16
|
1560 typedef typename Config::graph_type AdjList;
|
Chris@16
|
1561 const AdjList& cg = static_cast<const AdjList&>(g_);
|
Chris@16
|
1562 AdjList& g = const_cast<AdjList&>(cg);
|
Chris@16
|
1563 typedef typename Config::adjacency_iterator adjacency_iterator;
|
Chris@16
|
1564 typename Config::out_edge_iterator first, last;
|
Chris@16
|
1565 boost::tie(first, last) = out_edges(u, g);
|
Chris@16
|
1566 return std::make_pair(adjacency_iterator(first, &g),
|
Chris@16
|
1567 adjacency_iterator(last, &g));
|
Chris@16
|
1568 }
|
Chris@16
|
1569 template <class Config, class Base>
|
Chris@16
|
1570 inline std::pair<typename Config::inv_adjacency_iterator,
|
Chris@16
|
1571 typename Config::inv_adjacency_iterator>
|
Chris@16
|
1572 inv_adjacent_vertices(typename Config::vertex_descriptor u,
|
Chris@16
|
1573 const adj_list_helper<Config, Base>& g_)
|
Chris@16
|
1574 {
|
Chris@16
|
1575 typedef typename Config::graph_type AdjList;
|
Chris@16
|
1576 const AdjList& cg = static_cast<const AdjList&>(g_);
|
Chris@16
|
1577 AdjList& g = const_cast<AdjList&>(cg);
|
Chris@16
|
1578 typedef typename Config::inv_adjacency_iterator inv_adjacency_iterator;
|
Chris@16
|
1579 typename Config::in_edge_iterator first, last;
|
Chris@16
|
1580 boost::tie(first, last) = in_edges(u, g);
|
Chris@16
|
1581 return std::make_pair(inv_adjacency_iterator(first, &g),
|
Chris@16
|
1582 inv_adjacency_iterator(last, &g));
|
Chris@16
|
1583 }
|
Chris@16
|
1584 template <class Config, class Base>
|
Chris@16
|
1585 inline std::pair<typename Config::out_edge_iterator,
|
Chris@16
|
1586 typename Config::out_edge_iterator>
|
Chris@16
|
1587 out_edges(typename Config::vertex_descriptor u,
|
Chris@16
|
1588 const adj_list_helper<Config, Base>& g_)
|
Chris@16
|
1589 {
|
Chris@16
|
1590 typedef typename Config::graph_type AdjList;
|
Chris@16
|
1591 typedef typename Config::out_edge_iterator out_edge_iterator;
|
Chris@16
|
1592 const AdjList& cg = static_cast<const AdjList&>(g_);
|
Chris@16
|
1593 AdjList& g = const_cast<AdjList&>(cg);
|
Chris@16
|
1594 return
|
Chris@16
|
1595 std::make_pair(out_edge_iterator(g.out_edge_list(u).begin(), u),
|
Chris@16
|
1596 out_edge_iterator(g.out_edge_list(u).end(), u));
|
Chris@16
|
1597 }
|
Chris@16
|
1598 template <class Config, class Base>
|
Chris@16
|
1599 inline std::pair<typename Config::vertex_iterator,
|
Chris@16
|
1600 typename Config::vertex_iterator>
|
Chris@16
|
1601 vertices(const adj_list_helper<Config, Base>& g_)
|
Chris@16
|
1602 {
|
Chris@16
|
1603 typedef typename Config::graph_type AdjList;
|
Chris@16
|
1604 const AdjList& cg = static_cast<const AdjList&>(g_);
|
Chris@16
|
1605 AdjList& g = const_cast<AdjList&>(cg);
|
Chris@16
|
1606 return std::make_pair( g.vertex_set().begin(), g.vertex_set().end() );
|
Chris@16
|
1607 }
|
Chris@16
|
1608 template <class Config, class Base>
|
Chris@16
|
1609 inline typename Config::vertices_size_type
|
Chris@16
|
1610 num_vertices(const adj_list_helper<Config, Base>& g_)
|
Chris@16
|
1611 {
|
Chris@16
|
1612 typedef typename Config::graph_type AdjList;
|
Chris@16
|
1613 const AdjList& g = static_cast<const AdjList&>(g_);
|
Chris@16
|
1614 return g.vertex_set().size();
|
Chris@16
|
1615 }
|
Chris@16
|
1616 template <class Config, class Base>
|
Chris@16
|
1617 inline typename Config::degree_size_type
|
Chris@16
|
1618 out_degree(typename Config::vertex_descriptor u,
|
Chris@16
|
1619 const adj_list_helper<Config, Base>& g_)
|
Chris@16
|
1620 {
|
Chris@16
|
1621 typedef typename Config::graph_type AdjList;
|
Chris@16
|
1622 const AdjList& g = static_cast<const AdjList&>(g_);
|
Chris@16
|
1623 return g.out_edge_list(u).size();
|
Chris@16
|
1624 }
|
Chris@16
|
1625 template <class Config, class Base>
|
Chris@16
|
1626 inline std::pair<typename Config::edge_descriptor, bool>
|
Chris@16
|
1627 edge(typename Config::vertex_descriptor u,
|
Chris@16
|
1628 typename Config::vertex_descriptor v,
|
Chris@16
|
1629 const adj_list_helper<Config, Base>& g_)
|
Chris@16
|
1630 {
|
Chris@16
|
1631 typedef typename Config::graph_type Graph;
|
Chris@16
|
1632 typedef typename Config::StoredEdge StoredEdge;
|
Chris@16
|
1633 const Graph& cg = static_cast<const Graph&>(g_);
|
Chris@16
|
1634 const typename Config::OutEdgeList& el = cg.out_edge_list(u);
|
Chris@16
|
1635 typename Config::OutEdgeList::const_iterator it = graph_detail::
|
Chris@16
|
1636 find(el, StoredEdge(v));
|
Chris@16
|
1637 return std::make_pair(
|
Chris@16
|
1638 typename Config::edge_descriptor
|
Chris@16
|
1639 (u, v, (it == el.end() ? 0 : &(*it).get_property())),
|
Chris@16
|
1640 (it != el.end()));
|
Chris@16
|
1641 }
|
Chris@16
|
1642
|
Chris@16
|
1643 template <class Config, class Base>
|
Chris@16
|
1644 inline std::pair<typename Config::out_edge_iterator,
|
Chris@16
|
1645 typename Config::out_edge_iterator>
|
Chris@16
|
1646 edge_range(typename Config::vertex_descriptor u,
|
Chris@16
|
1647 typename Config::vertex_descriptor v,
|
Chris@16
|
1648 const adj_list_helper<Config, Base>& g_)
|
Chris@16
|
1649 {
|
Chris@16
|
1650 typedef typename Config::graph_type Graph;
|
Chris@16
|
1651 typedef typename Config::StoredEdge StoredEdge;
|
Chris@16
|
1652 const Graph& cg = static_cast<const Graph&>(g_);
|
Chris@16
|
1653 Graph& g = const_cast<Graph&>(cg);
|
Chris@16
|
1654 typedef typename Config::out_edge_iterator out_edge_iterator;
|
Chris@16
|
1655 typename Config::OutEdgeList& el = g.out_edge_list(u);
|
Chris@16
|
1656 typename Config::OutEdgeList::iterator first, last;
|
Chris@16
|
1657 typename Config::EdgeContainer fake_edge_container;
|
Chris@16
|
1658 boost::tie(first, last) = graph_detail::
|
Chris@101
|
1659 equal_range(el, StoredEdge(v));
|
Chris@16
|
1660 return std::make_pair(out_edge_iterator(first, u),
|
Chris@16
|
1661 out_edge_iterator(last, u));
|
Chris@16
|
1662 }
|
Chris@16
|
1663
|
Chris@16
|
1664 template <class Config>
|
Chris@16
|
1665 inline typename Config::degree_size_type
|
Chris@16
|
1666 in_degree(typename Config::vertex_descriptor u,
|
Chris@16
|
1667 const directed_edges_helper<Config>& g_)
|
Chris@16
|
1668 {
|
Chris@16
|
1669 typedef typename Config::graph_type Graph;
|
Chris@16
|
1670 const Graph& cg = static_cast<const Graph&>(g_);
|
Chris@16
|
1671 Graph& g = const_cast<Graph&>(cg);
|
Chris@16
|
1672 return in_edge_list(g, u).size();
|
Chris@16
|
1673 }
|
Chris@16
|
1674
|
Chris@16
|
1675 namespace detail {
|
Chris@16
|
1676 template <class Config, class Base, class Property>
|
Chris@16
|
1677 inline
|
Chris@16
|
1678 typename boost::property_map<typename Config::graph_type,
|
Chris@16
|
1679 Property>::type
|
Chris@16
|
1680 get_dispatch(adj_list_helper<Config,Base>&, Property p,
|
Chris@16
|
1681 boost::edge_property_tag) {
|
Chris@16
|
1682 typedef typename Config::graph_type Graph;
|
Chris@16
|
1683 typedef typename boost::property_map<Graph, Property>::type PA;
|
Chris@16
|
1684 return PA(p);
|
Chris@16
|
1685 }
|
Chris@16
|
1686 template <class Config, class Base, class Property>
|
Chris@16
|
1687 inline
|
Chris@16
|
1688 typename boost::property_map<typename Config::graph_type,
|
Chris@16
|
1689 Property>::const_type
|
Chris@16
|
1690 get_dispatch(const adj_list_helper<Config,Base>&, Property p,
|
Chris@16
|
1691 boost::edge_property_tag) {
|
Chris@16
|
1692 typedef typename Config::graph_type Graph;
|
Chris@16
|
1693 typedef typename boost::property_map<Graph, Property>::const_type PA;
|
Chris@16
|
1694 return PA(p);
|
Chris@16
|
1695 }
|
Chris@16
|
1696
|
Chris@16
|
1697 template <class Config, class Base, class Property>
|
Chris@16
|
1698 inline
|
Chris@16
|
1699 typename boost::property_map<typename Config::graph_type,
|
Chris@16
|
1700 Property>::type
|
Chris@16
|
1701 get_dispatch(adj_list_helper<Config,Base>& g, Property p,
|
Chris@16
|
1702 boost::vertex_property_tag) {
|
Chris@16
|
1703 typedef typename Config::graph_type Graph;
|
Chris@16
|
1704 typedef typename boost::property_map<Graph, Property>::type PA;
|
Chris@16
|
1705 return PA(&static_cast<Graph&>(g), p);
|
Chris@16
|
1706 }
|
Chris@16
|
1707 template <class Config, class Base, class Property>
|
Chris@16
|
1708 inline
|
Chris@16
|
1709 typename boost::property_map<typename Config::graph_type,
|
Chris@16
|
1710 Property>::const_type
|
Chris@16
|
1711 get_dispatch(const adj_list_helper<Config, Base>& g, Property p,
|
Chris@16
|
1712 boost::vertex_property_tag) {
|
Chris@16
|
1713 typedef typename Config::graph_type Graph;
|
Chris@16
|
1714 typedef typename boost::property_map<Graph, Property>::const_type PA;
|
Chris@16
|
1715 const Graph& cg = static_cast<const Graph&>(g);
|
Chris@16
|
1716 return PA(&cg, p);
|
Chris@16
|
1717 }
|
Chris@16
|
1718
|
Chris@16
|
1719 } // namespace detail
|
Chris@16
|
1720
|
Chris@16
|
1721 // Implementation of the PropertyGraph interface
|
Chris@16
|
1722 template <class Config, class Base, class Property>
|
Chris@16
|
1723 inline
|
Chris@16
|
1724 typename boost::property_map<typename Config::graph_type, Property>::type
|
Chris@16
|
1725 get(Property p, adj_list_helper<Config, Base>& g) {
|
Chris@16
|
1726 typedef typename detail::property_kind_from_graph<adj_list_helper<Config, Base>, Property>::type Kind;
|
Chris@16
|
1727 return detail::get_dispatch(g, p, Kind());
|
Chris@16
|
1728 }
|
Chris@16
|
1729 template <class Config, class Base, class Property>
|
Chris@16
|
1730 inline
|
Chris@16
|
1731 typename boost::property_map<typename Config::graph_type,
|
Chris@16
|
1732 Property>::const_type
|
Chris@16
|
1733 get(Property p, const adj_list_helper<Config, Base>& g) {
|
Chris@16
|
1734 typedef typename detail::property_kind_from_graph<adj_list_helper<Config, Base>, Property>::type Kind;
|
Chris@16
|
1735 return detail::get_dispatch(g, p, Kind());
|
Chris@16
|
1736 }
|
Chris@16
|
1737
|
Chris@16
|
1738 template <class Config, class Base, class Property, class Key>
|
Chris@16
|
1739 inline
|
Chris@16
|
1740 typename boost::property_traits<
|
Chris@16
|
1741 typename boost::property_map<typename Config::graph_type,
|
Chris@16
|
1742 Property>::type
|
Chris@16
|
1743 >::reference
|
Chris@16
|
1744 get(Property p, adj_list_helper<Config, Base>& g, const Key& key) {
|
Chris@16
|
1745 return get(get(p, g), key);
|
Chris@16
|
1746 }
|
Chris@16
|
1747
|
Chris@16
|
1748 template <class Config, class Base, class Property, class Key>
|
Chris@16
|
1749 inline
|
Chris@16
|
1750 typename boost::property_traits<
|
Chris@16
|
1751 typename boost::property_map<typename Config::graph_type,
|
Chris@16
|
1752 Property>::const_type
|
Chris@16
|
1753 >::reference
|
Chris@16
|
1754 get(Property p, const adj_list_helper<Config, Base>& g, const Key& key) {
|
Chris@16
|
1755 return get(get(p, g), key);
|
Chris@16
|
1756 }
|
Chris@16
|
1757
|
Chris@16
|
1758 template <class Config, class Base, class Property, class Key,class Value>
|
Chris@16
|
1759 inline void
|
Chris@16
|
1760 put(Property p, adj_list_helper<Config, Base>& g,
|
Chris@16
|
1761 const Key& key, const Value& value)
|
Chris@16
|
1762 {
|
Chris@16
|
1763 typedef typename Config::graph_type Graph;
|
Chris@16
|
1764 typedef typename boost::property_map<Graph, Property>::type Map;
|
Chris@16
|
1765 Map pmap = get(p, static_cast<Graph&>(g));
|
Chris@16
|
1766 put(pmap, key, value);
|
Chris@16
|
1767 }
|
Chris@16
|
1768
|
Chris@16
|
1769
|
Chris@16
|
1770 //=========================================================================
|
Chris@16
|
1771 // Generalize Adjacency List Implementation
|
Chris@16
|
1772
|
Chris@16
|
1773 struct adj_list_tag { };
|
Chris@16
|
1774
|
Chris@16
|
1775 template <class Derived, class Config, class Base>
|
Chris@16
|
1776 class adj_list_impl
|
Chris@16
|
1777 : public adj_list_helper<Config, Base>
|
Chris@16
|
1778 {
|
Chris@16
|
1779 typedef typename Config::OutEdgeList OutEdgeList;
|
Chris@16
|
1780 typedef typename Config::InEdgeList InEdgeList;
|
Chris@16
|
1781 typedef typename Config::StoredVertexList StoredVertexList;
|
Chris@16
|
1782 public:
|
Chris@16
|
1783 typedef typename Config::stored_vertex stored_vertex;
|
Chris@16
|
1784 typedef typename Config::EdgeContainer EdgeContainer;
|
Chris@16
|
1785 typedef typename Config::vertex_descriptor vertex_descriptor;
|
Chris@16
|
1786 typedef typename Config::edge_descriptor edge_descriptor;
|
Chris@16
|
1787 typedef typename Config::vertex_iterator vertex_iterator;
|
Chris@16
|
1788 typedef typename Config::edge_iterator edge_iterator;
|
Chris@16
|
1789 typedef typename Config::edge_parallel_category edge_parallel_category;
|
Chris@16
|
1790 typedef typename Config::vertices_size_type vertices_size_type;
|
Chris@16
|
1791 typedef typename Config::edges_size_type edges_size_type;
|
Chris@16
|
1792 typedef typename Config::degree_size_type degree_size_type;
|
Chris@16
|
1793 typedef typename Config::edge_property_type edge_property_type;
|
Chris@16
|
1794 typedef adj_list_tag graph_tag;
|
Chris@16
|
1795
|
Chris@16
|
1796 static vertex_descriptor null_vertex()
|
Chris@16
|
1797 {
|
Chris@16
|
1798 return 0;
|
Chris@16
|
1799 }
|
Chris@16
|
1800
|
Chris@16
|
1801 inline adj_list_impl() { }
|
Chris@16
|
1802
|
Chris@16
|
1803 inline adj_list_impl(const adj_list_impl& x) {
|
Chris@16
|
1804 copy_impl(x);
|
Chris@16
|
1805 }
|
Chris@16
|
1806 inline adj_list_impl& operator=(const adj_list_impl& x) {
|
Chris@16
|
1807 this->clear();
|
Chris@16
|
1808 copy_impl(x);
|
Chris@16
|
1809 return *this;
|
Chris@16
|
1810 }
|
Chris@16
|
1811 inline void clear() {
|
Chris@16
|
1812 for (typename StoredVertexList::iterator i = m_vertices.begin();
|
Chris@16
|
1813 i != m_vertices.end(); ++i)
|
Chris@16
|
1814 delete (stored_vertex*)*i;
|
Chris@16
|
1815 m_vertices.clear();
|
Chris@16
|
1816 m_edges.clear();
|
Chris@16
|
1817 }
|
Chris@16
|
1818 inline adj_list_impl(vertices_size_type num_vertices) {
|
Chris@16
|
1819 for (vertices_size_type i = 0; i < num_vertices; ++i)
|
Chris@16
|
1820 add_vertex(static_cast<Derived&>(*this));
|
Chris@16
|
1821 }
|
Chris@16
|
1822 template <class EdgeIterator>
|
Chris@16
|
1823 inline adj_list_impl(vertices_size_type num_vertices,
|
Chris@16
|
1824 EdgeIterator first, EdgeIterator last)
|
Chris@16
|
1825 {
|
Chris@16
|
1826 vertex_descriptor* v = new vertex_descriptor[num_vertices];
|
Chris@16
|
1827 for (vertices_size_type i = 0; i < num_vertices; ++i)
|
Chris@16
|
1828 v[i] = add_vertex(static_cast<Derived&>(*this));
|
Chris@16
|
1829
|
Chris@16
|
1830 while (first != last) {
|
Chris@16
|
1831 add_edge(v[(*first).first], v[(*first).second], *this);
|
Chris@16
|
1832 ++first;
|
Chris@16
|
1833 }
|
Chris@16
|
1834 delete [] v;
|
Chris@16
|
1835 }
|
Chris@16
|
1836 template <class EdgeIterator, class EdgePropertyIterator>
|
Chris@16
|
1837 inline adj_list_impl(vertices_size_type num_vertices,
|
Chris@16
|
1838 EdgeIterator first, EdgeIterator last,
|
Chris@16
|
1839 EdgePropertyIterator ep_iter)
|
Chris@16
|
1840 {
|
Chris@16
|
1841 vertex_descriptor* v = new vertex_descriptor[num_vertices];
|
Chris@16
|
1842 for (vertices_size_type i = 0; i < num_vertices; ++i)
|
Chris@16
|
1843 v[i] = add_vertex(static_cast<Derived&>(*this));
|
Chris@16
|
1844
|
Chris@16
|
1845 while (first != last) {
|
Chris@16
|
1846 add_edge(v[(*first).first], v[(*first).second], *ep_iter, *this);
|
Chris@16
|
1847 ++first;
|
Chris@16
|
1848 ++ep_iter;
|
Chris@16
|
1849 }
|
Chris@16
|
1850 delete [] v;
|
Chris@16
|
1851 }
|
Chris@16
|
1852 ~adj_list_impl() {
|
Chris@16
|
1853 for (typename StoredVertexList::iterator i = m_vertices.begin();
|
Chris@16
|
1854 i != m_vertices.end(); ++i)
|
Chris@16
|
1855 delete (stored_vertex*)*i;
|
Chris@16
|
1856 }
|
Chris@16
|
1857 // protected:
|
Chris@16
|
1858 inline OutEdgeList& out_edge_list(vertex_descriptor v) {
|
Chris@16
|
1859 stored_vertex* sv = (stored_vertex*)v;
|
Chris@16
|
1860 return sv->m_out_edges;
|
Chris@16
|
1861 }
|
Chris@16
|
1862 inline const OutEdgeList& out_edge_list(vertex_descriptor v) const {
|
Chris@16
|
1863 stored_vertex* sv = (stored_vertex*)v;
|
Chris@16
|
1864 return sv->m_out_edges;
|
Chris@16
|
1865 }
|
Chris@16
|
1866 inline StoredVertexList& vertex_set() { return m_vertices; }
|
Chris@16
|
1867 inline const StoredVertexList& vertex_set() const { return m_vertices; }
|
Chris@16
|
1868
|
Chris@16
|
1869 inline void copy_impl(const adj_list_impl& x_)
|
Chris@16
|
1870 {
|
Chris@16
|
1871 const Derived& x = static_cast<const Derived&>(x_);
|
Chris@16
|
1872
|
Chris@16
|
1873 // Would be better to have a constant time way to get from
|
Chris@16
|
1874 // vertices in x to the corresponding vertices in *this.
|
Chris@16
|
1875 std::map<stored_vertex*,stored_vertex*> vertex_map;
|
Chris@16
|
1876
|
Chris@16
|
1877 // Copy the stored vertex objects by adding each vertex
|
Chris@16
|
1878 // and copying its property object.
|
Chris@16
|
1879 vertex_iterator vi, vi_end;
|
Chris@16
|
1880 for (boost::tie(vi, vi_end) = vertices(x); vi != vi_end; ++vi) {
|
Chris@16
|
1881 stored_vertex* v = (stored_vertex*)add_vertex(*this);
|
Chris@16
|
1882 v->m_property = ((stored_vertex*)*vi)->m_property;
|
Chris@16
|
1883 vertex_map[(stored_vertex*)*vi] = v;
|
Chris@16
|
1884 }
|
Chris@16
|
1885 // Copy the edges by adding each edge and copying its
|
Chris@16
|
1886 // property object.
|
Chris@16
|
1887 edge_iterator ei, ei_end;
|
Chris@16
|
1888 for (boost::tie(ei, ei_end) = edges(x); ei != ei_end; ++ei) {
|
Chris@16
|
1889 edge_descriptor e;
|
Chris@16
|
1890 bool inserted;
|
Chris@16
|
1891 vertex_descriptor s = source(*ei,x), t = target(*ei,x);
|
Chris@16
|
1892 boost::tie(e, inserted) = add_edge(vertex_map[(stored_vertex*)s],
|
Chris@16
|
1893 vertex_map[(stored_vertex*)t], *this);
|
Chris@16
|
1894 *((edge_property_type*)e.m_eproperty)
|
Chris@16
|
1895 = *((edge_property_type*)(*ei).m_eproperty);
|
Chris@16
|
1896 }
|
Chris@16
|
1897 }
|
Chris@16
|
1898
|
Chris@16
|
1899
|
Chris@16
|
1900 typename Config::EdgeContainer m_edges;
|
Chris@16
|
1901 StoredVertexList m_vertices;
|
Chris@16
|
1902 };
|
Chris@16
|
1903
|
Chris@16
|
1904 // O(1)
|
Chris@16
|
1905 template <class Derived, class Config, class Base>
|
Chris@16
|
1906 inline typename Config::vertex_descriptor
|
Chris@16
|
1907 add_vertex(adj_list_impl<Derived, Config, Base>& g_)
|
Chris@16
|
1908 {
|
Chris@16
|
1909 Derived& g = static_cast<Derived&>(g_);
|
Chris@16
|
1910 typedef typename Config::stored_vertex stored_vertex;
|
Chris@16
|
1911 stored_vertex* v = new stored_vertex;
|
Chris@16
|
1912 typename Config::StoredVertexList::iterator pos;
|
Chris@16
|
1913 bool inserted;
|
Chris@16
|
1914 boost::tie(pos,inserted) = boost::graph_detail::push(g.m_vertices, v);
|
Chris@16
|
1915 v->m_position = pos;
|
Chris@16
|
1916 g.added_vertex(v);
|
Chris@16
|
1917 return v;
|
Chris@16
|
1918 }
|
Chris@16
|
1919 // O(1)
|
Chris@16
|
1920 template <class Derived, class Config, class Base>
|
Chris@16
|
1921 inline typename Config::vertex_descriptor
|
Chris@16
|
1922 add_vertex(const typename Config::vertex_property_type& p,
|
Chris@16
|
1923 adj_list_impl<Derived, Config, Base>& g_)
|
Chris@16
|
1924 {
|
Chris@16
|
1925 typedef typename Config::vertex_descriptor vertex_descriptor;
|
Chris@16
|
1926 Derived& g = static_cast<Derived&>(g_);
|
Chris@16
|
1927 if (optional<vertex_descriptor> v
|
Chris@16
|
1928 = g.vertex_by_property(get_property_value(p, vertex_bundle)))
|
Chris@16
|
1929 return *v;
|
Chris@16
|
1930
|
Chris@16
|
1931 typedef typename Config::stored_vertex stored_vertex;
|
Chris@16
|
1932 stored_vertex* v = new stored_vertex(p);
|
Chris@16
|
1933 typename Config::StoredVertexList::iterator pos;
|
Chris@16
|
1934 bool inserted;
|
Chris@16
|
1935 boost::tie(pos,inserted) = boost::graph_detail::push(g.m_vertices, v);
|
Chris@16
|
1936 v->m_position = pos;
|
Chris@16
|
1937 g.added_vertex(v);
|
Chris@16
|
1938 return v;
|
Chris@16
|
1939 }
|
Chris@16
|
1940 // O(1)
|
Chris@16
|
1941 template <class Derived, class Config, class Base>
|
Chris@16
|
1942 inline void remove_vertex(typename Config::vertex_descriptor u,
|
Chris@16
|
1943 adj_list_impl<Derived, Config, Base>& g_)
|
Chris@16
|
1944 {
|
Chris@16
|
1945 typedef typename Config::stored_vertex stored_vertex;
|
Chris@16
|
1946 Derived& g = static_cast<Derived&>(g_);
|
Chris@16
|
1947 g.removing_vertex(u, boost::graph_detail::iterator_stability(g_.m_vertices));
|
Chris@16
|
1948 stored_vertex* su = (stored_vertex*)u;
|
Chris@16
|
1949 g.m_vertices.erase(su->m_position);
|
Chris@16
|
1950 delete su;
|
Chris@16
|
1951 }
|
Chris@16
|
1952 // O(V)
|
Chris@16
|
1953 template <class Derived, class Config, class Base>
|
Chris@16
|
1954 inline typename Config::vertex_descriptor
|
Chris@16
|
1955 vertex(typename Config::vertices_size_type n,
|
Chris@16
|
1956 const adj_list_impl<Derived, Config, Base>& g_)
|
Chris@16
|
1957 {
|
Chris@16
|
1958 const Derived& g = static_cast<const Derived&>(g_);
|
Chris@16
|
1959 typename Config::vertex_iterator i = vertices(g).first;
|
Chris@16
|
1960 while (n--) ++i; // std::advance(i, n); (not VC++ portable)
|
Chris@16
|
1961 return *i;
|
Chris@16
|
1962 }
|
Chris@16
|
1963
|
Chris@16
|
1964 //=========================================================================
|
Chris@16
|
1965 // Vector-Backbone Adjacency List Implementation
|
Chris@16
|
1966
|
Chris@16
|
1967 namespace detail {
|
Chris@16
|
1968
|
Chris@16
|
1969 template <class Graph, class vertex_descriptor>
|
Chris@16
|
1970 inline void
|
Chris@16
|
1971 remove_vertex_dispatch(Graph& g, vertex_descriptor u,
|
Chris@16
|
1972 boost::directed_tag)
|
Chris@16
|
1973 {
|
Chris@16
|
1974 typedef typename Graph::edge_parallel_category edge_parallel_category;
|
Chris@16
|
1975 g.m_vertices.erase(g.m_vertices.begin() + u);
|
Chris@16
|
1976 vertex_descriptor V = num_vertices(g);
|
Chris@16
|
1977 if (u != V) {
|
Chris@16
|
1978 for (vertex_descriptor v = 0; v < V; ++v)
|
Chris@16
|
1979 reindex_edge_list(g.out_edge_list(v), u, edge_parallel_category());
|
Chris@16
|
1980 }
|
Chris@16
|
1981 }
|
Chris@16
|
1982
|
Chris@16
|
1983 template <class Graph, class vertex_descriptor>
|
Chris@16
|
1984 inline void
|
Chris@16
|
1985 remove_vertex_dispatch(Graph& g, vertex_descriptor u,
|
Chris@16
|
1986 boost::undirected_tag)
|
Chris@16
|
1987 {
|
Chris@16
|
1988 typedef typename Graph::global_edgelist_selector EdgeListS;
|
Chris@16
|
1989 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
1990
|
Chris@16
|
1991 typedef typename Graph::edge_parallel_category edge_parallel_category;
|
Chris@16
|
1992 g.m_vertices.erase(g.m_vertices.begin() + u);
|
Chris@16
|
1993 vertex_descriptor V = num_vertices(g);
|
Chris@16
|
1994 for (vertex_descriptor v = 0; v < V; ++v)
|
Chris@16
|
1995 reindex_edge_list(g.out_edge_list(v), u,
|
Chris@16
|
1996 edge_parallel_category());
|
Chris@16
|
1997 typedef typename Graph::EdgeContainer Container;
|
Chris@16
|
1998 typedef typename Container::iterator Iter;
|
Chris@16
|
1999 Iter ei = g.m_edges.begin(), ei_end = g.m_edges.end();
|
Chris@16
|
2000 for (; ei != ei_end; ++ei) {
|
Chris@16
|
2001 if (ei->m_source > u)
|
Chris@16
|
2002 --ei->m_source;
|
Chris@16
|
2003 if (ei->m_target > u)
|
Chris@16
|
2004 --ei->m_target;
|
Chris@16
|
2005 }
|
Chris@16
|
2006 }
|
Chris@16
|
2007 template <class Graph, class vertex_descriptor>
|
Chris@16
|
2008 inline void
|
Chris@16
|
2009 remove_vertex_dispatch(Graph& g, vertex_descriptor u,
|
Chris@16
|
2010 boost::bidirectional_tag)
|
Chris@16
|
2011 {
|
Chris@16
|
2012 typedef typename Graph::global_edgelist_selector EdgeListS;
|
Chris@16
|
2013 BOOST_STATIC_ASSERT((!is_same<EdgeListS, vecS>::value));
|
Chris@16
|
2014
|
Chris@16
|
2015 typedef typename Graph::edge_parallel_category edge_parallel_category;
|
Chris@16
|
2016 g.m_vertices.erase(g.m_vertices.begin() + u);
|
Chris@16
|
2017 vertex_descriptor V = num_vertices(g);
|
Chris@16
|
2018 vertex_descriptor v;
|
Chris@16
|
2019 if (u != V) {
|
Chris@16
|
2020 for (v = 0; v < V; ++v)
|
Chris@16
|
2021 reindex_edge_list(g.out_edge_list(v), u,
|
Chris@16
|
2022 edge_parallel_category());
|
Chris@16
|
2023 for (v = 0; v < V; ++v)
|
Chris@16
|
2024 reindex_edge_list(in_edge_list(g, v), u,
|
Chris@16
|
2025 edge_parallel_category());
|
Chris@16
|
2026
|
Chris@16
|
2027 typedef typename Graph::EdgeContainer Container;
|
Chris@16
|
2028 typedef typename Container::iterator Iter;
|
Chris@16
|
2029 Iter ei = g.m_edges.begin(), ei_end = g.m_edges.end();
|
Chris@16
|
2030 for (; ei != ei_end; ++ei) {
|
Chris@16
|
2031 if (ei->m_source > u)
|
Chris@16
|
2032 --ei->m_source;
|
Chris@16
|
2033 if (ei->m_target > u)
|
Chris@16
|
2034 --ei->m_target;
|
Chris@16
|
2035 }
|
Chris@16
|
2036 }
|
Chris@16
|
2037 }
|
Chris@16
|
2038
|
Chris@16
|
2039 template <class EdgeList, class vertex_descriptor>
|
Chris@16
|
2040 inline void
|
Chris@16
|
2041 reindex_edge_list(EdgeList& el, vertex_descriptor u,
|
Chris@16
|
2042 boost::allow_parallel_edge_tag)
|
Chris@16
|
2043 {
|
Chris@16
|
2044 typename EdgeList::iterator ei = el.begin(), e_end = el.end();
|
Chris@16
|
2045 for (; ei != e_end; ++ei)
|
Chris@16
|
2046 if ((*ei).get_target() > u)
|
Chris@16
|
2047 --(*ei).get_target();
|
Chris@16
|
2048 }
|
Chris@16
|
2049 template <class EdgeList, class vertex_descriptor>
|
Chris@16
|
2050 inline void
|
Chris@16
|
2051 reindex_edge_list(EdgeList& el, vertex_descriptor u,
|
Chris@16
|
2052 boost::disallow_parallel_edge_tag)
|
Chris@16
|
2053 {
|
Chris@16
|
2054 typename EdgeList::iterator ei = el.begin(), e_end = el.end();
|
Chris@16
|
2055 while (ei != e_end) {
|
Chris@16
|
2056 typename EdgeList::value_type ce = *ei;
|
Chris@16
|
2057 ++ei;
|
Chris@16
|
2058 if (ce.get_target() > u) {
|
Chris@16
|
2059 el.erase(ce);
|
Chris@16
|
2060 --ce.get_target();
|
Chris@16
|
2061 el.insert(ce);
|
Chris@16
|
2062 }
|
Chris@16
|
2063 }
|
Chris@16
|
2064 }
|
Chris@16
|
2065 } // namespace detail
|
Chris@16
|
2066
|
Chris@16
|
2067 struct vec_adj_list_tag { };
|
Chris@16
|
2068
|
Chris@16
|
2069 template <class Graph, class Config, class Base>
|
Chris@16
|
2070 class vec_adj_list_impl
|
Chris@16
|
2071 : public adj_list_helper<Config, Base>
|
Chris@16
|
2072 {
|
Chris@16
|
2073 typedef typename Config::OutEdgeList OutEdgeList;
|
Chris@16
|
2074 typedef typename Config::InEdgeList InEdgeList;
|
Chris@16
|
2075 typedef typename Config::StoredVertexList StoredVertexList;
|
Chris@16
|
2076 public:
|
Chris@16
|
2077 typedef typename Config::vertex_descriptor vertex_descriptor;
|
Chris@16
|
2078 typedef typename Config::edge_descriptor edge_descriptor;
|
Chris@16
|
2079 typedef typename Config::out_edge_iterator out_edge_iterator;
|
Chris@16
|
2080 typedef typename Config::edge_iterator edge_iterator;
|
Chris@16
|
2081 typedef typename Config::directed_category directed_category;
|
Chris@16
|
2082 typedef typename Config::vertices_size_type vertices_size_type;
|
Chris@16
|
2083 typedef typename Config::edges_size_type edges_size_type;
|
Chris@16
|
2084 typedef typename Config::degree_size_type degree_size_type;
|
Chris@16
|
2085 typedef typename Config::StoredEdge StoredEdge;
|
Chris@16
|
2086 typedef typename Config::stored_vertex stored_vertex;
|
Chris@16
|
2087 typedef typename Config::EdgeContainer EdgeContainer;
|
Chris@16
|
2088 typedef typename Config::edge_property_type edge_property_type;
|
Chris@16
|
2089 typedef vec_adj_list_tag graph_tag;
|
Chris@16
|
2090
|
Chris@16
|
2091 static vertex_descriptor null_vertex()
|
Chris@16
|
2092 {
|
Chris@16
|
2093 return (std::numeric_limits<vertex_descriptor>::max)();
|
Chris@16
|
2094 }
|
Chris@16
|
2095
|
Chris@16
|
2096 inline vec_adj_list_impl() { }
|
Chris@16
|
2097
|
Chris@16
|
2098 inline vec_adj_list_impl(const vec_adj_list_impl& x) {
|
Chris@16
|
2099 copy_impl(x);
|
Chris@16
|
2100 }
|
Chris@16
|
2101 inline vec_adj_list_impl& operator=(const vec_adj_list_impl& x) {
|
Chris@16
|
2102 this->clear();
|
Chris@16
|
2103 copy_impl(x);
|
Chris@16
|
2104 return *this;
|
Chris@16
|
2105 }
|
Chris@16
|
2106 inline void clear() {
|
Chris@16
|
2107 m_vertices.clear();
|
Chris@16
|
2108 m_edges.clear();
|
Chris@16
|
2109 }
|
Chris@16
|
2110
|
Chris@16
|
2111 inline vec_adj_list_impl(vertices_size_type _num_vertices)
|
Chris@16
|
2112 : m_vertices(_num_vertices) { }
|
Chris@16
|
2113
|
Chris@16
|
2114 template <class EdgeIterator>
|
Chris@16
|
2115 inline vec_adj_list_impl(vertices_size_type num_vertices,
|
Chris@16
|
2116 EdgeIterator first, EdgeIterator last)
|
Chris@16
|
2117 : m_vertices(num_vertices)
|
Chris@16
|
2118 {
|
Chris@16
|
2119 while (first != last) {
|
Chris@16
|
2120 add_edge((*first).first, (*first).second,
|
Chris@16
|
2121 static_cast<Graph&>(*this));
|
Chris@16
|
2122 ++first;
|
Chris@16
|
2123 }
|
Chris@16
|
2124 }
|
Chris@16
|
2125 template <class EdgeIterator, class EdgePropertyIterator>
|
Chris@16
|
2126 inline vec_adj_list_impl(vertices_size_type num_vertices,
|
Chris@16
|
2127 EdgeIterator first, EdgeIterator last,
|
Chris@16
|
2128 EdgePropertyIterator ep_iter)
|
Chris@16
|
2129 : m_vertices(num_vertices)
|
Chris@16
|
2130 {
|
Chris@16
|
2131 while (first != last) {
|
Chris@16
|
2132 add_edge((*first).first, (*first).second, *ep_iter,
|
Chris@16
|
2133 static_cast<Graph&>(*this));
|
Chris@16
|
2134 ++first;
|
Chris@16
|
2135 ++ep_iter;
|
Chris@16
|
2136 }
|
Chris@16
|
2137 }
|
Chris@16
|
2138
|
Chris@16
|
2139 // protected:
|
Chris@16
|
2140 inline boost::integer_range<vertex_descriptor> vertex_set() const {
|
Chris@16
|
2141 return boost::integer_range<vertex_descriptor>(0, m_vertices.size());
|
Chris@16
|
2142 }
|
Chris@16
|
2143 inline OutEdgeList& out_edge_list(vertex_descriptor v) {
|
Chris@16
|
2144 return m_vertices[v].m_out_edges;
|
Chris@16
|
2145 }
|
Chris@16
|
2146 inline const OutEdgeList& out_edge_list(vertex_descriptor v) const {
|
Chris@16
|
2147 return m_vertices[v].m_out_edges;
|
Chris@16
|
2148 }
|
Chris@16
|
2149 inline void copy_impl(const vec_adj_list_impl& x_)
|
Chris@16
|
2150 {
|
Chris@16
|
2151 const Graph& x = static_cast<const Graph&>(x_);
|
Chris@16
|
2152 // Copy the stored vertex objects by adding each vertex
|
Chris@16
|
2153 // and copying its property object.
|
Chris@16
|
2154 for (vertices_size_type i = 0; i < num_vertices(x); ++i) {
|
Chris@16
|
2155 vertex_descriptor v = add_vertex(*this);
|
Chris@16
|
2156 m_vertices[v].m_property = x.m_vertices[i].m_property;
|
Chris@16
|
2157 }
|
Chris@16
|
2158 // Copy the edges by adding each edge and copying its
|
Chris@16
|
2159 // property object.
|
Chris@16
|
2160 edge_iterator ei, ei_end;
|
Chris@16
|
2161 for (boost::tie(ei, ei_end) = edges(x); ei != ei_end; ++ei) {
|
Chris@16
|
2162 edge_descriptor e;
|
Chris@16
|
2163 bool inserted;
|
Chris@16
|
2164 boost::tie(e, inserted) = add_edge(source(*ei,x), target(*ei,x) , *this);
|
Chris@16
|
2165 *((edge_property_type*)e.m_eproperty)
|
Chris@16
|
2166 = *((edge_property_type*)(*ei).m_eproperty);
|
Chris@16
|
2167 }
|
Chris@16
|
2168 }
|
Chris@16
|
2169 typename Config::EdgeContainer m_edges;
|
Chris@16
|
2170 StoredVertexList m_vertices;
|
Chris@16
|
2171 };
|
Chris@16
|
2172 // Had to make these non-members to avoid accidental instantiation
|
Chris@16
|
2173 // on SGI MIPSpro C++
|
Chris@16
|
2174 template <class G, class C, class B>
|
Chris@16
|
2175 inline typename C::InEdgeList&
|
Chris@16
|
2176 in_edge_list(vec_adj_list_impl<G,C,B>& g,
|
Chris@16
|
2177 typename C::vertex_descriptor v) {
|
Chris@16
|
2178 return g.m_vertices[v].m_in_edges;
|
Chris@16
|
2179 }
|
Chris@16
|
2180 template <class G, class C, class B>
|
Chris@16
|
2181 inline const typename C::InEdgeList&
|
Chris@16
|
2182 in_edge_list(const vec_adj_list_impl<G,C,B>& g,
|
Chris@16
|
2183 typename C::vertex_descriptor v) {
|
Chris@16
|
2184 return g.m_vertices[v].m_in_edges;
|
Chris@16
|
2185 }
|
Chris@16
|
2186
|
Chris@16
|
2187 // O(1)
|
Chris@16
|
2188 template <class Graph, class Config, class Base>
|
Chris@16
|
2189 inline typename Config::vertex_descriptor
|
Chris@16
|
2190 add_vertex(vec_adj_list_impl<Graph, Config, Base>& g_) {
|
Chris@16
|
2191 Graph& g = static_cast<Graph&>(g_);
|
Chris@16
|
2192 g.m_vertices.resize(g.m_vertices.size() + 1);
|
Chris@16
|
2193 g.added_vertex(g.m_vertices.size() - 1);
|
Chris@16
|
2194 return g.m_vertices.size() - 1;
|
Chris@16
|
2195 }
|
Chris@16
|
2196
|
Chris@16
|
2197 template <class Graph, class Config, class Base>
|
Chris@16
|
2198 inline typename Config::vertex_descriptor
|
Chris@16
|
2199 add_vertex(const typename Config::vertex_property_type& p,
|
Chris@16
|
2200 vec_adj_list_impl<Graph, Config, Base>& g_) {
|
Chris@16
|
2201 typedef typename Config::vertex_descriptor vertex_descriptor;
|
Chris@16
|
2202 Graph& g = static_cast<Graph&>(g_);
|
Chris@16
|
2203 if (optional<vertex_descriptor> v
|
Chris@16
|
2204 = g.vertex_by_property(get_property_value(p, vertex_bundle)))
|
Chris@16
|
2205 return *v;
|
Chris@16
|
2206 typedef typename Config::stored_vertex stored_vertex;
|
Chris@16
|
2207 g.m_vertices.push_back(stored_vertex(p));
|
Chris@16
|
2208 g.added_vertex(g.m_vertices.size() - 1);
|
Chris@16
|
2209 return g.m_vertices.size() - 1;
|
Chris@16
|
2210 }
|
Chris@16
|
2211
|
Chris@16
|
2212 // Here we override the directed_graph_helper add_edge() function
|
Chris@16
|
2213 // so that the number of vertices is automatically changed if
|
Chris@16
|
2214 // either u or v is greater than the number of vertices.
|
Chris@16
|
2215 template <class Graph, class Config, class Base>
|
Chris@16
|
2216 inline std::pair<typename Config::edge_descriptor, bool>
|
Chris@16
|
2217 add_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
2218 typename Config::vertex_descriptor v,
|
Chris@16
|
2219 const typename Config::edge_property_type& p,
|
Chris@16
|
2220 vec_adj_list_impl<Graph, Config, Base>& g_)
|
Chris@16
|
2221 {
|
Chris@16
|
2222 BOOST_USING_STD_MAX();
|
Chris@16
|
2223 typename Config::vertex_descriptor x = max BOOST_PREVENT_MACRO_SUBSTITUTION(u, v);
|
Chris@16
|
2224 if (x >= num_vertices(g_))
|
Chris@16
|
2225 g_.m_vertices.resize(x + 1);
|
Chris@16
|
2226 adj_list_helper<Config, Base>& g = g_;
|
Chris@16
|
2227 return add_edge(u, v, p, g);
|
Chris@16
|
2228 }
|
Chris@16
|
2229 template <class Graph, class Config, class Base>
|
Chris@16
|
2230 inline std::pair<typename Config::edge_descriptor, bool>
|
Chris@16
|
2231 add_edge(typename Config::vertex_descriptor u,
|
Chris@16
|
2232 typename Config::vertex_descriptor v,
|
Chris@16
|
2233 vec_adj_list_impl<Graph, Config, Base>& g_)
|
Chris@16
|
2234 {
|
Chris@16
|
2235 typename Config::edge_property_type p;
|
Chris@16
|
2236 return add_edge(u, v, p, g_);
|
Chris@16
|
2237 }
|
Chris@16
|
2238
|
Chris@16
|
2239
|
Chris@16
|
2240 // O(V + E)
|
Chris@16
|
2241 template <class Graph, class Config, class Base>
|
Chris@16
|
2242 inline void remove_vertex(typename Config::vertex_descriptor v,
|
Chris@16
|
2243 vec_adj_list_impl<Graph, Config, Base>& g_)
|
Chris@16
|
2244 {
|
Chris@16
|
2245 typedef typename Config::directed_category Cat;
|
Chris@16
|
2246 Graph& g = static_cast<Graph&>(g_);
|
Chris@16
|
2247 g.removing_vertex(v, boost::graph_detail::iterator_stability(g_.m_vertices));
|
Chris@16
|
2248 detail::remove_vertex_dispatch(g, v, Cat());
|
Chris@16
|
2249 }
|
Chris@16
|
2250 // O(1)
|
Chris@16
|
2251 template <class Graph, class Config, class Base>
|
Chris@16
|
2252 inline typename Config::vertex_descriptor
|
Chris@16
|
2253 vertex(typename Config::vertices_size_type n,
|
Chris@16
|
2254 const vec_adj_list_impl<Graph, Config, Base>&)
|
Chris@16
|
2255 {
|
Chris@16
|
2256 return n;
|
Chris@16
|
2257 }
|
Chris@16
|
2258
|
Chris@16
|
2259
|
Chris@16
|
2260 namespace detail {
|
Chris@16
|
2261
|
Chris@16
|
2262 //=========================================================================
|
Chris@16
|
2263 // Adjacency List Generator
|
Chris@16
|
2264
|
Chris@16
|
2265 template <class Graph, class VertexListS, class OutEdgeListS,
|
Chris@16
|
2266 class DirectedS, class VertexProperty, class EdgeProperty,
|
Chris@16
|
2267 class GraphProperty, class EdgeListS>
|
Chris@16
|
2268 struct adj_list_gen
|
Chris@16
|
2269 {
|
Chris@16
|
2270 typedef typename detail::is_random_access<VertexListS>::type
|
Chris@16
|
2271 is_rand_access;
|
Chris@16
|
2272 typedef typename has_property<EdgeProperty>::type has_edge_property;
|
Chris@16
|
2273 typedef typename DirectedS::is_directed_t DirectedT;
|
Chris@16
|
2274 typedef typename DirectedS::is_bidir_t BidirectionalT;
|
Chris@16
|
2275
|
Chris@16
|
2276 struct config
|
Chris@16
|
2277 {
|
Chris@16
|
2278 typedef OutEdgeListS edgelist_selector;
|
Chris@16
|
2279 typedef EdgeListS global_edgelist_selector;
|
Chris@16
|
2280
|
Chris@16
|
2281 typedef Graph graph_type;
|
Chris@16
|
2282 typedef EdgeProperty edge_property_type;
|
Chris@16
|
2283 typedef VertexProperty vertex_property_type;
|
Chris@16
|
2284 typedef GraphProperty graph_property_type;
|
Chris@16
|
2285 typedef std::size_t vertices_size_type;
|
Chris@16
|
2286
|
Chris@16
|
2287 typedef adjacency_list_traits<OutEdgeListS, VertexListS, DirectedS>
|
Chris@16
|
2288 Traits;
|
Chris@16
|
2289
|
Chris@16
|
2290 typedef typename Traits::directed_category directed_category;
|
Chris@16
|
2291 typedef typename Traits::edge_parallel_category edge_parallel_category;
|
Chris@16
|
2292 typedef typename Traits::vertex_descriptor vertex_descriptor;
|
Chris@16
|
2293 typedef typename Traits::edge_descriptor edge_descriptor;
|
Chris@16
|
2294
|
Chris@16
|
2295 typedef void* vertex_ptr;
|
Chris@16
|
2296
|
Chris@16
|
2297 // need to reorganize this to avoid instantiating stuff
|
Chris@16
|
2298 // that doesn't get used -JGS
|
Chris@16
|
2299
|
Chris@16
|
2300 // VertexList and vertex_iterator
|
Chris@16
|
2301 typedef typename container_gen<VertexListS,
|
Chris@16
|
2302 vertex_ptr>::type SeqVertexList;
|
Chris@16
|
2303 typedef boost::integer_range<vertex_descriptor> RandVertexList;
|
Chris@16
|
2304 typedef typename mpl::if_<is_rand_access,
|
Chris@16
|
2305 RandVertexList, SeqVertexList>::type VertexList;
|
Chris@16
|
2306
|
Chris@16
|
2307 typedef typename VertexList::iterator vertex_iterator;
|
Chris@16
|
2308
|
Chris@16
|
2309 // EdgeContainer and StoredEdge
|
Chris@16
|
2310
|
Chris@16
|
2311 typedef typename container_gen<EdgeListS,
|
Chris@16
|
2312 list_edge<vertex_descriptor, EdgeProperty> >::type EdgeContainer;
|
Chris@16
|
2313
|
Chris@16
|
2314 typedef typename mpl::and_<DirectedT,
|
Chris@16
|
2315 typename mpl::not_<BidirectionalT>::type >::type on_edge_storage;
|
Chris@16
|
2316
|
Chris@16
|
2317 typedef typename mpl::if_<on_edge_storage,
|
Chris@16
|
2318 std::size_t, typename EdgeContainer::size_type
|
Chris@16
|
2319 >::type edges_size_type;
|
Chris@16
|
2320
|
Chris@16
|
2321 typedef typename EdgeContainer::iterator EdgeIter;
|
Chris@16
|
2322
|
Chris@16
|
2323 typedef typename detail::is_random_access<EdgeListS>::type is_edge_ra;
|
Chris@16
|
2324
|
Chris@16
|
2325 typedef typename mpl::if_<on_edge_storage,
|
Chris@16
|
2326 stored_edge_property<vertex_descriptor, EdgeProperty>,
|
Chris@16
|
2327 typename mpl::if_<is_edge_ra,
|
Chris@16
|
2328 stored_ra_edge_iter<vertex_descriptor, EdgeContainer, EdgeProperty>,
|
Chris@16
|
2329 stored_edge_iter<vertex_descriptor, EdgeIter, EdgeProperty>
|
Chris@16
|
2330 >::type
|
Chris@16
|
2331 >::type StoredEdge;
|
Chris@16
|
2332
|
Chris@16
|
2333 // Adjacency Types
|
Chris@16
|
2334
|
Chris@16
|
2335 typedef typename container_gen<OutEdgeListS, StoredEdge>::type
|
Chris@16
|
2336 OutEdgeList;
|
Chris@16
|
2337 typedef typename OutEdgeList::size_type degree_size_type;
|
Chris@16
|
2338 typedef typename OutEdgeList::iterator OutEdgeIter;
|
Chris@16
|
2339
|
Chris@16
|
2340 typedef boost::detail::iterator_traits<OutEdgeIter> OutEdgeIterTraits;
|
Chris@16
|
2341 typedef typename OutEdgeIterTraits::iterator_category OutEdgeIterCat;
|
Chris@16
|
2342 typedef typename OutEdgeIterTraits::difference_type OutEdgeIterDiff;
|
Chris@16
|
2343
|
Chris@16
|
2344 typedef out_edge_iter<
|
Chris@16
|
2345 OutEdgeIter, vertex_descriptor, edge_descriptor, OutEdgeIterDiff
|
Chris@16
|
2346 > out_edge_iterator;
|
Chris@16
|
2347
|
Chris@16
|
2348 typedef typename adjacency_iterator_generator<graph_type,
|
Chris@16
|
2349 vertex_descriptor, out_edge_iterator>::type adjacency_iterator;
|
Chris@16
|
2350
|
Chris@16
|
2351 typedef OutEdgeList InEdgeList;
|
Chris@16
|
2352 typedef OutEdgeIter InEdgeIter;
|
Chris@16
|
2353 typedef OutEdgeIterCat InEdgeIterCat;
|
Chris@16
|
2354 typedef OutEdgeIterDiff InEdgeIterDiff;
|
Chris@16
|
2355
|
Chris@16
|
2356 typedef in_edge_iter<
|
Chris@16
|
2357 InEdgeIter, vertex_descriptor, edge_descriptor, InEdgeIterDiff
|
Chris@16
|
2358 > in_edge_iterator;
|
Chris@16
|
2359
|
Chris@16
|
2360 typedef typename inv_adjacency_iterator_generator<graph_type,
|
Chris@16
|
2361 vertex_descriptor, in_edge_iterator>::type inv_adjacency_iterator;
|
Chris@16
|
2362
|
Chris@16
|
2363 // Edge Iterator
|
Chris@16
|
2364
|
Chris@16
|
2365 typedef boost::detail::iterator_traits<EdgeIter> EdgeIterTraits;
|
Chris@16
|
2366 typedef typename EdgeIterTraits::iterator_category EdgeIterCat;
|
Chris@16
|
2367 typedef typename EdgeIterTraits::difference_type EdgeIterDiff;
|
Chris@16
|
2368
|
Chris@16
|
2369 typedef undirected_edge_iter<
|
Chris@16
|
2370 EdgeIter
|
Chris@16
|
2371 , edge_descriptor
|
Chris@16
|
2372 , EdgeIterDiff
|
Chris@16
|
2373 > UndirectedEdgeIter; // also used for bidirectional
|
Chris@16
|
2374
|
Chris@16
|
2375 typedef adj_list_edge_iterator<vertex_iterator, out_edge_iterator,
|
Chris@16
|
2376 graph_type> DirectedEdgeIter;
|
Chris@16
|
2377
|
Chris@16
|
2378 typedef typename mpl::if_<on_edge_storage,
|
Chris@16
|
2379 DirectedEdgeIter, UndirectedEdgeIter>::type edge_iterator;
|
Chris@16
|
2380
|
Chris@16
|
2381 // stored_vertex and StoredVertexList
|
Chris@16
|
2382 typedef typename container_gen<VertexListS, vertex_ptr>::type
|
Chris@16
|
2383 SeqStoredVertexList;
|
Chris@16
|
2384 struct seq_stored_vertex {
|
Chris@16
|
2385 seq_stored_vertex() { }
|
Chris@16
|
2386 seq_stored_vertex(const VertexProperty& p) : m_property(p) { }
|
Chris@16
|
2387 OutEdgeList m_out_edges;
|
Chris@16
|
2388 VertexProperty m_property;
|
Chris@16
|
2389 typename SeqStoredVertexList::iterator m_position;
|
Chris@16
|
2390 };
|
Chris@16
|
2391 struct bidir_seq_stored_vertex {
|
Chris@16
|
2392 bidir_seq_stored_vertex() { }
|
Chris@16
|
2393 bidir_seq_stored_vertex(const VertexProperty& p) : m_property(p) { }
|
Chris@16
|
2394 OutEdgeList m_out_edges;
|
Chris@16
|
2395 InEdgeList m_in_edges;
|
Chris@16
|
2396 VertexProperty m_property;
|
Chris@16
|
2397 typename SeqStoredVertexList::iterator m_position;
|
Chris@16
|
2398 };
|
Chris@16
|
2399 struct rand_stored_vertex {
|
Chris@16
|
2400 rand_stored_vertex() { }
|
Chris@16
|
2401 rand_stored_vertex(const VertexProperty& p) : m_property(p) { }
|
Chris@16
|
2402 OutEdgeList m_out_edges;
|
Chris@16
|
2403 VertexProperty m_property;
|
Chris@16
|
2404 };
|
Chris@16
|
2405 struct bidir_rand_stored_vertex {
|
Chris@16
|
2406 bidir_rand_stored_vertex() { }
|
Chris@16
|
2407 bidir_rand_stored_vertex(const VertexProperty& p) : m_property(p) { }
|
Chris@16
|
2408 OutEdgeList m_out_edges;
|
Chris@16
|
2409 InEdgeList m_in_edges;
|
Chris@16
|
2410 VertexProperty m_property;
|
Chris@16
|
2411 };
|
Chris@16
|
2412 typedef typename mpl::if_<is_rand_access,
|
Chris@16
|
2413 typename mpl::if_<BidirectionalT,
|
Chris@16
|
2414 bidir_rand_stored_vertex, rand_stored_vertex>::type,
|
Chris@16
|
2415 typename mpl::if_<BidirectionalT,
|
Chris@16
|
2416 bidir_seq_stored_vertex, seq_stored_vertex>::type
|
Chris@16
|
2417 >::type StoredVertex;
|
Chris@16
|
2418 struct stored_vertex : public StoredVertex {
|
Chris@16
|
2419 stored_vertex() { }
|
Chris@16
|
2420 stored_vertex(const VertexProperty& p) : StoredVertex(p) { }
|
Chris@16
|
2421 };
|
Chris@16
|
2422
|
Chris@16
|
2423 typedef typename container_gen<VertexListS, stored_vertex>::type
|
Chris@16
|
2424 RandStoredVertexList;
|
Chris@16
|
2425 typedef typename mpl::if_< is_rand_access,
|
Chris@16
|
2426 RandStoredVertexList, SeqStoredVertexList>::type StoredVertexList;
|
Chris@16
|
2427 }; // end of config
|
Chris@16
|
2428
|
Chris@16
|
2429
|
Chris@16
|
2430 typedef typename mpl::if_<BidirectionalT,
|
Chris@16
|
2431 bidirectional_graph_helper_with_property<config>,
|
Chris@16
|
2432 typename mpl::if_<DirectedT,
|
Chris@16
|
2433 directed_graph_helper<config>,
|
Chris@16
|
2434 undirected_graph_helper<config>
|
Chris@16
|
2435 >::type
|
Chris@16
|
2436 >::type DirectedHelper;
|
Chris@16
|
2437
|
Chris@16
|
2438 typedef typename mpl::if_<is_rand_access,
|
Chris@16
|
2439 vec_adj_list_impl<Graph, config, DirectedHelper>,
|
Chris@16
|
2440 adj_list_impl<Graph, config, DirectedHelper>
|
Chris@16
|
2441 >::type type;
|
Chris@16
|
2442
|
Chris@16
|
2443 };
|
Chris@16
|
2444
|
Chris@16
|
2445 } // namespace detail
|
Chris@16
|
2446
|
Chris@16
|
2447 //=========================================================================
|
Chris@16
|
2448 // Vertex Property Maps
|
Chris@16
|
2449
|
Chris@16
|
2450 template <class Graph, class ValueType, class Reference, class Tag>
|
Chris@16
|
2451 struct adj_list_vertex_property_map
|
Chris@16
|
2452 : public boost::put_get_helper<
|
Chris@16
|
2453 Reference,
|
Chris@16
|
2454 adj_list_vertex_property_map<Graph, ValueType, Reference, Tag>
|
Chris@16
|
2455 >
|
Chris@16
|
2456 {
|
Chris@16
|
2457 typedef typename Graph::stored_vertex StoredVertex;
|
Chris@16
|
2458 typedef ValueType value_type;
|
Chris@16
|
2459 typedef Reference reference;
|
Chris@16
|
2460 typedef typename Graph::vertex_descriptor key_type;
|
Chris@16
|
2461 typedef boost::lvalue_property_map_tag category;
|
Chris@16
|
2462 inline adj_list_vertex_property_map(const Graph* = 0, Tag tag = Tag()): m_tag(tag) { }
|
Chris@16
|
2463 inline Reference operator[](key_type v) const {
|
Chris@16
|
2464 StoredVertex* sv = (StoredVertex*)v;
|
Chris@16
|
2465 return get_property_value(sv->m_property, m_tag);
|
Chris@16
|
2466 }
|
Chris@16
|
2467 inline Reference operator()(key_type v) const {
|
Chris@16
|
2468 return this->operator[](v);
|
Chris@16
|
2469 }
|
Chris@16
|
2470 Tag m_tag;
|
Chris@16
|
2471 };
|
Chris@16
|
2472
|
Chris@16
|
2473 template <class Graph, class Property, class PropRef>
|
Chris@16
|
2474 struct adj_list_vertex_all_properties_map
|
Chris@16
|
2475 : public boost::put_get_helper<PropRef,
|
Chris@16
|
2476 adj_list_vertex_all_properties_map<Graph, Property, PropRef>
|
Chris@16
|
2477 >
|
Chris@16
|
2478 {
|
Chris@16
|
2479 typedef typename Graph::stored_vertex StoredVertex;
|
Chris@16
|
2480 typedef Property value_type;
|
Chris@16
|
2481 typedef PropRef reference;
|
Chris@16
|
2482 typedef typename Graph::vertex_descriptor key_type;
|
Chris@16
|
2483 typedef boost::lvalue_property_map_tag category;
|
Chris@16
|
2484 inline adj_list_vertex_all_properties_map(const Graph* = 0, vertex_all_t = vertex_all_t()) { }
|
Chris@16
|
2485 inline PropRef operator[](key_type v) const {
|
Chris@16
|
2486 StoredVertex* sv = (StoredVertex*)v;
|
Chris@16
|
2487 return sv->m_property;
|
Chris@16
|
2488 }
|
Chris@16
|
2489 inline PropRef operator()(key_type v) const {
|
Chris@16
|
2490 return this->operator[](v);
|
Chris@16
|
2491 }
|
Chris@16
|
2492 };
|
Chris@16
|
2493
|
Chris@16
|
2494 template <class Graph, class GraphPtr, class ValueType, class Reference,
|
Chris@16
|
2495 class Tag>
|
Chris@16
|
2496 struct vec_adj_list_vertex_property_map
|
Chris@16
|
2497 : public boost::put_get_helper<
|
Chris@16
|
2498 Reference,
|
Chris@16
|
2499 vec_adj_list_vertex_property_map<Graph,GraphPtr,ValueType,Reference,
|
Chris@16
|
2500 Tag>
|
Chris@16
|
2501 >
|
Chris@16
|
2502 {
|
Chris@16
|
2503 typedef ValueType value_type;
|
Chris@16
|
2504 typedef Reference reference;
|
Chris@16
|
2505 typedef typename boost::graph_traits<Graph>::vertex_descriptor key_type;
|
Chris@16
|
2506 typedef boost::lvalue_property_map_tag category;
|
Chris@16
|
2507 vec_adj_list_vertex_property_map(GraphPtr g = 0, Tag tag = Tag()) : m_g(g), m_tag(tag) { }
|
Chris@16
|
2508 inline Reference operator[](key_type v) const {
|
Chris@16
|
2509 return get_property_value(m_g->m_vertices[v].m_property, m_tag);
|
Chris@16
|
2510 }
|
Chris@16
|
2511 inline Reference operator()(key_type v) const {
|
Chris@16
|
2512 return this->operator[](v);
|
Chris@16
|
2513 }
|
Chris@16
|
2514 GraphPtr m_g;
|
Chris@16
|
2515 Tag m_tag;
|
Chris@16
|
2516 };
|
Chris@16
|
2517
|
Chris@16
|
2518 template <class Graph, class GraphPtr, class Property, class PropertyRef>
|
Chris@16
|
2519 struct vec_adj_list_vertex_all_properties_map
|
Chris@16
|
2520 : public boost::put_get_helper<PropertyRef,
|
Chris@16
|
2521 vec_adj_list_vertex_all_properties_map<Graph,GraphPtr,Property,
|
Chris@16
|
2522 PropertyRef>
|
Chris@16
|
2523 >
|
Chris@16
|
2524 {
|
Chris@16
|
2525 typedef Property value_type;
|
Chris@16
|
2526 typedef PropertyRef reference;
|
Chris@16
|
2527 typedef typename boost::graph_traits<Graph>::vertex_descriptor key_type;
|
Chris@16
|
2528 typedef boost::lvalue_property_map_tag category;
|
Chris@16
|
2529 vec_adj_list_vertex_all_properties_map(GraphPtr g = 0, vertex_all_t = vertex_all_t()) : m_g(g) { }
|
Chris@16
|
2530 inline PropertyRef operator[](key_type v) const {
|
Chris@16
|
2531 return m_g->m_vertices[v].m_property;
|
Chris@16
|
2532 }
|
Chris@16
|
2533 inline PropertyRef operator()(key_type v) const {
|
Chris@16
|
2534 return this->operator[](v);
|
Chris@16
|
2535 }
|
Chris@16
|
2536 GraphPtr m_g;
|
Chris@16
|
2537 };
|
Chris@16
|
2538
|
Chris@16
|
2539 struct adj_list_any_vertex_pa {
|
Chris@16
|
2540 template <class Tag, class Graph, class Property>
|
Chris@16
|
2541 struct bind_ {
|
Chris@16
|
2542 typedef typename property_value<Property, Tag>::type value_type;
|
Chris@16
|
2543 typedef value_type& reference;
|
Chris@16
|
2544 typedef const value_type& const_reference;
|
Chris@16
|
2545
|
Chris@16
|
2546 typedef adj_list_vertex_property_map
|
Chris@16
|
2547 <Graph, value_type, reference, Tag> type;
|
Chris@16
|
2548 typedef adj_list_vertex_property_map
|
Chris@16
|
2549 <Graph, value_type, const_reference, Tag> const_type;
|
Chris@16
|
2550 };
|
Chris@16
|
2551 };
|
Chris@16
|
2552 struct adj_list_all_vertex_pa {
|
Chris@16
|
2553 template <class Tag, class Graph, class Property>
|
Chris@16
|
2554 struct bind_ {
|
Chris@16
|
2555 typedef typename Graph::vertex_descriptor Vertex;
|
Chris@16
|
2556 typedef adj_list_vertex_all_properties_map<Graph,Property,
|
Chris@16
|
2557 Property&> type;
|
Chris@16
|
2558 typedef adj_list_vertex_all_properties_map<Graph,Property,
|
Chris@16
|
2559 const Property&> const_type;
|
Chris@16
|
2560 };
|
Chris@16
|
2561 };
|
Chris@16
|
2562
|
Chris@16
|
2563 template <class Property, class Vertex>
|
Chris@16
|
2564 struct vec_adj_list_vertex_id_map
|
Chris@16
|
2565 : public boost::put_get_helper<
|
Chris@16
|
2566 Vertex, vec_adj_list_vertex_id_map<Property, Vertex>
|
Chris@16
|
2567 >
|
Chris@16
|
2568 {
|
Chris@16
|
2569 typedef Vertex value_type;
|
Chris@16
|
2570 typedef Vertex key_type;
|
Chris@16
|
2571 typedef Vertex reference;
|
Chris@16
|
2572 typedef boost::readable_property_map_tag category;
|
Chris@16
|
2573 inline vec_adj_list_vertex_id_map() { }
|
Chris@16
|
2574 template <class Graph>
|
Chris@16
|
2575 inline vec_adj_list_vertex_id_map(const Graph&, vertex_index_t) { }
|
Chris@16
|
2576 inline value_type operator[](key_type v) const { return v; }
|
Chris@16
|
2577 inline value_type operator()(key_type v) const { return v; }
|
Chris@16
|
2578 };
|
Chris@16
|
2579
|
Chris@16
|
2580 struct vec_adj_list_any_vertex_pa {
|
Chris@16
|
2581 template <class Tag, class Graph, class Property>
|
Chris@16
|
2582 struct bind_ {
|
Chris@16
|
2583 typedef typename property_value<Property, Tag>::type value_type;
|
Chris@16
|
2584 typedef value_type& reference;
|
Chris@16
|
2585 typedef const value_type& const_reference;
|
Chris@16
|
2586
|
Chris@16
|
2587 typedef vec_adj_list_vertex_property_map
|
Chris@16
|
2588 <Graph, Graph*, value_type, reference, Tag> type;
|
Chris@16
|
2589 typedef vec_adj_list_vertex_property_map
|
Chris@16
|
2590 <Graph, const Graph*, value_type, const_reference, Tag> const_type;
|
Chris@16
|
2591 };
|
Chris@16
|
2592 };
|
Chris@16
|
2593 struct vec_adj_list_id_vertex_pa {
|
Chris@16
|
2594 template <class Tag, class Graph, class Property>
|
Chris@16
|
2595 struct bind_ {
|
Chris@16
|
2596 typedef typename Graph::vertex_descriptor Vertex;
|
Chris@16
|
2597 typedef vec_adj_list_vertex_id_map<Property, Vertex> type;
|
Chris@16
|
2598 typedef vec_adj_list_vertex_id_map<Property, Vertex> const_type;
|
Chris@16
|
2599 };
|
Chris@16
|
2600 };
|
Chris@16
|
2601 struct vec_adj_list_all_vertex_pa {
|
Chris@16
|
2602 template <class Tag, class Graph, class Property>
|
Chris@16
|
2603 struct bind_ {
|
Chris@16
|
2604 typedef typename Graph::vertex_descriptor Vertex;
|
Chris@16
|
2605 typedef vec_adj_list_vertex_all_properties_map
|
Chris@16
|
2606 <Graph, Graph*, Property, Property&> type;
|
Chris@16
|
2607 typedef vec_adj_list_vertex_all_properties_map
|
Chris@16
|
2608 <Graph, const Graph*, Property, const Property&> const_type;
|
Chris@16
|
2609 };
|
Chris@16
|
2610 };
|
Chris@16
|
2611 namespace detail {
|
Chris@16
|
2612 template <class Tag, class Graph, class Property>
|
Chris@16
|
2613 struct adj_list_choose_vertex_pa
|
Chris@16
|
2614 : boost::mpl::if_<
|
Chris@16
|
2615 boost::is_same<Tag, vertex_all_t>,
|
Chris@16
|
2616 adj_list_all_vertex_pa,
|
Chris@16
|
2617 adj_list_any_vertex_pa>::type
|
Chris@16
|
2618 ::template bind_<Tag, Graph, Property>
|
Chris@16
|
2619 {};
|
Chris@16
|
2620
|
Chris@16
|
2621
|
Chris@16
|
2622 template <class Tag>
|
Chris@16
|
2623 struct vec_adj_list_choose_vertex_pa_helper {
|
Chris@16
|
2624 typedef vec_adj_list_any_vertex_pa type;
|
Chris@16
|
2625 };
|
Chris@16
|
2626 template <>
|
Chris@16
|
2627 struct vec_adj_list_choose_vertex_pa_helper<vertex_index_t> {
|
Chris@16
|
2628 typedef vec_adj_list_id_vertex_pa type;
|
Chris@16
|
2629 };
|
Chris@16
|
2630 template <>
|
Chris@16
|
2631 struct vec_adj_list_choose_vertex_pa_helper<vertex_all_t> {
|
Chris@16
|
2632 typedef vec_adj_list_all_vertex_pa type;
|
Chris@16
|
2633 };
|
Chris@16
|
2634 template <class Tag, class Graph, class Property>
|
Chris@16
|
2635 struct vec_adj_list_choose_vertex_pa
|
Chris@16
|
2636 : vec_adj_list_choose_vertex_pa_helper<Tag>::type::template bind_<Tag,Graph,Property>
|
Chris@16
|
2637 {};
|
Chris@16
|
2638 } // namespace detail
|
Chris@16
|
2639
|
Chris@16
|
2640 //=========================================================================
|
Chris@16
|
2641 // Edge Property Map
|
Chris@16
|
2642
|
Chris@16
|
2643 template <class Directed, class Value, class Ref, class Vertex,
|
Chris@16
|
2644 class Property, class Tag>
|
Chris@16
|
2645 struct adj_list_edge_property_map
|
Chris@16
|
2646 : public put_get_helper<
|
Chris@16
|
2647 Ref,
|
Chris@16
|
2648 adj_list_edge_property_map<Directed, Value, Ref, Vertex, Property,
|
Chris@16
|
2649 Tag>
|
Chris@16
|
2650 >
|
Chris@16
|
2651 {
|
Chris@16
|
2652 Tag tag;
|
Chris@16
|
2653 explicit adj_list_edge_property_map(Tag tag = Tag()): tag(tag) {}
|
Chris@16
|
2654
|
Chris@16
|
2655 typedef Value value_type;
|
Chris@16
|
2656 typedef Ref reference;
|
Chris@16
|
2657 typedef detail::edge_desc_impl<Directed, Vertex> key_type;
|
Chris@16
|
2658 typedef boost::lvalue_property_map_tag category;
|
Chris@16
|
2659 inline Ref operator[](key_type e) const {
|
Chris@16
|
2660 Property& p = *(Property*)e.get_property();
|
Chris@16
|
2661 return get_property_value(p, tag);
|
Chris@16
|
2662 }
|
Chris@16
|
2663 inline Ref operator()(key_type e) const {
|
Chris@16
|
2664 return this->operator[](e);
|
Chris@16
|
2665 }
|
Chris@16
|
2666 };
|
Chris@16
|
2667
|
Chris@16
|
2668 template <class Directed, class Property, class PropRef, class PropPtr,
|
Chris@16
|
2669 class Vertex>
|
Chris@16
|
2670 struct adj_list_edge_all_properties_map
|
Chris@16
|
2671 : public put_get_helper<PropRef,
|
Chris@16
|
2672 adj_list_edge_all_properties_map<Directed, Property, PropRef,
|
Chris@16
|
2673 PropPtr, Vertex>
|
Chris@16
|
2674 >
|
Chris@16
|
2675 {
|
Chris@16
|
2676 explicit adj_list_edge_all_properties_map(edge_all_t = edge_all_t()) {}
|
Chris@16
|
2677 typedef Property value_type;
|
Chris@16
|
2678 typedef PropRef reference;
|
Chris@16
|
2679 typedef detail::edge_desc_impl<Directed, Vertex> key_type;
|
Chris@16
|
2680 typedef boost::lvalue_property_map_tag category;
|
Chris@16
|
2681 inline PropRef operator[](key_type e) const {
|
Chris@16
|
2682 return *(PropPtr)e.get_property();
|
Chris@16
|
2683 }
|
Chris@16
|
2684 inline PropRef operator()(key_type e) const {
|
Chris@16
|
2685 return this->operator[](e);
|
Chris@16
|
2686 }
|
Chris@16
|
2687 };
|
Chris@16
|
2688
|
Chris@16
|
2689 // Edge Property Maps
|
Chris@16
|
2690
|
Chris@16
|
2691 namespace detail {
|
Chris@16
|
2692 struct adj_list_any_edge_pmap {
|
Chris@16
|
2693 template <class Graph, class Property, class Tag>
|
Chris@16
|
2694 struct bind_ {
|
Chris@16
|
2695 typedef typename property_value<Property,Tag>::type value_type;
|
Chris@16
|
2696 typedef value_type& reference;
|
Chris@16
|
2697 typedef const value_type& const_reference;
|
Chris@16
|
2698
|
Chris@16
|
2699 typedef adj_list_edge_property_map
|
Chris@16
|
2700 <typename Graph::directed_category, value_type, reference,
|
Chris@16
|
2701 typename Graph::vertex_descriptor,Property,Tag> type;
|
Chris@16
|
2702 typedef adj_list_edge_property_map
|
Chris@16
|
2703 <typename Graph::directed_category, value_type, const_reference,
|
Chris@16
|
2704 typename Graph::vertex_descriptor,const Property, Tag> const_type;
|
Chris@16
|
2705 };
|
Chris@16
|
2706 };
|
Chris@16
|
2707 struct adj_list_all_edge_pmap {
|
Chris@16
|
2708 template <class Graph, class Property, class Tag>
|
Chris@16
|
2709 struct bind_ {
|
Chris@16
|
2710 typedef adj_list_edge_all_properties_map
|
Chris@16
|
2711 <typename Graph::directed_category, Property, Property&, Property*,
|
Chris@16
|
2712 typename Graph::vertex_descriptor> type;
|
Chris@16
|
2713 typedef adj_list_edge_all_properties_map
|
Chris@16
|
2714 <typename Graph::directed_category, Property, const Property&,
|
Chris@16
|
2715 const Property*, typename Graph::vertex_descriptor> const_type;
|
Chris@16
|
2716 };
|
Chris@16
|
2717 };
|
Chris@16
|
2718
|
Chris@16
|
2719 template <class Tag>
|
Chris@16
|
2720 struct adj_list_choose_edge_pmap_helper {
|
Chris@16
|
2721 typedef adj_list_any_edge_pmap type;
|
Chris@16
|
2722 };
|
Chris@16
|
2723 template <>
|
Chris@16
|
2724 struct adj_list_choose_edge_pmap_helper<edge_all_t> {
|
Chris@16
|
2725 typedef adj_list_all_edge_pmap type;
|
Chris@16
|
2726 };
|
Chris@16
|
2727 template <class Tag, class Graph, class Property>
|
Chris@16
|
2728 struct adj_list_choose_edge_pmap
|
Chris@16
|
2729 : adj_list_choose_edge_pmap_helper<Tag>::type::template bind_<Graph, Property, Tag>
|
Chris@16
|
2730 {};
|
Chris@16
|
2731 struct adj_list_edge_property_selector {
|
Chris@16
|
2732 template <class Graph, class Property, class Tag>
|
Chris@16
|
2733 struct bind_: adj_list_choose_edge_pmap<Tag, Graph, Property> {};
|
Chris@16
|
2734 };
|
Chris@16
|
2735 } // namespace detail
|
Chris@16
|
2736
|
Chris@16
|
2737 template <>
|
Chris@16
|
2738 struct edge_property_selector<adj_list_tag> {
|
Chris@16
|
2739 typedef detail::adj_list_edge_property_selector type;
|
Chris@16
|
2740 };
|
Chris@16
|
2741 template <>
|
Chris@16
|
2742 struct edge_property_selector<vec_adj_list_tag> {
|
Chris@16
|
2743 typedef detail::adj_list_edge_property_selector type;
|
Chris@16
|
2744 };
|
Chris@16
|
2745
|
Chris@16
|
2746 // Vertex Property Maps
|
Chris@16
|
2747
|
Chris@16
|
2748 struct adj_list_vertex_property_selector {
|
Chris@16
|
2749 template <class Graph, class Property, class Tag>
|
Chris@16
|
2750 struct bind_
|
Chris@16
|
2751 : detail::adj_list_choose_vertex_pa<Tag,Graph,Property>
|
Chris@16
|
2752 {};
|
Chris@16
|
2753 };
|
Chris@16
|
2754 template <>
|
Chris@16
|
2755 struct vertex_property_selector<adj_list_tag> {
|
Chris@16
|
2756 typedef adj_list_vertex_property_selector type;
|
Chris@16
|
2757 };
|
Chris@16
|
2758
|
Chris@16
|
2759 struct vec_adj_list_vertex_property_selector {
|
Chris@16
|
2760 template <class Graph, class Property, class Tag>
|
Chris@16
|
2761 struct bind_: detail::vec_adj_list_choose_vertex_pa<Tag,Graph,Property> {};
|
Chris@16
|
2762 };
|
Chris@16
|
2763 template <>
|
Chris@16
|
2764 struct vertex_property_selector<vec_adj_list_tag> {
|
Chris@16
|
2765 typedef vec_adj_list_vertex_property_selector type;
|
Chris@16
|
2766 };
|
Chris@16
|
2767
|
Chris@16
|
2768 } // namespace boost
|
Chris@16
|
2769
|
Chris@16
|
2770 namespace boost {
|
Chris@16
|
2771
|
Chris@16
|
2772 template <typename V>
|
Chris@16
|
2773 struct hash< boost::detail::stored_edge<V> >
|
Chris@16
|
2774 {
|
Chris@16
|
2775 std::size_t
|
Chris@16
|
2776 operator()(const boost::detail::stored_edge<V>& e) const
|
Chris@16
|
2777 {
|
Chris@16
|
2778 return hash<V>()(e.m_target);
|
Chris@16
|
2779 }
|
Chris@16
|
2780 };
|
Chris@16
|
2781
|
Chris@16
|
2782 template <typename V, typename P>
|
Chris@16
|
2783 struct hash< boost::detail::stored_edge_property <V,P> >
|
Chris@16
|
2784 {
|
Chris@16
|
2785 std::size_t
|
Chris@16
|
2786 operator()(const boost::detail::stored_edge_property<V,P>& e) const
|
Chris@16
|
2787 {
|
Chris@16
|
2788 return hash<V>()(e.m_target);
|
Chris@16
|
2789 }
|
Chris@16
|
2790 };
|
Chris@16
|
2791
|
Chris@16
|
2792 template <typename V, typename I, typename P>
|
Chris@16
|
2793 struct hash< boost::detail::stored_edge_iter<V,I, P> >
|
Chris@16
|
2794 {
|
Chris@16
|
2795 std::size_t
|
Chris@16
|
2796 operator()(const boost::detail::stored_edge_iter<V,I,P>& e) const
|
Chris@16
|
2797 {
|
Chris@16
|
2798 return hash<V>()(e.m_target);
|
Chris@16
|
2799 }
|
Chris@16
|
2800 };
|
Chris@16
|
2801
|
Chris@16
|
2802 }
|
Chris@16
|
2803
|
Chris@16
|
2804
|
Chris@16
|
2805 #endif // BOOST_GRAPH_DETAIL_DETAIL_ADJACENCY_LIST_CCT
|
Chris@16
|
2806
|
Chris@16
|
2807 /*
|
Chris@16
|
2808 Implementation Notes:
|
Chris@16
|
2809
|
Chris@16
|
2810 Many of the public interface functions in this file would have been
|
Chris@16
|
2811 more conveniently implemented as inline friend functions.
|
Chris@16
|
2812 However there are a few compiler bugs that make that approach
|
Chris@16
|
2813 non-portable.
|
Chris@16
|
2814
|
Chris@16
|
2815 1. g++ inline friend in namespace bug
|
Chris@16
|
2816 2. g++ using clause doesn't work with inline friends
|
Chris@16
|
2817 3. VC++ doesn't have Koenig lookup
|
Chris@16
|
2818
|
Chris@16
|
2819 For these reasons, the functions were all written as non-inline free
|
Chris@16
|
2820 functions, and static cast was used to convert from the helper
|
Chris@16
|
2821 class to the adjacency_list derived class.
|
Chris@16
|
2822
|
Chris@16
|
2823 Looking back, it might have been better to write out all functions
|
Chris@16
|
2824 in terms of the adjacency_list, and then use a tag to dispatch
|
Chris@16
|
2825 to the various helpers instead of using inheritance.
|
Chris@16
|
2826
|
Chris@16
|
2827 */
|