gursoy_atun_layout.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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 – September 1, 2000 Proceedings,
  13. // 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. namespace detail {
  32. struct over_distance_limit : public std::exception {};
  33. template <typename PositionMap, typename NodeDistanceMap, typename Topology,
  34. typename Graph>
  35. struct update_position_visitor {
  36. typedef typename Topology::point_type Point;
  37. PositionMap position_map;
  38. NodeDistanceMap node_distance;
  39. const Topology& space;
  40. Point input_vector;
  41. double distance_limit;
  42. double learning_constant;
  43. double falloff_ratio;
  44. typedef boost::on_examine_vertex event_filter;
  45. typedef typename graph_traits<Graph>::vertex_descriptor
  46. vertex_descriptor;
  47. update_position_visitor(PositionMap position_map,
  48. NodeDistanceMap node_distance,
  49. const Topology& space,
  50. const Point& input_vector,
  51. double distance_limit,
  52. double learning_constant,
  53. double falloff_ratio):
  54. position_map(position_map), node_distance(node_distance),
  55. space(space),
  56. input_vector(input_vector), distance_limit(distance_limit),
  57. learning_constant(learning_constant), falloff_ratio(falloff_ratio) {}
  58. void operator()(vertex_descriptor v, const Graph&) const
  59. {
  60. #ifndef BOOST_NO_STDC_NAMESPACE
  61. using std::pow;
  62. #endif
  63. if (get(node_distance, v) > distance_limit)
  64. BOOST_THROW_EXCEPTION(over_distance_limit());
  65. Point old_position = get(position_map, v);
  66. double distance = get(node_distance, v);
  67. double fraction =
  68. learning_constant * pow(falloff_ratio, distance * distance);
  69. put(position_map, v,
  70. space.move_position_toward(old_position, fraction, input_vector));
  71. }
  72. };
  73. template<typename EdgeWeightMap>
  74. struct gursoy_shortest
  75. {
  76. template<typename Graph, typename NodeDistanceMap, typename UpdatePosition>
  77. static inline void
  78. run(const Graph& g, typename graph_traits<Graph>::vertex_descriptor s,
  79. NodeDistanceMap node_distance, UpdatePosition& update_position,
  80. EdgeWeightMap weight)
  81. {
  82. boost::dijkstra_shortest_paths(g, s, weight_map(weight).
  83. visitor(boost::make_dijkstra_visitor(std::make_pair(
  84. boost::record_distances(node_distance, boost::on_edge_relaxed()),
  85. update_position))));
  86. }
  87. };
  88. template<>
  89. struct gursoy_shortest<dummy_property_map>
  90. {
  91. template<typename Graph, typename NodeDistanceMap, typename UpdatePosition>
  92. static inline void
  93. run(const Graph& g, typename graph_traits<Graph>::vertex_descriptor s,
  94. NodeDistanceMap node_distance, UpdatePosition& update_position,
  95. dummy_property_map)
  96. {
  97. boost::breadth_first_search(g, s,
  98. visitor(boost::make_bfs_visitor(std::make_pair(
  99. boost::record_distances(node_distance, boost::on_tree_edge()),
  100. update_position))));
  101. }
  102. };
  103. } // namespace detail
  104. template <typename VertexListAndIncidenceGraph, typename Topology,
  105. typename PositionMap, typename Diameter, typename VertexIndexMap,
  106. typename EdgeWeightMap>
  107. void
  108. gursoy_atun_step
  109. (const VertexListAndIncidenceGraph& graph,
  110. const Topology& space,
  111. PositionMap position,
  112. Diameter diameter,
  113. double learning_constant,
  114. VertexIndexMap vertex_index_map,
  115. EdgeWeightMap weight)
  116. {
  117. #ifndef BOOST_NO_STDC_NAMESPACE
  118. using std::pow;
  119. using std::exp;
  120. #endif
  121. typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_iterator
  122. vertex_iterator;
  123. typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_descriptor
  124. vertex_descriptor;
  125. typedef typename Topology::point_type point_type;
  126. vertex_iterator i, iend;
  127. std::vector<double> distance_from_input_vector(num_vertices(graph));
  128. typedef boost::iterator_property_map<std::vector<double>::iterator,
  129. VertexIndexMap,
  130. double, double&>
  131. DistanceFromInputMap;
  132. DistanceFromInputMap distance_from_input(distance_from_input_vector.begin(),
  133. vertex_index_map);
  134. std::vector<double> node_distance_map_vector(num_vertices(graph));
  135. typedef boost::iterator_property_map<std::vector<double>::iterator,
  136. VertexIndexMap,
  137. double, double&>
  138. NodeDistanceMap;
  139. NodeDistanceMap node_distance(node_distance_map_vector.begin(),
  140. vertex_index_map);
  141. point_type input_vector = space.random_point();
  142. vertex_descriptor min_distance_loc
  143. = graph_traits<VertexListAndIncidenceGraph>::null_vertex();
  144. double min_distance = 0.0;
  145. bool min_distance_unset = true;
  146. for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) {
  147. double this_distance = space.distance(get(position, *i), input_vector);
  148. put(distance_from_input, *i, this_distance);
  149. if (min_distance_unset || this_distance < min_distance) {
  150. min_distance = this_distance;
  151. min_distance_loc = *i;
  152. }
  153. min_distance_unset = false;
  154. }
  155. BOOST_ASSERT (!min_distance_unset); // Graph must have at least one vertex
  156. boost::detail::update_position_visitor<
  157. PositionMap, NodeDistanceMap, Topology,
  158. VertexListAndIncidenceGraph>
  159. update_position(position, node_distance, space,
  160. input_vector, diameter, learning_constant,
  161. exp(-1. / (2 * diameter * diameter)));
  162. std::fill(node_distance_map_vector.begin(), node_distance_map_vector.end(), 0);
  163. try {
  164. typedef detail::gursoy_shortest<EdgeWeightMap> shortest;
  165. shortest::run(graph, min_distance_loc, node_distance, update_position,
  166. weight);
  167. } catch (const detail::over_distance_limit&) {
  168. /* Thrown to break out of BFS or Dijkstra early */
  169. }
  170. }
  171. template <typename VertexListAndIncidenceGraph, typename Topology,
  172. typename PositionMap, typename VertexIndexMap,
  173. typename EdgeWeightMap>
  174. void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph,
  175. const Topology& space,
  176. PositionMap position,
  177. int nsteps,
  178. double diameter_initial,
  179. double diameter_final,
  180. double learning_constant_initial,
  181. double learning_constant_final,
  182. VertexIndexMap vertex_index_map,
  183. EdgeWeightMap weight)
  184. {
  185. #ifndef BOOST_NO_STDC_NAMESPACE
  186. using std::pow;
  187. using std::exp;
  188. #endif
  189. typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_iterator
  190. vertex_iterator;
  191. vertex_iterator i, iend;
  192. double diameter_ratio = (double)diameter_final / diameter_initial;
  193. double learning_constant_ratio =
  194. learning_constant_final / learning_constant_initial;
  195. std::vector<double> distance_from_input_vector(num_vertices(graph));
  196. typedef boost::iterator_property_map<std::vector<double>::iterator,
  197. VertexIndexMap,
  198. double, double&>
  199. DistanceFromInputMap;
  200. DistanceFromInputMap distance_from_input(distance_from_input_vector.begin(),
  201. vertex_index_map);
  202. std::vector<int> node_distance_map_vector(num_vertices(graph));
  203. typedef boost::iterator_property_map<std::vector<int>::iterator,
  204. VertexIndexMap, double, double&>
  205. NodeDistanceMap;
  206. NodeDistanceMap node_distance(node_distance_map_vector.begin(),
  207. vertex_index_map);
  208. for (int round = 0; round < nsteps; ++round) {
  209. double part_done = (double)round / (nsteps - 1);
  210. // fprintf(stderr, "%2d%% done\n", int(rint(part_done * 100.)));
  211. int diameter = (int)(diameter_initial * pow(diameter_ratio, part_done));
  212. double learning_constant =
  213. learning_constant_initial * pow(learning_constant_ratio, part_done);
  214. gursoy_atun_step(graph, space, position, diameter, learning_constant,
  215. vertex_index_map, weight);
  216. }
  217. }
  218. template <typename VertexListAndIncidenceGraph, typename Topology,
  219. typename PositionMap, typename VertexIndexMap,
  220. typename EdgeWeightMap>
  221. void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  222. const Topology& space,
  223. PositionMap position,
  224. int nsteps,
  225. double diameter_initial,
  226. double diameter_final,
  227. double learning_constant_initial,
  228. double learning_constant_final,
  229. VertexIndexMap vertex_index_map,
  230. EdgeWeightMap weight)
  231. {
  232. typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_iterator
  233. vertex_iterator;
  234. vertex_iterator i, iend;
  235. for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) {
  236. put(position, *i, space.random_point());
  237. }
  238. gursoy_atun_refine(graph, space,
  239. position, nsteps,
  240. diameter_initial, diameter_final,
  241. learning_constant_initial, learning_constant_final,
  242. vertex_index_map, weight);
  243. }
  244. template <typename VertexListAndIncidenceGraph, typename Topology,
  245. typename PositionMap, typename VertexIndexMap>
  246. void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  247. const Topology& space,
  248. PositionMap position,
  249. int nsteps,
  250. double diameter_initial,
  251. double diameter_final,
  252. double learning_constant_initial,
  253. double learning_constant_final,
  254. VertexIndexMap vertex_index_map)
  255. {
  256. gursoy_atun_layout(graph, space, position, nsteps,
  257. diameter_initial, diameter_final,
  258. learning_constant_initial, learning_constant_final,
  259. vertex_index_map, dummy_property_map());
  260. }
  261. template <typename VertexListAndIncidenceGraph, typename Topology,
  262. typename PositionMap>
  263. void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  264. const Topology& space,
  265. PositionMap position,
  266. int nsteps,
  267. double diameter_initial,
  268. double diameter_final = 1.0,
  269. double learning_constant_initial = 0.8,
  270. double learning_constant_final = 0.2)
  271. {
  272. gursoy_atun_layout(graph, space, position, nsteps, diameter_initial,
  273. diameter_final, learning_constant_initial,
  274. learning_constant_final, get(vertex_index, graph));
  275. }
  276. template <typename VertexListAndIncidenceGraph, typename Topology,
  277. typename PositionMap>
  278. void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  279. const Topology& space,
  280. PositionMap position,
  281. int nsteps)
  282. {
  283. #ifndef BOOST_NO_STDC_NAMESPACE
  284. using std::sqrt;
  285. #endif
  286. gursoy_atun_layout(graph, space, position, nsteps,
  287. sqrt((double)num_vertices(graph)));
  288. }
  289. template <typename VertexListAndIncidenceGraph, typename Topology,
  290. typename PositionMap>
  291. void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  292. const Topology& space,
  293. PositionMap position)
  294. {
  295. gursoy_atun_layout(graph, space, position, num_vertices(graph));
  296. }
  297. template<typename VertexListAndIncidenceGraph, typename Topology,
  298. typename PositionMap, typename P, typename T, typename R>
  299. void
  300. gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
  301. const Topology& space,
  302. PositionMap position,
  303. const bgl_named_params<P,T,R>& params)
  304. {
  305. #ifndef BOOST_NO_STDC_NAMESPACE
  306. using std::sqrt;
  307. #endif
  308. std::pair<double, double> diam(sqrt(double(num_vertices(graph))), 1.0);
  309. std::pair<double, double> learn(0.8, 0.2);
  310. gursoy_atun_layout(graph, space, position,
  311. choose_param(get_param(params, iterations_t()),
  312. num_vertices(graph)),
  313. choose_param(get_param(params, diameter_range_t()),
  314. diam).first,
  315. choose_param(get_param(params, diameter_range_t()),
  316. diam).second,
  317. choose_param(get_param(params, learning_constant_range_t()),
  318. learn).first,
  319. choose_param(get_param(params, learning_constant_range_t()),
  320. learn).second,
  321. choose_const_pmap(get_param(params, vertex_index), graph,
  322. vertex_index),
  323. choose_param(get_param(params, edge_weight),
  324. dummy_property_map()));
  325. }
  326. } // namespace boost
  327. #endif // BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP