• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2005, 2006 The Trustees of Indiana University.
2 
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
7 //  Authors: Douglas Gregor
8 //           Andrew Lumsdaine
9 #define PBGL_ACCOUNTING
10 
11 #include <boost/graph/use_mpi.hpp>
12 #include <boost/config.hpp>
13 #include <boost/throw_exception.hpp>
14 #include <boost/graph/distributed/delta_stepping_shortest_paths.hpp>
15 #include <boost/graph/distributed/mpi_process_group.hpp>
16 #include <boost/lexical_cast.hpp>
17 #include <boost/graph/parallel/distribution.hpp>
18 #include <boost/graph/erdos_renyi_generator.hpp>
19 #include <boost/graph/distributed/adjacency_list.hpp>
20 #include <boost/graph/graphviz.hpp>
21 #include <boost/random.hpp>
22 #include <boost/test/minimal.hpp>
23 #include <boost/graph/iteration_macros.hpp>
24 
25 #include <iostream>
26 #include <iomanip>
27 
28 #ifdef BOOST_NO_EXCEPTIONS
29 void
throw_exception(std::exception const & ex)30 boost::throw_exception(std::exception const& ex)
31 {
32     std::cout << ex.what() << std::endl;
33     abort();
34 }
35 #endif
36 
37 /****************************************************************************
38  * Timing                                                                   *
39  ****************************************************************************/
40 typedef double time_type;
41 
get_time()42 inline time_type get_time()
43 {
44   return MPI_Wtime();
45 }
46 
print_time(time_type t)47 std::string print_time(time_type t)
48 {
49   std::ostringstream out;
50   out << std::setiosflags(std::ios::fixed) << std::setprecision(2) << t;
51   return out.str();
52 }
53 
54 /****************************************************************************
55  * Edge weight generator iterator                                           *
56  ****************************************************************************/
57 template<typename F, typename RandomGenerator>
58 class generator_iterator
59 {
60 public:
61   typedef std::input_iterator_tag iterator_category;
62   typedef typename F::result_type value_type;
63   typedef const value_type&       reference;
64   typedef const value_type*       pointer;
65   typedef void                    difference_type;
66 
67   explicit
generator_iterator(RandomGenerator & gen,const F & f=F ())68   generator_iterator(RandomGenerator& gen, const F& f = F())
69     : f(f), gen(&gen)
70   {
71     value = this->f(gen);
72   }
73 
operator *() const74   reference operator*() const  { return value; }
operator ->() const75   pointer   operator->() const { return &value; }
76 
operator ++()77   generator_iterator& operator++()
78   {
79     value = f(*gen);
80     return *this;
81   }
82 
operator ++(int)83   generator_iterator operator++(int)
84   {
85     generator_iterator temp(*this);
86     ++(*this);
87     return temp;
88   }
89 
operator ==(const generator_iterator & other) const90   bool operator==(const generator_iterator& other) const
91   { return f == other.f; }
92 
operator !=(const generator_iterator & other) const93   bool operator!=(const generator_iterator& other) const
94   { return !(*this == other); }
95 
96 private:
97   F f;
98   RandomGenerator* gen;
99   value_type value;
100 };
101 
102 template<typename F, typename RandomGenerator>
103 inline generator_iterator<F, RandomGenerator>
make_generator_iterator(RandomGenerator & gen,const F & f)104 make_generator_iterator( RandomGenerator& gen, const F& f)
105 { return generator_iterator<F, RandomGenerator>(gen, f); }
106 
107 /****************************************************************************
108  * Verification                                                             *
109  ****************************************************************************/
110 template <typename Graph, typename DistanceMap, typename WeightMap>
111 void
verify_shortest_paths(const Graph & g,DistanceMap distance,const WeightMap & weight)112 verify_shortest_paths(const Graph& g, DistanceMap distance,
113                       const WeightMap& weight) {
114 
115   distance.set_max_ghost_cells(0);
116 
117   BGL_FORALL_VERTICES_T(v, g, Graph) {
118     BGL_FORALL_OUTEDGES_T(v, e, g, Graph) {
119       get(distance, target(e, g));
120     }
121   }
122 
123   synchronize(process_group(g));
124 
125   BGL_FORALL_VERTICES_T(v, g, Graph) {
126     BGL_FORALL_OUTEDGES_T(v, e, g, Graph) {
127       assert(get(distance, target(e, g)) <=
128              get(distance, source(e, g)) + get(weight, e));
129     }
130   }
131 }
132 
133 using namespace boost;
134 using boost::graph::distributed::mpi_process_group;
135 
136 typedef int weight_type;
137 
138 struct WeightedEdge {
WeightedEdgeWeightedEdge139   WeightedEdge(weight_type weight = 0) : weight(weight) { }
140 
141   weight_type weight;
142 
143   template<typename Archiver>
serializeWeightedEdge144   void serialize(Archiver& ar, const unsigned int /*version*/)
145   {
146     ar & weight;
147   }
148 };
149 
150 struct VertexProperties {
VertexPropertiesVertexProperties151   VertexProperties(int d = 0)
152     : distance(d) { }
153 
154   int distance;
155 
156   template<typename Archiver>
serializeVertexProperties157   void serialize(Archiver& ar, const unsigned int /*version*/)
158   {
159     ar & distance;
160   }
161 };
162 
163 void
test_distributed_shortest_paths(int n,double p,int c,int seed)164 test_distributed_shortest_paths(int n, double p, int c, int seed)
165 {
166   typedef adjacency_list<listS,
167                          distributedS<mpi_process_group, vecS>,
168                          undirectedS,
169                          VertexProperties,
170                          WeightedEdge> Graph;
171 
172   typedef graph_traits<Graph>::vertices_size_type vertices_size_type;
173 
174   // Build a random number generator
175   minstd_rand gen;
176   gen.seed(seed);
177 
178   // Build a random graph
179   Graph g(erdos_renyi_iterator<minstd_rand, Graph>(gen, n, p),
180           erdos_renyi_iterator<minstd_rand, Graph>(),
181           make_generator_iterator(gen, uniform_int<int>(0, c)),
182           n);
183 
184   uniform_int<vertices_size_type> rand_vertex(0, n);
185 
186   graph::distributed::delta_stepping_shortest_paths(g,
187                                                     vertex(rand_vertex(gen), g),
188                                                     dummy_property_map(),
189                                                     get(&VertexProperties::distance, g),
190                                                     get(&WeightedEdge::weight, g));
191 
192   verify_shortest_paths(g,
193                         get(&VertexProperties::distance, g),
194                         get(&WeightedEdge::weight, g));
195 }
196 
test_main(int argc,char * argv[])197 int test_main(int argc, char* argv[])
198 {
199   mpi::environment env(argc, argv);
200 
201   int n = 1000;
202   double p = 0.01;
203   int c = 100;
204   int seed = 1;
205 
206   if (argc > 1) n             = lexical_cast<int>(argv[1]);
207   if (argc > 2) p             = lexical_cast<double>(argv[2]);
208   if (argc > 3) c             = lexical_cast<int>(argv[3]);
209   if (argc > 4) seed          = lexical_cast<int>(argv[4]);
210 
211   test_distributed_shortest_paths(n, p, c, seed);
212 
213   return 0;
214 }
215