epoc32/include/stdapis/boost/graph/gursoy_atun_layout.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
williamr@2
     1
// Copyright 2004 The Trustees of Indiana University.
williamr@2
     2
williamr@2
     3
// Distributed under the Boost Software License, Version 1.0.
williamr@2
     4
// (See accompanying file LICENSE_1_0.txt or copy at
williamr@2
     5
// http://www.boost.org/LICENSE_1_0.txt)
williamr@2
     6
williamr@2
     7
//  Authors: Jeremiah Willcock
williamr@2
     8
//           Douglas Gregor
williamr@2
     9
//           Andrew Lumsdaine
williamr@2
    10
#ifndef BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP
williamr@2
    11
#define BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP
williamr@2
    12
williamr@2
    13
// Gursoy-Atun graph layout, based on:
williamr@2
    14
// "Neighbourhood Preserving Load Balancing: A Self-Organizing Approach"
williamr@2
    15
// in EuroPar 2000, p. 234 of LNCS 1900
williamr@2
    16
// http://springerlink.metapress.com/link.asp?id=pcu07ew5rhexp9yt
williamr@2
    17
williamr@2
    18
#include <cmath>
williamr@2
    19
#include <vector>
williamr@2
    20
#include <exception>
williamr@2
    21
#include <algorithm>
williamr@2
    22
williamr@2
    23
#include <boost/graph/visitors.hpp>
williamr@2
    24
#include <boost/graph/properties.hpp>
williamr@2
    25
#include <boost/random/uniform_01.hpp>
williamr@2
    26
#include <boost/random/linear_congruential.hpp>
williamr@2
    27
#include <boost/shared_ptr.hpp>
williamr@2
    28
#include <boost/graph/breadth_first_search.hpp>
williamr@2
    29
#include <boost/graph/dijkstra_shortest_paths.hpp>
williamr@2
    30
#include <boost/graph/named_function_params.hpp>
williamr@2
    31
williamr@2
    32
