Chris@16: // Copyright 2004 The Trustees of Indiana University. Chris@16: Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // Authors: Jeremiah Willcock Chris@16: // Douglas Gregor Chris@16: // Andrew Lumsdaine Chris@16: #ifndef BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP Chris@16: #define BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP Chris@16: Chris@16: // Gursoy-Atun graph layout, based on: Chris@16: // "Neighbourhood Preserving Load Balancing: A Self-Organizing Approach" Chris@16: // in EuroPar 2000, p. 234 of LNCS 1900 Chris@16: // http://springerlink.metapress.com/link.asp?id=pcu07ew5rhexp9yt Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: struct over_distance_limit : public std::exception {}; Chris@16: Chris@16: template Chris@16: struct update_position_visitor { Chris@16: typedef typename Topology::point_type Point; Chris@16: PositionMap position_map; Chris@16: NodeDistanceMap node_distance; Chris@16: const Topology& space; Chris@16: Point input_vector; Chris@16: double distance_limit; Chris@16: double learning_constant; Chris@16: double falloff_ratio; Chris@16: Chris@16: typedef boost::on_examine_vertex event_filter; Chris@16: Chris@16: typedef typename graph_traits::vertex_descriptor Chris@16: vertex_descriptor; Chris@16: Chris@16: update_position_visitor(PositionMap position_map, Chris@16: NodeDistanceMap node_distance, Chris@16: const Topology& space, Chris@16: const Point& input_vector, Chris@16: double distance_limit, Chris@16: double learning_constant, Chris@16: double falloff_ratio): Chris@16: position_map(position_map), node_distance(node_distance), Chris@16: space(space), Chris@16: input_vector(input_vector), distance_limit(distance_limit), Chris@16: learning_constant(learning_constant), falloff_ratio(falloff_ratio) {} Chris@16: Chris@16: void operator()(vertex_descriptor v, const Graph&) const Chris@16: { Chris@16: #ifndef BOOST_NO_STDC_NAMESPACE Chris@16: using std::pow; Chris@16: #endif Chris@16: Chris@16: if (get(node_distance, v) > distance_limit) Chris@16: BOOST_THROW_EXCEPTION(over_distance_limit()); Chris@16: Point old_position = get(position_map, v); Chris@16: double distance = get(node_distance, v); Chris@16: double fraction = Chris@16: learning_constant * pow(falloff_ratio, distance * distance); Chris@16: put(position_map, v, Chris@16: space.move_position_toward(old_position, fraction, input_vector)); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct gursoy_shortest Chris@16: { Chris@16: template Chris@16: static inline void Chris@16: run(const Graph& g, typename graph_traits::vertex_descriptor s, Chris@16: NodeDistanceMap node_distance, UpdatePosition& update_position, Chris@16: EdgeWeightMap weight) Chris@16: { Chris@16: boost::dijkstra_shortest_paths(g, s, weight_map(weight). Chris@16: visitor(boost::make_dijkstra_visitor(std::make_pair( Chris@16: boost::record_distances(node_distance, boost::on_edge_relaxed()), Chris@16: update_position)))); Chris@16: } Chris@16: }; Chris@16: Chris@16: template<> Chris@16: struct gursoy_shortest Chris@16: { Chris@16: template Chris@16: static inline void Chris@16: run(const Graph& g, typename graph_traits::vertex_descriptor s, Chris@16: NodeDistanceMap node_distance, UpdatePosition& update_position, Chris@16: dummy_property_map) Chris@16: { Chris@16: boost::breadth_first_search(g, s, Chris@16: visitor(boost::make_bfs_visitor(std::make_pair( Chris@16: boost::record_distances(node_distance, boost::on_tree_edge()), Chris@16: update_position)))); Chris@16: } Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: template Chris@16: void Chris@16: gursoy_atun_step Chris@16: (const VertexListAndIncidenceGraph& graph, Chris@16: const Topology& space, Chris@16: PositionMap position, Chris@16: Diameter diameter, Chris@16: double learning_constant, Chris@16: VertexIndexMap vertex_index_map, Chris@16: EdgeWeightMap weight) Chris@16: { Chris@16: #ifndef BOOST_NO_STDC_NAMESPACE Chris@16: using std::pow; Chris@16: using std::exp; Chris@16: #endif Chris@16: Chris@16: typedef typename graph_traits::vertex_iterator Chris@16: vertex_iterator; Chris@16: typedef typename graph_traits::vertex_descriptor Chris@16: vertex_descriptor; Chris@16: typedef typename Topology::point_type point_type; Chris@16: vertex_iterator i, iend; Chris@16: std::vector distance_from_input_vector(num_vertices(graph)); Chris@16: typedef boost::iterator_property_map::iterator, Chris@16: VertexIndexMap, Chris@16: double, double&> Chris@16: DistanceFromInputMap; Chris@16: DistanceFromInputMap distance_from_input(distance_from_input_vector.begin(), Chris@16: vertex_index_map); Chris@16: std::vector node_distance_map_vector(num_vertices(graph)); Chris@16: typedef boost::iterator_property_map::iterator, Chris@16: VertexIndexMap, Chris@16: double, double&> Chris@16: NodeDistanceMap; Chris@16: NodeDistanceMap node_distance(node_distance_map_vector.begin(), Chris@16: vertex_index_map); Chris@16: point_type input_vector = space.random_point(); Chris@16: vertex_descriptor min_distance_loc Chris@16: = graph_traits::null_vertex(); Chris@16: double min_distance = 0.0; Chris@16: bool min_distance_unset = true; Chris@16: for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) { Chris@16: double this_distance = space.distance(get(position, *i), input_vector); Chris@16: put(distance_from_input, *i, this_distance); Chris@16: if (min_distance_unset || this_distance < min_distance) { Chris@16: min_distance = this_distance; Chris@16: min_distance_loc = *i; Chris@16: } Chris@16: min_distance_unset = false; Chris@16: } Chris@16: BOOST_ASSERT (!min_distance_unset); // Graph must have at least one vertex Chris@16: boost::detail::update_position_visitor< Chris@16: PositionMap, NodeDistanceMap, Topology, Chris@16: VertexListAndIncidenceGraph> Chris@16: update_position(position, node_distance, space, Chris@16: input_vector, diameter, learning_constant, Chris@16: exp(-1. / (2 * diameter * diameter))); Chris@16: std::fill(node_distance_map_vector.begin(), node_distance_map_vector.end(), 0); Chris@16: try { Chris@16: typedef detail::gursoy_shortest shortest; Chris@16: shortest::run(graph, min_distance_loc, node_distance, update_position, Chris@16: weight); Chris@16: } catch (detail::over_distance_limit) { Chris@16: /* Thrown to break out of BFS or Dijkstra early */ Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph, Chris@16: const Topology& space, Chris@16: PositionMap position, Chris@16: int nsteps, Chris@16: double diameter_initial, Chris@16: double diameter_final, Chris@16: double learning_constant_initial, Chris@16: double learning_constant_final, Chris@16: VertexIndexMap vertex_index_map, Chris@16: EdgeWeightMap weight) Chris@16: { Chris@16: #ifndef BOOST_NO_STDC_NAMESPACE Chris@16: using std::pow; Chris@16: using std::exp; Chris@16: #endif Chris@16: Chris@16: typedef typename graph_traits::vertex_iterator Chris@16: vertex_iterator; Chris@16: vertex_iterator i, iend; Chris@16: double diameter_ratio = (double)diameter_final / diameter_initial; Chris@16: double learning_constant_ratio = Chris@16: learning_constant_final / learning_constant_initial; Chris@16: std::vector distance_from_input_vector(num_vertices(graph)); Chris@16: typedef boost::iterator_property_map::iterator, Chris@16: VertexIndexMap, Chris@16: double, double&> Chris@16: DistanceFromInputMap; Chris@16: DistanceFromInputMap distance_from_input(distance_from_input_vector.begin(), Chris@16: vertex_index_map); Chris@16: std::vector node_distance_map_vector(num_vertices(graph)); Chris@16: typedef boost::iterator_property_map::iterator, Chris@16: VertexIndexMap, double, double&> Chris@16: NodeDistanceMap; Chris@16: NodeDistanceMap node_distance(node_distance_map_vector.begin(), Chris@16: vertex_index_map); Chris@16: for (int round = 0; round < nsteps; ++round) { Chris@16: double part_done = (double)round / (nsteps - 1); Chris@16: // fprintf(stderr, "%2d%% done\n", int(rint(part_done * 100.))); Chris@16: int diameter = (int)(diameter_initial * pow(diameter_ratio, part_done)); Chris@16: double learning_constant = Chris@16: learning_constant_initial * pow(learning_constant_ratio, part_done); Chris@16: gursoy_atun_step(graph, space, position, diameter, learning_constant, Chris@16: vertex_index_map, weight); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, Chris@16: const Topology& space, Chris@16: PositionMap position, Chris@16: int nsteps, Chris@16: double diameter_initial, Chris@16: double diameter_final, Chris@16: double learning_constant_initial, Chris@16: double learning_constant_final, Chris@16: VertexIndexMap vertex_index_map, Chris@16: EdgeWeightMap weight) Chris@16: { Chris@16: typedef typename graph_traits::vertex_iterator Chris@16: vertex_iterator; Chris@16: vertex_iterator i, iend; Chris@16: for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) { Chris@16: put(position, *i, space.random_point()); Chris@16: } Chris@16: gursoy_atun_refine(graph, space, Chris@16: position, nsteps, Chris@16: diameter_initial, diameter_final, Chris@16: learning_constant_initial, learning_constant_final, Chris@16: vertex_index_map, weight); Chris@16: } Chris@16: Chris@16: template Chris@16: void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, Chris@16: const Topology& space, Chris@16: PositionMap position, Chris@16: int nsteps, Chris@16: double diameter_initial, Chris@16: double diameter_final, Chris@16: double learning_constant_initial, Chris@16: double learning_constant_final, Chris@16: VertexIndexMap vertex_index_map) Chris@16: { Chris@16: gursoy_atun_layout(graph, space, position, nsteps, Chris@16: diameter_initial, diameter_final, Chris@16: learning_constant_initial, learning_constant_final, Chris@16: vertex_index_map, dummy_property_map()); Chris@16: } Chris@16: Chris@16: template Chris@16: void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, Chris@16: const Topology& space, Chris@16: PositionMap position, Chris@16: int nsteps, Chris@16: double diameter_initial, Chris@16: double diameter_final = 1.0, Chris@16: double learning_constant_initial = 0.8, Chris@16: double learning_constant_final = 0.2) Chris@16: { Chris@16: gursoy_atun_layout(graph, space, position, nsteps, diameter_initial, Chris@16: diameter_final, learning_constant_initial, Chris@16: learning_constant_final, get(vertex_index, graph)); Chris@16: } Chris@16: Chris@16: template Chris@16: void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, Chris@16: const Topology& space, Chris@16: PositionMap position, Chris@16: int nsteps) Chris@16: { Chris@16: #ifndef BOOST_NO_STDC_NAMESPACE Chris@16: using std::sqrt; Chris@16: #endif Chris@16: Chris@16: gursoy_atun_layout(graph, space, position, nsteps, Chris@16: sqrt((double)num_vertices(graph))); Chris@16: } Chris@16: Chris@16: template Chris@16: void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, Chris@16: const Topology& space, Chris@16: PositionMap position) Chris@16: { Chris@16: gursoy_atun_layout(graph, space, position, num_vertices(graph)); Chris@16: } Chris@16: Chris@16: template Chris@16: void Chris@16: gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, Chris@16: const Topology& space, Chris@16: PositionMap position, Chris@16: const bgl_named_params& params) Chris@16: { Chris@16: #ifndef BOOST_NO_STDC_NAMESPACE Chris@16: using std::sqrt; Chris@16: #endif Chris@16: Chris@16: std::pair diam(sqrt(double(num_vertices(graph))), 1.0); Chris@16: std::pair learn(0.8, 0.2); Chris@16: gursoy_atun_layout(graph, space, position, Chris@16: choose_param(get_param(params, iterations_t()), Chris@16: num_vertices(graph)), Chris@16: choose_param(get_param(params, diameter_range_t()), Chris@16: diam).first, Chris@16: choose_param(get_param(params, diameter_range_t()), Chris@16: diam).second, Chris@16: choose_param(get_param(params, learning_constant_range_t()), Chris@16: learn).first, Chris@16: choose_param(get_param(params, learning_constant_range_t()), Chris@16: learn).second, Chris@16: choose_const_pmap(get_param(params, vertex_index), graph, Chris@16: vertex_index), Chris@16: choose_param(get_param(params, edge_weight), Chris@16: dummy_property_map())); Chris@16: } Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP