File indexing completed on 2025-01-18 09:37:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #ifndef BOOST_DEHNE_GOTZ_MIN_SPANNING_TREE_HPP
0024 #define BOOST_DEHNE_GOTZ_MIN_SPANNING_TREE_HPP
0025
0026 #ifndef BOOST_GRAPH_USE_MPI
0027 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
0028 #endif
0029
0030 #include <boost/graph/graph_traits.hpp>
0031 #include <boost/property_map/property_map.hpp>
0032 #include <boost/property_map/parallel/parallel_property_maps.hpp>
0033 #include <vector>
0034 #include <boost/graph/parallel/algorithm.hpp>
0035 #include <boost/limits.hpp>
0036 #include <utility>
0037 #include <boost/pending/disjoint_sets.hpp>
0038 #include <boost/pending/indirect_cmp.hpp>
0039 #include <boost/property_map/parallel/caching_property_map.hpp>
0040 #include <boost/graph/vertex_and_edge_range.hpp>
0041 #include <boost/graph/kruskal_min_spanning_tree.hpp>
0042 #include <boost/iterator/counting_iterator.hpp>
0043 #include <boost/iterator/transform_iterator.hpp>
0044 #include <boost/graph/parallel/container_traits.hpp>
0045 #include <boost/graph/parallel/detail/untracked_pair.hpp>
0046 #include <cmath>
0047
0048 namespace boost { namespace graph { namespace distributed {
0049
0050 namespace detail {
0051
0052
0053
0054
0055
0056 struct smaller_weighted_edge
0057 {
0058 template<typename Edge, typename Weight>
0059 std::pair<Edge, Weight>
0060 operator()(const std::pair<Edge, Weight>& x,
0061 const std::pair<Edge, Weight>& y) const
0062 { return x.second < y.second? x : y; }
0063 };
0064
0065
0066
0067
0068
0069
0070
0071 template<typename DisjointSets, typename Graph>
0072 class do_has_same_supervertex
0073 {
0074 public:
0075 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
0076
0077 do_has_same_supervertex(DisjointSets& dset, const Graph& g)
0078 : dset(dset), g(g) { }
0079
0080 bool operator()(edge_descriptor e)
0081 { return dset.find_set(source(e, g)) == dset.find_set(target(e, g)); }
0082
0083 private:
0084 DisjointSets& dset;
0085 const Graph& g;
0086 };
0087
0088
0089
0090
0091 template<typename DisjointSets, typename Graph>
0092 inline do_has_same_supervertex<DisjointSets, Graph>
0093 has_same_supervertex(DisjointSets& dset, const Graph& g)
0094 { return do_has_same_supervertex<DisjointSets, Graph>(dset, g); }
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144 template<typename ProcessGroup, typename Graph, typename WeightMap,
0145 typename OutputIterator, typename RankMap, typename ParentMap,
0146 typename SupervertexMap, typename Vertex, typename EdgeList>
0147 OutputIterator
0148 boruvka_merge_step(ProcessGroup pg, const Graph& g, WeightMap weight_map,
0149 OutputIterator out,
0150 disjoint_sets<RankMap, ParentMap>& dset,
0151 SupervertexMap supervertex_map,
0152 std::vector<Vertex>& supervertices,
0153 EdgeList& edge_list)
0154 {
0155 typedef typename graph_traits<Graph>::vertex_descriptor
0156 vertex_descriptor;
0157 typedef typename graph_traits<Graph>::vertices_size_type
0158 vertices_size_type;
0159 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
0160 typedef typename EdgeList::iterator edge_iterator;
0161 typedef typename property_traits<WeightMap>::value_type
0162 weight_type;
0163 typedef boost::parallel::detail::untracked_pair<edge_descriptor,
0164 weight_type> w_edge;
0165 typedef typename property_traits<SupervertexMap>::value_type
0166 supervertex_index;
0167
0168 smaller_weighted_edge min_edge;
0169 weight_type inf = (std::numeric_limits<weight_type>::max)();
0170
0171
0172 for (std::size_t i = 0; i < supervertices.size(); ++i)
0173 put(supervertex_map, supervertices[i], i);
0174
0175
0176 std::vector<w_edge> candidate_edges(supervertices.size(),
0177 w_edge(edge_descriptor(), inf));
0178 for (edge_iterator ei = edge_list.begin(); ei != edge_list.end(); ++ei) {
0179 weight_type w = get(weight_map, *ei);
0180 supervertex_index u =
0181 get(supervertex_map, dset.find_set(source(*ei, g)));
0182 supervertex_index v =
0183 get(supervertex_map, dset.find_set(target(*ei, g)));
0184
0185 if (u != v) {
0186 candidate_edges[u] = min_edge(candidate_edges[u], w_edge(*ei, w));
0187 candidate_edges[v] = min_edge(candidate_edges[v], w_edge(*ei, w));
0188 }
0189 }
0190
0191
0192 all_reduce(pg,
0193 &candidate_edges[0],
0194 &candidate_edges[0] + candidate_edges.size(),
0195 &candidate_edges[0], min_edge);
0196
0197
0198
0199 for (vertices_size_type i = 0; i < candidate_edges.size(); ++i) {
0200 if (candidate_edges[i].second != inf) {
0201 edge_descriptor e = candidate_edges[i].first;
0202 vertex_descriptor u = dset.find_set(source(e, g));
0203 vertex_descriptor v = dset.find_set(target(e, g));
0204 if (u != v) {
0205
0206 cache(weight_map, e, candidate_edges[i].second);
0207 *out++ = e;
0208
0209
0210 dset.link(u, v);
0211
0212
0213
0214 vertex_descriptor victim = u;
0215 if (dset.find_set(u) == u) victim = v;
0216 supervertices[get(supervertex_map, victim)] =
0217 graph_traits<Graph>::null_vertex();
0218 }
0219 }
0220 }
0221
0222
0223 edge_list.erase(std::remove_if(edge_list.begin(), edge_list.end(),
0224 has_same_supervertex(dset, g)),
0225 edge_list.end());
0226
0227
0228
0229
0230
0231
0232 supervertices.erase(std::remove(supervertices.begin(),
0233 supervertices.end(),
0234 graph_traits<Graph>::null_vertex()),
0235 supervertices.end());
0236
0237 return out;
0238 }
0239
0240
0241
0242
0243
0244
0245
0246
0247 template<typename Graph>
0248 struct supervertex_edge_descriptor
0249 {
0250 typedef supervertex_edge_descriptor self_type;
0251 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
0252 typedef typename graph_traits<Graph>::edge_descriptor Edge;
0253
0254 Vertex source;
0255 Vertex target;
0256 Edge e;
0257
0258 operator Edge() const { return e; }
0259
0260 friend inline bool operator==(const self_type& x, const self_type& y)
0261 { return x.e == y.e; }
0262
0263 friend inline bool operator!=(const self_type& x, const self_type& y)
0264 { return x.e != y.e; }
0265 };
0266
0267 template<typename Graph>
0268 inline typename supervertex_edge_descriptor<Graph>::Vertex
0269 source(supervertex_edge_descriptor<Graph> se, const Graph&)
0270 { return se.source; }
0271
0272 template<typename Graph>
0273 inline typename supervertex_edge_descriptor<Graph>::Vertex
0274 target(supervertex_edge_descriptor<Graph> se, const Graph&)
0275 { return se.target; }
0276
0277
0278
0279
0280
0281
0282 template<typename Graph, typename DisjointSets>
0283 struct build_supervertex_edge_descriptor
0284 {
0285 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
0286 typedef typename graph_traits<Graph>::edge_descriptor Edge;
0287
0288 typedef Edge argument_type;
0289 typedef supervertex_edge_descriptor<Graph> result_type;
0290
0291 build_supervertex_edge_descriptor() : g(0), dsets(0) { }
0292
0293 build_supervertex_edge_descriptor(const Graph& g, DisjointSets& dsets)
0294 : g(&g), dsets(&dsets) { }
0295
0296 result_type operator()(argument_type e) const
0297 {
0298 result_type result;
0299 result.source = dsets->find_set(source(e, *g));
0300 result.target = dsets->find_set(target(e, *g));
0301 result.e = e;
0302 return result;
0303 }
0304
0305 private:
0306 const Graph* g;
0307 DisjointSets* dsets;
0308 };
0309
0310 template<typename Graph, typename DisjointSets>
0311 inline build_supervertex_edge_descriptor<Graph, DisjointSets>
0312 make_supervertex_edge_descriptor(const Graph& g, DisjointSets& dsets)
0313 { return build_supervertex_edge_descriptor<Graph, DisjointSets>(g, dsets); }
0314
0315 template<typename T>
0316 struct identity_function
0317 {
0318 typedef T argument_type;
0319 typedef T result_type;
0320
0321 result_type operator()(argument_type x) const { return x; }
0322 };
0323
0324 template<typename Graph, typename DisjointSets, typename EdgeMapper>
0325 class is_not_msf_edge
0326 {
0327 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
0328 typedef typename graph_traits<Graph>::edge_descriptor Edge;
0329
0330 public:
0331 is_not_msf_edge(const Graph& g, DisjointSets dset, EdgeMapper edge_mapper)
0332 : g(g), dset(dset), edge_mapper(edge_mapper) { }
0333
0334 bool operator()(Edge e)
0335 {
0336 Vertex u = dset.find_set(source(edge_mapper(e), g));
0337 Vertex v = dset.find_set(target(edge_mapper(e), g));
0338 if (u == v) return true;
0339 else {
0340 dset.link(u, v);
0341 return false;
0342 }
0343 }
0344
0345 private:
0346 const Graph& g;
0347 DisjointSets dset;
0348 EdgeMapper edge_mapper;
0349 };
0350
0351 template<typename Graph, typename ForwardIterator, typename EdgeList,
0352 typename EdgeMapper, typename RankMap, typename ParentMap>
0353 void
0354 sorted_mutating_kruskal(const Graph& g,
0355 ForwardIterator first_vertex,
0356 ForwardIterator last_vertex,
0357 EdgeList& edge_list, EdgeMapper edge_mapper,
0358 RankMap rank_map, ParentMap parent_map)
0359 {
0360 typedef disjoint_sets<RankMap, ParentMap> DisjointSets;
0361
0362
0363 DisjointSets dset(rank_map, parent_map);
0364 for (ForwardIterator v = first_vertex; v != last_vertex; ++v)
0365 dset.make_set(*v);
0366
0367 is_not_msf_edge<Graph, DisjointSets, EdgeMapper>
0368 remove_non_msf_edges(g, dset, edge_mapper);
0369 edge_list.erase(std::remove_if(edge_list.begin(), edge_list.end(),
0370 remove_non_msf_edges),
0371 edge_list.end());
0372 }
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432 template<typename ProcessGroup, typename Graph, typename ForwardIterator,
0433 typename EdgeList, typename WeightMap, typename GlobalIndexMap,
0434 typename EdgeMapper>
0435 ProcessGroup
0436 merge_local_minimum_spanning_trees_step(ProcessGroup pg,
0437 const Graph& g,
0438 ForwardIterator first_vertex,
0439 ForwardIterator last_vertex,
0440 EdgeList& edge_list,
0441 WeightMap weight,
0442 GlobalIndexMap global_index,
0443 EdgeMapper edge_mapper,
0444 bool already_local_msf)
0445 {
0446 typedef typename ProcessGroup::process_id_type process_id_type;
0447 typedef typename EdgeList::value_type edge_descriptor;
0448 typedef typename property_traits<WeightMap>::value_type weight_type;
0449 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0450
0451
0452 process_id_type const tree_factor = 3;
0453 process_id_type num_procs = num_processes(pg);
0454 process_id_type id = process_id(pg);
0455 process_id_type procs_left = (num_procs + tree_factor - 1) / tree_factor;
0456 std::size_t n = std::size_t(last_vertex - first_vertex);
0457
0458 if (!already_local_msf) {
0459
0460
0461
0462 std::vector<std::size_t> ranks(n);
0463 std::vector<vertex_descriptor> parents(n);
0464 detail::sorted_mutating_kruskal
0465 (g, first_vertex, last_vertex,
0466 edge_list, edge_mapper,
0467 make_iterator_property_map(ranks.begin(), global_index),
0468 make_iterator_property_map(parents.begin(), global_index));
0469 }
0470
0471 typedef std::pair<edge_descriptor, weight_type> w_edge;
0472
0473
0474 indirect_cmp<WeightMap, std::less<weight_type> > cmp_edge_weight(weight);
0475
0476 if (id < procs_left) {
0477
0478
0479 synchronize(pg);
0480 for (process_id_type from_id = procs_left + id; from_id < num_procs;
0481 from_id += procs_left) {
0482 std::size_t num_incoming_edges;
0483 receive(pg, from_id, 0, num_incoming_edges);
0484 if (num_incoming_edges > 0) {
0485 std::vector<w_edge> incoming_edges(num_incoming_edges);
0486 receive(pg, from_id, 1, &incoming_edges[0], num_incoming_edges);
0487
0488 edge_list.reserve(edge_list.size() + num_incoming_edges);
0489 for (std::size_t i = 0; i < num_incoming_edges; ++i) {
0490 cache(weight, incoming_edges[i].first, incoming_edges[i].second);
0491 edge_list.push_back(incoming_edges[i].first);
0492 }
0493 std::inplace_merge(edge_list.begin(),
0494 edge_list.end() - num_incoming_edges,
0495 edge_list.end(),
0496 cmp_edge_weight);
0497 }
0498 }
0499
0500
0501
0502 std::vector<std::size_t> ranks(n);
0503 std::vector<vertex_descriptor> parents(n);
0504 detail::sorted_mutating_kruskal
0505 (g, first_vertex, last_vertex,
0506 edge_list, edge_mapper,
0507 make_iterator_property_map(ranks.begin(), global_index),
0508 make_iterator_property_map(parents.begin(), global_index));
0509 } else {
0510
0511
0512
0513 send(pg, id % procs_left, 0, edge_list.size());
0514 if (edge_list.size() > 0) {
0515 std::vector<w_edge> outgoing_edges;
0516 outgoing_edges.reserve(edge_list.size());
0517 for (std::size_t i = 0; i < edge_list.size(); ++i) {
0518 outgoing_edges.push_back(std::make_pair(edge_list[i],
0519 get(weight, edge_list[i])));
0520 }
0521 send(pg, id % procs_left, 1, &outgoing_edges[0],
0522 outgoing_edges.size());
0523 }
0524 synchronize(pg);
0525 }
0526
0527
0528 return process_subgroup(pg,
0529 make_counting_iterator(process_id_type(0)),
0530 make_counting_iterator(procs_left));
0531 }
0532 }
0533
0534
0535
0536
0537 template<typename Graph, typename WeightMap, typename OutputIterator,
0538 typename VertexIndexMap, typename RankMap, typename ParentMap,
0539 typename SupervertexMap>
0540 OutputIterator
0541 dense_boruvka_minimum_spanning_tree(const Graph& g, WeightMap weight_map,
0542 OutputIterator out,
0543 VertexIndexMap index_map,
0544 RankMap rank_map, ParentMap parent_map,
0545 SupervertexMap supervertex_map)
0546 {
0547 using boost::graph::parallel::process_group;
0548
0549 typedef typename graph_traits<Graph>::traversal_category traversal_category;
0550
0551 BOOST_STATIC_ASSERT((is_convertible<traversal_category*,
0552 vertex_list_graph_tag*>::value));
0553
0554 typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
0555 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0556 typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
0557 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
0558
0559
0560 weight_map.set_max_ghost_cells(0);
0561
0562
0563 disjoint_sets<RankMap, ParentMap> dset(rank_map, parent_map);
0564 vertex_iterator vi, vi_end;
0565 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0566 dset.make_set(*vi);
0567
0568 std::vector<vertex_descriptor> supervertices;
0569 supervertices.assign(vertices(g).first, vertices(g).second);
0570
0571
0572
0573
0574
0575
0576
0577 std::vector<edge_descriptor> edge_list;
0578 kruskal_minimum_spanning_tree
0579 (make_vertex_and_edge_range(g, vertices(g).first, vertices(g).second,
0580 edges(g).first, edges(g).second),
0581 std::back_inserter(edge_list),
0582 boost::weight_map(weight_map).
0583 vertex_index_map(index_map));
0584
0585
0586
0587
0588 vertices_size_type old_num_supervertices;
0589 do {
0590 old_num_supervertices = supervertices.size();
0591 out = detail::boruvka_merge_step(process_group(g), g,
0592 weight_map, out,
0593 dset, supervertex_map, supervertices,
0594 edge_list);
0595 } while (supervertices.size() < old_num_supervertices);
0596
0597 return out;
0598 }
0599
0600 template<typename Graph, typename WeightMap, typename OutputIterator,
0601 typename VertexIndex>
0602 OutputIterator
0603 dense_boruvka_minimum_spanning_tree(const Graph& g, WeightMap weight_map,
0604 OutputIterator out, VertexIndex i_map)
0605 {
0606 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0607
0608 std::vector<std::size_t> ranks(num_vertices(g));
0609 std::vector<vertex_descriptor> parents(num_vertices(g));
0610 std::vector<std::size_t> supervertices(num_vertices(g));
0611
0612 return dense_boruvka_minimum_spanning_tree
0613 (g, weight_map, out, i_map,
0614 make_iterator_property_map(ranks.begin(), i_map),
0615 make_iterator_property_map(parents.begin(), i_map),
0616 make_iterator_property_map(supervertices.begin(), i_map));
0617 }
0618
0619 template<typename Graph, typename WeightMap, typename OutputIterator>
0620 OutputIterator
0621 dense_boruvka_minimum_spanning_tree(const Graph& g, WeightMap weight_map,
0622 OutputIterator out)
0623 {
0624 return dense_boruvka_minimum_spanning_tree(g, weight_map, out,
0625 get(vertex_index, g));
0626 }
0627
0628
0629
0630
0631 template<typename Graph, typename WeightMap, typename OutputIterator,
0632 typename GlobalIndexMap>
0633 OutputIterator
0634 merge_local_minimum_spanning_trees(const Graph& g, WeightMap weight,
0635 OutputIterator out,
0636 GlobalIndexMap global_index)
0637 {
0638 using boost::graph::parallel::process_group_type;
0639 using boost::graph::parallel::process_group;
0640
0641 typedef typename graph_traits<Graph>::traversal_category traversal_category;
0642
0643 BOOST_STATIC_ASSERT((is_convertible<traversal_category*,
0644 vertex_list_graph_tag*>::value));
0645
0646 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
0647
0648
0649 weight.set_max_ghost_cells(0);
0650
0651
0652 std::vector<edge_descriptor> edge_list;
0653 kruskal_minimum_spanning_tree
0654 (make_vertex_and_edge_range(g, vertices(g).first, vertices(g).second,
0655 edges(g).first, edges(g).second),
0656 std::back_inserter(edge_list),
0657 boost::weight_map(weight).vertex_index_map(global_index));
0658
0659
0660
0661
0662
0663
0664 typename process_group_type<Graph>::type pg = process_group(g);
0665 while (pg && num_processes(pg) > 1) {
0666 pg = detail::merge_local_minimum_spanning_trees_step
0667 (pg, g, vertices(g).first, vertices(g).second,
0668 edge_list, weight, global_index,
0669 detail::identity_function<edge_descriptor>(), true);
0670 }
0671
0672
0673
0674 if (pg && process_id(pg) == 0) {
0675 out = std::copy(edge_list.begin(), edge_list.end(), out);
0676 }
0677
0678 synchronize(process_group(g));
0679 return out;
0680 }
0681
0682 template<typename Graph, typename WeightMap, typename OutputIterator>
0683 inline OutputIterator
0684 merge_local_minimum_spanning_trees(const Graph& g, WeightMap weight,
0685 OutputIterator out)
0686 {
0687 return merge_local_minimum_spanning_trees(g, weight, out,
0688 get(vertex_index, g));
0689 }
0690
0691
0692
0693
0694 template<typename Graph, typename WeightMap, typename OutputIterator,
0695 typename GlobalIndexMap, typename RankMap, typename ParentMap,
0696 typename SupervertexMap>
0697 OutputIterator
0698 boruvka_then_merge(const Graph& g, WeightMap weight, OutputIterator out,
0699 GlobalIndexMap index, RankMap rank_map,
0700 ParentMap parent_map, SupervertexMap supervertex_map)
0701 {
0702 using std::log;
0703 using boost::graph::parallel::process_group_type;
0704 using boost::graph::parallel::process_group;
0705
0706 typedef typename graph_traits<Graph>::traversal_category traversal_category;
0707
0708 BOOST_STATIC_ASSERT((is_convertible<traversal_category*,
0709 vertex_list_graph_tag*>::value));
0710
0711 typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
0712 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0713 typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
0714 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
0715
0716
0717 weight.set_max_ghost_cells(0);
0718
0719
0720 std::vector<edge_descriptor> edge_list;
0721 kruskal_minimum_spanning_tree
0722 (make_vertex_and_edge_range(g, vertices(g).first, vertices(g).second,
0723 edges(g).first, edges(g).second),
0724 std::back_inserter(edge_list),
0725 boost::weight_map(weight).
0726 vertex_index_map(index));
0727
0728
0729 disjoint_sets<RankMap, ParentMap> dset(rank_map, parent_map);
0730 vertex_iterator vi, vi_end;
0731 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0732 dset.make_set(*vi);
0733
0734
0735 std::vector<vertex_descriptor> supervertices;
0736 supervertices.assign(vertices(g).first, vertices(g).second);
0737
0738
0739
0740 const std::size_t tree_factor = 3;
0741 double log_d_p = log((double)num_processes(process_group(g)))
0742 / log((double)tree_factor);
0743 vertices_size_type target_supervertices =
0744 vertices_size_type(num_vertices(g) / (log_d_p * log_d_p));
0745 vertices_size_type old_num_supervertices;
0746 while (supervertices.size() > target_supervertices) {
0747 old_num_supervertices = supervertices.size();
0748 out = detail::boruvka_merge_step(process_group(g), g,
0749 weight, out, dset,
0750 supervertex_map, supervertices,
0751 edge_list);
0752 if (supervertices.size() == old_num_supervertices)
0753 return out;
0754 }
0755
0756
0757 for (std::size_t i = 0; i < supervertices.size(); ++i)
0758 put(supervertex_map, supervertices[i], i);
0759
0760
0761
0762 typename process_group_type<Graph>::type pg = process_group(g);
0763 bool have_msf = false;
0764 while (pg && num_processes(pg) > 1) {
0765 pg = detail::merge_local_minimum_spanning_trees_step
0766 (pg, g, supervertices.begin(), supervertices.end(),
0767 edge_list, weight, supervertex_map,
0768 detail::make_supervertex_edge_descriptor(g, dset),
0769 have_msf);
0770 have_msf = true;
0771 }
0772
0773
0774
0775
0776
0777
0778 if (pg && process_id(pg) == 0)
0779 out = std::copy(edge_list.begin(), edge_list.end(), out);
0780
0781 synchronize(process_group(g));
0782 return out;
0783 }
0784
0785 template<typename Graph, typename WeightMap, typename OutputIterator,
0786 typename GlobalIndexMap>
0787 inline OutputIterator
0788 boruvka_then_merge(const Graph& g, WeightMap weight, OutputIterator out,
0789 GlobalIndexMap index)
0790 {
0791 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0792 typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
0793 std::vector<vertices_size_type> ranks(num_vertices(g));
0794 std::vector<vertex_descriptor> parents(num_vertices(g));
0795 std::vector<vertices_size_type> supervertex_indices(num_vertices(g));
0796
0797 return boruvka_then_merge
0798 (g, weight, out, index,
0799 make_iterator_property_map(ranks.begin(), index),
0800 make_iterator_property_map(parents.begin(), index),
0801 make_iterator_property_map(supervertex_indices.begin(), index));
0802 }
0803
0804 template<typename Graph, typename WeightMap, typename OutputIterator>
0805 inline OutputIterator
0806 boruvka_then_merge(const Graph& g, WeightMap weight, OutputIterator out)
0807 { return boruvka_then_merge(g, weight, out, get(vertex_index, g)); }
0808
0809
0810
0811
0812 template<typename Graph, typename WeightMap, typename OutputIterator,
0813 typename GlobalIndexMap, typename RankMap, typename ParentMap,
0814 typename SupervertexMap>
0815 OutputIterator
0816 boruvka_mixed_merge(const Graph& g, WeightMap weight, OutputIterator out,
0817 GlobalIndexMap index, RankMap rank_map,
0818 ParentMap parent_map, SupervertexMap supervertex_map)
0819 {
0820 using boost::graph::parallel::process_group_type;
0821 using boost::graph::parallel::process_group;
0822
0823 typedef typename graph_traits<Graph>::traversal_category traversal_category;
0824
0825 BOOST_STATIC_ASSERT((is_convertible<traversal_category*,
0826 vertex_list_graph_tag*>::value));
0827
0828 typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
0829 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0830 typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
0831 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
0832
0833
0834 weight.set_max_ghost_cells(0);
0835
0836
0837 disjoint_sets<RankMap, ParentMap> dset(rank_map, parent_map);
0838 vertex_iterator vi, vi_end;
0839 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0840 dset.make_set(*vi);
0841
0842
0843 std::vector<vertex_descriptor> supervertices;
0844 supervertices.assign(vertices(g).first, vertices(g).second);
0845
0846
0847 std::vector<edge_descriptor> edge_list;
0848 kruskal_minimum_spanning_tree
0849 (make_vertex_and_edge_range(g, vertices(g).first, vertices(g).second,
0850 edges(g).first, edges(g).second),
0851 std::back_inserter(edge_list),
0852 boost::weight_map(weight).
0853 vertex_index_map(index));
0854
0855 if (num_processes(process_group(g)) == 1) {
0856 return std::copy(edge_list.begin(), edge_list.end(), out);
0857 }
0858
0859
0860
0861
0862
0863
0864
0865 typename process_group_type<Graph>::type pg = process_group(g);
0866 vertices_size_type old_num_supervertices;
0867 while (pg && num_processes(pg) > 1) {
0868
0869 old_num_supervertices = supervertices.size();
0870 out = detail::boruvka_merge_step(pg, g, weight, out, dset,
0871 supervertex_map, supervertices,
0872 edge_list);
0873 if (old_num_supervertices == supervertices.size()) {
0874 edge_list.clear();
0875 break;
0876 }
0877
0878
0879 for (std::size_t i = 0; i < supervertices.size(); ++i)
0880 put(supervertex_map, supervertices[i], i);
0881
0882
0883
0884 pg = detail::merge_local_minimum_spanning_trees_step
0885 (pg, g, supervertices.begin(), supervertices.end(),
0886 edge_list, weight, supervertex_map,
0887 detail::make_supervertex_edge_descriptor(g, dset),
0888 true);
0889
0890 }
0891
0892
0893
0894
0895
0896
0897 if (pg && process_id(pg) == 0)
0898 out = std::copy(edge_list.begin(), edge_list.end(), out);
0899
0900 synchronize(process_group(g));
0901 return out;
0902 }
0903
0904 template<typename Graph, typename WeightMap, typename OutputIterator,
0905 typename GlobalIndexMap>
0906 inline OutputIterator
0907 boruvka_mixed_merge(const Graph& g, WeightMap weight, OutputIterator out,
0908 GlobalIndexMap index)
0909 {
0910 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0911 typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
0912 std::vector<vertices_size_type> ranks(num_vertices(g));
0913 std::vector<vertex_descriptor> parents(num_vertices(g));
0914 std::vector<vertices_size_type> supervertex_indices(num_vertices(g));
0915
0916 return boruvka_mixed_merge
0917 (g, weight, out, index,
0918 make_iterator_property_map(ranks.begin(), index),
0919 make_iterator_property_map(parents.begin(), index),
0920 make_iterator_property_map(supervertex_indices.begin(), index));
0921 }
0922
0923 template<typename Graph, typename WeightMap, typename OutputIterator>
0924 inline OutputIterator
0925 boruvka_mixed_merge(const Graph& g, WeightMap weight, OutputIterator out)
0926 { return boruvka_mixed_merge(g, weight, out, get(vertex_index, g)); }
0927
0928 }
0929
0930 using distributed::dense_boruvka_minimum_spanning_tree;
0931 using distributed::merge_local_minimum_spanning_trees;
0932 using distributed::boruvka_then_merge;
0933 using distributed::boruvka_mixed_merge;
0934
0935 } }
0936
0937
0938 #endif