PageRenderTime 117ms CodeModel.GetById 18ms app.highlight 83ms RepoModel.GetById 1ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/graph/distributed/adjacency_list.hpp

http://hadesmem.googlecode.com/
C++ Header | 3970 lines | 2664 code | 533 blank | 773 comment | 189 complexity | 3c4b75ee66cb03622c873a03e54057c9 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1// Copyright (C) 2004-2006 The Trustees of Indiana University.
   2// Copyright (C) 2007 Douglas Gregor 
   3
   4// Use, modification and distribution is subject to the Boost Software
   5// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
   6// http://www.boost.org/LICENSE_1_0.txt)
   7
   8//  Authors: Douglas Gregor
   9//           Andrew Lumsdaine
  10
  11#ifndef BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP
  12#define BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP
  13
  14#ifndef BOOST_GRAPH_USE_MPI
  15#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
  16#endif
  17
  18#include <boost/graph/adjacency_list.hpp>
  19#include <boost/graph/properties.hpp>
  20#include <boost/graph/graph_traits.hpp>
  21#include <boost/graph/iteration_macros.hpp>
  22#include <boost/graph/distributed/concepts.hpp>
  23#include <boost/iterator/transform_iterator.hpp>
  24#include <boost/property_map/property_map.hpp>
  25#include <boost/graph/adjacency_iterator.hpp>
  26#include <boost/property_map/parallel/distributed_property_map.hpp>
  27#include <boost/property_map/parallel/local_property_map.hpp>
  28#include <boost/graph/parallel/detail/property_holders.hpp>
  29#include <boost/mpl/if.hpp>
  30#include <boost/type_traits/is_same.hpp>
  31#include <boost/assert.hpp>
  32#include <list>
  33#include <algorithm>
  34#include <boost/limits.hpp>
  35#include <boost/graph/parallel/properties.hpp>
  36#include <boost/graph/parallel/distribution.hpp>
  37#include <boost/graph/parallel/algorithm.hpp>
  38#include <boost/graph/distributed/selector.hpp>
  39#include <boost/graph/parallel/process_group.hpp>
  40
  41// Callbacks
  42#include <boost/function/function2.hpp>
  43
  44// Serialization
  45#include <boost/serialization/base_object.hpp>
  46#include <boost/mpi/datatype.hpp>
  47#include <boost/pending/property_serialize.hpp>
  48#include <boost/graph/distributed/unsafe_serialize.hpp>
  49
  50// Named vertices
  51#include <boost/graph/distributed/named_graph.hpp>
  52
  53#include <boost/graph/distributed/shuffled_distribution.hpp>
  54
  55namespace boost {
  56
  57  /// The type used to store an identifier that uniquely names a processor.
  58  // NGE: I doubt we'll be running on more than 32768 procs for the time being
  59  typedef /*int*/ short processor_id_type;
  60
  61  // Tell which processor the target of an edge resides on (for
  62  // directed graphs) or which processor the other end point of the
  63  // edge resides on (for undirected graphs).
  64  enum edge_target_processor_id_t { edge_target_processor_id };
  65  BOOST_INSTALL_PROPERTY(edge, target_processor_id);
  66
  67  // For undirected graphs, tells whether the edge is locally owned.
  68  enum edge_locally_owned_t { edge_locally_owned };
  69  BOOST_INSTALL_PROPERTY(edge, locally_owned);
  70
  71  // For bidirectional graphs, stores the incoming edges.
  72  enum vertex_in_edges_t { vertex_in_edges };
  73  BOOST_INSTALL_PROPERTY(vertex, in_edges);
  74
  75  /// Tag class for directed, distributed adjacency list
  76  struct directed_distributed_adj_list_tag
  77    : public virtual distributed_graph_tag,
  78      public virtual distributed_vertex_list_graph_tag,
  79      public virtual distributed_edge_list_graph_tag,
  80      public virtual incidence_graph_tag,
  81      public virtual adjacency_graph_tag {};
  82
  83  /// Tag class for bidirectional, distributed adjacency list
  84  struct bidirectional_distributed_adj_list_tag
  85    : public virtual distributed_graph_tag,
  86      public virtual distributed_vertex_list_graph_tag,
  87      public virtual distributed_edge_list_graph_tag,
  88      public virtual incidence_graph_tag,
  89      public virtual adjacency_graph_tag,
  90      public virtual bidirectional_graph_tag {};
  91
  92  /// Tag class for undirected, distributed adjacency list
  93  struct undirected_distributed_adj_list_tag
  94    : public virtual distributed_graph_tag,
  95      public virtual distributed_vertex_list_graph_tag,
  96      public virtual distributed_edge_list_graph_tag,
  97      public virtual incidence_graph_tag,
  98      public virtual adjacency_graph_tag,
  99      public virtual bidirectional_graph_tag {};
 100
 101  namespace detail {
 102    template<typename Archiver, typename Directed, typename Vertex>
 103    void
 104    serialize(Archiver& ar, edge_base<Directed, Vertex>& e,
 105              const unsigned int /*version*/)
 106    {
 107      ar & unsafe_serialize(e.m_source)
 108         & unsafe_serialize(e.m_target);
 109    }
 110
 111    template<typename Archiver, typename Directed, typename Vertex>
 112    void
 113    serialize(Archiver& ar, edge_desc_impl<Directed, Vertex>& e,
 114              const unsigned int /*version*/)
 115    {
 116      ar & boost::serialization::base_object<edge_base<Directed, Vertex> >(e)
 117         & unsafe_serialize(e.m_eproperty);
 118    }
 119  }
 120
 121  namespace detail { namespace parallel {
 122  
 123    /**
 124     * A distributed vertex descriptor. These descriptors contain both
 125     * the ID of the processor that owns the vertex and a local vertex
 126     * descriptor that identifies the particular vertex for that
 127     * processor.
 128     */
 129    template<typename LocalDescriptor>
 130    struct global_descriptor
 131    {
 132      typedef LocalDescriptor local_descriptor_type;
 133
 134      global_descriptor() : owner(), local() { }
 135
 136      global_descriptor(processor_id_type owner, LocalDescriptor local)
 137        : owner(owner), local(local) { }
 138
 139      processor_id_type owner;
 140      LocalDescriptor local;
 141
 142      /**
 143       * A function object that, given a processor ID, generates
 144       * distributed vertex descriptors from local vertex
 145       * descriptors. This function object is used by the
 146       * vertex_iterator of the distributed adjacency list.
 147       */
 148      struct generator
 149      {
 150        typedef global_descriptor<LocalDescriptor> result_type;
 151        typedef LocalDescriptor argument_type;
 152
 153        generator() {}
 154        generator(processor_id_type owner) : owner(owner) {}
 155
 156        result_type operator()(argument_type v) const
 157        { return result_type(owner, v); }
 158
 159      private:
 160        processor_id_type owner;
 161      };
 162
 163      template<typename Archiver>
 164      void serialize(Archiver& ar, const unsigned int /*version*/)
 165      {
 166        ar & owner & unsafe_serialize(local);
 167      }
 168    };
 169
 170    /// Determine the process that owns the given descriptor
 171    template<typename LocalDescriptor>
 172    inline processor_id_type owner(const global_descriptor<LocalDescriptor>& v)
 173    { return v.owner; }
 174
 175    /// Determine the local portion of the given descriptor
 176    template<typename LocalDescriptor>
 177    inline LocalDescriptor local(const global_descriptor<LocalDescriptor>& v)
 178    { return v.local; }
 179
 180    /// Compare distributed vertex descriptors for equality
 181    template<typename LocalDescriptor>
 182    inline bool
 183    operator==(const global_descriptor<LocalDescriptor>& u,
 184               const global_descriptor<LocalDescriptor>& v)
 185    {
 186      return u.owner == v.owner && u.local == v.local;
 187    }
 188
 189    /// Compare distributed vertex descriptors for inequality
 190    template<typename LocalDescriptor>
 191    inline bool
 192    operator!=(const global_descriptor<LocalDescriptor>& u,
 193               const global_descriptor<LocalDescriptor>& v)
 194    { return !(u == v); }
 195
 196    template<typename LocalDescriptor>
 197    inline bool
 198    operator<(const global_descriptor<LocalDescriptor>& u,
 199              const global_descriptor<LocalDescriptor>& v)
 200    {
 201      return (u.owner) < v.owner || (u.owner == v.owner && (u.local) < v.local);
 202    }
 203
 204    template<typename LocalDescriptor>
 205    inline bool
 206    operator<=(const global_descriptor<LocalDescriptor>& u,
 207               const global_descriptor<LocalDescriptor>& v)
 208    {
 209      return u.owner <= v.owner || (u.owner == v.owner && u.local <= v.local);
 210    }
 211
 212    template<typename LocalDescriptor>
 213    inline bool
 214    operator>(const global_descriptor<LocalDescriptor>& u,
 215              const global_descriptor<LocalDescriptor>& v)
 216    {
 217      return v < u;
 218    }
 219
 220    template<typename LocalDescriptor>
 221    inline bool
 222    operator>=(const global_descriptor<LocalDescriptor>& u,
 223               const global_descriptor<LocalDescriptor>& v)
 224    {
 225      return v <= u;
 226    }
 227
 228    // DPG TBD: Add <, <=, >=, > for global descriptors
 229
 230    /**
 231     * A Readable Property Map that extracts a global descriptor pair
 232     * from a global_descriptor.
 233     */
 234    template<typename LocalDescriptor>
 235    struct global_descriptor_property_map
 236    {
 237      typedef std::pair<processor_id_type, LocalDescriptor> value_type;
 238      typedef value_type reference;
 239      typedef global_descriptor<LocalDescriptor> key_type;
 240      typedef readable_property_map_tag category;
 241    };
 242
 243    template<typename LocalDescriptor>
 244    inline std::pair<processor_id_type, LocalDescriptor>
 245    get(global_descriptor_property_map<LocalDescriptor>,
 246        global_descriptor<LocalDescriptor> x)
 247    {
 248      return std::pair<processor_id_type, LocalDescriptor>(x.owner, x.local);
 249    }
 250
 251    /**
 252     * A Readable Property Map that extracts the owner of a global
 253     * descriptor.
 254     */
 255    template<typename LocalDescriptor>
 256    struct owner_property_map
 257    {
 258      typedef processor_id_type value_type;
 259      typedef value_type reference;
 260      typedef global_descriptor<LocalDescriptor> key_type;
 261      typedef readable_property_map_tag category;
 262    };
 263
 264    template<typename LocalDescriptor>
 265    inline processor_id_type
 266    get(owner_property_map<LocalDescriptor>,
 267        global_descriptor<LocalDescriptor> x)
 268    {
 269      return x.owner;
 270    }
 271
 272    /**
 273     * A Readable Property Map that extracts the local descriptor from
 274     * a global descriptor.
 275     */
 276    template<typename LocalDescriptor>
 277    struct local_descriptor_property_map
 278    {
 279      typedef LocalDescriptor value_type;
 280      typedef value_type reference;
 281      typedef global_descriptor<LocalDescriptor> key_type;
 282      typedef readable_property_map_tag category;
 283    };
 284
 285    template<typename LocalDescriptor>
 286    inline LocalDescriptor
 287    get(local_descriptor_property_map<LocalDescriptor>,
 288        global_descriptor<LocalDescriptor> x)
 289    {
 290      return x.local;
 291    }
 292
 293    /**
 294     * Stores an incoming edge for a bidirectional distributed
 295     * adjacency list. The user does not see this type directly,
 296     * because it is just an implementation detail.
 297     */
 298    template<typename Edge>
 299    struct stored_in_edge
 300    {
 301      stored_in_edge(processor_id_type sp, Edge e)
 302        : source_processor(sp), e(e) {}
 303
 304      processor_id_type source_processor;
 305      Edge e;
 306    };
 307
 308    /**
 309     * A distributed edge descriptor. These descriptors contain the
 310     * underlying edge descriptor, the processor IDs for both the
 311     * source and the target of the edge, and a boolean flag that
 312     * indicates which of the processors actually owns the edge.
 313     */
 314    template<typename Edge>
 315    struct edge_descriptor
 316    {
 317      edge_descriptor(processor_id_type sp = processor_id_type(),
 318                      processor_id_type tp = processor_id_type(),
 319                      bool owns = false, Edge ld = Edge())
 320        : source_processor(sp), target_processor(tp),
 321          source_owns_edge(owns), local(ld) {}
 322
 323      processor_id_type owner() const
 324      {
 325        return source_owns_edge? source_processor : target_processor;
 326      }
 327
 328      /// The processor that the source vertex resides on
 329      processor_id_type source_processor;
 330
 331      /// The processor that the target vertex resides on
 332      processor_id_type target_processor;
 333
 334      /// True when the source processor owns the edge, false when the
 335      /// target processor owns the edge.
 336      bool source_owns_edge;
 337
 338      /// The local edge descriptor.
 339      Edge local;
 340
 341      /**
 342       * Function object that generates edge descriptors for the
 343       * out_edge_iterator of the given distributed adjacency list
 344       * from the edge descriptors of the underlying adjacency list.
 345       */
 346      template<typename Graph>
 347      class out_generator
 348      {
 349        typedef typename Graph::directed_selector directed_selector;
 350
 351      public:
 352        typedef edge_descriptor<Edge> result_type;
 353        typedef Edge argument_type;
 354
 355        out_generator() : g(0) {}
 356        explicit out_generator(const Graph& g) : g(&g) {}
 357
 358        result_type operator()(argument_type e) const
 359        { return map(e, directed_selector()); }
 360
 361      private:
 362        result_type map(argument_type e, directedS) const
 363        {
 364          return result_type(g->processor(),
 365                             get(edge_target_processor_id, g->base(), e),
 366                             true, e);
 367        }
 368
 369        result_type map(argument_type e, bidirectionalS) const
 370        {
 371          return result_type(g->processor(),
 372                             get(edge_target_processor_id, g->base(), e),
 373                             true, e);
 374        }
 375
 376        result_type map(argument_type e, undirectedS) const
 377        {
 378          return result_type(g->processor(),
 379                             get(edge_target_processor_id, g->base(), e),
 380                             get(edge_locally_owned, g->base(), e),
 381                             e);
 382        }
 383
 384        const Graph* g;
 385      };
 386
 387      /**
 388       * Function object that generates edge descriptors for the
 389       * in_edge_iterator of the given distributed adjacency list
 390       * from the edge descriptors of the underlying adjacency list.
 391       */
 392      template<typename Graph>
 393      class in_generator
 394      {
 395        typedef typename Graph::directed_selector DirectedS;
 396
 397      public:
 398        typedef typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
 399                                         stored_in_edge<Edge>,
 400                                         Edge>::type argument_type;
 401        typedef edge_descriptor<Edge> result_type;
 402
 403        in_generator() : g(0) {}
 404        explicit in_generator(const Graph& g) : g(&g) {}
 405
 406        result_type operator()(argument_type e) const
 407        { return map(e, DirectedS()); }
 408
 409      private:
 410        /**
 411         * For a bidirectional graph, we just generate the appropriate
 412         * edge. No tricks.
 413         */
 414        result_type map(argument_type e, bidirectionalS) const
 415        {
 416          return result_type(e.source_processor,
 417                             g->processor(),
 418                             true,
 419                             e.e);
 420        }
 421
 422        /**
 423         * For an undirected graph, we generate descriptors for the
 424         * incoming edges by swapping the source/target of the
 425         * underlying edge descriptor (a hack). The target processor
 426         * ID on the edge is actually the source processor for this
 427         * edge, and our processor is the target processor. If the
 428         * edge is locally owned, then it is owned by the target (us);
 429         * otherwise it is owned by the source.
 430         */
 431        result_type map(argument_type e, undirectedS) const
 432        {
 433          typename Graph::local_edge_descriptor local_edge(e);
 434          // TBD: This is a very, VERY lame hack that takes advantage
 435          // of our knowledge of the internals of the BGL
 436          // adjacency_list. There should be a cleaner way to handle
 437          // this...
 438          using std::swap;
 439          swap(local_edge.m_source, local_edge.m_target);
 440          return result_type(get(edge_target_processor_id, g->base(), e),
 441                             g->processor(),
 442                             !get(edge_locally_owned, g->base(), e),
 443                             local_edge);
 444        }
 445
 446        const Graph* g;
 447      };
 448
 449    private:
 450      friend class boost::serialization::access;
 451
 452      template<typename Archiver>
 453      void serialize(Archiver& ar, const unsigned int /*version*/)
 454      {
 455        ar
 456          & source_processor
 457          & target_processor
 458          & source_owns_edge
 459          & local;
 460      }
 461    };
 462
 463    /// Determine the process that owns this edge
 464    template<typename Edge>
 465    inline processor_id_type
 466    owner(const edge_descriptor<Edge>& e)
 467    { return e.source_owns_edge? e.source_processor : e.target_processor; }
 468
 469    /// Determine the local descriptor for this edge.
 470    template<typename Edge>
 471    inline Edge
 472    local(const edge_descriptor<Edge>& e)
 473    { return e.local; }
 474
 475    /**
 476     * A Readable Property Map that extracts the owner and local
 477     * descriptor of an edge descriptor.
 478     */
 479    template<typename Edge>
 480    struct edge_global_property_map
 481    {
 482      typedef std::pair<processor_id_type, Edge> value_type;
 483      typedef value_type reference;
 484      typedef edge_descriptor<Edge> key_type;
 485      typedef readable_property_map_tag category;
 486    };
 487
 488    template<typename Edge>
 489    inline std::pair<processor_id_type, Edge>
 490    get(edge_global_property_map<Edge>, const edge_descriptor<Edge>& e)
 491    {
 492      typedef std::pair<processor_id_type, Edge> result_type;
 493      return result_type(e.source_owns_edge? e.source_processor
 494                         /* target owns edge*/: e.target_processor,
 495                         e.local);
 496    }
 497
 498    /**
 499     * A Readable Property Map that extracts the owner of an edge
 500     * descriptor.
 501     */
 502    template<typename Edge>
 503    struct edge_owner_property_map
 504    {
 505      typedef processor_id_type value_type;
 506      typedef value_type reference;
 507      typedef edge_descriptor<Edge> key_type;
 508      typedef readable_property_map_tag category;
 509    };
 510
 511    template<typename Edge>
 512    inline processor_id_type
 513    get(edge_owner_property_map<Edge>, const edge_descriptor<Edge>& e)
 514    {
 515      return e.source_owns_edge? e.source_processor : e.target_processor;
 516    }
 517
 518    /**
 519     * A Readable Property Map that extracts the local descriptor from
 520     * an edge descriptor.
 521     */
 522    template<typename Edge>
 523    struct edge_local_property_map
 524    {
 525      typedef Edge value_type;
 526      typedef value_type reference;
 527      typedef edge_descriptor<Edge> key_type;
 528      typedef readable_property_map_tag category;
 529    };
 530
 531    template<typename Edge>
 532    inline Edge
 533    get(edge_local_property_map<Edge>,
 534        const edge_descriptor<Edge>& e)
 535    {
 536      return e.local;
 537    }
 538
 539    /** Compare distributed edge descriptors for equality.
 540     *
 541     * \todo need edge_descriptor to know if it is undirected so we
 542     * can compare both ways.
 543     */
 544    template<typename Edge>
 545    inline bool
 546    operator==(const edge_descriptor<Edge>& e1,
 547               const edge_descriptor<Edge>& e2)
 548    {
 549      return (e1.source_processor == e2.source_processor
 550              && e1.target_processor == e2.target_processor
 551              && e1.local == e2.local);
 552    }
 553
 554    /// Compare distributed edge descriptors for inequality.
 555    template<typename Edge>
 556    inline bool
 557    operator!=(const edge_descriptor<Edge>& e1,
 558               const edge_descriptor<Edge>& e2)
 559    { return !(e1 == e2); }
 560
 561    /**
 562     * Configuration for the distributed adjacency list. We use this
 563     * parameter to store all of the configuration details for the
 564     * implementation of the distributed adjacency list, which allows us to
 565     * get at the distribution type in the maybe_named_graph.
 566     */
 567    template<typename OutEdgeListS, typename ProcessGroup,
 568             typename InVertexListS, typename InDistribution,
 569             typename DirectedS, typename VertexProperty, 
 570             typename EdgeProperty, typename GraphProperty, 
 571             typename EdgeListS>
 572    struct adjacency_list_config
 573    {
 574      typedef typename mpl::if_<is_same<InVertexListS, defaultS>, 
 575                                vecS, InVertexListS>::type 
 576        VertexListS;
 577
 578      /// Introduce the target processor ID property for each edge
 579      typedef property<edge_target_processor_id_t, processor_id_type,
 580                       EdgeProperty> edge_property_with_id;
 581
 582      /// For undirected graphs, introduce the locally-owned property for edges
 583      typedef typename boost::mpl::if_<is_same<DirectedS, undirectedS>,
 584                                       property<edge_locally_owned_t, bool,
 585                                                edge_property_with_id>,
 586                                       edge_property_with_id>::type
 587        base_edge_property_type;
 588
 589      /// The edge descriptor type for the local subgraph
 590      typedef typename adjacency_list_traits<OutEdgeListS,
 591                                             VertexListS,
 592                                             directedS>::edge_descriptor
 593        local_edge_descriptor;
 594
 595      /// For bidirectional graphs, the type of an incoming stored edge
 596      typedef stored_in_edge<local_edge_descriptor> bidir_stored_edge;
 597
 598      /// The container type that will store incoming edges for a
 599      /// bidirectional graph.
 600      typedef typename container_gen<EdgeListS, bidir_stored_edge>::type
 601        in_edge_list_type;
 602
 603      // Bidirectional graphs have an extra vertex property to store
 604      // the incoming edges.
 605      typedef typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
 606                                       property<vertex_in_edges_t, in_edge_list_type,
 607                                                VertexProperty>,
 608                                       VertexProperty>::type 
 609        base_vertex_property_type;
 610
 611      // The type of the distributed adjacency list
 612      typedef adjacency_list<OutEdgeListS,
 613                             distributedS<ProcessGroup, 
 614                                          VertexListS, 
 615                                          InDistribution>,
 616                             DirectedS, VertexProperty, EdgeProperty,
 617                             GraphProperty, EdgeListS> 
 618        graph_type;
 619
 620      // The type of the underlying adjacency list implementation
 621      typedef adjacency_list<OutEdgeListS, VertexListS, directedS,
 622                             base_vertex_property_type,
 623                             base_edge_property_type,
 624                             GraphProperty,
 625                             EdgeListS> 
 626        inherited;
 627      
 628      typedef InDistribution in_distribution_type;
 629      typedef typename inherited::vertices_size_type vertices_size_type;
 630
 631          typedef typename ::boost::graph::distributed::select_distribution<
 632              in_distribution_type, VertexProperty, vertices_size_type, 
 633              ProcessGroup>::type 
 634        base_distribution_type;
 635
 636          typedef ::boost::graph::distributed::shuffled_distribution<
 637          base_distribution_type> distribution_type;
 638
 639      typedef VertexProperty vertex_property_type;
 640      typedef EdgeProperty edge_property_type;
 641      typedef ProcessGroup process_group_type;
 642
 643      typedef VertexListS vertex_list_selector;
 644      typedef OutEdgeListS out_edge_list_selector;
 645      typedef DirectedS directed_selector;
 646      typedef GraphProperty graph_property_type;
 647      typedef EdgeListS edge_list_selector;
 648    };
 649
 650    // Maybe initialize the indices of each vertex
 651    template<typename IteratorPair, typename VertexIndexMap>
 652    void
 653    maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index,
 654                                    read_write_property_map_tag)
 655    {
 656      typedef typename property_traits<VertexIndexMap>::value_type index_t;
 657      index_t next_index = 0;
 658      while (p.first != p.second)
 659        put(to_index, *p.first++, next_index++);
 660    }
 661
 662    template<typename IteratorPair, typename VertexIndexMap>
 663    inline void
 664    maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index,
 665                                    readable_property_map_tag)
 666    {
 667      // Do nothing
 668    }
 669
 670    template<typename IteratorPair, typename VertexIndexMap>
 671    inline void
 672    maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index)
 673    {
 674      typedef typename property_traits<VertexIndexMap>::category category;
 675      maybe_initialize_vertex_indices(p, to_index, category());
 676    }
 677
 678    template<typename IteratorPair>
 679    inline void
 680    maybe_initialize_vertex_indices(IteratorPair p,
 681                                    ::boost::detail::error_property_not_found)
 682    { }
 683
 684    /***********************************************************************
 685     * Message Payloads                                                    *
 686     ***********************************************************************/
 687
 688    /**
 689     * Data stored with a msg_add_edge message, which requests the
 690     * remote addition of an edge.
 691     */
 692    template<typename Vertex, typename LocalVertex>
 693    struct msg_add_edge_data
 694    {
 695      msg_add_edge_data() { }
 696
 697      msg_add_edge_data(Vertex source, Vertex target)
 698        : source(source.local), target(target) { }
 699
 700      /// The source of the edge; the processor will be the
 701      /// receiving processor.
 702      LocalVertex source;
 703        
 704      /// The target of the edge.
 705      Vertex target;
 706        
 707      template<typename Archiver>
 708      void serialize(Archiver& ar, const unsigned int /*version*/)
 709      {
 710        ar & unsafe_serialize(source) & target;
 711      }
 712    };
 713
 714    /**
 715     * Like @c msg_add_edge_data, but also includes a user-specified
 716     * property value to be attached to the edge.
 717     */
 718    template<typename Vertex, typename LocalVertex, typename EdgeProperty>
 719    struct msg_add_edge_with_property_data
 720      : msg_add_edge_data<Vertex, LocalVertex>, 
 721        maybe_store_property<EdgeProperty>
 722    {
 723    private:
 724      typedef msg_add_edge_data<Vertex, LocalVertex> inherited_data;
 725      typedef maybe_store_property<EdgeProperty> inherited_property;
 726
 727    public:
 728      msg_add_edge_with_property_data() { }
 729
 730      msg_add_edge_with_property_data(Vertex source, 
 731                                      Vertex target,
 732                                      const EdgeProperty& property)
 733        : inherited_data(source, target),
 734          inherited_property(property) { }
 735      
 736      template<typename Archiver>
 737      void serialize(Archiver& ar, const unsigned int /*version*/)
 738      {
 739        ar & boost::serialization::base_object<inherited_data>(*this) 
 740           & boost::serialization::base_object<inherited_property>(*this);
 741      }
 742    };
 743
 744    //------------------------------------------------------------------------
 745    // Distributed adjacency list property map details
 746    /**
 747     * Metafunction that extracts the given property from the given
 748     * distributed adjacency list type. This could be implemented much
 749     * more cleanly, but even newer versions of GCC (e.g., 3.2.3)
 750     * cannot properly handle partial specializations involving
 751     * enumerator types.
 752     */
 753    template<typename Property>
 754    struct get_adj_list_pmap
 755    {
 756      template<typename Graph>
 757      struct apply
 758      {
 759        typedef Graph graph_type;
 760        typedef typename graph_type::process_group_type process_group_type;
 761        typedef typename graph_type::inherited base_graph_type;
 762        typedef typename property_map<base_graph_type, Property>::type
 763          local_pmap;
 764        typedef typename property_map<base_graph_type, Property>::const_type
 765          local_const_pmap;
 766
 767        typedef graph_traits<graph_type> traits;
 768        typedef typename graph_type::local_vertex_descriptor local_vertex;
 769        typedef typename property_traits<local_pmap>::key_type local_key_type;
 770
 771        typedef typename property_traits<local_pmap>::value_type value_type;
 772
 773        typedef typename property_map<Graph, vertex_global_t>::const_type
 774          vertex_global_map;
 775        typedef typename property_map<Graph, edge_global_t>::const_type
 776          edge_global_map;
 777
 778        typedef typename mpl::if_c<(is_same<local_key_type,
 779                                            local_vertex>::value),
 780                                   vertex_global_map, edge_global_map>::type
 781          global_map;
 782
 783      public:
 784        typedef ::boost::parallel::distributed_property_map<
 785                  process_group_type, global_map, local_pmap> type;
 786
 787        typedef ::boost::parallel::distributed_property_map<
 788                  process_group_type, global_map, local_const_pmap> const_type;
 789      };
 790    };
 791
 792    /**
 793     * The local vertex index property map is actually a mapping from
 794     * the local vertex descriptors to vertex indices.
 795     */
 796    template<>
 797    struct get_adj_list_pmap<vertex_local_index_t>
 798    {
 799      template<typename Graph>
 800      struct apply
 801        : ::boost::property_map<typename Graph::inherited, vertex_index_t>
 802      { };
 803    };
 804
 805    /**
 806     * The vertex index property map maps from global descriptors
 807     * (e.g., the vertex descriptor of a distributed adjacency list)
 808     * to the underlying local index. It is not valid to use this
 809     * property map with nonlocal descriptors.
 810     */
 811    template<>
 812    struct get_adj_list_pmap<vertex_index_t>
 813    {
 814      template<typename Graph>
 815      struct apply
 816      {
 817      private:
 818        typedef typename property_map<Graph, vertex_global_t>::const_type
 819          global_map;
 820
 821        typedef property_map<typename Graph::inherited, vertex_index_t> local;
 822
 823      public:
 824        typedef local_property_map<typename Graph::process_group_type,
 825                                   global_map,
 826                                   typename local::type> type;
 827        typedef local_property_map<typename Graph::process_group_type,
 828                                   global_map,
 829                                   typename local::const_type> const_type;
 830      };
 831    };
 832
 833    /**
 834     * The vertex owner property map maps from vertex descriptors to
 835     * the processor that owns the vertex.
 836     */
 837    template<>
 838    struct get_adj_list_pmap<vertex_global_t>
 839    {
 840      template<typename Graph>
 841      struct apply
 842      {
 843      private:
 844        typedef typename Graph::local_vertex_descriptor
 845          local_vertex_descriptor;
 846      public:
 847        typedef global_descriptor_property_map<local_vertex_descriptor> type;
 848        typedef type const_type;
 849      };
 850    };
 851
 852    /**
 853     * The vertex owner property map maps from vertex descriptors to
 854     * the processor that owns the vertex.
 855     */
 856    template<>
 857    struct get_adj_list_pmap<vertex_owner_t>
 858    {
 859      template<typename Graph>
 860      struct apply
 861      {
 862      private:
 863        typedef typename Graph::local_vertex_descriptor
 864          local_vertex_descriptor;
 865      public:
 866        typedef owner_property_map<local_vertex_descriptor> type;
 867        typedef type const_type;
 868      };
 869    };
 870
 871    /**
 872     * The vertex local property map maps from vertex descriptors to
 873     * the local descriptor for that vertex.
 874     */
 875    template<>
 876    struct get_adj_list_pmap<vertex_local_t>
 877    {
 878      template<typename Graph>
 879      struct apply
 880      {
 881      private:
 882        typedef typename Graph::local_vertex_descriptor
 883          local_vertex_descriptor;
 884      public:
 885        typedef local_descriptor_property_map<local_vertex_descriptor> type;
 886        typedef type const_type;
 887      };
 888    };
 889
 890    /**
 891     * The edge global property map maps from edge descriptors to
 892     * a pair of the owning processor and local descriptor.
 893     */
 894    template<>
 895    struct get_adj_list_pmap<edge_global_t>
 896    {
 897      template<typename Graph>
 898      struct apply
 899      {
 900      private:
 901        typedef typename Graph::local_edge_descriptor
 902          local_edge_descriptor;
 903      public:
 904        typedef edge_global_property_map<local_edge_descriptor> type;
 905        typedef type const_type;
 906      };
 907    };
 908
 909    /**
 910     * The edge owner property map maps from edge descriptors to
 911     * the processor that owns the edge.
 912     */
 913    template<>
 914    struct get_adj_list_pmap<edge_owner_t>
 915    {
 916      template<typename Graph>
 917      struct apply
 918      {
 919      private:
 920        typedef typename Graph::local_edge_descriptor
 921          local_edge_descriptor;
 922      public:
 923        typedef edge_owner_property_map<local_edge_descriptor> type;
 924        typedef type const_type;
 925      };
 926    };
 927
 928    /**
 929     * The edge local property map maps from edge descriptors to
 930     * the local descriptor for that edge.
 931     */
 932    template<>
 933    struct get_adj_list_pmap<edge_local_t>
 934    {
 935      template<typename Graph>
 936      struct apply
 937      {
 938      private:
 939        typedef typename Graph::local_edge_descriptor
 940          local_edge_descriptor;
 941      public:
 942        typedef edge_local_property_map<local_edge_descriptor> type;
 943        typedef type const_type;
 944      };
 945    };
 946    //------------------------------------------------------------------------
 947
 948    // Directed graphs do not have in edges, so this is a no-op
 949    template<typename Graph>
 950    inline void
 951    remove_in_edge(typename Graph::edge_descriptor, Graph&, directedS)
 952    { }
 953
 954    // Bidirectional graphs have in edges stored in the
 955    // vertex_in_edges property.
 956    template<typename Graph>
 957    inline void
 958    remove_in_edge(typename Graph::edge_descriptor e, Graph& g, bidirectionalS)
 959    {
 960      typedef typename Graph::in_edge_list_type in_edge_list_type;
 961      in_edge_list_type& in_edges =
 962        get(vertex_in_edges, g.base())[target(e, g).local];
 963      typename in_edge_list_type::iterator i = in_edges.begin();
 964      while (i != in_edges.end()
 965             && !(i->source_processor == source(e, g).owner)
 966             && i->e == e.local)
 967        ++i;
 968
 969      BOOST_ASSERT(i != in_edges.end());
 970      in_edges.erase(i);
 971    }
 972
 973    // Undirected graphs have in edges stored as normal edges.
 974    template<typename Graph>
 975    inline void
 976    remove_in_edge(typename Graph::edge_descriptor e, Graph& g, undirectedS)
 977    {
 978      typedef typename Graph::inherited base_type;
 979      typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
 980
 981      // TBD: can we make this more efficient?
 982      // Removing edge (v, u). v is local
 983      base_type& bg = g.base();
 984      vertex_descriptor u = source(e, g);
 985      vertex_descriptor v = target(e, g);
 986      if (v.owner != process_id(g.process_group())) {
 987        using std::swap;
 988        swap(u, v);
 989      }
 990
 991      typename graph_traits<base_type>::out_edge_iterator ei, ei_end;
 992      for (boost::tie(ei, ei_end) = out_edges(v.local, bg); ei != ei_end; ++ei)
 993      {
 994        if (target(*ei, g.base()) == u.local
 995            // TBD: deal with parallel edges properly && *ei == e
 996            && get(edge_target_processor_id, bg, *ei) == u.owner) {
 997          remove_edge(ei, bg);
 998          return;
 999        }
1000      }
1001
1002      if (v.owner == process_id(g.process_group())) {
1003
1004      }
1005    }
1006
1007    //------------------------------------------------------------------------
1008    // Lazy addition of edges
1009
1010    // Work around the fact that an adjacency_list with vecS vertex
1011    // storage automatically adds edges when the descriptor is
1012    // out-of-range.
1013    template <class Graph, class Config, class Base>
1014    inline std::pair<typename Config::edge_descriptor, bool>
1015    add_local_edge(typename Config::vertex_descriptor u,
1016                   typename Config::vertex_descriptor v,
1017                   const typename Config::edge_property_type& p,
1018                   vec_adj_list_impl<Graph, Config, Base>& g_)
1019    {
1020      adj_list_helper<Config, Base>& g = g_;
1021      return add_edge(u, v, p, g);
1022    }
1023
1024    template <class Graph, class Config, class Base>
1025    inline std::pair<typename Config::edge_descriptor, bool>
1026    add_local_edge(typename Config::vertex_descriptor u,
1027                   typename Config::vertex_descriptor v,
1028                   const typename Config::edge_property_type& p,
1029                   boost::adj_list_impl<Graph, Config, Base>& g)
1030    {
1031      return add_edge(u, v, p, g);
1032    }
1033
1034    template <class EdgeProperty,class EdgeDescriptor>
1035    struct msg_nonlocal_edge_data
1036      : public detail::parallel::maybe_store_property<EdgeProperty>
1037    {
1038      typedef EdgeProperty edge_property_type;
1039      typedef EdgeDescriptor local_edge_descriptor;
1040      typedef detail::parallel::maybe_store_property<edge_property_type> 
1041        inherited;
1042
1043      msg_nonlocal_edge_data() {}
1044      msg_nonlocal_edge_data(local_edge_descriptor e,
1045                             const edge_property_type& p)
1046        : inherited(p), e(e) { }
1047
1048      local_edge_descriptor e;
1049
1050      template<typename Archiver>
1051      void serialize(Archiver& ar, const unsigned int /*version*/)
1052      {
1053        ar & boost::serialization::base_object<inherited>(*this) & e;
1054      }
1055    };
1056
1057    template <class EdgeDescriptor>
1058    struct msg_remove_edge_data
1059    {
1060      typedef EdgeDescriptor edge_descriptor;
1061      msg_remove_edge_data() {}
1062      explicit msg_remove_edge_data(edge_descriptor e) : e(e) {}
1063
1064      edge_descriptor e;
1065
1066      template<typename Archiver>
1067      void serialize(Archiver& ar, const unsigned int /*version*/)
1068      {
1069        ar & e;
1070      }
1071    };
1072
1073  } } // end namespace detail::parallel
1074
1075  /**
1076   * Adjacency list traits for a distributed adjacency list. Contains
1077   * the vertex and edge descriptors, the directed-ness, and the
1078   * parallel edges typedefs.
1079   */
1080  template<typename OutEdgeListS, typename ProcessGroup,
1081           typename InVertexListS, typename InDistribution, typename DirectedS>
1082  struct adjacency_list_traits<OutEdgeListS,
1083                               distributedS<ProcessGroup, 
1084                                            InVertexListS,
1085                                            InDistribution>,
1086                               DirectedS>
1087  {
1088  private:
1089    typedef typename mpl::if_<is_same<InVertexListS, defaultS>,
1090                              vecS,
1091                              InVertexListS>::type VertexListS;
1092
1093    typedef adjacency_list_traits<OutEdgeListS, VertexListS, directedS>
1094      base_type;
1095
1096  public:
1097    typedef typename base_type::vertex_descriptor local_vertex_descriptor;
1098    typedef typename base_type::edge_descriptor   local_edge_descriptor;
1099
1100    typedef typename boost::mpl::if_<typename DirectedS::is_bidir_t,
1101      bidirectional_tag,
1102      typename boost::mpl::if_<typename DirectedS::is_directed_t,
1103        directed_tag, undirected_tag
1104      >::type
1105    >::type directed_category;
1106
1107    typedef typename parallel_edge_traits<OutEdgeListS>::type
1108      edge_parallel_category;
1109
1110    typedef detail::parallel::global_descriptor<local_vertex_descriptor>
1111      vertex_descriptor;
1112
1113    typedef detail::parallel::edge_descriptor<local_edge_descriptor>
1114      edge_descriptor;
1115  };
1116
1117#define PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS                                    \
1118  typename OutEdgeListS, typename ProcessGroup, typename InVertexListS,        \
1119  typename InDistribution, typename DirectedS, typename VertexProperty,        \
1120  typename EdgeProperty,  typename GraphProperty, typename EdgeListS
1121
1122#define PBGL_DISTRIB_ADJLIST_TYPE                                              \
1123  adjacency_list<OutEdgeListS,                                                 \
1124                 distributedS<ProcessGroup, InVertexListS, InDistribution>,    \
1125                 DirectedS, VertexProperty, EdgeProperty, GraphProperty,       \
1126                 EdgeListS>
1127
1128#define PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG                             \
1129  typename OutEdgeListS, typename ProcessGroup, typename InVertexListS,        \
1130  typename InDistribution, typename VertexProperty,                            \
1131  typename EdgeProperty,  typename GraphProperty, typename EdgeListS
1132  
1133#define PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directed)                             \
1134  adjacency_list<OutEdgeListS,                                                 \
1135                 distributedS<ProcessGroup, InVertexListS, InDistribution>,    \
1136                 directed, VertexProperty, EdgeProperty, GraphProperty,        \
1137                 EdgeListS>
1138                 
1139  /** A distributed adjacency list.
1140   *
1141   * This class template partial specialization defines a distributed
1142   * (or "partitioned") adjacency list graph. The distributed
1143   * adjacency list is similar to the standard Boost Graph Library
1144   * adjacency list, which stores a list of vertices and for each
1145   * verted the list of edges outgoing from the vertex (and, in some
1146   * cases, also the edges incoming to the vertex). The distributed
1147   * adjacency list differs in that it partitions the graph into
1148   * several subgraphs that are then divided among different
1149   * processors (or nodes within a cluster). The distributed adjacency
1150   * list attempts to maintain a high degree of compatibility with the
1151   * standard, non-distributed adjacency list.
1152   *
1153   * The graph is partitioned by vertex, with each processor storing
1154   * all of the required information for a particular subset of the
1155   * vertices, including vertex properties, outgoing edges, and (for
1156   * bidirectional graphs) incoming edges. This information is
1157   * accessible only on the processor that owns the vertex: for
1158   * instance, if processor 0 owns vertex @c v, no other processor can
1159   * directly access the properties of @c v or enumerate its outgoing
1160   * edges.
1161   *
1162   * Edges in a graph may be entirely local (connecting two local
1163   * vertices), but more often it is the case that edges are
1164   * non-local, meaning that the two vertices they connect reside in
1165   * different processes. Edge properties are stored with the
1166   * originating vertex for directed and bidirectional graphs, and are
1167   * therefore only accessible from the processor that owns the
1168   * originating vertex. Other processors may query the source and
1169   * target of the edge, but cannot access its properties. This is
1170   * particularly interesting when accessing the incoming edges of a
1171   * bidirectional graph, which are not guaranteed to be stored on the
1172   * processor that is able to perform the iteration. For undirected
1173   * graphs the situation is more complicated, since no vertex clearly
1174   * owns the edges: the list of edges incident to a vertex may
1175   * contain a mix of local and non-local edges.
1176   *
1177   * The distributed adjacency list is able to model several of the
1178   * existing Graph concepts. It models the Graph concept because it
1179   * exposes vertex and edge descriptors in the normal way; these
1180   * descriptors model the GlobalDescriptor concept (because they have
1181   * an owner and a local descriptor), and as such the distributed
1182   * adjacency list models the DistributedGraph concept. The adjacency
1183   * list also models the IncidenceGraph and AdjacencyGraph concepts,
1184   * although this is only true so long as the domain of the valid
1185   * expression arguments are restricted to vertices and edges stored
1186   * locally. Likewise, bidirectional and undirected distributed
1187   * adjacency lists model the BidirectionalGraph concept (vertex and
1188   * edge domains must be respectived) and the distributed adjacency
1189   * list models the MutableGraph concept (vertices and edges can only
1190   * be added or removed locally). T he distributed adjacency list
1191   * does not, however, model the VertexListGraph or EdgeListGraph
1192   * concepts, because we can not efficiently enumerate all vertices
1193   * or edges in the graph. Instead, the local subsets of vertices and
1194   * edges can be enumerated (with the same syntax): the distributed
1195   * adjacency list therefore models the DistributedVertexListGraph
1196   * and DistributedEdgeListGraph concepts, because concurrent
1197   * iteration over all of the vertices or edges stored on each
1198   * processor will visit each vertex or edge.
1199   *
1200   * The distributed adjacency list is distinguished from the
1201   * non-distributed version by the vertex list descriptor, which will
1202   * be @c distributedS<ProcessGroup,VertexListS>. Here,
1203   * the VertexListS type plays the same role as the VertexListS type
1204   * in the non-distributed adjacency list: it allows one to select
1205   * the data structure that will be used to store the local
1206   * vertices. The ProcessGroup type, on the other hand, is unique to
1207   * distributed data structures: it is the type that abstracts a
1208   * group of cooperating processes, and it used for process
1209   * identification, communication, and synchronization, among other
1210   * things. Different process group types represent different
1211   * communication mediums (e.g., MPI, PVM, TCP) or different models
1212   * of communication (LogP, CGM, BSP, synchronous, etc.). This
1213   * distributed adjacency list assumes a model based on non-blocking
1214   * sends.
1215   *
1216   * Distribution of vertices across different processors is
1217   * accomplished in two different ways. When initially constructing
1218   * the graph, the user may provide a distribution object (that
1219   * models the Distribution concept), which will determine the
1220   * distribution of vertices to each process. Additionally, the @c
1221   * add_vertex and @c add_edge operations add vertices or edges
1222   * stored on the local processor. For @c add_edge, this is
1223   * accomplished by requiring that the source vertex of the new edge
1224   * be local to the process executing @c add_edge.
1225   *
1226   * Internal properties of a distributed adjacency list are
1227   * accessible in the same manner as internal properties for a
1228   * non-distributed adjacency list for local vertices or
1229   * edges. Access to properties for remote vertices or edges occurs
1230   * with the same syntax, but involve communication with the owner of
1231   * the information: for more information, refer to class template
1232   * @ref distributed_property_map, which manages distributed
1233   * property maps. Note that the distributed property maps created
1234   * for internal properties determine their reduction operation via
1235   * the metafunction @ref property_reduce, which for the vast
1236   * majority of uses is correct behavior.
1237   *
1238   * Communication among the processes coordinating on a particular
1239   * distributed graph relies on non-blocking message passing along
1240   * with synchronization. Local portions of the distributed graph may
1241   * be modified concurrently, including the introduction of non-local
1242   * edges, but prior to accessing the graph it is recommended that
1243   * the @c synchronize free function be invoked on the graph to clear
1244   * up any pending interprocess communication and modifications. All
1245   * processes will then be released from the synchronization barrier
1246   * concurrently.
1247   *
1248   * \todo Determine precisely what we should do with nonlocal edges
1249   * in undirected graphs. Our parallelization of certain algorithms
1250   * relies on the ability to access edge property maps immediately
1251   * (e.g., edge_weight_t), so it may be necessary to duplicate the
1252   * edge properties in both processes (but then we need some form of
1253   * coherence protocol).
1254   *
1255   * \todo What does the user do if @c property_reduce doesn't do the
1256   * right thing?
1257   */
1258  template<typename OutEdgeListS, typename ProcessGroup,
1259           typename InVertexListS, typename InDistribution, typename DirectedS,
1260           typename VertexProperty, typename EdgeProperty, 
1261           typename GraphProperty, typename EdgeListS>
1262  class adjacency_list<OutEdgeListS,
1263                       distributedS<ProcessGroup, 
1264                                    InVertexListS, 
1265                                    InDistribution>,
1266                       DirectedS, VertexProperty,
1267                       EdgeProperty, GraphProperty, EdgeListS>
1268    : // Support for named vertices
1269      public graph::distributed::maybe_named_graph<   
1270        adjacency_list<OutEdgeListS,
1271                       distributedS<ProcessGroup,
1272                                    InVertexListS,
1273                                    InDistribution>,
1274                       DirectedS, VertexProperty,
1275                       EdgeProperty, GraphProperty, EdgeListS>,
1276        typename adjacency_list_traits<OutEdgeListS, 
1277                                       distributedS<ProcessGroup,
1278                                                    InVertexListS,
1279                                                    InDistribution>,
1280                                       DirectedS>::vertex_descriptor,
1281        typename adjacency_list_traits<OutEdgeListS, 
1282                                       distributedS<ProcessGroup,
1283                                                    InVertexListS,
1284                                                    InDistribution>,
1285                                       DirectedS>::edge_descriptor,
1286        detail::parallel::adjacency_list_config<OutEdgeListS, ProcessGroup, 
1287                                                InVertexListS, InDistribution,
1288                                                DirectedS, VertexProperty, 
1289                                                EdgeProperty, GraphProperty, 
1290                                                EdgeListS> >
1291  {
1292    typedef detail::parallel::adjacency_list_config<OutEdgeListS, ProcessGroup, 
1293                                                InVertexListS, InDistribution,
1294                                                DirectedS, VertexProperty, 
1295                                                EdgeProperty, GraphProperty, 
1296                                                EdgeListS>
1297      config_type;
1298      
1299    typedef adjacency_list_traits<OutEdgeListS,
1300                                  distributedS<ProcessGroup, 
1301                                               InVertexListS, 
1302                                               InDistribution>,
1303                                  DirectedS> 
1304      traits_type;
1305
1306    typedef typename DirectedS::is_directed_t is_directed;
1307
1308    typedef EdgeListS edge_list_selector;
1309
1310  public:
1311    /// The container type that will store incoming edges for a
1312    /// bidirectional graph.
1313    typedef typename config_type::in_edge_list_type in_edge_list_type;
1314//    typedef typename inherited::edge_descriptor   edge_descriptor;
1315
1316    /// The type of the underlying adjacency list implementation
1317    typedef typename config_type::inherited inherited;
1318
1319    /// The type of properties stored in the local subgraph
1320    /// Bidirectional graphs have an extra vertex property to store
1321    /// the incoming edges.
1322    typedef typename inherited::vertex_property_type
1323      base_vertex_property_type;
1324
1325    /// The type of the distributed adjacency list (this type)
1326    typedef typename config_type::graph_type graph_type;
1327
1328    /// Expose graph components and graph category
1329    typedef typename traits_type::local_vertex_descriptor
1330      local_vertex_descriptor;
1331    typedef typename traits_type::local_edge_descriptor
1332      local_edge_descriptor;
1333    typedef typename traits

Large files files are truncated, but you can click here to view the full file