biconnected_components_test.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright 2004 The Trustees of Indiana University.
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Douglas Gregor
  6. // Andrew Lumsdaine
  7. #include <boost/graph/biconnected_components.hpp>
  8. #include <boost/graph/adjacency_list.hpp>
  9. #include <boost/test/minimal.hpp>
  10. #include <boost/lexical_cast.hpp>
  11. #include <vector>
  12. #include <iterator>
  13. #include <iostream>
  14. #include <algorithm>
  15. #include <boost/graph/connected_components.hpp>
  16. #include <boost/graph/random.hpp>
  17. #include <boost/random/linear_congruential.hpp>
  18. #include <fstream>
  19. using namespace boost;
  20. struct EdgeProperty
  21. {
  22. std::size_t component;
  23. };
  24. static bool any_errors = false;
  25. template<typename Graph, typename Vertex>
  26. void
  27. check_articulation_points(const Graph& g, std::vector<Vertex> art_points)
  28. {
  29. std::vector<int> components(num_vertices(g));
  30. int basic_comps =
  31. connected_components(g,
  32. make_iterator_property_map(components.begin(),
  33. get(vertex_index, g),
  34. int()));
  35. std::vector<Vertex> art_points_check;
  36. typename graph_traits<Graph>::vertex_iterator vi, vi_end;
  37. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
  38. Graph g_copy(g);
  39. Vertex victim = vertex(get(vertex_index, g, *vi), g_copy);
  40. clear_vertex(victim, g_copy);
  41. remove_vertex(victim, g_copy);
  42. int copy_comps =
  43. connected_components
  44. (g_copy,
  45. make_iterator_property_map(components.begin(),
  46. get(vertex_index, g_copy),
  47. int()));
  48. if (copy_comps > basic_comps)
  49. art_points_check.push_back(*vi);
  50. }
  51. std::sort(art_points.begin(), art_points.end());
  52. std::sort(art_points_check.begin(), art_points_check.end());
  53. BOOST_CHECK(art_points == art_points_check);
  54. if (art_points != art_points_check) {
  55. std::cerr << "ERROR!" << std::endl;
  56. std::cerr << "\tComputed: ";
  57. std::size_t i;
  58. for (i = 0; i < art_points.size(); ++i)
  59. std::cout << art_points[i] << ' ';
  60. std::cout << std::endl << "\tExpected: ";
  61. for (i = 0; i < art_points_check.size(); ++i)
  62. std::cout << art_points_check[i] << ' ';
  63. std::cout << std::endl;
  64. any_errors = true;
  65. } else std::cout << "OK." << std::endl;
  66. }
  67. typedef adjacency_list<listS, vecS, undirectedS,
  68. no_property, EdgeProperty> Graph;
  69. typedef graph_traits<Graph>::vertex_descriptor Vertex;
  70. bool test_graph(Graph& g) { // Returns false on failure
  71. std::vector<Vertex> art_points;
  72. std::cout << "Computing biconnected components & articulation points... ";
  73. std::cout.flush();
  74. std::size_t num_comps =
  75. biconnected_components(g,
  76. get(&EdgeProperty::component, g),
  77. std::back_inserter(art_points)).first;
  78. std::cout << "done.\n\t" << num_comps << " biconnected components.\n"
  79. << "\t" << art_points.size() << " articulation points.\n"
  80. << "\tTesting articulation points...";
  81. std::cout.flush();
  82. check_articulation_points(g, art_points);
  83. if (any_errors) {
  84. std::ofstream out("biconnected_components_test_failed.dot");
  85. out << "graph A {\n" << " node[shape=\"circle\"]\n";
  86. for (std::size_t i = 0; i < art_points.size(); ++i) {
  87. out << art_points[i] << " [ style=\"filled\" ];" << std::endl;
  88. }
  89. graph_traits<Graph>::edge_iterator ei, ei_end;
  90. for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
  91. out << source(*ei, g) << " -- " << target(*ei, g)
  92. << "[label=\"" << g[*ei].component << "\"]\n";
  93. out << "}\n";
  94. }
  95. return any_errors;
  96. }
  97. int test_main(int argc, char* argv[])
  98. {
  99. std::size_t n = 100;
  100. std::size_t m = 500;
  101. std::size_t seed = 1;
  102. if (argc > 1) n = lexical_cast<std::size_t>(argv[1]);
  103. if (argc > 2) m = lexical_cast<std::size_t>(argv[2]);
  104. if (argc > 3) seed = lexical_cast<std::size_t>(argv[3]);
  105. {
  106. Graph g(n);
  107. minstd_rand gen(seed);
  108. generate_random_graph(g, n, m, gen);
  109. if (test_graph(g)) return 1;
  110. }
  111. {
  112. Graph g(4);
  113. add_edge(2, 3, g);
  114. add_edge(0, 3, g);
  115. add_edge(0, 2, g);
  116. add_edge(1, 0, g);
  117. if (test_graph(g)) return 1;
  118. }
  119. return 0;
  120. }