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