transitive_closure_test.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright (C) 2001 Vladimir Prus <ghost@cs.msu.su>
  2. // Copyright (C) 2001 Jeremy Siek <jsiek@cs.indiana.edu>
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #include <iostream>
  7. #include <cstdlib>
  8. #include <ctime>
  9. #include <boost/graph/vector_as_graph.hpp>
  10. #include <boost/graph/adjacency_list.hpp>
  11. #include <boost/graph/adjacency_list_io.hpp>
  12. #include <boost/graph/graph_utility.hpp>
  13. #include <boost/graph/transitive_closure.hpp>
  14. #include <boost/progress.hpp>
  15. using namespace std;
  16. using namespace boost;
  17. void generate_graph(int n, double p, vector< vector<int> >& r1)
  18. {
  19. static class {
  20. public:
  21. double operator()() {
  22. return double(rand())/RAND_MAX;
  23. }
  24. } gen;
  25. r1.clear();
  26. r1.resize(n);
  27. for (int i = 0; i < n; ++i)
  28. for (int j = 0; j < n; ++j)
  29. if (gen() < p)
  30. r1[i].push_back(j);
  31. }
  32. template <class Graph>
  33. typename graph_traits<Graph>::degree_size_type
  34. num_incident(typename graph_traits<Graph>::vertex_descriptor u,
  35. typename graph_traits<Graph>::vertex_descriptor v,
  36. const Graph& g)
  37. {
  38. typename graph_traits<Graph>::degree_size_type d = 0;
  39. typename graph_traits<Graph>::out_edge_iterator i, i_end;
  40. for (boost::tie(i, i_end) = out_edges(u, g); i != i_end; ++i)
  41. if (target(*i, g) == v)
  42. ++d;
  43. return d;
  44. }
  45. // (i,j) is in E' iff j is reachable from i
  46. // Hmm, is_reachable does not detect when there is a non-trivial path
  47. // from i to i. It always returns true for is_reachable(i,i).
  48. // This needs to be fixed/worked around.
  49. template <typename Graph, typename GraphTC>
  50. bool check_transitive_closure(Graph& g, GraphTC& tc)
  51. {
  52. typename graph_traits<Graph>::vertex_iterator i, i_end;
  53. for (boost::tie(i, i_end) = vertices(g); i != i_end; ++i) {
  54. typename graph_traits<Graph>::vertex_iterator j, j_end;
  55. for (boost::tie(j, j_end) = vertices(g); j != j_end; ++j) {
  56. bool g_has_edge;
  57. typename graph_traits<Graph>::edge_descriptor e_g;
  58. typename graph_traits<Graph>::degree_size_type num_tc;
  59. boost::tie (e_g, g_has_edge) = edge(*i, *j, g);
  60. num_tc = num_incident(*i, *j, tc);
  61. if (*i == *j) {
  62. if (g_has_edge) {
  63. if (num_tc != 1)
  64. return false;
  65. } else {
  66. bool can_reach = false;
  67. typename graph_traits<Graph>::adjacency_iterator k, k_end;
  68. for (boost::tie(k, k_end) = adjacent_vertices(*i, g); k != k_end; ++k) {
  69. std::vector<default_color_type> color_map_vec(num_vertices(g));
  70. if (is_reachable(*k, *i, g, boost::make_iterator_property_map(color_map_vec.begin(), get(boost::vertex_index, g)))) {
  71. can_reach = true;
  72. break;
  73. }
  74. }
  75. if (can_reach) {
  76. if (num_tc != 1) {
  77. std::cout << "1. " << *i << std::endl;
  78. return false;
  79. }
  80. } else {
  81. if (num_tc != 0) {
  82. std::cout << "2. " << *i << std::endl;
  83. return false;
  84. }
  85. }
  86. }
  87. } else {
  88. std::vector<default_color_type> color_map_vec(num_vertices(g));
  89. if (is_reachable(*i, *j, g, boost::make_iterator_property_map(color_map_vec.begin(), get(boost::vertex_index, g)))) {
  90. if (num_tc != 1)
  91. return false;
  92. } else {
  93. if (num_tc != 0)
  94. return false;
  95. }
  96. }
  97. }
  98. }
  99. return true;
  100. }
  101. bool test(int n, double p)
  102. {
  103. vector< vector<int> > g1, g1_tc;
  104. generate_graph(n, p, g1);
  105. cout << "Created graph with " << n << " vertices.\n";
  106. vector< vector<int> > g1_c(g1);
  107. {
  108. progress_timer t;
  109. cout << "transitive_closure" << endl;
  110. transitive_closure(g1, g1_tc, vertex_index_map(get(boost::vertex_index, g1)));
  111. }
  112. if(check_transitive_closure(g1, g1_tc))
  113. return true;
  114. else {
  115. cout << "Original graph was ";
  116. print_graph(g1, get(boost::vertex_index, g1));
  117. cout << "Result is ";
  118. print_graph(g1_tc, get(boost::vertex_index, g1_tc));
  119. return false;
  120. }
  121. }
  122. int main()
  123. {
  124. srand(time(0));
  125. static class {
  126. public:
  127. double operator()() {
  128. return double(rand())/RAND_MAX;
  129. }
  130. } gen;
  131. for (size_t i = 0; i < 100; ++i) {
  132. int n = 0 + int(20*gen());
  133. double p = gen();
  134. if (!test(n, p)) {
  135. cout << "Failed." << endl;
  136. return 1;
  137. }
  138. }
  139. cout << "Passed." << endl;
  140. }