namespace boost { 
williamr@2
    33
williamr@2
    34
namespace detail {
williamr@2
    35
williamr@2
    36
struct over_distance_limit : public std::exception {};
williamr@2
    37
williamr@2
    38
template <typename PositionMap, typename NodeDistanceMap,  typename Topology,
williamr@2
    39
          typename Graph>
williamr@2
    40
struct update_position_visitor {
williamr@2
    41
  typedef typename Topology::point_type Point;
williamr@2
    42
  PositionMap position_map;
williamr@2
    43
  NodeDistanceMap node_distance;
williamr@2
    44
  const Topology& space;
williamr@2
    45
  Point input_vector;
williamr@2
    46
  double distance_limit;
williamr@2
    47
  double learning_constant;
williamr@2
    48
  double falloff_ratio;
williamr@2
    49
williamr@2
    50
  typedef boost::on_examine_vertex event_filter;
williamr@2
    51
williamr@2
    52
  typedef typename graph_traits<Graph>::vertex_descriptor
williamr@2
    53
    vertex_descriptor;
williamr@2
    54
williamr@2
    55
  update_position_visitor(PositionMap position_map,
williamr@2
    56
                          NodeDistanceMap node_distance,
williamr@2
    57
                          const Topology& space,
williamr@2
    58
                          const Point& input_vector,
williamr@2
    59
                          double distance_limit,
williamr@2
    60
                          double learning_constant,
williamr@2
    61
                          double falloff_ratio):
williamr@2
    62
    position_map(position_map), node_distance(node_distance), 
williamr@2
    63
    space(space),
williamr@2
    64
    input_vector(input_vector), distance_limit(distance_limit),
williamr@2
    65
    learning_constant(learning_constant), falloff_ratio(falloff_ratio) {}
williamr@2
    66
williamr@2
    67
  void operator()(vertex_descriptor v, const Graph&) const 
williamr@2
    68
  {
williamr@2
    69
#ifndef BOOST_NO_STDC_NAMESPACE
williamr@2
    70
    using std::pow;
williamr@2
    71
#endif
williamr@2
    72
williamr@2
    73
    if (get(node_distance, v) > distance_limit)
williamr@2
    74
      throw over_distance_limit();
williamr@2
    75
    Point old_position = get(position_map, v);
williamr@2
    76
    double distance = get(node_distance, v);
williamr@2
    77
    double fraction = 
williamr@2
    78
      learning_constant * pow(falloff_ratio, distance * distance);
williamr@2
    79
    put(position_map, v,
williamr@2
    80
        space.move_position_toward(old_position, fraction, input_vector));
williamr@2
    81
  }
williamr@2
    82
};
williamr@2
    83
williamr@2
    84
template<typename EdgeWeightMap>
williamr@2
    85
struct gursoy_shortest
williamr@2
    86
{
williamr@2
    87
  template<typename Graph, typename NodeDistanceMap, typename UpdatePosition>
williamr@2
    88
  static inline void 
williamr@2
    89
  run(const Graph& g, typename graph_traits<Graph>::vertex_descriptor s,
williamr@2
    90
      NodeDistanceMap node_distance,  UpdatePosition& update_position,
williamr@2
    91
      EdgeWeightMap weight)
williamr@2
    92
  {
williamr@2
    93
    boost::dijkstra_shortest_paths(g, s, weight_map(weight).
williamr@2
    94
      visitor(boost::make_dijkstra_visitor(std::make_pair(
williamr@2
    95
       boost::record_distances(node_distance, boost::on_edge_relaxed()),
williamr@2
    96
        update_position))));
williamr@2
    97
  }
williamr@2
    98
};
williamr@2
    99
williamr@2
   100
template<>
williamr@2
   101
struct gursoy_shortest<dummy_property_map>
williamr@2
   102
{
williamr@2
   103
  template<typename Graph, typename NodeDistanceMap, typename UpdatePosition>
williamr@2
   104
  static inline void 
williamr@2
   105
  run(const Graph& g, typename graph_traits<Graph>::vertex_descriptor s,
williamr@2
   106
      NodeDistanceMap node_distance,  UpdatePosition& update_position,
williamr@2
   107
      dummy_property_map)
williamr@2
   108
  {
williamr@2
   109
    boost::breadth_first_search(g, s,
williamr@2
   110
      visitor(boost::make_bfs_visitor(std::make_pair(
williamr@2
   111
        boost::record_distances(node_distance, boost::on_tree_edge()),
williamr@2
   112
        update_position))));
williamr@2
   113
  }
williamr@2
   114
};
williamr@2
   115
williamr@2
   116
} // namespace detail
williamr@2
   117
williamr@2
   118
template <typename VertexListAndIncidenceGraph,  typename Topology,
williamr@2
   119
          typename PositionMap, typename Diameter, typename VertexIndexMap, 
williamr@2
   120
          typename EdgeWeightMap>
williamr@2
   121
void 
williamr@2
   122
gursoy_atun_step
williamr@2
   123
  (const VertexListAndIncidenceGraph& graph,  
williamr@2
   124
   const Topology& space,
williamr@2
   125
   PositionMap position,
williamr@2
   126
   Diameter diameter,
williamr@2
   127
   double learning_constant,
williamr@2
   128
   VertexIndexMap vertex_index_map,
williamr@2
   129
   EdgeWeightMap weight)
williamr@2
   130
{
williamr@2
   131
#ifndef BOOST_NO_STDC_NAMESPACE
williamr@2
   132
  using std::pow;
williamr@2
   133
  using std::exp;
williamr@2
   134
#endif
williamr@2
   135
williamr@2
   136
  typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_iterator
williamr@2
   137
    vertex_iterator;
williamr@2
   138
  typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_descriptor
williamr@2
   139
    vertex_descriptor;
williamr@2
   140
  typedef typename Topology::point_type point_type;
williamr@2
   141
  vertex_iterator i, iend;
williamr@2
   142
  std::vector<double> distance_from_input_vector(num_vertices(graph));
williamr@2
   143
  typedef boost::iterator_property_map<std::vector<double>::iterator, 
williamr@2
   144
                                       VertexIndexMap,
williamr@2
   145
                                       double, double&>
williamr@2
   146
    DistanceFromInputMap;
williamr@2
   147
  DistanceFromInputMap distance_from_input(distance_from_input_vector.begin(),
williamr@2
   148
                                           vertex_index_map);
williamr@2
   149
  std::vector<double> node_distance_map_vector(num_vertices(graph));
williamr@2
   150
  typedef boost::iterator_property_map<std::vector<double>::iterator, 
williamr@2
   151
                                       VertexIndexMap,
williamr@2
   152
                                       double, double&>
williamr@2
   153
    NodeDistanceMap;
williamr@2
   154
  NodeDistanceMap node_distance(node_distance_map_vector.begin(),
williamr@2
   155
                                vertex_index_map);
williamr@2
   156
  point_type input_vector = space.random_point();
williamr@2
   157
  vertex_descriptor min_distance_loc 
williamr@2
   158
    = graph_traits<VertexListAndIncidenceGraph>::null_vertex();
williamr@2
   159
  double min_distance = 0.0;
williamr@2
   160
  bool min_distance_unset = true;
williamr@2
   161
  for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) {
williamr@2
   162
    double this_distance = space.distance(get(position, *i), input_vector);
williamr@2
   163
    put(distance_from_input, *i, this_distance);
williamr@2
   164
    if (min_distance_unset || this_distance < min_distance) {
williamr@2
   165
      min_distance = this_distance;
williamr@2
   166
      min_distance_loc = *i;
williamr@2
   167
    }
williamr@2
   168
    min_distance_unset = false;
williamr@2
   169
  }
williamr@2
   170
  assert (!min_distance_unset); // Graph must have at least one vertex
williamr@2
   171
  boost::detail::update_position_visitor<
williamr@2
   172
      PositionMap, NodeDistanceMap, Topology,
williamr@2
   173
      VertexListAndIncidenceGraph> 
williamr@2
   174
    update_position(position, node_distance, space,
williamr@2
   175
                    input_vector, diameter, learning_constant, 
williamr@2
   176
                    exp(-1. / (2 * diameter * diameter)));
williamr@2
   177
  std::fill(node_distance_map_vector.begin(), node_distance_map_vector.end(), 0);
williamr@2
   178
  try {
williamr@2
   179
    typedef detail::gursoy_shortest<EdgeWeightMap> shortest;
williamr@2
   180
    shortest::run(graph, min_distance_loc, node_distance, update_position,
williamr@2
   181
                  weight);    
williamr@2
   182
  } catch (detail::over_distance_limit) { 
williamr@2
   183
    /* Thrown to break out of BFS or Dijkstra early */ 
williamr@2
   184
  }
williamr@2
   185
}
williamr@2
   186
williamr@2
   187
template <typename VertexListAndIncidenceGraph,  typename Topology,
williamr@2
   188
          typename PositionMap, typename VertexIndexMap, 
williamr@2
   189
          typename EdgeWeightMap>
williamr@2
   190
void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph,  
williamr@2
   191
                        const Topology& space,
williamr@2
   192
                        PositionMap position,
williamr@2
   193
                        int nsteps,
williamr@2
   194
                        double diameter_initial,
williamr@2
   195
                        double diameter_final,
williamr@2
   196
                        double learning_constant_initial,
williamr@2
   197
                        double learning_constant_final,
williamr@2
   198
                        VertexIndexMap vertex_index_map,
williamr@2
   199
                        EdgeWeightMap weight) 
williamr@2
   200
{
williamr@2
   201
#ifndef BOOST_NO_STDC_NAMESPACE
williamr@2
   202
  using std::pow;
williamr@2
   203
  using std::exp;
williamr@2
   204
#endif
williamr@2
   205
williamr@2
   206
  typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_iterator
williamr@2
   207
    vertex_iterator;
williamr@2
   208
  typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_descriptor
williamr@2
   209
    vertex_descriptor;
williamr@2
   210
  typedef typename Topology::point_type point_type;
williamr@2
   211
  vertex_iterator i, iend;
williamr@2
   212
  double diameter_ratio = (double)diameter_final / diameter_initial;
williamr@2
   213
  double learning_constant_ratio = 
williamr@2
   214
    learning_constant_final / learning_constant_initial;
williamr@2
   215
  std::vector<double> distance_from_input_vector(num_vertices(graph));
williamr@2
   216
  typedef boost::iterator_property_map<std::vector<double>::iterator, 
williamr@2
   217
                                       VertexIndexMap,
williamr@2
   218
                                       double, double&>
williamr@2
   219
    DistanceFromInputMap;
williamr@2
   220
  DistanceFromInputMap distance_from_input(distance_from_input_vector.begin(),
williamr@2
   221
                                           vertex_index_map);
williamr@2
   222
  std::vector<int> node_distance_map_vector(num_vertices(graph));
williamr@2
   223
  typedef boost::iterator_property_map<std::vector<int>::iterator, 
williamr@2
   224
                                       VertexIndexMap, double, double&>
williamr@2
   225
    NodeDistanceMap;
williamr@2
   226
  NodeDistanceMap node_distance(node_distance_map_vector.begin(),
williamr@2
   227
                                vertex_index_map);
williamr@2
   228
  for (int round = 0; round < nsteps; ++round) {
williamr@2
   229
    double part_done = (double)round / (nsteps - 1);
williamr@2
   230
    int diameter = (int)(diameter_initial * pow(diameter_ratio, part_done));
williamr@2
   231
    double learning_constant = 
williamr@2
   232
      learning_constant_initial * pow(learning_constant_ratio, part_done);
williamr@2
   233
    gursoy_atun_step(graph, space, position, diameter, learning_constant, 
williamr@2
   234
                     vertex_index_map, weight);
williamr@2
   235
  }
williamr@2
   236
}
williamr@2
   237
williamr@2
   238
template <typename VertexListAndIncidenceGraph,  typename Topology,
williamr@2
   239
          typename PositionMap, typename VertexIndexMap, 
williamr@2
   240
          typename EdgeWeightMap>
williamr@2
   241
void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,  
williamr@2
   242
                        const Topology& space,
williamr@2
   243
                        PositionMap position,
williamr@2
   244
                        int nsteps,
williamr@2
   245
                        double diameter_initial,
williamr@2
   246
                        double diameter_final,
williamr@2
   247
                        double learning_constant_initial,
williamr@2
   248
                        double learning_constant_final,
williamr@2
   249
                        VertexIndexMap vertex_index_map,
williamr@2
   250
                        EdgeWeightMap weight)
williamr@2
   251
{
williamr@2
   252
  typedef typename graph_traits<VertexListAndIncidenceGraph>::vertex_iterator
williamr@2
   253
    vertex_iterator;
williamr@2
   254
  vertex_iterator i, iend;
williamr@2
   255
  for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) {
williamr@2
   256
    put(position, *i, space.random_point());
williamr@2
   257
  }
williamr@2
   258
  gursoy_atun_refine(graph, space,
williamr@2
   259
                     position, nsteps,
williamr@2
   260
                     diameter_initial, diameter_final, 
williamr@2
   261
                     learning_constant_initial, learning_constant_final,
williamr@2
   262
                     vertex_index_map, weight);
williamr@2
   263
}
williamr@2
   264
williamr@2
   265
template <typename VertexListAndIncidenceGraph,  typename Topology,
williamr@2
   266
          typename PositionMap, typename VertexIndexMap>
williamr@2
   267
void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,  
williamr@2
   268
                        const Topology& space,
williamr@2
   269
                        PositionMap position,
williamr@2
   270
                        int nsteps,
williamr@2
   271
                        double diameter_initial,
williamr@2
   272
                        double diameter_final,
williamr@2
   273
                        double learning_constant_initial,
williamr@2
   274
                        double learning_constant_final,
williamr@2
   275
                        VertexIndexMap vertex_index_map)
williamr@2
   276
{
williamr@2
   277
  gursoy_atun_layout(graph, space, position, nsteps, 
williamr@2
   278
                     diameter_initial, diameter_final, 
williamr@2
   279
                     learning_constant_initial, learning_constant_final, 
williamr@2
   280
                     vertex_index_map, dummy_property_map());
williamr@2
   281
}
williamr@2
   282
williamr@2
   283
template <typename VertexListAndIncidenceGraph, typename Topology,
williamr@2
   284
          typename PositionMap>
williamr@2
   285
void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,  
williamr@2
   286
                        const Topology& space,
williamr@2
   287
                        PositionMap position,
williamr@2
   288
                        int nsteps,
williamr@2
   289
                        double diameter_initial,
williamr@2
   290
                        double diameter_final = 1.0,
williamr@2
   291
                        double learning_constant_initial = 0.8,
williamr@2
   292
                        double learning_constant_final = 0.2)
williamr@2
   293
{ 
williamr@2
   294
  gursoy_atun_layout(graph, space, position, nsteps, diameter_initial,
williamr@2
   295
                     diameter_final, learning_constant_initial,
williamr@2
   296
                     learning_constant_final, get(vertex_index, graph)); 
williamr@2
   297
}
williamr@2
   298
williamr@2
   299
template <typename VertexListAndIncidenceGraph, typename Topology,
williamr@2
   300
          typename PositionMap>
williamr@2
   301
void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,  
williamr@2
   302
                        const Topology& space,
williamr@2
   303
                        PositionMap position,
williamr@2
   304
                        int nsteps)
