connected_components.hpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. // Copyright (C) 2004-2006 The Trustees of Indiana University.
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Nick Edmonds
  6. // Douglas Gregor
  7. // Andrew Lumsdaine
  8. #ifndef BOOST_GRAPH_PARALLEL_CC_HPP
  9. #define BOOST_GRAPH_PARALLEL_CC_HPP
  10. #ifndef BOOST_GRAPH_USE_MPI
  11. #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
  12. #endif
  13. #include <boost/detail/is_sorted.hpp>
  14. #include <boost/assert.hpp>
  15. #include <boost/property_map/property_map.hpp>
  16. #include <boost/property_map/parallel/parallel_property_maps.hpp>
  17. #include <boost/property_map/parallel/caching_property_map.hpp>
  18. #include <boost/graph/parallel/algorithm.hpp>
  19. #include <boost/pending/indirect_cmp.hpp>
  20. #include <boost/graph/graph_traits.hpp>
  21. #include <boost/graph/overloading.hpp>
  22. #include <boost/graph/distributed/concepts.hpp>
  23. #include <boost/graph/parallel/properties.hpp>
  24. #include <boost/graph/distributed/local_subgraph.hpp>
  25. #include <boost/graph/connected_components.hpp>
  26. #include <boost/graph/named_function_params.hpp>
  27. #include <boost/graph/parallel/process_group.hpp>
  28. #include <boost/optional.hpp>
  29. #include <functional>
  30. #include <algorithm>
  31. #include <vector>
  32. #include <list>
  33. #include <boost/graph/parallel/container_traits.hpp>
  34. #include <boost/graph/iteration_macros.hpp>
  35. #define PBGL_IN_PLACE_MERGE /* In place merge instead of sorting */
  36. //#define PBGL_SORT_ASSERT /* Assert sorted for in place merge */
  37. /* Explicit sychronization in pointer doubling step? */
  38. #define PBGL_EXPLICIT_SYNCH
  39. //#define PBGL_CONSTRUCT_METAGRAPH
  40. #ifdef PBGL_CONSTRUCT_METAGRAPH
  41. # define MAX_VERTICES_IN_METAGRAPH 10000
  42. #endif
  43. namespace boost { namespace graph { namespace distributed {
  44. namespace cc_detail {
  45. enum connected_components_message {
  46. edges_msg, req_parents_msg, parents_msg, root_adj_msg
  47. };
  48. template <typename Vertex>
  49. struct metaVertex {
  50. metaVertex() {}
  51. metaVertex(const Vertex& v) : name(v) {}
  52. template<typename Archiver>
  53. void serialize(Archiver& ar, const unsigned int /*version*/)
  54. {
  55. ar & name;
  56. }
  57. Vertex name;
  58. };
  59. #ifdef PBGL_CONSTRUCT_METAGRAPH
  60. // Build meta-graph on result of local connected components
  61. template <typename Graph, typename ParentMap, typename RootIterator,
  62. typename AdjacencyMap>
  63. void
  64. build_local_metagraph(const Graph& g, ParentMap p, RootIterator r,
  65. RootIterator r_end, AdjacencyMap& adj)
  66. {
  67. // TODO: Static assert that AdjacencyMap::value_type is std::vector<vertex_descriptor>
  68. typedef typename boost::graph::parallel::process_group_type<Graph>::type
  69. process_group_type;
  70. typedef typename process_group_type::process_id_type process_id_type;
  71. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  72. BOOST_STATIC_ASSERT((is_same<typename AdjacencyMap::mapped_type,
  73. std::vector<vertex_descriptor> >::value));
  74. using boost::graph::parallel::process_group;
  75. process_group_type pg = process_group(g);
  76. process_id_type id = process_id(pg);
  77. if (id != 0) {
  78. // Send component roots and their associated edges to P0
  79. for ( ; r != r_end; ++r ) {
  80. std::vector<vertex_descriptor> adjs(1, *r); // Root
  81. adjs.reserve(adjs.size() + adj[*r].size());
  82. for (typename std::vector<vertex_descriptor>::iterator iter = adj[*r].begin();
  83. iter != adj[*r].end(); ++iter)
  84. adjs.push_back(get(p, *iter)); // Adjacencies
  85. send(pg, 0, root_adj_msg, adjs);
  86. }
  87. }
  88. synchronize(pg);
  89. if (id == 0) {
  90. typedef metaVertex<vertex_descriptor> VertexProperties;
  91. typedef boost::adjacency_list<vecS, vecS, undirectedS,
  92. VertexProperties> metaGraph;
  93. typedef typename graph_traits<metaGraph>::vertex_descriptor
  94. meta_vertex_descriptor;
  95. std::map<vertex_descriptor, meta_vertex_descriptor> vertex_map;
  96. std::vector<std::pair<vertex_descriptor, vertex_descriptor> > edges;
  97. // Receive remote roots and edges
  98. while (optional<std::pair<process_id_type, int> > m = probe(pg)) {
  99. BOOST_ASSERT(m->second == root_adj_msg);
  100. std::vector<vertex_descriptor> adjs;
  101. receive(pg, m->first, m->second, adjs);
  102. vertex_map[adjs[0]] = graph_traits<metaGraph>::null_vertex();
  103. for (typename std::vector<vertex_descriptor>::iterator iter
  104. = ++adjs.begin(); iter != adjs.end(); ++iter)
  105. edges.push_back(std::make_pair(adjs[0], *iter));
  106. }
  107. // Add local roots and edges
  108. for ( ; r != r_end; ++r ) {
  109. vertex_map[*r] = graph_traits<metaGraph>::null_vertex();
  110. edges.reserve(edges.size() + adj[*r].size());
  111. for (typename std::vector<vertex_descriptor>::iterator iter = adj[*r].begin();
  112. iter != adj[*r].end(); ++iter)
  113. edges.push_back(std::make_pair(*r, get(p, *iter)));
  114. }
  115. // Build local meta-graph
  116. metaGraph mg;
  117. // Add vertices with property to map back to distributed graph vertex
  118. for (typename std::map<vertex_descriptor, meta_vertex_descriptor>::iterator
  119. iter = vertex_map.begin(); iter != vertex_map.end(); ++iter)
  120. vertex_map[iter->first]
  121. = add_vertex(metaVertex<vertex_descriptor>(iter->first), mg);
  122. // Build meta-vertex map
  123. typename property_map<metaGraph, vertex_descriptor VertexProperties::*>::type
  124. metaVertexMap = get(&VertexProperties::name, mg);
  125. typename std::vector<std::pair<vertex_descriptor, vertex_descriptor> >
  126. ::iterator edge_iter = edges.begin();
  127. for ( ; edge_iter != edges.end(); ++edge_iter)
  128. add_edge(vertex_map[edge_iter->first], vertex_map[edge_iter->second], mg);
  129. edges.clear();
  130. // Call connected_components on it
  131. typedef typename property_map<metaGraph, vertex_index_t>::type
  132. meta_index_map_type;
  133. meta_index_map_type meta_index = get(vertex_index, mg);
  134. std::vector<std::size_t> mg_component_vec(num_vertices(mg));
  135. typedef iterator_property_map<std::vector<std::size_t>::iterator,
  136. meta_index_map_type>
  137. meta_components_map_type;
  138. meta_components_map_type mg_component(mg_component_vec.begin(),
  139. meta_index);
  140. std::size_t num_comp = connected_components(mg, mg_component);
  141. // Update Parent pointers
  142. std::vector<meta_vertex_descriptor> roots(num_comp, graph_traits<metaGraph>::null_vertex());
  143. BGL_FORALL_VERTICES_T(v, mg, metaGraph) {
  144. size_t component = get(mg_component, v);
  145. if (roots[component] == graph_traits<metaGraph>::null_vertex() ||
  146. get(meta_index, v) < get(meta_index, roots[component]))
  147. roots[component] = v;
  148. }
  149. // Set all the local parent pointers
  150. BGL_FORALL_VERTICES_T(v, mg, metaGraph) {
  151. // Problem in value being put (3rd parameter)
  152. put(p, get(metaVertexMap, v), get(metaVertexMap, roots[get(mg_component, v)]));
  153. }
  154. }
  155. synchronize(p);
  156. }
  157. #endif
  158. /* Function object used to remove internal vertices and vertices >
  159. the current vertex from the adjacent vertex lists at each
  160. root */
  161. template <typename Vertex, typename ParentMap>
  162. class cull_adjacency_list
  163. {
  164. public:
  165. cull_adjacency_list(const Vertex v, const ParentMap p) : v(v), p(p) {}
  166. bool operator() (const Vertex x) { return (get(p, x) == v || x == v); }
  167. private:
  168. const Vertex v;
  169. const ParentMap p;
  170. };
  171. /* Comparison operator used to choose targets for hooking s.t. vertices
  172. that are hooked to are evenly distributed across processors */
  173. template <typename OwnerMap, typename LocalMap>
  174. class hashed_vertex_compare
  175. {
  176. public:
  177. hashed_vertex_compare (const OwnerMap& o, const LocalMap& l)
  178. : owner(o), local(l) { }
  179. template <typename Vertex>
  180. bool operator() (const Vertex x, const Vertex y)
  181. {
  182. if (get(local, x) < get(local, y))
  183. return true;
  184. else if (get(local, x) == get(local, y))
  185. return (get(owner, x) < get(owner, y));
  186. return false;
  187. }
  188. private:
  189. OwnerMap owner;
  190. LocalMap local;
  191. };
  192. #ifdef PBGL_EXPLICIT_SYNCH
  193. template <typename Graph, typename ParentMap, typename VertexList>
  194. void
  195. request_parent_map_entries(const Graph& g, ParentMap p,
  196. std::vector<VertexList>& parent_requests)
  197. {
  198. typedef typename boost::graph::parallel::process_group_type<Graph>
  199. ::type process_group_type;
  200. typedef typename process_group_type::process_id_type process_id_type;
  201. typedef typename graph_traits<Graph>::vertex_descriptor
  202. vertex_descriptor;
  203. process_group_type pg = process_group(g);
  204. /*
  205. This should probably be send_oob_with_reply, especially when Dave
  206. finishes prefetch-batching
  207. */
  208. // Send root requests
  209. for (process_id_type i = 0; i < num_processes(pg); ++i) {
  210. if (!parent_requests[i].empty()) {
  211. std::vector<vertex_descriptor> reqs(parent_requests[i].begin(),
  212. parent_requests[i].end());
  213. send(pg, i, req_parents_msg, reqs);
  214. }
  215. }
  216. synchronize(pg);
  217. // Receive root requests and reply to them
  218. while (optional<std::pair<process_id_type, int> > m = probe(pg)) {
  219. std::vector<vertex_descriptor> requests;
  220. receive(pg, m->first, m->second, requests);
  221. for (std::size_t i = 0; i < requests.size(); ++i)
  222. requests[i] = get(p, requests[i]);
  223. send(pg, m->first, parents_msg, requests);
  224. }
  225. synchronize(pg);
  226. // Receive requested parents
  227. std::vector<vertex_descriptor> responses;
  228. for (process_id_type i = 0; i < num_processes(pg); ++i) {
  229. if (!parent_requests[i].empty()) {
  230. receive(pg, i, parents_msg, responses);
  231. std::size_t parent_idx = 0;
  232. for (typename VertexList::iterator v = parent_requests[i].begin();
  233. v != parent_requests[i].end(); ++v, ++parent_idx)
  234. put(p, *v, responses[parent_idx]);
  235. }
  236. }
  237. }
  238. #endif
  239. template<typename DistributedGraph, typename ParentMap>
  240. void
  241. parallel_connected_components(DistributedGraph& g, ParentMap p)
  242. {
  243. using boost::connected_components;
  244. typedef typename graph_traits<DistributedGraph>::adjacency_iterator
  245. adjacency_iterator;
  246. typedef typename graph_traits<DistributedGraph>::vertex_descriptor
  247. vertex_descriptor;
  248. typedef typename boost::graph::parallel::process_group_type<DistributedGraph>
  249. ::type process_group_type;
  250. typedef typename process_group_type::process_id_type process_id_type;
  251. using boost::graph::parallel::process_group;
  252. process_group_type pg = process_group(g);
  253. process_id_type id = process_id(pg);
  254. // TODO (NGE): Should old_roots, roots, and completed_roots be std::list
  255. adjacency_iterator av1, av2;
  256. std::vector<vertex_descriptor> old_roots;
  257. typename std::vector<vertex_descriptor>::iterator liter;
  258. typename std::vector<vertex_descriptor>::iterator aliter;
  259. typename std::map<vertex_descriptor,
  260. std::vector<vertex_descriptor> > adj;
  261. typedef typename property_map<DistributedGraph, vertex_owner_t>::const_type
  262. OwnerMap;
  263. OwnerMap owner = get(vertex_owner, g);
  264. typedef typename property_map<DistributedGraph, vertex_local_t>::const_type
  265. LocalMap;
  266. LocalMap local = get(vertex_local, g);
  267. // We need to hold on to all of the parent pointers
  268. p.set_max_ghost_cells(0);
  269. //
  270. // STAGE 1 : Compute local components
  271. //
  272. local_subgraph<const DistributedGraph> ls(g);
  273. typedef typename property_map<local_subgraph<const DistributedGraph>,
  274. vertex_index_t>::type local_index_map_type;
  275. local_index_map_type local_index = get(vertex_index, ls);
  276. // Compute local connected components
  277. std::vector<std::size_t> ls_components_vec(num_vertices(ls));
  278. typedef iterator_property_map<std::vector<std::size_t>::iterator,
  279. local_index_map_type>
  280. ls_components_map_type;
  281. ls_components_map_type ls_component(ls_components_vec.begin(),
  282. local_index);
  283. std::size_t num_comp = connected_components(ls, ls_component);
  284. std::vector<vertex_descriptor>
  285. roots(num_comp, graph_traits<DistributedGraph>::null_vertex());
  286. BGL_FORALL_VERTICES_T(v, g, DistributedGraph) {
  287. size_t component = get(ls_component, v);
  288. if (roots[component] == graph_traits<DistributedGraph>::null_vertex() ||
  289. get(local_index, v) < get(local_index, roots[component]))
  290. roots[component] = v;
  291. }
  292. // Set all the local parent pointers
  293. BGL_FORALL_VERTICES_T(v, g, DistributedGraph) {
  294. put(p, v, roots[get(ls_component, v)]);
  295. }
  296. if (num_processes(pg) == 1) return;
  297. // Build adjacency list for all roots
  298. BGL_FORALL_VERTICES_T(v, g, DistributedGraph) {
  299. std::vector<vertex_descriptor>& my_adj = adj[get(p, v)];
  300. for (boost::tie(av1, av2) = adjacent_vertices(v, g);
  301. av1 != av2; ++av1) {
  302. if (get(owner, *av1) != id) my_adj.push_back(*av1);
  303. }
  304. }
  305. // For all vertices adjacent to a local vertex get p(v)
  306. for ( liter = roots.begin(); liter != roots.end(); ++liter ) {
  307. std::vector<vertex_descriptor>& my_adj = adj[*liter];
  308. for ( aliter = my_adj.begin(); aliter != my_adj.end(); ++aliter )
  309. request(p, *aliter);
  310. }
  311. synchronize(p);
  312. // Update adjacency list at root to make sure all adjacent
  313. // vertices are roots of remote components
  314. for ( liter = roots.begin(); liter != roots.end(); ++liter )
  315. {
  316. std::vector<vertex_descriptor>& my_adj = adj[*liter];
  317. for ( aliter = my_adj.begin(); aliter != my_adj.end(); ++aliter )
  318. *aliter = get(p, *aliter);
  319. my_adj.erase
  320. (std::remove_if(my_adj.begin(), my_adj.end(),
  321. cull_adjacency_list<vertex_descriptor,
  322. ParentMap>(*liter, p) ),
  323. my_adj.end());
  324. // This sort needs to be here to make sure the initial
  325. // adjacency list is sorted
  326. std::sort(my_adj.begin(), my_adj.end(), std::less<vertex_descriptor>());
  327. my_adj.erase(std::unique(my_adj.begin(), my_adj.end()), my_adj.end());
  328. }
  329. // Get p(v) for the new adjacent roots
  330. p.clear();
  331. for ( liter = roots.begin(); liter != roots.end(); ++liter ) {
  332. std::vector<vertex_descriptor>& my_adj = adj[*liter];
  333. for ( aliter = my_adj.begin(); aliter != my_adj.end(); ++aliter )
  334. request(p, *aliter);
  335. }
  336. #ifdef PBGL_EXPLICIT_SYNCH
  337. synchronize(p);
  338. #endif
  339. // Lastly, remove roots with no adjacent vertices, this is
  340. // unnecessary but will speed up sparse graphs
  341. for ( liter = roots.begin(); liter != roots.end(); /*in loop*/)
  342. {
  343. if ( adj[*liter].empty() )
  344. liter = roots.erase(liter);
  345. else
  346. ++liter;
  347. }
  348. #ifdef PBGL_CONSTRUCT_METAGRAPH
  349. /* TODO: If the number of roots is sufficiently small, we can
  350. use a 'problem folding' approach like we do in MST
  351. to gather all the roots and their adjacencies on one proc
  352. and solve for the connected components of the meta-graph */
  353. using boost::parallel::all_reduce;
  354. std::size_t num_roots = all_reduce(pg, roots.size(), std::plus<std::size_t>());
  355. if (num_roots < MAX_VERTICES_IN_METAGRAPH) {
  356. build_local_metagraph(g, p, roots.begin(), roots.end(), adj);
  357. // For each vertex in g, p(v) = p(p(v)), assign parent of leaf
  358. // vertices from first step to final parent
  359. BGL_FORALL_VERTICES_T(v, g, DistributedGraph) {
  360. put(p, v, get(p, get(p, v)));
  361. }
  362. synchronize(p);
  363. return;
  364. }
  365. #endif
  366. //
  367. // Parallel Phase
  368. //
  369. std::vector<vertex_descriptor> completed_roots;
  370. hashed_vertex_compare<OwnerMap, LocalMap> v_compare(owner, local);
  371. bool any_hooked;
  372. vertex_descriptor new_root;
  373. std::size_t steps = 0;
  374. do {
  375. ++steps;
  376. // Pull in new parents for hooking phase
  377. synchronize(p);
  378. //
  379. // Hooking
  380. //
  381. bool hooked = false;
  382. completed_roots.clear();
  383. for ( liter = roots.begin(); liter != roots.end(); )
  384. {
  385. new_root = graph_traits<DistributedGraph>::null_vertex();
  386. std::vector<vertex_descriptor>& my_adj = adj[*liter];
  387. for ( aliter = my_adj.begin(); aliter != my_adj.end(); ++aliter )
  388. // try to hook to better adjacent vertex
  389. if ( v_compare( get(p, *aliter), *liter ) )
  390. new_root = get(p, *aliter);
  391. if ( new_root != graph_traits<DistributedGraph>::null_vertex() )
  392. {
  393. hooked = true;
  394. put(p, *liter, new_root);
  395. old_roots.push_back(*liter);
  396. completed_roots.push_back(*liter);
  397. liter = roots.erase(liter);
  398. }
  399. else
  400. ++liter;
  401. }
  402. //
  403. // Pointer jumping, perform until new roots determined
  404. //
  405. // TODO: Implement cycle reduction rules to reduce this from
  406. // O(n) to O(log n) [n = cycle length]
  407. bool all_done;
  408. std::size_t parent_root_count;
  409. std::size_t double_steps = 0;
  410. do {
  411. ++double_steps;
  412. #ifndef PBGL_EXPLICIT_SYNCH
  413. // Get p(p(v)) for all old roots, and p(v) for all current roots
  414. for ( liter = old_roots.begin(); liter != old_roots.end(); ++liter )
  415. request(p, get(p, *liter));
  416. synchronize(p);
  417. #else
  418. // Build root requests
  419. typedef std::set<vertex_descriptor> VertexSet;
  420. std::vector<VertexSet> parent_requests(num_processes(pg));
  421. for ( liter = old_roots.begin(); liter != old_roots.end(); ++liter )
  422. {
  423. vertex_descriptor p1 = *liter;
  424. if (get(owner, p1) != id) parent_requests[get(owner, p1)].insert(p1);
  425. vertex_descriptor p2 = get(p, p1);
  426. if (get(owner, p2) != id) parent_requests[get(owner, p2)].insert(p2);
  427. }
  428. request_parent_map_entries(g, p, parent_requests);
  429. #endif
  430. // Perform a pointer jumping step on all old roots
  431. for ( liter = old_roots.begin(); liter != old_roots.end(); ++liter )
  432. put(p, *liter, get(p, get(p, *liter)));
  433. // make sure the parent of all old roots is itself a root
  434. parent_root_count = 0;
  435. for ( liter = old_roots.begin(); liter != old_roots.end(); ++liter )
  436. if ( get(p, *liter) == get(p, get(p, *liter)) )
  437. parent_root_count++;
  438. bool done = parent_root_count == old_roots.size();
  439. all_reduce(pg, &done, &done+1, &all_done,
  440. std::logical_and<bool>());
  441. } while ( !all_done );
  442. #ifdef PARALLEL_BGL_DEBUG
  443. if (id == 0) std::cerr << double_steps << " doubling steps.\n";
  444. #endif
  445. //
  446. // Add adjacent vertices of just completed roots to adjacent
  447. // vertex list at new parent
  448. //
  449. typename std::vector<vertex_descriptor> outgoing_edges;
  450. for ( liter = completed_roots.begin(); liter != completed_roots.end();
  451. ++liter )
  452. {
  453. vertex_descriptor new_parent = get(p, *liter);
  454. if ( get(owner, new_parent) == id )
  455. {
  456. std::vector<vertex_descriptor>& my_adj = adj[new_parent];
  457. my_adj.reserve(my_adj.size() + adj[*liter].size());
  458. my_adj.insert( my_adj.end(),
  459. adj[*liter].begin(), adj[*liter].end() );
  460. #ifdef PBGL_IN_PLACE_MERGE
  461. #ifdef PBGL_SORT_ASSERT
  462. BOOST_ASSERT(::boost::detail::is_sorted(my_adj.begin(),
  463. my_adj.end() - adj[*liter].size(),
  464. std::less<vertex_descriptor>()));
  465. BOOST_ASSERT(::boost::detail::is_sorted(my_adj.end() - adj[*liter].size(),
  466. my_adj.end(),
  467. std::less<vertex_descriptor>()));
  468. #endif
  469. std::inplace_merge(my_adj.begin(),
  470. my_adj.end() - adj[*liter].size(),
  471. my_adj.end(),
  472. std::less<vertex_descriptor>());
  473. #endif
  474. }
  475. else if ( adj[*liter].begin() != adj[*liter].end() )
  476. {
  477. outgoing_edges.clear();
  478. outgoing_edges.reserve(adj[*liter].size() + 1);
  479. // First element is the destination of the adjacency list
  480. outgoing_edges.push_back(new_parent);
  481. outgoing_edges.insert(outgoing_edges.end(),
  482. adj[*liter].begin(), adj[*liter].end() );
  483. send(pg, get(owner, new_parent), edges_msg, outgoing_edges);
  484. adj[*liter].clear();
  485. }
  486. }
  487. synchronize(pg);
  488. // Receive edges sent by remote nodes and add them to the
  489. // indicated vertex's adjacency list
  490. while (optional<std::pair<process_id_type, int> > m
  491. = probe(pg))
  492. {
  493. std::vector<vertex_descriptor> incoming_edges;
  494. receive(pg, m->first, edges_msg, incoming_edges);
  495. typename std::vector<vertex_descriptor>::iterator aviter
  496. = incoming_edges.begin();
  497. ++aviter;
  498. std::vector<vertex_descriptor>& my_adj = adj[incoming_edges[0]];
  499. my_adj.reserve(my_adj.size() + incoming_edges.size() - 1);
  500. my_adj.insert( my_adj.end(), aviter, incoming_edges.end() );
  501. #ifdef PBGL_IN_PLACE_MERGE
  502. std::size_t num_incoming_edges = incoming_edges.size();
  503. #ifdef PBGL_SORT_ASSERT
  504. BOOST_ASSERT(::boost::detail::is_sorted(my_adj.begin(),
  505. my_adj.end() - (num_incoming_edges-1),
  506. std::less<vertex_descriptor>()));
  507. BOOST_ASSERT(::boost::detail::is_sorted(my_adj.end() - (num_incoming_edges-1),
  508. my_adj.end(),
  509. std::less<vertex_descriptor>()));
  510. #endif
  511. std::inplace_merge(my_adj.begin(),
  512. my_adj.end() - (num_incoming_edges - 1),
  513. my_adj.end(),
  514. std::less<vertex_descriptor>());
  515. #endif
  516. }
  517. // Remove any adjacent vertices that are in the same component
  518. // as a root from that root's list
  519. for ( liter = roots.begin(); liter != roots.end(); ++liter )
  520. {
  521. // We can probably get away without sorting and removing
  522. // duplicates Though sorting *may* cause root
  523. // determination to occur faster by choosing the root with
  524. // the most potential to hook to at each step
  525. std::vector<vertex_descriptor>& my_adj = adj[*liter];
  526. my_adj.erase
  527. (std::remove_if(my_adj.begin(), my_adj.end(),
  528. cull_adjacency_list<vertex_descriptor,
  529. ParentMap>(*liter, p) ),
  530. my_adj.end());
  531. #ifndef PBGL_IN_PLACE_MERGE
  532. std::sort(my_adj.begin(), my_adj.end(),
  533. std::less<vertex_descriptor>() );
  534. #endif
  535. my_adj.erase(std::unique(my_adj.begin(), my_adj.end()), my_adj.end());
  536. }
  537. // Reduce result of empty root list test
  538. all_reduce(pg, &hooked, &hooked+1, &any_hooked,
  539. std::logical_or<bool>());
  540. } while ( any_hooked );
  541. #ifdef PARALLEL_BGL_DEBUG
  542. if (id == 0) std::cerr << steps << " iterations.\n";
  543. #endif
  544. //
  545. // Finalize
  546. //
  547. // For each vertex in g, p(v) = p(p(v)), assign parent of leaf
  548. // vertices from first step to final parent
  549. BGL_FORALL_VERTICES_T(v, g, DistributedGraph) {
  550. put(p, v, get(p, get(p, v)));
  551. }
  552. synchronize(p);
  553. }
  554. } // end namespace cc_detail
  555. template<typename Graph, typename ParentMap, typename ComponentMap>
  556. typename property_traits<ComponentMap>::value_type
  557. number_components_from_parents(const Graph& g, ParentMap p, ComponentMap c)
  558. {
  559. typedef typename graph_traits<Graph>::vertex_descriptor
  560. vertex_descriptor;
  561. typedef typename boost::graph::parallel::process_group_type<Graph>::type
  562. process_group_type;
  563. typedef typename property_traits<ComponentMap>::value_type
  564. ComponentMapType;
  565. process_group_type pg = process_group(g);
  566. /* Build list of roots */
  567. std::vector<vertex_descriptor> my_roots, all_roots;
  568. BGL_FORALL_VERTICES_T(v, g, Graph) {
  569. if( std::find( my_roots.begin(), my_roots.end(), get(p, v) )
  570. == my_roots.end() )
  571. my_roots.push_back( get(p, v) );
  572. }
  573. all_gather(pg, my_roots.begin(), my_roots.end(), all_roots);
  574. /* Number components */
  575. std::map<vertex_descriptor, ComponentMapType> comp_numbers;
  576. ComponentMapType c_num = 0;
  577. // Compute component numbers
  578. for (std::size_t i = 0; i < all_roots.size(); i++ )
  579. if ( comp_numbers.count(all_roots[i]) == 0 )
  580. comp_numbers[all_roots[i]] = c_num++;
  581. // Broadcast component numbers
  582. BGL_FORALL_VERTICES_T(v, g, Graph) {
  583. put( c, v, comp_numbers[get(p, v)] );
  584. }
  585. // Broadcast number of components
  586. if (process_id(pg) == 0) {
  587. typedef typename process_group_type::process_size_type
  588. process_size_type;
  589. for (process_size_type dest = 1, n = num_processes(pg);
  590. dest != n; ++dest)
  591. send(pg, dest, 0, c_num);
  592. }
  593. synchronize(pg);
  594. if (process_id(pg) != 0) receive(pg, 0, 0, c_num);
  595. synchronize(c);
  596. return c_num;
  597. }
  598. template<typename Graph, typename ParentMap>
  599. int
  600. number_components_from_parents(const Graph& g, ParentMap p,
  601. dummy_property_map)
  602. {
  603. using boost::parallel::all_reduce;
  604. // Count local roots.
  605. int num_roots = 0;
  606. BGL_FORALL_VERTICES_T(v, g, Graph)
  607. if (get(p, v) == v) ++num_roots;
  608. return all_reduce(g.process_group(), num_roots, std::plus<int>());
  609. }
  610. template<typename Graph, typename ComponentMap, typename ParentMap>
  611. typename property_traits<ComponentMap>::value_type
  612. connected_components
  613. (const Graph& g, ComponentMap c, ParentMap p
  614. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, distributed_graph_tag))
  615. {
  616. cc_detail::parallel_connected_components(g, p);
  617. return number_components_from_parents(g, p, c);
  618. }
  619. /* Construct ParentMap by default */
  620. template<typename Graph, typename ComponentMap>
  621. typename property_traits<ComponentMap>::value_type
  622. connected_components
  623. ( const Graph& g, ComponentMap c
  624. BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, distributed_graph_tag) )
  625. {
  626. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  627. std::vector<vertex_descriptor> x(num_vertices(g));
  628. return connected_components
  629. (g, c,
  630. make_iterator_property_map(x.begin(), get(vertex_index, g)));
  631. }
  632. } // end namespace distributed
  633. using distributed::connected_components;
  634. } // end namespace graph
  635. using graph::distributed::connected_components;
  636. } // end namespace boost
  637. #endif // BOOST_GRAPH_PARALLEL_CC_HPP