File indexing completed on 2025-01-18 09:37:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_GRAPH_DISTRIBUTED_HOHBERG_BICONNECTED_COMPONENTS_HPP
0017 #define BOOST_GRAPH_DISTRIBUTED_HOHBERG_BICONNECTED_COMPONENTS_HPP
0018
0019 #ifndef BOOST_GRAPH_USE_MPI
0020 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
0021 #endif
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #include <boost/graph/graph_traits.hpp>
0033 #include <boost/graph/parallel/container_traits.hpp>
0034 #include <boost/graph/parallel/process_group.hpp>
0035 #include <boost/static_assert.hpp>
0036 #include <boost/mpi/operations.hpp>
0037 #include <boost/type_traits/is_convertible.hpp>
0038 #include <boost/graph/graph_concepts.hpp>
0039 #include <boost/graph/iteration_macros.hpp>
0040 #include <boost/optional.hpp>
0041 #include <utility> // for std::pair
0042 #include <boost/assert.hpp>
0043 #include <algorithm> // for std::find, std::mismatch
0044 #include <vector>
0045 #include <boost/graph/parallel/algorithm.hpp>
0046 #include <boost/graph/distributed/connected_components.hpp>
0047 #include <boost/concept/assert.hpp>
0048
0049 namespace boost { namespace graph { namespace distributed {
0050
0051 namespace hohberg_detail {
0052 enum message_kind {
0053
0054
0055
0056 msg_path_header,
0057
0058
0059
0060 msg_path_vertices,
0061
0062
0063
0064 msg_tree_header,
0065
0066
0067
0068
0069 msg_tree_vertices,
0070
0071 msg_name
0072 };
0073
0074
0075 template<typename EdgeDescriptor>
0076 struct path_header
0077 {
0078
0079 EdgeDescriptor edge;
0080
0081
0082
0083 std::size_t path_length;
0084
0085 template<typename Archiver>
0086 void serialize(Archiver& ar, const unsigned int )
0087 {
0088 ar & edge & path_length;
0089 }
0090 };
0091
0092
0093 template<typename Vertex, typename Edge>
0094 struct tree_header
0095 {
0096
0097 Edge edge;
0098
0099
0100 Vertex gamma;
0101
0102
0103
0104
0105 std::size_t bicomp_length;
0106
0107 template<typename Archiver>
0108 void serialize(Archiver& ar, const unsigned int )
0109 {
0110 ar & edge & gamma & bicomp_length;
0111 }
0112 };
0113
0114
0115 template<typename EdgeDescriptor>
0116 struct name_header
0117 {
0118
0119 EdgeDescriptor edge;
0120
0121
0122 std::size_t name;
0123
0124 template<typename Archiver>
0125 void serialize(Archiver& ar, const unsigned int )
0126 {
0127 ar & edge & name;
0128 }
0129 };
0130
0131
0132
0133
0134
0135
0136
0137 template<typename T>
0138 T branch_point(const std::vector<T>& p1, const std::vector<T>& p2)
0139 {
0140 BOOST_ASSERT(!p1.empty());
0141 BOOST_ASSERT(!p2.empty());
0142 BOOST_ASSERT(p1.front() == p2.front());
0143
0144 typedef typename std::vector<T>::const_iterator iterator;
0145
0146 iterator mismatch_pos;
0147 if (p1.size() <= p2.size())
0148 mismatch_pos = std::mismatch(p1.begin(), p1.end(), p2.begin()).first;
0149 else
0150 mismatch_pos = std::mismatch(p2.begin(), p2.end(), p1.begin()).first;
0151 --mismatch_pos;
0152 return *mismatch_pos;
0153 }
0154
0155
0156
0157
0158 template<typename T>
0159 T infimum(const std::vector<T>& parent_path, T a, T b)
0160 {
0161 using std::swap;
0162
0163 typedef typename std::vector<T>::const_iterator iterator;
0164 iterator first = parent_path.begin(), last = parent_path.end();
0165
0166 #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
0167 std::cerr << "infimum(";
0168 for (iterator i = first; i != last; ++i) {
0169 if (i != first) std::cerr << ' ';
0170 std::cerr << local(*i) << '@' << owner(*i);
0171 }
0172 std::cerr << ", " << local(a) << '@' << owner(a) << ", "
0173 << local(b) << '@' << owner(b) << ") = ";
0174 #endif
0175
0176 if (a == b) {
0177 #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
0178 std::cerr << local(a) << '@' << owner(a) << std::endl;
0179 #endif
0180 return a;
0181 }
0182
0183
0184 --last;
0185 while (*last != a) {
0186
0187 if (*last == b) { swap(a,b); break; }
0188
0189 if (last == first) {
0190 #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
0191 std::cerr << local(*first) << '@' << owner(*first) << std::endl;
0192 #endif
0193 return *first;
0194 }
0195 else --last;
0196 }
0197
0198
0199 while (*last != b) {
0200 if (last == first) {
0201 #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
0202 std::cerr << local(*first) << '@' << owner(*first) << std::endl;
0203 #endif
0204 return *first;
0205 }
0206 else --last;
0207 }
0208
0209 #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
0210 std::cerr << local(*last) << '@' << owner(*last) << std::endl;
0211 #endif
0212
0213 return *last;
0214 }
0215 }
0216
0217
0218 template<typename Graph>
0219 struct hohberg_message
0220 {
0221 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
0222 typedef typename graph_traits<Graph>::edge_descriptor Edge;
0223
0224
0225 void assign(const std::vector<Vertex>& path)
0226 {
0227 gamma = graph_traits<Graph>::null_vertex();
0228 path_or_bicomp = path;
0229 }
0230
0231
0232 void assign(Vertex gamma, const std::vector<Vertex>& in_same_bicomponent)
0233 {
0234 this->gamma = gamma;
0235 path_or_bicomp = in_same_bicomponent;
0236 }
0237
0238 bool is_path() const { return gamma == graph_traits<Graph>::null_vertex(); }
0239 bool is_tree() const { return gamma != graph_traits<Graph>::null_vertex(); }
0240
0241
0242 Vertex gamma;
0243
0244
0245 std::vector<Vertex> path_or_bicomp;
0246 };
0247
0248
0249
0250
0251
0252 template<typename Graph>
0253 class hohberg_vertex_processor
0254 {
0255 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
0256 typedef typename graph_traits<Graph>::edge_descriptor Edge;
0257 typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
0258 typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
0259 typedef typename boost::graph::parallel::process_group_type<Graph>::type
0260 ProcessGroup;
0261 typedef std::vector<Vertex> path_t;
0262 typedef typename path_t::iterator path_iterator;
0263
0264 public:
0265 hohberg_vertex_processor()
0266 : phase(1),
0267 parent(graph_traits<Graph>::null_vertex()),
0268 eta(graph_traits<Graph>::null_vertex())
0269 {
0270 }
0271
0272
0273
0274
0275 void initialize_leader(Vertex alpha, const Graph& g);
0276
0277
0278
0279 void
0280 operator()(Edge e, path_t& path, const Graph& g);
0281
0282
0283
0284 void
0285 operator()(Edge e, Vertex gamma, path_t& in_same_bicomponent,
0286 const Graph& g);
0287
0288
0289 void operator()(Edge e, edges_size_type name, const Graph& g);
0290
0291
0292 unsigned char get_phase() const { return phase; }
0293
0294
0295
0296
0297
0298
0299 void
0300 start_naming_phase(Vertex alpha, const Graph& g, edges_size_type offset);
0301
0302
0303
0304
0305 edges_size_type num_starting_bicomponents(Vertex alpha, const Graph& g);
0306
0307
0308
0309 template<typename ComponentMap>
0310 void fill_edge_map(Vertex alpha, const Graph& g, ComponentMap& component);
0311
0312 protected:
0313
0314
0315 void echo_phase(Vertex alpha, const Graph& g);
0316
0317
0318 std::size_t get_edge_index(Edge e, const Graph& g);
0319
0320
0321
0322 std::size_t get_incident_edge_index(Vertex u, Vertex v, const Graph& g);
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333 unsigned char phase;
0334
0335
0336
0337 Vertex parent;
0338
0339
0340
0341
0342
0343 Vertex eta;
0344
0345
0346
0347
0348
0349
0350
0351
0352 degree_size_type num_edges_not_transmitted;
0353
0354
0355
0356
0357
0358 std::vector<Vertex> path_from_root;
0359
0360
0361
0362
0363
0364 struct per_edge_data
0365 {
0366 hohberg_message<Graph> msg;
0367 std::vector<Vertex> M;
0368 bool is_tree_edge;
0369 degree_size_type partition;
0370 };
0371
0372
0373
0374 std::vector<per_edge_data> edge_data;
0375
0376
0377
0378 std::vector<edges_size_type> local_to_global_partitions;
0379
0380 friend class boost::serialization::access;
0381
0382
0383
0384
0385
0386 template<typename Archiver>
0387 void serialize(Archiver&, const unsigned int )
0388 {
0389 BOOST_ASSERT(false);
0390 }
0391 };
0392
0393 template<typename Graph>
0394 void
0395 hohberg_vertex_processor<Graph>::initialize_leader(Vertex alpha,
0396 const Graph& g)
0397 {
0398 using namespace hohberg_detail;
0399
0400 ProcessGroup pg = process_group(g);
0401
0402 typename property_map<Graph, vertex_owner_t>::const_type
0403 owner = get(vertex_owner, g);
0404
0405 path_header<Edge> header;
0406 header.path_length = 1;
0407 BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
0408 header.edge = e;
0409 send(pg, get(owner, target(e, g)), msg_path_header, header);
0410 send(pg, get(owner, target(e, g)), msg_path_vertices, alpha);
0411 }
0412
0413 num_edges_not_transmitted = degree(alpha, g);
0414 edge_data.resize(num_edges_not_transmitted);
0415 phase = 2;
0416 }
0417
0418 template<typename Graph>
0419 void
0420 hohberg_vertex_processor<Graph>::operator()(Edge e, path_t& path,
0421 const Graph& g)
0422 {
0423 using namespace hohberg_detail;
0424
0425 typename property_map<Graph, vertex_owner_t>::const_type
0426 owner = get(vertex_owner, g);
0427
0428 #ifdef PBGL_HOHBERG_DEBUG
0429
0430
0431
0432
0433
0434
0435 std::cerr << "), phase = " << (int)phase << std::endl;
0436 #endif
0437
0438
0439 if (edge_data.empty())
0440 edge_data.resize(degree(target(e, g), g));
0441 per_edge_data& edata = edge_data[get_edge_index(e, g)];
0442
0443
0444 edata.msg.assign(path);
0445
0446
0447
0448 Vertex alpha = target(e, g);
0449
0450 switch (phase) {
0451 case 1:
0452 {
0453 num_edges_not_transmitted = degree(alpha, g) - 1;
0454 edata.is_tree_edge = true;
0455 parent = path.back();
0456 eta = parent;
0457 edata.M.clear(); edata.M.push_back(parent);
0458
0459
0460
0461 path.push_back(alpha);
0462 path_header<Edge> header;
0463 header.path_length = path.size();
0464 ProcessGroup pg = process_group(g);
0465 BGL_FORALL_OUTEDGES_T(alpha, oe, g, Graph) {
0466
0467 if (target(oe, g) != source(e, g)) {
0468 header.edge = oe;
0469 send(pg, get(owner, target(oe, g)), msg_path_header, header);
0470 send(pg, get(owner, target(oe, g)), msg_path_vertices, &path[0],
0471 header.path_length);
0472 }
0473 }
0474 path.pop_back();
0475
0476
0477 path_from_root.swap(path);
0478
0479
0480
0481 phase = 2;
0482
0483
0484 if (num_edges_not_transmitted == 0)
0485 echo_phase(alpha, g);
0486 return;
0487 }
0488
0489 case 2:
0490 {
0491 --num_edges_not_transmitted;
0492 edata.is_tree_edge = false;
0493
0494
0495 path_iterator pos = std::find(path.begin(), path.end(), alpha);
0496 if (pos != path.end()) {
0497
0498
0499 edata.M.clear();
0500 ++pos;
0501
0502 if (pos != path.end()) {
0503
0504 edata.M.push_back(*pos);
0505 ++pos;
0506 }
0507
0508
0509 if (pos != path.end()) edata.M.push_back(path.back());
0510 } else {
0511
0512
0513 edata.M.clear();
0514 edata.M.push_back(path.back());
0515 if (parent != path.back()) edata.M.push_back(parent);
0516
0517
0518 eta = infimum(path_from_root, eta, branch_point(path_from_root, path));
0519 }
0520 if (num_edges_not_transmitted == 0)
0521 echo_phase(alpha, g);
0522 break;
0523 }
0524
0525 default:
0526
0527 BOOST_ASSERT(false);
0528 }
0529 }
0530
0531 template<typename Graph>
0532 void
0533 hohberg_vertex_processor<Graph>::operator()(Edge e, Vertex gamma,
0534 path_t& in_same_bicomponent,
0535 const Graph& g)
0536 {
0537 using namespace hohberg_detail;
0538
0539 #ifdef PBGL_HOHBERG_DEBUG
0540 std::cerr << local(source(e, g)) << '@' << owner(source(e, g)) << " -> "
0541 << local(target(e, g)) << '@' << owner(target(e, g)) << ": tree("
0542 << local(gamma) << '@' << owner(gamma) << ", ";
0543 for (std::size_t i = 0; i < in_same_bicomponent.size(); ++i) {
0544 if (i > 0) std::cerr << ' ';
0545 std::cerr << local(in_same_bicomponent[i]) << '@'
0546 << owner(in_same_bicomponent[i]);
0547 }
0548 std::cerr << ", " << local(source(e, g)) << '@' << owner(source(e, g))
0549 << "), phase = " << (int)phase << std::endl;
0550 #endif
0551
0552
0553 per_edge_data& edata = edge_data[get_edge_index(e, g)];
0554
0555
0556 edata.msg.assign(gamma, in_same_bicomponent);
0557
0558
0559
0560 Vertex alpha = target(e, g);
0561 Vertex beta = source(e, g);
0562
0563 switch (phase) {
0564 case 2:
0565 --num_edges_not_transmitted;
0566 edata.is_tree_edge = true;
0567
0568 if (gamma == alpha) {
0569
0570 edata.M.swap(in_same_bicomponent);
0571 } else {
0572
0573 edata.M.clear();
0574 edata.M.push_back(parent);
0575 if (beta != parent) edata.M.push_back(beta);
0576 eta = infimum(path_from_root, eta, gamma);
0577 }
0578 if (num_edges_not_transmitted == 0)
0579 echo_phase(alpha, g);
0580 break;
0581
0582 default:
0583 BOOST_ASSERT(false);
0584 }
0585 }
0586
0587 template<typename Graph>
0588 void
0589 hohberg_vertex_processor<Graph>::operator()(Edge e, edges_size_type name,
0590 const Graph& g)
0591 {
0592 using namespace hohberg_detail;
0593
0594 #ifdef PBGL_HOHBERG_DEBUG
0595 std::cerr << local(source(e, g)) << '@' << owner(source(e, g)) << " -> "
0596 << local(target(e, g)) << '@' << owner(target(e, g)) << ": name("
0597 << name << "), phase = " << (int)phase << std::endl;
0598 #endif
0599
0600 BOOST_ASSERT(phase == 4);
0601
0602 typename property_map<Graph, vertex_owner_t>::const_type
0603 owner = get(vertex_owner, g);
0604
0605
0606
0607 ProcessGroup pg = process_group(g);
0608
0609 Vertex alpha = target(e, g);
0610
0611 std::size_t idx = 0;
0612 BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
0613 per_edge_data& edata = edge_data[idx++];
0614 if (edata.is_tree_edge
0615 && find(edata.M.begin(), edata.M.end(), parent) != edata.M.end()
0616 && target(e, g) != parent) {
0617
0618 name_header<Edge> header;
0619 header.edge = e;
0620 header.name = name;
0621 send(pg, get(owner, target(e, g)), msg_name, header);
0622 } else if (target(e, g) == parent) {
0623
0624 local_to_global_partitions[edata.partition] = name;
0625 }
0626 }
0627
0628
0629 phase = 5;
0630 }
0631
0632 template<typename Graph>
0633 typename hohberg_vertex_processor<Graph>::edges_size_type
0634 hohberg_vertex_processor<Graph>::
0635 num_starting_bicomponents(Vertex alpha, const Graph& g)
0636 {
0637 edges_size_type not_mapped = (std::numeric_limits<edges_size_type>::max)();
0638
0639 edges_size_type result = 0;
0640 std::size_t idx = 0;
0641 BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
0642 per_edge_data& edata = edge_data[idx++];
0643 if (edata.is_tree_edge
0644 && find(edata.M.begin(), edata.M.end(), parent) == edata.M.end()) {
0645
0646 if (local_to_global_partitions[edata.partition] == not_mapped)
0647 local_to_global_partitions[edata.partition] = result++;
0648 }
0649 }
0650
0651 #ifdef PBGL_HOHBERG_DEBUG
0652 std::cerr << local(alpha) << '@' << owner(alpha) << " has " << result
0653 << " bicomponents originating at it." << std::endl;
0654 #endif
0655
0656 return result;
0657 }
0658
0659 template<typename Graph>
0660 template<typename ComponentMap>
0661 void
0662 hohberg_vertex_processor<Graph>::
0663 fill_edge_map(Vertex alpha, const Graph& g, ComponentMap& component)
0664 {
0665 std::size_t idx = 0;
0666 BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
0667 per_edge_data& edata = edge_data[idx++];
0668 local_put(component, e, local_to_global_partitions[edata.partition]);
0669
0670 #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
0671 std::cerr << "component("
0672 << local(source(e, g)) << '@' << owner(source(e, g)) << " -> "
0673 << local(target(e, g)) << '@' << owner(target(e, g)) << ") = "
0674 << local_to_global_partitions[edata.partition]
0675 << " (partition = " << edata.partition << " of "
0676 << local_to_global_partitions.size() << ")" << std::endl;
0677 #endif
0678 }
0679 }
0680
0681 template<typename Graph>
0682 void
0683 hohberg_vertex_processor<Graph>::
0684 start_naming_phase(Vertex alpha, const Graph& g, edges_size_type offset)
0685 {
0686 using namespace hohberg_detail;
0687
0688 BOOST_ASSERT(phase == 4);
0689
0690 typename property_map<Graph, vertex_owner_t>::const_type
0691 owner = get(vertex_owner, g);
0692
0693
0694
0695 ProcessGroup pg = process_group(g);
0696
0697 bool has_more_children_to_name = false;
0698
0699
0700 edges_size_type not_mapped = (std::numeric_limits<edges_size_type>::max)();
0701 for (std::size_t i = 0; i < local_to_global_partitions.size(); ++i) {
0702 if (local_to_global_partitions[i] != not_mapped)
0703 local_to_global_partitions[i] += offset;
0704 }
0705
0706 std::size_t idx = 0;
0707 BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
0708 per_edge_data& edata = edge_data[idx++];
0709 if (edata.is_tree_edge
0710 && find(edata.M.begin(), edata.M.end(), parent) == edata.M.end()) {
0711
0712 name_header<Edge> header;
0713 header.edge = e;
0714 header.name = local_to_global_partitions[edata.partition];
0715 send(pg, get(owner, target(e, g)), msg_name, header);
0716 } else if (edata.is_tree_edge) {
0717 has_more_children_to_name = true;
0718 }
0719 #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
0720 std::cerr << "M[" << local(source(e, g)) << '@' << owner(source(e, g))
0721 << " -> " << local(target(e, g)) << '@' << owner(target(e, g))
0722 << "] = ";
0723 for (std::size_t i = 0; i < edata.M.size(); ++i) {
0724 std::cerr << local(edata.M[i]) << '@' << owner(edata.M[i]) << ' ';
0725 }
0726 std::cerr << std::endl;
0727 #endif
0728 }
0729
0730
0731 if (!has_more_children_to_name)
0732
0733 phase = 5;
0734 }
0735
0736 template<typename Graph>
0737 void
0738 hohberg_vertex_processor<Graph>::echo_phase(Vertex alpha, const Graph& g)
0739 {
0740 using namespace hohberg_detail;
0741
0742 typename property_map<Graph, vertex_owner_t>::const_type
0743 owner = get(vertex_owner, g);
0744
0745
0746 phase = 3;
0747
0748 if (parent != graph_traits<Graph>::null_vertex()) {
0749 Edge edge_to_parent;
0750
0751 #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 1
0752 std::cerr << local(alpha) << '@' << owner(alpha) << " echo: parent = "
0753 << local(parent) << '@' << owner(parent) << ", eta = "
0754 << local(eta) << '@' << owner(eta) << ", Gamma = ";
0755 #endif
0756
0757 std::vector<Vertex> bicomp;
0758 std::size_t e_index = 0;
0759 BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
0760 if (target(e, g) == parent && parent == eta) {
0761 edge_to_parent = e;
0762 if (find(bicomp.begin(), bicomp.end(), alpha) == bicomp.end()) {
0763 #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 1
0764 std::cerr << local(alpha) << '@' << owner(alpha) << ' ';
0765 #endif
0766 bicomp.push_back(alpha);
0767 }
0768 } else {
0769 if (target(e, g) == parent) edge_to_parent = e;
0770
0771 per_edge_data& edata = edge_data[e_index];
0772
0773 if (edata.msg.is_path()) {
0774 path_iterator pos = std::find(edata.msg.path_or_bicomp.begin(),
0775 edata.msg.path_or_bicomp.end(),
0776 eta);
0777 if (pos != edata.msg.path_or_bicomp.end()) {
0778 ++pos;
0779 if (pos != edata.msg.path_or_bicomp.end()
0780 && find(bicomp.begin(), bicomp.end(), *pos) == bicomp.end()) {
0781 #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 1
0782 std::cerr << local(*pos) << '@' << owner(*pos) << ' ';
0783 #endif
0784 bicomp.push_back(*pos);
0785 }
0786 }
0787 } else if (edata.msg.is_tree() && edata.msg.gamma == eta) {
0788 for (path_iterator i = edata.msg.path_or_bicomp.begin();
0789 i != edata.msg.path_or_bicomp.end(); ++i) {
0790 if (find(bicomp.begin(), bicomp.end(), *i) == bicomp.end()) {
0791 #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 1
0792 std::cerr << local(*i) << '@' << owner(*i) << ' ';
0793 #endif
0794 bicomp.push_back(*i);
0795 }
0796 }
0797 }
0798 }
0799 ++e_index;
0800 }
0801 #ifdef PBGL_HOHBERG_DEBUG
0802 std::cerr << std::endl;
0803 #endif
0804
0805
0806 tree_header<Vertex, Edge> header;
0807 header.edge = edge_to_parent;
0808 header.gamma = eta;
0809 header.bicomp_length = bicomp.size();
0810 ProcessGroup pg = process_group(g);
0811 send(pg, get(owner, parent), msg_tree_header, header);
0812 send(pg, get(owner, parent), msg_tree_vertices, &bicomp[0],
0813 header.bicomp_length);
0814 }
0815
0816
0817
0818
0819
0820 std::vector<degree_size_type> parent_vec(edge_data.size());
0821 degree_size_type idx = 0;
0822 for (idx = 0; idx < edge_data.size(); ++idx)
0823 parent_vec[idx] = idx;
0824
0825
0826
0827 idx = 0;
0828 BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
0829 per_edge_data& edata = edge_data[idx++];
0830
0831
0832 if (!edata.M.empty()) {
0833 degree_size_type e1 = get_incident_edge_index(alpha, edata.M.front(), g);
0834 while (parent_vec[e1] != e1) e1 = parent_vec[e1];
0835
0836 for (std::size_t i = 1; i < edata.M.size(); ++i) {
0837 degree_size_type e2 = get_incident_edge_index(alpha, edata.M[i], g);
0838 while (parent_vec[e2] != e2) e2 = parent_vec[e2];
0839 parent_vec[e2] = e1;
0840 }
0841 }
0842 }
0843
0844 edges_size_type not_mapped = (std::numeric_limits<edges_size_type>::max)();
0845
0846
0847 for (idx = 0; idx < parent_vec.size(); ++idx) {
0848 if (parent_vec[idx] == idx) {
0849 edge_data[idx].partition = local_to_global_partitions.size();
0850 local_to_global_partitions.push_back(not_mapped);
0851 }
0852 }
0853
0854
0855 for (idx = 0; idx < parent_vec.size(); ++idx) {
0856 degree_size_type rep = parent_vec[idx];
0857 while (rep != parent_vec[rep]) rep = parent_vec[rep];
0858 edge_data[idx].partition = edge_data[rep].partition;
0859 }
0860
0861
0862 phase = 4;
0863 }
0864
0865 template<typename Graph>
0866 std::size_t
0867 hohberg_vertex_processor<Graph>::get_edge_index(Edge e, const Graph& g)
0868 {
0869 std::size_t result = 0;
0870 BGL_FORALL_OUTEDGES_T(target(e, g), oe, g, Graph) {
0871 if (source(e, g) == target(oe, g)) return result;
0872 ++result;
0873 }
0874 BOOST_ASSERT(false);
0875 }
0876
0877 template<typename Graph>
0878 std::size_t
0879 hohberg_vertex_processor<Graph>::get_incident_edge_index(Vertex u, Vertex v,
0880 const Graph& g)
0881 {
0882 std::size_t result = 0;
0883 BGL_FORALL_OUTEDGES_T(u, e, g, Graph) {
0884 if (target(e, g) == v) return result;
0885 ++result;
0886 }
0887 BOOST_ASSERT(false);
0888 }
0889
0890 template<typename Graph, typename InputIterator, typename ComponentMap,
0891 typename VertexProcessorMap>
0892 typename graph_traits<Graph>::edges_size_type
0893 hohberg_biconnected_components
0894 (const Graph& g,
0895 ComponentMap component,
0896 InputIterator first, InputIterator last,
0897 VertexProcessorMap vertex_processor)
0898 {
0899 using namespace boost::graph::parallel;
0900 using namespace hohberg_detail;
0901 using boost::parallel::all_reduce;
0902
0903 typename property_map<Graph, vertex_owner_t>::const_type
0904 owner = get(vertex_owner, g);
0905
0906
0907 BOOST_STATIC_ASSERT(
0908 (is_convertible<typename graph_traits<Graph>::directed_category,
0909 undirected_tag>::value));
0910
0911
0912 BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
0913
0914 typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
0915 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0916 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
0917
0918
0919 typedef typename process_group_type<Graph>::type process_group_type;
0920 process_group_type pg = process_group(g);
0921
0922
0923 std::vector<edge_descriptor> tree_edges;
0924
0925
0926 while (first != last) {
0927 vertex_descriptor leader = *first;
0928 if (process_id(pg) == get(owner, leader))
0929 vertex_processor[leader].initialize_leader(leader, g);
0930 ++first;
0931 }
0932 synchronize(pg);
0933
0934
0935 edges_size_type num_bicomponents = 0;
0936
0937
0938
0939
0940
0941 std::size_t path_length = 1;
0942
0943 typedef std::vector<vertex_descriptor> path_t;
0944
0945 unsigned char minimum_phase = 5;
0946 do {
0947 while (optional<std::pair<int, int> > msg = probe(pg)) {
0948 switch (msg->second) {
0949 case msg_path_header:
0950 {
0951
0952 path_header<edge_descriptor> header;
0953 receive(pg, msg->first, msg->second, header);
0954 BOOST_ASSERT(path_length == header.path_length);
0955
0956
0957 path_t path(path_length);
0958 receive(pg, msg->first, msg_path_vertices, &path[0], path_length);
0959
0960 edge_descriptor e = header.edge;
0961 vertex_processor[target(e, g)](e, path, g);
0962 }
0963 break;
0964
0965 case msg_path_vertices:
0966
0967
0968 BOOST_ASSERT(false);
0969 break;
0970
0971 case msg_tree_header:
0972 {
0973
0974 tree_header<vertex_descriptor, edge_descriptor> header;
0975 receive(pg, msg->first, msg->second, header);
0976
0977
0978 path_t in_same_bicomponent(header.bicomp_length);
0979 receive(pg, msg->first, msg_tree_vertices, &in_same_bicomponent[0],
0980 header.bicomp_length);
0981
0982 edge_descriptor e = header.edge;
0983 vertex_processor[target(e, g)](e, header.gamma, in_same_bicomponent,
0984 g);
0985 }
0986 break;
0987
0988 case msg_tree_vertices:
0989
0990
0991 BOOST_ASSERT(false);
0992 break;
0993
0994 case msg_name:
0995 {
0996 name_header<edge_descriptor> header;
0997 receive(pg, msg->first, msg->second, header);
0998 edge_descriptor e = header.edge;
0999 vertex_processor[target(e, g)](e, header.name, g);
1000 }
1001 break;
1002
1003 default:
1004 BOOST_ASSERT(false);
1005 }
1006 }
1007 ++path_length;
1008
1009
1010 minimum_phase = 5;
1011 unsigned char maximum_phase = 1;
1012 BGL_FORALL_VERTICES_T(v, g, Graph) {
1013 minimum_phase = (std::min)(minimum_phase, vertex_processor[v].get_phase());
1014 maximum_phase = (std::max)(maximum_phase, vertex_processor[v].get_phase());
1015 }
1016
1017 #ifdef PBGL_HOHBERG_DEBUG
1018 if (process_id(pg) == 0)
1019 std::cerr << "<---------End of stage------------->" << std::endl;
1020 #endif
1021
1022 minimum_phase = all_reduce(pg, minimum_phase, boost::mpi::minimum<char>());
1023
1024 #ifdef PBGL_HOHBERG_DEBUG
1025 if (process_id(pg) == 0)
1026 std::cerr << "Minimum phase = " << (int)minimum_phase << std::endl;
1027 #endif
1028
1029 if (minimum_phase == 4
1030 && all_reduce(pg, maximum_phase, boost::mpi::maximum<char>()) == 4) {
1031
1032 #ifdef PBGL_HOHBERG_DEBUG
1033 if (process_id(pg) == 0)
1034 std::cerr << "<---------Naming phase------------->" << std::endl;
1035 #endif
1036
1037
1038 std::vector<edges_size_type> local_offsets;
1039 local_offsets.reserve(num_vertices(g));
1040 edges_size_type num_local_bicomponents = 0;
1041 BGL_FORALL_VERTICES_T(v, g, Graph) {
1042 local_offsets.push_back(num_local_bicomponents);
1043 num_local_bicomponents +=
1044 vertex_processor[v].num_starting_bicomponents(v, g);
1045 }
1046
1047 synchronize(pg);
1048
1049
1050
1051
1052
1053 std::vector<edges_size_type> all_bicomponents(num_processes(pg));
1054 all_gather(pg, &num_local_bicomponents, &num_local_bicomponents + 1,
1055 all_bicomponents);
1056 num_bicomponents = 0;
1057 edges_size_type my_global_offset = 0;
1058 for (std::size_t i = 0; i < all_bicomponents.size(); ++i) {
1059 if (i == (std::size_t)process_id(pg))
1060 my_global_offset = num_bicomponents;
1061 num_bicomponents += all_bicomponents[i];
1062 }
1063
1064 std::size_t index = 0;
1065 BGL_FORALL_VERTICES_T(v, g, Graph) {
1066 edges_size_type offset = my_global_offset + local_offsets[index++];
1067 vertex_processor[v].start_naming_phase(v, g, offset);
1068 }
1069 }
1070
1071 synchronize(pg);
1072 } while (minimum_phase < 5);
1073
1074
1075 BGL_FORALL_VERTICES_T(v, g, Graph)
1076 vertex_processor[v].fill_edge_map(v, g, component);
1077
1078 return num_bicomponents;
1079 }
1080
1081 template<typename Graph, typename ComponentMap, typename InputIterator>
1082 typename graph_traits<Graph>::edges_size_type
1083 hohberg_biconnected_components
1084 (const Graph& g, ComponentMap component,
1085 InputIterator first, InputIterator last)
1086
1087 {
1088 std::vector<hohberg_vertex_processor<Graph> >
1089 vertex_processors(num_vertices(g));
1090 return hohberg_biconnected_components
1091 (g, component, first, last,
1092 make_iterator_property_map(vertex_processors.begin(),
1093 get(vertex_index, g)));
1094 }
1095
1096 template<typename Graph, typename ComponentMap, typename ParentMap>
1097 typename graph_traits<Graph>::edges_size_type
1098 hohberg_biconnected_components(const Graph& g, ComponentMap component,
1099 ParentMap parent)
1100 {
1101
1102
1103 connected_components(g, dummy_property_map(), parent);
1104
1105
1106 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
1107 std::vector<vertex_descriptor> leaders;
1108 BGL_FORALL_VERTICES_T(v, g, Graph)
1109 if (get(parent, v) == v) leaders.push_back(v);
1110
1111 return hohberg_biconnected_components(g, component,
1112 leaders.begin(), leaders.end());
1113 }
1114
1115 template<typename Graph, typename ComponentMap>
1116 typename graph_traits<Graph>::edges_size_type
1117 hohberg_biconnected_components(const Graph& g, ComponentMap component)
1118 {
1119 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
1120 std::vector<vertex_descriptor> parents(num_vertices(g));
1121 return hohberg_biconnected_components
1122 (g, component, make_iterator_property_map(parents.begin(),
1123 get(vertex_index, g)));
1124 }
1125
1126 } } }
1127
1128 #endif