williamr@2
   305
{
williamr@2
   306
#ifndef BOOST_NO_STDC_NAMESPACE
williamr@2
   307
  using std::sqrt;
williamr@2
   308
#endif
williamr@2
   309
williamr@2
   310
  gursoy_atun_layout(graph, space, position, nsteps, 
williamr@2
   311
                     sqrt((double)num_vertices(graph)));
williamr@2
   312
}
williamr@2
   313
williamr@2
   314
template <typename VertexListAndIncidenceGraph, typename Topology,
williamr@2
   315
          typename PositionMap>
williamr@2
   316
void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,  
williamr@2
   317
                        const Topology& space,
williamr@2
   318
                        PositionMap position)
williamr@2
   319
{
williamr@2
   320
  gursoy_atun_layout(graph, space, position, num_vertices(graph));
williamr@2
   321
}
williamr@2
   322
williamr@2
   323
template<typename VertexListAndIncidenceGraph, typename Topology,
williamr@2
   324
         typename PositionMap, typename P, typename T, typename R>
williamr@2
   325
void 
williamr@2
   326
gursoy_atun_layout(const VertexListAndIncidenceGraph& graph,  
williamr@2
   327
                   const Topology& space,
williamr@2
   328
                   PositionMap position,
williamr@2
   329
                   const bgl_named_params<P,T,R>& params)
williamr@2
   330
{
williamr@2
   331
#ifndef BOOST_NO_STDC_NAMESPACE
williamr@2
   332
  using std::sqrt;
williamr@2
   333
#endif
williamr@2
   334
williamr@2
   335
  std::pair<double, double> diam(sqrt(double(num_vertices(graph))), 1.0);
williamr@2
   336
  std::pair<double, double> learn(0.8, 0.2);
williamr@2
   337
  gursoy_atun_layout(graph, space, position,
williamr@2
   338
                     choose_param(get_param(params, iterations_t()),
williamr@2
   339
                                  num_vertices(graph)),
williamr@2
   340
                     choose_param(get_param(params, diameter_range_t()), 
williamr@2
   341
                                  diam).first,
williamr@2
   342
                     choose_param(get_param(params, diameter_range_t()), 
williamr@2
   343
                                  diam).second,
williamr@2
   344
                     choose_param(get_param(params, learning_constant_range_t()), 
williamr@2
   345
                                  learn).first,
williamr@2
   346
                     choose_param(get_param(params, learning_constant_range_t()), 
williamr@2
   347
                                  learn).second,
williamr@2
   348
                     choose_const_pmap(get_param(params, vertex_index), graph,
williamr@2
   349
                                       vertex_index),
williamr@2
   350
                     choose_param(get_param(params, edge_weight), 
williamr@2
   351
                                  dummy_property_map()));
williamr@2
   352
}
williamr@2
   353
williamr@2
   354
/***********************************************************
williamr@2
   355
 * Topologies                                              *
williamr@2
   356
 ***********************************************************/
williamr@2
   357
template<std::size_t Dims>
williamr@2
   358
class convex_topology 
williamr@2
   359
{
williamr@2
   360
  struct point 
williamr@2
   361
  {
williamr@2
   362
    point() { }
williamr@2
   363
    double& operator[](std::size_t i) {return values[i];}
williamr@2
   364
    const double& operator[](std::size_t i) const {return values[i];}
williamr@2
   365
williamr@2
   366
  private:
williamr@2
   367
    double values[Dims];
williamr@2
   368
  };
williamr@2
   369
williamr@2
   370
 public:
williamr@2
   371
  typedef point point_type;
williamr@2
   372
williamr@2
   373
  double distance(point a, point b) const 
williamr@2
   374
  {
williamr@2
   375
    double dist = 0;
williamr@2
   376
    for (std::size_t i = 0; i < Dims; ++i) {
williamr@2
   377
      double diff = b[i] - a[i];
williamr@2
   378
      dist += diff * diff;
williamr@2
   379
    }
williamr@2
   380
    // Exact properties of the distance are not important, as long as
williamr@2
   381
    // < on what this returns matches real distances
williamr@2
   382
    return dist;
williamr@2
   383
  }
williamr@2
   384
williamr@2
   385
  point move_position_toward(point a, double fraction, point b) const 
williamr@2
   386
  {
williamr@2
   387
    point result;
williamr@2
   388
    for (std::size_t i = 0; i < Dims; ++i)
williamr@2
   389
      result[i] = a[i] + (b[i] - a[i]) * fraction;
williamr@2
   390
    return result;
williamr@2
   391
  }
williamr@2
   392
};
williamr@2
   393
williamr@2
   394
template<std::size_t Dims,
williamr@2
   395
         typename RandomNumberGenerator = minstd_rand>
williamr@2
   396
class hypercube_topology : public convex_topology<Dims>
williamr@2
   397
{
williamr@2
   398
  typedef uniform_01<RandomNumberGenerator, double> rand_t;
williamr@2
   399
williamr@2
   400
 public:
williamr@2
   401
  typedef typename convex_topology<Dims>::point_type point_type;
williamr@2
   402
williamr@2
   403
  explicit hypercube_topology(double scaling = 1.0) 
williamr@2
   404
    : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)), 
williamr@2
   405
      scaling(scaling) 
williamr@2
   406
  { }
williamr@2
   407
williamr@2
   408
  hypercube_topology(RandomNumberGenerator& gen, double scaling = 1.0) 
williamr@2
   409
    : gen_ptr(), rand(new rand_t(gen)), scaling(scaling) { }
williamr@2
   410
                     
williamr@2
   411
  point_type random_point() const 
williamr@2
   412
  {
williamr@2
   413
    point_type p;
williamr@2
   414
    for (std::size_t i = 0; i < Dims; ++i)
williamr@2
   415
      p[i] = (*rand)() * scaling;
williamr@2
   416
    return p;
williamr@2
   417
  }
williamr@2
   418
williamr@2
   419
 private:
williamr@2
   420
  shared_ptr<RandomNumberGenerator> gen_ptr;
williamr@2
   421
  shared_ptr<rand_t> rand;
williamr@2
   422
  double scaling;
williamr@2
   423
};
williamr@2
   424
williamr@2
   425
template<typename RandomNumberGenerator = minstd_rand>
williamr@2
   426
class square_topology : public hypercube_topology<2, RandomNumberGenerator>
williamr@2
   427
{
williamr@2
   428
  typedef hypercube_topology<2, RandomNumberGenerator> inherited;
williamr@2
   429
williamr@2
   430
 public:
williamr@2
   431
  explicit square_topology(double scaling = 1.0) : inherited(scaling) { }
williamr@2
   432
  
williamr@2
   433
  square_topology(RandomNumberGenerator& gen, double scaling = 1.0) 
williamr@2
   434
    : inherited(gen, scaling) { }
williamr@2
   435
};
williamr@2
   436
williamr@2
   437
template<typename RandomNumberGenerator = minstd_rand>
williamr@2
   438
class cube_topology : public hypercube_topology<3, RandomNumberGenerator>
williamr@2
   439
{
williamr@2
   440
  typedef hypercube_topology<3, RandomNumberGenerator> inherited;
williamr@2
   441
williamr@2
   442
 public:
williamr@2
   443
  explicit cube_topology(double scaling = 1.0) : inherited(scaling) { }
williamr@2
   444
  
williamr@2
   445
  cube_topology(RandomNumberGenerator& gen, double scaling = 1.0) 
williamr@2
   446
    : inherited(gen, scaling) { }
williamr@2
   447
};
williamr@2
   448
williamr@2
   449
template<std::size_t Dims,
williamr@2
   450
         typename RandomNumberGenerator = minstd_rand>
williamr@2
   451
class ball_topology : public convex_topology<Dims>
williamr@2
   452
{
williamr@2
   453
  typedef uniform_01<RandomNumberGenerator, double> rand_t;
williamr@2
   454
williamr@2
   455
 public:
williamr@2
   456
  typedef typename convex_topology<Dims>::point_type point_type;
williamr@2
   457
williamr@2
   458
  explicit ball_topology(double radius = 1.0) 
williamr@2
   459
    : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)), 
williamr@2
   460
      radius(radius) 
williamr@2
   461
  { }
williamr@2
   462
williamr@2
   463
  ball_topology(RandomNumberGenerator& gen, double radius = 1.0) 
williamr@2
   464
    : gen_ptr(), rand(new rand_t(gen)), radius(radius) { }
williamr@2
   465
                     
williamr@2
   466
  point_type random_point() const 
williamr@2
   467
  {
williamr@2
   468
    point_type p;
williamr@2
   469
    double dist_sum;
williamr@2
   470
    do {
williamr@2
   471
      dist_sum = 0.0;
williamr@2
   472
      for (std::size_t i = 0; i < Dims; ++i) {
williamr@2
   473
        double x = (*rand)() * 2*radius - radius;
williamr@2
   474
        p[i] = x;
williamr@2
   475
        dist_sum += x * x;
williamr@2
   476
      }
williamr@2
   477
    } while (dist_sum > radius*radius);
williamr@2
   478
    return p;
williamr@2
   479
  }
