bipartite_test.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /**
  2. *
  3. * Copyright (c) 2010 Matthias Walter (xammy@xammy.homelinux.net)
  4. *
  5. * Authors: Matthias Walter
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See
  8. * accompanying file LICENSE_1_0.txt or copy at
  9. * http://www.boost.org/LICENSE_1_0.txt)
  10. *
  11. */
  12. #include <boost/graph/adjacency_list.hpp>
  13. #include <boost/graph/lookup_edge.hpp>
  14. #include <boost/test/minimal.hpp>
  15. #include <boost/graph/bipartite.hpp>
  16. /// Verifies a 2-coloring
  17. template <typename Graph, typename ColorMap>
  18. void check_two_coloring (const Graph& g, const ColorMap color_map)
  19. {
  20. typedef boost::graph_traits <Graph> traits;
  21. typename traits::edge_iterator edge_iter, edge_end;
  22. for (boost::tie (edge_iter, edge_end) = boost::edges (g); edge_iter != edge_end; ++edge_iter)
  23. {
  24. typename traits::vertex_descriptor source, target;
  25. source = boost::source (*edge_iter, g);
  26. target = boost::target (*edge_iter, g);
  27. BOOST_REQUIRE (boost::get(color_map, source) != boost::get(color_map, target));
  28. }
  29. }
  30. /// Tests for a vertex sequence to define an odd cycle
  31. template <typename Graph, typename RandomAccessIterator>
  32. void check_odd_cycle (const Graph& g, RandomAccessIterator first, RandomAccessIterator beyond)
  33. {
  34. typedef boost::graph_traits <Graph> traits;
  35. typename traits::vertex_descriptor first_vertex, current_vertex, last_vertex;
  36. BOOST_CHECK ((beyond - first) % 2 == 1);
  37. // std::cout << "odd_cycle: " << int(*first) << std::endl;
  38. for (first_vertex = current_vertex = *first++; first != beyond; ++first)
  39. {
  40. // std::cout << "odd_cycle: " << int(*first) << std::endl;
  41. last_vertex = current_vertex;
  42. current_vertex = *first;
  43. BOOST_REQUIRE (boost::lookup_edge (current_vertex, last_vertex, g).second);
  44. }
  45. BOOST_REQUIRE (boost::lookup_edge (first_vertex, current_vertex, g).second);
  46. }
  47. /// Call the is_bipartite and find_odd_cycle functions and verify their results.
  48. template <typename Graph, typename IndexMap>
  49. void check_bipartite (const Graph& g, IndexMap index_map, bool is_bipartite)
  50. {
  51. typedef boost::graph_traits <Graph> traits;
  52. typedef std::vector <boost::default_color_type> partition_t;
  53. typedef std::vector <typename traits::vertex_descriptor> vertex_vector_t;
  54. typedef boost::iterator_property_map <partition_t::iterator, IndexMap> partition_map_t;
  55. partition_t partition (boost::num_vertices (g));
  56. partition_map_t partition_map (partition.begin (), index_map);
  57. vertex_vector_t odd_cycle (boost::num_vertices (g));
  58. bool first_result = boost::is_bipartite (g, index_map, partition_map);
  59. BOOST_REQUIRE (first_result == boost::is_bipartite(g, index_map));
  60. if (first_result)
  61. check_two_coloring (g, partition_map);
  62. BOOST_CHECK (first_result == is_bipartite);
  63. typename vertex_vector_t::iterator second_first = odd_cycle.begin ();
  64. typename vertex_vector_t::iterator second_beyond = boost::find_odd_cycle (g, index_map, partition_map, second_first);
  65. if (is_bipartite)
  66. {
  67. BOOST_CHECK (second_beyond == second_first);
  68. check_two_coloring (g, partition_map);
  69. }
  70. else
  71. {
  72. check_odd_cycle (g, second_first, second_beyond);
  73. }
  74. second_beyond = boost::find_odd_cycle (g, index_map, second_first);
  75. if (is_bipartite)
  76. {
  77. BOOST_CHECK (second_beyond == second_first);
  78. }
  79. else
  80. {
  81. check_odd_cycle (g, second_first, second_beyond);
  82. }
  83. }
  84. int test_main (int argc, char **argv)
  85. {
  86. typedef boost::adjacency_list <boost::vecS, boost::vecS, boost::undirectedS> vector_graph_t;
  87. typedef boost::adjacency_list <boost::listS, boost::listS, boost::undirectedS> list_graph_t;
  88. typedef std::pair <int, int> E;
  89. typedef std::map <boost::graph_traits <list_graph_t>::vertex_descriptor, size_t> index_map_t;
  90. typedef boost::associative_property_map <index_map_t> index_property_map_t;
  91. /**
  92. * Create the graph drawn below.
  93. *
  94. * 0 - 1 - 2
  95. * | |
  96. * 3 - 4 - 5 - 6
  97. * / \ /
  98. * | 7
  99. * | |
  100. * 8 - 9 - 10
  101. **/
  102. E bipartite_edges[] = { E (0, 1), E (0, 4), E (1, 2), E (2, 6), E (3, 4), E (3, 8), E (4, 5), E (4, 7), E (5, 6), E (
  103. 6, 7), E (7, 10), E (8, 9), E (9, 10) };
  104. vector_graph_t bipartite_vector_graph (&bipartite_edges[0],
  105. &bipartite_edges[0] + sizeof(bipartite_edges) / sizeof(E), 11);
  106. list_graph_t
  107. bipartite_list_graph (&bipartite_edges[0], &bipartite_edges[0] + sizeof(bipartite_edges) / sizeof(E), 11);
  108. /**
  109. * Create the graph drawn below.
  110. *
  111. * 2 - 1 - 0
  112. * | |
  113. * 3 - 6 - 5 - 4
  114. * / \ /
  115. * | 7
  116. * | /
  117. * 8 ---- 9
  118. *
  119. **/
  120. E non_bipartite_edges[] = { E (0, 1), E (0, 4), E (1, 2), E (2, 6), E (3, 4), E (3, 8), E (4, 5), E (4, 7), E (5, 6),
  121. E (6, 7), E (7, 9), E (8, 9) };
  122. vector_graph_t non_bipartite_vector_graph (&non_bipartite_edges[0], &non_bipartite_edges[0]
  123. + sizeof(non_bipartite_edges) / sizeof(E), 10);
  124. list_graph_t non_bipartite_list_graph (&non_bipartite_edges[0], &non_bipartite_edges[0] + sizeof(non_bipartite_edges)
  125. / sizeof(E), 10);
  126. /// Create index maps
  127. index_map_t bipartite_index_map, non_bipartite_index_map;
  128. boost::graph_traits <list_graph_t>::vertex_iterator vertex_iter, vertex_end;
  129. size_t i = 0;
  130. for (boost::tie (vertex_iter, vertex_end) = boost::vertices (bipartite_list_graph); vertex_iter != vertex_end; ++vertex_iter)
  131. {
  132. bipartite_index_map[*vertex_iter] = i++;
  133. }
  134. index_property_map_t bipartite_index_property_map = index_property_map_t (bipartite_index_map);
  135. i = 0;
  136. for (boost::tie (vertex_iter, vertex_end) = boost::vertices (non_bipartite_list_graph); vertex_iter != vertex_end; ++vertex_iter)
  137. {
  138. non_bipartite_index_map[*vertex_iter] = i++;
  139. }
  140. index_property_map_t non_bipartite_index_property_map = index_property_map_t (non_bipartite_index_map);
  141. /// Call real checks
  142. check_bipartite (bipartite_vector_graph, boost::get (boost::vertex_index, bipartite_vector_graph), true);
  143. check_bipartite (bipartite_list_graph, bipartite_index_property_map, true);
  144. check_bipartite (non_bipartite_vector_graph, boost::get (boost::vertex_index, non_bipartite_vector_graph), false);
  145. check_bipartite (non_bipartite_list_graph, non_bipartite_index_property_map, false);
  146. /// Test some more interfaces
  147. BOOST_REQUIRE (is_bipartite (bipartite_vector_graph));
  148. BOOST_REQUIRE (!is_bipartite (non_bipartite_vector_graph));
  149. return 0;
  150. }