File indexing completed on 2025-01-18 09:37:17
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #ifndef BOOST_GRAPH_DELTA_STEPPING_SHORTEST_PATHS_HPP
0040 #define BOOST_GRAPH_DELTA_STEPPING_SHORTEST_PATHS_HPP
0041
0042 #ifndef BOOST_GRAPH_USE_MPI
0043 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
0044 #endif
0045
0046 #include <boost/config.hpp>
0047 #include <boost/graph/graph_traits.hpp>
0048 #include <boost/property_map/property_map.hpp>
0049 #include <boost/property_map/parallel/parallel_property_maps.hpp>
0050 #include <boost/graph/iteration_macros.hpp>
0051 #include <limits>
0052 #include <list>
0053 #include <vector>
0054 #include <boost/graph/parallel/container_traits.hpp>
0055 #include <boost/graph/parallel/properties.hpp>
0056 #include <boost/graph/distributed/detail/dijkstra_shortest_paths.hpp>
0057 #include <utility> // for std::pair
0058 #include <functional> // for std::logical_or
0059 #include <boost/graph/parallel/algorithm.hpp> // for all_reduce
0060 #include <cassert>
0061 #include <algorithm> // for std::min, std::max
0062 #include <boost/graph/parallel/simple_trigger.hpp>
0063
0064 #ifdef PBGL_DELTA_STEPPING_DEBUG
0065 # include <iostream> // for std::cerr
0066 #endif
0067
0068 namespace boost { namespace graph { namespace distributed {
0069
0070 template<typename Graph, typename PredecessorMap, typename DistanceMap,
0071 typename EdgeWeightMap>
0072 class delta_stepping_impl {
0073 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
0074 typedef typename graph_traits<Graph>::degree_size_type Degree;
0075 typedef typename property_traits<EdgeWeightMap>::value_type Dist;
0076 typedef typename boost::graph::parallel::process_group_type<Graph>::type
0077 ProcessGroup;
0078
0079 typedef std::list<Vertex> Bucket;
0080 typedef typename Bucket::iterator BucketIterator;
0081 typedef typename std::vector<Bucket*>::size_type BucketIndex;
0082
0083 typedef detail::dijkstra_msg_value<DistanceMap, PredecessorMap> MessageValue;
0084
0085 enum {
0086
0087
0088
0089
0090
0091 msg_relax
0092 };
0093
0094 public:
0095 delta_stepping_impl(const Graph& g,
0096 PredecessorMap predecessor,
0097 DistanceMap distance,
0098 EdgeWeightMap weight,
0099 Dist delta);
0100
0101 delta_stepping_impl(const Graph& g,
0102 PredecessorMap predecessor,
0103 DistanceMap distance,
0104 EdgeWeightMap weight);
0105
0106 void run(Vertex s);
0107
0108 private:
0109
0110 void relax(Vertex u, Vertex v, Dist x);
0111
0112
0113
0114 void synchronize();
0115
0116
0117
0118
0119 void handle_relax_message(Vertex v, Dist x) { relax(v, v, x); }
0120
0121
0122
0123
0124 void handle_relax_message(Vertex v, const std::pair<Dist, Vertex>& p)
0125 { relax(p.second, v, p.first); }
0126
0127
0128 void setup_triggers();
0129
0130 void handle_msg_relax(int , int ,
0131 const std::pair<Vertex, typename MessageValue::type>& data,
0132 trigger_receive_context)
0133 { handle_relax_message(data.first, data.second); }
0134
0135 const Graph& g;
0136 PredecessorMap predecessor;
0137 DistanceMap distance;
0138 EdgeWeightMap weight;
0139 Dist delta;
0140 ProcessGroup pg;
0141 typename property_map<Graph, vertex_owner_t>::const_type owner;
0142 typename property_map<Graph, vertex_local_t>::const_type local;
0143
0144
0145
0146 std::vector<BucketIterator> position_in_bucket;
0147
0148
0149
0150
0151 std::vector<Bucket*> buckets;
0152
0153
0154
0155
0156
0157
0158 std::list<Vertex> dummy_list;
0159
0160
0161
0162 std::vector<bool> vertex_was_deleted;
0163 };
0164
0165 template<typename Graph, typename PredecessorMap, typename DistanceMap,
0166 typename EdgeWeightMap>
0167 delta_stepping_impl<Graph, PredecessorMap, DistanceMap, EdgeWeightMap>::
0168 delta_stepping_impl(const Graph& g,
0169 PredecessorMap predecessor,
0170 DistanceMap distance,
0171 EdgeWeightMap weight,
0172 Dist delta)
0173 : g(g),
0174 predecessor(predecessor),
0175 distance(distance),
0176 weight(weight),
0177 delta(delta),
0178 pg(boost::graph::parallel::process_group_adl(g), attach_distributed_object()),
0179 owner(get(vertex_owner, g)),
0180 local(get(vertex_local, g))
0181 {
0182 setup_triggers();
0183 }
0184
0185 template<typename Graph, typename PredecessorMap, typename DistanceMap,
0186 typename EdgeWeightMap>
0187 delta_stepping_impl<Graph, PredecessorMap, DistanceMap, EdgeWeightMap>::
0188 delta_stepping_impl(const Graph& g,
0189 PredecessorMap predecessor,
0190 DistanceMap distance,
0191 EdgeWeightMap weight)
0192 : g(g),
0193 predecessor(predecessor),
0194 distance(distance),
0195 weight(weight),
0196 pg(boost::graph::parallel::process_group_adl(g), attach_distributed_object()),
0197 owner(get(vertex_owner, g)),
0198 local(get(vertex_local, g))
0199 {
0200 using boost::parallel::all_reduce;
0201 using boost::parallel::maximum;
0202 using std::max;
0203
0204
0205 Dist max_edge_weight = 0;
0206 Degree max_degree = 0;
0207 BGL_FORALL_VERTICES_T(u, g, Graph) {
0208 max_degree = max BOOST_PREVENT_MACRO_SUBSTITUTION (max_degree, out_degree(u, g));
0209 BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
0210 max_edge_weight = max BOOST_PREVENT_MACRO_SUBSTITUTION (max_edge_weight, get(weight, e));
0211 }
0212
0213 max_edge_weight = all_reduce(pg, max_edge_weight, maximum<Dist>());
0214 max_degree = all_reduce(pg, max_degree, maximum<Degree>());
0215
0216
0217
0218 delta = max_edge_weight / max_degree;
0219 if (delta == 0)
0220 delta = 1;
0221
0222 setup_triggers();
0223 }
0224
0225 template<typename Graph, typename PredecessorMap, typename DistanceMap,
0226 typename EdgeWeightMap>
0227 void
0228 delta_stepping_impl<Graph, PredecessorMap, DistanceMap, EdgeWeightMap>::
0229 run(Vertex s)
0230 {
0231 Dist inf = (std::numeric_limits<Dist>::max)();
0232
0233
0234 position_in_bucket.clear();
0235 position_in_bucket.resize(num_vertices(g), dummy_list.end());
0236
0237
0238 vertex_was_deleted.clear();
0239 vertex_was_deleted.resize(num_vertices(g), false);
0240
0241
0242 BGL_FORALL_VERTICES_T(v, g, Graph)
0243 put(distance, v, inf);
0244
0245
0246 if (get(owner, s) == process_id(pg))
0247
0248 relax(s, s, 0);
0249 else
0250
0251 cache(distance, s, 0);
0252
0253 BucketIndex max_bucket = (std::numeric_limits<BucketIndex>::max)();
0254 BucketIndex current_bucket = 0;
0255 do {
0256
0257 synchronize();
0258
0259
0260 while (current_bucket < buckets.size()
0261 && (!buckets[current_bucket] || buckets[current_bucket]->empty()))
0262 ++current_bucket;
0263 if (current_bucket >= buckets.size())
0264 current_bucket = max_bucket;
0265
0266 #ifdef PBGL_DELTA_STEPPING_DEBUG
0267 std::cerr << "#" << process_id(pg) << ": lowest bucket is #"
0268 << current_bucket << std::endl;
0269 #endif
0270
0271
0272 using boost::parallel::all_reduce;
0273 using boost::parallel::minimum;
0274 current_bucket = all_reduce(pg, current_bucket, minimum<BucketIndex>());
0275
0276 if (current_bucket == max_bucket)
0277
0278 break;
0279
0280 #ifdef PBGL_DELTA_STEPPING_DEBUG
0281 if (process_id(pg) == 0)
0282 std::cerr << "Processing bucket #" << current_bucket << std::endl;
0283 #endif
0284
0285
0286
0287
0288
0289 std::vector<Vertex> deleted_vertices;
0290
0291
0292 bool nonempty_bucket;
0293 do {
0294
0295
0296 if (current_bucket < buckets.size() && buckets[current_bucket]) {
0297 Bucket& bucket = *buckets[current_bucket];
0298
0299 while (!bucket.empty()) {
0300 Vertex u = bucket.front();
0301
0302 #ifdef PBGL_DELTA_STEPPING_DEBUG
0303 std::cerr << "#" << process_id(pg) << ": processing vertex "
0304 << get(vertex_global, g, u).second << "@"
0305 << get(vertex_global, g, u).first
0306 << std::endl;
0307 #endif
0308
0309
0310 bucket.pop_front();
0311
0312
0313
0314 if (!vertex_was_deleted[get(local, u)]) {
0315 vertex_was_deleted[get(local, u)] = true;
0316 deleted_vertices.push_back(u);
0317 }
0318
0319
0320 Dist u_dist = get(distance, u);
0321 BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
0322 if (get(weight, e) <= delta)
0323 relax(u, target(e, g), u_dist + get(weight, e));
0324 }
0325 }
0326
0327
0328 synchronize();
0329
0330
0331 nonempty_bucket = (current_bucket < buckets.size()
0332 && buckets[current_bucket]
0333 && !buckets[current_bucket]->empty());
0334 } while (all_reduce(pg, nonempty_bucket, std::logical_or<bool>()));
0335
0336
0337
0338 for (typename std::vector<Vertex>::iterator iter = deleted_vertices.begin();
0339 iter != deleted_vertices.end(); ++iter) {
0340
0341 Vertex u = *iter;
0342 Dist u_dist = get(distance, u);
0343 BGL_FORALL_OUTEDGES_T(u, e, g, Graph)
0344 if (get(weight, e) > delta)
0345 relax(u, target(e, g), u_dist + get(weight, e));
0346 }
0347
0348
0349 ++current_bucket;
0350 } while (true);
0351
0352
0353 for (typename std::vector<Bucket*>::iterator iter = buckets.begin();
0354 iter != buckets.end(); ++iter) {
0355 if (*iter) {
0356 delete *iter;
0357 *iter = 0;
0358 }
0359 }
0360 }
0361
0362 template<typename Graph, typename PredecessorMap, typename DistanceMap,
0363 typename EdgeWeightMap>
0364 void
0365 delta_stepping_impl<Graph, PredecessorMap, DistanceMap, EdgeWeightMap>::
0366 relax(Vertex u, Vertex v, Dist x)
0367 {
0368 #ifdef PBGL_DELTA_STEPPING_DEBUG
0369 std::cerr << "#" << process_id(pg) << ": relax("
0370 << get(vertex_global, g, u).second << "@"
0371 << get(vertex_global, g, u).first << ", "
0372 << get(vertex_global, g, v).second << "@"
0373 << get(vertex_global, g, v).first << ", "
0374 << x << ")" << std::endl;
0375 #endif
0376
0377 if (x < get(distance, v)) {
0378
0379 if (get(owner, v) == process_id(pg)) {
0380
0381 BucketIndex new_index = static_cast<BucketIndex>(x / delta);
0382
0383
0384 if (new_index >= buckets.size()) buckets.resize(new_index + 1, 0);
0385
0386
0387 if (!buckets[new_index]) buckets[new_index] = new Bucket;
0388
0389 if (get(distance, v) != (std::numeric_limits<Dist>::max)()
0390 && !vertex_was_deleted[get(local, v)]) {
0391
0392
0393 BucketIndex old_index
0394 = static_cast<BucketIndex>(get(distance, v) / delta);
0395 buckets[new_index]->splice(buckets[new_index]->end(),
0396 *buckets[old_index],
0397 position_in_bucket[get(local, v)]);
0398 } else {
0399
0400
0401 buckets[new_index]->push_back(v);
0402 }
0403
0404
0405 position_in_bucket[get(local, v)] = buckets[new_index]->end();
0406 --position_in_bucket[get(local, v)];
0407
0408
0409 put(predecessor, v, u);
0410 put(distance, v, x);
0411 } else {
0412 #ifdef PBGL_DELTA_STEPPING_DEBUG
0413 std::cerr << "#" << process_id(pg) << ": sending relax("
0414 << get(vertex_global, g, u).second << "@"
0415 << get(vertex_global, g, u).first << ", "
0416 << get(vertex_global, g, v).second << "@"
0417 << get(vertex_global, g, v).first << ", "
0418 << x << ") to " << get(owner, v) << std::endl;
0419
0420 #endif
0421
0422 send(pg, get(owner, v), msg_relax,
0423 std::make_pair(v, MessageValue::create(x, u)));
0424
0425
0426 cache(distance, v, x);
0427 }
0428 }
0429 }
0430
0431 template<typename Graph, typename PredecessorMap, typename DistanceMap,
0432 typename EdgeWeightMap>
0433 void
0434 delta_stepping_impl<Graph, PredecessorMap, DistanceMap, EdgeWeightMap>::
0435 synchronize()
0436 {
0437 using boost::parallel::synchronize;
0438
0439
0440 synchronize(pg);
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453 }
0454
0455 template<typename Graph, typename PredecessorMap, typename DistanceMap,
0456 typename EdgeWeightMap>
0457 void
0458 delta_stepping_impl<Graph, PredecessorMap, DistanceMap, EdgeWeightMap>::
0459 setup_triggers()
0460 {
0461 using boost::graph::parallel::simple_trigger;
0462
0463 simple_trigger(pg, msg_relax, this,
0464 &delta_stepping_impl::handle_msg_relax);
0465 }
0466
0467 template<typename Graph, typename PredecessorMap, typename DistanceMap,
0468 typename EdgeWeightMap>
0469 void
0470 delta_stepping_shortest_paths
0471 (const Graph& g,
0472 typename graph_traits<Graph>::vertex_descriptor s,
0473 PredecessorMap predecessor, DistanceMap distance, EdgeWeightMap weight,
0474 typename property_traits<EdgeWeightMap>::value_type delta)
0475 {
0476
0477
0478 set_property_map_role(vertex_distance, distance);
0479
0480
0481
0482 delta_stepping_impl<Graph, PredecessorMap, DistanceMap, EdgeWeightMap>
0483 impl(g, predecessor, distance, weight, delta);
0484
0485
0486
0487 impl.run(s);
0488 }
0489
0490 template<typename Graph, typename PredecessorMap, typename DistanceMap,
0491 typename EdgeWeightMap>
0492 void
0493 delta_stepping_shortest_paths
0494 (const Graph& g,
0495 typename graph_traits<Graph>::vertex_descriptor s,
0496 PredecessorMap predecessor, DistanceMap distance, EdgeWeightMap weight)
0497 {
0498
0499
0500 set_property_map_role(vertex_distance, distance);
0501
0502
0503
0504 delta_stepping_impl<Graph, PredecessorMap, DistanceMap, EdgeWeightMap>
0505 impl(g, predecessor, distance, weight);
0506
0507
0508
0509 impl.run(s);
0510 }
0511
0512 } } }
0513
0514 #endif