williamr@2
   480
williamr@2
   481
 private:
williamr@2
   482
  shared_ptr<RandomNumberGenerator> gen_ptr;
williamr@2
   483
  shared_ptr<rand_t> rand;
williamr@2
   484
  double radius;
williamr@2
   485
};
williamr@2
   486
williamr@2
   487
template<typename RandomNumberGenerator = minstd_rand>
williamr@2
   488
class circle_topology : public ball_topology<2, RandomNumberGenerator>
williamr@2
   489
{
williamr@2
   490
  typedef ball_topology<2, RandomNumberGenerator> inherited;
williamr@2
   491
williamr@2
   492
 public:
williamr@2
   493
  explicit circle_topology(double radius = 1.0) : inherited(radius) { }
williamr@2
   494
  
williamr@2
   495
  circle_topology(RandomNumberGenerator& gen, double radius = 1.0) 
williamr@2
   496
    : inherited(gen, radius) { }
williamr@2
   497
};
williamr@2
   498
williamr@2
   499
template<typename RandomNumberGenerator = minstd_rand>
williamr@2
   500
class sphere_topology : public ball_topology<3, RandomNumberGenerator>
williamr@2
   501
{
williamr@2
   502
  typedef ball_topology<3, RandomNumberGenerator> inherited;
williamr@2
   503
williamr@2
   504
 public:
williamr@2
   505
  explicit sphere_topology(double radius = 1.0) : inherited(radius) { }
williamr@2
   506
  
williamr@2
   507
  sphere_topology(RandomNumberGenerator& gen, double radius = 1.0) 
williamr@2
   508
    : inherited(gen, radius) { }
williamr@2
   509
};
williamr@2
   510
williamr@2
   511
template<typename RandomNumberGenerator = minstd_rand>
williamr@2
   512
class heart_topology 
williamr@2
   513
{
williamr@2
   514
  // Heart is defined as the union of three shapes:
williamr@2
   515
  // Square w/ corners (+-1000, -1000), (0, 0), (0, -2000)
williamr@2
   516
  // Circle centered at (-500, -500) radius 500*sqrt(2)
williamr@2
   517
  // Circle centered at (500, -500) radius 500*sqrt(2)
williamr@2
   518
  // Bounding box (-1000, -2000) - (1000, 500*(sqrt(2) - 1))
williamr@2
   519
williamr@2
   520
  struct point 
williamr@2
   521
  {
williamr@2
   522
    point() { values[0] = 0.0; values[1] = 0.0; }
williamr@2
   523
    point(double x, double y) { values[0] = x; values[1] = y; }
williamr@2
   524
williamr@2
   525
    double& operator[](std::size_t i)       { return values[i]; }
williamr@2
   526
    double  operator[](std::size_t i) const { return values[i]; }
williamr@2
   527
williamr@2
   528
  private:
williamr@2
   529
    double values[2];
williamr@2
   530
  };
williamr@2
   531
williamr@2
   532
  bool in_heart(point p) const 
williamr@2
   533
  {
williamr@2
   534
#ifndef BOOST_NO_STDC_NAMESPACE
williamr@2
   535
    using std::abs;
williamr@2
   536
    using std::pow;
williamr@2
   537
#endif
williamr@2
   538
williamr@2
   539
    if (p[1] < abs(p[0]) - 2000) return false; // Bottom
williamr@2
   540
    if (p[1] <= -1000) return true; // Diagonal of square
williamr@2
   541
    if (pow(p[0] - -500, 2) + pow(p[1] - -500, 2) <= 500000)
williamr@2
   542
      return true; // Left circle
williamr@2
   543
    if (pow(p[0] - 500, 2) + pow(p[1] - -500, 2) <= 500000)
williamr@2
   544
      return true; // Right circle
williamr@2
   545
    return false;
williamr@2
   546
  }
williamr@2
   547
williamr@2
   548
  bool segment_within_heart(point p1, point p2) const 
williamr@2
   549
  {
williamr@2
   550
    // Assumes that p1 and p2 are within the heart
williamr@2
   551
    if ((p1[0] < 0) == (p2[0] < 0)) return true; // Same side of symmetry line
williamr@2
   552
    if (p1[0] == p2[0]) return true; // Vertical
williamr@2
   553
    double slope = (p2[1] - p1[1]) / (p2[0] - p1[0]);
williamr@2
   554
    double intercept = p1[1] - p1[0] * slope;
williamr@2
   555
    if (intercept > 0) return false; // Crosses between circles
williamr@2
   556
    return true;
williamr@2
   557
  }
williamr@2
   558
williamr@2
   559
  typedef uniform_01<RandomNumberGenerator, double> rand_t;
williamr@2
   560
williamr@2
   561
 public:
williamr@2
   562
  typedef point point_type;
williamr@2
   563
williamr@2
   564
  heart_topology() 
williamr@2
   565
    : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)) { }
