Chris@16: // Copyright (C) 2004-2006 The Trustees of Indiana University. Chris@16: // Copyright (C) 2007 Douglas Gregor Chris@16: Chris@16: // Use, modification and distribution is subject to the Boost Software Chris@16: // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // Authors: Douglas Gregor Chris@16: // Andrew Lumsdaine Chris@16: Chris@16: #ifndef BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP Chris@16: #define BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP Chris@16: Chris@16: #ifndef BOOST_GRAPH_USE_MPI Chris@16: #error "Parallel BGL files should not be included unless has been included" Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: // Callbacks Chris@16: #include Chris@16: Chris@16: // Serialization Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: // Named vertices Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: /// The type used to store an identifier that uniquely names a processor. Chris@16: // NGE: I doubt we'll be running on more than 32768 procs for the time being Chris@16: typedef /*int*/ short processor_id_type; Chris@16: Chris@16: // Tell which processor the target of an edge resides on (for Chris@16: // directed graphs) or which processor the other end point of the Chris@16: // edge resides on (for undirected graphs). Chris@16: enum edge_target_processor_id_t { edge_target_processor_id }; Chris@16: BOOST_INSTALL_PROPERTY(edge, target_processor_id); Chris@16: Chris@16: // For undirected graphs, tells whether the edge is locally owned. Chris@16: enum edge_locally_owned_t { edge_locally_owned }; Chris@16: BOOST_INSTALL_PROPERTY(edge, locally_owned); Chris@16: Chris@16: // For bidirectional graphs, stores the incoming edges. Chris@16: enum vertex_in_edges_t { vertex_in_edges }; Chris@16: BOOST_INSTALL_PROPERTY(vertex, in_edges); Chris@16: Chris@16: /// Tag class for directed, distributed adjacency list Chris@16: struct directed_distributed_adj_list_tag Chris@16: : public virtual distributed_graph_tag, Chris@16: public virtual distributed_vertex_list_graph_tag, Chris@16: public virtual distributed_edge_list_graph_tag, Chris@16: public virtual incidence_graph_tag, Chris@16: public virtual adjacency_graph_tag {}; Chris@16: Chris@16: /// Tag class for bidirectional, distributed adjacency list Chris@16: struct bidirectional_distributed_adj_list_tag Chris@16: : public virtual distributed_graph_tag, Chris@16: public virtual distributed_vertex_list_graph_tag, Chris@16: public virtual distributed_edge_list_graph_tag, Chris@16: public virtual incidence_graph_tag, Chris@16: public virtual adjacency_graph_tag, Chris@16: public virtual bidirectional_graph_tag {}; Chris@16: Chris@16: /// Tag class for undirected, distributed adjacency list Chris@16: struct undirected_distributed_adj_list_tag Chris@16: : public virtual distributed_graph_tag, Chris@16: public virtual distributed_vertex_list_graph_tag, Chris@16: public virtual distributed_edge_list_graph_tag, Chris@16: public virtual incidence_graph_tag, Chris@16: public virtual adjacency_graph_tag, Chris@16: public virtual bidirectional_graph_tag {}; Chris@16: Chris@16: namespace detail { Chris@16: template Chris@16: void Chris@16: serialize(Archiver& ar, edge_base& e, Chris@16: const unsigned int /*version*/) Chris@16: { Chris@16: ar & unsafe_serialize(e.m_source) Chris@16: & unsafe_serialize(e.m_target); Chris@16: } Chris@16: Chris@16: template Chris@16: void Chris@16: serialize(Archiver& ar, edge_desc_impl& e, Chris@16: const unsigned int /*version*/) Chris@16: { Chris@16: ar & boost::serialization::base_object >(e) Chris@16: & unsafe_serialize(e.m_eproperty); Chris@16: } Chris@16: } Chris@16: Chris@16: namespace detail { namespace parallel { Chris@16: Chris@16: /** Chris@16: * A distributed vertex descriptor. These descriptors contain both Chris@16: * the ID of the processor that owns the vertex and a local vertex Chris@16: * descriptor that identifies the particular vertex for that Chris@16: * processor. Chris@16: */ Chris@16: template Chris@16: struct global_descriptor Chris@16: { Chris@16: typedef LocalDescriptor local_descriptor_type; Chris@16: Chris@16: global_descriptor() : owner(), local() { } Chris@16: Chris@16: global_descriptor(processor_id_type owner, LocalDescriptor local) Chris@16: : owner(owner), local(local) { } Chris@16: Chris@16: processor_id_type owner; Chris@16: LocalDescriptor local; Chris@16: Chris@16: /** Chris@16: * A function object that, given a processor ID, generates Chris@16: * distributed vertex descriptors from local vertex Chris@16: * descriptors. This function object is used by the Chris@16: * vertex_iterator of the distributed adjacency list. Chris@16: */ Chris@16: struct generator Chris@16: { Chris@16: typedef global_descriptor result_type; Chris@16: typedef LocalDescriptor argument_type; Chris@16: Chris@16: generator() {} Chris@16: generator(processor_id_type owner) : owner(owner) {} Chris@16: Chris@16: result_type operator()(argument_type v) const Chris@16: { return result_type(owner, v); } Chris@16: Chris@16: private: Chris@16: processor_id_type owner; Chris@16: }; Chris@16: Chris@16: template Chris@16: void serialize(Archiver& ar, const unsigned int /*version*/) Chris@16: { Chris@16: ar & owner & unsafe_serialize(local); Chris@16: } Chris@16: }; Chris@16: Chris@16: /// Determine the process that owns the given descriptor Chris@16: template Chris@16: inline processor_id_type owner(const global_descriptor& v) Chris@16: { return v.owner; } Chris@16: Chris@16: /// Determine the local portion of the given descriptor Chris@16: template Chris@16: inline LocalDescriptor local(const global_descriptor& v) Chris@16: { return v.local; } Chris@16: Chris@16: /// Compare distributed vertex descriptors for equality Chris@16: template Chris@16: inline bool Chris@16: operator==(const global_descriptor& u, Chris@16: const global_descriptor& v) Chris@16: { Chris@16: return u.owner == v.owner && u.local == v.local; Chris@16: } Chris@16: Chris@16: /// Compare distributed vertex descriptors for inequality Chris@16: template Chris@16: inline bool Chris@16: operator!=(const global_descriptor& u, Chris@16: const global_descriptor& v) Chris@16: { return !(u == v); } Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator<(const global_descriptor& u, Chris@16: const global_descriptor& v) Chris@16: { Chris@16: return (u.owner) < v.owner || (u.owner == v.owner && (u.local) < v.local); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator<=(const global_descriptor& u, Chris@16: const global_descriptor& v) Chris@16: { Chris@16: return u.owner <= v.owner || (u.owner == v.owner && u.local <= v.local); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator>(const global_descriptor& u, Chris@16: const global_descriptor& v) Chris@16: { Chris@16: return v < u; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator>=(const global_descriptor& u, Chris@16: const global_descriptor& v) Chris@16: { Chris@16: return v <= u; Chris@16: } Chris@16: Chris@16: // DPG TBD: Add <, <=, >=, > for global descriptors Chris@16: Chris@16: /** Chris@16: * A Readable Property Map that extracts a global descriptor pair Chris@16: * from a global_descriptor. Chris@16: */ Chris@16: template Chris@16: struct global_descriptor_property_map Chris@16: { Chris@16: typedef std::pair value_type; Chris@16: typedef value_type reference; Chris@16: typedef global_descriptor key_type; Chris@16: typedef readable_property_map_tag category; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline std::pair Chris@16: get(global_descriptor_property_map, Chris@16: global_descriptor x) Chris@16: { Chris@16: return std::pair(x.owner, x.local); Chris@16: } Chris@16: Chris@16: /** Chris@16: * A Readable Property Map that extracts the owner of a global Chris@16: * descriptor. Chris@16: */ Chris@16: template Chris@16: struct owner_property_map Chris@16: { Chris@16: typedef processor_id_type value_type; Chris@16: typedef value_type reference; Chris@16: typedef global_descriptor key_type; Chris@16: typedef readable_property_map_tag category; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline processor_id_type Chris@16: get(owner_property_map, Chris@16: global_descriptor x) Chris@16: { Chris@16: return x.owner; Chris@16: } Chris@16: Chris@16: /** Chris@16: * A Readable Property Map that extracts the local descriptor from Chris@16: * a global descriptor. Chris@16: */ Chris@16: template Chris@16: struct local_descriptor_property_map Chris@16: { Chris@16: typedef LocalDescriptor value_type; Chris@16: typedef value_type reference; Chris@16: typedef global_descriptor key_type; Chris@16: typedef readable_property_map_tag category; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline LocalDescriptor Chris@16: get(local_descriptor_property_map, Chris@16: global_descriptor x) Chris@16: { Chris@16: return x.local; Chris@16: } Chris@16: Chris@16: /** Chris@16: * Stores an incoming edge for a bidirectional distributed Chris@16: * adjacency list. The user does not see this type directly, Chris@16: * because it is just an implementation detail. Chris@16: */ Chris@16: template Chris@16: struct stored_in_edge Chris@16: { Chris@16: stored_in_edge(processor_id_type sp, Edge e) Chris@16: : source_processor(sp), e(e) {} Chris@16: Chris@16: processor_id_type source_processor; Chris@16: Edge e; Chris@16: }; Chris@16: Chris@16: /** Chris@16: * A distributed edge descriptor. These descriptors contain the Chris@16: * underlying edge descriptor, the processor IDs for both the Chris@16: * source and the target of the edge, and a boolean flag that Chris@16: * indicates which of the processors actually owns the edge. Chris@16: */ Chris@16: template Chris@16: struct edge_descriptor Chris@16: { Chris@16: edge_descriptor(processor_id_type sp = processor_id_type(), Chris@16: processor_id_type tp = processor_id_type(), Chris@16: bool owns = false, Edge ld = Edge()) Chris@16: : source_processor(sp), target_processor(tp), Chris@16: source_owns_edge(owns), local(ld) {} Chris@16: Chris@16: processor_id_type owner() const Chris@16: { Chris@16: return source_owns_edge? source_processor : target_processor; Chris@16: } Chris@16: Chris@16: /// The processor that the source vertex resides on Chris@16: processor_id_type source_processor; Chris@16: Chris@16: /// The processor that the target vertex resides on Chris@16: processor_id_type target_processor; Chris@16: Chris@16: /// True when the source processor owns the edge, false when the Chris@16: /// target processor owns the edge. Chris@16: bool source_owns_edge; Chris@16: Chris@16: /// The local edge descriptor. Chris@16: Edge local; Chris@16: Chris@16: /** Chris@16: * Function object that generates edge descriptors for the Chris@16: * out_edge_iterator of the given distributed adjacency list Chris@16: * from the edge descriptors of the underlying adjacency list. Chris@16: */ Chris@16: template Chris@16: class out_generator Chris@16: { Chris@16: typedef typename Graph::directed_selector directed_selector; Chris@16: Chris@16: public: Chris@16: typedef edge_descriptor result_type; Chris@16: typedef Edge argument_type; Chris@16: Chris@16: out_generator() : g(0) {} Chris@16: explicit out_generator(const Graph& g) : g(&g) {} Chris@16: Chris@16: result_type operator()(argument_type e) const Chris@16: { return map(e, directed_selector()); } Chris@16: Chris@16: private: Chris@16: result_type map(argument_type e, directedS) const Chris@16: { Chris@16: return result_type(g->processor(), Chris@16: get(edge_target_processor_id, g->base(), e), Chris@16: true, e); Chris@16: } Chris@16: Chris@16: result_type map(argument_type e, bidirectionalS) const Chris@16: { Chris@16: return result_type(g->processor(), Chris@16: get(edge_target_processor_id, g->base(), e), Chris@16: true, e); Chris@16: } Chris@16: Chris@16: result_type map(argument_type e, undirectedS) const Chris@16: { Chris@16: return result_type(g->processor(), Chris@16: get(edge_target_processor_id, g->base(), e), Chris@16: get(edge_locally_owned, g->base(), e), Chris@16: e); Chris@16: } Chris@16: Chris@16: const Graph* g; Chris@16: }; Chris@16: Chris@16: /** Chris@16: * Function object that generates edge descriptors for the Chris@16: * in_edge_iterator of the given distributed adjacency list Chris@16: * from the edge descriptors of the underlying adjacency list. Chris@16: */ Chris@16: template Chris@16: class in_generator Chris@16: { Chris@16: typedef typename Graph::directed_selector DirectedS; Chris@16: Chris@16: public: Chris@16: typedef typename boost::mpl::if_, Chris@16: stored_in_edge, Chris@16: Edge>::type argument_type; Chris@16: typedef edge_descriptor result_type; Chris@16: Chris@16: in_generator() : g(0) {} Chris@16: explicit in_generator(const Graph& g) : g(&g) {} Chris@16: Chris@16: result_type operator()(argument_type e) const Chris@16: { return map(e, DirectedS()); } Chris@16: Chris@16: private: Chris@16: /** Chris@16: * For a bidirectional graph, we just generate the appropriate Chris@16: * edge. No tricks. Chris@16: */ Chris@16: result_type map(argument_type e, bidirectionalS) const Chris@16: { Chris@16: return result_type(e.source_processor, Chris@16: g->processor(), Chris@16: true, Chris@16: e.e); Chris@16: } Chris@16: Chris@16: /** Chris@16: * For an undirected graph, we generate descriptors for the Chris@16: * incoming edges by swapping the source/target of the Chris@16: * underlying edge descriptor (a hack). The target processor Chris@16: * ID on the edge is actually the source processor for this Chris@16: * edge, and our processor is the target processor. If the Chris@16: * edge is locally owned, then it is owned by the target (us); Chris@16: * otherwise it is owned by the source. Chris@16: */ Chris@16: result_type map(argument_type e, undirectedS) const Chris@16: { Chris@16: typename Graph::local_edge_descriptor local_edge(e); Chris@16: // TBD: This is a very, VERY lame hack that takes advantage Chris@16: // of our knowledge of the internals of the BGL Chris@16: // adjacency_list. There should be a cleaner way to handle Chris@16: // this... Chris@16: using std::swap; Chris@16: swap(local_edge.m_source, local_edge.m_target); Chris@16: return result_type(get(edge_target_processor_id, g->base(), e), Chris@16: g->processor(), Chris@16: !get(edge_locally_owned, g->base(), e), Chris@16: local_edge); Chris@16: } Chris@16: Chris@16: const Graph* g; Chris@16: }; Chris@16: Chris@16: private: Chris@16: friend class boost::serialization::access; Chris@16: Chris@16: template Chris@16: void serialize(Archiver& ar, const unsigned int /*version*/) Chris@16: { Chris@16: ar Chris@16: & source_processor Chris@16: & target_processor Chris@16: & source_owns_edge Chris@16: & local; Chris@16: } Chris@16: }; Chris@16: Chris@16: /// Determine the process that owns this edge Chris@16: template Chris@16: inline processor_id_type Chris@16: owner(const edge_descriptor& e) Chris@16: { return e.source_owns_edge? e.source_processor : e.target_processor; } Chris@16: Chris@16: /// Determine the local descriptor for this edge. Chris@16: template Chris@16: inline Edge Chris@16: local(const edge_descriptor& e) Chris@16: { return e.local; } Chris@16: Chris@16: /** Chris@16: * A Readable Property Map that extracts the owner and local Chris@16: * descriptor of an edge descriptor. Chris@16: */ Chris@16: template Chris@16: struct edge_global_property_map Chris@16: { Chris@16: typedef std::pair value_type; Chris@16: typedef value_type reference; Chris@16: typedef edge_descriptor key_type; Chris@16: typedef readable_property_map_tag category; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline std::pair Chris@16: get(edge_global_property_map, const edge_descriptor& e) Chris@16: { Chris@16: typedef std::pair result_type; Chris@16: return result_type(e.source_owns_edge? e.source_processor Chris@16: /* target owns edge*/: e.target_processor, Chris@16: e.local); Chris@16: } Chris@16: Chris@16: /** Chris@16: * A Readable Property Map that extracts the owner of an edge Chris@16: * descriptor. Chris@16: */ Chris@16: template Chris@16: struct edge_owner_property_map Chris@16: { Chris@16: typedef processor_id_type value_type; Chris@16: typedef value_type reference; Chris@16: typedef edge_descriptor key_type; Chris@16: typedef readable_property_map_tag category; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline processor_id_type Chris@16: get(edge_owner_property_map, const edge_descriptor& e) Chris@16: { Chris@16: return e.source_owns_edge? e.source_processor : e.target_processor; Chris@16: } Chris@16: Chris@16: /** Chris@16: * A Readable Property Map that extracts the local descriptor from Chris@16: * an edge descriptor. Chris@16: */ Chris@16: template Chris@16: struct edge_local_property_map Chris@16: { Chris@16: typedef Edge value_type; Chris@16: typedef value_type reference; Chris@16: typedef edge_descriptor key_type; Chris@16: typedef readable_property_map_tag category; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline Edge Chris@16: get(edge_local_property_map, Chris@16: const edge_descriptor& e) Chris@16: { Chris@16: return e.local; Chris@16: } Chris@16: Chris@16: /** Compare distributed edge descriptors for equality. Chris@16: * Chris@16: * \todo need edge_descriptor to know if it is undirected so we Chris@16: * can compare both ways. Chris@16: */ Chris@16: template Chris@16: inline bool Chris@16: operator==(const edge_descriptor& e1, Chris@16: const edge_descriptor& e2) Chris@16: { Chris@16: return (e1.source_processor == e2.source_processor Chris@16: && e1.target_processor == e2.target_processor Chris@16: && e1.local == e2.local); Chris@16: } Chris@16: Chris@16: /// Compare distributed edge descriptors for inequality. Chris@16: template Chris@16: inline bool Chris@16: operator!=(const edge_descriptor& e1, Chris@16: const edge_descriptor& e2) Chris@16: { return !(e1 == e2); } Chris@16: Chris@16: /** Chris@16: * Configuration for the distributed adjacency list. We use this Chris@16: * parameter to store all of the configuration details for the Chris@16: * implementation of the distributed adjacency list, which allows us to Chris@16: * get at the distribution type in the maybe_named_graph. Chris@16: */ Chris@16: template Chris@16: struct adjacency_list_config Chris@16: { Chris@16: typedef typename mpl::if_, Chris@16: vecS, InVertexListS>::type Chris@16: VertexListS; Chris@16: Chris@16: /// Introduce the target processor ID property for each edge Chris@16: typedef property edge_property_with_id; Chris@16: Chris@16: /// For undirected graphs, introduce the locally-owned property for edges Chris@16: typedef typename boost::mpl::if_, Chris@16: property, Chris@16: edge_property_with_id>::type Chris@16: base_edge_property_type; Chris@16: Chris@16: /// The edge descriptor type for the local subgraph Chris@16: typedef typename adjacency_list_traits::edge_descriptor Chris@16: local_edge_descriptor; Chris@16: Chris@16: /// For bidirectional graphs, the type of an incoming stored edge Chris@16: typedef stored_in_edge bidir_stored_edge; Chris@16: Chris@16: /// The container type that will store incoming edges for a Chris@16: /// bidirectional graph. Chris@16: typedef typename container_gen::type Chris@16: in_edge_list_type; Chris@16: Chris@16: // Bidirectional graphs have an extra vertex property to store Chris@16: // the incoming edges. Chris@16: typedef typename boost::mpl::if_, Chris@16: property, Chris@16: VertexProperty>::type Chris@16: base_vertex_property_type; Chris@16: Chris@16: // The type of the distributed adjacency list Chris@16: typedef adjacency_list, Chris@16: DirectedS, VertexProperty, EdgeProperty, Chris@16: GraphProperty, EdgeListS> Chris@16: graph_type; Chris@16: Chris@16: // The type of the underlying adjacency list implementation Chris@16: typedef adjacency_list Chris@16: inherited; Chris@16: Chris@16: typedef InDistribution in_distribution_type; Chris@16: typedef typename inherited::vertices_size_type vertices_size_type; Chris@16: Chris@16: typedef typename ::boost::graph::distributed::select_distribution< Chris@16: in_distribution_type, VertexProperty, vertices_size_type, Chris@16: ProcessGroup>::type Chris@16: base_distribution_type; Chris@16: Chris@16: typedef ::boost::graph::distributed::shuffled_distribution< Chris@16: base_distribution_type> distribution_type; Chris@16: Chris@16: typedef VertexProperty vertex_property_type; Chris@16: typedef EdgeProperty edge_property_type; Chris@16: typedef ProcessGroup process_group_type; Chris@16: Chris@16: typedef VertexListS vertex_list_selector; Chris@16: typedef OutEdgeListS out_edge_list_selector; Chris@16: typedef DirectedS directed_selector; Chris@16: typedef GraphProperty graph_property_type; Chris@16: typedef EdgeListS edge_list_selector; Chris@16: }; Chris@16: Chris@16: // Maybe initialize the indices of each vertex Chris@16: template Chris@16: void Chris@16: maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index, Chris@16: read_write_property_map_tag) Chris@16: { Chris@16: typedef typename property_traits::value_type index_t; Chris@16: index_t next_index = 0; Chris@16: while (p.first != p.second) Chris@16: put(to_index, *p.first++, next_index++); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void Chris@16: maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index, Chris@16: readable_property_map_tag) Chris@16: { Chris@16: // Do nothing Chris@16: } Chris@16: Chris@16: template Chris@16: inline void Chris@16: maybe_initialize_vertex_indices(IteratorPair p, VertexIndexMap to_index) Chris@16: { Chris@16: typedef typename property_traits::category category; Chris@16: maybe_initialize_vertex_indices(p, to_index, category()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void Chris@16: maybe_initialize_vertex_indices(IteratorPair p, Chris@16: ::boost::detail::error_property_not_found) Chris@16: { } Chris@16: Chris@16: /*********************************************************************** Chris@16: * Message Payloads * Chris@16: ***********************************************************************/ Chris@16: Chris@16: /** Chris@16: * Data stored with a msg_add_edge message, which requests the Chris@16: * remote addition of an edge. Chris@16: */ Chris@16: template Chris@16: struct msg_add_edge_data Chris@16: { Chris@16: msg_add_edge_data() { } Chris@16: Chris@16: msg_add_edge_data(Vertex source, Vertex target) Chris@16: : source(source.local), target(target) { } Chris@16: Chris@16: /// The source of the edge; the processor will be the Chris@16: /// receiving processor. Chris@16: LocalVertex source; Chris@16: Chris@16: /// The target of the edge. Chris@16: Vertex target; Chris@16: Chris@16: template Chris@16: void serialize(Archiver& ar, const unsigned int /*version*/) Chris@16: { Chris@16: ar & unsafe_serialize(source) & target; Chris@16: } Chris@16: }; Chris@16: Chris@16: /** Chris@16: * Like @c msg_add_edge_data, but also includes a user-specified Chris@16: * property value to be attached to the edge. Chris@16: */ Chris@16: template Chris@16: struct msg_add_edge_with_property_data Chris@16: : msg_add_edge_data, Chris@16: maybe_store_property Chris@16: { Chris@16: private: Chris@16: typedef msg_add_edge_data inherited_data; Chris@16: typedef maybe_store_property inherited_property; Chris@16: Chris@16: public: Chris@16: msg_add_edge_with_property_data() { } Chris@16: Chris@16: msg_add_edge_with_property_data(Vertex source, Chris@16: Vertex target, Chris@16: const EdgeProperty& property) Chris@16: : inherited_data(source, target), Chris@16: inherited_property(property) { } Chris@16: Chris@16: template Chris@16: void serialize(Archiver& ar, const unsigned int /*version*/) Chris@16: { Chris@16: ar & boost::serialization::base_object(*this) Chris@16: & boost::serialization::base_object(*this); Chris@16: } Chris@16: }; Chris@16: Chris@16: //------------------------------------------------------------------------ Chris@16: // Distributed adjacency list property map details Chris@16: /** Chris@16: * Metafunction that extracts the given property from the given Chris@16: * distributed adjacency list type. This could be implemented much Chris@16: * more cleanly, but even newer versions of GCC (e.g., 3.2.3) Chris@16: * cannot properly handle partial specializations involving Chris@16: * enumerator types. Chris@16: */ Chris@16: template Chris@16: struct get_adj_list_pmap Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: typedef Graph graph_type; Chris@16: typedef typename graph_type::process_group_type process_group_type; Chris@16: typedef typename graph_type::inherited base_graph_type; Chris@16: typedef typename property_map::type Chris@16: local_pmap; Chris@16: typedef typename property_map::const_type Chris@16: local_const_pmap; Chris@16: Chris@16: typedef graph_traits traits; Chris@16: typedef typename graph_type::local_vertex_descriptor local_vertex; Chris@16: typedef typename property_traits::key_type local_key_type; Chris@16: Chris@16: typedef typename property_traits::value_type value_type; Chris@16: Chris@16: typedef typename property_map::const_type Chris@16: vertex_global_map; Chris@16: typedef typename property_map::const_type Chris@16: edge_global_map; Chris@16: Chris@16: typedef typename mpl::if_c<(is_same::value), Chris@16: vertex_global_map, edge_global_map>::type Chris@16: global_map; Chris@16: Chris@16: public: Chris@16: typedef ::boost::parallel::distributed_property_map< Chris@16: process_group_type, global_map, local_pmap> type; Chris@16: Chris@16: typedef ::boost::parallel::distributed_property_map< Chris@16: process_group_type, global_map, local_const_pmap> const_type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: /** Chris@16: * The local vertex index property map is actually a mapping from Chris@16: * the local vertex descriptors to vertex indices. Chris@16: */ Chris@16: template<> Chris@16: struct get_adj_list_pmap Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: : ::boost::property_map Chris@16: { }; Chris@16: }; Chris@16: Chris@16: /** Chris@16: * The vertex index property map maps from global descriptors Chris@16: * (e.g., the vertex descriptor of a distributed adjacency list) Chris@16: * to the underlying local index. It is not valid to use this Chris@16: * property map with nonlocal descriptors. Chris@16: */ Chris@16: template<> Chris@16: struct get_adj_list_pmap Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: private: Chris@16: typedef typename property_map::const_type Chris@16: global_map; Chris@16: Chris@16: typedef property_map local; Chris@16: Chris@16: public: Chris@16: typedef local_property_map type; Chris@16: typedef local_property_map const_type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: /** Chris@16: * The vertex owner property map maps from vertex descriptors to Chris@16: * the processor that owns the vertex. Chris@16: */ Chris@16: template<> Chris@16: struct get_adj_list_pmap Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: private: Chris@16: typedef typename Graph::local_vertex_descriptor Chris@16: local_vertex_descriptor; Chris@16: public: Chris@16: typedef global_descriptor_property_map type; Chris@16: typedef type const_type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: /** Chris@16: * The vertex owner property map maps from vertex descriptors to Chris@16: * the processor that owns the vertex. Chris@16: */ Chris@16: template<> Chris@16: struct get_adj_list_pmap Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: private: Chris@16: typedef typename Graph::local_vertex_descriptor Chris@16: local_vertex_descriptor; Chris@16: public: Chris@16: typedef owner_property_map type; Chris@16: typedef type const_type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: /** Chris@16: * The vertex local property map maps from vertex descriptors to Chris@16: * the local descriptor for that vertex. Chris@16: */ Chris@16: template<> Chris@16: struct get_adj_list_pmap Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: private: Chris@16: typedef typename Graph::local_vertex_descriptor Chris@16: local_vertex_descriptor; Chris@16: public: Chris@16: typedef local_descriptor_property_map type; Chris@16: typedef type const_type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: /** Chris@16: * The edge global property map maps from edge descriptors to Chris@16: * a pair of the owning processor and local descriptor. Chris@16: */ Chris@16: template<> Chris@16: struct get_adj_list_pmap Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: private: Chris@16: typedef typename Graph::local_edge_descriptor Chris@16: local_edge_descriptor; Chris@16: public: Chris@16: typedef edge_global_property_map type; Chris@16: typedef type const_type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: /** Chris@16: * The edge owner property map maps from edge descriptors to Chris@16: * the processor that owns the edge. Chris@16: */ Chris@16: template<> Chris@16: struct get_adj_list_pmap Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: private: Chris@16: typedef typename Graph::local_edge_descriptor Chris@16: local_edge_descriptor; Chris@16: public: Chris@16: typedef edge_owner_property_map type; Chris@16: typedef type const_type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: /** Chris@16: * The edge local property map maps from edge descriptors to Chris@16: * the local descriptor for that edge. Chris@16: */ Chris@16: template<> Chris@16: struct get_adj_list_pmap Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: { Chris@16: private: Chris@16: typedef typename Graph::local_edge_descriptor Chris@16: local_edge_descriptor; Chris@16: public: Chris@16: typedef edge_local_property_map type; Chris@16: typedef type const_type; Chris@16: }; Chris@16: }; Chris@16: //------------------------------------------------------------------------ Chris@16: Chris@16: // Directed graphs do not have in edges, so this is a no-op Chris@16: template Chris@16: inline void Chris@16: remove_in_edge(typename Graph::edge_descriptor, Graph&, directedS) Chris@16: { } Chris@16: Chris@16: // Bidirectional graphs have in edges stored in the Chris@16: // vertex_in_edges property. Chris@16: template Chris@16: inline void Chris@16: remove_in_edge(typename Graph::edge_descriptor e, Graph& g, bidirectionalS) Chris@16: { Chris@16: typedef typename Graph::in_edge_list_type in_edge_list_type; Chris@16: in_edge_list_type& in_edges = Chris@16: get(vertex_in_edges, g.base())[target(e, g).local]; Chris@16: typename in_edge_list_type::iterator i = in_edges.begin(); Chris@16: while (i != in_edges.end() Chris@16: && !(i->source_processor == source(e, g).owner) Chris@16: && i->e == e.local) Chris@16: ++i; Chris@16: Chris@16: BOOST_ASSERT(i != in_edges.end()); Chris@16: in_edges.erase(i); Chris@16: } Chris@16: Chris@16: // Undirected graphs have in edges stored as normal edges. Chris@16: template Chris@16: inline void Chris@16: remove_in_edge(typename Graph::edge_descriptor e, Graph& g, undirectedS) Chris@16: { Chris@16: typedef typename Graph::inherited base_type; Chris@16: typedef typename graph_traits::vertex_descriptor vertex_descriptor; Chris@16: Chris@16: // TBD: can we make this more efficient? Chris@16: // Removing edge (v, u). v is local Chris@16: base_type& bg = g.base(); Chris@16: vertex_descriptor u = source(e, g); Chris@16: vertex_descriptor v = target(e, g); Chris@16: if (v.owner != process_id(g.process_group())) { Chris@16: using std::swap; Chris@16: swap(u, v); Chris@16: } Chris@16: Chris@16: typename graph_traits::out_edge_iterator ei, ei_end; Chris@16: for (boost::tie(ei, ei_end) = out_edges(v.local, bg); ei != ei_end; ++ei) Chris@16: { Chris@16: if (target(*ei, g.base()) == u.local Chris@16: // TBD: deal with parallel edges properly && *ei == e Chris@16: && get(edge_target_processor_id, bg, *ei) == u.owner) { Chris@16: remove_edge(ei, bg); Chris@16: return; Chris@16: } Chris@16: } Chris@16: Chris@16: if (v.owner == process_id(g.process_group())) { Chris@16: Chris@16: } Chris@16: } Chris@16: Chris@16: //------------------------------------------------------------------------ Chris@16: // Lazy addition of edges Chris@16: Chris@16: // Work around the fact that an adjacency_list with vecS vertex Chris@16: // storage automatically adds edges when the descriptor is Chris@16: // out-of-range. Chris@16: template Chris@16: inline std::pair Chris@16: add_local_edge(typename Config::vertex_descriptor u, Chris@16: typename Config::vertex_descriptor v, Chris@16: const typename Config::edge_property_type& p, Chris@16: vec_adj_list_impl& g_) Chris@16: { Chris@16: adj_list_helper& g = g_; Chris@16: return add_edge(u, v, p, g); Chris@16: } Chris@16: Chris@16: template Chris@16: inline std::pair Chris@16: add_local_edge(typename Config::vertex_descriptor u, Chris@16: typename Config::vertex_descriptor v, Chris@16: const typename Config::edge_property_type& p, Chris@16: boost::adj_list_impl& g) Chris@16: { Chris@16: return add_edge(u, v, p, g); Chris@16: } Chris@16: Chris@16: template Chris@16: struct msg_nonlocal_edge_data Chris@16: : public detail::parallel::maybe_store_property Chris@16: { Chris@16: typedef EdgeProperty edge_property_type; Chris@16: typedef EdgeDescriptor local_edge_descriptor; Chris@16: typedef detail::parallel::maybe_store_property Chris@16: inherited; Chris@16: Chris@16: msg_nonlocal_edge_data() {} Chris@16: msg_nonlocal_edge_data(local_edge_descriptor e, Chris@16: const edge_property_type& p) Chris@16: : inherited(p), e(e) { } Chris@16: Chris@16: local_edge_descriptor e; Chris@16: Chris@16: template Chris@16: void serialize(Archiver& ar, const unsigned int /*version*/) Chris@16: { Chris@16: ar & boost::serialization::base_object(*this) & e; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct msg_remove_edge_data Chris@16: { Chris@16: typedef EdgeDescriptor edge_descriptor; Chris@16: msg_remove_edge_data() {} Chris@16: explicit msg_remove_edge_data(edge_descriptor e) : e(e) {} Chris@16: Chris@16: edge_descriptor e; Chris@16: Chris@16: template Chris@16: void serialize(Archiver& ar, const unsigned int /*version*/) Chris@16: { Chris@16: ar & e; Chris@16: } Chris@16: }; Chris@16: Chris@16: } } // end namespace detail::parallel Chris@16: Chris@16: /** Chris@16: * Adjacency list traits for a distributed adjacency list. Contains Chris@16: * the vertex and edge descriptors, the directed-ness, and the Chris@16: * parallel edges typedefs. Chris@16: */ Chris@16: template Chris@16: struct adjacency_list_traits, Chris@16: DirectedS> Chris@16: { Chris@16: private: Chris@16: typedef typename mpl::if_, Chris@16: vecS, Chris@16: InVertexListS>::type VertexListS; Chris@16: Chris@16: typedef adjacency_list_traits Chris@16: base_type; Chris@16: Chris@16: public: Chris@16: typedef typename base_type::vertex_descriptor local_vertex_descriptor; Chris@16: typedef typename base_type::edge_descriptor local_edge_descriptor; Chris@16: Chris@16: typedef typename boost::mpl::if_::type Chris@16: >::type directed_category; Chris@16: Chris@16: typedef typename parallel_edge_traits::type Chris@16: edge_parallel_category; Chris@16: Chris@16: typedef detail::parallel::global_descriptor Chris@16: vertex_descriptor; Chris@16: Chris@16: typedef detail::parallel::edge_descriptor Chris@16: edge_descriptor; Chris@16: }; Chris@16: Chris@16: #define PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS \ Chris@16: typename OutEdgeListS, typename ProcessGroup, typename InVertexListS, \ Chris@16: typename InDistribution, typename DirectedS, typename VertexProperty, \ Chris@16: typename EdgeProperty, typename GraphProperty, typename EdgeListS Chris@16: Chris@16: #define PBGL_DISTRIB_ADJLIST_TYPE \ Chris@16: adjacency_list, \ Chris@16: DirectedS, VertexProperty, EdgeProperty, GraphProperty, \ Chris@16: EdgeListS> Chris@16: Chris@16: #define PBGL_DISTRIB_ADJLIST_TEMPLATE_PARMS_CONFIG \ Chris@16: typename OutEdgeListS, typename ProcessGroup, typename InVertexListS, \ Chris@16: typename InDistribution, typename VertexProperty, \ Chris@16: typename EdgeProperty, typename GraphProperty, typename EdgeListS Chris@16: Chris@16: #define PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directed) \ Chris@16: adjacency_list, \ Chris@16: directed, VertexProperty, EdgeProperty, GraphProperty, \ Chris@16: EdgeListS> Chris@16: Chris@16: /** A distributed adjacency list. Chris@16: * Chris@16: * This class template partial specialization defines a distributed Chris@16: * (or "partitioned") adjacency list graph. The distributed Chris@16: * adjacency list is similar to the standard Boost Graph Library Chris@16: * adjacency list, which stores a list of vertices and for each Chris@16: * verted the list of edges outgoing from the vertex (and, in some Chris@16: * cases, also the edges incoming to the vertex). The distributed Chris@16: * adjacency list differs in that it partitions the graph into Chris@16: * several subgraphs that are then divided among different Chris@16: * processors (or nodes within a cluster). The distributed adjacency Chris@16: * list attempts to maintain a high degree of compatibility with the Chris@16: * standard, non-distributed adjacency list. Chris@16: * Chris@16: * The graph is partitioned by vertex, with each processor storing Chris@16: * all of the required information for a particular subset of the Chris@16: * vertices, including vertex properties, outgoing edges, and (for Chris@16: * bidirectional graphs) incoming edges. This information is Chris@16: * accessible only on the processor that owns the vertex: for Chris@16: * instance, if processor 0 owns vertex @c v, no other processor can Chris@16: * directly access the properties of @c v or enumerate its outgoing Chris@16: * edges. Chris@16: * Chris@16: * Edges in a graph may be entirely local (connecting two local Chris@16: * vertices), but more often it is the case that edges are Chris@16: * non-local, meaning that the two vertices they connect reside in Chris@16: * different processes. Edge properties are stored with the Chris@16: * originating vertex for directed and bidirectional graphs, and are Chris@16: * therefore only accessible from the processor that owns the Chris@16: * originating vertex. Other processors may query the source and Chris@16: * target of the edge, but cannot access its properties. This is Chris@16: * particularly interesting when accessing the incoming edges of a Chris@16: * bidirectional graph, which are not guaranteed to be stored on the Chris@16: * processor that is able to perform the iteration. For undirected Chris@16: * graphs the situation is more complicated, since no vertex clearly Chris@16: * owns the edges: the list of edges incident to a vertex may Chris@16: * contain a mix of local and non-local edges. Chris@16: * Chris@16: * The distributed adjacency list is able to model several of the Chris@16: * existing Graph concepts. It models the Graph concept because it Chris@16: * exposes vertex and edge descriptors in the normal way; these Chris@16: * descriptors model the GlobalDescriptor concept (because they have Chris@16: * an owner and a local descriptor), and as such the distributed Chris@16: * adjacency list models the DistributedGraph concept. The adjacency Chris@16: * list also models the IncidenceGraph and AdjacencyGraph concepts, Chris@16: * although this is only true so long as the domain of the valid Chris@16: * expression arguments are restricted to vertices and edges stored Chris@16: * locally. Likewise, bidirectional and undirected distributed Chris@16: * adjacency lists model the BidirectionalGraph concept (vertex and Chris@16: * edge domains must be respectived) and the distributed adjacency Chris@16: * list models the MutableGraph concept (vertices and edges can only Chris@16: * be added or removed locally). T he distributed adjacency list Chris@16: * does not, however, model the VertexListGraph or EdgeListGraph Chris@16: * concepts, because we can not efficiently enumerate all vertices Chris@16: * or edges in the graph. Instead, the local subsets of vertices and Chris@16: * edges can be enumerated (with the same syntax): the distributed Chris@16: * adjacency list therefore models the DistributedVertexListGraph Chris@16: * and DistributedEdgeListGraph concepts, because concurrent Chris@16: * iteration over all of the vertices or edges stored on each Chris@16: * processor will visit each vertex or edge. Chris@16: * Chris@16: * The distributed adjacency list is distinguished from the Chris@16: * non-distributed version by the vertex list descriptor, which will Chris@16: * be @c distributedS. Here, Chris@16: * the VertexListS type plays the same role as the VertexListS type Chris@16: * in the non-distributed adjacency list: it allows one to select Chris@16: * the data structure that will be used to store the local Chris@16: * vertices. The ProcessGroup type, on the other hand, is unique to Chris@16: * distributed data structures: it is the type that abstracts a Chris@16: * group of cooperating processes, and it used for process Chris@16: * identification, communication, and synchronization, among other Chris@16: * things. Different process group types represent different Chris@16: * communication mediums (e.g., MPI, PVM, TCP) or different models Chris@16: * of communication (LogP, CGM, BSP, synchronous, etc.). This Chris@16: * distributed adjacency list assumes a model based on non-blocking Chris@16: * sends. Chris@16: * Chris@16: * Distribution of vertices across different processors is Chris@16: * accomplished in two different ways. When initially constructing Chris@16: * the graph, the user may provide a distribution object (that Chris@16: * models the Distribution concept), which will determine the Chris@16: * distribution of vertices to each process. Additionally, the @c Chris@16: * add_vertex and @c add_edge operations add vertices or edges Chris@16: * stored on the local processor. For @c add_edge, this is Chris@16: * accomplished by requiring that the source vertex of the new edge Chris@16: * be local to the process executing @c add_edge. Chris@16: * Chris@16: * Internal properties of a distributed adjacency list are Chris@16: * accessible in the same manner as internal properties for a Chris@16: * non-distributed adjacency list for local vertices or Chris@16: * edges. Access to properties for remote vertices or edges occurs Chris@16: * with the same syntax, but involve communication with the owner of Chris@16: * the information: for more information, refer to class template Chris@16: * @ref distributed_property_map, which manages distributed Chris@16: * property maps. Note that the distributed property maps created Chris@16: * for internal properties determine their reduction operation via Chris@16: * the metafunction @ref property_reduce, which for the vast Chris@16: * majority of uses is correct behavior. Chris@16: * Chris@16: * Communication among the processes coordinating on a particular Chris@16: * distributed graph relies on non-blocking message passing along Chris@16: * with synchronization. Local portions of the distributed graph may Chris@16: * be modified concurrently, including the introduction of non-local Chris@16: * edges, but prior to accessing the graph it is recommended that Chris@16: * the @c synchronize free function be invoked on the graph to clear Chris@16: * up any pending interprocess communication and modifications. All Chris@16: * processes will then be released from the synchronization barrier Chris@16: * concurrently. Chris@16: * Chris@16: * \todo Determine precisely what we should do with nonlocal edges Chris@16: * in undirected graphs. Our parallelization of certain algorithms Chris@16: * relies on the ability to access edge property maps immediately Chris@16: * (e.g., edge_weight_t), so it may be necessary to duplicate the Chris@16: * edge properties in both processes (but then we need some form of Chris@16: * coherence protocol). Chris@16: * Chris@16: * \todo What does the user do if @c property_reduce doesn't do the Chris@16: * right thing? Chris@16: */ Chris@16: template Chris@16: class adjacency_list, Chris@16: DirectedS, VertexProperty, Chris@16: EdgeProperty, GraphProperty, EdgeListS> Chris@16: : // Support for named vertices Chris@16: public graph::distributed::maybe_named_graph< Chris@16: adjacency_list, Chris@16: DirectedS, VertexProperty, Chris@16: EdgeProperty, GraphProperty, EdgeListS>, Chris@16: typename adjacency_list_traits, Chris@16: DirectedS>::vertex_descriptor, Chris@16: typename adjacency_list_traits, Chris@16: DirectedS>::edge_descriptor, Chris@16: detail::parallel::adjacency_list_config > Chris@16: { Chris@16: typedef detail::parallel::adjacency_list_config Chris@16: config_type; Chris@16: Chris@16: typedef adjacency_list_traits, Chris@16: DirectedS> Chris@16: traits_type; Chris@16: Chris@16: typedef typename DirectedS::is_directed_t is_directed; Chris@16: Chris@16: typedef EdgeListS edge_list_selector; Chris@16: Chris@16: public: Chris@16: /// The container type that will store incoming edges for a Chris@16: /// bidirectional graph. Chris@16: typedef typename config_type::in_edge_list_type in_edge_list_type; Chris@16: // typedef typename inherited::edge_descriptor edge_descriptor; Chris@16: Chris@16: /// The type of the underlying adjacency list implementation Chris@16: typedef typename config_type::inherited inherited; Chris@16: Chris@16: /// The type of properties stored in the local subgraph Chris@16: /// Bidirectional graphs have an extra vertex property to store Chris@16: /// the incoming edges. Chris@16: typedef typename inherited::vertex_property_type Chris@16: base_vertex_property_type; Chris@16: Chris@16: /// The type of the distributed adjacency list (this type) Chris@16: typedef typename config_type::graph_type graph_type; Chris@16: Chris@16: /// Expose graph components and graph category Chris@16: typedef typename traits_type::local_vertex_descriptor Chris@16: local_vertex_descriptor; Chris@16: typedef typename traits_type::local_edge_descriptor Chris@16: local_edge_descriptor; Chris@16: typedef typename traits_type::vertex_descriptor vertex_descriptor; Chris@16: typedef typename traits_type::edge_descriptor edge_descriptor; Chris@16: Chris@16: typedef typename traits_type::directed_category directed_category; Chris@16: typedef typename inherited::edge_parallel_category Chris@16: edge_parallel_category; Chris@16: typedef typename inherited::graph_tag graph_tag; Chris@16: Chris@16: // Current implementation requires the ability to have parallel Chris@16: // edges in the underlying adjacency_list. Which processor each Chris@16: // edge refers to is attached as an internal property. TBD: Chris@16: // remove this restriction, which may require some rewriting. Chris@16: BOOST_STATIC_ASSERT((is_same::value)); Chris@16: Chris@16: /** Determine the graph traversal category. Chris@16: * Chris@16: * A directed distributed adjacency list models the Distributed Chris@16: * Graph, Incidence Graph, and Adjacency Graph Chris@16: * concepts. Bidirectional and undirected graphs also model the Chris@16: * Bidirectional Graph concept. Note that when modeling these Chris@16: * concepts the domains of certain operations (e.g., in_edges) Chris@16: * are restricted; see the distributed adjacency_list Chris@16: * documentation. Chris@16: */ Chris@16: typedef typename boost::mpl::if_< Chris@16: is_same, Chris@16: directed_distributed_adj_list_tag, Chris@16: typename boost::mpl::if_, Chris@16: bidirectional_distributed_adj_list_tag, Chris@16: undirected_distributed_adj_list_tag>::type> Chris@16: ::type traversal_category; Chris@16: Chris@16: typedef typename inherited::degree_size_type degree_size_type; Chris@16: typedef typename inherited::vertices_size_type vertices_size_type; Chris@16: typedef typename inherited::edges_size_type edges_size_type; Chris@16: typedef VertexProperty vertex_property_type; Chris@16: typedef EdgeProperty edge_property_type; Chris@16: typedef typename inherited::graph_property_type graph_property_type; Chris@16: typedef typename inherited::vertex_bundled vertex_bundled; Chris@16: typedef typename inherited::edge_bundled edge_bundled; Chris@16: typedef typename inherited::graph_bundled graph_bundled; Chris@16: Chris@16: typedef typename container_gen::type Chris@16: local_edge_list_type; Chris@16: Chris@16: private: Chris@16: typedef typename boost::mpl::if_, Chris@16: typename in_edge_list_type::const_iterator, Chris@16: typename inherited::out_edge_iterator>::type Chris@16: base_in_edge_iterator; Chris@16: Chris@16: typedef typename inherited::out_edge_iterator base_out_edge_iterator; Chris@16: typedef typename graph_traits::edge_iterator Chris@16: base_edge_iterator; Chris@16: typedef typename inherited::edge_property_type base_edge_property_type; Chris@16: Chris@16: typedef typename local_edge_list_type::const_iterator Chris@16: undirected_edge_iterator; Chris@16: Chris@16: typedef InDistribution in_distribution_type; Chris@16: Chris@16: typedef parallel::trigger_receive_context trigger_receive_context; Chris@16: Chris@16: public: Chris@16: /// Iterator over the (local) vertices of the graph Chris@16: typedef transform_iterator Chris@16: vertex_iterator; Chris@16: Chris@16: /// Helper for out_edge_iterator Chris@16: typedef typename edge_descriptor::template out_generator Chris@16: out_edge_generator; Chris@16: Chris@16: /// Iterator over the outgoing edges of a vertex Chris@16: typedef transform_iterator Chris@16: out_edge_iterator; Chris@16: Chris@16: /// Helper for in_edge_iterator Chris@16: typedef typename edge_descriptor::template in_generator Chris@16: in_edge_generator; Chris@16: Chris@16: /// Iterator over the incoming edges of a vertex Chris@16: typedef transform_iterator Chris@16: in_edge_iterator; Chris@16: Chris@16: /// Iterator over the neighbors of a vertex Chris@16: typedef boost::adjacency_iterator< Chris@16: adjacency_list, vertex_descriptor, out_edge_iterator, Chris@16: typename detail::iterator_traits Chris@16: ::difference_type> Chris@16: adjacency_iterator; Chris@16: Chris@16: /// Iterator over the (local) edges in a graph Chris@16: typedef typename boost::mpl::if_, Chris@16: undirected_edge_iterator, Chris@16: transform_iterator Chris@16: >::type Chris@16: edge_iterator; Chris@16: Chris@16: public: Chris@16: /// The type of the mixin for named vertices Chris@16: typedef graph::distributed::maybe_named_graph Chris@16: named_graph_mixin; Chris@16: Chris@16: /// Process group used for communication Chris@16: typedef ProcessGroup process_group_type; Chris@16: Chris@16: /// How to refer to a process Chris@16: typedef typename process_group_type::process_id_type process_id_type; Chris@16: Chris@16: /// Whether this graph is directed, undirected, or bidirectional Chris@16: typedef DirectedS directed_selector; Chris@16: Chris@16: // Structure used for the lazy addition of vertices Chris@16: struct lazy_add_vertex_with_property; Chris@16: friend struct lazy_add_vertex_with_property; Chris@16: Chris@16: // Structure used for the lazy addition of edges Chris@16: struct lazy_add_edge; Chris@16: friend struct lazy_add_edge; Chris@16: Chris@16: // Structure used for the lazy addition of edges with properties Chris@16: struct lazy_add_edge_with_property; Chris@16: friend struct lazy_add_edge_with_property; Chris@16: Chris@16: /// default_distribution_type is the type of the distribution used if the Chris@16: /// user didn't specify an explicit one Chris@16: typedef typename graph::distributed::select_distribution< Chris@16: InDistribution, VertexProperty, vertices_size_type, Chris@16: ProcessGroup>::default_type Chris@16: default_distribution_type; Chris@16: Chris@16: /// distribution_type is the type of the distribution instance stored in Chris@16: /// the maybe_named_graph base class Chris@16: typedef typename graph::distributed::select_distribution< Chris@16: InDistribution, VertexProperty, vertices_size_type, Chris@16: ProcessGroup>::type Chris@16: base_distribution_type; Chris@16: Chris@16: typedef graph::distributed::shuffled_distribution< Chris@16: base_distribution_type> distribution_type; Chris@16: Chris@16: private: Chris@16: // FIXME: the original adjacency_list contained this comment: Chris@16: // Default copy constructor and copy assignment operators OK??? TBD Chris@16: // but the adj_list_impl contained these declarations: Chris@16: adjacency_list(const adjacency_list& other); Chris@16: adjacency_list& operator=(const adjacency_list& other); Chris@16: Chris@16: public: Chris@16: adjacency_list(const ProcessGroup& pg = ProcessGroup()) Chris@16: : named_graph_mixin(pg, default_distribution_type(pg, 0)), Chris@16: m_local_graph(GraphProperty()), Chris@101: process_group_(pg, boost::parallel::attach_distributed_object()) Chris@16: { Chris@16: setup_triggers(); Chris@16: } Chris@16: Chris@16: adjacency_list(const ProcessGroup& pg, Chris@16: const base_distribution_type& distribution) Chris@16: : named_graph_mixin(pg, distribution), Chris@16: m_local_graph(GraphProperty()), Chris@101: process_group_(pg, boost::parallel::attach_distributed_object()) Chris@16: { Chris@16: setup_triggers(); Chris@16: } Chris@16: Chris@16: adjacency_list(const GraphProperty& g, Chris@16: const ProcessGroup& pg = ProcessGroup()) Chris@16: : named_graph_mixin(pg, default_distribution_type(pg, 0)), Chris@16: m_local_graph(g), Chris@101: process_group_(pg, boost::parallel::attach_distributed_object()) Chris@16: { Chris@16: setup_triggers(); Chris@16: } Chris@16: Chris@16: adjacency_list(vertices_size_type n, Chris@16: const GraphProperty& p, Chris@16: const ProcessGroup& pg, Chris@16: const base_distribution_type& distribution) Chris@16: : named_graph_mixin(pg, distribution), Chris@16: m_local_graph(distribution.block_size(process_id(pg), n), p), Chris@101: process_group_(pg, boost::parallel::attach_distributed_object()) Chris@16: { Chris@16: setup_triggers(); Chris@16: Chris@16: detail::parallel::maybe_initialize_vertex_indices(vertices(base()), Chris@16: get(vertex_index, base())); Chris@16: } Chris@16: Chris@16: adjacency_list(vertices_size_type n, Chris@16: const ProcessGroup& pg, Chris@16: const base_distribution_type& distribution) Chris@16: : named_graph_mixin(pg, distribution), Chris@16: m_local_graph(distribution.block_size(process_id(pg), n), GraphProperty()), Chris@101: process_group_(pg, boost::parallel::attach_distributed_object()) Chris@16: { Chris@16: setup_triggers(); Chris@16: Chris@16: detail::parallel::maybe_initialize_vertex_indices(vertices(base()), Chris@16: get(vertex_index, base())); Chris@16: } Chris@16: Chris@16: adjacency_list(vertices_size_type n, Chris@16: const GraphProperty& p, Chris@16: const ProcessGroup& pg = ProcessGroup()) Chris@16: : named_graph_mixin(pg, default_distribution_type(pg, n)), Chris@16: m_local_graph(this->distribution().block_size(process_id(pg), n), p), Chris@101: process_group_(pg, boost::parallel::attach_distributed_object()) Chris@16: { Chris@16: setup_triggers(); Chris@16: Chris@16: detail::parallel::maybe_initialize_vertex_indices(vertices(base()), Chris@16: get(vertex_index, base())); Chris@16: } Chris@16: Chris@16: adjacency_list(vertices_size_type n, Chris@16: const ProcessGroup& pg = ProcessGroup()) Chris@16: : named_graph_mixin(pg, default_distribution_type(pg, n)), Chris@16: m_local_graph(this->distribution().block_size(process_id(pg), n), Chris@16: GraphProperty()), Chris@101: process_group_(pg, boost::parallel::attach_distributed_object()) Chris@16: { Chris@16: setup_triggers(); Chris@16: Chris@16: detail::parallel::maybe_initialize_vertex_indices(vertices(base()), Chris@16: get(vertex_index, base())); Chris@16: } Chris@16: Chris@16: /* Chris@16: * We assume that every processor sees the same list of edges, so Chris@16: * they skip over any that don't originate from themselves. This Chris@16: * means that programs switching between a local and a distributed Chris@16: * graph will keep the same semantics. Chris@16: */ Chris@16: template Chris@16: adjacency_list(EdgeIterator first, EdgeIterator last, Chris@16: vertices_size_type n, Chris@16: const ProcessGroup& pg = ProcessGroup(), Chris@16: const GraphProperty& p = GraphProperty()) Chris@16: : named_graph_mixin(pg, default_distribution_type(pg, n)), Chris@16: m_local_graph(this->distribution().block_size(process_id(pg), n), p), Chris@101: process_group_(pg, boost::parallel::attach_distributed_object()) Chris@16: { Chris@16: setup_triggers(); Chris@16: Chris@16: typedef typename config_type::VertexListS vertex_list_selector; Chris@16: initialize(first, last, n, this->distribution(), vertex_list_selector()); Chris@16: detail::parallel::maybe_initialize_vertex_indices(vertices(base()), Chris@16: get(vertex_index, base())); Chris@16: Chris@16: } Chris@16: Chris@16: template Chris@16: adjacency_list(EdgeIterator first, EdgeIterator last, Chris@16: EdgePropertyIterator ep_iter, Chris@16: vertices_size_type n, Chris@16: const ProcessGroup& pg = ProcessGroup(), Chris@16: const GraphProperty& p = GraphProperty()) Chris@16: : named_graph_mixin(pg, default_distribution_type(pg, n)), Chris@16: m_local_graph(this->distribution().block_size(process_id(pg), n), p), Chris@101: process_group_(pg, boost::parallel::attach_distributed_object()) Chris@16: { Chris@16: setup_triggers(); Chris@16: Chris@16: typedef typename config_type::VertexListS vertex_list_selector; Chris@16: initialize(first, last, ep_iter, n, this->distribution(), Chris@16: vertex_list_selector()); Chris@16: detail::parallel::maybe_initialize_vertex_indices(vertices(base()), Chris@16: get(vertex_index, base())); Chris@16: Chris@16: } Chris@16: Chris@16: template Chris@16: adjacency_list(EdgeIterator first, EdgeIterator last, Chris@16: vertices_size_type n, Chris@16: const ProcessGroup& pg, Chris@16: const base_distribution_type& distribution, Chris@16: const GraphProperty& p = GraphProperty()) Chris@16: : named_graph_mixin(pg, distribution), Chris@16: m_local_graph(distribution.block_size(process_id(pg), n), p), Chris@101: process_group_(pg, boost::parallel::attach_distributed_object()) Chris@16: { Chris@16: setup_triggers(); Chris@16: Chris@16: typedef typename config_type::VertexListS vertex_list_selector; Chris@16: initialize(first, last, n, this->distribution(), vertex_list_selector()); Chris@16: detail::parallel::maybe_initialize_vertex_indices(vertices(base()), Chris@16: get(vertex_index, base())); Chris@16: Chris@16: } Chris@16: Chris@16: template Chris@16: adjacency_list(EdgeIterator first, EdgeIterator last, Chris@16: EdgePropertyIterator ep_iter, Chris@16: vertices_size_type n, Chris@16: const ProcessGroup& pg, Chris@16: const base_distribution_type& distribution, Chris@16: const GraphProperty& p = GraphProperty()) Chris@16: : named_graph_mixin(pg, distribution), Chris@16: m_local_graph(this->distribution().block_size(process_id(pg), n), p), Chris@101: process_group_(pg, boost::parallel::attach_distributed_object()) Chris@16: { Chris@16: setup_triggers(); Chris@16: Chris@16: typedef typename config_type::VertexListS vertex_list_selector; Chris@16: initialize(first, last, ep_iter, n, distribution, Chris@16: vertex_list_selector()); Chris@16: detail::parallel::maybe_initialize_vertex_indices(vertices(base()), Chris@16: get(vertex_index, base())); Chris@16: Chris@16: } Chris@16: Chris@16: ~adjacency_list() Chris@16: { Chris@16: synchronize(process_group_); Chris@16: } Chris@16: Chris@16: void clear() Chris@16: { Chris@16: base().clear(); Chris@16: local_edges_.clear(); Chris@16: named_graph_mixin::clearing_graph(); Chris@16: } Chris@16: Chris@16: void swap(adjacency_list& other) Chris@16: { Chris@16: using std::swap; Chris@16: Chris@16: base().swap(other); Chris@16: swap(process_group_, other.process_group_); Chris@16: } Chris@16: Chris@16: static vertex_descriptor null_vertex() Chris@16: { Chris@16: return vertex_descriptor(processor_id_type(0), Chris@16: inherited::null_vertex()); Chris@16: } Chris@16: Chris@16: inherited& base() { return m_local_graph; } Chris@16: const inherited& base() const { return m_local_graph; } Chris@16: Chris@16: processor_id_type processor() const { return process_id(process_group_); } Chris@16: process_group_type process_group() const { return process_group_.base(); } Chris@16: Chris@16: local_edge_list_type& local_edges() { return local_edges_; } Chris@16: const local_edge_list_type& local_edges() const { return local_edges_; } Chris@16: Chris@16: // Redistribute the vertices of the graph by placing each vertex Chris@16: // v on the processor get(vertex_to_processor, v). Chris@16: template Chris@16: void redistribute(VertexProcessorMap vertex_to_processor); Chris@16: Chris@16: // Directly access a vertex or edge bundle Chris@16: vertex_bundled& operator[](vertex_descriptor v) Chris@16: { Chris@16: BOOST_ASSERT(v.owner == processor()); Chris@16: return base()[v.local]; Chris@16: } Chris@16: Chris@16: const vertex_bundled& operator[](vertex_descriptor v) const Chris@16: { Chris@16: BOOST_ASSERT(v.owner == processor()); Chris@16: return base()[v.local]; Chris@16: } Chris@16: Chris@16: edge_bundled& operator[](edge_descriptor e) Chris@16: { Chris@16: BOOST_ASSERT(e.owner() == processor()); Chris@16: return base()[e.local]; Chris@16: } Chris@16: Chris@16: const edge_bundled& operator[](edge_descriptor e) const Chris@16: { Chris@16: BOOST_ASSERT(e.owner() == processor()); Chris@16: return base()[e.local]; Chris@16: } Chris@16: Chris@16: graph_bundled& operator[](graph_bundle_t) Chris@16: { return get_property(*this); } Chris@16: Chris@16: graph_bundled const& operator[](graph_bundle_t) const Chris@16: { return get_property(*this); } Chris@16: Chris@16: template Chris@16: void save(std::string const& filename) const; Chris@16: Chris@16: template Chris@16: void load(std::string const& filename); Chris@16: Chris@16: // Callback that will be invoked whenever a new vertex is added locally Chris@16: boost::function on_add_vertex; Chris@16: Chris@16: // Callback that will be invoked whenever a new edge is added locally Chris@16: boost::function on_add_edge; Chris@16: Chris@16: private: Chris@16: // Request vertex->processor mapping for neighbors Chris@16: template Chris@16: void Chris@16: request_in_neighbors(vertex_descriptor, Chris@16: VertexProcessorMap, Chris@16: directedS) { } Chris@16: Chris@16: // Request vertex->processor mapping for neighbors Chris@16: template Chris@16: void Chris@16: request_in_neighbors(vertex_descriptor, Chris@16: VertexProcessorMap, Chris@16: undirectedS) { } Chris@16: Chris@16: // Request vertex->processor mapping for neighbors Chris@16: template Chris@16: void Chris@16: request_in_neighbors(vertex_descriptor v, Chris@16: VertexProcessorMap vertex_to_processor, Chris@16: bidirectionalS); Chris@16: Chris@16: // Clear the list of in-edges, but don't tell the remote processor Chris@16: void clear_in_edges_local(vertex_descriptor v, directedS) {} Chris@16: void clear_in_edges_local(vertex_descriptor v, undirectedS) {} Chris@16: Chris@16: void clear_in_edges_local(vertex_descriptor v, bidirectionalS) Chris@16: { get(vertex_in_edges, base())[v.local].clear(); } Chris@16: Chris@16: // Remove in-edges that have migrated Chris@16: template Chris@16: void Chris@16: remove_migrated_in_edges(vertex_descriptor, Chris@16: VertexProcessorMap, Chris@16: directedS) { } Chris@16: Chris@16: // Remove in-edges that have migrated Chris@16: template Chris@16: void Chris@16: remove_migrated_in_edges(vertex_descriptor, Chris@16: VertexProcessorMap, Chris@16: undirectedS) { } Chris@16: Chris@16: // Remove in-edges that have migrated Chris@16: template Chris@16: void Chris@16: remove_migrated_in_edges(vertex_descriptor v, Chris@16: VertexProcessorMap vertex_to_processor, Chris@16: bidirectionalS); Chris@16: Chris@16: // Initialize the graph with the given edge list and vertex Chris@16: // distribution. This variation works only when Chris@16: // VertexListS=vecS, and we know how to create remote vertex Chris@16: // descriptors based solely on the distribution. Chris@16: template Chris@16: void Chris@16: initialize(EdgeIterator first, EdgeIterator last, Chris@16: vertices_size_type, const base_distribution_type& distribution, Chris@16: vecS); Chris@16: Chris@16: // Initialize the graph with the given edge list, edge Chris@16: // properties, and vertex distribution. This variation works Chris@16: // only when VertexListS=vecS, and we know how to create remote Chris@16: // vertex descriptors based solely on the distribution. Chris@16: template Chris@16: void Chris@16: initialize(EdgeIterator first, EdgeIterator last, Chris@16: EdgePropertyIterator ep_iter, Chris@16: vertices_size_type, const base_distribution_type& distribution, Chris@16: vecS); Chris@16: Chris@16: // Initialize the graph with the given edge list, edge Chris@16: // properties, and vertex distribution. Chris@16: template Chris@16: void Chris@16: initialize(EdgeIterator first, EdgeIterator last, Chris@16: EdgePropertyIterator ep_iter, Chris@16: vertices_size_type n, Chris@16: const base_distribution_type& distribution, Chris@16: VertexListS); Chris@16: Chris@16: // Initialize the graph with the given edge list and vertex Chris@16: // distribution. This is nearly identical to the one below it, Chris@16: // for which I should be flogged. However, this version does use Chris@16: // slightly less memory than the version that accepts an edge Chris@16: // property iterator. Chris@16: template Chris@16: void Chris@16: initialize(EdgeIterator first, EdgeIterator last, Chris@16: vertices_size_type n, Chris@16: const base_distribution_type& distribution, Chris@16: VertexListS); Chris@16: Chris@16: public: Chris@16: //--------------------------------------------------------------------- Chris@16: // Build a vertex property instance for the underlying adjacency Chris@16: // list from the given property instance of the type exposed to Chris@16: // the user. Chris@16: base_vertex_property_type Chris@16: build_vertex_property(const vertex_property_type& p) Chris@16: { return build_vertex_property(p, directed_selector()); } Chris@16: Chris@16: base_vertex_property_type Chris@16: build_vertex_property(const vertex_property_type& p, directedS) Chris@16: { Chris@16: return base_vertex_property_type(p); Chris@16: } Chris@16: Chris@16: base_vertex_property_type Chris@16: build_vertex_property(const vertex_property_type& p, bidirectionalS) Chris@16: { Chris@16: return base_vertex_property_type(in_edge_list_type(), p); Chris@16: } Chris@16: Chris@16: base_vertex_property_type Chris@16: build_vertex_property(const vertex_property_type& p, undirectedS) Chris@16: { Chris@16: return base_vertex_property_type(p); Chris@16: } Chris@16: //--------------------------------------------------------------------- Chris@16: Chris@16: //--------------------------------------------------------------------- Chris@16: // Build an edge property instance for the underlying adjacency Chris@16: // list from the given property instance of the type exposed to Chris@16: // the user. Chris@16: base_edge_property_type build_edge_property(const edge_property_type& p) Chris@16: { return build_edge_property(p, directed_selector()); } Chris@16: Chris@16: base_edge_property_type Chris@16: build_edge_property(const edge_property_type& p, directedS) Chris@16: { Chris@16: return base_edge_property_type(0, p); Chris@16: } Chris@16: Chris@16: base_edge_property_type Chris@16: build_edge_property(const edge_property_type& p, bidirectionalS) Chris@16: { Chris@16: return base_edge_property_type(0, p); Chris@16: } Chris@16: Chris@16: base_edge_property_type Chris@16: build_edge_property(const edge_property_type& p, undirectedS) Chris@16: { Chris@16: typedef typename base_edge_property_type::next_type Chris@16: edge_property_with_id; Chris@16: return base_edge_property_type(true, edge_property_with_id(0, p)); Chris@16: } Chris@16: //--------------------------------------------------------------------- Chris@16: Chris@16: //--------------------------------------------------------------------- Chris@16: // Opposite of above. Chris@16: edge_property_type split_edge_property(const base_edge_property_type& p) Chris@16: { return split_edge_property(p, directed_selector()); } Chris@16: Chris@16: edge_property_type Chris@16: split_edge_property(const base_edge_property_type& p, directedS) Chris@16: { Chris@16: return p.m_base; Chris@16: } Chris@16: Chris@16: edge_property_type Chris@16: split_edge_property(const base_edge_property_type& p, bidirectionalS) Chris@16: { Chris@16: return p.m_base; Chris@16: } Chris@16: Chris@16: edge_property_type Chris@16: split_edge_property(const base_edge_property_type& p, undirectedS) Chris@16: { Chris@16: return p.m_base.m_base; Chris@16: } Chris@16: //--------------------------------------------------------------------- Chris@16: Chris@16: /** The set of messages that can be transmitted and received by Chris@16: * a distributed adjacency list. This list will eventually be Chris@16: * exhaustive, but is currently quite limited. Chris@16: */ Chris@16: enum { Chris@16: /** Chris@16: * Request to add or find a vertex with the given vertex Chris@16: * property. The data will be a vertex_property_type Chris@16: * structure. Chris@16: */ Chris@16: msg_add_vertex_with_property = 0, Chris@16: Chris@16: /** Chris@16: * Request to add or find a vertex with the given vertex Chris@16: * property, and request that the remote processor return the Chris@16: * descriptor for the added/found edge. The data will be a Chris@16: * vertex_property_type structure. Chris@16: */ Chris@16: msg_add_vertex_with_property_and_reply, Chris@16: Chris@16: /** Chris@16: * Reply to a msg_add_vertex_* message, containing the local Chris@16: * vertex descriptor that was added or found. Chris@16: */ Chris@16: msg_add_vertex_reply, Chris@16: Chris@16: /** Chris@16: * Request to add an edge remotely. The data will be a Chris@16: * msg_add_edge_data structure. Chris@16: */ Chris@16: msg_add_edge, Chris@16: Chris@16: /** Chris@16: * Request to add an edge remotely. The data will be a Chris@16: * msg_add_edge_with_property_data structure. Chris@16: */ Chris@16: msg_add_edge_with_property, Chris@16: Chris@16: /** Chris@16: * Request to add an edge remotely and reply back with the Chris@16: * edge descriptor. The data will be a Chris@16: * msg_add_edge_data structure. Chris@16: */ Chris@16: msg_add_edge_with_reply, Chris@16: Chris@16: /** Chris@16: * Request to add an edge remotely and reply back with the Chris@16: * edge descriptor. The data will be a Chris@16: * msg_add_edge_with_property_data structure. Chris@16: */ Chris@16: msg_add_edge_with_property_and_reply, Chris@16: Chris@16: /** Chris@16: * Reply message responding to an @c msg_add_edge_with_reply Chris@16: * or @c msg_add_edge_with_property_and_reply messages. The Chris@16: * data will be a std::pair. Chris@16: */ Chris@16: msg_add_edge_reply, Chris@16: Chris@16: /** Chris@16: * Indicates that a nonlocal edge has been created that should Chris@16: * be added locally. Only valid for bidirectional and Chris@16: * undirected graphs. The message carries a Chris@16: * msg_nonlocal_edge_data structure. Chris@16: */ Chris@16: msg_nonlocal_edge, Chris@16: Chris@16: /** Chris@16: * Indicates that a remote edge should be removed. This Chris@16: * message does not exist for directedS graphs but may refer Chris@16: * to either in-edges or out-edges for undirectedS graphs. Chris@16: */ Chris@16: msg_remove_edge, Chris@16: Chris@16: /** Chris@16: * Indicates the number of vertices and edges that will be Chris@16: * relocated from the source processor to the target Chris@16: * processor. The data will be a pair. Chris@16: */ Chris@16: msg_num_relocated Chris@16: }; Chris@16: Chris@16: typedef detail::parallel::msg_add_edge_data Chris@16: msg_add_edge_data; Chris@16: Chris@16: typedef detail::parallel::msg_add_edge_with_property_data Chris@16: msg_add_edge_with_property_data; Chris@16: Chris@16: typedef boost::detail::parallel::msg_nonlocal_edge_data< Chris@16: edge_property_type,local_edge_descriptor> msg_nonlocal_edge_data; Chris@16: Chris@16: typedef boost::detail::parallel::msg_remove_edge_data Chris@16: msg_remove_edge_data; Chris@16: Chris@16: void send_remove_edge_request(edge_descriptor e) Chris@16: { Chris@16: process_id_type dest = e.target_processor; Chris@16: if (e.target_processor == process_id(process_group_)) Chris@16: dest = e.source_processor; Chris@16: send(process_group_, dest, msg_remove_edge, msg_remove_edge_data(e)); Chris@16: } Chris@16: Chris@16: /// Process incoming messages. Chris@16: void setup_triggers(); Chris@16: Chris@16: void Chris@16: handle_add_vertex_with_property(int source, int tag, Chris@16: const vertex_property_type&, Chris@16: trigger_receive_context); Chris@16: Chris@16: local_vertex_descriptor Chris@16: handle_add_vertex_with_property_and_reply(int source, int tag, Chris@16: const vertex_property_type&, Chris@16: trigger_receive_context); Chris@16: Chris@16: void Chris@16: handle_add_edge(int source, int tag, const msg_add_edge_data& data, Chris@16: trigger_receive_context); Chris@16: Chris@16: boost::parallel::detail::untracked_pair Chris@16: handle_add_edge_with_reply(int source, int tag, Chris@16: const msg_add_edge_data& data, Chris@16: trigger_receive_context); Chris@16: Chris@16: void Chris@16: handle_add_edge_with_property(int source, int tag, Chris@16: const msg_add_edge_with_property_data&, Chris@16: trigger_receive_context); Chris@16: Chris@16: boost::parallel::detail::untracked_pair Chris@16: handle_add_edge_with_property_and_reply Chris@16: (int source, int tag, const msg_add_edge_with_property_data&, Chris@16: trigger_receive_context); Chris@16: Chris@16: void Chris@16: handle_nonlocal_edge(int source, int tag, Chris@16: const msg_nonlocal_edge_data& data, Chris@16: trigger_receive_context); Chris@16: Chris@16: void Chris@16: handle_remove_edge(int source, int tag, Chris@16: const msg_remove_edge_data& data, Chris@16: trigger_receive_context); Chris@16: Chris@16: protected: Chris@16: /** Add an edge (locally) that was received from another Chris@16: * processor. This operation is a no-op for directed graphs, Chris@16: * because all edges reside on the local processor. For Chris@16: * bidirectional graphs, this routine places the edge onto the Chris@16: * list of incoming edges for the target vertex. For undirected Chris@16: * graphs, the edge is placed along with all of the other edges Chris@16: * for the target vertex, but it is marked as a non-local edge Chris@16: * descriptor. Chris@16: * Chris@16: * \todo There is a potential problem here, where we could Chris@16: * unintentionally allow duplicate edges in undirected graphs Chris@16: * because the same edge is added on two different processors Chris@16: * simultaneously. It's not an issue now, because we require Chris@16: * that the graph allow parallel edges. Once we do support Chris@16: * containers such as setS or hash_setS that disallow parallel Chris@16: * edges we will need to deal with this. Chris@16: */ Chris@16: void Chris@16: add_remote_edge(const msg_nonlocal_edge_data&, Chris@16: processor_id_type, directedS) Chris@16: { } Chris@16: Chris@16: Chris@16: /** Chris@16: * \overload Chris@16: */ Chris@16: void Chris@16: add_remote_edge(const msg_nonlocal_edge_data& data, Chris@16: processor_id_type other_proc, bidirectionalS) Chris@16: { Chris@16: typedef detail::parallel::stored_in_edge stored_edge; Chris@16: Chris@16: stored_edge edge(other_proc, data.e); Chris@16: local_vertex_descriptor v = target(data.e, base()); Chris@16: boost::graph_detail::push(get(vertex_in_edges, base())[v], edge); Chris@16: } Chris@16: Chris@16: /** Chris@16: * \overload Chris@16: */ Chris@16: void Chris@16: add_remote_edge(const msg_nonlocal_edge_data& data, Chris@16: processor_id_type other_proc, undirectedS) Chris@16: { Chris@16: std::pair edge = Chris@16: detail::parallel::add_local_edge(target(data.e, base()), Chris@16: source(data.e, base()), Chris@16: build_edge_property(data.get_property()), base()); Chris@16: BOOST_ASSERT(edge.second); Chris@16: put(edge_target_processor_id, base(), edge.first, other_proc); Chris@16: Chris@16: if (edge.second && on_add_edge) Chris@16: on_add_edge(edge_descriptor(processor(), other_proc, false, Chris@16: edge.first), Chris@16: *this); Chris@16: } Chris@16: Chris@16: void Chris@16: remove_local_edge(const msg_remove_edge_data&, processor_id_type, Chris@16: directedS) Chris@16: { } Chris@16: Chris@16: void Chris@16: remove_local_edge(const msg_remove_edge_data& data, Chris@16: processor_id_type other_proc, bidirectionalS) Chris@16: { Chris@16: /* When the source is local, we first check if the edge still Chris@16: * exists (it may have been deleted locally) and, if so, Chris@16: * remove it locally. Chris@16: */ Chris@16: vertex_descriptor src = source(data.e, *this); Chris@16: vertex_descriptor tgt = target(data.e, *this); Chris@16: Chris@16: if (src.owner == process_id(process_group_)) { Chris@16: base_out_edge_iterator ei, ei_end; Chris@16: for (boost::tie(ei, ei_end) = out_edges(src.local, base()); Chris@16: ei != ei_end; ++ei) { Chris@16: // TBD: can't check the descriptor here, because it could Chris@16: // have changed if we're allowing the removal of Chris@16: // edges. Egads! Chris@16: if (tgt.local == target(*ei, base()) Chris@16: && get(edge_target_processor_id, base(), *ei) == other_proc) Chris@16: break; Chris@16: } Chris@16: Chris@16: if (ei != ei_end) boost::remove_edge(ei, base()); Chris@16: Chris@16: remove_local_edge_from_list(src, tgt, undirectedS()); Chris@16: } else { Chris@16: BOOST_ASSERT(tgt.owner == process_id(process_group_)); Chris@16: in_edge_list_type& in_edges = Chris@16: get(vertex_in_edges, base())[tgt.local]; Chris@16: typename in_edge_list_type::iterator ei; Chris@16: for (ei = in_edges.begin(); ei != in_edges.end(); ++ei) { Chris@16: if (src.local == source(ei->e, base()) Chris@16: && src.owner == ei->source_processor) Chris@16: break; Chris@16: } Chris@16: Chris@16: if (ei != in_edges.end()) in_edges.erase(ei); Chris@16: } Chris@16: } Chris@16: Chris@16: void Chris@16: remove_local_edge(const msg_remove_edge_data& data, Chris@16: processor_id_type other_proc, undirectedS) Chris@16: { Chris@16: vertex_descriptor local_vertex = source(data.e, *this); Chris@16: vertex_descriptor remote_vertex = target(data.e, *this); Chris@16: if (remote_vertex.owner == process_id(process_group_)) { Chris@16: using std::swap; Chris@16: swap(local_vertex, remote_vertex); Chris@16: } Chris@16: Chris@16: // Remove the edge from the out-edge list, if it is there Chris@16: { Chris@16: base_out_edge_iterator ei, ei_end; Chris@16: for (boost::tie(ei, ei_end) = out_edges(local_vertex.local, base()); Chris@16: ei != ei_end; ++ei) { Chris@16: // TBD: can't check the descriptor here, because it could Chris@16: // have changed if we're allowing the removal of Chris@16: // edges. Egads! Chris@16: if (remote_vertex.local == target(*ei, base()) Chris@16: && get(edge_target_processor_id, base(), *ei) == other_proc) Chris@16: break; Chris@16: } Chris@16: Chris@16: if (ei != ei_end) boost::remove_edge(ei, base()); Chris@16: } Chris@16: Chris@16: remove_local_edge_from_list(local_vertex, remote_vertex, undirectedS()); Chris@16: } Chris@16: Chris@16: public: Chris@16: void Chris@16: remove_local_edge_from_list(vertex_descriptor, vertex_descriptor, Chris@16: directedS) Chris@16: { Chris@16: } Chris@16: Chris@16: void Chris@16: remove_local_edge_from_list(vertex_descriptor, vertex_descriptor, Chris@16: bidirectionalS) Chris@16: { Chris@16: } Chris@16: Chris@16: void Chris@16: remove_local_edge_from_list(vertex_descriptor src, vertex_descriptor tgt, Chris@16: undirectedS) Chris@16: { Chris@16: // TBD: At some point we'll be able to improve the speed here Chris@16: // because we'll know when the edge can't be in the local Chris@16: // list. Chris@16: { Chris@16: typename local_edge_list_type::iterator ei; Chris@16: for (ei = local_edges_.begin(); ei != local_edges_.end(); ++ei) { Chris@16: if ((source(*ei, *this) == src Chris@16: && target(*ei, *this) == tgt) Chris@16: || (source(*ei, *this) == tgt Chris@16: && target(*ei, *this) == src)) Chris@16: break; Chris@16: } Chris@16: Chris@16: if (ei != local_edges_.end()) local_edges_.erase(ei); Chris@16: } Chris@16: Chris@16: } Chris@16: Chris@16: private: Chris@16: /// The local subgraph Chris@16: inherited m_local_graph; Chris@16: Chris@16: /// The process group through which this distributed graph Chris@16: /// communicates. Chris@16: process_group_type process_group_; Chris@16: Chris@16: // TBD: should only be available for undirected graphs, but for Chris@16: // now it'll just be empty for directed and bidirectional Chris@16: // graphs. Chris@16: local_edge_list_type local_edges_; Chris@16: }; Chris@16: Chris@16: //------------------------------------------------------------------------ Chris@16: // Lazy addition of vertices Chris@16: template Chris@16: struct PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property Chris@16: { Chris@16: /// Construct a lazy request to add a vertex Chris@16: lazy_add_vertex_with_property(adjacency_list& self, Chris@16: const vertex_property_type& property) Chris@16: : self(self), property(property), committed(false) { } Chris@16: Chris@16: /// Copying a lazy_add_vertex_with_property transfers the Chris@16: /// responsibility for adding the vertex to the newly-constructed Chris@16: /// object. Chris@16: lazy_add_vertex_with_property(const lazy_add_vertex_with_property& other) Chris@16: : self(other.self), property(other.property), Chris@16: committed(other.committed) Chris@16: { Chris@16: other.committed = true; Chris@16: } Chris@16: Chris@16: /// If the vertex has not yet been added, add the vertex but don't Chris@16: /// wait for a reply. Chris@16: ~lazy_add_vertex_with_property(); Chris@16: Chris@16: /// Returns commit(). Chris@16: operator vertex_descriptor() const { return commit(); } Chris@16: Chris@16: // Add the vertex. This operation will block if the vertex is Chris@16: // being added remotely. Chris@16: vertex_descriptor commit() const; Chris@16: Chris@16: protected: Chris@16: adjacency_list& self; Chris@16: vertex_property_type property; Chris@16: mutable bool committed; Chris@16: Chris@16: private: Chris@16: // No copy-assignment semantics Chris@16: void operator=(lazy_add_vertex_with_property&); Chris@16: }; Chris@16: Chris@16: template Chris@16: PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property:: Chris@16: ~lazy_add_vertex_with_property() Chris@16: { Chris@16: /// If this vertex has already been created or will be created by Chris@16: /// someone else, or if someone threw an exception, we will not Chris@16: /// create the vertex now. Chris@16: if (committed || std::uncaught_exception()) Chris@16: return; Chris@16: Chris@16: committed = true; Chris@16: Chris@16: process_id_type owner Chris@16: = static_cast(self).owner_by_property(property); Chris@16: if (owner == self.processor()) { Chris@16: /// Add the vertex locally. Chris@16: vertex_descriptor v(owner, Chris@16: add_vertex(self.build_vertex_property(property), Chris@16: self.base())); Chris@16: if (self.on_add_vertex) Chris@16: self.on_add_vertex(v, self); Chris@16: } Chris@16: else Chris@16: /// Ask the owner of this new vertex to add the vertex. We Chris@16: /// don't need a reply. Chris@16: send(self.process_group_, owner, msg_add_vertex_with_property, Chris@16: property); Chris@16: } Chris@16: Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor Chris@16: PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property:: Chris@16: commit() const Chris@16: { Chris@16: BOOST_ASSERT(!this->committed); Chris@16: this->committed = true; Chris@16: Chris@16: process_id_type owner Chris@16: = static_cast(self).owner_by_property(property); Chris@16: local_vertex_descriptor local_v; Chris@16: if (owner == self.processor()) Chris@16: /// Add the vertex locally. Chris@16: local_v = add_vertex(self.build_vertex_property(property), Chris@16: self.base()); Chris@16: else { Chris@16: // Request that the remote process add the vertex immediately Chris@16: send_oob_with_reply(self.process_group_, owner, Chris@16: msg_add_vertex_with_property_and_reply, property, Chris@16: local_v); Chris@16: } Chris@16: Chris@16: vertex_descriptor v(owner, local_v); Chris@16: if (self.on_add_vertex) Chris@16: self.on_add_vertex(v, self); Chris@16: Chris@16: // Build the full vertex descriptor to return Chris@16: return v; Chris@16: } Chris@16: Chris@16: Chris@16: /** Chris@16: * Data structure returned from add_edge that will "lazily" add Chris@16: * the edge, either when it is converted to a Chris@16: * @c pair or when the most recent copy has Chris@16: * been destroyed. Chris@16: */ Chris@16: template Chris@16: struct PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge Chris@16: { Chris@16: /// Construct a lazy request to add an edge Chris@16: lazy_add_edge(adjacency_list& self, Chris@16: vertex_descriptor source, vertex_descriptor target) Chris@16: : self(self), source(source), target(target), committed(false) { } Chris@16: Chris@16: /// Copying a lazy_add_edge transfers the responsibility for Chris@16: /// adding the edge to the newly-constructed object. Chris@16: lazy_add_edge(const lazy_add_edge& other) Chris@16: : self(other.self), source(other.source), target(other.target), Chris@16: committed(other.committed) Chris@16: { Chris@16: other.committed = true; Chris@16: } Chris@16: Chris@16: /// If the edge has not yet been added, add the edge but don't Chris@16: /// wait for a reply. Chris@16: ~lazy_add_edge(); Chris@16: Chris@16: /// Returns commit(). Chris@16: operator std::pair() const { return commit(); } Chris@16: Chris@16: // Add the edge. This operation will block if a remote edge is Chris@16: // being added. Chris@16: std::pair commit() const; Chris@16: Chris@16: protected: Chris@16: std::pair Chris@16: add_local_edge(const edge_property_type& property, directedS) const; Chris@16: Chris@16: std::pair Chris@16: add_local_edge(const edge_property_type& property, bidirectionalS) const; Chris@16: Chris@16: std::pair Chris@16: add_local_edge(const edge_property_type& property, undirectedS) const; Chris@16: Chris@16: adjacency_list& self; Chris@16: vertex_descriptor source; Chris@16: vertex_descriptor target; Chris@16: mutable bool committed; Chris@16: Chris@16: private: Chris@16: // No copy-assignment semantics Chris@16: void operator=(lazy_add_edge&); Chris@16: }; Chris@16: Chris@16: template Chris@16: PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::~lazy_add_edge() Chris@16: { Chris@16: /// If this edge has already been created or will be created by Chris@16: /// someone else, or if someone threw an exception, we will not Chris@16: /// create the edge now. Chris@16: if (committed || std::uncaught_exception()) Chris@16: return; Chris@16: Chris@16: committed = true; Chris@16: Chris@16: if (source.owner == self.processor()) Chris@16: this->add_local_edge(edge_property_type(), DirectedS()); Chris@16: else Chris@16: // Request that the remote processor add an edge and, but Chris@16: // don't wait for a reply. Chris@16: send(self.process_group_, source.owner, msg_add_edge, Chris@16: msg_add_edge_data(source, target)); Chris@16: } Chris@16: Chris@16: template Chris@16: std::pair Chris@16: PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge::commit() const Chris@16: { Chris@16: BOOST_ASSERT(!committed); Chris@16: committed = true; Chris@16: Chris@16: if (source.owner == self.processor()) Chris@16: return this->add_local_edge(edge_property_type(), DirectedS()); Chris@16: else { Chris@16: // Request that the remote processor add an edge Chris@16: boost::parallel::detail::untracked_pair result; Chris@16: send_oob_with_reply(self.process_group_, source.owner, Chris@16: msg_add_edge_with_reply, Chris@16: msg_add_edge_data(source, target), result); Chris@16: return result; Chris@16: } Chris@16: } Chris@16: Chris@16: // Add a local edge into a directed graph Chris@16: template Chris@16: std::pair Chris@16: PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge:: Chris@16: add_local_edge(const edge_property_type& property, directedS) const Chris@16: { Chris@16: // Add the edge to the local part of the graph Chris@16: std::pair inserted = Chris@16: detail::parallel::add_local_edge(source.local, target.local, Chris@16: self.build_edge_property(property), Chris@16: self.base()); Chris@16: Chris@16: if (inserted.second) Chris@16: // Keep track of the owner of the target Chris@16: put(edge_target_processor_id, self.base(), inserted.first, Chris@16: target.owner); Chris@16: Chris@16: // Compose the edge descriptor and return the result Chris@16: edge_descriptor e(source.owner, target.owner, true, inserted.first); Chris@16: Chris@16: // Trigger the on_add_edge event Chris@16: if (inserted.second && self.on_add_edge) Chris@16: self.on_add_edge(e, self); Chris@16: Chris@16: return std::pair(e, inserted.second); Chris@16: } Chris@16: Chris@16: template Chris@16: std::pair Chris@16: PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge:: Chris@16: add_local_edge(const edge_property_type& property, bidirectionalS) const Chris@16: { Chris@16: // Add the directed edge. Chris@16: std::pair result Chris@16: = this->add_local_edge(property, directedS()); Chris@16: Chris@16: if (result.second) { Chris@16: if (target.owner == self.processor()) { Chris@16: // Edge is local, so add the stored edge to the in_edges list Chris@16: typedef detail::parallel::stored_in_edge Chris@16: stored_edge; Chris@16: Chris@16: stored_edge e(self.processor(), result.first.local); Chris@16: boost::graph_detail::push(get(vertex_in_edges, Chris@16: self.base())[target.local], e); Chris@16: } Chris@16: else { Chris@16: // Edge is remote, so notify the target's owner that an edge Chris@16: // has been added. Chris@101: if (self.process_group_.trigger_context() == boost::parallel::trc_out_of_band) Chris@16: send_oob(self.process_group_, target.owner, msg_nonlocal_edge, Chris@16: msg_nonlocal_edge_data(result.first.local, property)); Chris@16: else Chris@16: send(self.process_group_, target.owner, msg_nonlocal_edge, Chris@16: msg_nonlocal_edge_data(result.first.local, property)); Chris@16: } Chris@16: } Chris@16: Chris@16: return result; Chris@16: } Chris@16: Chris@16: template Chris@16: std::pair Chris@16: PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge:: Chris@16: add_local_edge(const edge_property_type& property, undirectedS) const Chris@16: { Chris@16: // Add the directed edge Chris@16: std::pair result Chris@16: = this->add_local_edge(property, directedS()); Chris@16: Chris@16: if (result.second) { Chris@16: if (target.owner == self.processor()) { Chris@16: // Edge is local, so add the new edge to the list Chris@16: Chris@16: // TODO: This is not what we want to do for an undirected Chris@16: // edge, because we haven't linked the source and target's Chris@16: // representations of those edges. Chris@16: local_edge_descriptor return_edge = Chris@16: detail::parallel::add_local_edge(target.local, source.local, Chris@16: self.build_edge_property(property), Chris@16: self.base()).first; Chris@16: Chris@16: put(edge_target_processor_id, self.base(), return_edge, Chris@16: source.owner); Chris@16: } Chris@16: else { Chris@16: // Edge is remote, so notify the target's owner that an edge Chris@16: // has been added. Chris@101: if (self.process_group_.trigger_context() == boost::parallel::trc_out_of_band) Chris@16: send_oob(self.process_group_, target.owner, msg_nonlocal_edge, Chris@16: msg_nonlocal_edge_data(result.first.local, property)); Chris@16: else Chris@16: send(self.process_group_, target.owner, msg_nonlocal_edge, Chris@16: msg_nonlocal_edge_data(result.first.local, property)); Chris@16: Chris@16: } Chris@16: Chris@16: // Add this edge to the list of local edges Chris@16: graph_detail::push(self.local_edges(), result.first); Chris@16: } Chris@16: Chris@16: return result; Chris@16: } Chris@16: Chris@16: Chris@16: /** Chris@16: * Data structure returned from add_edge that will "lazily" add Chris@16: * the edge with its property, either when it is converted to a Chris@16: * pair or when the most recent copy has Chris@16: * been destroyed. Chris@16: */ Chris@16: template Chris@16: struct PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge_with_property Chris@16: : lazy_add_edge Chris@16: { Chris@16: /// Construct a lazy request to add an edge Chris@16: lazy_add_edge_with_property(adjacency_list& self, Chris@16: vertex_descriptor source, Chris@16: vertex_descriptor target, Chris@16: const edge_property_type& property) Chris@16: : lazy_add_edge(self, source, target), property(property) { } Chris@16: Chris@16: /// Copying a lazy_add_edge transfers the responsibility for Chris@16: /// adding the edge to the newly-constructed object. Chris@16: lazy_add_edge_with_property(const lazy_add_edge& other) Chris@16: : lazy_add_edge(other), property(other.property) { } Chris@16: Chris@16: /// If the edge has not yet been added, add the edge but don't Chris@16: /// wait for a reply. Chris@16: ~lazy_add_edge_with_property(); Chris@16: Chris@16: /// Returns commit(). Chris@16: operator std::pair() const { return commit(); } Chris@16: Chris@16: // Add the edge. This operation will block if a remote edge is Chris@16: // being added. Chris@16: std::pair commit() const; Chris@16: Chris@16: private: Chris@16: // No copy-assignment semantics Chris@16: void operator=(lazy_add_edge_with_property&); Chris@16: Chris@16: edge_property_type property; Chris@16: }; Chris@16: Chris@16: template Chris@16: PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge_with_property:: Chris@16: ~lazy_add_edge_with_property() Chris@16: { Chris@16: /// If this edge has already been created or will be created by Chris@16: /// someone else, or if someone threw an exception, we will not Chris@16: /// create the edge now. Chris@16: if (this->committed || std::uncaught_exception()) Chris@16: return; Chris@16: Chris@16: this->committed = true; Chris@16: Chris@16: if (this->source.owner == this->self.processor()) Chris@16: // Add a local edge Chris@16: this->add_local_edge(property, DirectedS()); Chris@16: else Chris@16: // Request that the remote processor add an edge and, but Chris@16: // don't wait for a reply. Chris@16: send(this->self.process_group_, this->source.owner, Chris@16: msg_add_edge_with_property, Chris@16: msg_add_edge_with_property_data(this->source, this->target, Chris@16: property)); Chris@16: } Chris@16: Chris@16: template Chris@16: std::pair Chris@16: PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge_with_property:: Chris@16: commit() const Chris@16: { Chris@16: BOOST_ASSERT(!this->committed); Chris@16: this->committed = true; Chris@16: Chris@16: if (this->source.owner == this->self.processor()) Chris@16: // Add a local edge Chris@16: return this->add_local_edge(property, DirectedS()); Chris@16: else { Chris@16: // Request that the remote processor add an edge Chris@16: boost::parallel::detail::untracked_pair result; Chris@16: send_oob_with_reply(this->self.process_group_, this->source.owner, Chris@16: msg_add_edge_with_property_and_reply, Chris@16: msg_add_edge_with_property_data(this->source, Chris@16: this->target, Chris@16: property), Chris@16: result); Chris@16: return result; Chris@16: } Chris@16: } Chris@16: Chris@16: Chris@16: /** Chris@16: * Returns the set of vertices local to this processor. Note that Chris@16: * although this routine matches a valid expression of a Chris@16: * VertexListGraph, it does not meet the semantic requirements of Chris@16: * VertexListGraph because it returns only local vertices (not all Chris@16: * vertices). Chris@16: */ Chris@16: template Chris@16: std::pair Chris@16: vertices(const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE Chris@16: ::vertex_descriptor Vertex; Chris@16: Chris@16: typedef typename Vertex::generator generator; Chris@16: Chris@16: return std::make_pair(make_transform_iterator(vertices(g.base()).first, Chris@16: generator(g.processor())), Chris@16: make_transform_iterator(vertices(g.base()).second, Chris@16: generator(g.processor()))); Chris@16: } Chris@16: Chris@16: /** Chris@16: * Returns the number of vertices local to this processor. Note that Chris@16: * although this routine matches a valid expression of a Chris@16: * VertexListGraph, it does not meet the semantic requirements of Chris@16: * VertexListGraph because it returns only a count of local vertices Chris@16: * (not all vertices). Chris@16: */ Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE Chris@16: ::vertices_size_type Chris@16: num_vertices(const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: return num_vertices(g.base()); Chris@16: } Chris@16: Chris@16: /*************************************************************************** Chris@16: * Implementation of Incidence Graph concept Chris@16: ***************************************************************************/ Chris@16: /** Chris@16: * Returns the source of edge @param e in @param g. Chris@16: */ Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor Chris@16: source(const detail::parallel::edge_descriptor& e, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE Chris@16: ::vertex_descriptor Vertex; Chris@16: return Vertex(e.source_processor, source(e.local, g.base())); Chris@16: } Chris@16: Chris@16: /** Chris@16: * Returns the target of edge @param e in @param g. Chris@16: */ Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor Chris@16: target(const detail::parallel::edge_descriptor& e, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE Chris@16: ::vertex_descriptor Vertex; Chris@16: return Vertex(e.target_processor, target(e.local, g.base())); Chris@16: } Chris@16: Chris@16: /** Chris@16: * Return the set of edges outgoing from a particular vertex. The Chris@16: * vertex @param v must be local to the processor executing this Chris@16: * routine. Chris@16: */ Chris@16: template Chris@16: std::pair Chris@16: out_edges(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: BOOST_ASSERT(v.owner == g.processor()); Chris@16: Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE impl; Chris@16: typedef typename impl::out_edge_generator generator; Chris@16: Chris@16: return std::make_pair( Chris@16: make_transform_iterator(out_edges(v.local, g.base()).first, Chris@16: generator(g)), Chris@16: make_transform_iterator(out_edges(v.local, g.base()).second, Chris@16: generator(g))); Chris@16: } Chris@16: Chris@16: /** Chris@16: * Return the number of edges outgoing from a particular vertex. The Chris@16: * vertex @param v must be local to the processor executing this Chris@16: * routine. Chris@16: */ Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::degree_size_type Chris@16: out_degree(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: BOOST_ASSERT(v.owner == g.processor()); Chris@16: Chris@16: return out_degree(v.local, g.base()); Chris@16: } Chris@16: Chris@16: /*************************************************************************** Chris@16: * Implementation of Bidirectional Graph concept Chris@16: ***************************************************************************/ Chris@16: /** Chris@16: * Returns the set of edges incoming to a particular vertex. The Chris@16: * vertex @param v must be local to the processor executing this Chris@16: * routine. Chris@16: */ Chris@16: template Chris@16: std::pair Chris@16: in_edges(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Chris@16: ::vertex_descriptor v, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g) Chris@16: { Chris@16: BOOST_ASSERT(v.owner == g.processor()); Chris@16: Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) impl; Chris@16: typedef typename impl::inherited base_graph_type; Chris@16: typedef typename impl::in_edge_generator generator; Chris@16: Chris@16: Chris@16: typename property_map::const_type Chris@16: in_edges = get(vertex_in_edges, g.base()); Chris@16: Chris@16: return std::make_pair(make_transform_iterator(in_edges[v.local].begin(), Chris@16: generator(g)), Chris@16: make_transform_iterator(in_edges[v.local].end(), Chris@16: generator(g))); Chris@16: } Chris@16: Chris@16: /** Chris@16: * \overload Chris@16: */ Chris@16: template Chris@16: std::pair Chris@16: in_edges(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) Chris@16: ::vertex_descriptor v, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g) Chris@16: { Chris@16: BOOST_ASSERT(v.owner == g.processor()); Chris@16: Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) impl; Chris@16: typedef typename impl::in_edge_generator generator; Chris@16: Chris@16: return std::make_pair( Chris@16: make_transform_iterator(out_edges(v.local, g.base()).first, Chris@16: generator(g)), Chris@16: make_transform_iterator(out_edges(v.local, g.base()).second, Chris@16: generator(g))); Chris@16: } Chris@16: Chris@16: /** Chris@16: * Returns the number of edges incoming to a particular vertex. The Chris@16: * vertex @param v must be local to the processor executing this Chris@16: * routine. Chris@16: */ Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)::degree_size_type Chris@16: in_degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Chris@16: ::vertex_descriptor v, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g) Chris@16: { Chris@16: BOOST_ASSERT(v.owner == g.processor()); Chris@16: Chris@16: return get(vertex_in_edges, g.base())[v.local].size(); Chris@16: } Chris@16: Chris@16: /** Chris@16: * \overload Chris@16: */ Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::degree_size_type Chris@16: in_degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) Chris@16: ::vertex_descriptor v, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g) Chris@16: { Chris@16: BOOST_ASSERT(v.owner == g.processor()); Chris@16: Chris@16: return out_degree(v.local, g.base()); Chris@16: } Chris@16: Chris@16: /** Chris@16: * Returns the number of edges incident on the given vertex. The Chris@16: * vertex @param v must be local to the processor executing this Chris@16: * routine. Chris@16: */ Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) Chris@16: ::degree_size_type Chris@16: degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) Chris@16: ::vertex_descriptor v, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g) Chris@16: { Chris@16: BOOST_ASSERT(v.owner == g.processor()); Chris@16: return out_degree(v.local, g.base()); Chris@16: } Chris@16: Chris@16: /** Chris@16: * \overload Chris@16: */ Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Chris@16: ::degree_size_type Chris@16: degree(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Chris@16: ::vertex_descriptor v, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g) Chris@16: { Chris@16: BOOST_ASSERT(v.owner == g.processor()); Chris@16: return out_degree(v, g) + in_degree(v, g); Chris@16: } Chris@16: Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::edges_size_type Chris@16: num_edges(const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: return num_edges(g.base()); Chris@16: } Chris@16: Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::edges_size_type Chris@16: num_edges(const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g) Chris@16: { Chris@16: return g.local_edges().size(); Chris@16: } Chris@16: Chris@16: template Chris@16: std::pair< Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::edge_iterator, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::edge_iterator> Chris@16: edges(const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE impl; Chris@16: typedef typename impl::out_edge_generator generator; Chris@16: Chris@16: return std::make_pair(make_transform_iterator(edges(g.base()).first, Chris@16: generator(g)), Chris@16: make_transform_iterator(edges(g.base()).second, Chris@16: generator(g))); Chris@16: } Chris@16: Chris@16: template Chris@16: std::pair< Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::edge_iterator, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)::edge_iterator> Chris@16: edges(const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g) Chris@16: { Chris@16: return std::make_pair(g.local_edges().begin(), g.local_edges().end()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor Chris@16: vertex(typename PBGL_DISTRIB_ADJLIST_TYPE::vertices_size_type n, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor Chris@16: vertex_descriptor; Chris@16: Chris@16: return vertex_descriptor(g.distribution()(n), g.distribution().local(n)); Chris@16: } Chris@16: Chris@16: /*************************************************************************** Chris@16: * Access to particular edges Chris@16: ***************************************************************************/ Chris@16: template Chris@16: std::pair< Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::edge_descriptor, Chris@16: bool Chris@16: > Chris@16: edge(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::vertex_descriptor u, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::vertex_descriptor v, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS) Chris@16: ::edge_descriptor edge_descriptor; Chris@16: Chris@16: // For directed graphs, u must be local Chris@16: BOOST_ASSERT(u.owner == process_id(g.process_group())); Chris@16: Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS) Chris@16: ::out_edge_iterator ei, ei_end; Chris@16: for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) { Chris@16: if (target(*ei, g) == v) return std::make_pair(*ei, true); Chris@16: } Chris@16: return std::make_pair(edge_descriptor(), false); Chris@16: } Chris@16: Chris@16: template Chris@16: std::pair< Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor, Chris@16: bool Chris@16: > Chris@16: edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE Chris@16: ::edge_descriptor edge_descriptor; Chris@16: Chris@16: // For bidirectional and undirected graphs, u must be local or v Chris@16: // must be local Chris@16: if (u.owner == process_id(g.process_group())) { Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::out_edge_iterator ei, ei_end; Chris@16: for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) { Chris@16: if (target(*ei, g) == v) return std::make_pair(*ei, true); Chris@16: } Chris@16: return std::make_pair(edge_descriptor(), false); Chris@16: } else if (v.owner == process_id(g.process_group())) { Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::in_edge_iterator ei, ei_end; Chris@16: for (boost::tie(ei, ei_end) = in_edges(v, g); ei != ei_end; ++ei) { Chris@16: if (source(*ei, g) == u) return std::make_pair(*ei, true); Chris@16: } Chris@16: return std::make_pair(edge_descriptor(), false); Chris@16: } else { Chris@16: BOOST_ASSERT(false); Chris@16: abort(); Chris@16: } Chris@16: } Chris@16: Chris@16: #if 0 Chris@16: // TBD: not yet supported Chris@16: std::pair Chris@16: edge_range(vertex_descriptor u, vertex_descriptor v, Chris@16: const adjacency_list& g); Chris@16: #endif Chris@16: Chris@16: /*************************************************************************** Chris@16: * Implementation of Adjacency Graph concept Chris@16: ***************************************************************************/ Chris@16: template Chris@16: std::pair Chris@16: adjacent_vertices(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v, Chris@16: const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE::adjacency_iterator iter; Chris@16: return std::make_pair(iter(out_edges(v, g).first, &g), Chris@16: iter(out_edges(v, g).second, &g)); Chris@16: } Chris@16: Chris@16: /*************************************************************************** Chris@16: * Implementation of Mutable Graph concept Chris@16: ***************************************************************************/ Chris@16: Chris@16: /************************************************************************ Chris@16: * add_edge Chris@16: ************************************************************************/ Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge Chris@16: add_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_edge lazy_add_edge; Chris@16: Chris@16: return lazy_add_edge(g, u, v); Chris@16: } Chris@16: Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE Chris@16: ::lazy_add_edge_with_property Chris@16: add_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::edge_property_type const& p, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE Chris@16: ::lazy_add_edge_with_property lazy_add_edge_with_property; Chris@16: return lazy_add_edge_with_property(g, u, v, p); Chris@16: } Chris@16: Chris@16: /************************************************************************ Chris@16: * Chris@16: * remove_edge Chris@16: * Chris@16: ************************************************************************/ Chris@16: template Chris@16: void Chris@16: remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::edge_descriptor e, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: BOOST_ASSERT(source(e, g).owner == g.processor() Chris@16: || target(e, g).owner == g.processor()); Chris@16: Chris@16: if (target(e, g).owner == g.processor()) Chris@16: detail::parallel::remove_in_edge(e, g, DirectedS()); Chris@16: if (source(e, g).owner == g.processor()) Chris@16: remove_edge(e.local, g.base()); Chris@16: Chris@16: g.remove_local_edge_from_list(source(e, g), target(e, g), DirectedS()); Chris@16: Chris@16: if (source(e, g).owner != g.processor() Chris@16: || (target(e, g).owner != g.processor() Chris@16: && !(is_same::value))) { Chris@16: g.send_remove_edge_request(e); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void Chris@16: remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE Chris@16: ::edge_descriptor edge_descriptor; Chris@16: std::pair the_edge = edge(u, v, g); Chris@16: if (the_edge.second) remove_edge(the_edge.first, g); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void Chris@16: remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE::out_edge_iterator ei, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: remove_edge(*ei, g); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void Chris@16: remove_edge(typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS) Chris@16: ::out_edge_iterator ei, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g) Chris@16: { Chris@16: BOOST_ASSERT(source(*ei, g).owner == g.processor()); Chris@16: remove_edge(ei->local, g.base()); Chris@16: } Chris@16: Chris@16: /************************************************************************ Chris@16: * Chris@16: * remove_out_edge_if Chris@16: * Chris@16: ************************************************************************/ Chris@16: namespace parallel { namespace detail { Chris@16: /** Chris@16: * Function object that applies the underlying predicate to Chris@16: * determine if an out-edge should be removed. If so, either Chris@16: * removes the incoming edge (if it is stored locally) or sends a Chris@16: * message to the owner of the target requesting that it remove Chris@16: * the edge. Chris@16: */ Chris@16: template Chris@16: struct remove_out_edge_predicate Chris@16: { Chris@16: typedef typename graph_traits::edge_descriptor edge_descriptor; Chris@16: typedef typename Graph::local_edge_descriptor argument_type; Chris@16: typedef typename Graph::directed_selector directed_selector; Chris@16: typedef bool result_type; Chris@16: Chris@16: remove_out_edge_predicate(Graph& g, Predicate& predicate) Chris@16: : g(g), predicate(predicate) { } Chris@16: Chris@16: bool operator()(const argument_type& le) Chris@16: { Chris@16: typedef typename edge_descriptor::template out_generator Chris@16: generator; Chris@16: Chris@16: edge_descriptor e = generator(g)(le); Chris@16: Chris@16: if (predicate(e)) { Chris@16: if (source(e, g).owner != target(e, g).owner Chris@16: && !(is_same::value)) Chris@16: g.send_remove_edge_request(e); Chris@16: else Chris@16: ::boost::detail::parallel::remove_in_edge(e, g, Chris@16: directed_selector()); Chris@16: Chris@16: g.remove_local_edge_from_list(source(e, g), target(e, g), Chris@16: directed_selector()); Chris@16: return true; Chris@16: } else return false; Chris@16: } Chris@16: Chris@16: private: Chris@16: Graph& g; Chris@16: Predicate predicate; Chris@16: }; Chris@16: } } // end namespace parallel::detail Chris@16: Chris@16: template Chris@16: inline void Chris@16: remove_out_edge_if Chris@16: (typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u, Chris@16: Predicate predicate, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE Graph; Chris@16: typedef parallel::detail::remove_out_edge_predicate Chris@16: Pred; Chris@16: Chris@16: BOOST_ASSERT(u.owner == g.processor()); Chris@16: remove_out_edge_if(u.local, Pred(g, predicate), g.base()); Chris@16: } Chris@16: Chris@16: /************************************************************************ Chris@16: * Chris@16: * remove_in_edge_if Chris@16: * Chris@16: ************************************************************************/ Chris@16: namespace parallel { namespace detail { Chris@16: /** Chris@16: * Function object that applies the underlying predicate to Chris@16: * determine if an in-edge should be removed. If so, either Chris@16: * removes the outgoing edge (if it is stored locally) or sends a Chris@16: * message to the owner of the target requesting that it remove Chris@16: * the edge. Only required for bidirectional graphs. Chris@16: */ Chris@16: template Chris@16: struct remove_in_edge_predicate Chris@16: { Chris@16: typedef typename graph_traits::edge_descriptor edge_descriptor; Chris@16: typedef bool result_type; Chris@16: Chris@16: remove_in_edge_predicate(Graph& g, const Predicate& predicate) Chris@16: : g(g), predicate(predicate) { } Chris@16: Chris@16: template Chris@16: bool operator()(const StoredEdge& le) Chris@16: { Chris@16: typedef typename edge_descriptor::template in_generator Chris@16: generator; Chris@16: Chris@16: edge_descriptor e = generator(g)(le); Chris@16: Chris@16: if (predicate(e)) { Chris@16: if (source(e, g).owner != target(e, g).owner) Chris@16: g.send_remove_edge_request(e); Chris@16: else Chris@16: remove_edge(source(e, g).local, target(e, g).local, g.base()); Chris@16: return true; Chris@16: } else return false; Chris@16: } Chris@16: Chris@16: private: Chris@16: Graph& g; Chris@16: Predicate predicate; Chris@16: }; Chris@16: } } // end namespace parallel::detail Chris@16: Chris@16: template Chris@16: inline void Chris@16: remove_in_edge_if Chris@16: (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Chris@16: ::vertex_descriptor u, Chris@16: Predicate predicate, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Graph; Chris@16: typedef parallel::detail::remove_in_edge_predicate Chris@16: Pred; Chris@16: Chris@16: BOOST_ASSERT(u.owner == g.processor()); Chris@16: graph_detail::erase_if(get(vertex_in_edges, g.base())[u.local], Chris@16: Pred(g, predicate)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void Chris@16: remove_in_edge_if Chris@16: (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) Chris@16: ::vertex_descriptor u, Chris@16: Predicate predicate, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g) Chris@16: { Chris@16: remove_out_edge_if(u, predicate, g); Chris@16: } Chris@16: Chris@16: /************************************************************************ Chris@16: * Chris@16: * remove_edge_if Chris@16: * Chris@16: ************************************************************************/ Chris@16: namespace parallel { namespace detail { Chris@16: /** Chris@16: * Function object that applies the underlying predicate to Chris@16: * determine if a directed edge can be removed. This only applies Chris@16: * to directed graphs. Chris@16: */ Chris@16: template Chris@16: struct remove_directed_edge_predicate Chris@16: { Chris@16: typedef typename Graph::local_edge_descriptor argument_type; Chris@16: typedef typename graph_traits::edge_descriptor edge_descriptor; Chris@16: typedef bool result_type; Chris@16: Chris@16: remove_directed_edge_predicate(Graph& g, const Predicate& predicate) Chris@16: : g(g), predicate(predicate) { } Chris@16: Chris@16: bool operator()(const argument_type& le) Chris@16: { Chris@16: typedef typename edge_descriptor::template out_generator Chris@16: generator; Chris@16: Chris@16: edge_descriptor e = generator(g)(le); Chris@16: return predicate(e); Chris@16: } Chris@16: Chris@16: private: Chris@16: Graph& g; Chris@16: Predicate predicate; Chris@16: }; Chris@16: } } // end namespace parallel::detail Chris@16: Chris@16: template Chris@16: inline void Chris@16: remove_edge_if(Predicate predicate, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS) Graph; Chris@16: typedef parallel::detail::remove_directed_edge_predicate Pred; Chris@16: remove_edge_if(Pred(g, predicate), g.base()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void Chris@16: remove_edge_if(Predicate predicate, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Graph; Chris@16: typedef parallel::detail::remove_out_edge_predicate Pred; Chris@16: remove_edge_if(Pred(g, predicate), g.base()); Chris@16: } Chris@16: Chris@16: namespace parallel { namespace detail { Chris@16: /** Chris@16: * Function object that applies the underlying predicate to Chris@16: * determine if an undirected edge should be removed. If so, Chris@16: * removes the local edges associated with the edge and Chris@16: * (potentially) sends a message to the remote processor that also Chris@16: * is removing this edge. Chris@16: */ Chris@16: template Chris@16: struct remove_undirected_edge_predicate Chris@16: { Chris@16: typedef typename graph_traits::edge_descriptor argument_type; Chris@16: typedef bool result_type; Chris@16: Chris@16: remove_undirected_edge_predicate(Graph& g, Predicate& predicate) Chris@16: : g(g), predicate(predicate) { } Chris@16: Chris@16: bool operator()(const argument_type& e) Chris@16: { Chris@16: if (predicate(e)) { Chris@16: if (source(e, g).owner != target(e, g).owner) Chris@16: g.send_remove_edge_request(e); Chris@16: if (target(e, g).owner == g.processor()) Chris@16: ::boost::detail::parallel::remove_in_edge(e, g, undirectedS()); Chris@16: if (source(e, g).owner == g.processor()) Chris@16: remove_edge(e.local, g.base()); Chris@16: return true; Chris@16: } else return false; Chris@16: } Chris@16: Chris@16: private: Chris@16: Graph& g; Chris@16: Predicate predicate; Chris@16: }; Chris@16: } } // end namespace parallel::detail Chris@16: Chris@16: template Chris@16: inline void Chris@16: remove_edge_if(Predicate predicate, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) Graph; Chris@16: typedef parallel::detail::remove_undirected_edge_predicate Pred; Chris@16: graph_detail::erase_if(g.local_edges(), Pred(g, predicate)); Chris@16: } Chris@16: Chris@16: /************************************************************************ Chris@16: * Chris@16: * clear_vertex Chris@16: * Chris@16: ************************************************************************/ Chris@16: namespace parallel { namespace detail { Chris@16: struct always_true Chris@16: { Chris@16: typedef bool result_type; Chris@16: Chris@16: template bool operator()(const T&) const { return true; } Chris@16: }; Chris@16: } } // end namespace parallel::detail Chris@16: Chris@16: template Chris@16: void Chris@16: clear_vertex Chris@16: (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Chris@16: ::vertex_descriptor u, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g) Chris@16: { Chris@16: clear_out_edges(u, g); Chris@16: clear_in_edges(u, g); Chris@16: } Chris@16: Chris@16: template Chris@16: void Chris@16: clear_vertex Chris@16: (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS) Chris@16: ::vertex_descriptor u, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(undirectedS)& g) Chris@16: { Chris@16: remove_out_edge_if(u, parallel::detail::always_true(), g); Chris@16: } Chris@16: Chris@16: /************************************************************************ Chris@16: * Chris@16: * clear_out_edges Chris@16: * Chris@16: ************************************************************************/ Chris@16: template Chris@16: void Chris@16: clear_out_edges Chris@16: (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)::vertex_descriptor u, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(directedS)& g) Chris@16: { Chris@16: BOOST_ASSERT(u.owner == g.processor()); Chris@16: clear_out_edges(u.local, g.base()); Chris@16: } Chris@16: Chris@16: template Chris@16: void Chris@16: clear_out_edges Chris@16: (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Chris@16: ::vertex_descriptor u, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g) Chris@16: { Chris@16: remove_out_edge_if(u, parallel::detail::always_true(), g); Chris@16: } Chris@16: Chris@16: /************************************************************************ Chris@16: * Chris@16: * clear_in_edges Chris@16: * Chris@16: ************************************************************************/ Chris@16: template Chris@16: void Chris@16: clear_in_edges Chris@16: (typename PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS) Chris@16: ::vertex_descriptor u, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE_CONFIG(bidirectionalS)& g) Chris@16: { Chris@16: remove_in_edge_if(u, parallel::detail::always_true(), g); Chris@16: } Chris@16: Chris@16: /************************************************************************ Chris@16: * Chris@16: * add_vertex Chris@16: * Chris@16: ************************************************************************/ Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor Chris@16: add_vertex(PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE graph_type; Chris@16: typename graph_type::vertex_property_type p; Chris@16: return add_vertex(p, g); Chris@16: } Chris@16: Chris@16: template Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::lazy_add_vertex_with_property Chris@16: add_vertex(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_property_type const& p, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE Chris@16: ::lazy_add_vertex_with_property lazy_add_vertex; Chris@16: return lazy_add_vertex(g, p); Chris@16: } Chris@16: Chris@16: /************************************************************************ Chris@16: * Chris@16: * remove_vertex Chris@16: * Chris@16: ************************************************************************/ Chris@16: template Chris@16: void Chris@16: remove_vertex(typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor u, Chris@16: PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename PBGL_DISTRIB_ADJLIST_TYPE::graph_type graph_type; Chris@16: typedef typename graph_type::named_graph_mixin named_graph_mixin; Chris@16: BOOST_ASSERT(u.owner == g.processor()); Chris@16: static_cast(static_cast(g)) Chris@16: .removing_vertex(u, boost::graph_detail::iterator_stability(g.base().m_vertices)); Chris@16: g.distribution().clear(); Chris@16: remove_vertex(u.local, g.base()); Chris@16: } Chris@16: Chris@16: /*************************************************************************** Chris@16: * Implementation of Property Graph concept Chris@16: ***************************************************************************/ Chris@16: template Chris@16: struct property_map Chris@16: : detail::parallel::get_adj_list_pmap Chris@16: ::template apply Chris@16: { }; Chris@16: Chris@16: template Chris@16: struct property_map Chris@16: : boost::detail::parallel::get_adj_list_pmap Chris@16: // FIXME: in the original code the following was not const Chris@16: ::template apply Chris@16: { }; Chris@16: Chris@16: template Chris@16: typename property_map::type Chris@16: get(Property p, PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE Graph; Chris@16: typedef typename property_map::type result_type; Chris@16: typedef typename property_traits::value_type value_type; Chris@16: typedef typename property_reduce::template apply Chris@16: reduce; Chris@16: Chris@16: typedef typename property_traits::key_type descriptor; Chris@16: typedef typename graph_traits::vertex_descriptor vertex_descriptor; Chris@16: typedef typename mpl::if_, Chris@16: vertex_global_t, edge_global_t>::type Chris@16: global_map_t; Chris@16: Chris@16: return result_type(g.process_group(), get(global_map_t(), g), Chris@16: get(p, g.base()), reduce()); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(Property p, const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE Graph; Chris@16: typedef typename property_map::const_type result_type; Chris@16: typedef typename property_traits::value_type value_type; Chris@16: typedef typename property_reduce::template apply Chris@16: reduce; Chris@16: Chris@16: typedef typename property_traits::key_type descriptor; Chris@16: typedef typename graph_traits::vertex_descriptor vertex_descriptor; Chris@16: typedef typename mpl::if_, Chris@16: vertex_global_t, edge_global_t>::type Chris@16: global_map_t; Chris@16: Chris@16: return result_type(g.process_group(), get(global_map_t(), g), Chris@16: get(p, g.base()), reduce()); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::type Chris@16: get(vertex_local_index_t, PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: return get(vertex_local_index, g.base()); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(vertex_local_index_t, const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: return get(vertex_local_index, g.base()); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(vertex_global_t, const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: vertex_global_t>::const_type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(vertex_global_t, PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: vertex_global_t>::const_type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: /// Retrieve a property map mapping from a vertex descriptor to its Chris@16: /// owner. Chris@16: template Chris@16: typename property_map::type Chris@16: get(vertex_owner_t, PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: vertex_owner_t>::type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: /// Retrieve a property map mapping from a vertex descriptor to its Chris@16: /// owner. Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(vertex_owner_t, const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: vertex_owner_t>::const_type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: /// Retrieve the owner of a vertex Chris@16: template Chris@16: inline processor_id_type Chris@16: get(vertex_owner_t, PBGL_DISTRIB_ADJLIST_TYPE&, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v) Chris@16: { Chris@16: return v.owner; Chris@16: } Chris@16: Chris@16: /// Retrieve the owner of a vertex Chris@16: template Chris@16: inline processor_id_type Chris@16: get(vertex_owner_t, const PBGL_DISTRIB_ADJLIST_TYPE&, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v) Chris@16: { Chris@16: return v.owner; Chris@16: } Chris@16: Chris@16: /// Retrieve a property map that maps from a vertex descriptor to Chris@16: /// its local descriptor. Chris@16: template Chris@16: typename property_map::type Chris@16: get(vertex_local_t, PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: vertex_local_t>::type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: /// Retrieve a property map that maps from a vertex descriptor to Chris@16: /// its local descriptor. Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(vertex_local_t, const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: vertex_local_t>::const_type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: /// Retrieve the local descriptor of a vertex Chris@16: template Chris@16: inline typename PBGL_DISTRIB_ADJLIST_TYPE::local_vertex_descriptor Chris@16: get(vertex_local_t, PBGL_DISTRIB_ADJLIST_TYPE&, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v) Chris@16: { Chris@16: return v.local; Chris@16: } Chris@16: Chris@16: /// Retrieve the local descriptor of a vertex Chris@16: template Chris@16: inline typename PBGL_DISTRIB_ADJLIST_TYPE::local_vertex_descriptor Chris@16: get(vertex_local_t, const PBGL_DISTRIB_ADJLIST_TYPE&, Chris@16: typename PBGL_DISTRIB_ADJLIST_TYPE::vertex_descriptor v) Chris@16: { Chris@16: return v.local; Chris@16: } Chris@16: Chris@16: Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(edge_global_t, const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: edge_global_t>::const_type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(edge_global_t, PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: edge_global_t>::const_type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::type Chris@16: get(edge_owner_t, PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: edge_owner_t>::type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(edge_owner_t, const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: edge_owner_t>::const_type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::type Chris@16: get(edge_local_t, PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: edge_local_t>::type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(edge_local_t, const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef typename property_map< Chris@16: PBGL_DISTRIB_ADJLIST_TYPE, Chris@16: edge_local_t>::const_type result_type; Chris@16: return result_type(); Chris@16: } Chris@16: Chris@16: template Chris@16: inline Chris@16: typename property_traits::const_type Chris@16: >::value_type Chris@16: get(Property p, const PBGL_DISTRIB_ADJLIST_TYPE& g, const Key& key) Chris@16: { Chris@16: if (owner(key) == process_id(g.process_group())) Chris@16: return get(p, g.base(), local(key)); Chris@16: else Chris@16: BOOST_ASSERT(false); Chris@16: } Chris@16: Chris@16: template Chris@16: void Chris@16: put(Property p, PBGL_DISTRIB_ADJLIST_TYPE& g, const Key& key, const Value& v) Chris@16: { Chris@16: if (owner(key) == process_id(g.process_group())) Chris@16: put(p, g.base(), local(key), v); Chris@16: else Chris@16: BOOST_ASSERT(false); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::type Chris@16: get(vertex_index_t vi, PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE graph_type; Chris@16: typedef typename property_map::type Chris@16: result_type; Chris@16: return result_type(g.process_group(), get(vertex_global, g), Chris@16: get(vi, g.base())); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(vertex_index_t vi, const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE graph_type; Chris@16: typedef typename property_map::const_type Chris@16: result_type; Chris@16: return result_type(g.process_group(), get(vertex_global, g), Chris@16: get(vi, g.base())); Chris@16: } Chris@16: Chris@16: /*************************************************************************** Chris@16: * Implementation of bundled properties Chris@16: ***************************************************************************/ Chris@16: template Chris@16: struct property_map Chris@16: : detail::parallel::get_adj_list_pmap Chris@16: ::template apply Chris@16: { }; Chris@16: Chris@16: template Chris@16: struct property_map Chris@16: : detail::parallel::get_adj_list_pmap Chris@16: ::template apply Chris@16: { }; Chris@16: Chris@16: template Chris@16: typename property_map::type Chris@16: get(T Bundle::* p, PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE Graph; Chris@16: typedef typename property_map::type result_type; Chris@16: typedef typename property_traits::value_type value_type; Chris@16: typedef typename property_reduce::template apply Chris@16: reduce; Chris@16: Chris@16: typedef typename property_traits::key_type descriptor; Chris@16: typedef typename graph_traits::vertex_descriptor vertex_descriptor; Chris@16: typedef typename mpl::if_, Chris@16: vertex_global_t, edge_global_t>::type Chris@16: global_map_t; Chris@16: Chris@16: return result_type(g.process_group(), get(global_map_t(), g), Chris@16: get(p, g.base()), reduce()); Chris@16: } Chris@16: Chris@16: template Chris@16: typename property_map::const_type Chris@16: get(T Bundle::* p, const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: typedef PBGL_DISTRIB_ADJLIST_TYPE Graph; Chris@16: typedef typename property_map::const_type result_type; Chris@16: typedef typename property_traits::value_type value_type; Chris@16: typedef typename property_reduce::template apply Chris@16: reduce; Chris@16: Chris@16: typedef typename property_traits::key_type descriptor; Chris@16: typedef typename graph_traits::vertex_descriptor vertex_descriptor; Chris@16: typedef typename mpl::if_, Chris@16: vertex_global_t, edge_global_t>::type Chris@16: global_map_t; Chris@16: Chris@16: return result_type(g.process_group(), get(global_map_t(), g), Chris@16: get(p, g.base()), reduce()); Chris@16: } Chris@16: Chris@16: /*************************************************************************** Chris@16: * Implementation of DistributedGraph concept Chris@16: ***************************************************************************/ Chris@16: template Chris@16: void synchronize(const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { Chris@16: synchronize(g.process_group()); Chris@16: } Chris@16: Chris@16: template Chris@16: ProcessGroup Chris@16: process_group(const PBGL_DISTRIB_ADJLIST_TYPE& g) Chris@16: { return g.process_group(); } Chris@16: Chris@16: /*************************************************************************** Chris@16: * Specializations of is_mpi_datatype for Serializable entities Chris@16: ***************************************************************************/ Chris@16: namespace mpi { Chris@16: template Chris@16: struct is_mpi_datatype > Chris@16: : is_mpi_datatype { }; Chris@16: Chris@16: template Chris@16: struct is_mpi_datatype > Chris@16: : is_mpi_datatype > { }; Chris@16: Chris@16: template Chris@16: struct is_mpi_datatype > Chris@16: : is_mpi_datatype { }; Chris@16: Chris@16: template Chris@16: struct is_mpi_datatype > Chris@16: : is_mpi_datatype { }; Chris@16: Chris@16: template Chris@16: struct is_mpi_datatype > Chris@16: : is_mpi_datatype { }; Chris@16: Chris@16: template Chris@16: struct is_mpi_datatype > Chris@16: : mpl::and_, is_mpi_datatype > { }; Chris@16: Chris@16: Chris@16: template Chris@16: struct is_mpi_datatype > Chris@16: : mpl::and_< Chris@16: is_mpi_datatype >, Chris@16: is_mpi_datatype > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_mpi_datatype< Chris@16: boost::detail::parallel::msg_remove_edge_data > Chris@16: : is_mpi_datatype {}; Chris@16: } Chris@16: Chris@16: /*************************************************************************** Chris@16: * Specializations of is_bitwise_serializable for Serializable entities Chris@16: ***************************************************************************/ Chris@16: namespace serialization { Chris@16: template Chris@16: struct is_bitwise_serializable > Chris@16: : is_bitwise_serializable { }; Chris@16: Chris@16: template Chris@16: struct is_bitwise_serializable > Chris@16: : is_bitwise_serializable > { }; Chris@16: Chris@16: template Chris@16: struct is_bitwise_serializable > Chris@16: : is_bitwise_serializable { }; Chris@16: Chris@16: template Chris@16: struct is_bitwise_serializable > Chris@16: : is_bitwise_serializable { }; Chris@16: Chris@16: template Chris@16: struct is_bitwise_serializable > Chris@16: : is_bitwise_serializable { }; Chris@16: Chris@16: template Chris@16: struct is_bitwise_serializable > Chris@16: : mpl::and_, Chris@16: is_bitwise_serializable > { }; Chris@16: Chris@16: template Chris@16: struct is_bitwise_serializable > Chris@16: : mpl::and_< Chris@16: is_bitwise_serializable< Chris@16: boost::detail::parallel::maybe_store_property >, Chris@16: is_bitwise_serializable > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_bitwise_serializable< Chris@16: boost::detail::parallel::msg_remove_edge_data > Chris@16: : is_bitwise_serializable {}; Chris@16: Chris@16: template Chris@16: struct implementation_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct implementation_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct implementation_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct implementation_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct implementation_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct implementation_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct implementation_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct implementation_level< Chris@16: boost::detail::parallel::msg_remove_edge_data > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct tracking_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct tracking_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct tracking_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct tracking_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct tracking_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct tracking_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct tracking_level > Chris@16: : mpl::int_ {}; Chris@16: Chris@16: template Chris@16: struct tracking_level< Chris@16: boost::detail::parallel::msg_remove_edge_data > Chris@16: : mpl::int_ {}; Chris@16: } Chris@16: Chris@16: // Hash function for global descriptors Chris@16: template Chris@16: struct hash > Chris@16: { Chris@16: typedef detail::parallel::global_descriptor argument_type; Chris@16: std::size_t operator()(argument_type const& x) const Chris@16: { Chris@16: std::size_t hash = hash_value(x.owner); Chris@16: hash_combine(hash, x.local); Chris@16: return hash; Chris@16: } Chris@16: }; Chris@16: Chris@16: // Hash function for parallel edge descriptors Chris@16: template Chris@16: struct hash > Chris@16: { Chris@16: typedef detail::parallel::edge_descriptor argument_type; Chris@16: Chris@16: std::size_t operator()(argument_type const& x) const Chris@16: { Chris@16: std::size_t hash = hash_value(x.owner()); Chris@16: hash_combine(hash, x.local); Chris@16: return hash; Chris@16: } Chris@16: }; Chris@16: Chris@16: } // end namespace boost Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #endif // BOOST_GRAPH_DISTRIBUTED_ADJACENCY_LIST_HPP