File indexing completed on 2025-01-18 09:37:37
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_GRAPH_STRONG_COMPONENTS_HPP
0013 #define BOOST_GRAPH_STRONG_COMPONENTS_HPP
0014
0015 #include <stack>
0016 #include <boost/config.hpp>
0017 #include <boost/graph/depth_first_search.hpp>
0018 #include <boost/type_traits/conversion_traits.hpp>
0019 #include <boost/static_assert.hpp>
0020 #include <boost/graph/overloading.hpp>
0021 #include <boost/graph/detail/mpi_include.hpp>
0022 #include <boost/concept/assert.hpp>
0023
0024 namespace boost
0025 {
0026
0027
0028
0029
0030
0031
0032
0033 namespace detail
0034 {
0035
0036 template < typename ComponentMap, typename RootMap, typename DiscoverTime,
0037 typename Stack >
0038 class tarjan_scc_visitor : public dfs_visitor<>
0039 {
0040 typedef typename property_traits< ComponentMap >::value_type comp_type;
0041 typedef typename property_traits< DiscoverTime >::value_type time_type;
0042
0043 public:
0044 tarjan_scc_visitor(ComponentMap comp_map, RootMap r, DiscoverTime d,
0045 comp_type& c_, Stack& s_)
0046 : c(c_)
0047 , comp(comp_map)
0048 , root(r)
0049 , discover_time(d)
0050 , dfs_time(time_type())
0051 , s(s_)
0052 {
0053 }
0054
0055 template < typename Graph >
0056 void discover_vertex(
0057 typename graph_traits< Graph >::vertex_descriptor v, const Graph&)
0058 {
0059 put(root, v, v);
0060 put(comp, v, (std::numeric_limits< comp_type >::max)());
0061 put(discover_time, v, dfs_time++);
0062 s.push(v);
0063 }
0064 template < typename Graph >
0065 void finish_vertex(
0066 typename graph_traits< Graph >::vertex_descriptor v, const Graph& g)
0067 {
0068 typename graph_traits< Graph >::vertex_descriptor w;
0069 typename graph_traits< Graph >::out_edge_iterator ei, ei_end;
0070 for (boost::tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei)
0071 {
0072 w = target(*ei, g);
0073 if (get(comp, w) == (std::numeric_limits< comp_type >::max)())
0074 put(root, v,
0075 this->min_discover_time(get(root, v), get(root, w)));
0076 }
0077 if (get(root, v) == v)
0078 {
0079 do
0080 {
0081 w = s.top();
0082 s.pop();
0083 put(comp, w, c);
0084 put(root, w, v);
0085 } while (w != v);
0086 ++c;
0087 }
0088 }
0089
0090 private:
0091 template < typename Vertex >
0092 Vertex min_discover_time(Vertex u, Vertex v)
0093 {
0094 return get(discover_time, u) < get(discover_time, v) ? u : v;
0095 }
0096
0097 comp_type& c;
0098 ComponentMap comp;
0099 RootMap root;
0100 DiscoverTime discover_time;
0101 time_type dfs_time;
0102 Stack& s;
0103 };
0104
0105 template < class Graph, class ComponentMap, class RootMap,
0106 class DiscoverTime, class P, class T, class R >
0107 typename property_traits< ComponentMap >::value_type strong_components_impl(
0108 const Graph& g,
0109 ComponentMap comp,
0110
0111 RootMap root, DiscoverTime discover_time,
0112 const bgl_named_params< P, T, R >& params)
0113 {
0114 typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
0115 BOOST_CONCEPT_ASSERT(
0116 (ReadWritePropertyMapConcept< ComponentMap, Vertex >));
0117 BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< RootMap, Vertex >));
0118 typedef typename property_traits< RootMap >::value_type RootV;
0119 BOOST_CONCEPT_ASSERT((ConvertibleConcept< RootV, Vertex >));
0120 BOOST_CONCEPT_ASSERT(
0121 (ReadWritePropertyMapConcept< DiscoverTime, Vertex >));
0122
0123 typename property_traits< ComponentMap >::value_type total = 0;
0124
0125 std::stack< Vertex > s;
0126 detail::tarjan_scc_visitor< ComponentMap, RootMap, DiscoverTime,
0127 std::stack< Vertex > >
0128 vis(comp, root, discover_time, total, s);
0129 depth_first_search(g, params.visitor(vis));
0130 return total;
0131 }
0132
0133
0134
0135
0136
0137
0138 template < class DiscoverTimeMap > struct strong_comp_dispatch2
0139 {
0140 template < class Graph, class ComponentMap, class RootMap, class P,
0141 class T, class R >
0142 inline static typename property_traits< ComponentMap >::value_type
0143 apply(const Graph& g, ComponentMap comp, RootMap r_map,
0144 const bgl_named_params< P, T, R >& params, DiscoverTimeMap time_map)
0145 {
0146 return strong_components_impl(g, comp, r_map, time_map, params);
0147 }
0148 };
0149
0150 template <> struct strong_comp_dispatch2< param_not_found >
0151 {
0152 template < class Graph, class ComponentMap, class RootMap, class P,
0153 class T, class R >
0154 inline static typename property_traits< ComponentMap >::value_type
0155 apply(const Graph& g, ComponentMap comp, RootMap r_map,
0156 const bgl_named_params< P, T, R >& params, param_not_found)
0157 {
0158 typedef
0159 typename graph_traits< Graph >::vertices_size_type size_type;
0160 size_type n = num_vertices(g) > 0 ? num_vertices(g) : 1;
0161 std::vector< size_type > time_vec(n);
0162 return strong_components_impl(g, comp, r_map,
0163 make_iterator_property_map(time_vec.begin(),
0164 choose_const_pmap(
0165 get_param(params, vertex_index), g, vertex_index),
0166 time_vec[0]),
0167 params);
0168 }
0169 };
0170
0171 template < class Graph, class ComponentMap, class RootMap, class P, class T,
0172 class R, class DiscoverTimeMap >
0173 inline typename property_traits< ComponentMap >::value_type scc_helper2(
0174 const Graph& g, ComponentMap comp, RootMap r_map,
0175 const bgl_named_params< P, T, R >& params, DiscoverTimeMap time_map)
0176 {
0177 return strong_comp_dispatch2< DiscoverTimeMap >::apply(
0178 g, comp, r_map, params, time_map);
0179 }
0180
0181 template < class RootMap > struct strong_comp_dispatch1
0182 {
0183
0184 template < class Graph, class ComponentMap, class P, class T, class R >
0185 inline static typename property_traits< ComponentMap >::value_type
0186 apply(const Graph& g, ComponentMap comp,
0187 const bgl_named_params< P, T, R >& params, RootMap r_map)
0188 {
0189 return scc_helper2(g, comp, r_map, params,
0190 get_param(params, vertex_discover_time));
0191 }
0192 };
0193 template <> struct strong_comp_dispatch1< param_not_found >
0194 {
0195
0196 template < class Graph, class ComponentMap, class P, class T, class R >
0197 inline static typename property_traits< ComponentMap >::value_type
0198 apply(const Graph& g, ComponentMap comp,
0199 const bgl_named_params< P, T, R >& params, param_not_found)
0200 {
0201 typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
0202 typename std::vector< Vertex >::size_type n
0203 = num_vertices(g) > 0 ? num_vertices(g) : 1;
0204 std::vector< Vertex > root_vec(n);
0205 return scc_helper2(g, comp,
0206 make_iterator_property_map(root_vec.begin(),
0207 choose_const_pmap(
0208 get_param(params, vertex_index), g, vertex_index),
0209 root_vec[0]),
0210 params, get_param(params, vertex_discover_time));
0211 }
0212 };
0213
0214 template < class Graph, class ComponentMap, class RootMap, class P, class T,
0215 class R >
0216 inline typename property_traits< ComponentMap >::value_type scc_helper1(
0217 const Graph& g, ComponentMap comp,
0218 const bgl_named_params< P, T, R >& params, RootMap r_map)
0219 {
0220 return detail::strong_comp_dispatch1< RootMap >::apply(
0221 g, comp, params, r_map);
0222 }
0223
0224 }
0225
0226 template < class Graph, class ComponentMap, class P, class T, class R >
0227 inline typename property_traits< ComponentMap >::value_type strong_components(
0228 const Graph& g, ComponentMap comp,
0229 const bgl_named_params< P, T, R >& params BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0230 Graph, vertex_list_graph_tag))
0231 {
0232 typedef typename graph_traits< Graph >::directed_category DirCat;
0233 BOOST_STATIC_ASSERT(
0234 (is_convertible< DirCat*, directed_tag* >::value == true));
0235 return detail::scc_helper1(
0236 g, comp, params, get_param(params, vertex_root_t()));
0237 }
0238
0239 template < class Graph, class ComponentMap >
0240 inline typename property_traits< ComponentMap >::value_type strong_components(
0241 const Graph& g,
0242 ComponentMap comp BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0243 Graph, vertex_list_graph_tag))
0244 {
0245 typedef typename graph_traits< Graph >::directed_category DirCat;
0246 BOOST_STATIC_ASSERT(
0247 (is_convertible< DirCat*, directed_tag* >::value == true));
0248 bgl_named_params< int, int > params(0);
0249 return strong_components(g, comp, params);
0250 }
0251
0252 template < typename Graph, typename ComponentMap, typename ComponentLists >
0253 void build_component_lists(const Graph& g,
0254 typename graph_traits< Graph >::vertices_size_type num_scc,
0255 ComponentMap component_number, ComponentLists& components)
0256 {
0257 components.resize(num_scc);
0258 typename graph_traits< Graph >::vertex_iterator vi, vi_end;
0259 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0260 components[component_number[*vi]].push_back(*vi);
0261 }
0262
0263 }
0264
0265 #include <queue>
0266 #include <vector>
0267 #include <boost/graph/transpose_graph.hpp>
0268 #include <boost/pending/indirect_cmp.hpp>
0269 #include <boost/graph/connected_components.hpp> // for components_recorder
0270
0271 namespace boost
0272 {
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285 template < class Graph, class DFSVisitor, class ComponentsMap,
0286 class DiscoverTime, class FinishTime, class ColorMap >
0287 typename property_traits< ComponentsMap >::value_type
0288 kosaraju_strong_components(
0289 Graph& G, ComponentsMap c, FinishTime finish_time, ColorMap color)
0290 {
0291 BOOST_CONCEPT_ASSERT((MutableGraphConcept< Graph >));
0292
0293
0294 typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
0295 typedef typename property_traits< ColorMap >::value_type ColorValue;
0296 typedef color_traits< ColorValue > Color;
0297 typename property_traits< FinishTime >::value_type time = 0;
0298 depth_first_search(G,
0299 make_dfs_visitor(stamp_times(finish_time, time, on_finish_vertex())),
0300 color);
0301
0302 Graph G_T(num_vertices(G));
0303 transpose_graph(G, G_T);
0304
0305 typedef typename property_traits< ComponentsMap >::value_type count_type;
0306
0307 count_type c_count(0);
0308 detail::components_recorder< ComponentsMap > vis(c, c_count);
0309
0310
0311 typename graph_traits< Graph >::vertex_iterator ui, ui_end;
0312 for (boost::tie(ui, ui_end) = vertices(G_T); ui != ui_end; ++ui)
0313 put(color, *ui, Color::white());
0314
0315 typedef typename property_traits< FinishTime >::value_type D;
0316 typedef indirect_cmp< FinishTime, std::less< D > > Compare;
0317
0318 Compare fl(finish_time);
0319 std::priority_queue< Vertex, std::vector< Vertex >, Compare > Q(fl);
0320
0321 typename graph_traits< Graph >::vertex_iterator i, j, iend, jend;
0322 boost::tie(i, iend) = vertices(G_T);
0323 boost::tie(j, jend) = vertices(G);
0324 for (; i != iend; ++i, ++j)
0325 {
0326 put(finish_time, *i, get(finish_time, *j));
0327 Q.push(*i);
0328 }
0329
0330 while (!Q.empty())
0331 {
0332 Vertex u = Q.top();
0333 Q.pop();
0334 if (get(color, u) == Color::white())
0335 {
0336 depth_first_visit(G_T, u, vis, color);
0337 ++c_count;
0338 }
0339 }
0340 return c_count;
0341 }
0342
0343 }
0344
0345 #include BOOST_GRAPH_MPI_INCLUDE( <boost/graph/distributed/strong_components.hpp >)
0346
0347 #endif