File indexing completed on 2025-01-30 09:43:09
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP
0010 #define BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP
0011
0012 #include <vector>
0013 #include <algorithm> // for std::min and std::max
0014 #include <functional>
0015 #include <boost/config.hpp>
0016 #include <boost/bind/bind.hpp>
0017 #include <boost/graph/strong_components.hpp>
0018 #include <boost/graph/topological_sort.hpp>
0019 #include <boost/graph/graph_concepts.hpp>
0020 #include <boost/graph/named_function_params.hpp>
0021 #include <boost/graph/adjacency_list.hpp>
0022 #include <boost/concept/assert.hpp>
0023
0024 namespace boost
0025 {
0026
0027 namespace detail
0028 {
0029 inline void union_successor_sets(const std::vector< std::size_t >& s1,
0030 const std::vector< std::size_t >& s2, std::vector< std::size_t >& s3)
0031 {
0032 BOOST_USING_STD_MIN();
0033 for (std::size_t k = 0; k < s1.size(); ++k)
0034 s3[k] = min BOOST_PREVENT_MACRO_SUBSTITUTION(s1[k], s2[k]);
0035 }
0036 }
0037
0038 namespace detail
0039 {
0040 template < typename TheContainer, typename ST = std::size_t,
0041 typename VT = typename TheContainer::value_type >
0042 struct subscript_t
0043 {
0044 typedef ST argument_type;
0045 typedef VT& result_type;
0046
0047 subscript_t(TheContainer& c) : container(&c) {}
0048 VT& operator()(const ST& i) const { return (*container)[i]; }
0049
0050 protected:
0051 TheContainer* container;
0052 };
0053 template < typename TheContainer >
0054 subscript_t< TheContainer > subscript(TheContainer& c)
0055 {
0056 return subscript_t< TheContainer >(c);
0057 }
0058 }
0059
0060 template < typename Graph, typename GraphTC, typename G_to_TC_VertexMap,
0061 typename VertexIndexMap >
0062 void transitive_closure(const Graph& g, GraphTC& tc,
0063 G_to_TC_VertexMap g_to_tc_map, VertexIndexMap index_map)
0064 {
0065 if (num_vertices(g) == 0)
0066 return;
0067 typedef typename graph_traits< Graph >::vertex_descriptor vertex;
0068 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator;
0069 typedef typename property_traits< VertexIndexMap >::value_type size_type;
0070 typedef
0071 typename graph_traits< Graph >::adjacency_iterator adjacency_iterator;
0072
0073 BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >));
0074 BOOST_CONCEPT_ASSERT((AdjacencyGraphConcept< Graph >));
0075 BOOST_CONCEPT_ASSERT((VertexMutableGraphConcept< GraphTC >));
0076 BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept< GraphTC >));
0077 BOOST_CONCEPT_ASSERT(
0078 (ReadablePropertyMapConcept< VertexIndexMap, vertex >));
0079
0080 typedef size_type cg_vertex;
0081 std::vector< cg_vertex > component_number_vec(num_vertices(g));
0082 iterator_property_map< cg_vertex*, VertexIndexMap, cg_vertex, cg_vertex& >
0083 component_number(&component_number_vec[0], index_map);
0084
0085 const cg_vertex num_scc
0086 = strong_components(g, component_number, vertex_index_map(index_map));
0087
0088 std::vector< std::vector< vertex > > components;
0089 build_component_lists(g, num_scc, component_number, components);
0090
0091 typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS >
0092 CG_t;
0093 CG_t CG(num_scc);
0094 for (cg_vertex s = 0; s < components.size(); ++s)
0095 {
0096 std::vector< cg_vertex > adj;
0097 for (size_type i = 0; i < components[s].size(); ++i)
0098 {
0099 vertex u = components[s][i];
0100 adjacency_iterator v, v_end;
0101 for (boost::tie(v, v_end) = adjacent_vertices(u, g); v != v_end;
0102 ++v)
0103 {
0104 cg_vertex t = component_number[*v];
0105 if (s != t)
0106 adj.push_back(t);
0107 }
0108 }
0109 std::sort(adj.begin(), adj.end());
0110 const typename std::vector< cg_vertex >::iterator di
0111 = std::unique(adj.begin(), adj.end());
0112
0113 for (typename std::vector< cg_vertex >::const_iterator i = adj.begin();
0114 i != di; ++i)
0115 {
0116 add_edge(s, *i, CG);
0117 }
0118 }
0119
0120 std::vector< cg_vertex > topo_order;
0121 std::vector< cg_vertex > topo_number(num_vertices(CG));
0122 topological_sort(CG, std::back_inserter(topo_order),
0123 vertex_index_map(identity_property_map()));
0124 std::reverse(topo_order.begin(), topo_order.end());
0125 size_type n = 0;
0126 for (typename std::vector< cg_vertex >::iterator iter = topo_order.begin();
0127 iter != topo_order.end(); ++iter)
0128 topo_number[*iter] = n++;
0129
0130 std::vector< std::vector< cg_vertex > > CG_vec(num_vertices(CG));
0131 for (size_type i = 0; i < num_vertices(CG); ++i)
0132 {
0133 using namespace boost::placeholders;
0134
0135 typedef typename boost::graph_traits< CG_t >::adjacency_iterator
0136 cg_adj_iter;
0137 std::pair< cg_adj_iter, cg_adj_iter > pr = adjacent_vertices(i, CG);
0138 CG_vec[i].assign(pr.first, pr.second);
0139 std::sort(CG_vec[i].begin(), CG_vec[i].end(),
0140 boost::bind(std::less< cg_vertex >(),
0141 boost::bind(detail::subscript(topo_number), _1),
0142 boost::bind(detail::subscript(topo_number), _2)));
0143 }
0144
0145 std::vector< std::vector< cg_vertex > > chains;
0146 {
0147 std::vector< cg_vertex > in_a_chain(CG_vec.size());
0148 for (typename std::vector< cg_vertex >::iterator i = topo_order.begin();
0149 i != topo_order.end(); ++i)
0150 {
0151 cg_vertex v = *i;
0152 if (!in_a_chain[v])
0153 {
0154 chains.resize(chains.size() + 1);
0155 std::vector< cg_vertex >& chain = chains.back();
0156 for (;;)
0157 {
0158 chain.push_back(v);
0159 in_a_chain[v] = true;
0160
0161 typename std::vector< cg_vertex >::const_iterator next
0162 #ifdef __cpp_lib_not_fn
0163 = std::find_if(CG_vec[v].begin(), CG_vec[v].end(),
0164 std::not_fn(detail::subscript(in_a_chain)));
0165 #else
0166 = std::find_if(CG_vec[v].begin(), CG_vec[v].end(),
0167 std::not1(detail::subscript(in_a_chain)));
0168 #endif
0169
0170 if (next != CG_vec[v].end())
0171 v = *next;
0172 else
0173 break;
0174 }
0175 }
0176 }
0177 }
0178 std::vector< size_type > chain_number(CG_vec.size());
0179 std::vector< size_type > pos_in_chain(CG_vec.size());
0180 for (size_type i = 0; i < chains.size(); ++i)
0181 for (size_type j = 0; j < chains[i].size(); ++j)
0182 {
0183 cg_vertex v = chains[i][j];
0184 chain_number[v] = i;
0185 pos_in_chain[v] = j;
0186 }
0187
0188 cg_vertex inf = (std::numeric_limits< cg_vertex >::max)();
0189 std::vector< std::vector< cg_vertex > > successors(
0190 CG_vec.size(), std::vector< cg_vertex >(chains.size(), inf));
0191 for (typename std::vector< cg_vertex >::reverse_iterator i
0192 = topo_order.rbegin();
0193 i != topo_order.rend(); ++i)
0194 {
0195 cg_vertex u = *i;
0196 typename std::vector< cg_vertex >::const_iterator adj, adj_last;
0197 for (adj = CG_vec[u].begin(), adj_last = CG_vec[u].end();
0198 adj != adj_last; ++adj)
0199 {
0200 cg_vertex v = *adj;
0201 if (topo_number[v] < successors[u][chain_number[v]])
0202 {
0203
0204 detail::union_successor_sets(
0205 successors[u], successors[v], successors[u]);
0206
0207 successors[u][chain_number[v]] = topo_number[v];
0208 }
0209 }
0210 }
0211
0212 for (size_type i = 0; i < CG_vec.size(); ++i)
0213 CG_vec[i].clear();
0214 for (size_type i = 0; i < CG_vec.size(); ++i)
0215 for (size_type j = 0; j < chains.size(); ++j)
0216 {
0217 size_type topo_num = successors[i][j];
0218 if (topo_num < inf)
0219 {
0220 cg_vertex v = topo_order[topo_num];
0221 for (size_type k = pos_in_chain[v]; k < chains[j].size(); ++k)
0222 CG_vec[i].push_back(chains[j][k]);
0223 }
0224 }
0225
0226
0227 {
0228 vertex_iterator i, i_end;
0229 for (boost::tie(i, i_end) = vertices(g); i != i_end; ++i)
0230 g_to_tc_map[*i] = add_vertex(tc);
0231 }
0232
0233 typename std::vector< std::vector< cg_vertex > >::const_iterator si, si_end;
0234 for (si = CG_vec.begin(), si_end = CG_vec.end(); si != si_end; ++si)
0235 {
0236 cg_vertex s = si - CG_vec.begin();
0237 typename std::vector< cg_vertex >::const_iterator i, i_end;
0238 for (i = CG_vec[s].begin(), i_end = CG_vec[s].end(); i != i_end; ++i)
0239 {
0240 cg_vertex t = *i;
0241 for (size_type k = 0; k < components[s].size(); ++k)
0242 for (size_type l = 0; l < components[t].size(); ++l)
0243 add_edge(g_to_tc_map[components[s][k]],
0244 g_to_tc_map[components[t][l]], tc);
0245 }
0246 }
0247
0248 for (size_type i = 0; i < components.size(); ++i)
0249 if (components[i].size() > 1)
0250 for (size_type k = 0; k < components[i].size(); ++k)
0251 for (size_type l = 0; l < components[i].size(); ++l)
0252 {
0253 vertex u = components[i][k], v = components[i][l];
0254 add_edge(g_to_tc_map[u], g_to_tc_map[v], tc);
0255 }
0256
0257
0258
0259 {
0260 vertex_iterator i, i_end;
0261 for (boost::tie(i, i_end) = vertices(g); i != i_end; ++i)
0262 {
0263 adjacency_iterator ab, ae;
0264 for (boost::tie(ab, ae) = adjacent_vertices(*i, g); ab != ae; ++ab)
0265 {
0266 if (*ab == *i)
0267 if (components[component_number[*i]].size() == 1)
0268 add_edge(g_to_tc_map[*i], g_to_tc_map[*i], tc);
0269 }
0270 }
0271 }
0272 }
0273
0274 template < typename Graph, typename GraphTC >
0275 void transitive_closure(const Graph& g, GraphTC& tc)
0276 {
0277 if (num_vertices(g) == 0)
0278 return;
0279 typedef typename property_map< Graph, vertex_index_t >::const_type
0280 VertexIndexMap;
0281 VertexIndexMap index_map = get(vertex_index, g);
0282
0283 typedef typename graph_traits< GraphTC >::vertex_descriptor tc_vertex;
0284 std::vector< tc_vertex > to_tc_vec(num_vertices(g));
0285 iterator_property_map< tc_vertex*, VertexIndexMap, tc_vertex, tc_vertex& >
0286 g_to_tc_map(&to_tc_vec[0], index_map);
0287
0288 transitive_closure(g, tc, g_to_tc_map, index_map);
0289 }
0290
0291 namespace detail
0292 {
0293 template < typename Graph, typename GraphTC, typename G_to_TC_VertexMap,
0294 typename VertexIndexMap >
0295 void transitive_closure_dispatch(const Graph& g, GraphTC& tc,
0296 G_to_TC_VertexMap g_to_tc_map, VertexIndexMap index_map)
0297 {
0298 typedef typename graph_traits< GraphTC >::vertex_descriptor tc_vertex;
0299 typename std::vector< tc_vertex >::size_type n
0300 = is_default_param(g_to_tc_map) ? num_vertices(g) : 1;
0301 std::vector< tc_vertex > to_tc_vec(n);
0302
0303 transitive_closure(g, tc,
0304 choose_param(g_to_tc_map,
0305 make_iterator_property_map(
0306 to_tc_vec.begin(), index_map, to_tc_vec[0])),
0307 index_map);
0308 }
0309 }
0310
0311 template < typename Graph, typename GraphTC, typename P, typename T,
0312 typename R >
0313 void transitive_closure(
0314 const Graph& g, GraphTC& tc, const bgl_named_params< P, T, R >& params)
0315 {
0316 if (num_vertices(g) == 0)
0317 return;
0318 detail::transitive_closure_dispatch(g, tc,
0319 get_param(params, orig_to_copy_t()),
0320 choose_const_pmap(get_param(params, vertex_index), g, vertex_index));
0321 }
0322
0323 template < typename G > void warshall_transitive_closure(G& g)
0324 {
0325 typedef typename graph_traits< G >::vertex_iterator vertex_iterator;
0326
0327 BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< G >));
0328 BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept< G >));
0329
0330
0331
0332
0333
0334
0335
0336 vertex_iterator ki, ke, ii, ie, ji, je;
0337 for (boost::tie(ki, ke) = vertices(g); ki != ke; ++ki)
0338 for (boost::tie(ii, ie) = vertices(g); ii != ie; ++ii)
0339 if (edge(*ii, *ki, g).second)
0340 for (boost::tie(ji, je) = vertices(g); ji != je; ++ji)
0341 if (!edge(*ii, *ji, g).second && edge(*ki, *ji, g).second)
0342 {
0343 add_edge(*ii, *ji, g);
0344 }
0345 }
0346
0347 template < typename G > void warren_transitive_closure(G& g)
0348 {
0349 using namespace boost;
0350 typedef typename graph_traits< G >::vertex_iterator vertex_iterator;
0351
0352 BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< G >));
0353 BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept< G >));
0354
0355
0356 if (num_vertices(g) == 0)
0357 return;
0358
0359
0360
0361
0362
0363
0364
0365 vertex_iterator ic, ie, jc, je, kc, ke;
0366 for (boost::tie(ic, ie) = vertices(g), ++ic; ic != ie; ++ic)
0367 for (boost::tie(kc, ke) = vertices(g); *kc != *ic; ++kc)
0368 if (edge(*ic, *kc, g).second)
0369 for (boost::tie(jc, je) = vertices(g); jc != je; ++jc)
0370 if (!edge(*ic, *jc, g).second && edge(*kc, *jc, g).second)
0371 {
0372 add_edge(*ic, *jc, g);
0373 }
0374
0375
0376
0377
0378
0379
0380 for (boost::tie(ic, ie) = vertices(g), --ie; ic != ie; ++ic)
0381 for (kc = ic, ke = ie, ++kc; kc != ke; ++kc)
0382 if (edge(*ic, *kc, g).second)
0383 for (boost::tie(jc, je) = vertices(g); jc != je; ++jc)
0384 if (!edge(*ic, *jc, g).second && edge(*kc, *jc, g).second)
0385 {
0386 add_edge(*ic, *jc, g);
0387 }
0388 }
0389
0390 }
0391
0392 #endif