123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128 |
- #ifndef BOOST_GRAPH_DISTRIBUTED_HOHBERG_BICONNECTED_COMPONENTS_HPP
- #define BOOST_GRAPH_DISTRIBUTED_HOHBERG_BICONNECTED_COMPONENTS_HPP
- #ifndef BOOST_GRAPH_USE_MPI
- #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
- #endif
- #include <boost/graph/graph_traits.hpp>
- #include <boost/graph/parallel/container_traits.hpp>
- #include <boost/graph/parallel/process_group.hpp>
- #include <boost/static_assert.hpp>
- #include <boost/mpi/operations.hpp>
- #include <boost/type_traits/is_convertible.hpp>
- #include <boost/graph/graph_concepts.hpp>
- #include <boost/graph/iteration_macros.hpp>
- #include <boost/optional.hpp>
- #include <utility> // for std::pair
- #include <boost/assert.hpp>
- #include <algorithm> // for std::find, std::mismatch
- #include <vector>
- #include <boost/graph/parallel/algorithm.hpp>
- #include <boost/graph/distributed/connected_components.hpp>
- #include <boost/concept/assert.hpp>
- namespace boost { namespace graph { namespace distributed {
- namespace hohberg_detail {
- enum message_kind {
-
- msg_path_header,
-
- msg_path_vertices,
-
- msg_tree_header,
-
- msg_tree_vertices,
-
- msg_name
- };
-
- template<typename EdgeDescriptor>
- struct path_header
- {
-
- EdgeDescriptor edge;
-
-
- std::size_t path_length;
- template<typename Archiver>
- void serialize(Archiver& ar, const unsigned int )
- {
- ar & edge & path_length;
- }
- };
-
- template<typename Vertex, typename Edge>
- struct tree_header
- {
-
- Edge edge;
-
- Vertex gamma;
-
-
-
- std::size_t bicomp_length;
- template<typename Archiver>
- void serialize(Archiver& ar, const unsigned int )
- {
- ar & edge & gamma & bicomp_length;
- }
- };
-
- template<typename EdgeDescriptor>
- struct name_header
- {
-
- EdgeDescriptor edge;
-
- std::size_t name;
- template<typename Archiver>
- void serialize(Archiver& ar, const unsigned int )
- {
- ar & edge & name;
- }
- };
-
- template<typename T>
- T branch_point(const std::vector<T>& p1, const std::vector<T>& p2)
- {
- BOOST_ASSERT(!p1.empty());
- BOOST_ASSERT(!p2.empty());
- BOOST_ASSERT(p1.front() == p2.front());
- typedef typename std::vector<T>::const_iterator iterator;
- iterator mismatch_pos;
- if (p1.size() <= p2.size())
- mismatch_pos = std::mismatch(p1.begin(), p1.end(), p2.begin()).first;
- else
- mismatch_pos = std::mismatch(p2.begin(), p2.end(), p1.begin()).first;
- --mismatch_pos;
- return *mismatch_pos;
- }
-
- template<typename T>
- T infimum(const std::vector<T>& parent_path, T a, T b)
- {
- using std::swap;
- typedef typename std::vector<T>::const_iterator iterator;
- iterator first = parent_path.begin(), last = parent_path.end();
- #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
- std::cerr << "infimum(";
- for (iterator i = first; i != last; ++i) {
- if (i != first) std::cerr << ' ';
- std::cerr << local(*i) << '@' << owner(*i);
- }
- std::cerr << ", " << local(a) << '@' << owner(a) << ", "
- << local(b) << '@' << owner(b) << ") = ";
- #endif
- if (a == b) {
- #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
- std::cerr << local(a) << '@' << owner(a) << std::endl;
- #endif
- return a;
- }
-
- --last;
- while (*last != a) {
-
- if (*last == b) { swap(a,b); break; }
- if (last == first) {
- #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
- std::cerr << local(*first) << '@' << owner(*first) << std::endl;
- #endif
- return *first;
- }
- else --last;
- }
-
- while (*last != b) {
- if (last == first) {
- #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
- std::cerr << local(*first) << '@' << owner(*first) << std::endl;
- #endif
- return *first;
- }
- else --last;
- }
- #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
- std::cerr << local(*last) << '@' << owner(*last) << std::endl;
- #endif
-
- return *last;
- }
- }
- template<typename Graph>
- struct hohberg_message
- {
- typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
- typedef typename graph_traits<Graph>::edge_descriptor Edge;
-
- void assign(const std::vector<Vertex>& path)
- {
- gamma = graph_traits<Graph>::null_vertex();
- path_or_bicomp = path;
- }
-
- void assign(Vertex gamma, const std::vector<Vertex>& in_same_bicomponent)
- {
- this->gamma = gamma;
- path_or_bicomp = in_same_bicomponent;
- }
- bool is_path() const { return gamma == graph_traits<Graph>::null_vertex(); }
- bool is_tree() const { return gamma != graph_traits<Graph>::null_vertex(); }
-
- Vertex gamma;
-
- std::vector<Vertex> path_or_bicomp;
- };
- template<typename Graph>
- class hohberg_vertex_processor
- {
- typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
- typedef typename graph_traits<Graph>::edge_descriptor Edge;
- typedef typename graph_traits<Graph>::degree_size_type degree_size_type;
- typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
- typedef typename boost::graph::parallel::process_group_type<Graph>::type
- ProcessGroup;
- typedef std::vector<Vertex> path_t;
- typedef typename path_t::iterator path_iterator;
- public:
- hohberg_vertex_processor()
- : phase(1),
- parent(graph_traits<Graph>::null_vertex()),
- eta(graph_traits<Graph>::null_vertex())
- {
- }
-
-
-
- void initialize_leader(Vertex alpha, const Graph& g);
-
-
- void
- operator()(Edge e, path_t& path, const Graph& g);
-
-
- void
- operator()(Edge e, Vertex gamma, path_t& in_same_bicomponent,
- const Graph& g);
-
- void operator()(Edge e, edges_size_type name, const Graph& g);
-
- unsigned char get_phase() const { return phase; }
-
-
-
-
-
- void
- start_naming_phase(Vertex alpha, const Graph& g, edges_size_type offset);
-
- edges_size_type num_starting_bicomponents(Vertex alpha, const Graph& g);
-
-
- template<typename ComponentMap>
- void fill_edge_map(Vertex alpha, const Graph& g, ComponentMap& component);
- protected:
-
- void echo_phase(Vertex alpha, const Graph& g);
-
- std::size_t get_edge_index(Edge e, const Graph& g);
-
- std::size_t get_incident_edge_index(Vertex u, Vertex v, const Graph& g);
-
- unsigned char phase;
-
- Vertex parent;
-
- Vertex eta;
-
- degree_size_type num_edges_not_transmitted;
-
- std::vector<Vertex> path_from_root;
-
- struct per_edge_data
- {
- hohberg_message<Graph> msg;
- std::vector<Vertex> M;
- bool is_tree_edge;
- degree_size_type partition;
- };
-
- std::vector<per_edge_data> edge_data;
-
- std::vector<edges_size_type> local_to_global_partitions;
- friend class boost::serialization::access;
-
-
-
-
- template<typename Archiver>
- void serialize(Archiver&, const unsigned int )
- {
- BOOST_ASSERT(false);
- }
- };
- template<typename Graph>
- void
- hohberg_vertex_processor<Graph>::initialize_leader(Vertex alpha,
- const Graph& g)
- {
- using namespace hohberg_detail;
- ProcessGroup pg = process_group(g);
- typename property_map<Graph, vertex_owner_t>::const_type
- owner = get(vertex_owner, g);
- path_header<Edge> header;
- header.path_length = 1;
- BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
- header.edge = e;
- send(pg, get(owner, target(e, g)), msg_path_header, header);
- send(pg, get(owner, target(e, g)), msg_path_vertices, alpha);
- }
- num_edges_not_transmitted = degree(alpha, g);
- edge_data.resize(num_edges_not_transmitted);
- phase = 2;
- }
- template<typename Graph>
- void
- hohberg_vertex_processor<Graph>::operator()(Edge e, path_t& path,
- const Graph& g)
- {
- using namespace hohberg_detail;
- typename property_map<Graph, vertex_owner_t>::const_type
- owner = get(vertex_owner, g);
- #ifdef PBGL_HOHBERG_DEBUG
- std::cerr << "), phase = " << (int)phase << std::endl;
- #endif
-
- if (edge_data.empty())
- edge_data.resize(degree(target(e, g), g));
- per_edge_data& edata = edge_data[get_edge_index(e, g)];
-
- edata.msg.assign(path);
-
-
- Vertex alpha = target(e, g);
- switch (phase) {
- case 1:
- {
- num_edges_not_transmitted = degree(alpha, g) - 1;
- edata.is_tree_edge = true;
- parent = path.back();
- eta = parent;
- edata.M.clear(); edata.M.push_back(parent);
-
-
- path.push_back(alpha);
- path_header<Edge> header;
- header.path_length = path.size();
- ProcessGroup pg = process_group(g);
- BGL_FORALL_OUTEDGES_T(alpha, oe, g, Graph) {
-
- if (target(oe, g) != source(e, g)) {
- header.edge = oe;
- send(pg, get(owner, target(oe, g)), msg_path_header, header);
- send(pg, get(owner, target(oe, g)), msg_path_vertices, &path[0],
- header.path_length);
- }
- }
- path.pop_back();
-
- path_from_root.swap(path);
-
-
- phase = 2;
-
- if (num_edges_not_transmitted == 0)
- echo_phase(alpha, g);
- return;
- }
- case 2:
- {
- --num_edges_not_transmitted;
- edata.is_tree_edge = false;
-
- path_iterator pos = std::find(path.begin(), path.end(), alpha);
- if (pos != path.end()) {
-
-
- edata.M.clear();
- ++pos;
-
- if (pos != path.end()) {
-
- edata.M.push_back(*pos);
- ++pos;
- }
-
-
- if (pos != path.end()) edata.M.push_back(path.back());
- } else {
-
-
- edata.M.clear();
- edata.M.push_back(path.back());
- if (parent != path.back()) edata.M.push_back(parent);
-
- eta = infimum(path_from_root, eta, branch_point(path_from_root, path));
- }
- if (num_edges_not_transmitted == 0)
- echo_phase(alpha, g);
- break;
- }
- default:
- BOOST_ASSERT(false);
- }
- }
- template<typename Graph>
- void
- hohberg_vertex_processor<Graph>::operator()(Edge e, Vertex gamma,
- path_t& in_same_bicomponent,
- const Graph& g)
- {
- using namespace hohberg_detail;
- #ifdef PBGL_HOHBERG_DEBUG
- std::cerr << local(source(e, g)) << '@' << owner(source(e, g)) << " -> "
- << local(target(e, g)) << '@' << owner(target(e, g)) << ": tree("
- << local(gamma) << '@' << owner(gamma) << ", ";
- for (std::size_t i = 0; i < in_same_bicomponent.size(); ++i) {
- if (i > 0) std::cerr << ' ';
- std::cerr << local(in_same_bicomponent[i]) << '@'
- << owner(in_same_bicomponent[i]);
- }
- std::cerr << ", " << local(source(e, g)) << '@' << owner(source(e, g))
- << "), phase = " << (int)phase << std::endl;
- #endif
-
- per_edge_data& edata = edge_data[get_edge_index(e, g)];
-
- edata.msg.assign(gamma, in_same_bicomponent);
-
-
- Vertex alpha = target(e, g);
- Vertex beta = source(e, g);
- switch (phase) {
- case 2:
- --num_edges_not_transmitted;
- edata.is_tree_edge = true;
- if (gamma == alpha) {
-
- edata.M.swap(in_same_bicomponent);
- } else {
-
- edata.M.clear();
- edata.M.push_back(parent);
- if (beta != parent) edata.M.push_back(beta);
- eta = infimum(path_from_root, eta, gamma);
- }
- if (num_edges_not_transmitted == 0)
- echo_phase(alpha, g);
- break;
- default:
- BOOST_ASSERT(false);
- }
- }
- template<typename Graph>
- void
- hohberg_vertex_processor<Graph>::operator()(Edge e, edges_size_type name,
- const Graph& g)
- {
- using namespace hohberg_detail;
- #ifdef PBGL_HOHBERG_DEBUG
- std::cerr << local(source(e, g)) << '@' << owner(source(e, g)) << " -> "
- << local(target(e, g)) << '@' << owner(target(e, g)) << ": name("
- << name << "), phase = " << (int)phase << std::endl;
- #endif
- BOOST_ASSERT(phase == 4);
- typename property_map<Graph, vertex_owner_t>::const_type
- owner = get(vertex_owner, g);
-
-
- ProcessGroup pg = process_group(g);
- Vertex alpha = target(e, g);
- std::size_t idx = 0;
- BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
- per_edge_data& edata = edge_data[idx++];
- if (edata.is_tree_edge
- && find(edata.M.begin(), edata.M.end(), parent) != edata.M.end()
- && target(e, g) != parent) {
-
- name_header<Edge> header;
- header.edge = e;
- header.name = name;
- send(pg, get(owner, target(e, g)), msg_name, header);
- } else if (target(e, g) == parent) {
-
- local_to_global_partitions[edata.partition] = name;
- }
- }
-
- phase = 5;
- }
- template<typename Graph>
- typename hohberg_vertex_processor<Graph>::edges_size_type
- hohberg_vertex_processor<Graph>::
- num_starting_bicomponents(Vertex alpha, const Graph& g)
- {
- edges_size_type not_mapped = (std::numeric_limits<edges_size_type>::max)();
- edges_size_type result = 0;
- std::size_t idx = 0;
- BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
- per_edge_data& edata = edge_data[idx++];
- if (edata.is_tree_edge
- && find(edata.M.begin(), edata.M.end(), parent) == edata.M.end()) {
-
- if (local_to_global_partitions[edata.partition] == not_mapped)
- local_to_global_partitions[edata.partition] = result++;
- }
- }
- #ifdef PBGL_HOHBERG_DEBUG
- std::cerr << local(alpha) << '@' << owner(alpha) << " has " << result
- << " bicomponents originating at it." << std::endl;
- #endif
- return result;
- }
- template<typename Graph>
- template<typename ComponentMap>
- void
- hohberg_vertex_processor<Graph>::
- fill_edge_map(Vertex alpha, const Graph& g, ComponentMap& component)
- {
- std::size_t idx = 0;
- BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
- per_edge_data& edata = edge_data[idx++];
- local_put(component, e, local_to_global_partitions[edata.partition]);
- #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
- std::cerr << "component("
- << local(source(e, g)) << '@' << owner(source(e, g)) << " -> "
- << local(target(e, g)) << '@' << owner(target(e, g)) << ") = "
- << local_to_global_partitions[edata.partition]
- << " (partition = " << edata.partition << " of "
- << local_to_global_partitions.size() << ")" << std::endl;
- #endif
- }
- }
- template<typename Graph>
- void
- hohberg_vertex_processor<Graph>::
- start_naming_phase(Vertex alpha, const Graph& g, edges_size_type offset)
- {
- using namespace hohberg_detail;
- BOOST_ASSERT(phase == 4);
- typename property_map<Graph, vertex_owner_t>::const_type
- owner = get(vertex_owner, g);
-
-
- ProcessGroup pg = process_group(g);
- bool has_more_children_to_name = false;
-
- edges_size_type not_mapped = (std::numeric_limits<edges_size_type>::max)();
- for (std::size_t i = 0; i < local_to_global_partitions.size(); ++i) {
- if (local_to_global_partitions[i] != not_mapped)
- local_to_global_partitions[i] += offset;
- }
- std::size_t idx = 0;
- BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
- per_edge_data& edata = edge_data[idx++];
- if (edata.is_tree_edge
- && find(edata.M.begin(), edata.M.end(), parent) == edata.M.end()) {
-
- name_header<Edge> header;
- header.edge = e;
- header.name = local_to_global_partitions[edata.partition];
- send(pg, get(owner, target(e, g)), msg_name, header);
- } else if (edata.is_tree_edge) {
- has_more_children_to_name = true;
- }
- #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 2
- std::cerr << "M[" << local(source(e, g)) << '@' << owner(source(e, g))
- << " -> " << local(target(e, g)) << '@' << owner(target(e, g))
- << "] = ";
- for (std::size_t i = 0; i < edata.M.size(); ++i) {
- std::cerr << local(edata.M[i]) << '@' << owner(edata.M[i]) << ' ';
- }
- std::cerr << std::endl;
- #endif
- }
-
- if (!has_more_children_to_name)
-
- phase = 5;
- }
- template<typename Graph>
- void
- hohberg_vertex_processor<Graph>::echo_phase(Vertex alpha, const Graph& g)
- {
- using namespace hohberg_detail;
- typename property_map<Graph, vertex_owner_t>::const_type
- owner = get(vertex_owner, g);
-
- phase = 3;
- if (parent != graph_traits<Graph>::null_vertex()) {
- Edge edge_to_parent;
- #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 1
- std::cerr << local(alpha) << '@' << owner(alpha) << " echo: parent = "
- << local(parent) << '@' << owner(parent) << ", eta = "
- << local(eta) << '@' << owner(eta) << ", Gamma = ";
- #endif
- std::vector<Vertex> bicomp;
- std::size_t e_index = 0;
- BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
- if (target(e, g) == parent && parent == eta) {
- edge_to_parent = e;
- if (find(bicomp.begin(), bicomp.end(), alpha) == bicomp.end()) {
- #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 1
- std::cerr << local(alpha) << '@' << owner(alpha) << ' ';
- #endif
- bicomp.push_back(alpha);
- }
- } else {
- if (target(e, g) == parent) edge_to_parent = e;
- per_edge_data& edata = edge_data[e_index];
- if (edata.msg.is_path()) {
- path_iterator pos = std::find(edata.msg.path_or_bicomp.begin(),
- edata.msg.path_or_bicomp.end(),
- eta);
- if (pos != edata.msg.path_or_bicomp.end()) {
- ++pos;
- if (pos != edata.msg.path_or_bicomp.end()
- && find(bicomp.begin(), bicomp.end(), *pos) == bicomp.end()) {
- #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 1
- std::cerr << local(*pos) << '@' << owner(*pos) << ' ';
- #endif
- bicomp.push_back(*pos);
- }
- }
- } else if (edata.msg.is_tree() && edata.msg.gamma == eta) {
- for (path_iterator i = edata.msg.path_or_bicomp.begin();
- i != edata.msg.path_or_bicomp.end(); ++i) {
- if (find(bicomp.begin(), bicomp.end(), *i) == bicomp.end()) {
- #if defined(PBGL_HOHBERG_DEBUG) && PBGL_HOHBERG_DEBUG > 1
- std::cerr << local(*i) << '@' << owner(*i) << ' ';
- #endif
- bicomp.push_back(*i);
- }
- }
- }
- }
- ++e_index;
- }
- #ifdef PBGL_HOHBERG_DEBUG
- std::cerr << std::endl;
- #endif
-
- tree_header<Vertex, Edge> header;
- header.edge = edge_to_parent;
- header.gamma = eta;
- header.bicomp_length = bicomp.size();
- ProcessGroup pg = process_group(g);
- send(pg, get(owner, parent), msg_tree_header, header);
- send(pg, get(owner, parent), msg_tree_vertices, &bicomp[0],
- header.bicomp_length);
- }
-
-
-
- std::vector<degree_size_type> parent_vec(edge_data.size());
- degree_size_type idx = 0;
- for (idx = 0; idx < edge_data.size(); ++idx)
- parent_vec[idx] = idx;
-
-
- idx = 0;
- BGL_FORALL_OUTEDGES_T(alpha, e, g, Graph) {
- per_edge_data& edata = edge_data[idx++];
-
- if (!edata.M.empty()) {
- degree_size_type e1 = get_incident_edge_index(alpha, edata.M.front(), g);
- while (parent_vec[e1] != e1) e1 = parent_vec[e1];
- for (std::size_t i = 1; i < edata.M.size(); ++i) {
- degree_size_type e2 = get_incident_edge_index(alpha, edata.M[i], g);
- while (parent_vec[e2] != e2) e2 = parent_vec[e2];
- parent_vec[e2] = e1;
- }
- }
- }
- edges_size_type not_mapped = (std::numeric_limits<edges_size_type>::max)();
-
- for (idx = 0; idx < parent_vec.size(); ++idx) {
- if (parent_vec[idx] == idx) {
- edge_data[idx].partition = local_to_global_partitions.size();
- local_to_global_partitions.push_back(not_mapped);
- }
- }
-
- for (idx = 0; idx < parent_vec.size(); ++idx) {
- degree_size_type rep = parent_vec[idx];
- while (rep != parent_vec[rep]) rep = parent_vec[rep];
- edge_data[idx].partition = edge_data[rep].partition;
- }
-
- phase = 4;
- }
- template<typename Graph>
- std::size_t
- hohberg_vertex_processor<Graph>::get_edge_index(Edge e, const Graph& g)
- {
- std::size_t result = 0;
- BGL_FORALL_OUTEDGES_T(target(e, g), oe, g, Graph) {
- if (source(e, g) == target(oe, g)) return result;
- ++result;
- }
- BOOST_ASSERT(false);
- }
- template<typename Graph>
- std::size_t
- hohberg_vertex_processor<Graph>::get_incident_edge_index(Vertex u, Vertex v,
- const Graph& g)
- {
- std::size_t result = 0;
- BGL_FORALL_OUTEDGES_T(u, e, g, Graph) {
- if (target(e, g) == v) return result;
- ++result;
- }
- BOOST_ASSERT(false);
- }
- template<typename Graph, typename InputIterator, typename ComponentMap,
- typename VertexProcessorMap>
- typename graph_traits<Graph>::edges_size_type
- hohberg_biconnected_components
- (const Graph& g,
- ComponentMap component,
- InputIterator first, InputIterator last,
- VertexProcessorMap vertex_processor)
- {
- using namespace boost::graph::parallel;
- using namespace hohberg_detail;
- using boost::parallel::all_reduce;
- typename property_map<Graph, vertex_owner_t>::const_type
- owner = get(vertex_owner, g);
-
- BOOST_STATIC_ASSERT(
- (is_convertible<typename graph_traits<Graph>::directed_category,
- undirected_tag>::value));
-
- BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
- typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
- typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
- typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
-
- typedef typename process_group_type<Graph>::type process_group_type;
- process_group_type pg = process_group(g);
-
- std::vector<edge_descriptor> tree_edges;
-
- while (first != last) {
- vertex_descriptor leader = *first;
- if (process_id(pg) == get(owner, leader))
- vertex_processor[leader].initialize_leader(leader, g);
- ++first;
- }
- synchronize(pg);
-
- edges_size_type num_bicomponents = 0;
-
-
-
-
- std::size_t path_length = 1;
- typedef std::vector<vertex_descriptor> path_t;
- unsigned char minimum_phase = 5;
- do {
- while (optional<std::pair<int, int> > msg = probe(pg)) {
- switch (msg->second) {
- case msg_path_header:
- {
-
- path_header<edge_descriptor> header;
- receive(pg, msg->first, msg->second, header);
- BOOST_ASSERT(path_length == header.path_length);
-
- path_t path(path_length);
- receive(pg, msg->first, msg_path_vertices, &path[0], path_length);
- edge_descriptor e = header.edge;
- vertex_processor[target(e, g)](e, path, g);
- }
- break;
- case msg_path_vertices:
-
-
- BOOST_ASSERT(false);
- break;
- case msg_tree_header:
- {
-
- tree_header<vertex_descriptor, edge_descriptor> header;
- receive(pg, msg->first, msg->second, header);
-
- path_t in_same_bicomponent(header.bicomp_length);
- receive(pg, msg->first, msg_tree_vertices, &in_same_bicomponent[0],
- header.bicomp_length);
- edge_descriptor e = header.edge;
- vertex_processor[target(e, g)](e, header.gamma, in_same_bicomponent,
- g);
- }
- break;
- case msg_tree_vertices:
-
-
- BOOST_ASSERT(false);
- break;
- case msg_name:
- {
- name_header<edge_descriptor> header;
- receive(pg, msg->first, msg->second, header);
- edge_descriptor e = header.edge;
- vertex_processor[target(e, g)](e, header.name, g);
- }
- break;
- default:
- BOOST_ASSERT(false);
- }
- }
- ++path_length;
-
- minimum_phase = 5;
- unsigned char maximum_phase = 1;
- BGL_FORALL_VERTICES_T(v, g, Graph) {
- minimum_phase = (std::min)(minimum_phase, vertex_processor[v].get_phase());
- maximum_phase = (std::max)(maximum_phase, vertex_processor[v].get_phase());
- }
- #ifdef PBGL_HOHBERG_DEBUG
- if (process_id(pg) == 0)
- std::cerr << "<---------End of stage------------->" << std::endl;
- #endif
-
- minimum_phase = all_reduce(pg, minimum_phase, boost::mpi::minimum<char>());
- #ifdef PBGL_HOHBERG_DEBUG
- if (process_id(pg) == 0)
- std::cerr << "Minimum phase = " << (int)minimum_phase << std::endl;
- #endif
- if (minimum_phase == 4
- && all_reduce(pg, maximum_phase, boost::mpi::maximum<char>()) == 4) {
- #ifdef PBGL_HOHBERG_DEBUG
- if (process_id(pg) == 0)
- std::cerr << "<---------Naming phase------------->" << std::endl;
- #endif
-
-
- std::vector<edges_size_type> local_offsets;
- local_offsets.reserve(num_vertices(g));
- edges_size_type num_local_bicomponents = 0;
- BGL_FORALL_VERTICES_T(v, g, Graph) {
- local_offsets.push_back(num_local_bicomponents);
- num_local_bicomponents +=
- vertex_processor[v].num_starting_bicomponents(v, g);
- }
- synchronize(pg);
-
-
-
-
- std::vector<edges_size_type> all_bicomponents(num_processes(pg));
- all_gather(pg, &num_local_bicomponents, &num_local_bicomponents + 1,
- all_bicomponents);
- num_bicomponents = 0;
- edges_size_type my_global_offset = 0;
- for (std::size_t i = 0; i < all_bicomponents.size(); ++i) {
- if (i == (std::size_t)process_id(pg))
- my_global_offset = num_bicomponents;
- num_bicomponents += all_bicomponents[i];
- }
- std::size_t index = 0;
- BGL_FORALL_VERTICES_T(v, g, Graph) {
- edges_size_type offset = my_global_offset + local_offsets[index++];
- vertex_processor[v].start_naming_phase(v, g, offset);
- }
- }
- synchronize(pg);
- } while (minimum_phase < 5);
-
- BGL_FORALL_VERTICES_T(v, g, Graph)
- vertex_processor[v].fill_edge_map(v, g, component);
- return num_bicomponents;
- }
- template<typename Graph, typename ComponentMap, typename InputIterator>
- typename graph_traits<Graph>::edges_size_type
- hohberg_biconnected_components
- (const Graph& g, ComponentMap component,
- InputIterator first, InputIterator last)
- {
- std::vector<hohberg_vertex_processor<Graph> >
- vertex_processors(num_vertices(g));
- return hohberg_biconnected_components
- (g, component, first, last,
- make_iterator_property_map(vertex_processors.begin(),
- get(vertex_index, g)));
- }
- template<typename Graph, typename ComponentMap, typename ParentMap>
- typename graph_traits<Graph>::edges_size_type
- hohberg_biconnected_components(const Graph& g, ComponentMap component,
- ParentMap parent)
- {
-
-
- connected_components(g, dummy_property_map(), parent);
-
- typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
- std::vector<vertex_descriptor> leaders;
- BGL_FORALL_VERTICES_T(v, g, Graph)
- if (get(parent, v) == v) leaders.push_back(v);
- return hohberg_biconnected_components(g, component,
- leaders.begin(), leaders.end());
- }
- template<typename Graph, typename ComponentMap>
- typename graph_traits<Graph>::edges_size_type
- hohberg_biconnected_components(const Graph& g, ComponentMap component)
- {
- typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
- std::vector<vertex_descriptor> parents(num_vertices(g));
- return hohberg_biconnected_components
- (g, component, make_iterator_property_map(parents.begin(),
- get(vertex_index, g)));
- }
- } } }
- #endif
|