File indexing completed on 2025-01-18 09:37:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_GRAPH_PARALLEL_CC_HPP
0011 #define BOOST_GRAPH_PARALLEL_CC_HPP
0012
0013 #ifndef BOOST_GRAPH_USE_MPI
0014 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
0015 #endif
0016
0017 #include <boost/detail/is_sorted.hpp>
0018 #include <boost/assert.hpp>
0019 #include <boost/property_map/property_map.hpp>
0020 #include <boost/property_map/parallel/parallel_property_maps.hpp>
0021 #include <boost/property_map/parallel/caching_property_map.hpp>
0022 #include <boost/graph/parallel/algorithm.hpp>
0023 #include <boost/pending/indirect_cmp.hpp>
0024 #include <boost/graph/graph_traits.hpp>
0025 #include <boost/graph/overloading.hpp>
0026 #include <boost/graph/distributed/concepts.hpp>
0027 #include <boost/graph/parallel/properties.hpp>
0028 #include <boost/graph/distributed/local_subgraph.hpp>
0029 #include <boost/graph/connected_components.hpp>
0030 #include <boost/graph/named_function_params.hpp>
0031 #include <boost/graph/parallel/process_group.hpp>
0032 #include <boost/optional.hpp>
0033 #include <functional>
0034 #include <algorithm>
0035 #include <vector>
0036 #include <list>
0037 #include <boost/graph/parallel/container_traits.hpp>
0038 #include <boost/graph/iteration_macros.hpp>
0039
0040 #define PBGL_IN_PLACE_MERGE
0041
0042
0043
0044 #define PBGL_EXPLICIT_SYNCH
0045
0046 #ifdef PBGL_CONSTRUCT_METAGRAPH
0047 # define MAX_VERTICES_IN_METAGRAPH 10000
0048 #endif
0049
0050 namespace boost { namespace graph { namespace distributed {
0051 namespace cc_detail {
0052 enum connected_components_message {
0053 edges_msg, req_parents_msg, parents_msg, root_adj_msg
0054 };
0055
0056 template <typename Vertex>
0057 struct metaVertex {
0058 metaVertex() {}
0059 metaVertex(const Vertex& v) : name(v) {}
0060
0061 template<typename Archiver>
0062 void serialize(Archiver& ar, const unsigned int )
0063 {
0064 ar & name;
0065 }
0066
0067 Vertex name;
0068 };
0069
0070 #ifdef PBGL_CONSTRUCT_METAGRAPH
0071
0072 template <typename Graph, typename ParentMap, typename RootIterator,
0073 typename AdjacencyMap>
0074 void
0075 build_local_metagraph(const Graph& g, ParentMap p, RootIterator r,
0076 RootIterator r_end, AdjacencyMap& adj)
0077 {
0078
0079
0080 typedef typename boost::graph::parallel::process_group_type<Graph>::type
0081 process_group_type;
0082 typedef typename process_group_type::process_id_type process_id_type;
0083
0084 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0085
0086 BOOST_STATIC_ASSERT((is_same<typename AdjacencyMap::mapped_type,
0087 std::vector<vertex_descriptor> >::value));
0088
0089 using boost::graph::parallel::process_group;
0090
0091 process_group_type pg = process_group(g);
0092 process_id_type id = process_id(pg);
0093
0094 if (id != 0) {
0095
0096
0097 for ( ; r != r_end; ++r ) {
0098 std::vector<vertex_descriptor> adjs(1, *r);
0099 adjs.reserve(adjs.size() + adj[*r].size());
0100 for (typename std::vector<vertex_descriptor>::iterator iter = adj[*r].begin();
0101 iter != adj[*r].end(); ++iter)
0102 adjs.push_back(get(p, *iter));
0103
0104 send(pg, 0, root_adj_msg, adjs);
0105 }
0106 }
0107
0108 synchronize(pg);
0109
0110 if (id == 0) {
0111 typedef metaVertex<vertex_descriptor> VertexProperties;
0112
0113 typedef boost::adjacency_list<vecS, vecS, undirectedS,
0114 VertexProperties> metaGraph;
0115 typedef typename graph_traits<metaGraph>::vertex_descriptor
0116 meta_vertex_descriptor;
0117
0118 std::map<vertex_descriptor, meta_vertex_descriptor> vertex_map;
0119 std::vector<std::pair<vertex_descriptor, vertex_descriptor> > edges;
0120
0121
0122 while (optional<std::pair<process_id_type, int> > m = probe(pg)) {
0123 BOOST_ASSERT(m->second == root_adj_msg);
0124
0125 std::vector<vertex_descriptor> adjs;
0126 receive(pg, m->first, m->second, adjs);
0127
0128 vertex_map[adjs[0]] = graph_traits<metaGraph>::null_vertex();
0129 for (typename std::vector<vertex_descriptor>::iterator iter
0130 = ++adjs.begin(); iter != adjs.end(); ++iter)
0131 edges.push_back(std::make_pair(adjs[0], *iter));
0132 }
0133
0134
0135 for ( ; r != r_end; ++r ) {
0136 vertex_map[*r] = graph_traits<metaGraph>::null_vertex();
0137 edges.reserve(edges.size() + adj[*r].size());
0138 for (typename std::vector<vertex_descriptor>::iterator iter = adj[*r].begin();
0139 iter != adj[*r].end(); ++iter)
0140 edges.push_back(std::make_pair(*r, get(p, *iter)));
0141 }
0142
0143
0144 metaGraph mg;
0145
0146
0147 for (typename std::map<vertex_descriptor, meta_vertex_descriptor>::iterator
0148 iter = vertex_map.begin(); iter != vertex_map.end(); ++iter)
0149 vertex_map[iter->first]
0150 = add_vertex(metaVertex<vertex_descriptor>(iter->first), mg);
0151
0152
0153 typename property_map<metaGraph, vertex_descriptor VertexProperties::*>::type
0154 metaVertexMap = get(&VertexProperties::name, mg);
0155
0156 typename std::vector<std::pair<vertex_descriptor, vertex_descriptor> >
0157 ::iterator edge_iter = edges.begin();
0158 for ( ; edge_iter != edges.end(); ++edge_iter)
0159 add_edge(vertex_map[edge_iter->first], vertex_map[edge_iter->second], mg);
0160
0161 edges.clear();
0162
0163
0164 typedef typename property_map<metaGraph, vertex_index_t>::type
0165 meta_index_map_type;
0166 meta_index_map_type meta_index = get(vertex_index, mg);
0167
0168 std::vector<std::size_t> mg_component_vec(num_vertices(mg));
0169 typedef iterator_property_map<std::vector<std::size_t>::iterator,
0170 meta_index_map_type>
0171 meta_components_map_type;
0172 meta_components_map_type mg_component(mg_component_vec.begin(),
0173 meta_index);
0174 std::size_t num_comp = connected_components(mg, mg_component);
0175
0176
0177 std::vector<meta_vertex_descriptor> roots(num_comp, graph_traits<metaGraph>::null_vertex());
0178
0179 BGL_FORALL_VERTICES_T(v, mg, metaGraph) {
0180 size_t component = get(mg_component, v);
0181 if (roots[component] == graph_traits<metaGraph>::null_vertex() ||
0182 get(meta_index, v) < get(meta_index, roots[component]))
0183 roots[component] = v;
0184 }
0185
0186
0187 BGL_FORALL_VERTICES_T(v, mg, metaGraph) {
0188
0189 put(p, get(metaVertexMap, v), get(metaVertexMap, roots[get(mg_component, v)]));
0190 }
0191 }
0192
0193 synchronize(p);
0194 }
0195 #endif
0196
0197
0198
0199
0200 template <typename Vertex, typename ParentMap>
0201 class cull_adjacency_list
0202 {
0203 public:
0204 cull_adjacency_list(const Vertex v, const ParentMap p) : v(v), p(p) {}
0205 bool operator() (const Vertex x) { return (get(p, x) == v || x == v); }
0206
0207 private:
0208 const Vertex v;
0209 const ParentMap p;
0210 };
0211
0212
0213
0214 template <typename OwnerMap, typename LocalMap>
0215 class hashed_vertex_compare
0216 {
0217 public:
0218 hashed_vertex_compare (const OwnerMap& o, const LocalMap& l)
0219 : owner(o), local(l) { }
0220
0221 template <typename Vertex>
0222 bool operator() (const Vertex x, const Vertex y)
0223 {
0224 if (get(local, x) < get(local, y))
0225 return true;
0226 else if (get(local, x) == get(local, y))
0227 return (get(owner, x) < get(owner, y));
0228 return false;
0229 }
0230
0231 private:
0232 OwnerMap owner;
0233 LocalMap local;
0234 };
0235
0236 #ifdef PBGL_EXPLICIT_SYNCH
0237 template <typename Graph, typename ParentMap, typename VertexList>
0238 void
0239 request_parent_map_entries(const Graph& g, ParentMap p,
0240 std::vector<VertexList>& parent_requests)
0241 {
0242 typedef typename boost::graph::parallel::process_group_type<Graph>
0243 ::type process_group_type;
0244 typedef typename process_group_type::process_id_type process_id_type;
0245
0246 typedef typename graph_traits<Graph>::vertex_descriptor
0247 vertex_descriptor;
0248
0249 process_group_type pg = process_group(g);
0250
0251
0252
0253
0254
0255
0256
0257 for (process_id_type i = 0; i < num_processes(pg); ++i) {
0258 if (!parent_requests[i].empty()) {
0259 std::vector<vertex_descriptor> reqs(parent_requests[i].begin(),
0260 parent_requests[i].end());
0261 send(pg, i, req_parents_msg, reqs);
0262 }
0263 }
0264
0265 synchronize(pg);
0266
0267
0268 while (optional<std::pair<process_id_type, int> > m = probe(pg)) {
0269 std::vector<vertex_descriptor> requests;
0270 receive(pg, m->first, m->second, requests);
0271 for (std::size_t i = 0; i < requests.size(); ++i)
0272 requests[i] = get(p, requests[i]);
0273 send(pg, m->first, parents_msg, requests);
0274 }
0275
0276 synchronize(pg);
0277
0278
0279 std::vector<vertex_descriptor> responses;
0280 for (process_id_type i = 0; i < num_processes(pg); ++i) {
0281 if (!parent_requests[i].empty()) {
0282 receive(pg, i, parents_msg, responses);
0283 std::size_t parent_idx = 0;
0284 for (typename VertexList::iterator v = parent_requests[i].begin();
0285 v != parent_requests[i].end(); ++v, ++parent_idx)
0286 put(p, *v, responses[parent_idx]);
0287 }
0288 }
0289 }
0290 #endif
0291
0292 template<typename DistributedGraph, typename ParentMap>
0293 void
0294 parallel_connected_components(DistributedGraph& g, ParentMap p)
0295 {
0296 using boost::connected_components;
0297
0298 typedef typename graph_traits<DistributedGraph>::adjacency_iterator
0299 adjacency_iterator;
0300 typedef typename graph_traits<DistributedGraph>::vertex_descriptor
0301 vertex_descriptor;
0302
0303 typedef typename boost::graph::parallel::process_group_type<DistributedGraph>
0304 ::type process_group_type;
0305 typedef typename process_group_type::process_id_type process_id_type;
0306
0307 using boost::graph::parallel::process_group;
0308
0309 process_group_type pg = process_group(g);
0310 process_id_type id = process_id(pg);
0311
0312
0313 adjacency_iterator av1, av2;
0314 std::vector<vertex_descriptor> old_roots;
0315 typename std::vector<vertex_descriptor>::iterator liter;
0316 typename std::vector<vertex_descriptor>::iterator aliter;
0317 typename std::map<vertex_descriptor,
0318 std::vector<vertex_descriptor> > adj;
0319
0320 typedef typename property_map<DistributedGraph, vertex_owner_t>::const_type
0321 OwnerMap;
0322 OwnerMap owner = get(vertex_owner, g);
0323 typedef typename property_map<DistributedGraph, vertex_local_t>::const_type
0324 LocalMap;
0325 LocalMap local = get(vertex_local, g);
0326
0327
0328 p.set_max_ghost_cells(0);
0329
0330
0331
0332
0333 local_subgraph<const DistributedGraph> ls(g);
0334 typedef typename property_map<local_subgraph<const DistributedGraph>,
0335 vertex_index_t>::type local_index_map_type;
0336 local_index_map_type local_index = get(vertex_index, ls);
0337
0338
0339 std::vector<std::size_t> ls_components_vec(num_vertices(ls));
0340 typedef iterator_property_map<std::vector<std::size_t>::iterator,
0341 local_index_map_type>
0342 ls_components_map_type;
0343 ls_components_map_type ls_component(ls_components_vec.begin(),
0344 local_index);
0345 std::size_t num_comp = connected_components(ls, ls_component);
0346
0347 std::vector<vertex_descriptor>
0348 roots(num_comp, graph_traits<DistributedGraph>::null_vertex());
0349
0350 BGL_FORALL_VERTICES_T(v, g, DistributedGraph) {
0351 size_t component = get(ls_component, v);
0352 if (roots[component] == graph_traits<DistributedGraph>::null_vertex() ||
0353 get(local_index, v) < get(local_index, roots[component]))
0354 roots[component] = v;
0355 }
0356
0357
0358 BGL_FORALL_VERTICES_T(v, g, DistributedGraph) {
0359 put(p, v, roots[get(ls_component, v)]);
0360 }
0361
0362 if (num_processes(pg) == 1) return;
0363
0364
0365 BGL_FORALL_VERTICES_T(v, g, DistributedGraph) {
0366 std::vector<vertex_descriptor>& my_adj = adj[get(p, v)];
0367 for (boost::tie(av1, av2) = adjacent_vertices(v, g);
0368 av1 != av2; ++av1) {
0369 if (get(owner, *av1) != id) my_adj.push_back(*av1);
0370 }
0371 }
0372
0373
0374 for ( liter = roots.begin(); liter != roots.end(); ++liter ) {
0375 std::vector<vertex_descriptor>& my_adj = adj[*liter];
0376 for ( aliter = my_adj.begin(); aliter != my_adj.end(); ++aliter )
0377 request(p, *aliter);
0378 }
0379 synchronize(p);
0380
0381
0382
0383 for ( liter = roots.begin(); liter != roots.end(); ++liter )
0384 {
0385 std::vector<vertex_descriptor>& my_adj = adj[*liter];
0386 for ( aliter = my_adj.begin(); aliter != my_adj.end(); ++aliter )
0387 *aliter = get(p, *aliter);
0388
0389 my_adj.erase
0390 (std::remove_if(my_adj.begin(), my_adj.end(),
0391 cull_adjacency_list<vertex_descriptor,
0392 ParentMap>(*liter, p) ),
0393 my_adj.end());
0394
0395
0396 std::sort(my_adj.begin(), my_adj.end(), std::less<vertex_descriptor>());
0397 my_adj.erase(std::unique(my_adj.begin(), my_adj.end()), my_adj.end());
0398 }
0399
0400
0401 p.clear();
0402 for ( liter = roots.begin(); liter != roots.end(); ++liter ) {
0403 std::vector<vertex_descriptor>& my_adj = adj[*liter];
0404 for ( aliter = my_adj.begin(); aliter != my_adj.end(); ++aliter )
0405 request(p, *aliter);
0406 }
0407 #ifdef PBGL_EXPLICIT_SYNCH
0408 synchronize(p);
0409 #endif
0410
0411
0412
0413 for ( liter = roots.begin(); liter != roots.end(); )
0414 {
0415 if ( adj[*liter].empty() )
0416 liter = roots.erase(liter);
0417 else
0418 ++liter;
0419 }
0420
0421 #ifdef PBGL_CONSTRUCT_METAGRAPH
0422
0423
0424
0425
0426 using boost::parallel::all_reduce;
0427 std::size_t num_roots = all_reduce(pg, roots.size(), std::plus<std::size_t>());
0428 if (num_roots < MAX_VERTICES_IN_METAGRAPH) {
0429 build_local_metagraph(g, p, roots.begin(), roots.end(), adj);
0430
0431
0432
0433 BGL_FORALL_VERTICES_T(v, g, DistributedGraph) {
0434 put(p, v, get(p, get(p, v)));
0435 }
0436
0437 synchronize(p);
0438
0439 return;
0440 }
0441 #endif
0442
0443
0444
0445
0446
0447 std::vector<vertex_descriptor> completed_roots;
0448 hashed_vertex_compare<OwnerMap, LocalMap> v_compare(owner, local);
0449 bool any_hooked;
0450 vertex_descriptor new_root;
0451
0452 std::size_t steps = 0;
0453
0454 do {
0455 ++steps;
0456
0457
0458 synchronize(p);
0459
0460
0461
0462
0463 bool hooked = false;
0464 completed_roots.clear();
0465 for ( liter = roots.begin(); liter != roots.end(); )
0466 {
0467 new_root = graph_traits<DistributedGraph>::null_vertex();
0468 std::vector<vertex_descriptor>& my_adj = adj[*liter];
0469 for ( aliter = my_adj.begin(); aliter != my_adj.end(); ++aliter )
0470
0471 if ( v_compare( get(p, *aliter), *liter ) )
0472 new_root = get(p, *aliter);
0473
0474 if ( new_root != graph_traits<DistributedGraph>::null_vertex() )
0475 {
0476 hooked = true;
0477 put(p, *liter, new_root);
0478 old_roots.push_back(*liter);
0479 completed_roots.push_back(*liter);
0480 liter = roots.erase(liter);
0481 }
0482 else
0483 ++liter;
0484 }
0485
0486
0487
0488
0489
0490
0491
0492 bool all_done;
0493 std::size_t parent_root_count;
0494
0495 std::size_t double_steps = 0;
0496
0497 do {
0498 ++double_steps;
0499 #ifndef PBGL_EXPLICIT_SYNCH
0500
0501 for ( liter = old_roots.begin(); liter != old_roots.end(); ++liter )
0502 request(p, get(p, *liter));
0503
0504 synchronize(p);
0505 #else
0506
0507 typedef std::set<vertex_descriptor> VertexSet;
0508 std::vector<VertexSet> parent_requests(num_processes(pg));
0509 for ( liter = old_roots.begin(); liter != old_roots.end(); ++liter )
0510 {
0511 vertex_descriptor p1 = *liter;
0512 if (get(owner, p1) != id) parent_requests[get(owner, p1)].insert(p1);
0513 vertex_descriptor p2 = get(p, p1);
0514 if (get(owner, p2) != id) parent_requests[get(owner, p2)].insert(p2);
0515 }
0516
0517 request_parent_map_entries(g, p, parent_requests);
0518 #endif
0519
0520 for ( liter = old_roots.begin(); liter != old_roots.end(); ++liter )
0521 put(p, *liter, get(p, get(p, *liter)));
0522
0523
0524 parent_root_count = 0;
0525 for ( liter = old_roots.begin(); liter != old_roots.end(); ++liter )
0526 if ( get(p, *liter) == get(p, get(p, *liter)) )
0527 parent_root_count++;
0528
0529 bool done = parent_root_count == old_roots.size();
0530
0531 all_reduce(pg, &done, &done+1, &all_done,
0532 std::logical_and<bool>());
0533 } while ( !all_done );
0534 #ifdef PARALLEL_BGL_DEBUG
0535 if (id == 0) std::cerr << double_steps << " doubling steps.\n";
0536 #endif
0537
0538
0539
0540
0541 typename std::vector<vertex_descriptor> outgoing_edges;
0542 for ( liter = completed_roots.begin(); liter != completed_roots.end();
0543 ++liter )
0544 {
0545 vertex_descriptor new_parent = get(p, *liter);
0546
0547 if ( get(owner, new_parent) == id )
0548 {
0549 std::vector<vertex_descriptor>& my_adj = adj[new_parent];
0550 my_adj.reserve(my_adj.size() + adj[*liter].size());
0551 my_adj.insert( my_adj.end(),
0552 adj[*liter].begin(), adj[*liter].end() );
0553 #ifdef PBGL_IN_PLACE_MERGE
0554 #ifdef PBGL_SORT_ASSERT
0555 BOOST_ASSERT(::boost::detail::is_sorted(my_adj.begin(),
0556 my_adj.end() - adj[*liter].size(),
0557 std::less<vertex_descriptor>()));
0558 BOOST_ASSERT(::boost::detail::is_sorted(my_adj.end() - adj[*liter].size(),
0559 my_adj.end(),
0560 std::less<vertex_descriptor>()));
0561 #endif
0562 std::inplace_merge(my_adj.begin(),
0563 my_adj.end() - adj[*liter].size(),
0564 my_adj.end(),
0565 std::less<vertex_descriptor>());
0566 #endif
0567
0568
0569 }
0570 else if ( adj[*liter].begin() != adj[*liter].end() )
0571 {
0572 outgoing_edges.clear();
0573 outgoing_edges.reserve(adj[*liter].size() + 1);
0574
0575 outgoing_edges.push_back(new_parent);
0576 outgoing_edges.insert(outgoing_edges.end(),
0577 adj[*liter].begin(), adj[*liter].end() );
0578 send(pg, get(owner, new_parent), edges_msg, outgoing_edges);
0579 adj[*liter].clear();
0580 }
0581 }
0582 synchronize(pg);
0583
0584
0585
0586 while (optional<std::pair<process_id_type, int> > m
0587 = probe(pg))
0588 {
0589 std::vector<vertex_descriptor> incoming_edges;
0590 receive(pg, m->first, edges_msg, incoming_edges);
0591 typename std::vector<vertex_descriptor>::iterator aviter
0592 = incoming_edges.begin();
0593 ++aviter;
0594
0595 std::vector<vertex_descriptor>& my_adj = adj[incoming_edges[0]];
0596
0597 my_adj.reserve(my_adj.size() + incoming_edges.size() - 1);
0598 my_adj.insert( my_adj.end(), aviter, incoming_edges.end() );
0599
0600 #ifdef PBGL_IN_PLACE_MERGE
0601 std::size_t num_incoming_edges = incoming_edges.size();
0602 #ifdef PBGL_SORT_ASSERT
0603 BOOST_ASSERT(::boost::detail::is_sorted(my_adj.begin(),
0604 my_adj.end() - (num_incoming_edges-1),
0605 std::less<vertex_descriptor>()));
0606 BOOST_ASSERT(::boost::detail::is_sorted(my_adj.end() - (num_incoming_edges-1),
0607 my_adj.end(),
0608 std::less<vertex_descriptor>()));
0609 #endif
0610 std::inplace_merge(my_adj.begin(),
0611 my_adj.end() - (num_incoming_edges - 1),
0612 my_adj.end(),
0613 std::less<vertex_descriptor>());
0614 #endif
0615
0616 }
0617
0618
0619
0620
0621 for ( liter = roots.begin(); liter != roots.end(); ++liter )
0622 {
0623
0624
0625
0626
0627 std::vector<vertex_descriptor>& my_adj = adj[*liter];
0628 my_adj.erase
0629 (std::remove_if(my_adj.begin(), my_adj.end(),
0630 cull_adjacency_list<vertex_descriptor,
0631 ParentMap>(*liter, p) ),
0632 my_adj.end());
0633 #ifndef PBGL_IN_PLACE_MERGE
0634 std::sort(my_adj.begin(), my_adj.end(),
0635 std::less<vertex_descriptor>() );
0636 #endif
0637 my_adj.erase(std::unique(my_adj.begin(), my_adj.end()), my_adj.end());
0638 }
0639
0640
0641 all_reduce(pg, &hooked, &hooked+1, &any_hooked,
0642 std::logical_or<bool>());
0643 } while ( any_hooked );
0644 #ifdef PARALLEL_BGL_DEBUG
0645 if (id == 0) std::cerr << steps << " iterations.\n";
0646 #endif
0647
0648
0649
0650
0651
0652
0653 BGL_FORALL_VERTICES_T(v, g, DistributedGraph) {
0654 put(p, v, get(p, get(p, v)));
0655 }
0656
0657 synchronize(p);
0658 }
0659
0660 }
0661
0662 template<typename Graph, typename ParentMap, typename ComponentMap>
0663 typename property_traits<ComponentMap>::value_type
0664 number_components_from_parents(const Graph& g, ParentMap p, ComponentMap c)
0665 {
0666 typedef typename graph_traits<Graph>::vertex_descriptor
0667 vertex_descriptor;
0668 typedef typename boost::graph::parallel::process_group_type<Graph>::type
0669 process_group_type;
0670 typedef typename property_traits<ComponentMap>::value_type
0671 ComponentMapType;
0672
0673 process_group_type pg = process_group(g);
0674
0675
0676 std::vector<vertex_descriptor> my_roots, all_roots;
0677
0678 BGL_FORALL_VERTICES_T(v, g, Graph) {
0679 if( std::find( my_roots.begin(), my_roots.end(), get(p, v) )
0680 == my_roots.end() )
0681 my_roots.push_back( get(p, v) );
0682 }
0683
0684 all_gather(pg, my_roots.begin(), my_roots.end(), all_roots);
0685
0686
0687 std::map<vertex_descriptor, ComponentMapType> comp_numbers;
0688 ComponentMapType c_num = 0;
0689
0690
0691 for (std::size_t i = 0; i < all_roots.size(); i++ )
0692 if ( comp_numbers.count(all_roots[i]) == 0 )
0693 comp_numbers[all_roots[i]] = c_num++;
0694
0695
0696 BGL_FORALL_VERTICES_T(v, g, Graph) {
0697 put( c, v, comp_numbers[get(p, v)] );
0698 }
0699
0700
0701 if (process_id(pg) == 0) {
0702 typedef typename process_group_type::process_size_type
0703 process_size_type;
0704 for (process_size_type dest = 1, n = num_processes(pg);
0705 dest != n; ++dest)
0706 send(pg, dest, 0, c_num);
0707 }
0708 synchronize(pg);
0709
0710 if (process_id(pg) != 0) receive(pg, 0, 0, c_num);
0711
0712 synchronize(c);
0713
0714 return c_num;
0715 }
0716
0717 template<typename Graph, typename ParentMap>
0718 int
0719 number_components_from_parents(const Graph& g, ParentMap p,
0720 dummy_property_map)
0721 {
0722 using boost::parallel::all_reduce;
0723
0724
0725 int num_roots = 0;
0726 BGL_FORALL_VERTICES_T(v, g, Graph)
0727 if (get(p, v) == v) ++num_roots;
0728 return all_reduce(g.process_group(), num_roots, std::plus<int>());
0729 }
0730
0731 template<typename Graph, typename ComponentMap, typename ParentMap>
0732 typename property_traits<ComponentMap>::value_type
0733 connected_components
0734 (const Graph& g, ComponentMap c, ParentMap p
0735 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, distributed_graph_tag))
0736 {
0737 cc_detail::parallel_connected_components(g, p);
0738 return number_components_from_parents(g, p, c);
0739 }
0740
0741
0742 template<typename Graph, typename ComponentMap>
0743 typename property_traits<ComponentMap>::value_type
0744 connected_components
0745 ( const Graph& g, ComponentMap c
0746 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, distributed_graph_tag) )
0747 {
0748 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0749
0750 std::vector<vertex_descriptor> x(num_vertices(g));
0751
0752 return connected_components
0753 (g, c,
0754 make_iterator_property_map(x.begin(), get(vertex_index, g)));
0755 }
0756 }
0757
0758 using distributed::connected_components;
0759 }
0760
0761 using graph::distributed::connected_components;
0762 }
0763
0764 #endif