Ticket #10382: adjacency_list_fixed.hpp

File adjacency_list_fixed.hpp, 105.2 KB (added by phreakuencies@…, 8 years ago)

adjacency list fixed for 4.9

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