distributed_shortest_paths_test.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Copyright (C) 2005, 2006 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. #define PBGL_ACCOUNTING
  8. #include <boost/graph/use_mpi.hpp>
  9. #include <boost/config.hpp>
  10. #include <boost/throw_exception.hpp>
  11. #include <boost/graph/distributed/delta_stepping_shortest_paths.hpp>
  12. #include <boost/graph/distributed/mpi_process_group.hpp>
  13. #include <boost/lexical_cast.hpp>
  14. #include <boost/graph/parallel/distribution.hpp>
  15. #include <boost/graph/erdos_renyi_generator.hpp>
  16. #include <boost/graph/distributed/adjacency_list.hpp>
  17. #include <boost/graph/graphviz.hpp>
  18. #include <boost/random.hpp>
  19. #include <boost/test/minimal.hpp>
  20. #include <boost/graph/iteration_macros.hpp>
  21. #include <iostream>
  22. #include <iomanip>
  23. #ifdef BOOST_NO_EXCEPTIONS
  24. void
  25. boost::throw_exception(std::exception const& ex)
  26. {
  27. std::cout << ex.what() << std::endl;
  28. abort();
  29. }
  30. #endif
  31. /****************************************************************************
  32. * Timing *
  33. ****************************************************************************/
  34. typedef double time_type;
  35. inline time_type get_time()
  36. {
  37. return MPI_Wtime();
  38. }
  39. std::string print_time(time_type t)
  40. {
  41. std::ostringstream out;
  42. out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
  43. return out.str();
  44. }
  45. /****************************************************************************
  46. * Edge weight generator iterator *
  47. ****************************************************************************/
  48. template<typename F, typename RandomGenerator>
  49. class generator_iterator
  50. {
  51. public:
  52. typedef std::input_iterator_tag iterator_category;
  53. typedef typename F::result_type value_type;
  54. typedef const value_type& reference;
  55. typedef const value_type* pointer;
  56. typedef void difference_type;
  57. explicit
  58. generator_iterator(RandomGenerator& gen, const F& f = F())
  59. : f(f), gen(&gen)
  60. {
  61. value = this->f(gen);
  62. }
  63. reference operator*() const { return value; }
  64. pointer operator->() const { return &value; }
  65. generator_iterator& operator++()
  66. {
  67. value = f(*gen);
  68. return *this;
  69. }
  70. generator_iterator operator++(int)
  71. {
  72. generator_iterator temp(*this);
  73. ++(*this);
  74. return temp;
  75. }
  76. bool operator==(const generator_iterator& other) const
  77. { return f == other.f; }
  78. bool operator!=(const generator_iterator& other) const
  79. { return !(*this == other); }
  80. private:
  81. F f;
  82. RandomGenerator* gen;
  83. value_type value;
  84. };
  85. template<typename F, typename RandomGenerator>
  86. inline generator_iterator<F, RandomGenerator>
  87. make_generator_iterator( RandomGenerator& gen, const F& f)
  88. { return generator_iterator<F, RandomGenerator>(gen, f); }
  89. /****************************************************************************
  90. * Verification *
  91. ****************************************************************************/
  92. template <typename Graph, typename DistanceMap, typename WeightMap>
  93. void
  94. verify_shortest_paths(const Graph& g, DistanceMap distance,
  95. const WeightMap& weight) {
  96. distance.set_max_ghost_cells(0);
  97. BGL_FORALL_VERTICES_T(v, g, Graph) {
  98. BGL_FORALL_OUTEDGES_T(v, e, g, Graph) {
  99. get(distance, target(e, g));
  100. }
  101. }
  102. synchronize(process_group(g));
  103. BGL_FORALL_VERTICES_T(v, g, Graph) {
  104. BGL_FORALL_OUTEDGES_T(v, e, g, Graph) {
  105. assert(get(distance, target(e, g)) <=
  106. get(distance, source(e, g)) + get(weight, e));
  107. }
  108. }
  109. }
  110. using namespace boost;
  111. using boost::graph::distributed::mpi_process_group;
  112. typedef int weight_type;
  113. struct WeightedEdge {
  114. WeightedEdge(weight_type weight = 0) : weight(weight) { }
  115. weight_type weight;
  116. template<typename Archiver>
  117. void serialize(Archiver& ar, const unsigned int /*version*/)
  118. {
  119. ar & weight;
  120. }
  121. };
  122. struct VertexProperties {
  123. VertexProperties(int d = 0)
  124. : distance(d) { }
  125. int distance;
  126. template<typename Archiver>
  127. void serialize(Archiver& ar, const unsigned int /*version*/)
  128. {
  129. ar & distance;
  130. }
  131. };
  132. void
  133. test_distributed_shortest_paths(int n, double p, int c, int seed)
  134. {
  135. typedef adjacency_list<listS,
  136. distributedS<mpi_process_group, vecS>,
  137. undirectedS,
  138. VertexProperties,
  139. WeightedEdge> Graph;
  140. typedef graph_traits<Graph>::vertices_size_type vertices_size_type;
  141. // Build a random number generator
  142. minstd_rand gen;
  143. gen.seed(seed);
  144. // Build a random graph
  145. Graph g(erdos_renyi_iterator<minstd_rand, Graph>(gen, n, p),
  146. erdos_renyi_iterator<minstd_rand, Graph>(),
  147. make_generator_iterator(gen, uniform_int<int>(0, c)),
  148. n);
  149. uniform_int<vertices_size_type> rand_vertex(0, n);
  150. graph::distributed::delta_stepping_shortest_paths(g,
  151. vertex(rand_vertex(gen), g),
  152. dummy_property_map(),
  153. get(&VertexProperties::distance, g),
  154. get(&WeightedEdge::weight, g));
  155. verify_shortest_paths(g,
  156. get(&VertexProperties::distance, g),
  157. get(&WeightedEdge::weight, g));
  158. }
  159. int test_main(int argc, char* argv[])
  160. {
  161. mpi::environment env(argc, argv);
  162. int n = 1000;
  163. double p = 0.01;
  164. int c = 100;
  165. int seed = 1;
  166. if (argc > 1) n = lexical_cast<int>(argv[1]);
  167. if (argc > 2) p = lexical_cast<double>(argv[2]);
  168. if (argc > 3) c = lexical_cast<int>(argv[3]);
  169. if (argc > 4) seed = lexical_cast<int>(argv[4]);
  170. test_distributed_shortest_paths(n, p, c, seed);
  171. return 0;
  172. }