| 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 |
|
|---|
| 73 | namespace 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 |
|
|---|
| 2772 | namespace 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 | */
|
|---|