gursoy_atun_layout.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. // Copyright 2004 The Trustees of Indiana University.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Jeremiah Willcock
  6. // Douglas Gregor
  7. // Andrew Lumsdaine
  8. #ifndef BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP
  9. #define BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP
  10. // Gürsoy-Atun graph layout, based on:
  11. // "Neighbourhood Preserving Load Balancing: A Self-Organizing Approach"
  12. // in 6th International Euro-Par Conference Munich, Germany, August 29 –
  13. // September 1, 2000 Proceedings, pp 234-241
  14. // https://doi.org/10.1007/3-540-44520-X_32
  15. #include <boost/config/no_tr1/cmath.hpp>
  16. #include <boost/throw_exception.hpp>
  17. #include <boost/assert.hpp>
  18. #include <vector>
  19. #include <exception>
  20. #include <algorithm>
  21. #include <boost/graph/visitors.hpp>
  22. #include <boost/graph/properties.hpp>
  23. #include <boost/random/uniform_01.hpp>
  24. #include <boost/random/linear_congruential.hpp>
  25. #include <boost/shared_ptr.hpp>
  26. #include <boost/graph/breadth_first_search.hpp>
  27. #include <boost/graph/dijkstra_shortest_paths.hpp>
  28. #include <boost/graph/named_function_params.hpp>
  29. #include <boost/graph/topology.hpp>
  30. namespace boost
  31. {
  32. namespace detail
  33. {
  34. struct over_distance_limit : public std::exception
  35. {
  36. };
  37. template < typename PositionMap, typename NodeDistanceMap,
  38. typename Topology, typename Graph >
  39. struct update_position_visitor
  40. {
  41. typedef typename Topology::point_type Point;
  42. PositionMap position_map;
  43. NodeDistanceMap node_distance;
  44. const Topology& space;
  45. Point input_vector;
  46. double distance_limit;
  47. double learning_constant;
  48. double falloff_ratio;
  49. typedef boost::on_examine_vertex event_filter;
  50. typedef
  51. typename graph_traits< Graph >::vertex_descriptor vertex_descriptor;
  52. update_position_visitor(PositionMap position_map,
  53. NodeDistanceMap node_distance, const Topology& space,
  54. const Point& input_vector, double distance_limit,
  55. double learning_constant, double falloff_ratio)
  56. : position_map(position_map)
  57. , node_distance(node_distance)
  58. , space(space)
  59. , input_vector(input_vector)
  60. , distance_limit(distance_limit)
  61. , learning_constant(learning_constant)
  62. , falloff_ratio(falloff_ratio)
  63. {
  64. }
  65. void operator()(vertex_descriptor v, const Graph&) const
  66. {
  67. #ifndef BOOST_NO_STDC_NAMESPACE
  68. using std::pow;
  69. #endif
  70. if (get(node_distance, v) > distance_limit)
  71. BOOST_THROW_EXCEPTION(over_distance_limit());
  72. Point old_position = get(position_map, v);
  73. double distance = get(node_distance, v);
  74. double fraction
  75. = learning_constant * pow(falloff_ratio, distance * distance);
  76. put(position_map, v,
  77. space.move_position_toward(
  78. old_position, fraction, input_vector));
  79. }
  80. };
  81. template < typename EdgeWeightMap > struct gursoy_shortest
  82. {
  83. template < typename Graph, typename NodeDistanceMap,
  84. typename UpdatePosition >
  85. static inline void run(const Graph& g,
  86. typename graph_traits< Graph >::vertex_descriptor s,
  87. NodeDistanceMap node_distance, UpdatePosition& update_position,
  88. EdgeWeightMap weight)
  89. {
  90. boost::dijkstra_shortest_paths(g, s,
  91. weight_map(weight).visitor(boost::make_dijkstra_visitor(
  92. std::make_pair(boost::record_distances(
  93. node_distance, boost::on_edge_relaxed()),
  94. update_position))));
  95. }
  96. };
  97. template <> struct gursoy_shortest< dummy_property_map >
  98. {
  99. template < typename Graph, typename NodeDistanceMap,
  100. typename UpdatePosition >
  101. static inline void run(const Graph& g,
  102. typename graph_traits< Graph >::vertex_descriptor s,
  103. NodeDistanceMap node_distance, UpdatePosition& update_position,
  104. dummy_property_map)
  105. {
  106. boost::breadth_first_search(g, s,
  107. visitor(boost::make_bfs_visitor(
  108. std::make_pair(boost::record_distances(
  109. node_distance, boost::on_tree_edge()),
  110. update_position))));
  111. }
  112. };
  113. } // namespace detail
  114. template < typename VertexListAndIncidenceGraph, typename Topology,
  115. typename PositionMap, typename Diameter, typename VertexIndexMap,
  116. typename EdgeWeightMap >
  117. void gursoy_atun_step(const VertexListAndIncidenceGraph& graph,
  118. const Topology& space, PositionMap position, Diameter diameter,
  119. double learning_constant, VertexIndexMap vertex_index_map,
  120. EdgeWeightMap weight)
  121. {
  122. #ifndef BOOST_NO_STDC_NAMESPACE
  123. using std::exp;
  124. using std::pow;
  125. #endif
  126. typedef
  127. typename graph_traits< VertexListAndIncidenceGraph >::vertex_iterator
  128. vertex_iterator;
  129. typedef
  130. typename graph_traits< VertexListAndIncidenceGraph >::vertex_descriptor
  131. vertex_descriptor;
  132. typedef typename Topology::point_type point_type;
  133. vertex_iterator i, iend;
  134. std::vector< double > distance_from_input_vector(num_vertices(graph));
  135. typedef boost::iterator_property_map< std::vector< double >::iterator,
  136. VertexIndexMap, double, double& >
  137. DistanceFromInputMap;
  138. DistanceFromInputMap distance_from_input(
  139. distance_from_input_vector.begin(), vertex_index_map);
  140. std::vector< double > node_distance_map_vector(num_vertices(graph));
  141. typedef boost::iterator_property_map< std::vector< double >::iterator,
  142. VertexIndexMap, double, double& >
  143. NodeDistanceMap;
  144. NodeDistanceMap node_distance(
  145. node_distance_map_vector.begin(), vertex_index_map);
  146. point_type input_vector = space.random_point();
  147. vertex_descriptor min_distance_loc
  148. = graph_traits< VertexListAndIncidenceGraph >::null_vertex();
  149. double min_distance = 0.0;
  150. bool min_distance_unset = true;
  151. for (boost::tie(i, iend) = vertices(graph); i != iend; ++i)
  152. {
  153. double this_distance = space.distance(get(position, *i), input_vector);
  154. put(distance_from_input, *i, this_distance);
  155. if (min_distance_unset || this_distance < min_distance)
  156. {
  157. min_distance = this_distance;
  158. min_distance_loc = *i;
  159. }
  160. min_distance_unset = false;
  161. }
  162. BOOST_ASSERT(!min_distance_unset); // Graph must have at least one vertex
  163. boost::detail::update_position_visitor< PositionMap, NodeDistanceMap,
  164. Topology, VertexListAndIncidenceGraph >
  165. update_position(position, node_distance, space, input_vector, diameter,
  166. learning_constant, exp(-1. / (2 * diameter * diameter)));
  167. std::fill(
  168. node_distance_map_vector.begin(), node_distance_map_vector.end(), 0);
  169. try
  170. {
  171. typedef detail::gursoy_shortest< EdgeWeightMap > shortest;
  172. shortest::run(
  173. graph, min_distance_loc, node_distance, update_position, weight);
  174. }
  175. catch (const detail::over_distance_limit&)
  176. {
  177. /* Thrown to break out of BFS or Dijkstra early */
  178. }
  179. }
  180. template < typename VertexListAndIncidenceGraph, typename Topology,
  181. typename PositionMap, typename VertexIndexMap, typename EdgeWeightMap >
  182. void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph,
  183. const Topology& space, PositionMap position, int nsteps,
  184. double diameter_initial, double diameter_final,
  185. double learning_constant_initial, double learning_constant_final,
  186. VertexIndexMap vertex_index_map, EdgeWeightMap weight)
  187. {
  188. #ifndef BOOST_NO_STDC_NAMESPACE
  189. using std::exp;
  190. using std::pow;
  191. #endif
  192. typedef
  193. typename graph_traits< VertexListAndIncidenceGraph >::vertex_iterator
  194. vertex_iterator;
  195. vertex_iterator i, iend;
  196. double diameter_ratio = (double)diameter_final / diameter_initial;
  197. double learning_constant_ratio
  198. = learning_constant_final / learning_constant_initial;
  199. std::vector< double > distance_from_input_vector(num_vertices(graph));
  200. typedef boost::iterator_property_map< std::vector< double >::iterator,
  201. VertexIndexMap, double, double& >
  202. DistanceFromInputMap;
  203. DistanceFromInputMap distance_from_input(
  204. distance_from_input_vector.begin(), vertex_index_map);
  205. std::vector< int > node_distance_map_vector(num_vertices(graph));
  206. typedef boost::iterator_property_map< std::vector< int >::iterator,
  207. VertexIndexMap, double, double& >
  208. NodeDistanceMap;
  209. NodeDistanceMap node_distance(
  210. node_distance_map_vector.begin(), vertex_index_map);
  211. for (int round = 0; round < nsteps; ++round)
  212. {
  213. double part_done = (double)round / (nsteps - 1);
  214. // fprintf(stderr, "%2d%% done\n", int(rint(part_done * 100.)));
  215. int diameter = (int)(diameter_initial * pow(diameter_ratio, part_done));
  216. double learning_constant = learning_constant_initial
  217. * pow(learning_constant_ratio, part_done);
  218. gursoy_atun_step(graph, space, position, diameter, learning_constant,
  219. vertex_index_map, weight);
  220. }
  221. }
  222. template < typename VertexListAndIncidenceGraph, typename Topology,
  223. typename PositionMap, typename VertexIndexMap, typename EdgeWeightMap >
  224. void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  225. const Topology& space, PositionMap position, int nsteps,
  226. double diameter_initial, double diameter_final,
  227. double learning_constant_initial, double learning_constant_final,
  228. VertexIndexMap vertex_index_map, EdgeWeightMap weight)
  229. {
  230. typedef
  231. typename graph_traits< VertexListAndIncidenceGraph >::vertex_iterator
  232. vertex_iterator;
  233. vertex_iterator i, iend;
  234. for (boost::tie(i, iend) = vertices(graph); i != iend; ++i)
  235. {
  236. put(position, *i, space.random_point());
  237. }
  238. gursoy_atun_refine(graph, space, position, nsteps, diameter_initial,
  239. diameter_final, learning_constant_initial, learning_constant_final,
  240. vertex_index_map, weight);
  241. }
  242. template < typename VertexListAndIncidenceGraph, typename Topology,
  243. typename PositionMap, typename VertexIndexMap >
  244. void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  245. const Topology& space, PositionMap position, int nsteps,
  246. double diameter_initial, double diameter_final,
  247. double learning_constant_initial, double learning_constant_final,
  248. VertexIndexMap vertex_index_map)
  249. {
  250. gursoy_atun_layout(graph, space, position, nsteps, diameter_initial,
  251. diameter_final, learning_constant_initial, learning_constant_final,
  252. vertex_index_map, dummy_property_map());
  253. }
  254. template < typename VertexListAndIncidenceGraph, typename Topology,
  255. typename PositionMap >
  256. void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  257. const Topology& space, PositionMap position, int nsteps,
  258. double diameter_initial, double diameter_final = 1.0,
  259. double learning_constant_initial = 0.8,
  260. double learning_constant_final = 0.2)
  261. {
  262. gursoy_atun_layout(graph, space, position, nsteps, diameter_initial,
  263. diameter_final, learning_constant_initial, learning_constant_final,
  264. get(vertex_index, graph));
  265. }
  266. template < typename VertexListAndIncidenceGraph, typename Topology,
  267. typename PositionMap >
  268. void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  269. const Topology& space, PositionMap position, int nsteps)
  270. {
  271. #ifndef BOOST_NO_STDC_NAMESPACE
  272. using std::sqrt;
  273. #endif
  274. gursoy_atun_layout(
  275. graph, space, position, nsteps, sqrt((double)num_vertices(graph)));
  276. }
  277. template < typename VertexListAndIncidenceGraph, typename Topology,
  278. typename PositionMap >
  279. void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  280. const Topology& space, PositionMap position)
  281. {
  282. gursoy_atun_layout(graph, space, position, num_vertices(graph));
  283. }
  284. template < typename VertexListAndIncidenceGraph, typename Topology,
  285. typename PositionMap, typename P, typename T, typename R >
  286. void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  287. const Topology& space, PositionMap position,
  288. const bgl_named_params< P, T, R >& params)
  289. {
  290. #ifndef BOOST_NO_STDC_NAMESPACE
  291. using std::sqrt;
  292. #endif
  293. std::pair< double, double > diam(sqrt(double(num_vertices(graph))), 1.0);
  294. std::pair< double, double > learn(0.8, 0.2);
  295. gursoy_atun_layout(graph, space, position,
  296. choose_param(get_param(params, iterations_t()), num_vertices(graph)),
  297. choose_param(get_param(params, diameter_range_t()), diam).first,
  298. choose_param(get_param(params, diameter_range_t()), diam).second,
  299. choose_param(get_param(params, learning_constant_range_t()), learn)
  300. .first,
  301. choose_param(get_param(params, learning_constant_range_t()), learn)
  302. .second,
  303. choose_const_pmap(get_param(params, vertex_index), graph, vertex_index),
  304. choose_param(get_param(params, edge_weight), dummy_property_map()));
  305. }
  306. } // namespace boost
  307. #endif // BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP