File indexing completed on 2025-01-18 09:37:30
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_GRAPH_HAWICK_CIRCUITS_HPP
0008 #define BOOST_GRAPH_HAWICK_CIRCUITS_HPP
0009
0010 #include <algorithm>
0011 #include <boost/assert.hpp>
0012 #include <boost/foreach.hpp>
0013 #include <boost/graph/graph_traits.hpp>
0014 #include <boost/graph/one_bit_color_map.hpp>
0015 #include <boost/graph/properties.hpp>
0016 #include <boost/move/utility.hpp>
0017 #include <boost/property_map/property_map.hpp>
0018 #include <boost/range/begin.hpp>
0019 #include <boost/range/end.hpp>
0020 #include <boost/range/iterator.hpp>
0021 #include <boost/tuple/tuple.hpp> // for boost::tie
0022 #include <boost/type_traits/remove_reference.hpp>
0023 #include <boost/utility/result_of.hpp>
0024 #include <set>
0025 #include <utility> // for std::pair
0026 #include <vector>
0027
0028 namespace boost
0029 {
0030 namespace hawick_circuits_detail
0031 {
0032
0033 struct get_all_adjacent_vertices
0034 {
0035 template < typename Sig > struct result;
0036
0037 template < typename This, typename Vertex, typename Graph >
0038 struct result< This(Vertex, Graph) >
0039 {
0040 private:
0041 typedef typename remove_reference< Graph >::type RawGraph;
0042 typedef graph_traits< RawGraph > Traits;
0043 typedef typename Traits::adjacency_iterator AdjacencyIterator;
0044
0045 public:
0046 typedef std::pair< AdjacencyIterator, AdjacencyIterator > type;
0047 };
0048
0049 template < typename Vertex, typename Graph >
0050 typename result< get_all_adjacent_vertices(
0051 BOOST_FWD_REF(Vertex), BOOST_FWD_REF(Graph)) >::type
0052 operator()(BOOST_FWD_REF(Vertex) v, BOOST_FWD_REF(Graph) g) const
0053 {
0054 return adjacent_vertices(
0055 boost::forward< Vertex >(v), boost::forward< Graph >(g));
0056 }
0057 };
0058
0059
0060 struct get_unique_adjacent_vertices
0061 {
0062 template < typename Sig > struct result;
0063
0064 template < typename This, typename Vertex, typename Graph >
0065 struct result< This(Vertex, Graph) >
0066 {
0067 typedef std::set< typename remove_reference< Vertex >::type > type;
0068 };
0069
0070 template < typename Vertex, typename Graph >
0071 typename result< get_unique_adjacent_vertices(
0072 Vertex, Graph const&) >::type
0073 operator()(Vertex v, Graph const& g) const
0074 {
0075 typedef typename result< get_unique_adjacent_vertices(
0076 Vertex, Graph const&) >::type Set;
0077 return Set(
0078 adjacent_vertices(v, g).first, adjacent_vertices(v, g).second);
0079 }
0080 };
0081
0082
0083
0084
0085
0086 template < typename Container, typename Value >
0087 bool contains(Container const& c, Value const& v)
0088 {
0089 return std::find(boost::begin(c), boost::end(c), v) != boost::end(c);
0090 }
0091
0092
0093
0094
0095
0096
0097
0098
0099 template < typename Graph, typename Visitor, typename VertexIndexMap,
0100 typename Stack, typename ClosedMatrix, typename GetAdjacentVertices >
0101 struct hawick_circuits_from
0102 {
0103 private:
0104 typedef graph_traits< Graph > Traits;
0105 typedef typename Traits::vertex_descriptor Vertex;
0106 typedef typename Traits::edge_descriptor Edge;
0107 typedef typename Traits::vertices_size_type VerticesSize;
0108 typedef
0109 typename property_traits< VertexIndexMap >::value_type VertexIndex;
0110
0111 typedef typename result_of< GetAdjacentVertices(
0112 Vertex, Graph const&) >::type AdjacentVertices;
0113 typedef typename range_iterator< AdjacentVertices const >::type
0114 AdjacencyIterator;
0115
0116
0117
0118
0119
0120 typedef one_bit_color_map< VertexIndexMap > BlockedMap;
0121 typedef typename property_traits< BlockedMap >::value_type BlockedColor;
0122
0123 static BlockedColor blocked_false_color()
0124 {
0125 return color_traits< BlockedColor >::white();
0126 }
0127
0128 static BlockedColor blocked_true_color()
0129 {
0130 return color_traits< BlockedColor >::black();
0131 }
0132
0133
0134
0135 bool blocked_map_starts_all_unblocked() const
0136 {
0137 BOOST_FOREACH (Vertex v, vertices(graph_))
0138 if (is_blocked(v))
0139 return false;
0140 return true;
0141 }
0142
0143
0144
0145 bool all_closed_rows_are_empty() const
0146 {
0147 BOOST_FOREACH (typename ClosedMatrix::reference row, closed_)
0148 if (!row.empty())
0149 return false;
0150 return true;
0151 }
0152
0153 public:
0154 hawick_circuits_from(Graph const& graph, Visitor& visitor,
0155 VertexIndexMap const& vim, Stack& stack, ClosedMatrix& closed,
0156 VerticesSize n_vertices)
0157 : graph_(graph)
0158 , visitor_(visitor)
0159 , vim_(vim)
0160 , stack_(stack)
0161 , closed_(closed)
0162 , blocked_(n_vertices, vim_)
0163 {
0164 BOOST_ASSERT(blocked_map_starts_all_unblocked());
0165
0166
0167
0168
0169 BOOST_ASSERT(stack_.empty());
0170 BOOST_ASSERT(closed_.size() == n_vertices);
0171 BOOST_ASSERT(all_closed_rows_are_empty());
0172 }
0173
0174 private:
0175
0176 VertexIndex index_of(Vertex v) const { return get(vim_, v); }
0177
0178
0179 bool is_closed_to(Vertex u, Vertex v) const
0180 {
0181 typedef typename ClosedMatrix::const_reference VertexList;
0182 VertexList closed_to_u = closed_[index_of(u)];
0183 return contains(closed_to_u, v);
0184 }
0185
0186
0187 void close_to(Vertex u, Vertex v)
0188 {
0189 BOOST_ASSERT(!is_closed_to(u, v));
0190 closed_[index_of(u)].push_back(v);
0191 }
0192
0193
0194 bool is_blocked(Vertex v) const
0195 {
0196 return get(blocked_, v) == blocked_true_color();
0197 }
0198
0199
0200 void block(Vertex v) { put(blocked_, v, blocked_true_color()); }
0201
0202
0203 void unblock(Vertex u)
0204 {
0205 typedef typename ClosedMatrix::reference VertexList;
0206
0207 put(blocked_, u, blocked_false_color());
0208 VertexList closed_to_u = closed_[index_of(u)];
0209
0210 while (!closed_to_u.empty())
0211 {
0212 Vertex const w = closed_to_u.back();
0213 closed_to_u.pop_back();
0214 if (is_blocked(w))
0215 unblock(w);
0216 }
0217 BOOST_ASSERT(closed_to_u.empty());
0218 }
0219
0220
0221 bool circuit(Vertex start, Vertex v)
0222 {
0223 bool found_circuit = false;
0224 stack_.push_back(v);
0225 block(v);
0226
0227
0228 VertexIndex const index_of_start = index_of(start);
0229 AdjacentVertices const adj_vertices
0230 = GetAdjacentVertices()(v, graph_);
0231 AdjacencyIterator const w_end = boost::end(adj_vertices);
0232
0233 for (AdjacencyIterator w_it = boost::begin(adj_vertices);
0234 w_it != w_end; ++w_it)
0235 {
0236 Vertex const w = *w_it;
0237
0238
0239
0240 if (index_of(w) < index_of_start)
0241 continue;
0242
0243
0244 else if (w == start)
0245 {
0246
0247
0248 visitor_.cycle(const_cast< Stack const& >(stack_), graph_);
0249 found_circuit = true;
0250 }
0251
0252
0253
0254 else if (!is_blocked(w) && circuit(start, w))
0255 found_circuit = true;
0256 }
0257
0258 if (found_circuit)
0259 unblock(v);
0260 else
0261 for (AdjacencyIterator w_it = boost::begin(adj_vertices);
0262 w_it != w_end; ++w_it)
0263 {
0264 Vertex const w = *w_it;
0265
0266
0267 if (index_of(w) < index_of_start)
0268 continue;
0269
0270
0271 if (!is_closed_to(w, v))
0272 close_to(w, v);
0273 }
0274
0275 BOOST_ASSERT(v == stack_.back());
0276 stack_.pop_back();
0277 return found_circuit;
0278 }
0279
0280 public:
0281 void operator()(Vertex start) { circuit(start, start); }
0282
0283 private:
0284 Graph const& graph_;
0285 Visitor& visitor_;
0286 VertexIndexMap const& vim_;
0287 Stack& stack_;
0288 ClosedMatrix& closed_;
0289 BlockedMap blocked_;
0290 };
0291
0292 template < typename GetAdjacentVertices, typename Graph, typename Visitor,
0293 typename VertexIndexMap >
0294 void call_hawick_circuits(Graph const& graph,
0295 Visitor visitor, VertexIndexMap const& vertex_index_map)
0296 {
0297 typedef graph_traits< Graph > Traits;
0298 typedef typename Traits::vertex_descriptor Vertex;
0299 typedef typename Traits::vertices_size_type VerticesSize;
0300 typedef typename Traits::vertex_iterator VertexIterator;
0301
0302 typedef std::vector< Vertex > Stack;
0303 typedef std::vector< std::vector< Vertex > > ClosedMatrix;
0304
0305 typedef hawick_circuits_from< Graph, Visitor, VertexIndexMap, Stack,
0306 ClosedMatrix, GetAdjacentVertices >
0307 SubAlgorithm;
0308
0309 VerticesSize const n_vertices = num_vertices(graph);
0310 Stack stack;
0311 stack.reserve(n_vertices);
0312 ClosedMatrix closed(n_vertices);
0313
0314 VertexIterator start, last;
0315 for (boost::tie(start, last) = vertices(graph); start != last; ++start)
0316 {
0317
0318
0319
0320
0321
0322
0323
0324 SubAlgorithm sub_algo(
0325 graph, visitor, vertex_index_map, stack, closed, n_vertices);
0326 sub_algo(*start);
0327 stack.clear();
0328 typename ClosedMatrix::iterator row, last_row = closed.end();
0329 for (row = closed.begin(); row != last_row; ++row)
0330 row->clear();
0331 }
0332 }
0333
0334 template < typename GetAdjacentVertices, typename Graph, typename Visitor >
0335 void call_hawick_circuits(
0336 Graph const& graph, BOOST_FWD_REF(Visitor) visitor)
0337 {
0338 call_hawick_circuits< GetAdjacentVertices >(graph,
0339 boost::forward< Visitor >(visitor), get(vertex_index, graph));
0340 }
0341 }
0342
0343
0344 template < typename Graph, typename Visitor, typename VertexIndexMap >
0345 void hawick_circuits(BOOST_FWD_REF(Graph) graph, BOOST_FWD_REF(Visitor) visitor,
0346 BOOST_FWD_REF(VertexIndexMap) vertex_index_map)
0347 {
0348 hawick_circuits_detail::call_hawick_circuits<
0349 hawick_circuits_detail::get_all_adjacent_vertices >(
0350 boost::forward< Graph >(graph), boost::forward< Visitor >(visitor),
0351 boost::forward< VertexIndexMap >(vertex_index_map));
0352 }
0353
0354 template < typename Graph, typename Visitor >
0355 void hawick_circuits(BOOST_FWD_REF(Graph) graph, BOOST_FWD_REF(Visitor) visitor)
0356 {
0357 hawick_circuits_detail::call_hawick_circuits<
0358 hawick_circuits_detail::get_all_adjacent_vertices >(
0359 boost::forward< Graph >(graph), boost::forward< Visitor >(visitor));
0360 }
0361
0362
0363
0364
0365
0366 template < typename Graph, typename Visitor, typename VertexIndexMap >
0367 void hawick_unique_circuits(BOOST_FWD_REF(Graph) graph,
0368 BOOST_FWD_REF(Visitor) visitor,
0369 BOOST_FWD_REF(VertexIndexMap) vertex_index_map)
0370 {
0371 hawick_circuits_detail::call_hawick_circuits<
0372 hawick_circuits_detail::get_unique_adjacent_vertices >(
0373 boost::forward< Graph >(graph), boost::forward< Visitor >(visitor),
0374 boost::forward< VertexIndexMap >(vertex_index_map));
0375 }
0376
0377 template < typename Graph, typename Visitor >
0378 void hawick_unique_circuits(
0379 BOOST_FWD_REF(Graph) graph, BOOST_FWD_REF(Visitor) visitor)
0380 {
0381 hawick_circuits_detail::call_hawick_circuits<
0382 hawick_circuits_detail::get_unique_adjacent_vertices >(
0383 boost::forward< Graph >(graph), boost::forward< Visitor >(visitor));
0384 }
0385 }
0386
0387 #endif