File indexing completed on 2025-01-18 09:37:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef BOOST_GRAPH_BIPARTITE_HPP
0014 #define BOOST_GRAPH_BIPARTITE_HPP
0015
0016 #include <utility>
0017 #include <vector>
0018 #include <exception>
0019 #include <boost/graph/properties.hpp>
0020 #include <boost/graph/adjacency_list.hpp>
0021 #include <boost/graph/depth_first_search.hpp>
0022 #include <boost/graph/one_bit_color_map.hpp>
0023
0024 namespace boost
0025 {
0026
0027 namespace detail
0028 {
0029
0030
0031
0032
0033
0034
0035 template < typename Vertex >
0036 struct BOOST_SYMBOL_VISIBLE bipartite_visitor_error : std::exception
0037 {
0038 std::pair< Vertex, Vertex > witnesses;
0039
0040 bipartite_visitor_error(Vertex a, Vertex b) : witnesses(a, b) {}
0041
0042 const char* what() const throw() { return "Graph is not bipartite."; }
0043 };
0044
0045
0046
0047
0048
0049 template < typename PartitionMap > struct bipartition_colorize
0050 {
0051 typedef on_tree_edge event_filter;
0052
0053 bipartition_colorize(PartitionMap partition_map)
0054 : partition_map_(partition_map)
0055 {
0056 }
0057
0058 template < typename Edge, typename Graph >
0059 void operator()(Edge e, const Graph& g)
0060 {
0061 typedef typename graph_traits< Graph >::vertex_descriptor
0062 vertex_descriptor_t;
0063 typedef color_traits<
0064 typename property_traits< PartitionMap >::value_type >
0065 color_traits;
0066
0067 vertex_descriptor_t source_vertex = source(e, g);
0068 vertex_descriptor_t target_vertex = target(e, g);
0069 if (get(partition_map_, source_vertex) == color_traits::white())
0070 put(partition_map_, target_vertex, color_traits::black());
0071 else
0072 put(partition_map_, target_vertex, color_traits::white());
0073 }
0074
0075 private:
0076 PartitionMap partition_map_;
0077 };
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 template < typename PartitionMap >
0088 inline bipartition_colorize< PartitionMap > colorize_bipartition(
0089 PartitionMap partition_map)
0090 {
0091 return bipartition_colorize< PartitionMap >(partition_map);
0092 }
0093
0094
0095
0096
0097
0098 template < typename PartitionMap > struct bipartition_check
0099 {
0100 typedef on_back_edge event_filter;
0101
0102 bipartition_check(PartitionMap partition_map)
0103 : partition_map_(partition_map)
0104 {
0105 }
0106
0107 template < typename Edge, typename Graph >
0108 void operator()(Edge e, const Graph& g)
0109 {
0110 typedef typename graph_traits< Graph >::vertex_descriptor
0111 vertex_descriptor_t;
0112
0113 vertex_descriptor_t source_vertex = source(e, g);
0114 vertex_descriptor_t target_vertex = target(e, g);
0115 if (get(partition_map_, source_vertex)
0116 == get(partition_map_, target_vertex))
0117 throw bipartite_visitor_error< vertex_descriptor_t >(
0118 source_vertex, target_vertex);
0119 }
0120
0121 private:
0122 PartitionMap partition_map_;
0123 };
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 template < typename PartitionMap >
0134 inline bipartition_check< PartitionMap > check_bipartition(
0135 PartitionMap partition_map)
0136 {
0137 return bipartition_check< PartitionMap >(partition_map);
0138 }
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150 template < typename BiDirectionalIterator1,
0151 typename BiDirectionalIterator2 >
0152 inline std::pair< BiDirectionalIterator1, BiDirectionalIterator2 >
0153 reverse_mismatch(
0154 std::pair< BiDirectionalIterator1, BiDirectionalIterator1 > sequence1,
0155 std::pair< BiDirectionalIterator2, BiDirectionalIterator2 > sequence2)
0156 {
0157 if (sequence1.first == sequence1.second
0158 || sequence2.first == sequence2.second)
0159 return std::make_pair(sequence1.first, sequence2.first);
0160
0161 BiDirectionalIterator1 iter1 = sequence1.second;
0162 BiDirectionalIterator2 iter2 = sequence2.second;
0163
0164 while (true)
0165 {
0166 --iter1;
0167 --iter2;
0168 if (*iter1 != *iter2)
0169 {
0170 ++iter1;
0171 ++iter2;
0172 break;
0173 }
0174 if (iter1 == sequence1.first)
0175 break;
0176 if (iter2 == sequence2.first)
0177 break;
0178 }
0179
0180 return std::make_pair(iter1, iter2);
0181 }
0182
0183 }
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 template < typename Graph, typename IndexMap, typename PartitionMap >
0199 bool is_bipartite(
0200 const Graph& graph, const IndexMap index_map, PartitionMap partition_map)
0201 {
0202
0203 typedef
0204 typename property_traits< PartitionMap >::value_type partition_color_t;
0205 typedef
0206 typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
0207
0208
0209
0210
0211
0212
0213
0214
0215 try
0216 {
0217 depth_first_search(graph,
0218 vertex_index_map(index_map).visitor(make_dfs_visitor(
0219 std::make_pair(detail::colorize_bipartition(partition_map),
0220 std::make_pair(detail::check_bipartition(partition_map),
0221 put_property(partition_map,
0222 color_traits< partition_color_t >::white(),
0223 on_start_vertex()))))));
0224 }
0225 catch (const detail::bipartite_visitor_error< vertex_descriptor_t >&)
0226 {
0227 return false;
0228 }
0229
0230 return true;
0231 }
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 template < typename Graph, typename IndexMap >
0242 bool is_bipartite(const Graph& graph, const IndexMap index_map)
0243 {
0244 typedef one_bit_color_map< IndexMap > partition_map_t;
0245 partition_map_t partition_map(num_vertices(graph), index_map);
0246
0247 return is_bipartite(graph, index_map, partition_map);
0248 }
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 template < typename Graph > bool is_bipartite(const Graph& graph)
0260 {
0261 return is_bipartite(graph, get(vertex_index, graph));
0262 }
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279 template < typename Graph, typename IndexMap, typename PartitionMap,
0280 typename OutputIterator >
0281 OutputIterator find_odd_cycle(const Graph& graph, const IndexMap index_map,
0282 PartitionMap partition_map, OutputIterator result)
0283 {
0284
0285 typedef
0286 typename property_traits< PartitionMap >::value_type partition_color_t;
0287 typedef
0288 typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
0289 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
0290 vertex_iterator_t vertex_iter, vertex_end;
0291
0292
0293 typedef std::vector< vertex_descriptor_t > predecessors_t;
0294 typedef iterator_property_map< typename predecessors_t::iterator, IndexMap,
0295 vertex_descriptor_t, vertex_descriptor_t& >
0296 predecessor_map_t;
0297
0298 predecessors_t predecessors(
0299 num_vertices(graph), graph_traits< Graph >::null_vertex());
0300 predecessor_map_t predecessor_map(predecessors.begin(), index_map);
0301
0302
0303 for (boost::tie(vertex_iter, vertex_end) = vertices(graph);
0304 vertex_iter != vertex_end; ++vertex_iter)
0305 {
0306 put(predecessor_map, *vertex_iter, *vertex_iter);
0307 }
0308
0309
0310 try
0311 {
0312 depth_first_search(graph,
0313 vertex_index_map(index_map).visitor(make_dfs_visitor(
0314 std::make_pair(detail::colorize_bipartition(partition_map),
0315 std::make_pair(detail::check_bipartition(partition_map),
0316 std::make_pair(
0317 put_property(partition_map,
0318 color_traits< partition_color_t >::white(),
0319 on_start_vertex()),
0320 record_predecessors(
0321 predecessor_map, on_tree_edge())))))));
0322 }
0323 catch (const detail::bipartite_visitor_error< vertex_descriptor_t >& error)
0324 {
0325 typedef std::vector< vertex_descriptor_t > path_t;
0326
0327 path_t path1, path2;
0328 vertex_descriptor_t next, current;
0329
0330
0331 next = error.witnesses.first;
0332 do
0333 {
0334 current = next;
0335 path1.push_back(current);
0336 next = predecessor_map[current];
0337 } while (current != next);
0338
0339
0340 next = error.witnesses.second;
0341 do
0342 {
0343 current = next;
0344 path2.push_back(current);
0345 next = predecessor_map[current];
0346 } while (current != next);
0347
0348
0349 std::pair< typename path_t::iterator, typename path_t::iterator >
0350 mismatch = detail::reverse_mismatch(
0351 std::make_pair(path1.begin(), path1.end()),
0352 std::make_pair(path2.begin(), path2.end()));
0353
0354
0355 result = std::copy(path1.begin(), mismatch.first + 1, result);
0356 return std::reverse_copy(path2.begin(), mismatch.second, result);
0357 }
0358
0359 return result;
0360 }
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374 template < typename Graph, typename IndexMap, typename OutputIterator >
0375 OutputIterator find_odd_cycle(
0376 const Graph& graph, const IndexMap index_map, OutputIterator result)
0377 {
0378 typedef one_bit_color_map< IndexMap > partition_map_t;
0379 partition_map_t partition_map(num_vertices(graph), index_map);
0380
0381 return find_odd_cycle(graph, index_map, partition_map, result);
0382 }
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396 template < typename Graph, typename OutputIterator >
0397 OutputIterator find_odd_cycle(const Graph& graph, OutputIterator result)
0398 {
0399 return find_odd_cycle(graph, get(vertex_index, graph), result);
0400 }
0401 }
0402
0403 #endif