williamr@2
   566
williamr@2
   567
  heart_topology(RandomNumberGenerator& gen) 
williamr@2
   568
    : gen_ptr(), rand(new rand_t(gen)) { }
williamr@2
   569
williamr@2
   570
  point random_point() const 
williamr@2
   571
  {
williamr@2
   572
#ifndef BOOST_NO_STDC_NAMESPACE
williamr@2
   573
    using std::sqrt;
williamr@2
   574
#endif
williamr@2
   575
williamr@2
   576
    point result;
williamr@2
   577
    double sqrt2 = sqrt(2.);
williamr@2
   578
    do {
williamr@2
   579
      result[0] = (*rand)() * (1000 + 1000 * sqrt2) - (500 + 500 * sqrt2);
williamr@2
   580
      result[1] = (*rand)() * (2000 + 500 * (sqrt2 - 1)) - 2000;
williamr@2
   581
    } while (!in_heart(result));
williamr@2
   582
    return result;
williamr@2
   583
  }
williamr@2
   584
williamr@2
   585
  double distance(point a, point b) const 
williamr@2
   586
  {
williamr@2
   587
#ifndef BOOST_NO_STDC_NAMESPACE
williamr@2
   588
    using std::sqrt;
williamr@2
   589
#endif
williamr@2
   590
    if (segment_within_heart(a, b)) {
williamr@2
   591
      // Straight line
williamr@2
   592
      return sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]));
williamr@2
   593
    } else {
williamr@2
   594
      // Straight line bending around (0, 0)
williamr@2
   595
      return sqrt(a[0] * a[0] + a[1] * a[1]) + sqrt(b[0] * b[0] + b[1] * b[1]);
williamr@2
   596
    }
williamr@2
   597
  }
williamr@2
   598
williamr@2
   599
  point move_position_toward(point a, double fraction, point b) const 
williamr@2
   600
  {
williamr@2
   601
#ifndef BOOST_NO_STDC_NAMESPACE
williamr@2
   602
    using std::sqrt;
williamr@2
   603
#endif
williamr@2
   604
williamr@2
   605
    if (segment_within_heart(a, b)) {
williamr@2
   606
      // Straight line
williamr@2
   607
      return point(a[0] + (b[0] - a[0]) * fraction,
williamr@2
   608
                   a[1] + (b[1] - a[1]) * fraction);
williamr@2
   609
    } else {
williamr@2
   610
      double distance_to_point_a = sqrt(a[0] * a[0] + a[1] * a[1]);
williamr@2
   611
      double distance_to_point_b = sqrt(b[0] * b[0] + b[1] * b[1]);
williamr@2
   612
      double location_of_point = distance_to_point_a / 
williamr@2
   613
                                   (distance_to_point_a + distance_to_point_b);
williamr@2
   614
      if (fraction < location_of_point)
williamr@2
   615
        return point(a[0] * (1 - fraction / location_of_point), 
williamr@2
   616
                     a[1] * (1 - fraction / location_of_point));
williamr@2
   617
      else
williamr@2
   618
        return point(
williamr@2
   619
          b[0] * ((fraction - location_of_point) / (1 - location_of_point)),
williamr@2
   620
          b[1] * ((fraction - location_of_point) / (1 - location_of_point)));
williamr@2
   621
    }
williamr@2
   622
  }
williamr@2
   623
williamr@2
   624
 private:
williamr@2
   625
  shared_ptr<RandomNumberGenerator> gen_ptr;
williamr@2
   626
  shared_ptr<rand_t> rand;
williamr@2
   627
};
williamr@2
   628
williamr@2
   629
} // namespace boost
williamr@2
   630
williamr@2
   631
#endif // BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP