File indexing completed on 2025-10-29 08:20:27
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 
0011 #ifndef BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP
0012 #define BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP
0013 
0014 #ifndef BOOST_GRAPH_USE_MPI
0015 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
0016 #endif
0017 
0018 #include <boost/core/uncaught_exceptions.hpp>
0019 #include <boost/graph/adjacency_list.hpp>
0020 #include <boost/graph/properties.hpp>
0021 #include <boost/graph/graph_traits.hpp>
0022 #include <boost/graph/iteration_macros.hpp>
0023 #include <boost/graph/distributed/concepts.hpp>
0024 #include <boost/iterator/transform_iterator.hpp>
0025 #include <boost/property_map/property_map.hpp>
0026 #include <boost/property_map/parallel/parallel_property_maps.hpp>
0027 #include <boost/graph/adjacency_iterator.hpp>
0028 #include <boost/property_map/parallel/distributed_property_map.hpp>
0029 #include <boost/property_map/parallel/local_property_map.hpp>
0030 #include <boost/graph/parallel/detail/property_holders.hpp>
0031 #include <boost/mpl/if.hpp>
0032 #include <boost/type_traits/is_same.hpp>
0033 #include <boost/assert.hpp>
0034 #include <list>
0035 #include <iterator>
0036 #include <algorithm>
0037 #include <boost/limits.hpp>
0038 #include <boost/graph/parallel/properties.hpp>
0039 #include <boost/graph/parallel/distribution.hpp>
0040 #include <boost/graph/parallel/algorithm.hpp>
0041 #include <boost/graph/distributed/selector.hpp>
0042 #include <boost/graph/parallel/process_group.hpp>
0043 #include <boost/pending/container_traits.hpp>
0044 
0045 
0046 #include <boost/function/function2.hpp>
0047 
0048 
0049 #include <boost/serialization/base_object.hpp>
0050 #include <boost/mpi/datatype.hpp>
0051 #include <boost/pending/property_serialize.hpp>
0052 #include <boost/graph/distributed/unsafe_serialize.hpp>
0053 
0054 
0055 #include <boost/graph/distributed/named_graph.hpp>
0056 
0057 #include <boost/graph/distributed/shuffled_distribution.hpp>
0058 
0059 namespace boost {
0060 
0061   
0062   
0063   typedef  short processor_id_type;
0064 
0065   
0066   
0067   
0068   enum edge_target_processor_id_t { edge_target_processor_id };
0069   BOOST_INSTALL_PROPERTY(edge, target_processor_id);
0070 
0071   
0072   enum edge_locally_owned_t { edge_locally_owned };
0073   BOOST_INSTALL_PROPERTY(edge, locally_owned);
0074 
0075   
0076   enum vertex_in_edges_t { vertex_in_edges };
0077   BOOST_INSTALL_PROPERTY(vertex, in_edges);
0078 
0079   
0080   struct directed_distributed_adj_list_tag
0081     : public virtual distributed_graph_tag,
0082       public virtual distributed_vertex_list_graph_tag,
0083       public virtual distributed_edge_list_graph_tag,
0084       public virtual incidence_graph_tag,
0085       public virtual adjacency_graph_tag {};
0086 
0087   
0088   struct bidirectional_distributed_adj_list_tag
0089     : public virtual distributed_graph_tag,
0090       public virtual distributed_vertex_list_graph_tag,
0091       public virtual distributed_edge_list_graph_tag,
0092       public virtual incidence_graph_tag,
0093       public virtual adjacency_graph_tag,
0094       public virtual bidirectional_graph_tag {};
0095 
0096   
0097   struct undirected_distributed_adj_list_tag
0098     : public virtual distributed_graph_tag,
0099       public virtual distributed_vertex_list_graph_tag,
0100       public virtual distributed_edge_list_graph_tag,
0101       public virtual incidence_graph_tag,
0102       public virtual adjacency_graph_tag,
0103       public virtual bidirectional_graph_tag {};
0104 
0105   namespace detail {
0106     template<typename Archiver, typename Directed, typename Vertex>
0107     void
0108     serialize(Archiver& ar, edge_base<Directed, Vertex>& e,
0109               const unsigned int )
0110     {
0111       ar & unsafe_serialize(e.m_source)
0112          & unsafe_serialize(e.m_target);
0113     }
0114 
0115     template<typename Archiver, typename Directed, typename Vertex>
0116     void
0117     serialize(Archiver& ar, edge_desc_impl<Directed, Vertex>& e,
0118               const unsigned int )
0119     {
0120       ar & boost::serialization::base_object<edge_base<Directed, Vertex> >(e)
0121          & unsafe_serialize(e.m_eproperty);
0122     }
0123   }
0124 
0125   namespace detail { namespace parallel {
0126   
0127     
0128 
0129 
0130 
0131 
0132 
0133     template<typename LocalDescriptor>
0134     struct global_descriptor
0135     {
0136       typedef LocalDescriptor local_descriptor_type;
0137 
0138       global_descriptor() : owner(), local() { }
0139 
0140       global_descriptor(processor_id_type owner, LocalDescriptor local)
0141         : owner(owner), local(local) { }
0142 
0143       processor_id_type owner;
0144       LocalDescriptor local;
0145 
0146       
0147 
0148 
0149 
0150 
0151 
0152       struct generator
0153       {
0154         typedef global_descriptor<LocalDescriptor> result_type;
0155         typedef LocalDescriptor argument_type;
0156 
0157         generator() {}
0158         generator(processor_id_type owner) : owner(owner) {}
0159 
0160         result_type operator()(argument_type v) const
0161         { return result_type(owner, v); }
0162 
0163       private:
0164         processor_id_type owner;
0165       };
0166 
0167       template<typename Archiver>
0168       void serialize(Archiver& ar, const unsigned int )
0169       {
0170         ar & owner & unsafe_serialize(local);
0171       }
0172     };
0173 
0174     
0175     template<typename LocalDescriptor>
0176     inline processor_id_type owner(const global_descriptor<LocalDescriptor>& v)
0177     { return v.owner; }
0178 
0179     
0180     template<typename LocalDescriptor>
0181     inline LocalDescriptor local(const global_descriptor<LocalDescriptor>& v)
0182     { return v.local; }
0183 
0184     
0185     template<typename LocalDescriptor>
0186     inline bool
0187     operator==(const global_descriptor<LocalDescriptor>& u,
0188                const global_descriptor<LocalDescriptor>& v)
0189     {
0190       return u.owner == v.owner && u.local == v.local;
0191     }
0192 
0193     
0194     template<typename LocalDescriptor>
0195     inline bool
0196     operator!=(const global_descriptor<LocalDescriptor>& u,
0197                const global_descriptor<LocalDescriptor>& v)
0198     { return !(u == v); }
0199 
0200     template<typename LocalDescriptor>
0201     inline bool
0202     operator<(const global_descriptor<LocalDescriptor>& u,
0203               const global_descriptor<LocalDescriptor>& v)
0204     {
0205       return (u.owner) < v.owner || (u.owner == v.owner && (u.local) < v.local);
0206     }
0207 
0208     template<typename LocalDescriptor>
0209     inline bool
0210     operator<=(const global_descriptor<LocalDescriptor>& u,
0211                const global_descriptor<LocalDescriptor>& v)
0212     {
0213       return u.owner <= v.owner || (u.owner == v.owner && u.local <= v.local);
0214     }
0215 
0216     template<typename LocalDescriptor>
0217     inline bool
0218     operator>(const global_descriptor<LocalDescriptor>& u,
0219               const global_descriptor<LocalDescriptor>& v)
0220     {
0221       return v < u;
0222     }
0223 
0224     template<typename LocalDescriptor>
0225     inline bool
0226     operator>=(const global_descriptor<LocalDescriptor>& u,
0227                const global_descriptor<LocalDescriptor>& v)
0228     {
0229       return v <= u;
0230     }
0231 
0232     
0233 
0234     
0235 
0236 
0237 
0238     template<typename LocalDescriptor>
0239     struct global_descriptor_property_map
0240     {
0241       typedef std::pair<processor_id_type, LocalDescriptor> value_type;
0242       typedef value_type reference;
0243       typedef global_descriptor<LocalDescriptor> key_type;
0244       typedef readable_property_map_tag category;
0245     };
0246 
0247     template<typename LocalDescriptor>
0248     inline std::pair<processor_id_type, LocalDescriptor>
0249     get(global_descriptor_property_map<LocalDescriptor>,
0250         global_descriptor<LocalDescriptor> x)
0251     {
0252       return std::pair<processor_id_type, LocalDescriptor>(x.owner, x.local);
0253     }
0254 
0255     
0256 
0257 
0258 
0259     template<typename LocalDescriptor>
0260     struct owner_property_map
0261     {
0262       typedef processor_id_type value_type;
0263       typedef value_type reference;
0264       typedef global_descriptor<LocalDescriptor> key_type;
0265       typedef readable_property_map_tag category;
0266     };
0267 
0268     template<typename LocalDescriptor>
0269     inline processor_id_type
0270     get(owner_property_map<LocalDescriptor>,
0271         global_descriptor<LocalDescriptor> x)
0272     {
0273       return x.owner;
0274     }
0275 
0276     
0277 
0278 
0279 
0280     template<typename LocalDescriptor>
0281     struct local_descriptor_property_map
0282     {
0283       typedef LocalDescriptor value_type;
0284       typedef value_type reference;
0285       typedef global_descriptor<LocalDescriptor> key_type;
0286       typedef readable_property_map_tag category;
0287     };
0288 
0289     template<typename LocalDescriptor>
0290     inline LocalDescriptor
0291     get(local_descriptor_property_map<LocalDescriptor>,
0292         global_descriptor<LocalDescriptor> x)
0293     {
0294       return x.local;
0295     }
0296 
0297     
0298 
0299 
0300 
0301 
0302     template<typename Edge>
0303     struct stored_in_edge
0304     {
0305       stored_in_edge(processor_id_type sp, Edge e)
0306         : source_processor(sp), e(e) {}
0307 
0308       processor_id_type source_processor;
0309       Edge e;
0310     };
0311 
0312     
0313 
0314 
0315 
0316 
0317 
0318     template<typename Edge>
0319     struct edge_descriptor
0320     {
0321       edge_descriptor(processor_id_type sp = processor_id_type(),
0322                       processor_id_type tp = processor_id_type(),
0323                       bool owns = false, Edge ld = Edge())
0324         : source_processor(sp), target_processor(tp),
0325           source_owns_edge(owns), local(ld) {}
0326 
0327       processor_id_type owner() const
0328       {
0329         return source_owns_edge? source_processor : target_processor;
0330       }
0331 
0332       
0333       processor_id_type source_processor;
0334 
0335       
0336       processor_id_type target_processor;
0337 
0338       
0339       
0340       bool source_owns_edge;
0341 
0342       
0343       Edge local;
0344 
0345       
0346 
0347 
0348 
0349 
0350       template<typename Graph>
0351       class out_generator
0352       {
0353         typedef typename Graph::directed_selector directed_selector;
0354 
0355       public:
0356         typedef edge_descriptor<Edge> result_type;
0357         typedef Edge argument_type;
0358 
0359         out_generator() : g(0) {}
0360         explicit out_generator(const Graph& g) : g(&g) {}
0361 
0362         result_type operator()(argument_type e) const
0363         { return map(e, directed_selector()); }
0364 
0365       private:
0366         result_type map(argument_type e, directedS) const
0367         {
0368           return result_type(g->processor(),
0369                              get(edge_target_processor_id, g->base(), e),
0370                              true, e);
0371         }
0372 
0373         result_type map(argument_type e, bidirectionalS) const
0374         {
0375           return result_type(g->processor(),
0376                              get(edge_target_processor_id, g->base(), e),
0377                              true, e);
0378         }
0379 
0380         result_type map(argument_type e, undirectedS) const
0381         {
0382           return result_type(g->processor(),
0383                              get(edge_target_processor_id, g->base(), e),
0384                              get(edge_locally_owned, g->base(), e),
0385                              e);
0386         }
0387 
0388         const Graph* g;
0389       };
0390 
0391       
0392 
0393 
0394 
0395 
0396       template<typename Graph>
0397       class in_generator
0398       {
0399         typedef typename Graph::directed_selector DirectedS;
0400 
0401       public:
0402         typedef typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
0403                                          stored_in_edge<Edge>,
0404                                          Edge>::type argument_type;
0405         typedef edge_descriptor<Edge> result_type;
0406 
0407         in_generator() : g(0) {}
0408         explicit in_generator(const Graph& g) : g(&g) {}
0409 
0410         result_type operator()(argument_type e) const
0411         { return map(e, DirectedS()); }
0412 
0413       private:
0414         
0415 
0416 
0417 
0418         result_type map(argument_type e, bidirectionalS) const
0419         {
0420           return result_type(e.source_processor,
0421                              g->processor(),
0422                              true,
0423                              e.e);
0424         }
0425 
0426         
0427 
0428 
0429 
0430 
0431 
0432 
0433 
0434 
0435         result_type map(argument_type e, undirectedS) const
0436         {
0437           typename Graph::local_edge_descriptor local_edge(e);
0438           
0439           
0440           
0441           
0442           using std::swap;
0443           swap(local_edge.m_source, local_edge.m_target);
0444           return result_type(get(edge_target_processor_id, g->base(), e),
0445                              g->processor(),
0446                              !get(edge_locally_owned, g->base(), e),
0447                              local_edge);
0448         }
0449 
0450         const Graph* g;
0451       };
0452 
0453     private:
0454       friend class boost::serialization::access;
0455 
0456       template<typename Archiver>
0457       void serialize(Archiver& ar, const unsigned int )
0458       {
0459         ar
0460           & source_processor
0461           & target_processor
0462           & source_owns_edge
0463           & local;
0464       }
0465     };
0466 
0467     
0468     template<typename Edge>
0469     inline processor_id_type
0470     owner(const edge_descriptor<Edge>& e)
0471     { return e.source_owns_edge? e.source_processor : e.target_processor; }
0472 
0473     
0474     template<typename Edge>
0475     inline Edge
0476     local(const edge_descriptor<Edge>& e)
0477     { return e.local; }
0478 
0479     
0480 
0481 
0482 
0483     template<typename Edge>
0484     struct edge_global_property_map
0485     {
0486       typedef std::pair<processor_id_type, Edge> value_type;
0487       typedef value_type reference;
0488       typedef edge_descriptor<Edge> key_type;
0489       typedef readable_property_map_tag category;
0490     };
0491 
0492     template<typename Edge>
0493     inline std::pair<processor_id_type, Edge>
0494     get(edge_global_property_map<Edge>, const edge_descriptor<Edge>& e)
0495     {
0496       typedef std::pair<processor_id_type, Edge> result_type;
0497       return result_type(e.source_owns_edge? e.source_processor
0498                          : e.target_processor,
0499                          e.local);
0500     }
0501 
0502     
0503 
0504 
0505 
0506     template<typename Edge>
0507     struct edge_owner_property_map
0508     {
0509       typedef processor_id_type value_type;
0510       typedef value_type reference;
0511       typedef edge_descriptor<Edge> key_type;
0512       typedef readable_property_map_tag category;
0513     };
0514 
0515     template<typename Edge>
0516     inline processor_id_type
0517     get(edge_owner_property_map<Edge>, const edge_descriptor<Edge>& e)
0518     {
0519       return e.source_owns_edge? e.source_processor : e.target_processor;
0520     }
0521 
0522     
0523 
0524 
0525 
0526     template<typename Edge>
0527     struct edge_local_property_map
0528     {
0529       typedef Edge value_type;
0530       typedef value_type reference;
0531       typedef edge_descriptor<Edge> key_type;
0532       typedef readable_property_map_tag category;
0533     };
0534 
0535     template<typename Edge>
0536     inline Edge
0537     get(edge_local_property_map<Edge>,
0538         const edge_descriptor<Edge>& e)
0539     {
0540       return e.local;
0541     }
0542 
0543     
0544 
0545 
0546 
0547 
0548     template<typename Edge>
0549     inline bool
0550     operator==(const edge_descriptor<Edge>& e1,
0551                const edge_descriptor<Edge>& e2)
0552     {
0553       return (e1.source_processor == e2.source_processor
0554               && e1.target_processor == e2.target_processor
0555               && e1.local == e2.local);
0556     }
0557 
0558     
0559     template<typename Edge>
0560     inline bool
0561     operator!=(const edge_descriptor<Edge>& e1,
0562                const edge_descriptor<Edge>& e2)
0563     { return !(e1 == e2); }
0564 
0565     
0566 
0567 
0568 
0569 
0570 
0571     template<typename OutEdgeListS, typename ProcessGroup,
0572              typename InVertexListS, typename InDistribution,
0573              typename DirectedS, typename VertexProperty, 
0574              typename EdgeProperty, typename GraphProperty, 
0575              typename EdgeListS>
0576     struct adjacency_list_config
0577     {
0578       typedef typename mpl::if_<is_same<InVertexListS, defaultS>, 
0579                                 vecS, InVertexListS>::type 
0580         VertexListS;
0581 
0582       
0583       typedef property<edge_target_processor_id_t, processor_id_type,
0584                        EdgeProperty> edge_property_with_id;
0585 
0586       
0587       typedef typename boost::mpl::if_<is_same<DirectedS, undirectedS>,
0588                                        property<edge_locally_owned_t, bool,
0589                                                 edge_property_with_id>,
0590                                        edge_property_with_id>::type
0591         base_edge_property_type;
0592 
0593       
0594       typedef typename adjacency_list_traits<OutEdgeListS,
0595                                              VertexListS,
0596                                              directedS>::edge_descriptor
0597         local_edge_descriptor;
0598 
0599       
0600       typedef stored_in_edge<local_edge_descriptor> bidir_stored_edge;
0601 
0602       
0603       
0604       typedef typename container_gen<EdgeListS, bidir_stored_edge>::type
0605         in_edge_list_type;
0606 
0607       
0608       
0609       typedef typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
0610                                        property<vertex_in_edges_t, in_edge_list_type,
0611                                                 VertexProperty>,
0612                                        VertexProperty>::type 
0613         base_vertex_property_type;
0614 
0615       
0616       typedef adjacency_list<OutEdgeListS,
0617                              distributedS<ProcessGroup, 
0618                                           VertexListS, 
0619                                           InDistribution>,
0620                              DirectedS, VertexProperty, EdgeProperty,
0621                              GraphProperty, EdgeListS> 
0622         graph_type;
0623 
0624       
0625       typedef adjacency_list<OutEdgeListS, VertexListS, directedS,
0626                              base_vertex_property_type,
0627                              base_edge_property_type,
0628                              GraphProperty,
0629                              EdgeListS> 
0630         inherited;
0631       
0632       typedef InDistribution in_distribution_type;
0633       typedef typename inherited::vertices_size_type vertices_size_type;
0634 
0635           typedef typename ::boost::graph::distributed::select_distribution<
0636               in_distribution_type, VertexProperty, vertices_size_type, 
0637               ProcessGroup>::type 
0638         base_distribution_type;
0639 
0640           typedef ::boost::graph::distributed::shuffled_distribution<
0641           base_distribution_type> distribution_type;
0642 
0643       typedef VertexProperty vertex_property_type;
0644       typedef EdgeProperty edge_property_type;
0645       typedef ProcessGroup process_group_type;
0646 
0647       typedef VertexListS vertex_list_selector;
0648       typedef OutEdgeListS out_edge_list_selector;
0649       typedef DirectedS directed_selector;
0650       typedef GraphProperty graph_property_type;
0651       typedef EdgeListS edge_list_selector;
0652     };
0653 
0654     
0655     template<typename IteratorPair, typename VertexIndexMap>
0656     void
0657     maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index,
0658                                     read_write_property_map_tag)
0659     {
0660       typedef typename property_traits<VertexIndexMap>::value_type index_t;
0661       index_t next_index = 0;
0662       while (p.first != p.second)
0663         put(to_index, *p.first++, next_index++);
0664     }
0665 
0666     template<typename IteratorPair, typename VertexIndexMap>
0667     inline void
0668     maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index,
0669                                     readable_property_map_tag)
0670     {
0671       
0672     }
0673 
0674     template<typename IteratorPair, typename VertexIndexMap>
0675     inline void
0676     maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index)
0677     {
0678       typedef typename property_traits<VertexIndexMap>::category category;
0679       maybe_initialize_vertex_indices(p, to_index, category());
0680     }
0681 
0682     template<typename IteratorPair>
0683     inline void
0684     maybe_initialize_vertex_indices(IteratorPair p,
0685                                     ::boost::detail::error_property_not_found)
0686     { }
0687 
0688     
0689 
0690 
0691 
0692     
0693 
0694 
0695 
0696     template<typename Vertex, typename LocalVertex>
0697     struct msg_add_edge_data
0698     {
0699       msg_add_edge_data() { }
0700 
0701       msg_add_edge_data(Vertex source, Vertex target)
0702         : source(source.local), target(target) { }
0703 
0704       
0705       
0706       LocalVertex source;
0707         
0708       
0709       Vertex target;
0710         
0711       template<typename Archiver>
0712       void serialize(Archiver& ar, const unsigned int )
0713       {
0714         ar & unsafe_serialize(source) & target;
0715       }
0716     };
0717 
0718     
0719 
0720 
0721 
0722     template<typename Vertex, typename LocalVertex, typename EdgeProperty>
0723     struct msg_add_edge_with_property_data
0724       : msg_add_edge_data<Vertex, LocalVertex>, 
0725         maybe_store_property<EdgeProperty>
0726     {
0727     private:
0728       typedef msg_add_edge_data<Vertex, LocalVertex> inherited_data;
0729       typedef maybe_store_property<EdgeProperty> inherited_property;
0730 
0731     public:
0732       msg_add_edge_with_property_data() { }
0733 
0734       msg_add_edge_with_property_data(Vertex source, 
0735                                       Vertex target,
0736                                       const EdgeProperty& property)
0737         : inherited_data(source, target),
0738           inherited_property(property) { }
0739       
0740       template<typename Archiver>
0741       void serialize(Archiver& ar, const unsigned int )
0742       {
0743         ar & boost::serialization::base_object<inherited_data>(*this) 
0744            & boost::serialization::base_object<inherited_property>(*this);
0745       }
0746     };
0747 
0748     
0749     
0750     
0751 
0752 
0753 
0754 
0755 
0756 
0757     template<typename Property>
0758     struct get_adj_list_pmap
0759     {
0760       template<typename Graph>
0761       struct apply
0762       {
0763         typedef Graph graph_type;
0764         typedef typename graph_type::process_group_type process_group_type;
0765         typedef typename graph_type::inherited base_graph_type;
0766         typedef typename property_map<base_graph_type, Property>::type
0767           local_pmap;
0768         typedef typename property_map<base_graph_type, Property>::const_type
0769           local_const_pmap;
0770 
0771         typedef graph_traits<graph_type> traits;
0772         typedef typename graph_type::local_vertex_descriptor local_vertex;
0773         typedef typename property_traits<local_pmap>::key_type local_key_type;
0774 
0775         typedef typename property_traits<local_pmap>::value_type value_type;
0776 
0777         typedef typename property_map<Graph, vertex_global_t>::const_type
0778           vertex_global_map;
0779         typedef typename property_map<Graph, edge_global_t>::const_type
0780           edge_global_map;
0781 
0782         typedef typename mpl::if_c<(is_same<local_key_type,
0783                                             local_vertex>::value),
0784                                    vertex_global_map, edge_global_map>::type
0785           global_map;
0786 
0787       public:
0788         typedef ::boost::parallel::distributed_property_map<
0789                   process_group_type, global_map, local_pmap> type;
0790 
0791         typedef ::boost::parallel::distributed_property_map<
0792                   process_group_type, global_map, local_const_pmap> const_type;
0793       };
0794     };
0795 
0796     
0797 
0798 
0799 
0800     template<>
0801     struct get_adj_list_pmap<vertex_local_index_t>
0802     {
0803       template<typename Graph>
0804       struct apply
0805         : ::boost::property_map<typename Graph::inherited, vertex_index_t>
0806       { };
0807     };
0808 
0809     
0810 
0811 
0812 
0813 
0814 
0815     template<>
0816     struct get_adj_list_pmap<vertex_index_t>
0817     {
0818       template<typename Graph>
0819       struct apply
0820       {
0821       private:
0822         typedef typename property_map<Graph, vertex_global_t>::const_type
0823           global_map;
0824 
0825         typedef property_map<typename Graph::inherited, vertex_index_t> local;
0826 
0827       public:
0828         typedef local_property_map<typename Graph::process_group_type,
0829                                    global_map,
0830                                    typename local::type> type;
0831         typedef local_property_map<typename Graph::process_group_type,
0832                                    global_map,
0833                                    typename local::const_type> const_type;
0834       };
0835     };
0836 
0837     
0838 
0839 
0840 
0841     template<>
0842     struct get_adj_list_pmap<vertex_global_t>
0843     {
0844       template<typename Graph>
0845       struct apply
0846       {
0847       private:
0848         typedef typename Graph::local_vertex_descriptor
0849           local_vertex_descriptor;
0850       public:
0851         typedef global_descriptor_property_map<local_vertex_descriptor> type;
0852         typedef type const_type;
0853       };
0854     };
0855 
0856     
0857 
0858 
0859 
0860     template<>
0861     struct get_adj_list_pmap<vertex_owner_t>
0862     {
0863       template<typename Graph>
0864       struct apply
0865       {
0866       private:
0867         typedef typename Graph::local_vertex_descriptor
0868           local_vertex_descriptor;
0869       public:
0870         typedef owner_property_map<local_vertex_descriptor> type;
0871         typedef type const_type;
0872       };
0873     };
0874 
0875     
0876 
0877 
0878 
0879     template<>
0880     struct get_adj_list_pmap<vertex_local_t>
0881     {
0882       template<typename Graph>
0883       struct apply
0884       {
0885       private:
0886         typedef typename Graph::local_vertex_descriptor
0887           local_vertex_descriptor;
0888       public:
0889         typedef local_descriptor_property_map<local_vertex_descriptor> type;
0890         typedef type const_type;
0891       };
0892     };
0893 
0894     
0895 
0896 
0897 
0898     template<>
0899     struct get_adj_list_pmap<edge_global_t>
0900     {
0901       template<typename Graph>
0902       struct apply
0903       {
0904       private:
0905         typedef typename Graph::local_edge_descriptor
0906           local_edge_descriptor;
0907       public:
0908         typedef edge_global_property_map<local_edge_descriptor> type;
0909         typedef type const_type;
0910       };
0911     };
0912 
0913     
0914 
0915 
0916 
0917     template<>
0918     struct get_adj_list_pmap<edge_owner_t>
0919     {
0920       template<typename Graph>
0921       struct apply
0922       {
0923       private:
0924         typedef typename Graph::local_edge_descriptor
0925           local_edge_descriptor;
0926       public:
0927         typedef edge_owner_property_map<local_edge_descriptor> type;
0928         typedef type const_type;
0929       };
0930     };
0931 
0932     
0933 
0934 
0935 
0936     template<>
0937     struct get_adj_list_pmap<edge_local_t>
0938     {
0939       template<typename Graph>
0940       struct apply
0941       {
0942       private:
0943         typedef typename Graph::local_edge_descriptor
0944           local_edge_descriptor;
0945       public:
0946         typedef edge_local_property_map<local_edge_descriptor> type;
0947         typedef type const_type;
0948       };
0949     };
0950     
0951 
0952     
0953     template<typename Graph>
0954     inline void
0955     remove_in_edge(typename Graph::edge_descriptor, Graph&, directedS)
0956     { }
0957 
0958     
0959     
0960     template<typename Graph>
0961     inline void
0962     remove_in_edge(typename Graph::edge_descriptor e, Graph& g, bidirectionalS)
0963     {
0964       typedef typename Graph::in_edge_list_type in_edge_list_type;
0965       in_edge_list_type& in_edges =
0966         get(vertex_in_edges, g.base())[target(e, g).local];
0967       typename in_edge_list_type::iterator i = in_edges.begin();
0968       while (i != in_edges.end()
0969              && !(i->source_processor == source(e, g).owner)
0970              && i->e == e.local)
0971         ++i;
0972 
0973       BOOST_ASSERT(i != in_edges.end());
0974       in_edges.erase(i);
0975     }
0976 
0977     
0978     template<typename Graph>
0979     inline void
0980     remove_in_edge(typename Graph::edge_descriptor e, Graph& g, undirectedS)
0981     {
0982       typedef typename Graph::inherited base_type;
0983       typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0984 
0985       
0986       
0987       base_type& bg = g.base();
0988       vertex_descriptor u = source(e, g);
0989       vertex_descriptor v = target(e, g);
0990       if (v.owner != process_id(g.process_group())) {
0991         using std::swap;
0992         swap(u, v);
0993       }
0994 
0995       typename graph_traits<base_type>::out_edge_iterator ei, ei_end;
0996       for (boost::tie(ei, ei_end) = out_edges(v.local, bg); ei != ei_end; ++ei)
0997       {
0998         if (target(*ei, g.base()) == u.local
0999             
1000             && get(edge_target_processor_id, bg, *ei) == u.owner) {
1001           remove_edge(ei, bg);
1002           return;
1003         }
1004       }
1005 
1006       if (v.owner == process_id(g.process_group())) {
1007 
1008       }
1009     }
1010 
1011     
1012     
1013 
1014     
1015     
1016     
1017     template <class Graph, class Config, class Base>
1018     inline std::pair<typename Config::edge_descriptor, bool>
1019     add_local_edge(typename Config::vertex_descriptor u,
1020                    typename Config::vertex_descriptor v,
1021                    const typename Config::edge_property_type& p,
1022                    vec_adj_list_impl<Graph, Config, Base>& g_)
1023     {
1024       adj_list_helper<Config, Base>& g = g_;
1025       return add_edge(u, v, p, g);
1026     }
1027 
1028     template <class Graph, class Config, class Base>
1029     inline std::pair<typename Config::edge_descriptor, bool>
1030     add_local_edge(typename Config::vertex_descriptor u,
1031                    typename Config::vertex_descriptor v,
1032                    const typename Config::edge_property_type& p,
1033                    boost::adj_list_impl<Graph, Config, Base>& g)
1034     {
1035       return add_edge(u, v, p, g);
1036     }
1037 
1038     template <class EdgeProperty,class EdgeDescriptor>
1039     struct msg_nonlocal_edge_data
1040       : public detail::parallel::maybe_store_property<EdgeProperty>
1041     {
1042       typedef EdgeProperty edge_property_type;
1043       typedef EdgeDescriptor local_edge_descriptor;
1044       typedef detail::parallel::maybe_store_property<edge_property_type> 
1045         inherited;
1046 
1047       msg_nonlocal_edge_data() {}
1048       msg_nonlocal_edge_data(local_edge_descriptor e,
1049                              const edge_property_type& p)
1050         : inherited(p), e(e) { }
1051 
1052       local_edge_descriptor e;
1053 
1054       template<typename Archiver>
1055       void serialize(Archiver& ar, const unsigned int )
1056       {
1057         ar & boost::serialization::base_object<inherited>(*this) & e;
1058       }
1059     };
1060 
1061     template <class EdgeDescriptor>
1062     struct msg_remove_edge_data
1063     {
1064       typedef EdgeDescriptor edge_descriptor;
1065       msg_remove_edge_data() {}
1066       explicit msg_remove_edge_data(edge_descriptor e) : e(e) {}
1067 
1068       edge_descriptor e;
1069 
1070       template<typename Archiver>
1071       void serialize(Archiver& ar, const unsigned int )
1072       {
1073         ar & e;
1074       }
1075     };
1076 
1077   } } 
1078 
1079   
1080 
1081 
1082 
1083 
1084   template<typename OutEdgeListS, typename ProcessGroup,
1085            typename InVertexListS, typename InDistribution, typename DirectedS>
1086   struct adjacency_list_traits<OutEdgeListS,
1087                                distributedS<ProcessGroup, 
1088                                             InVertexListS,
1089                                             InDistribution>,
1090                                DirectedS>
1091   {
1092   private:
1093     typedef typename mpl::if_<is_same<InVertexListS, defaultS>,
1094                               vecS,
1095                               InVertexListS>::type VertexListS;
1096 
1097     typedef adjacency_list_traits<OutEdgeListS, VertexListS, directedS>
1098       base_type;
1099 
1100   public:
1101     typedef typename base_type::vertex_descriptor local_vertex_descriptor;
1102     typedef typename base_type::edge_descriptor   local_edge_descriptor;
1103 
1104     typedef typename boost::mpl::if_<typename DirectedS::is_bidir_t,
1105       bidirectional_tag,
1106       typename boost::mpl::if_<typename DirectedS::is_directed_t,
1107         directed_tag, undirected_tag
1108       >::type
1109     >::type directed_category;
1110 
1111     typedef typename parallel_edge_traits<OutEdgeListS>::type
1112       edge_parallel_category;
1113 
1114     typedef detail::parallel::global_descriptor<local_vertex_descriptor>
1115       vertex_descriptor;
1116 
1117     typedef detail::parallel::edge_descriptor<local_edge_descriptor>
1118       edge_descriptor;
1119   };
1120 
1121 #define PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS                                    \
1122   typename OutEdgeListS, typename ProcessGroup, typename InVertexListS,        \
1123   typename InDistribution, typename DirectedS, typename VertexProperty,        \
1124   typename EdgeProperty,  typename GraphProperty, typename EdgeListS
1125 
1126 #define PBGL_DISTRIB_ADJLIST_TYPE                                              \
1127   adjacency_list<OutEdgeListS,                                                 \
1128                  distributedS<ProcessGroup, InVertexListS, InDistribution>,    \
1129                  DirectedS, VertexProperty, EdgeProperty, GraphProperty,       \
1130                  EdgeListS>
1131 
1132 #define PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG                             \
1133   typename OutEdgeListS, typename ProcessGroup, typename InVertexListS,        \
1134   typename InDistribution, typename VertexProperty,                            \
1135   typename EdgeProperty,  typename GraphProperty, typename EdgeListS
1136   
1137 #define PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directed)                             \
1138   adjacency_list<OutEdgeListS,                                                 \
1139                  distributedS<ProcessGroup, InVertexListS, InDistribution>,    \
1140                  directed, VertexProperty, EdgeProperty, GraphProperty,        \
1141                  EdgeListS>
1142                  
1143   
1144 
1145 
1146 
1147 
1148 
1149 
1150 
1151 
1152 
1153 
1154 
1155 
1156 
1157 
1158 
1159 
1160 
1161 
1162 
1163 
1164 
1165 
1166 
1167 
1168 
1169 
1170 
1171 
1172 
1173 
1174 
1175 
1176 
1177 
1178 
1179 
1180 
1181 
1182 
1183 
1184 
1185 
1186 
1187 
1188 
1189 
1190 
1191 
1192 
1193 
1194 
1195 
1196 
1197 
1198 
1199 
1200 
1201 
1202 
1203 
1204 
1205 
1206 
1207 
1208 
1209 
1210 
1211 
1212 
1213 
1214 
1215 
1216 
1217 
1218 
1219 
1220 
1221 
1222 
1223 
1224 
1225 
1226 
1227 
1228 
1229 
1230 
1231 
1232 
1233 
1234 
1235 
1236 
1237 
1238 
1239 
1240 
1241 
1242 
1243 
1244 
1245 
1246 
1247 
1248 
1249 
1250 
1251 
1252 
1253 
1254 
1255 
1256 
1257 
1258 
1259 
1260 
1261 
1262   template<typename OutEdgeListS, typename ProcessGroup,
1263            typename InVertexListS, typename InDistribution, typename DirectedS,
1264            typename VertexProperty, typename EdgeProperty, 
1265            typename GraphProperty, typename EdgeListS>
1266   class adjacency_list<OutEdgeListS,
1267                        distributedS<ProcessGroup, 
1268                                     InVertexListS, 
1269                                     InDistribution>,
1270                        DirectedS, VertexProperty,
1271                        EdgeProperty, GraphProperty, EdgeListS>
1272     : 
1273       public graph::distributed::maybe_named_graph<   
1274         adjacency_list<OutEdgeListS,
1275                        distributedS<ProcessGroup,
1276                                     InVertexListS,
1277                                     InDistribution>,
1278                        DirectedS, VertexProperty,
1279                        EdgeProperty, GraphProperty, EdgeListS>,
1280         typename adjacency_list_traits<OutEdgeListS, 
1281                                        distributedS<ProcessGroup,
1282                                                     InVertexListS,
1283                                                     InDistribution>,
1284                                        DirectedS>::vertex_descriptor,
1285         typename adjacency_list_traits<OutEdgeListS, 
1286                                        distributedS<ProcessGroup,
1287                                                     InVertexListS,
1288                                                     InDistribution>,
1289                                        DirectedS>::edge_descriptor,
1290         detail::parallel::adjacency_list_config<OutEdgeListS, ProcessGroup, 
1291                                                 InVertexListS, InDistribution,
1292                                                 DirectedS, VertexProperty, 
1293                                                 EdgeProperty, GraphProperty, 
1294                                                 EdgeListS> >
1295   {
1296     typedef detail::parallel::adjacency_list_config<OutEdgeListS, ProcessGroup, 
1297                                                 InVertexListS, InDistribution,
1298                                                 DirectedS, VertexProperty, 
1299                                                 EdgeProperty, GraphProperty, 
1300                                                 EdgeListS>
1301       config_type;
1302       
1303     typedef adjacency_list_traits<OutEdgeListS,
1304                                   distributedS<ProcessGroup, 
1305                                                InVertexListS, 
1306                                                InDistribution>,
1307                                   DirectedS> 
1308       traits_type;
1309 
1310     typedef typename DirectedS::is_directed_t is_directed;
1311 
1312     typedef EdgeListS edge_list_selector;
1313 
1314   public:
1315     
1316     
1317     typedef typename config_type::in_edge_list_type in_edge_list_type;
1318 
1319 
1320     
1321     typedef typename config_type::inherited inherited;
1322 
1323     
1324     
1325     
1326     typedef typename inherited::vertex_property_type
1327       base_vertex_property_type;
1328 
1329     
1330     typedef typename config_type::graph_type graph_type;
1331 
1332     
1333     typedef typename traits_type::local_vertex_descriptor
1334       local_vertex_descriptor;
1335     typedef typename traits_type::local_edge_descriptor
1336       local_edge_descriptor;
1337     typedef typename traits_type::vertex_descriptor vertex_descriptor;
1338     typedef typename traits_type::edge_descriptor edge_descriptor;
1339 
1340     typedef typename traits_type::directed_category directed_category;
1341     typedef typename inherited::edge_parallel_category
1342       edge_parallel_category;
1343     typedef typename inherited::graph_tag graph_tag;
1344 
1345     
1346     
1347     
1348     
1349     BOOST_STATIC_ASSERT((is_same<edge_parallel_category,
1350                                  allow_parallel_edge_tag>::value));
1351 
1352     
1353 
1354 
1355 
1356 
1357 
1358 
1359 
1360 
1361 
1362     typedef typename boost::mpl::if_<
1363               is_same<DirectedS, directedS>,
1364               directed_distributed_adj_list_tag,
1365               typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
1366                                        bidirectional_distributed_adj_list_tag,
1367                                        undirected_distributed_adj_list_tag>::type>
1368       ::type traversal_category;
1369 
1370     typedef typename inherited::degree_size_type degree_size_type;
1371     typedef typename inherited::vertices_size_type vertices_size_type;
1372     typedef typename inherited::edges_size_type edges_size_type;
1373     typedef VertexProperty vertex_property_type;
1374     typedef EdgeProperty edge_property_type;
1375     typedef typename inherited::graph_property_type graph_property_type;
1376     typedef typename inherited::vertex_bundled vertex_bundled;
1377     typedef typename inherited::edge_bundled edge_bundled;
1378     typedef typename inherited::graph_bundled graph_bundled;
1379 
1380     typedef typename container_gen<edge_list_selector, edge_descriptor>::type
1381       local_edge_list_type;
1382 
1383   private:
1384     typedef typename boost::mpl::if_<is_same<DirectedS, bidirectionalS>,
1385                                      typename in_edge_list_type::const_iterator,
1386                                      typename inherited::out_edge_iterator>::type
1387       base_in_edge_iterator;
1388 
1389     typedef typename inherited::out_edge_iterator base_out_edge_iterator;
1390     typedef typename graph_traits<inherited>::edge_iterator
1391       base_edge_iterator;
1392     typedef typename inherited::edge_property_type base_edge_property_type;
1393 
1394     typedef typename local_edge_list_type::const_iterator
1395       undirected_edge_iterator;
1396 
1397     typedef InDistribution in_distribution_type;
1398 
1399     typedef parallel::trigger_receive_context trigger_receive_context;
1400 
1401   public:
1402     
1403     typedef transform_iterator<typename vertex_descriptor::generator,
1404                                typename inherited::vertex_iterator>
1405       vertex_iterator;
1406 
1407     
1408     typedef typename edge_descriptor::template out_generator<adjacency_list>
1409       out_edge_generator;
1410 
1411     
1412     typedef transform_iterator<out_edge_generator,
1413                                typename inherited::out_edge_iterator>
1414       out_edge_iterator;
1415 
1416     
1417     typedef typename edge_descriptor::template in_generator<adjacency_list>
1418       in_edge_generator;
1419 
1420     
1421     typedef transform_iterator<in_edge_generator, base_in_edge_iterator>
1422       in_edge_iterator;
1423 
1424     
1425     typedef boost::adjacency_iterator<
1426               adjacency_list, vertex_descriptor, out_edge_iterator,
1427               typename std::iterator_traits<base_out_edge_iterator>
1428                          ::difference_type>
1429       adjacency_iterator;
1430 
1431     
1432     typedef typename boost::mpl::if_<is_same<DirectedS, undirectedS>,
1433                                      undirected_edge_iterator,
1434                                      transform_iterator<out_edge_generator,
1435                                                         base_edge_iterator>
1436                                      >::type 
1437       edge_iterator;
1438 
1439   public:
1440     
1441     typedef graph::distributed::maybe_named_graph<graph_type, 
1442                                                   vertex_descriptor, 
1443                                                   edge_descriptor, 
1444                                                   config_type> 
1445       named_graph_mixin;
1446         
1447     
1448     typedef ProcessGroup process_group_type;
1449 
1450     
1451     typedef typename process_group_type::process_id_type process_id_type;
1452 
1453     
1454     typedef DirectedS directed_selector;
1455 
1456     
1457     struct lazy_add_vertex_with_property;
1458     friend struct lazy_add_vertex_with_property;
1459 
1460     
1461     struct lazy_add_edge;
1462     friend struct lazy_add_edge;
1463 
1464     
1465     struct lazy_add_edge_with_property;
1466     friend struct lazy_add_edge_with_property;
1467 
1468     
1469     
1470     typedef typename graph::distributed::select_distribution<
1471               InDistribution, VertexProperty, vertices_size_type, 
1472               ProcessGroup>::default_type 
1473       default_distribution_type;
1474     
1475     
1476     
1477     typedef typename graph::distributed::select_distribution<
1478               InDistribution, VertexProperty, vertices_size_type,
1479               ProcessGroup>::type 
1480       base_distribution_type;
1481 
1482       typedef graph::distributed::shuffled_distribution<
1483           base_distribution_type> distribution_type;
1484 
1485   private:
1486     
1487     
1488     
1489     adjacency_list(const adjacency_list& other);
1490     adjacency_list& operator=(const adjacency_list& other);
1491 
1492   public:
1493     adjacency_list(const ProcessGroup& pg = ProcessGroup())
1494       : named_graph_mixin(pg, default_distribution_type(pg, 0)),
1495         m_local_graph(GraphProperty()), 
1496         process_group_(pg, boost::parallel::attach_distributed_object())
1497     {
1498       setup_triggers();
1499     }
1500 
1501     adjacency_list(const ProcessGroup& pg, 
1502                    const base_distribution_type& distribution)
1503       : named_graph_mixin(pg, distribution),
1504         m_local_graph(GraphProperty()), 
1505         process_group_(pg, boost::parallel::attach_distributed_object())
1506     {
1507       setup_triggers();
1508     }
1509 
1510     adjacency_list(const GraphProperty& g,
1511                    const ProcessGroup& pg = ProcessGroup())
1512       : named_graph_mixin(pg, default_distribution_type(pg, 0)),
1513         m_local_graph(g), 
1514         process_group_(pg, boost::parallel::attach_distributed_object())
1515     {
1516       setup_triggers();
1517     }
1518 
1519     adjacency_list(vertices_size_type n,
1520                    const GraphProperty& p,
1521                    const ProcessGroup& pg,
1522                    const base_distribution_type& distribution)
1523       : named_graph_mixin(pg, distribution),
1524         m_local_graph(distribution.block_size(process_id(pg), n), p),
1525         process_group_(pg, boost::parallel::attach_distributed_object())
1526     {
1527       setup_triggers();
1528 
1529       detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
1530                                       get(vertex_index, base()));
1531     }
1532 
1533     adjacency_list(vertices_size_type n,
1534                    const ProcessGroup& pg,
1535                    const base_distribution_type& distribution)
1536       : named_graph_mixin(pg, distribution),
1537         m_local_graph(distribution.block_size(process_id(pg), n), GraphProperty()),
1538         process_group_(pg, boost::parallel::attach_distributed_object()) 
1539     {
1540       setup_triggers();
1541 
1542       detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
1543                                       get(vertex_index, base()));
1544     }
1545 
1546     adjacency_list(vertices_size_type n,
1547                    const GraphProperty& p,
1548                    const ProcessGroup& pg = ProcessGroup())
1549       : named_graph_mixin(pg, default_distribution_type(pg, n)),
1550         m_local_graph(this->distribution().block_size(process_id(pg), n), p),
1551         process_group_(pg, boost::parallel::attach_distributed_object())
1552     {
1553       setup_triggers();
1554 
1555       detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
1556                                       get(vertex_index, base()));
1557     }
1558 
1559     adjacency_list(vertices_size_type n,
1560                    const ProcessGroup& pg = ProcessGroup())
1561       : named_graph_mixin(pg, default_distribution_type(pg, n)),
1562         m_local_graph(this->distribution().block_size(process_id(pg), n), 
1563                       GraphProperty()),
1564         process_group_(pg, boost::parallel::attach_distributed_object())
1565     {
1566       setup_triggers();
1567 
1568       detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
1569                                       get(vertex_index, base()));
1570     }
1571 
1572     
1573 
1574 
1575 
1576 
1577 
1578     template <class EdgeIterator>
1579     adjacency_list(EdgeIterator first, EdgeIterator last,
1580                    vertices_size_type n,
1581                    const ProcessGroup& pg = ProcessGroup(),
1582                    const GraphProperty& p = GraphProperty())
1583       : named_graph_mixin(pg, default_distribution_type(pg, n)),
1584         m_local_graph(this->distribution().block_size(process_id(pg), n), p),
1585         process_group_(pg, boost::parallel::attach_distributed_object())
1586     {
1587       setup_triggers();
1588 
1589       typedef typename config_type::VertexListS vertex_list_selector;
1590       initialize(first, last, n, this->distribution(), vertex_list_selector());
1591       detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
1592                                       get(vertex_index, base()));
1593 
1594     }
1595 
1596     template <class EdgeIterator, class EdgePropertyIterator>
1597     adjacency_list(EdgeIterator first, EdgeIterator last,
1598                    EdgePropertyIterator ep_iter,
1599                    vertices_size_type n,
1600                    const ProcessGroup& pg = ProcessGroup(),
1601                    const GraphProperty& p = GraphProperty())
1602       : named_graph_mixin(pg, default_distribution_type(pg, n)),
1603         m_local_graph(this->distribution().block_size(process_id(pg), n), p),
1604         process_group_(pg, boost::parallel::attach_distributed_object())
1605     {
1606       setup_triggers();
1607 
1608       typedef typename config_type::VertexListS vertex_list_selector;
1609       initialize(first, last, ep_iter, n, this->distribution(),
1610                  vertex_list_selector());
1611       detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
1612                                       get(vertex_index, base()));
1613 
1614     }
1615 
1616     template <class EdgeIterator>
1617     adjacency_list(EdgeIterator first, EdgeIterator last,
1618                    vertices_size_type n,
1619                    const ProcessGroup& pg,
1620                    const base_distribution_type& distribution,
1621                    const GraphProperty& p = GraphProperty())
1622       : named_graph_mixin(pg, distribution),
1623         m_local_graph(distribution.block_size(process_id(pg), n), p),
1624         process_group_(pg, boost::parallel::attach_distributed_object())
1625     {
1626       setup_triggers();
1627 
1628       typedef typename config_type::VertexListS vertex_list_selector;
1629       initialize(first, last, n, this->distribution(), vertex_list_selector());
1630       detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
1631                                       get(vertex_index, base()));
1632 
1633     }
1634 
1635     template <class EdgeIterator, class EdgePropertyIterator>
1636     adjacency_list(EdgeIterator first, EdgeIterator last,
1637                    EdgePropertyIterator ep_iter,
1638                    vertices_size_type n,
1639                    const ProcessGroup& pg,
1640                    const base_distribution_type& distribution,
1641                    const GraphProperty& p = GraphProperty())
1642       : named_graph_mixin(pg, distribution),
1643         m_local_graph(this->distribution().block_size(process_id(pg), n), p),
1644         process_group_(pg, boost::parallel::attach_distributed_object())
1645     {
1646       setup_triggers();
1647 
1648       typedef typename config_type::VertexListS vertex_list_selector;
1649       initialize(first, last, ep_iter, n, distribution,
1650                  vertex_list_selector());
1651       detail::parallel::maybe_initialize_vertex_indices(vertices(base()),
1652                                       get(vertex_index, base()));
1653 
1654     }
1655 
1656     ~adjacency_list()
1657     {
1658       synchronize(process_group_);
1659     }
1660 
1661     void clear()
1662     {
1663       base().clear();
1664       local_edges_.clear();
1665       named_graph_mixin::clearing_graph();
1666     }
1667 
1668     void swap(adjacency_list& other)
1669     {
1670       using std::swap;
1671 
1672       base().swap(other);
1673       swap(process_group_, other.process_group_);
1674     }
1675 
1676     static vertex_descriptor null_vertex()
1677     {
1678       return vertex_descriptor(processor_id_type(0),
1679                                inherited::null_vertex());
1680     }
1681 
1682     inherited&       base()       { return m_local_graph; }
1683     const inherited& base() const { return m_local_graph; }
1684 
1685     processor_id_type processor() const { return process_id(process_group_); }
1686     process_group_type process_group() const { return process_group_.base(); }
1687 
1688     local_edge_list_type&       local_edges()       { return local_edges_; }
1689     const local_edge_list_type& local_edges() const { return local_edges_; }
1690 
1691     
1692     
1693     template<typename VertexProcessorMap>
1694     void redistribute(VertexProcessorMap vertex_to_processor);
1695 
1696     
1697     vertex_bundled& operator[](vertex_descriptor v)
1698     {
1699       BOOST_ASSERT(v.owner == processor());
1700       return base()[v.local];
1701     }
1702     
1703     const vertex_bundled& operator[](vertex_descriptor v) const
1704     {
1705       BOOST_ASSERT(v.owner == processor());
1706       return base()[v.local];
1707     }
1708     
1709     edge_bundled& operator[](edge_descriptor e)
1710     {
1711       BOOST_ASSERT(e.owner() == processor());
1712       return base()[e.local];
1713     }
1714     
1715     const edge_bundled& operator[](edge_descriptor e) const
1716     {
1717       BOOST_ASSERT(e.owner() == processor());
1718       return base()[e.local];
1719     }
1720 
1721     graph_bundled& operator[](graph_bundle_t)
1722     { return get_property(*this); }
1723 
1724     graph_bundled const& operator[](graph_bundle_t) const
1725     { return get_property(*this); }
1726 
1727     template<typename OStreamConstructibleArchive>
1728     void save(std::string const& filename) const;
1729 
1730     template<typename IStreamConstructibleArchive>
1731     void load(std::string const& filename);
1732 
1733     
1734     boost::function<void(vertex_descriptor, adjacency_list&)> on_add_vertex;
1735 
1736     
1737     boost::function<void(edge_descriptor, adjacency_list&)> on_add_edge;
1738 
1739   private:
1740     
1741     template<typename VertexProcessorMap>
1742     void
1743     request_in_neighbors(vertex_descriptor,
1744                          VertexProcessorMap,
1745                          directedS) { }
1746 
1747     
1748     template<typename VertexProcessorMap>
1749     void
1750     request_in_neighbors(vertex_descriptor,
1751                          VertexProcessorMap,
1752                          undirectedS) { }
1753 
1754     
1755     template<typename VertexProcessorMap>
1756     void
1757     request_in_neighbors(vertex_descriptor v,
1758                          VertexProcessorMap vertex_to_processor,
1759                          bidirectionalS);
1760 
1761     
1762     void clear_in_edges_local(vertex_descriptor v, directedS) {}
1763     void clear_in_edges_local(vertex_descriptor v, undirectedS) {}
1764 
1765     void clear_in_edges_local(vertex_descriptor v, bidirectionalS)
1766     { get(vertex_in_edges, base())[v.local].clear(); }
1767 
1768     
1769     template<typename VertexProcessorMap>
1770     void
1771     remove_migrated_in_edges(vertex_descriptor,
1772                              VertexProcessorMap,
1773                              directedS) { }
1774 
1775     
1776     template<typename VertexProcessorMap>
1777     void
1778     remove_migrated_in_edges(vertex_descriptor,
1779                              VertexProcessorMap,
1780                              undirectedS) { }
1781 
1782     
1783     template<typename VertexProcessorMap>
1784     void
1785     remove_migrated_in_edges(vertex_descriptor v,
1786                              VertexProcessorMap vertex_to_processor,
1787                              bidirectionalS);
1788 
1789     
1790     
1791     
1792     
1793     template<typename EdgeIterator>
1794     void
1795     initialize(EdgeIterator first, EdgeIterator last,
1796                vertices_size_type, const base_distribution_type& distribution, 
1797                vecS);
1798 
1799     
1800     
1801     
1802     
1803     template<typename EdgeIterator, typename EdgePropertyIterator>
1804     void
1805     initialize(EdgeIterator first, EdgeIterator last,
1806                EdgePropertyIterator ep_iter,
1807                vertices_size_type, const base_distribution_type& distribution, 
1808                vecS);
1809 
1810     
1811     
1812     template<typename EdgeIterator, typename EdgePropertyIterator,
1813              typename VertexListS>
1814     void
1815     initialize(EdgeIterator first, EdgeIterator last,
1816                EdgePropertyIterator ep_iter,
1817                vertices_size_type n, 
1818                const base_distribution_type& distribution,
1819                VertexListS);
1820 
1821     
1822     
1823     
1824     
1825     
1826     template<typename EdgeIterator, typename VertexListS>
1827     void
1828     initialize(EdgeIterator first, EdgeIterator last,
1829                vertices_size_type n, 
1830                const base_distribution_type& distribution,
1831                VertexListS);
1832 
1833   public:
1834     
1835     
1836     
1837     
1838     base_vertex_property_type 
1839     build_vertex_property(const vertex_property_type& p)
1840     { return build_vertex_property(p, directed_selector()); }
1841 
1842     base_vertex_property_type
1843     build_vertex_property(const vertex_property_type& p, directedS)
1844     {
1845       return base_vertex_property_type(p);
1846     }
1847 
1848     base_vertex_property_type
1849     build_vertex_property(const vertex_property_type& p, bidirectionalS)
1850     {
1851       return base_vertex_property_type(in_edge_list_type(), p);
1852     }
1853 
1854     base_vertex_property_type
1855     build_vertex_property(const vertex_property_type& p, undirectedS)
1856     {
1857       return base_vertex_property_type(p);
1858     }
1859     
1860 
1861     
1862     
1863     
1864     
1865     base_edge_property_type build_edge_property(const edge_property_type& p)
1866     { return build_edge_property(p, directed_selector()); }
1867 
1868     base_edge_property_type
1869     build_edge_property(const edge_property_type& p, directedS)
1870     {
1871       return base_edge_property_type(0, p);
1872     }
1873 
1874     base_edge_property_type
1875     build_edge_property(const edge_property_type& p, bidirectionalS)
1876     {
1877       return base_edge_property_type(0, p);
1878     }
1879 
1880     base_edge_property_type
1881     build_edge_property(const edge_property_type& p, undirectedS)
1882     {
1883       typedef typename base_edge_property_type::next_type
1884         edge_property_with_id;
1885       return base_edge_property_type(true, edge_property_with_id(0, p));
1886     }
1887     
1888 
1889     
1890     
1891     edge_property_type split_edge_property(const base_edge_property_type& p)
1892     { return split_edge_property(p, directed_selector()); }
1893 
1894     edge_property_type
1895     split_edge_property(const base_edge_property_type& p, directedS)
1896     {
1897       return p.m_base;
1898     }
1899 
1900     edge_property_type
1901     split_edge_property(const base_edge_property_type& p, bidirectionalS)
1902     {
1903       return p.m_base;
1904     }
1905 
1906     edge_property_type
1907     split_edge_property(const base_edge_property_type& p, undirectedS)
1908     {
1909       return p.m_base.m_base;
1910     }
1911     
1912 
1913     
1914 
1915 
1916 
1917     enum {
1918       
1919 
1920 
1921 
1922 
1923       msg_add_vertex_with_property = 0,
1924 
1925       
1926 
1927 
1928 
1929 
1930 
1931       msg_add_vertex_with_property_and_reply,
1932 
1933       
1934 
1935 
1936 
1937       msg_add_vertex_reply,
1938 
1939       
1940 
1941 
1942 
1943       msg_add_edge,
1944 
1945       
1946 
1947 
1948 
1949       msg_add_edge_with_property,
1950 
1951       
1952 
1953 
1954 
1955 
1956       msg_add_edge_with_reply,
1957 
1958       
1959 
1960 
1961 
1962 
1963       msg_add_edge_with_property_and_reply,
1964 
1965       
1966 
1967 
1968 
1969 
1970       msg_add_edge_reply,
1971 
1972       
1973 
1974 
1975 
1976 
1977 
1978       msg_nonlocal_edge,
1979 
1980       
1981 
1982 
1983 
1984 
1985       msg_remove_edge,
1986 
1987       
1988 
1989 
1990 
1991 
1992 
1993       msg_num_relocated
1994     };
1995 
1996     typedef detail::parallel::msg_add_edge_data<vertex_descriptor,
1997                                                 local_vertex_descriptor>
1998       msg_add_edge_data;
1999 
2000     typedef detail::parallel::msg_add_edge_with_property_data
2001               <vertex_descriptor, local_vertex_descriptor, 
2002                edge_property_type> msg_add_edge_with_property_data;
2003 
2004     typedef  boost::detail::parallel::msg_nonlocal_edge_data<
2005       edge_property_type,local_edge_descriptor> msg_nonlocal_edge_data;
2006 
2007     typedef boost::detail::parallel::msg_remove_edge_data<edge_descriptor>
2008       msg_remove_edge_data;
2009 
2010     void send_remove_edge_request(edge_descriptor e)
2011     {
2012       process_id_type dest = e.target_processor;
2013       if (e.target_processor == process_id(process_group_))
2014         dest = e.source_processor;
2015       send(process_group_, dest, msg_remove_edge, msg_remove_edge_data(e));
2016     }
2017 
2018     
2019     void setup_triggers();
2020 
2021     void 
2022     handle_add_vertex_with_property(int source, int tag,
2023                                     const vertex_property_type&,
2024                                     trigger_receive_context);
2025 
2026     local_vertex_descriptor
2027     handle_add_vertex_with_property_and_reply(int source, int tag,
2028                                         const vertex_property_type&,
2029                                         trigger_receive_context);
2030 
2031     void 
2032     handle_add_edge(int source, int tag, const msg_add_edge_data& data,
2033                     trigger_receive_context);
2034 
2035     boost::parallel::detail::untracked_pair<edge_descriptor, bool>
2036     handle_add_edge_with_reply(int source, int tag, 
2037                          const msg_add_edge_data& data,
2038                          trigger_receive_context);
2039 
2040     void 
2041     handle_add_edge_with_property(int source, int tag,
2042                                   const msg_add_edge_with_property_data&,
2043                                   trigger_receive_context);
2044               
2045     boost::parallel::detail::untracked_pair<edge_descriptor, bool>
2046     handle_add_edge_with_property_and_reply
2047       (int source, int tag, const msg_add_edge_with_property_data&,
2048        trigger_receive_context);
2049 
2050     void 
2051     handle_nonlocal_edge(int source, int tag, 
2052                          const msg_nonlocal_edge_data& data,
2053                          trigger_receive_context);
2054 
2055     void 
2056     handle_remove_edge(int source, int tag, 
2057                        const msg_remove_edge_data& data,
2058                        trigger_receive_context);
2059          
2060   protected:
2061     
2062 
2063 
2064 
2065 
2066 
2067 
2068 
2069 
2070 
2071 
2072 
2073 
2074 
2075 
2076 
2077 
2078     void
2079     add_remote_edge(const msg_nonlocal_edge_data&,
2080                     processor_id_type, directedS)
2081     { }
2082 
2083 
2084     
2085 
2086 
2087     void
2088     add_remote_edge(const msg_nonlocal_edge_data& data,
2089                     processor_id_type other_proc, bidirectionalS)
2090     {
2091       typedef detail::parallel::stored_in_edge<local_edge_descriptor> stored_edge;
2092 
2093       stored_edge edge(other_proc, data.e);
2094       local_vertex_descriptor v = target(data.e, base());
2095       boost::graph_detail::push(get(vertex_in_edges, base())[v], edge);
2096     }
2097 
2098     
2099 
2100 
2101     void
2102     add_remote_edge(const msg_nonlocal_edge_data& data,
2103                     processor_id_type other_proc, undirectedS)
2104     {
2105       std::pair<local_edge_descriptor, bool> edge =
2106         detail::parallel::add_local_edge(target(data.e, base()), 
2107                        source(data.e, base()),
2108                        build_edge_property(data.get_property()), base());
2109       BOOST_ASSERT(edge.second);
2110       put(edge_target_processor_id, base(), edge.first, other_proc);
2111 
2112       if (edge.second && on_add_edge)
2113         on_add_edge(edge_descriptor(processor(), other_proc, false, 
2114                                     edge.first),
2115                     *this);
2116     }
2117 
2118     void
2119     remove_local_edge(const msg_remove_edge_data&, processor_id_type,
2120                       directedS)
2121     { }
2122 
2123     void
2124     remove_local_edge(const msg_remove_edge_data& data,
2125                       processor_id_type other_proc, bidirectionalS)
2126     {
2127       
2128 
2129 
2130 
2131       vertex_descriptor src = source(data.e, *this);
2132       vertex_descriptor tgt = target(data.e, *this);
2133 
2134       if (src.owner == process_id(process_group_)) {
2135         base_out_edge_iterator ei, ei_end;
2136         for (boost::tie(ei, ei_end) = out_edges(src.local, base());
2137              ei != ei_end; ++ei) {
2138           
2139           
2140           
2141           if (tgt.local == target(*ei, base())
2142               && get(edge_target_processor_id, base(), *ei) == other_proc)
2143             break;
2144         }
2145 
2146         if (ei != ei_end) boost::remove_edge(ei, base());
2147 
2148         remove_local_edge_from_list(src, tgt, undirectedS());
2149       } else {
2150         BOOST_ASSERT(tgt.owner == process_id(process_group_));
2151         in_edge_list_type& in_edges =
2152           get(vertex_in_edges, base())[tgt.local];
2153         typename in_edge_list_type::iterator ei;
2154         for (ei = in_edges.begin(); ei != in_edges.end(); ++ei) {
2155           if (src.local == source(ei->e, base())
2156               && src.owner == ei->source_processor)
2157             break;
2158         }
2159 
2160         if (ei != in_edges.end()) in_edges.erase(ei);
2161       }
2162     }
2163 
2164     void
2165     remove_local_edge(const msg_remove_edge_data& data,
2166                       processor_id_type other_proc, undirectedS)
2167     {
2168       vertex_descriptor local_vertex = source(data.e, *this);
2169       vertex_descriptor remote_vertex = target(data.e, *this);
2170       if (remote_vertex.owner == process_id(process_group_)) {
2171         using std::swap;
2172         swap(local_vertex, remote_vertex);
2173       }
2174 
2175       
2176       {
2177         base_out_edge_iterator ei, ei_end;
2178         for (boost::tie(ei, ei_end) = out_edges(local_vertex.local, base());
2179              ei != ei_end; ++ei) {
2180           
2181           
2182           
2183           if (remote_vertex.local == target(*ei, base())
2184               && get(edge_target_processor_id, base(), *ei) == other_proc)
2185             break;
2186         }
2187 
2188         if (ei != ei_end) boost::remove_edge(ei, base());
2189       }
2190 
2191       remove_local_edge_from_list(local_vertex, remote_vertex, undirectedS());
2192     }
2193 
2194   public:
2195     void
2196     remove_local_edge_from_list(vertex_descriptor, vertex_descriptor,
2197                                 directedS)
2198     {
2199     }
2200 
2201     void
2202     remove_local_edge_from_list(vertex_descriptor, vertex_descriptor,
2203                                 bidirectionalS)
2204     {
2205     }
2206 
2207     void
2208     remove_local_edge_from_list(vertex_descriptor src, vertex_descriptor tgt,
2209                                 undirectedS)
2210     {
2211       
2212       
2213       
2214       {
2215         typename local_edge_list_type::iterator ei;
2216         for (ei = local_edges_.begin(); ei != local_edges_.end(); ++ei) {
2217           if ((source(*ei, *this) == src
2218                && target(*ei, *this) == tgt)
2219               || (source(*ei, *this) == tgt
2220                   && target(*ei, *this) == src))
2221             break;
2222         }
2223 
2224         if (ei != local_edges_.end()) local_edges_.erase(ei);
2225       }
2226 
2227     }
2228 
2229   private:
2230     
2231     inherited m_local_graph;
2232 
2233     
2234     
2235     process_group_type process_group_;
2236 
2237     
2238     
2239     
2240     local_edge_list_type local_edges_;
2241   };
2242 
2243   
2244   
2245   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2246   struct PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property
2247   {
2248     
2249     lazy_add_vertex_with_property(adjacency_list& self, 
2250                                   const vertex_property_type& property)
2251       : self(self), property(property), committed(false) { }
2252 
2253     
2254     
2255     
2256     lazy_add_vertex_with_property(const lazy_add_vertex_with_property& other)
2257       : self(other.self), property(other.property),
2258         committed(other.committed)
2259     {
2260       other.committed = true;
2261     }
2262 
2263     
2264     
2265     ~lazy_add_vertex_with_property();
2266 
2267     
2268     operator vertex_descriptor() const { return commit(); }
2269 
2270     
2271     
2272     vertex_descriptor commit() const;
2273 
2274   protected:
2275     adjacency_list& self;
2276     vertex_property_type property;
2277     mutable bool committed;
2278 
2279   private:
2280     
2281     void operator=(lazy_add_vertex_with_property&);
2282   };
2283 
2284   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2285   PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property::
2286   ~lazy_add_vertex_with_property()
2287   {
2288     
2289     
2290     
2291     if (committed || boost::core::uncaught_exceptions() > 0)
2292       return;
2293 
2294     committed = true;
2295 
2296     process_id_type owner 
2297       = static_cast<graph_type&>(self).owner_by_property(property);
2298     if (owner == self.processor()) {
2299       
2300       vertex_descriptor v(owner, 
2301                           add_vertex(self.build_vertex_property(property), 
2302                                      self.base()));
2303       if (self.on_add_vertex)
2304         self.on_add_vertex(v, self);
2305     }
2306     else
2307       
2308       
2309       send(self.process_group_, owner, msg_add_vertex_with_property,
2310            property);
2311   }
2312 
2313   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2314   typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor 
2315   PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property::
2316   commit() const
2317   {
2318     BOOST_ASSERT(!this->committed);
2319     this->committed = true;
2320 
2321     process_id_type owner 
2322       = static_cast<graph_type&>(self).owner_by_property(property);
2323     local_vertex_descriptor local_v;
2324     if (owner == self.processor())
2325       
2326       local_v = add_vertex(self.build_vertex_property(property), 
2327                            self.base());
2328     else {
2329       
2330       send_oob_with_reply(self.process_group_, owner,
2331                msg_add_vertex_with_property_and_reply, property,
2332                local_v);
2333     }
2334 
2335     vertex_descriptor v(owner, local_v);
2336     if (self.on_add_vertex)
2337       self.on_add_vertex(v, self);
2338 
2339     
2340     return v;
2341   }
2342   
2343 
2344   
2345 
2346 
2347 
2348 
2349 
2350   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2351   struct PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge
2352   {
2353     
2354     lazy_add_edge(adjacency_list& self, 
2355                   vertex_descriptor source, vertex_descriptor target)
2356       : self(self), source(source), target(target), committed(false) { }
2357 
2358     
2359     
2360     lazy_add_edge(const lazy_add_edge& other)
2361       : self(other.self), source(other.source), target(other.target), 
2362         committed(other.committed)
2363     {
2364       other.committed = true;
2365     }
2366 
2367     
2368     
2369     ~lazy_add_edge();
2370 
2371     
2372     operator std::pair<edge_descriptor, bool>() const { return commit(); }
2373 
2374     
2375     
2376     std::pair<edge_descriptor, bool> commit() const;
2377 
2378   protected:
2379     std::pair<edge_descriptor, bool> 
2380     add_local_edge(const edge_property_type& property, directedS) const;
2381 
2382     std::pair<edge_descriptor, bool> 
2383     add_local_edge(const edge_property_type& property, bidirectionalS) const;
2384 
2385     std::pair<edge_descriptor, bool> 
2386     add_local_edge(const edge_property_type& property, undirectedS) const;
2387 
2388     adjacency_list& self;
2389     vertex_descriptor source;
2390     vertex_descriptor target;
2391     mutable bool committed;
2392 
2393   private:
2394     
2395     void operator=(lazy_add_edge&);
2396   };
2397 
2398   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2399   PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::~lazy_add_edge()
2400   {
2401     
2402     
2403     
2404     if (committed || boost::core::uncaught_exceptions() > 0)
2405       return;
2406 
2407     committed = true;
2408 
2409     if (source.owner == self.processor())
2410       this->add_local_edge(edge_property_type(), DirectedS());
2411     else
2412       
2413       
2414       send(self.process_group_, source.owner, msg_add_edge,
2415            msg_add_edge_data(source, target));
2416   }
2417 
2418   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2419   std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor, bool>
2420   PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::commit() const
2421   {
2422     BOOST_ASSERT(!committed);
2423     committed = true;
2424 
2425     if (source.owner == self.processor())
2426       return this->add_local_edge(edge_property_type(), DirectedS());
2427     else {
2428       
2429       boost::parallel::detail::untracked_pair<edge_descriptor, bool> result;
2430       send_oob_with_reply(self.process_group_, source.owner, 
2431                           msg_add_edge_with_reply,
2432                           msg_add_edge_data(source, target), result);
2433       return result;
2434     }
2435   }
2436 
2437   
2438   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2439   std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor, bool>
2440   PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::
2441   add_local_edge(const edge_property_type& property, directedS) const
2442   {
2443     
2444     std::pair<local_edge_descriptor, bool> inserted =
2445       detail::parallel::add_local_edge(source.local, target.local,
2446                                        self.build_edge_property(property), 
2447                                        self.base());
2448 
2449     if (inserted.second)
2450       
2451       put(edge_target_processor_id, self.base(), inserted.first, 
2452           target.owner);
2453 
2454     
2455     edge_descriptor e(source.owner, target.owner, true, inserted.first);
2456 
2457     
2458     if (inserted.second && self.on_add_edge)
2459       self.on_add_edge(e, self);
2460 
2461     return std::pair<edge_descriptor, bool>(e, inserted.second);
2462   }
2463 
2464   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2465   std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor, bool>
2466   PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::
2467   add_local_edge(const edge_property_type& property, bidirectionalS) const
2468   {
2469     
2470     std::pair<edge_descriptor, bool> result 
2471       = this->add_local_edge(property, directedS());
2472 
2473     if (result.second) {
2474       if (target.owner == self.processor()) {
2475         
2476         typedef detail::parallel::stored_in_edge<local_edge_descriptor>
2477           stored_edge;
2478 
2479         stored_edge e(self.processor(), result.first.local);
2480         boost::graph_detail::push(get(vertex_in_edges, 
2481                                       self.base())[target.local], e);
2482       } 
2483       else {
2484         
2485         
2486         if (self.process_group_.trigger_context() == boost::parallel::trc_out_of_band)
2487           send_oob(self.process_group_, target.owner, msg_nonlocal_edge,
2488                    msg_nonlocal_edge_data(result.first.local, property));
2489         else
2490           send(self.process_group_, target.owner, msg_nonlocal_edge,
2491                msg_nonlocal_edge_data(result.first.local, property));
2492       }
2493     }
2494 
2495     return result;
2496   }
2497 
2498   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2499   std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor, bool>
2500   PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::
2501   add_local_edge(const edge_property_type& property, undirectedS) const
2502   {
2503     
2504     std::pair<edge_descriptor, bool> result
2505       = this->add_local_edge(property, directedS());
2506 
2507     if (result.second) {
2508       if (target.owner == self.processor()) {
2509         
2510 
2511         
2512         
2513         
2514         local_edge_descriptor return_edge =
2515           detail::parallel::add_local_edge(target.local, source.local,
2516                                            self.build_edge_property(property),
2517                                            self.base()).first;
2518 
2519         put(edge_target_processor_id, self.base(), return_edge, 
2520             source.owner);
2521       }
2522       else {
2523         
2524         
2525         if (self.process_group_.trigger_context() == boost::parallel::trc_out_of_band)
2526           send_oob(self.process_group_, target.owner, msg_nonlocal_edge,
2527                    msg_nonlocal_edge_data(result.first.local, property));
2528         else
2529           send(self.process_group_, target.owner, msg_nonlocal_edge,
2530                msg_nonlocal_edge_data(result.first.local, property));
2531           
2532       }
2533 
2534       
2535       graph_detail::push(self.local_edges(), result.first);
2536     }
2537 
2538     return result;
2539   }
2540 
2541 
2542   
2543 
2544 
2545 
2546 
2547 
2548   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2549   struct PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge_with_property
2550     : lazy_add_edge
2551   {
2552     
2553     lazy_add_edge_with_property(adjacency_list& self, 
2554                                 vertex_descriptor source, 
2555                                 vertex_descriptor target,
2556                                 const edge_property_type& property)
2557       : lazy_add_edge(self, source, target), property(property) { }
2558 
2559     
2560     
2561     lazy_add_edge_with_property(const lazy_add_edge& other)
2562       : lazy_add_edge(other), property(other.property) { }
2563 
2564     
2565     
2566     ~lazy_add_edge_with_property();
2567 
2568     
2569     operator std::pair<edge_descriptor, bool>() const { return commit(); }
2570 
2571     
2572     
2573     std::pair<edge_descriptor, bool> commit() const;
2574 
2575   private:
2576     
2577     void operator=(lazy_add_edge_with_property&);
2578 
2579     edge_property_type property;
2580   };
2581 
2582   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2583   PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge_with_property::
2584   ~lazy_add_edge_with_property()
2585   {
2586     
2587     
2588     
2589     if (this->committed || boost::core::uncaught_exceptions() > 0)
2590       return;
2591 
2592     this->committed = true;
2593 
2594     if (this->source.owner == this->self.processor())
2595       
2596       this->add_local_edge(property, DirectedS());
2597     else
2598       
2599       
2600       send(this->self.process_group_, this->source.owner, 
2601            msg_add_edge_with_property,
2602            msg_add_edge_with_property_data(this->source, this->target, 
2603                                            property));
2604   }
2605 
2606   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2607   std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor, bool>
2608   PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge_with_property::
2609   commit() const
2610   {
2611     BOOST_ASSERT(!this->committed);
2612     this->committed = true;
2613 
2614     if (this->source.owner == this->self.processor())
2615       
2616       return this->add_local_edge(property, DirectedS());
2617     else {
2618       
2619       boost::parallel::detail::untracked_pair<edge_descriptor, bool> result;
2620       send_oob_with_reply(this->self.process_group_, this->source.owner, 
2621                           msg_add_edge_with_property_and_reply,
2622                           msg_add_edge_with_property_data(this->source, 
2623                                                           this->target, 
2624                                                           property),
2625                           result);
2626       return result;
2627     }
2628   }
2629 
2630 
2631   
2632 
2633 
2634 
2635 
2636 
2637 
2638   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2639   std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE
2640                        ::vertex_iterator,
2641             typename PBGL_DISTRIB_ADJLIST_TYPE
2642                        ::vertex_iterator>
2643   vertices(const PBGL_DISTRIB_ADJLIST_TYPE& g)
2644   {
2645     typedef typename PBGL_DISTRIB_ADJLIST_TYPE
2646       ::vertex_descriptor Vertex;
2647 
2648     typedef typename Vertex::generator generator;
2649 
2650     return std::make_pair(make_transform_iterator(vertices(g.base()).first,
2651                                                   generator(g.processor())),
2652                           make_transform_iterator(vertices(g.base()).second,
2653                                                   generator(g.processor())));
2654   }
2655 
2656   
2657 
2658 
2659 
2660 
2661 
2662 
2663   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2664   typename PBGL_DISTRIB_ADJLIST_TYPE
2665              ::vertices_size_type
2666   num_vertices(const PBGL_DISTRIB_ADJLIST_TYPE& g)
2667   {
2668     return num_vertices(g.base());
2669   }
2670 
2671   
2672 
2673 
2674   
2675 
2676 
2677   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename Edge>
2678   typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor
2679   source(const detail::parallel::edge_descriptor<Edge>& e,
2680          const PBGL_DISTRIB_ADJLIST_TYPE& g)
2681   {
2682     typedef typename PBGL_DISTRIB_ADJLIST_TYPE
2683       ::vertex_descriptor Vertex;
2684     return Vertex(e.source_processor, source(e.local, g.base()));
2685   }
2686 
2687   
2688 
2689 
2690   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename Edge>
2691   typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor
2692   target(const detail::parallel::edge_descriptor<Edge>& e,
2693          const PBGL_DISTRIB_ADJLIST_TYPE& g)
2694   {
2695     typedef typename PBGL_DISTRIB_ADJLIST_TYPE
2696       ::vertex_descriptor Vertex;
2697     return Vertex(e.target_processor, target(e.local, g.base()));
2698   }
2699 
2700   
2701 
2702 
2703 
2704 
2705   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2706   std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::out_edge_iterator,
2707             typename PBGL_DISTRIB_ADJLIST_TYPE::out_edge_iterator>
2708   out_edges(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
2709             const PBGL_DISTRIB_ADJLIST_TYPE& g)
2710   {
2711     BOOST_ASSERT(v.owner == g.processor());
2712 
2713     typedef PBGL_DISTRIB_ADJLIST_TYPE impl;
2714     typedef typename impl::out_edge_generator generator;
2715 
2716     return std::make_pair(
2717              make_transform_iterator(out_edges(v.local, g.base()).first,
2718                                      generator(g)),
2719              make_transform_iterator(out_edges(v.local, g.base()).second,
2720                                      generator(g)));
2721   }
2722 
2723   
2724 
2725 
2726 
2727 
2728   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2729   typename PBGL_DISTRIB_ADJLIST_TYPE::degree_size_type
2730   out_degree(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
2731              const PBGL_DISTRIB_ADJLIST_TYPE& g)
2732   {
2733     BOOST_ASSERT(v.owner == g.processor());
2734 
2735     return out_degree(v.local, g.base());
2736   }
2737 
2738   
2739 
2740 
2741   
2742 
2743 
2744 
2745 
2746   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
2747   std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
2748                        ::in_edge_iterator,
2749             typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
2750                        ::in_edge_iterator>
2751   in_edges(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
2752                          ::vertex_descriptor v,
2753            const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
2754   {
2755     BOOST_ASSERT(v.owner == g.processor());
2756 
2757     typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) impl;
2758     typedef typename impl::inherited base_graph_type;
2759     typedef typename impl::in_edge_generator generator;
2760 
2761 
2762     typename property_map<base_graph_type, vertex_in_edges_t>::const_type
2763       in_edges = get(vertex_in_edges, g.base());
2764 
2765     return std::make_pair(make_transform_iterator(in_edges[v.local].begin(),
2766                                                   generator(g)),
2767                           make_transform_iterator(in_edges[v.local].end(),
2768                                                   generator(g)));
2769   }
2770 
2771   
2772 
2773 
2774   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
2775   std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
2776                        ::in_edge_iterator,
2777             typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
2778                        ::in_edge_iterator>
2779   in_edges(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
2780                          ::vertex_descriptor v,
2781            const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
2782   {
2783     BOOST_ASSERT(v.owner == g.processor());
2784 
2785     typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) impl;
2786     typedef typename impl::in_edge_generator generator;
2787 
2788     return std::make_pair(
2789               make_transform_iterator(out_edges(v.local, g.base()).first,
2790                                      generator(g)),
2791              make_transform_iterator(out_edges(v.local, g.base()).second,
2792                                      generator(g)));
2793   }
2794 
2795   
2796 
2797 
2798 
2799 
2800   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
2801   typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)::degree_size_type
2802   in_degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
2803                            ::vertex_descriptor v,
2804             const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
2805   {
2806     BOOST_ASSERT(v.owner == g.processor());
2807 
2808     return get(vertex_in_edges, g.base())[v.local].size();
2809   }
2810 
2811   
2812 
2813 
2814   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
2815   typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::degree_size_type
2816   in_degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
2817                            ::vertex_descriptor v,
2818             const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
2819   {
2820     BOOST_ASSERT(v.owner == g.processor());
2821 
2822     return out_degree(v.local, g.base());
2823   }
2824 
2825   
2826 
2827 
2828 
2829 
2830   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
2831   typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
2832                        ::degree_size_type
2833   degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
2834                          ::vertex_descriptor v,
2835          const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
2836   {
2837     BOOST_ASSERT(v.owner == g.processor());
2838     return out_degree(v.local, g.base());
2839   }
2840 
2841   
2842 
2843 
2844   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
2845   typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
2846                        ::degree_size_type
2847   degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
2848                          ::vertex_descriptor v,
2849          const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
2850   {
2851     BOOST_ASSERT(v.owner == g.processor());
2852     return out_degree(v, g) + in_degree(v, g);
2853   }
2854 
2855   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2856   typename PBGL_DISTRIB_ADJLIST_TYPE::edges_size_type
2857   num_edges(const PBGL_DISTRIB_ADJLIST_TYPE& g)
2858   {
2859     return num_edges(g.base());
2860   }
2861 
2862   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
2863   typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::edges_size_type
2864   num_edges(const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
2865   {
2866     return g.local_edges().size();
2867   }
2868 
2869   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2870   std::pair<
2871     typename PBGL_DISTRIB_ADJLIST_TYPE::edge_iterator,
2872     typename PBGL_DISTRIB_ADJLIST_TYPE::edge_iterator>
2873   edges(const PBGL_DISTRIB_ADJLIST_TYPE& g)
2874   {
2875     typedef PBGL_DISTRIB_ADJLIST_TYPE impl;
2876     typedef typename impl::out_edge_generator generator;
2877 
2878     return std::make_pair(make_transform_iterator(edges(g.base()).first,
2879                                                   generator(g)),
2880                           make_transform_iterator(edges(g.base()).second,
2881                                                   generator(g)));
2882   }
2883 
2884   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
2885   std::pair<
2886     typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::edge_iterator,
2887     typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::edge_iterator>
2888   edges(const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
2889   {
2890     return std::make_pair(g.local_edges().begin(), g.local_edges().end());
2891   }
2892 
2893   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2894   inline
2895   typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor
2896   vertex(typename PBGL_DISTRIB_ADJLIST_TYPE::vertices_size_type n,
2897          const PBGL_DISTRIB_ADJLIST_TYPE& g)
2898   {
2899     typedef typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor 
2900       vertex_descriptor;
2901 
2902     return vertex_descriptor(g.distribution()(n), g.distribution().local(n));
2903   }
2904 
2905   
2906 
2907 
2908   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
2909   std::pair<
2910     typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::edge_descriptor,
2911     bool
2912   >
2913   edge(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::vertex_descriptor u,
2914        typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::vertex_descriptor v,
2915        const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g)
2916   {
2917     typedef typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)
2918                        ::edge_descriptor edge_descriptor;
2919 
2920     
2921     BOOST_ASSERT(u.owner == process_id(g.process_group()));
2922 
2923     typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)
2924         ::out_edge_iterator ei, ei_end;
2925     for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
2926       if (target(*ei, g) == v) return std::make_pair(*ei, true);
2927     }
2928     return std::make_pair(edge_descriptor(), false);
2929   }
2930 
2931   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2932   std::pair<
2933     typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor,
2934     bool
2935   >
2936   edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
2937        typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
2938        const PBGL_DISTRIB_ADJLIST_TYPE& g)
2939   {
2940     typedef typename PBGL_DISTRIB_ADJLIST_TYPE
2941                        ::edge_descriptor edge_descriptor;
2942 
2943     
2944     
2945     if (u.owner == process_id(g.process_group())) {
2946       typename PBGL_DISTRIB_ADJLIST_TYPE::out_edge_iterator ei, ei_end;
2947       for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
2948         if (target(*ei, g) == v) return std::make_pair(*ei, true);
2949       }
2950       return std::make_pair(edge_descriptor(), false);
2951     } else if (v.owner == process_id(g.process_group())) {
2952       typename PBGL_DISTRIB_ADJLIST_TYPE::in_edge_iterator ei, ei_end;
2953       for (boost::tie(ei, ei_end) = in_edges(v, g); ei != ei_end; ++ei) {
2954         if (source(*ei, g) == u) return std::make_pair(*ei, true);
2955       }
2956       return std::make_pair(edge_descriptor(), false);
2957     } else {
2958       BOOST_ASSERT(false);
2959       abort();
2960     }
2961   }
2962 
2963 #if 0
2964   
2965   std::pair<out_edge_iterator, out_edge_iterator>
2966   edge_range(vertex_descriptor u, vertex_descriptor v,
2967              const adjacency_list& g);
2968 #endif
2969 
2970   
2971 
2972 
2973   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2974   std::pair<typename PBGL_DISTRIB_ADJLIST_TYPE::adjacency_iterator,
2975             typename PBGL_DISTRIB_ADJLIST_TYPE::adjacency_iterator>
2976   adjacent_vertices(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
2977                     const PBGL_DISTRIB_ADJLIST_TYPE& g)
2978   {
2979     typedef typename PBGL_DISTRIB_ADJLIST_TYPE::adjacency_iterator iter;
2980     return std::make_pair(iter(out_edges(v, g).first, &g),
2981                           iter(out_edges(v, g).second, &g));
2982   }
2983 
2984   
2985 
2986 
2987 
2988   
2989 
2990 
2991   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
2992   typename PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge
2993   add_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
2994            typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
2995            PBGL_DISTRIB_ADJLIST_TYPE& g)
2996   {
2997     typedef typename PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge lazy_add_edge;
2998 
2999     return lazy_add_edge(g, u, v);
3000   }
3001 
3002   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3003   typename PBGL_DISTRIB_ADJLIST_TYPE
3004     ::lazy_add_edge_with_property
3005   add_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
3006            typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
3007            typename PBGL_DISTRIB_ADJLIST_TYPE::edge_property_type const& p,
3008            PBGL_DISTRIB_ADJLIST_TYPE& g)
3009   {
3010     typedef typename PBGL_DISTRIB_ADJLIST_TYPE
3011       ::lazy_add_edge_with_property lazy_add_edge_with_property;
3012     return lazy_add_edge_with_property(g, u, v, p);
3013   }
3014 
3015   
3016 
3017 
3018 
3019 
3020   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3021   void
3022   remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor e,
3023               PBGL_DISTRIB_ADJLIST_TYPE& g)
3024   {
3025     BOOST_ASSERT(source(e, g).owner == g.processor()
3026                  || target(e, g).owner == g.processor());
3027 
3028     if (target(e, g).owner == g.processor())
3029       detail::parallel::remove_in_edge(e, g, DirectedS());
3030     if (source(e, g).owner == g.processor())
3031       remove_edge(e.local, g.base());
3032 
3033     g.remove_local_edge_from_list(source(e, g), target(e, g), DirectedS());
3034 
3035     if (source(e, g).owner != g.processor()
3036         || (target(e, g).owner != g.processor()
3037             && !(is_same<DirectedS, directedS>::value))) {
3038       g.send_remove_edge_request(e);
3039     }
3040   }
3041 
3042   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3043   void
3044   remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
3045               typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v,
3046               PBGL_DISTRIB_ADJLIST_TYPE& g)
3047   {
3048     typedef typename PBGL_DISTRIB_ADJLIST_TYPE
3049                        ::edge_descriptor edge_descriptor;
3050     std::pair<edge_descriptor, bool> the_edge = edge(u, v, g);
3051     if (the_edge.second) remove_edge(the_edge.first, g);
3052   }
3053 
3054   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3055   inline void
3056   remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::out_edge_iterator ei,
3057               PBGL_DISTRIB_ADJLIST_TYPE& g)
3058   {
3059     remove_edge(*ei, g);
3060   }
3061 
3062   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
3063   inline void
3064   remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)
3065                 ::out_edge_iterator ei,
3066               PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g)
3067   {
3068     BOOST_ASSERT(source(*ei, g).owner == g.processor());
3069     remove_edge(ei->local, g.base());
3070   }
3071 
3072   
3073 
3074 
3075 
3076 
3077   namespace parallel { namespace detail {
3078     
3079 
3080 
3081 
3082 
3083 
3084 
3085     template<typename Graph, typename Predicate>
3086     struct remove_out_edge_predicate
3087     {
3088       typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
3089       typedef typename Graph::local_edge_descriptor         argument_type;
3090       typedef typename Graph::directed_selector             directed_selector;
3091       typedef bool result_type;
3092 
3093       remove_out_edge_predicate(Graph& g, Predicate& predicate)
3094         : g(g), predicate(predicate) { }
3095 
3096       bool operator()(const argument_type& le)
3097       {
3098         typedef typename edge_descriptor::template out_generator<Graph>
3099           generator;
3100 
3101         edge_descriptor e = generator(g)(le);
3102 
3103         if (predicate(e)) {
3104           if (source(e, g).owner != target(e, g).owner
3105               && !(is_same<directed_selector, directedS>::value))
3106             g.send_remove_edge_request(e);
3107           else
3108             ::boost::detail::parallel::remove_in_edge(e, g,
3109                                                       directed_selector());
3110 
3111            g.remove_local_edge_from_list(source(e, g), target(e, g),
3112                                          directed_selector());
3113           return true;
3114         } else return false;
3115       }
3116 
3117     private:
3118       Graph& g;
3119       Predicate predicate;
3120     };
3121   } } 
3122 
3123   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename Predicate>
3124   inline void
3125   remove_out_edge_if
3126      (typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
3127       Predicate predicate,
3128       PBGL_DISTRIB_ADJLIST_TYPE& g)
3129   {
3130     typedef PBGL_DISTRIB_ADJLIST_TYPE Graph;
3131     typedef parallel::detail::remove_out_edge_predicate<Graph, Predicate>
3132       Pred;
3133 
3134     BOOST_ASSERT(u.owner == g.processor());
3135     remove_out_edge_if(u.local, Pred(g, predicate), g.base());
3136   }
3137 
3138   
3139 
3140 
3141 
3142 
3143   namespace parallel { namespace detail {
3144     
3145 
3146 
3147 
3148 
3149 
3150 
3151     template<typename Graph, typename Predicate>
3152     struct remove_in_edge_predicate
3153     {
3154       typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
3155       typedef bool result_type;
3156 
3157       remove_in_edge_predicate(Graph& g, const Predicate& predicate)
3158         : g(g), predicate(predicate) { }
3159 
3160       template<typename StoredEdge>
3161       bool operator()(const StoredEdge& le)
3162       {
3163         typedef typename edge_descriptor::template in_generator<Graph>
3164           generator;
3165 
3166         edge_descriptor e = generator(g)(le);
3167 
3168         if (predicate(e)) {
3169           if (source(e, g).owner != target(e, g).owner)
3170             g.send_remove_edge_request(e);
3171           else
3172             remove_edge(source(e, g).local, target(e, g).local, g.base());
3173           return true;
3174         } else return false;
3175       }
3176 
3177     private:
3178       Graph& g;
3179       Predicate predicate;
3180     };
3181   } } 
3182 
3183   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG, typename Predicate>
3184   inline void
3185   remove_in_edge_if
3186      (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
3187                  ::vertex_descriptor u,
3188       Predicate predicate,
3189       PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
3190   {
3191     typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Graph;
3192     typedef parallel::detail::remove_in_edge_predicate<Graph, Predicate>
3193       Pred;
3194 
3195     BOOST_ASSERT(u.owner == g.processor());
3196     graph_detail::erase_if(get(vertex_in_edges, g.base())[u.local],
3197                            Pred(g, predicate));
3198   }
3199 
3200   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG, typename Predicate>
3201   inline void
3202   remove_in_edge_if
3203      (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
3204                  ::vertex_descriptor u,
3205       Predicate predicate,
3206       PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
3207   {
3208     remove_out_edge_if(u, predicate, g);
3209   }
3210 
3211   
3212 
3213 
3214 
3215 
3216   namespace parallel { namespace detail {
3217     
3218 
3219 
3220 
3221 
3222     template<typename Graph, typename Predicate>
3223     struct remove_directed_edge_predicate
3224     {
3225       typedef typename Graph::local_edge_descriptor argument_type;
3226       typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
3227       typedef bool result_type;
3228 
3229       remove_directed_edge_predicate(Graph& g, const Predicate& predicate)
3230         : g(g), predicate(predicate) { }
3231 
3232       bool operator()(const argument_type& le)
3233       {
3234         typedef typename edge_descriptor::template out_generator<Graph>
3235           generator;
3236 
3237         edge_descriptor e = generator(g)(le);
3238         return predicate(e);
3239       }
3240 
3241     private:
3242       Graph& g;
3243       Predicate predicate;
3244     };
3245   } } 
3246 
3247   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG, typename Predicate>
3248   inline void
3249   remove_edge_if(Predicate predicate, 
3250                  PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g)
3251   {
3252     typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS) Graph;
3253     typedef parallel::detail::remove_directed_edge_predicate<Graph,
3254                                                              Predicate> Pred;
3255     remove_edge_if(Pred(g, predicate), g.base());
3256   }
3257 
3258   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG, typename Predicate>
3259   inline void
3260   remove_edge_if(Predicate predicate,
3261                  PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
3262   {
3263     typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Graph;
3264     typedef parallel::detail::remove_out_edge_predicate<Graph,
3265                                                         Predicate> Pred;
3266     remove_edge_if(Pred(g, predicate), g.base());
3267   }
3268 
3269   namespace parallel { namespace detail {
3270     
3271 
3272 
3273 
3274 
3275 
3276 
3277     template<typename Graph, typename Predicate>
3278     struct remove_undirected_edge_predicate
3279     {
3280       typedef typename graph_traits<Graph>::edge_descriptor argument_type;
3281       typedef bool result_type;
3282 
3283       remove_undirected_edge_predicate(Graph& g, Predicate& predicate)
3284         : g(g), predicate(predicate) { }
3285 
3286       bool operator()(const argument_type& e)
3287       {
3288         if (predicate(e)) {
3289           if (source(e, g).owner != target(e, g).owner)
3290             g.send_remove_edge_request(e);
3291           if (target(e, g).owner == g.processor())
3292             ::boost::detail::parallel::remove_in_edge(e, g, undirectedS());
3293           if (source(e, g).owner == g.processor())
3294             remove_edge(e.local, g.base());
3295           return true;
3296         } else return false;
3297       }
3298 
3299     private:
3300       Graph& g;
3301       Predicate predicate;
3302     };
3303   } } 
3304 
3305   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG, typename Predicate>
3306   inline void
3307   remove_edge_if(Predicate predicate,
3308                  PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
3309   {
3310     typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) Graph;
3311     typedef parallel::detail::remove_undirected_edge_predicate<Graph,
3312                                                                Predicate> Pred;
3313     graph_detail::erase_if(g.local_edges(), Pred(g, predicate));
3314   }
3315 
3316   
3317 
3318 
3319 
3320 
3321   namespace parallel { namespace detail {
3322     struct always_true
3323     {
3324       typedef bool result_type;
3325 
3326       template<typename T> bool operator()(const T&) const { return true; }
3327     };
3328   } } 
3329 
3330   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
3331   void
3332   clear_vertex
3333     (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
3334           ::vertex_descriptor u,
3335       PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
3336   {
3337     clear_out_edges(u, g);
3338     clear_in_edges(u, g);
3339   }
3340 
3341   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
3342   void
3343   clear_vertex
3344     (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)
3345                 ::vertex_descriptor u,
3346       PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g)
3347   {
3348     remove_out_edge_if(u, parallel::detail::always_true(), g);
3349   }
3350 
3351   
3352 
3353 
3354 
3355 
3356   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
3357   void
3358   clear_out_edges
3359     (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::vertex_descriptor u,
3360       PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g)
3361   {
3362     BOOST_ASSERT(u.owner == g.processor());
3363     clear_out_edges(u.local, g.base());
3364   }
3365 
3366   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
3367   void
3368   clear_out_edges
3369     (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
3370                 ::vertex_descriptor u,
3371       PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
3372   {
3373     remove_out_edge_if(u, parallel::detail::always_true(), g);
3374   }
3375 
3376   
3377 
3378 
3379 
3380 
3381   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG>
3382   void
3383   clear_in_edges
3384     (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)
3385                 ::vertex_descriptor u,
3386       PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g)
3387   {
3388     remove_in_edge_if(u, parallel::detail::always_true(), g);
3389   }
3390 
3391   
3392 
3393 
3394 
3395 
3396   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3397   typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor
3398   add_vertex(PBGL_DISTRIB_ADJLIST_TYPE& g)
3399   {
3400     typedef PBGL_DISTRIB_ADJLIST_TYPE graph_type;
3401     typename graph_type::vertex_property_type p;
3402     return add_vertex(p, g);
3403   }
3404 
3405   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3406   typename PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property
3407   add_vertex(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_property_type const& p,
3408              PBGL_DISTRIB_ADJLIST_TYPE& g)
3409   {
3410     typedef typename PBGL_DISTRIB_ADJLIST_TYPE
3411                        ::lazy_add_vertex_with_property lazy_add_vertex;
3412     return lazy_add_vertex(g, p);
3413   }
3414 
3415   
3416 
3417 
3418 
3419 
3420   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3421   void
3422   remove_vertex(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u,
3423                 PBGL_DISTRIB_ADJLIST_TYPE& g)
3424   {
3425     typedef typename PBGL_DISTRIB_ADJLIST_TYPE::graph_type graph_type;
3426     typedef typename graph_type::named_graph_mixin named_graph_mixin;
3427     BOOST_ASSERT(u.owner == g.processor());
3428     static_cast<named_graph_mixin&>(static_cast<graph_type&>(g))
3429       .removing_vertex(u, boost::graph_detail::iterator_stability(g.base().m_vertices));
3430     g.distribution().clear();
3431     remove_vertex(u.local, g.base());
3432   }
3433 
3434   
3435 
3436 
3437   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename Property>
3438   struct property_map<PBGL_DISTRIB_ADJLIST_TYPE, Property>
3439   : detail::parallel::get_adj_list_pmap<Property>
3440       ::template apply<PBGL_DISTRIB_ADJLIST_TYPE>
3441   { };
3442 
3443   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename Property>
3444   struct property_map<PBGL_DISTRIB_ADJLIST_TYPE const, Property>
3445           : boost::detail::parallel::get_adj_list_pmap<Property>
3446 
3447       ::template apply<PBGL_DISTRIB_ADJLIST_TYPE const>
3448   { };
3449 
3450   template<typename Property, PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3451   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, Property>::type
3452   get(Property p, PBGL_DISTRIB_ADJLIST_TYPE& g)
3453   {
3454     typedef PBGL_DISTRIB_ADJLIST_TYPE Graph;
3455     typedef typename property_map<Graph, Property>::type result_type;
3456     typedef typename property_traits<result_type>::value_type value_type;
3457     typedef typename property_reduce<Property>::template apply<value_type>
3458       reduce;
3459 
3460     typedef typename property_traits<result_type>::key_type descriptor;
3461     typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
3462     typedef typename mpl::if_<is_same<descriptor, vertex_descriptor>,
3463                               vertex_global_t, edge_global_t>::type
3464       global_map_t;
3465 
3466     return result_type(g.process_group(), get(global_map_t(), g),
3467                        get(p, g.base()), reduce());
3468   }
3469 
3470   template<typename Property, PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3471   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, Property>::const_type
3472   get(Property p, const PBGL_DISTRIB_ADJLIST_TYPE& g)
3473   {
3474     typedef PBGL_DISTRIB_ADJLIST_TYPE Graph;
3475     typedef typename property_map<Graph, Property>::const_type result_type;
3476     typedef typename property_traits<result_type>::value_type value_type;
3477     typedef typename property_reduce<Property>::template apply<value_type>
3478       reduce;
3479 
3480     typedef typename property_traits<result_type>::key_type descriptor;
3481     typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
3482     typedef typename mpl::if_<is_same<descriptor, vertex_descriptor>,
3483                               vertex_global_t, edge_global_t>::type
3484       global_map_t;
3485 
3486     return result_type(g.process_group(), get(global_map_t(), g),
3487                        get(p, g.base()), reduce());
3488   }
3489 
3490   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3491   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_local_index_t>::type
3492   get(vertex_local_index_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
3493   {
3494     return get(vertex_local_index, g.base());
3495   }
3496 
3497   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3498   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE,
3499                         vertex_local_index_t>::const_type
3500   get(vertex_local_index_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
3501   {
3502     return get(vertex_local_index, g.base());
3503   }
3504 
3505   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3506   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_global_t>::const_type
3507   get(vertex_global_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
3508   {
3509     typedef typename property_map<
3510                        PBGL_DISTRIB_ADJLIST_TYPE,
3511                        vertex_global_t>::const_type result_type;
3512     return result_type();
3513   }
3514 
3515   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3516   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_global_t>::const_type
3517   get(vertex_global_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
3518   {
3519     typedef typename property_map<
3520                        PBGL_DISTRIB_ADJLIST_TYPE,
3521                        vertex_global_t>::const_type result_type;
3522     return result_type();
3523   }
3524 
3525   
3526   
3527   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3528   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_owner_t>::type
3529   get(vertex_owner_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
3530   {
3531     typedef typename property_map<
3532                        PBGL_DISTRIB_ADJLIST_TYPE,
3533                        vertex_owner_t>::type result_type;
3534     return result_type();
3535   }
3536 
3537   
3538   
3539   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3540   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_owner_t>::const_type
3541   get(vertex_owner_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
3542   {
3543     typedef typename property_map<
3544                        PBGL_DISTRIB_ADJLIST_TYPE,
3545                        vertex_owner_t>::const_type result_type;
3546     return result_type();
3547   }
3548 
3549   
3550   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3551   inline processor_id_type
3552   get(vertex_owner_t, PBGL_DISTRIB_ADJLIST_TYPE&,
3553       typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v)
3554   {
3555     return v.owner;
3556   }
3557 
3558   
3559   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3560   inline processor_id_type
3561   get(vertex_owner_t, const PBGL_DISTRIB_ADJLIST_TYPE&,
3562       typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v)
3563   {
3564     return v.owner;
3565   }
3566 
3567   
3568   
3569   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3570   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_local_t>::type
3571   get(vertex_local_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
3572   {
3573     typedef typename property_map<
3574                        PBGL_DISTRIB_ADJLIST_TYPE,
3575                        vertex_local_t>::type result_type;
3576     return result_type();
3577   }
3578 
3579   
3580   
3581   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3582   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_local_t>::const_type
3583   get(vertex_local_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
3584   {
3585     typedef typename property_map<
3586                        PBGL_DISTRIB_ADJLIST_TYPE,
3587                        vertex_local_t>::const_type result_type;
3588     return result_type();
3589   }
3590 
3591   
3592   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3593   inline typename PBGL_DISTRIB_ADJLIST_TYPE::local_vertex_descriptor
3594   get(vertex_local_t, PBGL_DISTRIB_ADJLIST_TYPE&,
3595       typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v)
3596   {
3597     return v.local;
3598   }
3599 
3600   
3601   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3602   inline typename PBGL_DISTRIB_ADJLIST_TYPE::local_vertex_descriptor
3603   get(vertex_local_t, const PBGL_DISTRIB_ADJLIST_TYPE&,
3604       typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v)
3605   {
3606     return v.local;
3607   }
3608 
3609 
3610   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3611   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_global_t>::const_type
3612   get(edge_global_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
3613   {
3614     typedef typename property_map<
3615                        PBGL_DISTRIB_ADJLIST_TYPE,
3616                        edge_global_t>::const_type result_type;
3617     return result_type();
3618   }
3619 
3620   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3621   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_global_t>::const_type
3622   get(edge_global_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
3623   {
3624     typedef typename property_map<
3625                        PBGL_DISTRIB_ADJLIST_TYPE,
3626                        edge_global_t>::const_type result_type;
3627     return result_type();
3628   }
3629 
3630   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3631   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_owner_t>::type
3632   get(edge_owner_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
3633   {
3634     typedef typename property_map<
3635                        PBGL_DISTRIB_ADJLIST_TYPE,
3636                        edge_owner_t>::type result_type;
3637     return result_type();
3638   }
3639 
3640   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3641   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_owner_t>::const_type
3642   get(edge_owner_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
3643   {
3644     typedef typename property_map<
3645                        PBGL_DISTRIB_ADJLIST_TYPE,
3646                        edge_owner_t>::const_type result_type;
3647     return result_type();
3648   }
3649 
3650   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3651   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_local_t>::type
3652   get(edge_local_t, PBGL_DISTRIB_ADJLIST_TYPE& g)
3653   {
3654     typedef typename property_map<
3655                        PBGL_DISTRIB_ADJLIST_TYPE,
3656                        edge_local_t>::type result_type;
3657     return result_type();
3658   }
3659 
3660   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3661   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, edge_local_t>::const_type
3662   get(edge_local_t, const PBGL_DISTRIB_ADJLIST_TYPE& g)
3663   {
3664     typedef typename property_map<
3665                        PBGL_DISTRIB_ADJLIST_TYPE,
3666                        edge_local_t>::const_type result_type;
3667     return result_type();
3668   }
3669 
3670   template<typename Property, PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS,
3671            typename Key>
3672   inline
3673   typename property_traits<typename property_map<
3674                 PBGL_DISTRIB_ADJLIST_TYPE, Property>::const_type
3675            >::value_type
3676   get(Property p, const PBGL_DISTRIB_ADJLIST_TYPE& g, const Key& key)
3677   {
3678     if (owner(key) == process_id(g.process_group()))
3679       return get(p, g.base(), local(key));
3680     else
3681       BOOST_ASSERT(false);
3682   }
3683 
3684   template<typename Property, PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS,
3685            typename Key, typename Value>
3686   void
3687   put(Property p, PBGL_DISTRIB_ADJLIST_TYPE& g, const Key& key, const Value& v)
3688   {
3689     if (owner(key) == process_id(g.process_group()))
3690       put(p, g.base(), local(key), v);
3691     else
3692       BOOST_ASSERT(false);
3693   }
3694 
3695   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3696   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_index_t>::type
3697   get(vertex_index_t vi, PBGL_DISTRIB_ADJLIST_TYPE& g)
3698   {
3699     typedef PBGL_DISTRIB_ADJLIST_TYPE graph_type;
3700     typedef typename property_map<graph_type, vertex_index_t>::type
3701       result_type;
3702     return result_type(g.process_group(), get(vertex_global, g),
3703                        get(vi, g.base()));
3704   }
3705 
3706   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3707   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, vertex_index_t>::const_type
3708   get(vertex_index_t vi, const PBGL_DISTRIB_ADJLIST_TYPE& g)
3709   {
3710     typedef PBGL_DISTRIB_ADJLIST_TYPE graph_type;
3711     typedef typename property_map<graph_type, vertex_index_t>::const_type
3712       result_type;
3713     return result_type(g.process_group(), get(vertex_global, g),
3714                        get(vi, g.base()));
3715   }
3716 
3717   
3718 
3719 
3720   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename T, typename Bundle>
3721   struct property_map<PBGL_DISTRIB_ADJLIST_TYPE, T Bundle::*>
3722     : detail::parallel::get_adj_list_pmap<T Bundle::*>
3723       ::template apply<PBGL_DISTRIB_ADJLIST_TYPE>
3724   { };
3725 
3726   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename T, typename Bundle>
3727   struct property_map<PBGL_DISTRIB_ADJLIST_TYPE const, T Bundle::*>
3728     : detail::parallel::get_adj_list_pmap<T Bundle::*>
3729       ::template apply<PBGL_DISTRIB_ADJLIST_TYPE const>
3730   { };
3731 
3732   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename T, typename Bundle>
3733   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, T Bundle::*>::type
3734   get(T Bundle::* p, PBGL_DISTRIB_ADJLIST_TYPE& g)
3735   {
3736     typedef PBGL_DISTRIB_ADJLIST_TYPE Graph;
3737     typedef typename property_map<Graph, T Bundle::*>::type result_type;
3738     typedef typename property_traits<result_type>::value_type value_type;
3739     typedef typename property_reduce<T Bundle::*>::template apply<value_type>
3740       reduce;
3741 
3742     typedef typename property_traits<result_type>::key_type descriptor;
3743     typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
3744     typedef typename mpl::if_<is_same<descriptor, vertex_descriptor>,
3745                               vertex_global_t, edge_global_t>::type
3746       global_map_t;
3747 
3748     return result_type(g.process_group(), get(global_map_t(), g),
3749                        get(p, g.base()), reduce());
3750   }
3751 
3752   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS, typename T, typename Bundle>
3753   typename property_map<PBGL_DISTRIB_ADJLIST_TYPE, T Bundle::*>::const_type
3754   get(T Bundle::* p, const PBGL_DISTRIB_ADJLIST_TYPE& g)
3755   {
3756     typedef PBGL_DISTRIB_ADJLIST_TYPE Graph;
3757     typedef typename property_map<Graph, T Bundle::*>::const_type result_type;
3758     typedef typename property_traits<result_type>::value_type value_type;
3759     typedef typename property_reduce<T Bundle::*>::template apply<value_type>
3760       reduce;
3761 
3762     typedef typename property_traits<result_type>::key_type descriptor;
3763     typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
3764     typedef typename mpl::if_<is_same<descriptor, vertex_descriptor>,
3765                               vertex_global_t, edge_global_t>::type
3766       global_map_t;
3767 
3768     return result_type(g.process_group(), get(global_map_t(), g),
3769                        get(p, g.base()), reduce());
3770   }
3771 
3772   
3773 
3774 
3775   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3776   void synchronize(const PBGL_DISTRIB_ADJLIST_TYPE& g)
3777   {
3778     synchronize(g.process_group());
3779   }
3780 
3781   template<PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS>
3782   ProcessGroup
3783   process_group(const PBGL_DISTRIB_ADJLIST_TYPE& g)
3784   { return g.process_group(); }
3785 
3786   
3787 
3788 
3789   namespace mpi {
3790     template<typename Directed, typename Vertex>
3791     struct is_mpi_datatype<boost::detail::edge_base<Directed, Vertex> >
3792       : is_mpi_datatype<Vertex> { };
3793 
3794     template<typename Directed, typename Vertex>
3795     struct is_mpi_datatype<boost::detail::edge_desc_impl<Directed, Vertex> >
3796       : is_mpi_datatype<boost::detail::edge_base<Directed, Vertex> > { };
3797 
3798     template<typename LocalDescriptor>
3799     struct is_mpi_datatype<boost::detail::parallel::global_descriptor<LocalDescriptor> >
3800       : is_mpi_datatype<LocalDescriptor> { };
3801 
3802     template<typename Edge>
3803     struct is_mpi_datatype<boost::detail::parallel::edge_descriptor<Edge> >
3804       : is_mpi_datatype<Edge> { };
3805 
3806     template<typename Vertex, typename LocalVertex>
3807     struct is_mpi_datatype<boost::detail::parallel::
3808                              msg_add_edge_data<Vertex, LocalVertex> >
3809       : is_mpi_datatype<Vertex> { };
3810 
3811     template<typename Vertex, typename LocalVertex, typename EdgeProperty>
3812     struct is_mpi_datatype<boost::detail::parallel::
3813                              msg_add_edge_with_property_data<Vertex, 
3814                                                              LocalVertex,
3815                                                              EdgeProperty> >
3816       : mpl::and_<is_mpi_datatype<Vertex>, is_mpi_datatype<EdgeProperty> > { };
3817 
3818 
3819    template<typename EdgeProperty, typename EdgeDescriptor>
3820    struct is_mpi_datatype<boost::detail::parallel::msg_nonlocal_edge_data<
3821                           EdgeProperty,EdgeDescriptor> >
3822            : mpl::and_<
3823                is_mpi_datatype<boost::detail::parallel::maybe_store_property<
3824                            EdgeProperty> >,
3825            is_mpi_datatype<EdgeDescriptor> >
3826   {};
3827    
3828    template<typename EdgeDescriptor>
3829    struct is_mpi_datatype<
3830             boost::detail::parallel::msg_remove_edge_data<EdgeDescriptor> >
3831            : is_mpi_datatype<EdgeDescriptor> {};
3832   }
3833 
3834   
3835 
3836 
3837   namespace serialization {
3838     template<typename Directed, typename Vertex>
3839     struct is_bitwise_serializable<boost::detail::edge_base<Directed, Vertex> >
3840       : is_bitwise_serializable<Vertex> { };
3841 
3842     template<typename Directed, typename Vertex>
3843     struct is_bitwise_serializable<boost::detail::edge_desc_impl<Directed, Vertex> >
3844       : is_bitwise_serializable<boost::detail::edge_base<Directed, Vertex> > { };
3845 
3846     template<typename LocalDescriptor>
3847     struct is_bitwise_serializable<boost::detail::parallel::global_descriptor<LocalDescriptor> >
3848       : is_bitwise_serializable<LocalDescriptor> { };
3849 
3850     template<typename Edge>
3851     struct is_bitwise_serializable<boost::detail::parallel::edge_descriptor<Edge> >
3852       : is_bitwise_serializable<Edge> { };
3853 
3854     template<typename Vertex, typename LocalVertex>
3855     struct is_bitwise_serializable<boost::detail::parallel::
3856                              msg_add_edge_data<Vertex, LocalVertex> >
3857       : is_bitwise_serializable<Vertex> { };
3858 
3859     template<typename Vertex, typename LocalVertex, typename EdgeProperty>
3860     struct is_bitwise_serializable<boost::detail::parallel::
3861                              msg_add_edge_with_property_data<Vertex, 
3862                                                              LocalVertex,
3863                                                              EdgeProperty> >
3864       : mpl::and_<is_bitwise_serializable<Vertex>, 
3865                   is_bitwise_serializable<EdgeProperty> > { };
3866 
3867    template<typename EdgeProperty, typename EdgeDescriptor>
3868    struct is_bitwise_serializable<boost::detail::parallel::msg_nonlocal_edge_data<
3869                                   EdgeProperty,EdgeDescriptor> >
3870            : mpl::and_<
3871                is_bitwise_serializable<
3872                 boost::detail::parallel::maybe_store_property<EdgeProperty> >,
3873            is_bitwise_serializable<EdgeDescriptor> >
3874   {};
3875    
3876    template<typename EdgeDescriptor>
3877    struct is_bitwise_serializable<
3878             boost::detail::parallel::msg_remove_edge_data<EdgeDescriptor> >
3879            : is_bitwise_serializable<EdgeDescriptor> {};
3880    
3881     template<typename Directed, typename Vertex>
3882     struct implementation_level<boost::detail::edge_base<Directed, Vertex> >
3883       : mpl::int_<object_serializable> {};
3884 
3885     template<typename Directed, typename Vertex>
3886     struct implementation_level<boost::detail::edge_desc_impl<Directed, Vertex> >
3887       : mpl::int_<object_serializable> {};
3888 
3889     template<typename LocalDescriptor>
3890     struct implementation_level<boost::detail::parallel::global_descriptor<LocalDescriptor> >
3891       : mpl::int_<object_serializable> {};
3892 
3893     template<typename Edge>
3894     struct implementation_level<boost::detail::parallel::edge_descriptor<Edge> >
3895       : mpl::int_<object_serializable> {};
3896 
3897     template<typename Vertex, typename LocalVertex>
3898     struct implementation_level<boost::detail::parallel::
3899                              msg_add_edge_data<Vertex, LocalVertex> >
3900       : mpl::int_<object_serializable> {};
3901 
3902     template<typename Vertex, typename LocalVertex, typename EdgeProperty>
3903     struct implementation_level<boost::detail::parallel::
3904                              msg_add_edge_with_property_data<Vertex, 
3905                                                              LocalVertex,
3906                                                              EdgeProperty> >
3907       : mpl::int_<object_serializable> {};
3908 
3909    template<typename EdgeProperty, typename EdgeDescriptor>
3910    struct implementation_level<boost::detail::parallel::msg_nonlocal_edge_data<
3911                                EdgeProperty,EdgeDescriptor> >
3912            : mpl::int_<object_serializable> {};
3913    
3914    template<typename EdgeDescriptor>
3915    struct implementation_level<
3916             boost::detail::parallel::msg_remove_edge_data<EdgeDescriptor> >
3917           : mpl::int_<object_serializable> {};
3918    
3919     template<typename Directed, typename Vertex>
3920     struct tracking_level<boost::detail::edge_base<Directed, Vertex> >
3921       : mpl::int_<track_never> {};
3922 
3923     template<typename Directed, typename Vertex>
3924     struct tracking_level<boost::detail::edge_desc_impl<Directed, Vertex> >
3925       : mpl::int_<track_never> {};
3926 
3927     template<typename LocalDescriptor>
3928     struct tracking_level<boost::detail::parallel::global_descriptor<LocalDescriptor> >
3929       : mpl::int_<track_never> {};
3930 
3931     template<typename Edge>
3932     struct tracking_level<boost::detail::parallel::edge_descriptor<Edge> >
3933       : mpl::int_<track_never> {};
3934 
3935     template<typename Vertex, typename LocalVertex>
3936     struct tracking_level<boost::detail::parallel::
3937                              msg_add_edge_data<Vertex, LocalVertex> >
3938       : mpl::int_<track_never> {};
3939 
3940     template<typename Vertex, typename LocalVertex, typename EdgeProperty>
3941     struct tracking_level<boost::detail::parallel::
3942                              msg_add_edge_with_property_data<Vertex, 
3943                                                              LocalVertex,
3944                                                              EdgeProperty> >
3945       : mpl::int_<track_never> {};
3946 
3947    template<typename EdgeProperty, typename EdgeDescriptor>
3948    struct tracking_level<boost::detail::parallel::msg_nonlocal_edge_data<
3949                          EdgeProperty,EdgeDescriptor> >
3950            : mpl::int_<track_never> {};
3951    
3952    template<typename EdgeDescriptor>
3953    struct tracking_level<
3954             boost::detail::parallel::msg_remove_edge_data<EdgeDescriptor> >
3955           : mpl::int_<track_never> {};
3956   }
3957 
3958   
3959   template<typename LocalDescriptor>
3960   struct hash<detail::parallel::global_descriptor<LocalDescriptor> >
3961   {
3962     typedef detail::parallel::global_descriptor<LocalDescriptor> argument_type;
3963     std::size_t operator()(argument_type const& x) const
3964     {
3965       std::size_t hash = hash_value(x.owner);
3966       hash_combine(hash, x.local);
3967       return hash;
3968     }
3969   };
3970 
3971   
3972   template<typename Edge>
3973   struct hash<detail::parallel::edge_descriptor<Edge> >
3974   {
3975     typedef detail::parallel::edge_descriptor<Edge> argument_type;
3976 
3977     std::size_t operator()(argument_type const& x) const
3978     {
3979       std::size_t hash = hash_value(x.owner());
3980       hash_combine(hash, x.local);
3981       return hash;
3982     }
3983   };
3984 
3985 } 
3986 
3987 #include <boost/graph/distributed/adjlist/handlers.hpp>
3988 #include <boost/graph/distributed/adjlist/initialize.hpp>
3989 #include <boost/graph/distributed/adjlist/redistribute.hpp>
3990 #include <boost/graph/distributed/adjlist/serialization.hpp>
3991 
3992 #endif