File indexing completed on 2025-01-18 09:37:17
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GRAPH_DISTRIBUTED_FRUCHTERMAN_REINGOLD_HPP
0010 #define BOOST_GRAPH_DISTRIBUTED_FRUCHTERMAN_REINGOLD_HPP
0011
0012 #ifndef BOOST_GRAPH_USE_MPI
0013 #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
0014 #endif
0015
0016 #include <boost/graph/fruchterman_reingold.hpp>
0017
0018 namespace boost { namespace graph { namespace distributed {
0019
0020 class simple_tiling
0021 {
0022 public:
0023 simple_tiling(int columns, int rows, bool flip = true)
0024 : columns(columns), rows(rows), flip(flip)
0025 {
0026 }
0027
0028
0029
0030 int operator()(int x, int y) const
0031 {
0032 return flip? (rows - y - 1) * columns + x : y * columns + x;
0033 }
0034
0035
0036
0037 std::pair<int, int> operator()(int id)
0038 {
0039 int my_col = id % columns;
0040 int my_row = flip? rows - (id / columns) - 1 : id / columns;
0041 return std::make_pair(my_col, my_row);
0042 }
0043
0044 int columns, rows;
0045
0046 private:
0047 bool flip;
0048 };
0049
0050
0051 struct no_force_pairs
0052 {
0053 template<typename Graph, typename ApplyForce>
0054 void operator()(const Graph&, const ApplyForce&)
0055 {
0056 }
0057 };
0058
0059
0060 template<typename PositionMap, typename DisplacementMap, typename LocalForces,
0061 typename NonLocalForces = no_force_pairs>
0062 class distributed_force_pairs_proxy
0063 {
0064 public:
0065 distributed_force_pairs_proxy(const PositionMap& position,
0066 const DisplacementMap& displacement,
0067 const LocalForces& local_forces,
0068 const NonLocalForces& nonlocal_forces = NonLocalForces())
0069 : position(position), displacement(displacement),
0070 local_forces(local_forces), nonlocal_forces(nonlocal_forces)
0071 {
0072 }
0073
0074 template<typename Graph, typename ApplyForce>
0075 void operator()(const Graph& g, ApplyForce apply_force)
0076 {
0077
0078 displacement.flush();
0079
0080
0081 synchronize(position);
0082
0083
0084 displacement.reset();
0085
0086
0087 local_forces(g, apply_force);
0088
0089
0090 nonlocal_forces(g, apply_force);
0091 }
0092
0093 protected:
0094 PositionMap position;
0095 DisplacementMap displacement;
0096 LocalForces local_forces;
0097 NonLocalForces nonlocal_forces;
0098 };
0099
0100 template<typename PositionMap, typename DisplacementMap, typename LocalForces>
0101 inline
0102 distributed_force_pairs_proxy<PositionMap, DisplacementMap, LocalForces>
0103 make_distributed_force_pairs(const PositionMap& position,
0104 const DisplacementMap& displacement,
0105 const LocalForces& local_forces)
0106 {
0107 typedef
0108 distributed_force_pairs_proxy<PositionMap, DisplacementMap, LocalForces>
0109 result_type;
0110 return result_type(position, displacement, local_forces);
0111 }
0112
0113 template<typename PositionMap, typename DisplacementMap, typename LocalForces,
0114 typename NonLocalForces>
0115 inline
0116 distributed_force_pairs_proxy<PositionMap, DisplacementMap, LocalForces,
0117 NonLocalForces>
0118 make_distributed_force_pairs(const PositionMap& position,
0119 const DisplacementMap& displacement,
0120 const LocalForces& local_forces,
0121 const NonLocalForces& nonlocal_forces)
0122 {
0123 typedef
0124 distributed_force_pairs_proxy<PositionMap, DisplacementMap, LocalForces,
0125 NonLocalForces>
0126 result_type;
0127 return result_type(position, displacement, local_forces, nonlocal_forces);
0128 }
0129
0130
0131
0132 template<typename PositionMap>
0133 class neighboring_tiles_force_pairs
0134 {
0135 public:
0136 typedef typename property_traits<PositionMap>::value_type Point;
0137 typedef typename point_traits<Point>::component_type Dim;
0138
0139 enum bucket_position { left, top, right, bottom, end_position };
0140
0141 neighboring_tiles_force_pairs(PositionMap position, Point origin,
0142 Point extent, simple_tiling tiling)
0143 : position(position), origin(origin), extent(extent), tiling(tiling)
0144 {
0145 }
0146
0147 template<typename Graph, typename ApplyForce>
0148 void operator()(const Graph& g, ApplyForce apply_force)
0149 {
0150
0151 if (tiling.columns == 1 && tiling.rows == 1)
0152 return;
0153
0154 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
0155 #ifndef BOOST_NO_STDC_NAMESPACE
0156 using std::sqrt;
0157 #endif
0158
0159
0160 Dim two_k = Dim(2) * sqrt(extent[0] * extent[1] / num_vertices(g));
0161
0162 std::vector<vertex_descriptor> my_vertices[4];
0163 std::vector<vertex_descriptor> neighbor_vertices[4];
0164
0165
0166 Dim cutoffs[4];
0167 cutoffs[left] = origin[0] + two_k;
0168 cutoffs[top] = origin[1] + two_k;
0169 cutoffs[right] = origin[0] + extent[0] - two_k;
0170 cutoffs[bottom] = origin[1] + extent[1] - two_k;
0171
0172
0173 typename PositionMap::process_group_type pg = position.process_group();
0174 std::pair<int, int> my_tile = tiling(process_id(pg));
0175 int neighbors[4] = { -1, -1, -1, -1 } ;
0176 if (my_tile.first > 0)
0177 neighbors[left] = tiling(my_tile.first - 1, my_tile.second);
0178 if (my_tile.second > 0)
0179 neighbors[top] = tiling(my_tile.first, my_tile.second - 1);
0180 if (my_tile.first < tiling.columns - 1)
0181 neighbors[right] = tiling(my_tile.first + 1, my_tile.second);
0182 if (my_tile.second < tiling.rows - 1)
0183 neighbors[bottom] = tiling(my_tile.first, my_tile.second + 1);
0184
0185
0186 BGL_FORALL_VERTICES_T(v, g, Graph) {
0187 if (position[v][0] <= cutoffs[left]) my_vertices[left].push_back(v);
0188 if (position[v][1] <= cutoffs[top]) my_vertices[top].push_back(v);
0189 if (position[v][0] >= cutoffs[right]) my_vertices[right].push_back(v);
0190 if (position[v][1] >= cutoffs[bottom]) my_vertices[bottom].push_back(v);
0191 }
0192
0193
0194 bucket_position pos;
0195 for (pos = left; pos < end_position; pos = bucket_position(pos + 1)) {
0196 if (neighbors[pos] != -1) {
0197 send(pg, neighbors[pos], 0, my_vertices[pos].size());
0198 if (!my_vertices[pos].empty())
0199 send(pg, neighbors[pos], 1,
0200 &my_vertices[pos].front(), my_vertices[pos].size());
0201 }
0202 }
0203
0204
0205 synchronize(pg);
0206
0207
0208 for (pos = left; pos < end_position; pos = bucket_position(pos + 1)) {
0209 if (neighbors[pos] != -1) {
0210 std::size_t incoming_vertices;
0211 receive(pg, neighbors[pos], 0, incoming_vertices);
0212
0213 if (incoming_vertices) {
0214 neighbor_vertices[pos].resize(incoming_vertices);
0215 receive(pg, neighbors[pos], 1, &neighbor_vertices[pos].front(),
0216 incoming_vertices);
0217 }
0218 }
0219 }
0220
0221
0222 for (pos = left; pos < end_position; pos = bucket_position(pos + 1))
0223 for (typename std::vector<vertex_descriptor>::iterator i =
0224 neighbor_vertices[pos].begin();
0225 i != neighbor_vertices[pos].end();
0226 ++i)
0227 request(position, *i);
0228 synchronize(position);
0229
0230
0231
0232 for (pos = left; pos < end_position; pos = bucket_position(pos + 1)) {
0233 for (typename std::vector<vertex_descriptor>::iterator i =
0234 my_vertices[pos].begin();
0235 i != my_vertices[pos].end();
0236 ++i)
0237 for (typename std::vector<vertex_descriptor>::iterator j =
0238 neighbor_vertices[pos].begin();
0239 j != neighbor_vertices[pos].end();
0240 ++j)
0241 apply_force(*i, *j);
0242 }
0243 }
0244
0245 protected:
0246 PositionMap position;
0247 Point origin;
0248 Point extent;
0249 simple_tiling tiling;
0250 };
0251
0252 template<typename PositionMap>
0253 inline neighboring_tiles_force_pairs<PositionMap>
0254 make_neighboring_tiles_force_pairs
0255 (PositionMap position,
0256 typename property_traits<PositionMap>::value_type origin,
0257 typename property_traits<PositionMap>::value_type extent,
0258 simple_tiling tiling)
0259 {
0260 return neighboring_tiles_force_pairs<PositionMap>(position, origin, extent,
0261 tiling);
0262 }
0263
0264 template<typename DisplacementMap, typename Cooling>
0265 class distributed_cooling_proxy
0266 {
0267 public:
0268 typedef typename Cooling::result_type result_type;
0269
0270 distributed_cooling_proxy(const DisplacementMap& displacement,
0271 const Cooling& cooling)
0272 : displacement(displacement), cooling(cooling)
0273 {
0274 }
0275
0276 result_type operator()()
0277 {
0278
0279 synchronize(displacement.data->process_group);
0280
0281
0282 return cooling();
0283 }
0284
0285 protected:
0286 DisplacementMap displacement;
0287 Cooling cooling;
0288 };
0289
0290 template<typename DisplacementMap, typename Cooling>
0291 inline distributed_cooling_proxy<DisplacementMap, Cooling>
0292 make_distributed_cooling(const DisplacementMap& displacement,
0293 const Cooling& cooling)
0294 {
0295 typedef distributed_cooling_proxy<DisplacementMap, Cooling> result_type;
0296 return result_type(displacement, cooling);
0297 }
0298
0299 template<typename Point>
0300 struct point_accumulating_reducer {
0301 BOOST_STATIC_CONSTANT(bool, non_default_resolver = true);
0302
0303 template<typename K>
0304 Point operator()(const K&) const { return Point(); }
0305
0306 template<typename K>
0307 Point operator()(const K&, const Point& p1, const Point& p2) const
0308 { return Point(p1[0] + p2[0], p1[1] + p2[1]); }
0309 };
0310
0311 template<typename Graph, typename PositionMap,
0312 typename AttractiveForce, typename RepulsiveForce,
0313 typename ForcePairs, typename Cooling, typename DisplacementMap>
0314 void
0315 fruchterman_reingold_force_directed_layout
0316 (const Graph& g,
0317 PositionMap position,
0318 typename property_traits<PositionMap>::value_type const& origin,
0319 typename property_traits<PositionMap>::value_type const& extent,
0320 AttractiveForce attractive_force,
0321 RepulsiveForce repulsive_force,
0322 ForcePairs force_pairs,
0323 Cooling cool,
0324 DisplacementMap displacement)
0325 {
0326 typedef typename property_traits<PositionMap>::value_type Point;
0327
0328
0329 displacement.set_reduce(point_accumulating_reducer<Point>());
0330
0331
0332 BGL_FORALL_VERTICES_T(u, g, Graph)
0333 BGL_FORALL_ADJ_T(u, v, g, Graph)
0334 request(position, v);
0335
0336
0337 boost::fruchterman_reingold_force_directed_layout
0338 (g, position, origin, extent,
0339 attractive_force, repulsive_force,
0340 make_distributed_force_pairs(position, displacement, force_pairs),
0341 make_distributed_cooling(displacement, cool),
0342 displacement);
0343 }
0344
0345 template<typename Graph, typename PositionMap,
0346 typename AttractiveForce, typename RepulsiveForce,
0347 typename ForcePairs, typename Cooling, typename DisplacementMap>
0348 void
0349 fruchterman_reingold_force_directed_layout
0350 (const Graph& g,
0351 PositionMap position,
0352 typename property_traits<PositionMap>::value_type const& origin,
0353 typename property_traits<PositionMap>::value_type const& extent,
0354 AttractiveForce attractive_force,
0355 RepulsiveForce repulsive_force,
0356 ForcePairs force_pairs,
0357 Cooling cool,
0358 DisplacementMap displacement,
0359 simple_tiling tiling)
0360 {
0361 typedef typename property_traits<PositionMap>::value_type Point;
0362
0363
0364 displacement.set_reduce(point_accumulating_reducer<Point>());
0365
0366
0367 BGL_FORALL_VERTICES_T(u, g, Graph)
0368 BGL_FORALL_ADJ_T(u, v, g, Graph)
0369 request(position, v);
0370
0371
0372 boost::fruchterman_reingold_force_directed_layout
0373 (g, position, origin, extent,
0374 attractive_force, repulsive_force,
0375 make_distributed_force_pairs
0376 (position, displacement, force_pairs,
0377 make_neighboring_tiles_force_pairs(position, origin, extent, tiling)),
0378 make_distributed_cooling(displacement, cool),
0379 displacement);
0380 }
0381
0382 } } }
0383
0384 #endif