annotate DEPENDENCIES/generic/include/boost/graph/bipartite.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 /**
Chris@16 2 *
Chris@16 3 * Copyright (c) 2010 Matthias Walter (xammy@xammy.homelinux.net)
Chris@16 4 *
Chris@16 5 * Authors: Matthias Walter
Chris@16 6 *
Chris@16 7 * Distributed under the Boost Software License, Version 1.0. (See
Chris@16 8 * accompanying file LICENSE_1_0.txt or copy at
Chris@16 9 * http://www.boost.org/LICENSE_1_0.txt)
Chris@16 10 *
Chris@16 11 */
Chris@16 12
Chris@16 13 #ifndef BOOST_GRAPH_BIPARTITE_HPP
Chris@16 14 #define BOOST_GRAPH_BIPARTITE_HPP
Chris@16 15
Chris@16 16 #include <utility>
Chris@16 17 #include <vector>
Chris@16 18 #include <exception>
Chris@16 19 #include <boost/graph/properties.hpp>
Chris@16 20 #include <boost/graph/adjacency_list.hpp>
Chris@16 21 #include <boost/graph/depth_first_search.hpp>
Chris@16 22 #include <boost/graph/one_bit_color_map.hpp>
Chris@16 23 #include <boost/bind.hpp>
Chris@16 24
Chris@16 25 namespace boost {
Chris@16 26
Chris@16 27 namespace detail {
Chris@16 28
Chris@16 29 /**
Chris@16 30 * The bipartite_visitor_error is thrown if an edge cannot be colored.
Chris@16 31 * The witnesses are the edges incident vertices.
Chris@16 32 */
Chris@16 33
Chris@16 34 template <typename Vertex>
Chris@16 35 struct bipartite_visitor_error: std::exception
Chris@16 36 {
Chris@16 37 std::pair <Vertex, Vertex> witnesses;
Chris@16 38
Chris@16 39 bipartite_visitor_error (Vertex a, Vertex b) :
Chris@16 40 witnesses (a, b)
Chris@16 41 {
Chris@16 42
Chris@16 43 }
Chris@16 44
Chris@16 45 const char* what () const throw ()
Chris@16 46 {
Chris@16 47 return "Graph is not bipartite.";
Chris@16 48 }
Chris@16 49 };
Chris@16 50
Chris@16 51 /**
Chris@16 52 * Functor which colors edges to be non-monochromatic.
Chris@16 53 */
Chris@16 54
Chris@16 55 template <typename PartitionMap>
Chris@16 56 struct bipartition_colorize
Chris@16 57 {
Chris@16 58 typedef on_tree_edge event_filter;
Chris@16 59
Chris@16 60 bipartition_colorize (PartitionMap partition_map) :
Chris@16 61 partition_map_ (partition_map)
Chris@16 62 {
Chris@16 63
Chris@16 64 }
Chris@16 65
Chris@16 66 template <typename Edge, typename Graph>
Chris@16 67 void operator() (Edge e, const Graph& g)
Chris@16 68 {
Chris@16 69 typedef typename graph_traits <Graph>::vertex_descriptor vertex_descriptor_t;
Chris@16 70 typedef color_traits <typename property_traits <PartitionMap>::value_type> color_traits;
Chris@16 71
Chris@16 72 vertex_descriptor_t source_vertex = source (e, g);
Chris@16 73 vertex_descriptor_t target_vertex = target (e, g);
Chris@16 74 if (get (partition_map_, source_vertex) == color_traits::white ())
Chris@16 75 put (partition_map_, target_vertex, color_traits::black ());
Chris@16 76 else
Chris@16 77 put (partition_map_, target_vertex, color_traits::white ());
Chris@16 78 }
Chris@16 79
Chris@16 80 private:
Chris@16 81 PartitionMap partition_map_;
Chris@16 82 };
Chris@16 83
Chris@16 84 /**
Chris@16 85 * Creates a bipartition_colorize functor which colors edges
Chris@16 86 * to be non-monochromatic.
Chris@16 87 *
Chris@16 88 * @param partition_map Color map for the bipartition
Chris@16 89 * @return The functor.
Chris@16 90 */
Chris@16 91
Chris@16 92 template <typename PartitionMap>
Chris@16 93 inline bipartition_colorize <PartitionMap> colorize_bipartition (PartitionMap partition_map)
Chris@16 94 {
Chris@16 95 return bipartition_colorize <PartitionMap> (partition_map);
Chris@16 96 }
Chris@16 97
Chris@16 98 /**
Chris@16 99 * Functor which tests an edge to be monochromatic.
Chris@16 100 */
Chris@16 101
Chris@16 102 template <typename PartitionMap>
Chris@16 103 struct bipartition_check
Chris@16 104 {
Chris@16 105 typedef on_back_edge event_filter;
Chris@16 106
Chris@16 107 bipartition_check (PartitionMap partition_map) :
Chris@16 108 partition_map_ (partition_map)
Chris@16 109 {
Chris@16 110
Chris@16 111 }
Chris@16 112
Chris@16 113 template <typename Edge, typename Graph>
Chris@16 114 void operator() (Edge e, const Graph& g)
Chris@16 115 {
Chris@16 116 typedef typename graph_traits <Graph>::vertex_descriptor vertex_descriptor_t;
Chris@16 117
Chris@16 118 vertex_descriptor_t source_vertex = source (e, g);
Chris@16 119 vertex_descriptor_t target_vertex = target (e, g);
Chris@16 120 if (get (partition_map_, source_vertex) == get (partition_map_, target_vertex))
Chris@16 121 throw bipartite_visitor_error <vertex_descriptor_t> (source_vertex, target_vertex);
Chris@16 122 }
Chris@16 123
Chris@16 124 private:
Chris@16 125 PartitionMap partition_map_;
Chris@16 126 };
Chris@16 127
Chris@16 128 /**
Chris@16 129 * Creates a bipartition_check functor which raises an error if a
Chris@16 130 * monochromatic edge is found.
Chris@16 131 *
Chris@16 132 * @param partition_map The map for a bipartition.
Chris@16 133 * @return The functor.
Chris@16 134 */
Chris@16 135
Chris@16 136 template <typename PartitionMap>
Chris@16 137 inline bipartition_check <PartitionMap> check_bipartition (PartitionMap partition_map)
Chris@16 138 {
Chris@16 139 return bipartition_check <PartitionMap> (partition_map);
Chris@16 140 }
Chris@16 141
Chris@16 142 /**
Chris@16 143 * Find the beginning of a common suffix of two sequences
Chris@16 144 *
Chris@16 145 * @param sequence1 Pair of bidirectional iterators defining the first sequence.
Chris@16 146 * @param sequence2 Pair of bidirectional iterators defining the second sequence.
Chris@16 147 * @return Pair of iterators pointing to the beginning of the common suffix.
Chris@16 148 */
Chris@16 149
Chris@16 150 template <typename BiDirectionalIterator1, typename BiDirectionalIterator2>
Chris@16 151 inline std::pair <BiDirectionalIterator1, BiDirectionalIterator2> reverse_mismatch (std::pair <
Chris@16 152 BiDirectionalIterator1, BiDirectionalIterator1> sequence1, std::pair <BiDirectionalIterator2,
Chris@16 153 BiDirectionalIterator2> sequence2)
Chris@16 154 {
Chris@16 155 if (sequence1.first == sequence1.second || sequence2.first == sequence2.second)
Chris@16 156 return std::make_pair (sequence1.first, sequence2.first);
Chris@16 157
Chris@16 158 BiDirectionalIterator1 iter1 = sequence1.second;
Chris@16 159 BiDirectionalIterator2 iter2 = sequence2.second;
Chris@16 160
Chris@16 161 while (true)
Chris@16 162 {
Chris@16 163 --iter1;
Chris@16 164 --iter2;
Chris@16 165 if (*iter1 != *iter2)
Chris@16 166 {
Chris@16 167 ++iter1;
Chris@16 168 ++iter2;
Chris@16 169 break;
Chris@16 170 }
Chris@16 171 if (iter1 == sequence1.first)
Chris@16 172 break;
Chris@16 173 if (iter2 == sequence2.first)
Chris@16 174 break;
Chris@16 175 }
Chris@16 176
Chris@16 177 return std::make_pair (iter1, iter2);
Chris@16 178 }
Chris@16 179
Chris@16 180 }
Chris@16 181
Chris@16 182 /**
Chris@16 183 * Checks a given graph for bipartiteness and fills the given color map with
Chris@16 184 * white and black according to the bipartition. If the graph is not
Chris@16 185 * bipartite, the contents of the color map are undefined. Runs in linear
Chris@16 186 * time in the size of the graph, if access to the property maps is in
Chris@16 187 * constant time.
Chris@16 188 *
Chris@16 189 * @param graph The given graph.
Chris@16 190 * @param index_map An index map associating vertices with an index.
Chris@16 191 * @param partition_map A color map to fill with the bipartition.
Chris@16 192 * @return true if and only if the given graph is bipartite.
Chris@16 193 */
Chris@16 194
Chris@16 195 template <typename Graph, typename IndexMap, typename PartitionMap>
Chris@16 196 bool is_bipartite (const Graph& graph, const IndexMap index_map, PartitionMap partition_map)
Chris@16 197 {
Chris@16 198 /// General types and variables
Chris@16 199 typedef typename property_traits <PartitionMap>::value_type partition_color_t;
Chris@16 200 typedef typename graph_traits <Graph>::vertex_descriptor vertex_descriptor_t;
Chris@16 201
Chris@16 202 /// Declare dfs visitor
Chris@16 203 // detail::empty_recorder recorder;
Chris@16 204 // typedef detail::bipartite_visitor <PartitionMap, detail::empty_recorder> dfs_visitor_t;
Chris@16 205 // dfs_visitor_t dfs_visitor (partition_map, recorder);
Chris@16 206
Chris@16 207
Chris@16 208 /// Call dfs
Chris@16 209 try
Chris@16 210 {
Chris@16 211 depth_first_search (graph, vertex_index_map (index_map).visitor (make_dfs_visitor (std::make_pair (
Chris@16 212 detail::colorize_bipartition (partition_map), std::make_pair (detail::check_bipartition (partition_map),
Chris@16 213 put_property (partition_map, color_traits <partition_color_t>::white (), on_start_vertex ()))))));
Chris@16 214 }
Chris@16 215 catch (detail::bipartite_visitor_error <vertex_descriptor_t> error)
Chris@16 216 {
Chris@16 217 return false;
Chris@16 218 }
Chris@16 219
Chris@16 220 return true;
Chris@16 221 }
Chris@16 222
Chris@16 223 /**
Chris@16 224 * Checks a given graph for bipartiteness.
Chris@16 225 *
Chris@16 226 * @param graph The given graph.
Chris@16 227 * @param index_map An index map associating vertices with an index.
Chris@16 228 * @return true if and only if the given graph is bipartite.
Chris@16 229 */
Chris@16 230
Chris@16 231 template <typename Graph, typename IndexMap>
Chris@16 232 bool is_bipartite (const Graph& graph, const IndexMap index_map)
Chris@16 233 {
Chris@16 234 typedef one_bit_color_map <IndexMap> partition_map_t;
Chris@16 235 partition_map_t partition_map (num_vertices (graph), index_map);
Chris@16 236
Chris@16 237 return is_bipartite (graph, index_map, partition_map);
Chris@16 238 }
Chris@16 239
Chris@16 240 /**
Chris@16 241 * Checks a given graph for bipartiteness. The graph must
Chris@16 242 * have an internal vertex_index property. Runs in linear time in the
Chris@16 243 * size of the graph, if access to the property maps is in constant time.
Chris@16 244 *
Chris@16 245 * @param graph The given graph.
Chris@16 246 * @return true if and only if the given graph is bipartite.
Chris@16 247 */
Chris@16 248
Chris@16 249 template <typename Graph>
Chris@16 250 bool is_bipartite (const Graph& graph)
Chris@16 251 {
Chris@16 252 return is_bipartite (graph, get (vertex_index, graph));
Chris@16 253 }
Chris@16 254
Chris@16 255 /**
Chris@16 256 * Checks a given graph for bipartiteness and fills a given color map with
Chris@16 257 * white and black according to the bipartition. If the graph is not
Chris@16 258 * bipartite, a sequence of vertices, producing an odd-cycle, is written to
Chris@16 259 * the output iterator. The final iterator value is returned. Runs in linear
Chris@16 260 * time in the size of the graph, if access to the property maps is in
Chris@16 261 * constant time.
Chris@16 262 *
Chris@16 263 * @param graph The given graph.
Chris@16 264 * @param index_map An index map associating vertices with an index.
Chris@16 265 * @param partition_map A color map to fill with the bipartition.
Chris@16 266 * @param result An iterator to write the odd-cycle vertices to.
Chris@16 267 * @return The final iterator value after writing.
Chris@16 268 */
Chris@16 269
Chris@16 270 template <typename Graph, typename IndexMap, typename PartitionMap, typename OutputIterator>
Chris@16 271 OutputIterator find_odd_cycle (const Graph& graph, const IndexMap index_map, PartitionMap partition_map,
Chris@16 272 OutputIterator result)
Chris@16 273 {
Chris@16 274 /// General types and variables
Chris@16 275 typedef typename property_traits <PartitionMap>::value_type partition_color_t;
Chris@16 276 typedef typename graph_traits <Graph>::vertex_descriptor vertex_descriptor_t;
Chris@16 277 typedef typename graph_traits <Graph>::vertex_iterator vertex_iterator_t;
Chris@16 278 vertex_iterator_t vertex_iter, vertex_end;
Chris@16 279
Chris@16 280 /// Declare predecessor map
Chris@16 281 typedef std::vector <vertex_descriptor_t> predecessors_t;
Chris@16 282 typedef iterator_property_map <typename predecessors_t::iterator, IndexMap, vertex_descriptor_t,
Chris@16 283 vertex_descriptor_t&> predecessor_map_t;
Chris@16 284
Chris@16 285 predecessors_t predecessors (num_vertices (graph), graph_traits <Graph>::null_vertex ());
Chris@16 286 predecessor_map_t predecessor_map (predecessors.begin (), index_map);
Chris@16 287
Chris@16 288 /// Initialize predecessor map
Chris@16 289 for (boost::tie (vertex_iter, vertex_end) = vertices (graph); vertex_iter != vertex_end; ++vertex_iter)
Chris@16 290 {
Chris@16 291 put (predecessor_map, *vertex_iter, *vertex_iter);
Chris@16 292 }
Chris@16 293
Chris@16 294 /// Call dfs
Chris@16 295 try
Chris@16 296 {
Chris@16 297 depth_first_search (graph, vertex_index_map (index_map).visitor (make_dfs_visitor (std::make_pair (
Chris@16 298 detail::colorize_bipartition (partition_map), std::make_pair (detail::check_bipartition (partition_map),
Chris@16 299 std::make_pair (put_property (partition_map, color_traits <partition_color_t>::white (),
Chris@16 300 on_start_vertex ()), record_predecessors (predecessor_map, on_tree_edge ())))))));
Chris@16 301 }
Chris@16 302 catch (detail::bipartite_visitor_error <vertex_descriptor_t> error)
Chris@16 303 {
Chris@16 304 typedef std::vector <vertex_descriptor_t> path_t;
Chris@16 305
Chris@16 306 path_t path1, path2;
Chris@16 307 vertex_descriptor_t next, current;
Chris@16 308
Chris@16 309 /// First path
Chris@16 310 next = error.witnesses.first;
Chris@16 311 do
Chris@16 312 {
Chris@16 313 current = next;
Chris@16 314 path1.push_back (current);
Chris@16 315 next = predecessor_map[current];
Chris@16 316 }
Chris@16 317 while (current != next);
Chris@16 318
Chris@16 319 /// Second path
Chris@16 320 next = error.witnesses.second;
Chris@16 321 do
Chris@16 322 {
Chris@16 323 current = next;
Chris@16 324 path2.push_back (current);
Chris@16 325 next = predecessor_map[current];
Chris@16 326 }
Chris@16 327 while (current != next);
Chris@16 328
Chris@16 329 /// Find beginning of common suffix
Chris@16 330 std::pair <typename path_t::iterator, typename path_t::iterator> mismatch = detail::reverse_mismatch (
Chris@16 331 std::make_pair (path1.begin (), path1.end ()), std::make_pair (path2.begin (), path2.end ()));
Chris@16 332
Chris@16 333 /// Copy the odd-length cycle
Chris@16 334 result = std::copy (path1.begin (), mismatch.first + 1, result);
Chris@16 335 return std::reverse_copy (path2.begin (), mismatch.second, result);
Chris@16 336 }
Chris@16 337
Chris@16 338 return result;
Chris@16 339 }
Chris@16 340
Chris@16 341 /**
Chris@16 342 * Checks a given graph for bipartiteness. If the graph is not bipartite, a
Chris@16 343 * sequence of vertices, producing an odd-cycle, is written to the output
Chris@16 344 * iterator. The final iterator value is returned. Runs in linear time in the
Chris@16 345 * size of the graph, if access to the property maps is in constant time.
Chris@16 346 *
Chris@16 347 * @param graph The given graph.
Chris@16 348 * @param index_map An index map associating vertices with an index.
Chris@16 349 * @param result An iterator to write the odd-cycle vertices to.
Chris@16 350 * @return The final iterator value after writing.
Chris@16 351 */
Chris@16 352
Chris@16 353 template <typename Graph, typename IndexMap, typename OutputIterator>
Chris@16 354 OutputIterator find_odd_cycle (const Graph& graph, const IndexMap index_map, OutputIterator result)
Chris@16 355 {
Chris@16 356 typedef one_bit_color_map <IndexMap> partition_map_t;
Chris@16 357 partition_map_t partition_map (num_vertices (graph), index_map);
Chris@16 358
Chris@16 359 return find_odd_cycle (graph, index_map, partition_map, result);
Chris@16 360 }
Chris@16 361
Chris@16 362 /**
Chris@16 363 * Checks a given graph for bipartiteness. If the graph is not bipartite, a
Chris@16 364 * sequence of vertices, producing an odd-cycle, is written to the output
Chris@16 365 * iterator. The final iterator value is returned. The graph must have an
Chris@16 366 * internal vertex_index property. Runs in linear time in the size of the
Chris@16 367 * graph, if access to the property maps is in constant time.
Chris@16 368 *
Chris@16 369 * @param graph The given graph.
Chris@16 370 * @param result An iterator to write the odd-cycle vertices to.
Chris@16 371 * @return The final iterator value after writing.
Chris@16 372 */
Chris@16 373
Chris@16 374 template <typename Graph, typename OutputIterator>
Chris@16 375 OutputIterator find_odd_cycle (const Graph& graph, OutputIterator result)
Chris@16 376 {
Chris@16 377 return find_odd_cycle (graph, get (vertex_index, graph), result);
Chris@16 378 }
Chris@16 379 }
Chris@16 380
Chris@16 381 #endif /// BOOST_GRAPH_BIPARTITE_HPP