os/ossrv/stdcpp/tsrc/Boost_test/graph/src/layout_test.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright 2004 The Trustees of Indiana University.
sl@0
     2
sl@0
     3
// Use, modification and distribution is subject to the Boost Software
sl@0
     4
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
sl@0
     5
// http://www.boost.org/LICENSE_1_0.txt)
sl@0
     6
sl@0
     7
//  Authors: Douglas Gregor
sl@0
     8
//           Andrew Lumsdaine
sl@0
     9
/*
sl@0
    10
 * © Portions copyright (c) 2006-2007 Nokia Corporation.  All rights reserved.
sl@0
    11
*/
sl@0
    12
sl@0
    13
#include <boost/graph/fruchterman_reingold.hpp>
sl@0
    14
#include <boost/graph/random_layout.hpp>
sl@0
    15
#include <boost/graph/kamada_kawai_spring_layout.hpp>
sl@0
    16
#include <boost/graph/circle_layout.hpp>
sl@0
    17
#include <boost/graph/adjacency_list.hpp>
sl@0
    18
#include <boost/random/linear_congruential.hpp>
sl@0
    19
#include <boost/test/minimal.hpp>
sl@0
    20
#include <iostream>
sl@0
    21
#include <boost/limits.hpp>
sl@0
    22
#include <fstream>
sl@0
    23
#include <string>
sl@0
    24
#ifdef __SYMBIAN32__
sl@0
    25
#include "std_log_result.h"
sl@0
    26
#define LOG_FILENAME_LINE __FILE__, __LINE__
sl@0
    27
#endif
sl@0
    28
using namespace boost;
sl@0
    29
sl@0
    30
enum vertex_position_t { vertex_position };
sl@0
    31
namespace boost { BOOST_INSTALL_PROPERTY(vertex, position); }
sl@0
    32
sl@0
    33
struct point
sl@0
    34
{
sl@0
    35
  double x;
sl@0
    36
  double y;
sl@0
    37
};
sl@0
    38
sl@0
    39
template<typename Graph, typename PositionMap>
sl@0
    40
void print_graph_layout(const Graph& g, PositionMap position)
sl@0
    41
{
sl@0
    42
  typename graph_traits<Graph>::vertex_iterator vi, vi_end;
sl@0
    43
  int xmin = 0, xmax = 0, ymin = 0, ymax = 0;
sl@0
    44
  for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
sl@0
    45
    if ((int)position[*vi].x < xmin) xmin = (int)position[*vi].x;
sl@0
    46
    if ((int)position[*vi].x > xmax) xmax = (int)position[*vi].x;
sl@0
    47
    if ((int)position[*vi].y < ymin) ymin = (int)position[*vi].y;
sl@0
    48
    if ((int)position[*vi].y > ymax) ymax = (int)position[*vi].y;
sl@0
    49
  }
sl@0
    50
sl@0
    51
  for (int y = ymin; y <= ymax; ++y) {
sl@0
    52
    for (int x = xmin; x <= xmax; ++x) {
sl@0
    53
      // Find vertex at this position
sl@0
    54
      typename graph_traits<Graph>::vertices_size_type index = 0;
sl@0
    55
      for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi, ++index) {
sl@0
    56
        if ((int)position[*vi].x == x && (int)position[*vi].y == y)
sl@0
    57
          break;
sl@0
    58
      }
sl@0
    59
sl@0
    60
      if (vi == vi_end) std::cout << ' ';
sl@0
    61
      else std::cout << (char)(index + 'A');
sl@0
    62
    }
sl@0
    63
    std::cout << std::endl;
sl@0
    64
  }
sl@0
    65
}
sl@0
    66
sl@0
    67
template<typename Graph, typename PositionMap>
sl@0
    68
void dump_graph_layout(std::string name, const Graph& g, PositionMap position)
sl@0
    69
{
sl@0
    70
  std::ofstream out((name + ".dot").c_str());
sl@0
    71
  out << "graph " << name << " {" << std::endl;
sl@0
    72
sl@0
    73
  typename graph_traits<Graph>::vertex_iterator vi, vi_end;
sl@0
    74
  for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
sl@0
    75
    out << "  n" << get(vertex_index, g, *vi) << "[ pos=\"" 
sl@0
    76
        << (int)position[*vi].x + 25 << ", " << (int)position[*vi].y + 25 
sl@0
    77
        << "\" ];\n";
sl@0
    78
  }
sl@0
    79
sl@0
    80
  typename graph_traits<Graph>::edge_iterator ei, ei_end;
sl@0
    81
  for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
sl@0
    82
    out << "  n" << get(vertex_index, g, source(*ei, g)) << " -- n"
sl@0
    83
        << get(vertex_index, g, target(*ei, g)) << ";\n";
sl@0
    84
  }
sl@0
    85
  out << "}\n";
sl@0
    86
}
sl@0
    87
sl@0
    88
template<typename Graph>
sl@0
    89
void 
sl@0
    90
test_circle_layout(Graph*, typename graph_traits<Graph>::vertices_size_type n)
sl@0
    91
{
sl@0
    92
  typedef typename graph_traits<Graph>::vertex_descriptor vertex;
sl@0
    93
  typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
sl@0
    94
  typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
sl@0
    95
  typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
sl@0
    96
sl@0
    97
  Graph g(n);
sl@0
    98
sl@0
    99
  // Initialize vertex indices
sl@0
   100
  vertex_iterator vi = vertices(g).first;
sl@0
   101
  for (vertices_size_type i = 0; i < n; ++i, ++vi) 
sl@0
   102
    put(vertex_index, g, *vi, i);
sl@0
   103
sl@0
   104
  circle_graph_layout(g, get(vertex_position, g), 10.0);
sl@0
   105
sl@0
   106
  std::cout << "Regular polygon layout with " << n << " points.\n";
sl@0
   107
  print_graph_layout(g, get(vertex_position, g));
sl@0
   108
}
sl@0
   109
sl@0
   110
struct simple_edge
sl@0
   111
{
sl@0
   112
  int first, second;
sl@0
   113
};
sl@0
   114
sl@0
   115
struct kamada_kawai_done 
sl@0
   116
{
sl@0
   117
  kamada_kawai_done() : last_delta() {}
sl@0
   118
sl@0
   119
  template<typename Graph>
sl@0
   120
  bool operator()(double delta_p, 
sl@0
   121
                  typename boost::graph_traits<Graph>::vertex_descriptor p,
sl@0
   122
                  const Graph& g,
sl@0
   123
                  bool global)
sl@0
   124
  {
sl@0
   125
    if (global) {
sl@0
   126
      double diff = last_delta - delta_p;
sl@0
   127
      if (diff < 0) diff = -diff;
sl@0
   128
      last_delta = delta_p;
sl@0
   129
      return diff < 0.01;
sl@0
   130
    } else {
sl@0
   131
      return delta_p < 0.01;
sl@0
   132
    }
sl@0
   133
  }
sl@0
   134
sl@0
   135
  double last_delta;
sl@0
   136
};
sl@0
   137
sl@0
   138
template<typename Graph>
sl@0
   139
void
sl@0
   140
test_triangle(Graph*)
sl@0
   141
{
sl@0
   142
  typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
sl@0
   143
  typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
sl@0
   144
sl@0
   145
  Graph g;
sl@0
   146
  
sl@0
   147
  vertex_descriptor u = add_vertex(g); put(vertex_index, g, u, 0);
sl@0
   148
  vertex_descriptor v = add_vertex(g); put(vertex_index, g, v, 1);
sl@0
   149
  vertex_descriptor w = add_vertex(g); put(vertex_index, g, w, 2);
sl@0
   150
sl@0
   151
  edge_descriptor e1 = add_edge(u, v, g).first; put(edge_weight, g, e1, 1.0);
sl@0
   152
  edge_descriptor e2 = add_edge(v, w, g).first; put(edge_weight, g, e2, 1.0);
sl@0
   153
  edge_descriptor e3 = add_edge(w, u, g).first; put(edge_weight, g, e3, 1.0);
sl@0
   154
sl@0
   155
  circle_graph_layout(g, get(vertex_position, g), 25.0);
sl@0
   156
sl@0
   157
  bool ok = kamada_kawai_spring_layout(g, 
sl@0
   158
                                       get(vertex_position, g),
sl@0
   159
                                       get(edge_weight, g),
sl@0
   160
                                       side_length(50.0));
sl@0
   161
  BOOST_CHECK(ok);
sl@0
   162
sl@0
   163
  std::cout << "Triangle layout (Kamada-Kawai).\n";
sl@0
   164
  print_graph_layout(g, get(vertex_position, g));
sl@0
   165
}
sl@0
   166
sl@0
   167
template<typename Graph>
sl@0
   168
void
sl@0
   169
test_cube(Graph*)
sl@0
   170
{
sl@0
   171
  enum {A, B, C, D, E, F, G, H};
sl@0
   172
  simple_edge cube_edges[12] = {
sl@0
   173
    {A, E}, {A, B}, {A, D}, {B, F}, {B, C}, {C, D}, {C, G}, {D, H}, 
sl@0
   174
    {E, H}, {E, F}, {F, G}, {G, H}
sl@0
   175
  };
sl@0
   176
sl@0
   177
  Graph g(&cube_edges[0], &cube_edges[12], 8);
sl@0
   178
  
sl@0
   179
  typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
sl@0
   180
  typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
sl@0
   181
sl@0
   182
  vertex_iterator vi, vi_end;
sl@0
   183
  int i = 0;
sl@0
   184
  for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
sl@0
   185
    put(vertex_index, g, *vi, i++);
sl@0
   186
sl@0
   187
  edge_iterator ei, ei_end;
sl@0
   188
  for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
sl@0
   189
    put(edge_weight, g, *ei, 1.0);
sl@0
   190
    std::cerr << "(" << (char)(get(vertex_index, g, source(*ei, g)) + 'A') 
sl@0
   191
              << ", " << (char)(get(vertex_index, g, target(*ei, g)) + 'A')
sl@0
   192
              << ") ";
sl@0
   193
  }
sl@0
   194
  std::cerr << std::endl;
sl@0
   195
sl@0
   196
  circle_graph_layout(g, get(vertex_position, g), 25.0);
sl@0
   197
sl@0
   198
  bool ok = kamada_kawai_spring_layout(g, 
sl@0
   199
                                       get(vertex_position, g),
sl@0
   200
                                       get(edge_weight, g),
sl@0
   201
                                       side_length(50.0),
sl@0
   202
                                       kamada_kawai_done());
sl@0
   203
  BOOST_CHECK(ok);
sl@0
   204
sl@0
   205
  std::cout << "Cube layout (Kamada-Kawai).\n";
sl@0
   206
  print_graph_layout(g, get(vertex_position, g));
sl@0
   207
sl@0
   208
  dump_graph_layout("cube", g, get(vertex_position, g));
sl@0
   209
sl@0
   210
  minstd_rand gen;
sl@0
   211
  random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0, 
sl@0
   212
                      gen);
sl@0
   213
sl@0
   214
  std::vector<point> displacements(num_vertices(g));
sl@0
   215
  fruchterman_reingold_force_directed_layout
sl@0
   216
    (g,
sl@0
   217
     get(vertex_position, g),
sl@0
   218
     50.0,
sl@0
   219
     50.0,
sl@0
   220
     square_distance_attractive_force(),
sl@0
   221
     square_distance_repulsive_force(),
sl@0
   222
     all_force_pairs(),
sl@0
   223
     linear_cooling<double>(100),
sl@0
   224
     make_iterator_property_map(displacements.begin(),
sl@0
   225
                                get(vertex_index, g),
sl@0
   226
                                point()));
sl@0
   227
sl@0
   228
  std::cout << "Cube layout (Fruchterman-Reingold).\n";
sl@0
   229
  print_graph_layout(g, get(vertex_position, g));
sl@0
   230
sl@0
   231
  dump_graph_layout("cube-fr", g, get(vertex_position, g));
sl@0
   232
}
sl@0
   233
sl@0
   234
template<typename Graph>
sl@0
   235
void
sl@0
   236
test_triangular(Graph*)
sl@0
   237
{
sl@0
   238
  enum {A, B, C, D, E, F, G, H, I, J};
sl@0
   239
  simple_edge triangular_edges[18] = {
sl@0
   240
    {A, B}, {A, C}, {B, C}, {B, D}, {B, E}, {C, E}, {C, F}, {D, E}, {D, G},
sl@0
   241
    {D, H}, {E, F}, {E, H}, {E, I}, {F, I}, {F, J}, {G, H}, {H, I}, {I, J}
sl@0
   242
  };
sl@0
   243
sl@0
   244
  Graph g(&triangular_edges[0], &triangular_edges[18], 10);
sl@0
   245
  
sl@0
   246
  typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
sl@0
   247
  typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
sl@0
   248
sl@0
   249
  vertex_iterator vi, vi_end;
sl@0
   250
  int i = 0;
sl@0
   251
  for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
sl@0
   252
    put(vertex_index, g, *vi, i++);
sl@0
   253
sl@0
   254
  edge_iterator ei, ei_end;
sl@0
   255
  for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
sl@0
   256
    put(edge_weight, g, *ei, 1.0);
sl@0
   257
    std::cerr << "(" << (char)(get(vertex_index, g, source(*ei, g)) + 'A') 
sl@0
   258
              << ", " << (char)(get(vertex_index, g, target(*ei, g)) + 'A')
sl@0
   259
              << ") ";
sl@0
   260
  }
sl@0
   261
  std::cerr << std::endl;
sl@0
   262
sl@0
   263
  circle_graph_layout(g, get(vertex_position, g), 25.0);
sl@0
   264
sl@0
   265
  bool ok = kamada_kawai_spring_layout(g, 
sl@0
   266
                                       get(vertex_position, g),
sl@0
   267
                                       get(edge_weight, g),
sl@0
   268
                                       side_length(50.0),
sl@0
   269
                                       kamada_kawai_done());
sl@0
   270
  BOOST_CHECK(ok);
sl@0
   271
sl@0
   272
  std::cout << "Triangular layout (Kamada-Kawai).\n";
sl@0
   273
  print_graph_layout(g, get(vertex_position, g));
sl@0
   274
sl@0
   275
  dump_graph_layout("triangular-kk", g, get(vertex_position, g));
sl@0
   276
sl@0
   277
  minstd_rand gen;
sl@0
   278
  random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0, 
sl@0
   279
                      gen);
sl@0
   280
sl@0
   281
  dump_graph_layout("random", g, get(vertex_position, g));
sl@0
   282
sl@0
   283
  std::vector<point> displacements(num_vertices(g));
sl@0
   284
  fruchterman_reingold_force_directed_layout
sl@0
   285
    (g,
sl@0
   286
     get(vertex_position, g),
sl@0
   287
     50.0,
sl@0
   288
     50.0,
sl@0
   289
     attractive_force(square_distance_attractive_force()).
sl@0
   290
     cooling(linear_cooling<double>(100)));
sl@0
   291
sl@0
   292
  std::cout << "Triangular layout (Fruchterman-Reingold).\n";
sl@0
   293
  print_graph_layout(g, get(vertex_position, g));
sl@0
   294
sl@0
   295
  dump_graph_layout("triangular-fr", g, get(vertex_position, g));
sl@0
   296
}
sl@0
   297
sl@0
   298
template<typename Graph>
sl@0
   299
void
sl@0
   300
test_disconnected(Graph*)
sl@0
   301
{
sl@0
   302
  enum {A, B, C, D, E, F, G, H};
sl@0
   303
  simple_edge triangular_edges[13] = {
sl@0
   304
    {A, B}, {B, C}, {C, A}, 
sl@0
   305
    {D, E}, {E, F}, {F, G}, {G, H}, {H, D},
sl@0
   306
    {D, F}, {F, H}, {H, E}, {E, G}, {G, D}
sl@0
   307
  };
sl@0
   308
sl@0
   309
  Graph g(&triangular_edges[0], &triangular_edges[13], 8);
sl@0
   310
  
sl@0
   311
  typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
sl@0
   312
  typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
sl@0
   313
sl@0
   314
  vertex_iterator vi, vi_end;
sl@0
   315
  int i = 0;
sl@0
   316
  for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
sl@0
   317
    put(vertex_index, g, *vi, i++);
sl@0
   318
sl@0
   319
  edge_iterator ei, ei_end;
sl@0
   320
  for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
sl@0
   321
    put(edge_weight, g, *ei, 1.0);
sl@0
   322
    std::cerr << "(" << (char)(get(vertex_index, g, source(*ei, g)) + 'A') 
sl@0
   323
              << ", " << (char)(get(vertex_index, g, target(*ei, g)) + 'A')
sl@0
   324
              << ") ";
sl@0
   325
  }
sl@0
   326
  std::cerr << std::endl;
sl@0
   327
sl@0
   328
  circle_graph_layout(g, get(vertex_position, g), 25.0);
sl@0
   329
sl@0
   330
  bool ok = kamada_kawai_spring_layout(g, 
sl@0
   331
                                       get(vertex_position, g),
sl@0
   332
                                       get(edge_weight, g),
sl@0
   333
                                       side_length(50.0),
sl@0
   334
                                       kamada_kawai_done());
sl@0
   335
  BOOST_CHECK(!ok);
sl@0
   336
sl@0
   337
  minstd_rand gen;
sl@0
   338
  random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0, 
sl@0
   339
                      gen);
sl@0
   340
sl@0
   341
  std::vector<point> displacements(num_vertices(g));
sl@0
   342
  fruchterman_reingold_force_directed_layout
sl@0
   343
    (g,
sl@0
   344
     get(vertex_position, g),
sl@0
   345
     50.0,
sl@0
   346
     50.0,
sl@0
   347
     attractive_force(square_distance_attractive_force()).
sl@0
   348
     cooling(linear_cooling<double>(50)));
sl@0
   349
sl@0
   350
  std::cout << "Disconnected layout (Fruchterman-Reingold).\n";
sl@0
   351
  print_graph_layout(g, get(vertex_position, g));
sl@0
   352
sl@0
   353
  dump_graph_layout("disconnected-fr", g, get(vertex_position, g));
sl@0
   354
}
sl@0
   355
sl@0
   356
int test_main(int, char*[])
sl@0
   357
{
sl@0
   358
  typedef adjacency_list<listS, listS, undirectedS, 
sl@0
   359
                         // Vertex properties
sl@0
   360
                         property<vertex_index_t, int,
sl@0
   361
                         property<vertex_position_t, point> >,
sl@0
   362
                         // Edge properties
sl@0
   363
                         property<edge_weight_t, double> > Graph;
sl@0
   364
sl@0
   365
  test_circle_layout((Graph*)0, 5);
sl@0
   366
  test_cube((Graph*)0);
sl@0
   367
  test_triangular((Graph*)0);
sl@0
   368
  test_disconnected((Graph*)0);
sl@0
   369
   
sl@0
   370
#ifdef __SYMBIAN32__
sl@0
   371
std_log(LOG_FILENAME_LINE,"[End Test Case ]");
sl@0
   372
sl@0
   373
	testResultXml("layout_test");
sl@0
   374
	close_log_file();
sl@0
   375
#endif
sl@0
   376
  return 0;
sl@0
   377
}