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

http://hadesmem.googlecode.com/ · C++ Header · 769 lines · 543 code · 127 blank · 99 comment · 112 complexity · f9964bf509734f553619d93f7af572fd MD5 · raw file

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