File indexing completed on 2025-01-30 09:43:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP
0011 #define BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP
0012
0013
0014
0015
0016
0017
0018
0019 #include <boost/config/no_tr1/cmath.hpp>
0020 #include <boost/throw_exception.hpp>
0021 #include <boost/assert.hpp>
0022 #include <vector>
0023 #include <exception>
0024 #include <algorithm>
0025
0026 #include <boost/graph/visitors.hpp>
0027 #include <boost/graph/properties.hpp>
0028 #include <boost/random/uniform_01.hpp>
0029 #include <boost/random/linear_congruential.hpp>
0030 #include <boost/shared_ptr.hpp>
0031 #include <boost/graph/breadth_first_search.hpp>
0032 #include <boost/graph/dijkstra_shortest_paths.hpp>
0033 #include <boost/graph/named_function_params.hpp>
0034 #include <boost/graph/topology.hpp>
0035
0036 namespace boost
0037 {
0038
0039 namespace detail
0040 {
0041
0042 struct over_distance_limit : public std::exception
0043 {
0044 };
0045
0046 template < typename PositionMap, typename NodeDistanceMap,
0047 typename Topology, typename Graph >
0048 struct update_position_visitor
0049 {
0050 typedef typename Topology::point_type Point;
0051 PositionMap position_map;
0052 NodeDistanceMap node_distance;
0053 const Topology& space;
0054 Point input_vector;
0055 double distance_limit;
0056 double learning_constant;
0057 double falloff_ratio;
0058
0059 typedef boost::on_examine_vertex event_filter;
0060
0061 typedef
0062 typename graph_traits< Graph >::vertex_descriptor vertex_descriptor;
0063
0064 update_position_visitor(PositionMap position_map,
0065 NodeDistanceMap node_distance, const Topology& space,
0066 const Point& input_vector, double distance_limit,
0067 double learning_constant, double falloff_ratio)
0068 : position_map(position_map)
0069 , node_distance(node_distance)
0070 , space(space)
0071 , input_vector(input_vector)
0072 , distance_limit(distance_limit)
0073 , learning_constant(learning_constant)
0074 , falloff_ratio(falloff_ratio)
0075 {
0076 }
0077
0078 void operator()(vertex_descriptor v, const Graph&) const
0079 {
0080 #ifndef BOOST_NO_STDC_NAMESPACE
0081 using std::pow;
0082 #endif
0083
0084 if (get(node_distance, v) > distance_limit)
0085 BOOST_THROW_EXCEPTION(over_distance_limit());
0086 Point old_position = get(position_map, v);
0087 double distance = get(node_distance, v);
0088 double fraction
0089 = learning_constant * pow(falloff_ratio, distance * distance);
0090 put(position_map, v,
0091 space.move_position_toward(
0092 old_position, fraction, input_vector));
0093 }
0094 };
0095
0096 template < typename EdgeWeightMap > struct gursoy_shortest
0097 {
0098 template < typename Graph, typename NodeDistanceMap,
0099 typename UpdatePosition >
0100 static inline void run(const Graph& g,
0101 typename graph_traits< Graph >::vertex_descriptor s,
0102 NodeDistanceMap node_distance, UpdatePosition& update_position,
0103 EdgeWeightMap weight)
0104 {
0105 boost::dijkstra_shortest_paths(g, s,
0106 weight_map(weight).visitor(boost::make_dijkstra_visitor(
0107 std::make_pair(boost::record_distances(
0108 node_distance, boost::on_edge_relaxed()),
0109 update_position))));
0110 }
0111 };
0112
0113 template <> struct gursoy_shortest< dummy_property_map >
0114 {
0115 template < typename Graph, typename NodeDistanceMap,
0116 typename UpdatePosition >
0117 static inline void run(const Graph& g,
0118 typename graph_traits< Graph >::vertex_descriptor s,
0119 NodeDistanceMap node_distance, UpdatePosition& update_position,
0120 dummy_property_map)
0121 {
0122 boost::breadth_first_search(g, s,
0123 visitor(boost::make_bfs_visitor(
0124 std::make_pair(boost::record_distances(
0125 node_distance, boost::on_tree_edge()),
0126 update_position))));
0127 }
0128 };
0129
0130 }
0131
0132 template < typename VertexListAndIncidenceGraph, typename Topology,
0133 typename PositionMap, typename Diameter, typename VertexIndexMap,
0134 typename EdgeWeightMap >
0135 void gursoy_atun_step(const VertexListAndIncidenceGraph& graph,
0136 const Topology& space, PositionMap position, Diameter diameter,
0137 double learning_constant, VertexIndexMap vertex_index_map,
0138 EdgeWeightMap weight)
0139 {
0140 #ifndef BOOST_NO_STDC_NAMESPACE
0141 using std::exp;
0142 using std::pow;
0143 #endif
0144
0145 typedef
0146 typename graph_traits< VertexListAndIncidenceGraph >::vertex_iterator
0147 vertex_iterator;
0148 typedef
0149 typename graph_traits< VertexListAndIncidenceGraph >::vertex_descriptor
0150 vertex_descriptor;
0151 typedef typename Topology::point_type point_type;
0152 vertex_iterator i, iend;
0153 std::vector< double > distance_from_input_vector(num_vertices(graph));
0154 typedef boost::iterator_property_map< std::vector< double >::iterator,
0155 VertexIndexMap, double, double& >
0156 DistanceFromInputMap;
0157 DistanceFromInputMap distance_from_input(
0158 distance_from_input_vector.begin(), vertex_index_map);
0159 std::vector< double > node_distance_map_vector(num_vertices(graph));
0160 typedef boost::iterator_property_map< std::vector< double >::iterator,
0161 VertexIndexMap, double, double& >
0162 NodeDistanceMap;
0163 NodeDistanceMap node_distance(
0164 node_distance_map_vector.begin(), vertex_index_map);
0165 point_type input_vector = space.random_point();
0166 vertex_descriptor min_distance_loc
0167 = graph_traits< VertexListAndIncidenceGraph >::null_vertex();
0168 double min_distance = 0.0;
0169 bool min_distance_unset = true;
0170 for (boost::tie(i, iend) = vertices(graph); i != iend; ++i)
0171 {
0172 double this_distance = space.distance(get(position, *i), input_vector);
0173 put(distance_from_input, *i, this_distance);
0174 if (min_distance_unset || this_distance < min_distance)
0175 {
0176 min_distance = this_distance;
0177 min_distance_loc = *i;
0178 }
0179 min_distance_unset = false;
0180 }
0181 BOOST_ASSERT(!min_distance_unset);
0182 boost::detail::update_position_visitor< PositionMap, NodeDistanceMap,
0183 Topology, VertexListAndIncidenceGraph >
0184 update_position(position, node_distance, space, input_vector, diameter,
0185 learning_constant, exp(-1. / (2 * diameter * diameter)));
0186 std::fill(
0187 node_distance_map_vector.begin(), node_distance_map_vector.end(), 0);
0188 try
0189 {
0190 typedef detail::gursoy_shortest< EdgeWeightMap > shortest;
0191 shortest::run(
0192 graph, min_distance_loc, node_distance, update_position, weight);
0193 }
0194 catch (const detail::over_distance_limit&)
0195 {
0196
0197 }
0198 }
0199
0200 template < typename VertexListAndIncidenceGraph, typename Topology,
0201 typename PositionMap, typename VertexIndexMap, typename EdgeWeightMap >
0202 void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph,
0203 const Topology& space, PositionMap position, int nsteps,
0204 double diameter_initial, double diameter_final,
0205 double learning_constant_initial, double learning_constant_final,
0206 VertexIndexMap vertex_index_map, EdgeWeightMap weight)
0207 {
0208 #ifndef BOOST_NO_STDC_NAMESPACE
0209 using std::exp;
0210 using std::pow;
0211 #endif
0212
0213 typedef
0214 typename graph_traits< VertexListAndIncidenceGraph >::vertex_iterator
0215 vertex_iterator;
0216 vertex_iterator i, iend;
0217 double diameter_ratio = (double)diameter_final / diameter_initial;
0218 double learning_constant_ratio
0219 = learning_constant_final / learning_constant_initial;
0220 std::vector< double > distance_from_input_vector(num_vertices(graph));
0221 typedef boost::iterator_property_map< std::vector< double >::iterator,
0222 VertexIndexMap, double, double& >
0223 DistanceFromInputMap;
0224 DistanceFromInputMap distance_from_input(
0225 distance_from_input_vector.begin(), vertex_index_map);
0226 std::vector< int > node_distance_map_vector(num_vertices(graph));
0227 typedef boost::iterator_property_map< std::vector< int >::iterator,
0228 VertexIndexMap, double, double& >
0229 NodeDistanceMap;
0230 NodeDistanceMap node_distance(
0231 node_distance_map_vector.begin(), vertex_index_map);
0232 for (int round = 0; round < nsteps; ++round)
0233 {
0234 double part_done = (double)round / (nsteps - 1);
0235
0236 int diameter = (int)(diameter_initial * pow(diameter_ratio, part_done));
0237 double learning_constant = learning_constant_initial
0238 * pow(learning_constant_ratio, part_done);
0239 gursoy_atun_step(graph, space, position, diameter, learning_constant,
0240 vertex_index_map, weight);
0241 }
0242 }
0243
0244 template < typename VertexListAndIncidenceGraph, typename Topology,
0245 typename PositionMap, typename VertexIndexMap, typename EdgeWeightMap >
0246 void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
0247 const Topology& space, PositionMap position, int nsteps,
0248 double diameter_initial, double diameter_final,
0249 double learning_constant_initial, double learning_constant_final,
0250 VertexIndexMap vertex_index_map, EdgeWeightMap weight)
0251 {
0252 typedef
0253 typename graph_traits< VertexListAndIncidenceGraph >::vertex_iterator
0254 vertex_iterator;
0255 vertex_iterator i, iend;
0256 for (boost::tie(i, iend) = vertices(graph); i != iend; ++i)
0257 {
0258 put(position, *i, space.random_point());
0259 }
0260 gursoy_atun_refine(graph, space, position, nsteps, diameter_initial,
0261 diameter_final, learning_constant_initial, learning_constant_final,
0262 vertex_index_map, weight);
0263 }
0264
0265 template < typename VertexListAndIncidenceGraph, typename Topology,
0266 typename PositionMap, typename VertexIndexMap >
0267 void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
0268 const Topology& space, PositionMap position, int nsteps,
0269 double diameter_initial, double diameter_final,
0270 double learning_constant_initial, double learning_constant_final,
0271 VertexIndexMap vertex_index_map)
0272 {
0273 gursoy_atun_layout(graph, space, position, nsteps, diameter_initial,
0274 diameter_final, learning_constant_initial, learning_constant_final,
0275 vertex_index_map, dummy_property_map());
0276 }
0277
0278 template < typename VertexListAndIncidenceGraph, typename Topology,
0279 typename PositionMap >
0280 void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
0281 const Topology& space, PositionMap position, int nsteps,
0282 double diameter_initial, double diameter_final = 1.0,
0283 double learning_constant_initial = 0.8,
0284 double learning_constant_final = 0.2)
0285 {
0286 gursoy_atun_layout(graph, space, position, nsteps, diameter_initial,
0287 diameter_final, learning_constant_initial, learning_constant_final,
0288 get(vertex_index, graph));
0289 }
0290
0291 template < typename VertexListAndIncidenceGraph, typename Topology,
0292 typename PositionMap >
0293 void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
0294 const Topology& space, PositionMap position, int nsteps)
0295 {
0296 #ifndef BOOST_NO_STDC_NAMESPACE
0297 using std::sqrt;
0298 #endif
0299
0300 gursoy_atun_layout(
0301 graph, space, position, nsteps, sqrt((double)num_vertices(graph)));
0302 }
0303
0304 template < typename VertexListAndIncidenceGraph, typename Topology,
0305 typename PositionMap >
0306 void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
0307 const Topology& space, PositionMap position)
0308 {
0309 gursoy_atun_layout(graph, space, position, num_vertices(graph));
0310 }
0311
0312 template < typename VertexListAndIncidenceGraph, typename Topology,
0313 typename PositionMap, typename P, typename T, typename R >
0314 void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,
0315 const Topology& space, PositionMap position,
0316 const bgl_named_params< P, T, R >& params)
0317 {
0318 #ifndef BOOST_NO_STDC_NAMESPACE
0319 using std::sqrt;
0320 #endif
0321
0322 std::pair< double, double > diam(sqrt(double(num_vertices(graph))), 1.0);
0323 std::pair< double, double > learn(0.8, 0.2);
0324 gursoy_atun_layout(graph, space, position,
0325 choose_param(get_param(params, iterations_t()), num_vertices(graph)),
0326 choose_param(get_param(params, diameter_range_t()), diam).first,
0327 choose_param(get_param(params, diameter_range_t()), diam).second,
0328 choose_param(get_param(params, learning_constant_range_t()), learn)
0329 .first,
0330 choose_param(get_param(params, learning_constant_range_t()), learn)
0331 .second,
0332 choose_const_pmap(get_param(params, vertex_index), graph, vertex_index),
0333 choose_param(get_param(params, edge_weight), dummy_property_map()));
0334 }
0335
0336 }
0337
0338 #endif