tools/lgf-gen.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 03 Apr 2009 18:59:15 +0200
changeset 600 6ac5d9ae1d3d
parent 507 d9e43511d11c
child 562 ab6da8cf5ab2
permissions -rw-r--r--
Support real types + numerical stability fix in NS (#254)

- Real types are supported by appropriate inicialization.
- A feature of the XTI spanning tree structure is removed to ensure
numerical stability (could cause problems using integer types).
The node potentials are updated always on the lower subtree,
in order to prevent overflow problems.
The former method isn't notably faster during to our tests.
alpar@507
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@507
     2
 *
alpar@507
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@507
     4
 *
alpar@507
     5
 * Copyright (C) 2003-2009
alpar@507
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@507
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@507
     8
 *
alpar@507
     9
 * Permission to use, modify and distribute this software is granted
alpar@507
    10
 * provided that this copyright notice appears in all copies. For
alpar@507
    11
 * precise terms see the accompanying LICENSE file.
alpar@507
    12
 *
alpar@507
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@507
    14
 * express or implied, and with no claim as to its suitability for any
alpar@507
    15
 * purpose.
alpar@507
    16
 *
alpar@507
    17
 */
alpar@507
    18
alpar@507
    19
/// \ingroup tools
alpar@507
    20
/// \file
alpar@507
    21
/// \brief Special plane digraph generator.
alpar@507
    22
///
alpar@507
    23
/// Graph generator application for various types of plane graphs.
alpar@507
    24
///
alpar@507
    25
/// See
alpar@507
    26
/// \verbatim
alpar@507
    27
///  lgf-gen --help
alpar@507
    28
/// \endverbatim
alpar@507
    29
/// for more info on the usage.
alpar@507
    30
///
alpar@507
    31
alpar@507
    32
alpar@507
    33
#include <algorithm>
alpar@507
    34
#include <set>
alpar@507
    35
#include <lemon/list_graph.h>
alpar@507
    36
#include <lemon/random.h>
alpar@507
    37
#include <lemon/dim2.h>
alpar@507
    38
#include <lemon/bfs.h>
alpar@507
    39
#include <lemon/counter.h>
alpar@507
    40
#include <lemon/suurballe.h>
alpar@507
    41
#include <lemon/graph_to_eps.h>
alpar@507
    42
#include <lemon/lgf_writer.h>
alpar@507
    43
#include <lemon/arg_parser.h>
alpar@507
    44
#include <lemon/euler.h>
alpar@507
    45
#include <lemon/math.h>
alpar@507
    46
#include <lemon/kruskal.h>
alpar@507
    47
#include <lemon/time_measure.h>
alpar@507
    48
alpar@507
    49
using namespace lemon;
alpar@507
    50
alpar@507
    51
typedef dim2::Point<double> Point;
alpar@507
    52
alpar@507
    53
GRAPH_TYPEDEFS(ListGraph);
alpar@507
    54
alpar@507
    55
bool progress=true;
alpar@507
    56
alpar@507
    57
int N;
alpar@507
    58
// int girth;
alpar@507
    59
alpar@507
    60
ListGraph g;
alpar@507
    61
alpar@507
    62
std::vector<Node> nodes;
alpar@507
    63
ListGraph::NodeMap<Point> coords(g);
alpar@507
    64
alpar@507
    65
alpar@507
    66
double totalLen(){
alpar@507
    67
  double tlen=0;
alpar@507
    68
  for(EdgeIt e(g);e!=INVALID;++e)
alpar@507
    69
    tlen+=sqrt((coords[g.v(e)]-coords[g.u(e)]).normSquare());
alpar@507
    70
  return tlen;
alpar@507
    71
}
alpar@507
    72
alpar@507
    73
int tsp_impr_num=0;
alpar@507
    74
alpar@507
    75
const double EPSILON=1e-8;
alpar@507
    76
bool tsp_improve(Node u, Node v)
alpar@507
    77
{
alpar@507
    78
  double luv=std::sqrt((coords[v]-coords[u]).normSquare());
alpar@507
    79
  Node u2=u;
alpar@507
    80
  Node v2=v;
alpar@507
    81
  do {
alpar@507
    82
    Node n;
alpar@507
    83
    for(IncEdgeIt e(g,v2);(n=g.runningNode(e))==u2;++e) { }
alpar@507
    84
    u2=v2;
alpar@507
    85
    v2=n;
alpar@507
    86
    if(luv+std::sqrt((coords[v2]-coords[u2]).normSquare())-EPSILON>
alpar@507
    87
       std::sqrt((coords[u]-coords[u2]).normSquare())+
alpar@507
    88
       std::sqrt((coords[v]-coords[v2]).normSquare()))
alpar@507
    89
      {
alpar@507
    90
         g.erase(findEdge(g,u,v));
alpar@507
    91
         g.erase(findEdge(g,u2,v2));
alpar@507
    92
        g.addEdge(u2,u);
alpar@507
    93
        g.addEdge(v,v2);
alpar@507
    94
        tsp_impr_num++;
alpar@507
    95
        return true;
alpar@507
    96
      }
alpar@507
    97
  } while(v2!=u);
alpar@507
    98
  return false;
alpar@507
    99
}
alpar@507
   100
alpar@507
   101
bool tsp_improve(Node u)
alpar@507
   102
{
alpar@507
   103
  for(IncEdgeIt e(g,u);e!=INVALID;++e)
alpar@507
   104
    if(tsp_improve(u,g.runningNode(e))) return true;
alpar@507
   105
  return false;
alpar@507
   106
}
alpar@507
   107
alpar@507
   108
void tsp_improve()
alpar@507
   109
{
alpar@507
   110
  bool b;
alpar@507
   111
  do {
alpar@507
   112
    b=false;
alpar@507
   113
    for(NodeIt n(g);n!=INVALID;++n)
alpar@507
   114
      if(tsp_improve(n)) b=true;
alpar@507
   115
  } while(b);
alpar@507
   116
}
alpar@507
   117
alpar@507
   118
void tsp()
alpar@507
   119
{
alpar@507
   120
  for(int i=0;i<N;i++) g.addEdge(nodes[i],nodes[(i+1)%N]);
alpar@507
   121
  tsp_improve();
alpar@507
   122
}
alpar@507
   123
alpar@507
   124
class Line
alpar@507
   125
{
alpar@507
   126
public:
alpar@507
   127
  Point a;
alpar@507
   128
  Point b;
alpar@507
   129
  Line(Point _a,Point _b) :a(_a),b(_b) {}
alpar@507
   130
  Line(Node _a,Node _b) : a(coords[_a]),b(coords[_b]) {}
alpar@507
   131
  Line(const Arc &e) : a(coords[g.source(e)]),b(coords[g.target(e)]) {}
alpar@507
   132
  Line(const Edge &e) : a(coords[g.u(e)]),b(coords[g.v(e)]) {}
alpar@507
   133
};
alpar@507
   134
alpar@507
   135
inline std::ostream& operator<<(std::ostream &os, const Line &l)
alpar@507
   136
{
alpar@507
   137
  os << l.a << "->" << l.b;
alpar@507
   138
  return os;
alpar@507
   139
}
alpar@507
   140
alpar@507
   141
bool cross(Line a, Line b)
alpar@507
   142
{
alpar@507
   143
  Point ao=rot90(a.b-a.a);
alpar@507
   144
  Point bo=rot90(b.b-b.a);
alpar@507
   145
  return (ao*(b.a-a.a))*(ao*(b.b-a.a))<0 &&
alpar@507
   146
    (bo*(a.a-b.a))*(bo*(a.b-b.a))<0;
alpar@507
   147
}
alpar@507
   148
alpar@507
   149
struct Parc
alpar@507
   150
{
alpar@507
   151
  Node a;
alpar@507
   152
  Node b;
alpar@507
   153
  double len;
alpar@507
   154
};
alpar@507
   155
alpar@507
   156
bool pedgeLess(Parc a,Parc b)
alpar@507
   157
{
alpar@507
   158
  return a.len<b.len;
alpar@507
   159
}
alpar@507
   160
alpar@507
   161
std::vector<Edge> arcs;
alpar@507
   162
alpar@507
   163
namespace _delaunay_bits {
alpar@507
   164
alpar@507
   165
  struct Part {
alpar@507
   166
    int prev, curr, next;
alpar@507
   167
alpar@507
   168
    Part(int p, int c, int n) : prev(p), curr(c), next(n) {}
alpar@507
   169
  };
alpar@507
   170
alpar@507
   171
  inline std::ostream& operator<<(std::ostream& os, const Part& part) {
alpar@507
   172
    os << '(' << part.prev << ',' << part.curr << ',' << part.next << ')';
alpar@507
   173
    return os;
alpar@507
   174
  }
alpar@507
   175
alpar@507
   176
  inline double circle_point(const Point& p, const Point& q, const Point& r) {
alpar@507
   177
    double a = p.x * (q.y - r.y) + q.x * (r.y - p.y) + r.x * (p.y - q.y);
alpar@507
   178
    if (a == 0) return std::numeric_limits<double>::quiet_NaN();
alpar@507
   179
alpar@507
   180
    double d = (p.x * p.x + p.y * p.y) * (q.y - r.y) +
alpar@507
   181
      (q.x * q.x + q.y * q.y) * (r.y - p.y) +
alpar@507
   182
      (r.x * r.x + r.y * r.y) * (p.y - q.y);
alpar@507
   183
alpar@507
   184
    double e = (p.x * p.x + p.y * p.y) * (q.x - r.x) +
alpar@507
   185
      (q.x * q.x + q.y * q.y) * (r.x - p.x) +
alpar@507
   186
      (r.x * r.x + r.y * r.y) * (p.x - q.x);
alpar@507
   187
alpar@507
   188
    double f = (p.x * p.x + p.y * p.y) * (q.x * r.y - r.x * q.y) +
alpar@507
   189
      (q.x * q.x + q.y * q.y) * (r.x * p.y - p.x * r.y) +
alpar@507
   190
      (r.x * r.x + r.y * r.y) * (p.x * q.y - q.x * p.y);
alpar@507
   191
alpar@507
   192
    return d / (2 * a) + sqrt((d * d + e * e) / (4 * a * a) + f / a);
alpar@507
   193
  }
alpar@507
   194
alpar@507
   195
  inline bool circle_form(const Point& p, const Point& q, const Point& r) {
alpar@507
   196
    return rot90(q - p) * (r - q) < 0.0;
alpar@507
   197
  }
alpar@507
   198
alpar@507
   199
  inline double intersection(const Point& p, const Point& q, double sx) {
alpar@507
   200
    const double epsilon = 1e-8;
alpar@507
   201
alpar@507
   202
    if (p.x == q.x) return (p.y + q.y) / 2.0;
alpar@507
   203
alpar@507
   204
    if (sx < p.x + epsilon) return p.y;
alpar@507
   205
    if (sx < q.x + epsilon) return q.y;
alpar@507
   206
alpar@507
   207
    double a = q.x - p.x;
alpar@507
   208
    double b = (q.x - sx) * p.y - (p.x - sx) * q.y;
alpar@507
   209
    double d = (q.x - sx) * (p.x - sx) * (p - q).normSquare();
alpar@507
   210
    return (b - sqrt(d)) / a;
alpar@507
   211
  }
alpar@507
   212
alpar@507
   213
  struct YLess {
alpar@507
   214
alpar@507
   215
alpar@507
   216
    YLess(const std::vector<Point>& points, double& sweep)
alpar@507
   217
      : _points(points), _sweep(sweep) {}
alpar@507
   218
alpar@507
   219
    bool operator()(const Part& l, const Part& r) const {
alpar@507
   220
      const double epsilon = 1e-8;
alpar@507
   221
alpar@507
   222
      //      std::cerr << l << " vs " << r << std::endl;
alpar@507
   223
      double lbx = l.prev != -1 ?
alpar@507
   224
        intersection(_points[l.prev], _points[l.curr], _sweep) :
alpar@507
   225
        - std::numeric_limits<double>::infinity();
alpar@507
   226
      double rbx = r.prev != -1 ?
alpar@507
   227
        intersection(_points[r.prev], _points[r.curr], _sweep) :
alpar@507
   228
        - std::numeric_limits<double>::infinity();
alpar@507
   229
      double lex = l.next != -1 ?
alpar@507
   230
        intersection(_points[l.curr], _points[l.next], _sweep) :
alpar@507
   231
        std::numeric_limits<double>::infinity();
alpar@507
   232
      double rex = r.next != -1 ?
alpar@507
   233
        intersection(_points[r.curr], _points[r.next], _sweep) :
alpar@507
   234
        std::numeric_limits<double>::infinity();
alpar@507
   235
alpar@507
   236
      if (lbx > lex) std::swap(lbx, lex);
alpar@507
   237
      if (rbx > rex) std::swap(rbx, rex);
alpar@507
   238
alpar@507
   239
      if (lex < epsilon + rex && lbx + epsilon < rex) return true;
alpar@507
   240
      if (rex < epsilon + lex && rbx + epsilon < lex) return false;
alpar@507
   241
      return lex < rex;
alpar@507
   242
    }
alpar@507
   243
alpar@507
   244
    const std::vector<Point>& _points;
alpar@507
   245
    double& _sweep;
alpar@507
   246
  };
alpar@507
   247
alpar@507
   248
  struct BeachIt;
alpar@507
   249
alpar@507
   250
  typedef std::multimap<double, BeachIt> SpikeHeap;
alpar@507
   251
alpar@507
   252
  typedef std::multimap<Part, SpikeHeap::iterator, YLess> Beach;
alpar@507
   253
alpar@507
   254
  struct BeachIt {
alpar@507
   255
    Beach::iterator it;
alpar@507
   256
alpar@507
   257
    BeachIt(Beach::iterator iter) : it(iter) {}
alpar@507
   258
  };
alpar@507
   259
alpar@507
   260
}
alpar@507
   261
alpar@507
   262
inline void delaunay() {
alpar@507
   263
  Counter cnt("Number of arcs added: ");
alpar@507
   264
alpar@507
   265
  using namespace _delaunay_bits;
alpar@507
   266
alpar@507
   267
  typedef _delaunay_bits::Part Part;
alpar@507
   268
  typedef std::vector<std::pair<double, int> > SiteHeap;
alpar@507
   269
alpar@507
   270
alpar@507
   271
  std::vector<Point> points;
alpar@507
   272
  std::vector<Node> nodes;
alpar@507
   273
alpar@507
   274
  for (NodeIt it(g); it != INVALID; ++it) {
alpar@507
   275
    nodes.push_back(it);
alpar@507
   276
    points.push_back(coords[it]);
alpar@507
   277
  }
alpar@507
   278
alpar@507
   279
  SiteHeap siteheap(points.size());
alpar@507
   280
alpar@507
   281
  double sweep;
alpar@507
   282
alpar@507
   283
alpar@507
   284
  for (int i = 0; i < int(siteheap.size()); ++i) {
alpar@507
   285
    siteheap[i] = std::make_pair(points[i].x, i);
alpar@507
   286
  }
alpar@507
   287
alpar@507
   288
  std::sort(siteheap.begin(), siteheap.end());
alpar@507
   289
  sweep = siteheap.front().first;
alpar@507
   290
alpar@507
   291
  YLess yless(points, sweep);
alpar@507
   292
  Beach beach(yless);
alpar@507
   293
alpar@507
   294
  SpikeHeap spikeheap;
alpar@507
   295
alpar@507
   296
  std::set<std::pair<int, int> > arcs;
alpar@507
   297
alpar@507
   298
  int siteindex = 0;
alpar@507
   299
  {
alpar@507
   300
    SiteHeap front;
alpar@507
   301
alpar@507
   302
    while (siteindex < int(siteheap.size()) &&
alpar@507
   303
           siteheap[0].first == siteheap[siteindex].first) {
alpar@507
   304
      front.push_back(std::make_pair(points[siteheap[siteindex].second].y,
alpar@507
   305
                                     siteheap[siteindex].second));
alpar@507
   306
      ++siteindex;
alpar@507
   307
    }
alpar@507
   308
alpar@507
   309
    std::sort(front.begin(), front.end());
alpar@507
   310
alpar@507
   311
    for (int i = 0; i < int(front.size()); ++i) {
alpar@507
   312
      int prev = (i == 0 ? -1 : front[i - 1].second);
alpar@507
   313
      int curr = front[i].second;
alpar@507
   314
      int next = (i + 1 == int(front.size()) ? -1 : front[i + 1].second);
alpar@507
   315
alpar@507
   316
      beach.insert(std::make_pair(Part(prev, curr, next),
alpar@507
   317
                                  spikeheap.end()));
alpar@507
   318
    }
alpar@507
   319
  }
alpar@507
   320
alpar@507
   321
  while (siteindex < int(points.size()) || !spikeheap.empty()) {
alpar@507
   322
alpar@507
   323
    SpikeHeap::iterator spit = spikeheap.begin();
alpar@507
   324
alpar@507
   325
    if (siteindex < int(points.size()) &&
alpar@507
   326
        (spit == spikeheap.end() || siteheap[siteindex].first < spit->first)) {
alpar@507
   327
      int site = siteheap[siteindex].second;
alpar@507
   328
      sweep = siteheap[siteindex].first;
alpar@507
   329
alpar@507
   330
      Beach::iterator bit = beach.upper_bound(Part(site, site, site));
alpar@507
   331
alpar@507
   332
      if (bit->second != spikeheap.end()) {
alpar@507
   333
        spikeheap.erase(bit->second);
alpar@507
   334
      }
alpar@507
   335
alpar@507
   336
      int prev = bit->first.prev;
alpar@507
   337
      int curr = bit->first.curr;
alpar@507
   338
      int next = bit->first.next;
alpar@507
   339
alpar@507
   340
      beach.erase(bit);
alpar@507
   341
alpar@507
   342
      SpikeHeap::iterator pit = spikeheap.end();
alpar@507
   343
      if (prev != -1 &&
alpar@507
   344
          circle_form(points[prev], points[curr], points[site])) {
alpar@507
   345
        double x = circle_point(points[prev], points[curr], points[site]);
alpar@507
   346
        pit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
alpar@507
   347
        pit->second.it =
alpar@507
   348
          beach.insert(std::make_pair(Part(prev, curr, site), pit));
alpar@507
   349
      } else {
alpar@507
   350
        beach.insert(std::make_pair(Part(prev, curr, site), pit));
alpar@507
   351
      }
alpar@507
   352
alpar@507
   353
      beach.insert(std::make_pair(Part(curr, site, curr), spikeheap.end()));
alpar@507
   354
alpar@507
   355
      SpikeHeap::iterator nit = spikeheap.end();
alpar@507
   356
      if (next != -1 &&
alpar@507
   357
          circle_form(points[site], points[curr],points[next])) {
alpar@507
   358
        double x = circle_point(points[site], points[curr], points[next]);
alpar@507
   359
        nit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
alpar@507
   360
        nit->second.it =
alpar@507
   361
          beach.insert(std::make_pair(Part(site, curr, next), nit));
alpar@507
   362
      } else {
alpar@507
   363
        beach.insert(std::make_pair(Part(site, curr, next), nit));
alpar@507
   364
      }
alpar@507
   365
alpar@507
   366
      ++siteindex;
alpar@507
   367
    } else {
alpar@507
   368
      sweep = spit->first;
alpar@507
   369
alpar@507
   370
      Beach::iterator bit = spit->second.it;
alpar@507
   371
alpar@507
   372
      int prev = bit->first.prev;
alpar@507
   373
      int curr = bit->first.curr;
alpar@507
   374
      int next = bit->first.next;
alpar@507
   375
alpar@507
   376
      {
alpar@507
   377
        std::pair<int, int> arc;
alpar@507
   378
alpar@507
   379
        arc = prev < curr ?
alpar@507
   380
          std::make_pair(prev, curr) : std::make_pair(curr, prev);
alpar@507
   381
alpar@507
   382
        if (arcs.find(arc) == arcs.end()) {
alpar@507
   383
          arcs.insert(arc);
alpar@507
   384
          g.addEdge(nodes[prev], nodes[curr]);
alpar@507
   385
          ++cnt;
alpar@507
   386
        }
alpar@507
   387
alpar@507
   388
        arc = curr < next ?
alpar@507
   389
          std::make_pair(curr, next) : std::make_pair(next, curr);
alpar@507
   390
alpar@507
   391
        if (arcs.find(arc) == arcs.end()) {
alpar@507
   392
          arcs.insert(arc);
alpar@507
   393
          g.addEdge(nodes[curr], nodes[next]);
alpar@507
   394
          ++cnt;
alpar@507
   395
        }
alpar@507
   396
      }
alpar@507
   397
alpar@507
   398
      Beach::iterator pbit = bit; --pbit;
alpar@507
   399
      int ppv = pbit->first.prev;
alpar@507
   400
      Beach::iterator nbit = bit; ++nbit;
alpar@507
   401
      int nnt = nbit->first.next;
alpar@507
   402
alpar@507
   403
      if (bit->second != spikeheap.end()) spikeheap.erase(bit->second);
alpar@507
   404
      if (pbit->second != spikeheap.end()) spikeheap.erase(pbit->second);
alpar@507
   405
      if (nbit->second != spikeheap.end()) spikeheap.erase(nbit->second);
alpar@507
   406
alpar@507
   407
      beach.erase(nbit);
alpar@507
   408
      beach.erase(bit);
alpar@507
   409
      beach.erase(pbit);
alpar@507
   410
alpar@507
   411
      SpikeHeap::iterator pit = spikeheap.end();
alpar@507
   412
      if (ppv != -1 && ppv != next &&
alpar@507
   413
          circle_form(points[ppv], points[prev], points[next])) {
alpar@507
   414
        double x = circle_point(points[ppv], points[prev], points[next]);
alpar@507
   415
        if (x < sweep) x = sweep;
alpar@507
   416
        pit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
alpar@507
   417
        pit->second.it =
alpar@507
   418
          beach.insert(std::make_pair(Part(ppv, prev, next), pit));
alpar@507
   419
      } else {
alpar@507
   420
        beach.insert(std::make_pair(Part(ppv, prev, next), pit));
alpar@507
   421
      }
alpar@507
   422
alpar@507
   423
      SpikeHeap::iterator nit = spikeheap.end();
alpar@507
   424
      if (nnt != -1 && prev != nnt &&
alpar@507
   425
          circle_form(points[prev], points[next], points[nnt])) {
alpar@507
   426
        double x = circle_point(points[prev], points[next], points[nnt]);
alpar@507
   427
        if (x < sweep) x = sweep;
alpar@507
   428
        nit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
alpar@507
   429
        nit->second.it =
alpar@507
   430
          beach.insert(std::make_pair(Part(prev, next, nnt), nit));
alpar@507
   431
      } else {
alpar@507
   432
        beach.insert(std::make_pair(Part(prev, next, nnt), nit));
alpar@507
   433
      }
alpar@507
   434
alpar@507
   435
    }
alpar@507
   436
  }
alpar@507
   437
alpar@507
   438
  for (Beach::iterator it = beach.begin(); it != beach.end(); ++it) {
alpar@507
   439
    int curr = it->first.curr;
alpar@507
   440
    int next = it->first.next;
alpar@507
   441
alpar@507
   442
    if (next == -1) continue;
alpar@507
   443
alpar@507
   444
    std::pair<int, int> arc;
alpar@507
   445
alpar@507
   446
    arc = curr < next ?
alpar@507
   447
      std::make_pair(curr, next) : std::make_pair(next, curr);
alpar@507
   448
alpar@507
   449
    if (arcs.find(arc) == arcs.end()) {
alpar@507
   450
      arcs.insert(arc);
alpar@507
   451
      g.addEdge(nodes[curr], nodes[next]);
alpar@507
   452
      ++cnt;
alpar@507
   453
    }
alpar@507
   454
  }
alpar@507
   455
}
alpar@507
   456
alpar@507
   457
void sparse(int d)
alpar@507
   458
{
alpar@507
   459
  Counter cnt("Number of arcs removed: ");
alpar@507
   460
  Bfs<ListGraph> bfs(g);
alpar@507
   461
  for(std::vector<Edge>::reverse_iterator ei=arcs.rbegin();
alpar@507
   462
      ei!=arcs.rend();++ei)
alpar@507
   463
    {
alpar@507
   464
      Node a=g.u(*ei);
alpar@507
   465
      Node b=g.v(*ei);
alpar@507
   466
      g.erase(*ei);
alpar@507
   467
      bfs.run(a,b);
alpar@507
   468
      if(bfs.predArc(b)==INVALID || bfs.dist(b)>d)
alpar@507
   469
        g.addEdge(a,b);
alpar@507
   470
      else cnt++;
alpar@507
   471
    }
alpar@507
   472
}
alpar@507
   473
alpar@507
   474
void sparse2(int d)
alpar@507
   475
{
alpar@507
   476
  Counter cnt("Number of arcs removed: ");
alpar@507
   477
  for(std::vector<Edge>::reverse_iterator ei=arcs.rbegin();
alpar@507
   478
      ei!=arcs.rend();++ei)
alpar@507
   479
    {
alpar@507
   480
      Node a=g.u(*ei);
alpar@507
   481
      Node b=g.v(*ei);
alpar@507
   482
      g.erase(*ei);
alpar@507
   483
      ConstMap<Arc,int> cegy(1);
alpar@507
   484
      Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy,a,b);
alpar@507
   485
      int k=sur.run(2);
alpar@507
   486
      if(k<2 || sur.totalLength()>d)
alpar@507
   487
        g.addEdge(a,b);
alpar@507
   488
      else cnt++;
alpar@507
   489
//       else std::cout << "Remove arc " << g.id(a) << "-" << g.id(b) << '\n';
alpar@507
   490
    }
alpar@507
   491
}
alpar@507
   492
alpar@507
   493
void sparseTriangle(int d)
alpar@507
   494
{
alpar@507
   495
  Counter cnt("Number of arcs added: ");
alpar@507
   496
  std::vector<Parc> pedges;
alpar@507
   497
  for(NodeIt n(g);n!=INVALID;++n)
alpar@507
   498
    for(NodeIt m=++(NodeIt(n));m!=INVALID;++m)
alpar@507
   499
      {
alpar@507
   500
        Parc p;
alpar@507
   501
        p.a=n;
alpar@507
   502
        p.b=m;
alpar@507
   503
        p.len=(coords[m]-coords[n]).normSquare();
alpar@507
   504
        pedges.push_back(p);
alpar@507
   505
      }
alpar@507
   506
  std::sort(pedges.begin(),pedges.end(),pedgeLess);
alpar@507
   507
  for(std::vector<Parc>::iterator pi=pedges.begin();pi!=pedges.end();++pi)
alpar@507
   508
    {
alpar@507
   509
      Line li(pi->a,pi->b);
alpar@507
   510
      EdgeIt e(g);
alpar@507
   511
      for(;e!=INVALID && !cross(e,li);++e) ;
alpar@507
   512
      Edge ne;
alpar@507
   513
      if(e==INVALID) {
alpar@507
   514
        ConstMap<Arc,int> cegy(1);
alpar@507
   515
        Suurballe<ListGraph,ConstMap<Arc,int> >
alpar@507
   516
          sur(g,cegy,pi->a,pi->b);
alpar@507
   517
        int k=sur.run(2);
alpar@507
   518
        if(k<2 || sur.totalLength()>d)
alpar@507
   519
          {
alpar@507
   520
            ne=g.addEdge(pi->a,pi->b);
alpar@507
   521
            arcs.push_back(ne);
alpar@507
   522
            cnt++;
alpar@507
   523
          }
alpar@507
   524
      }
alpar@507
   525
    }
alpar@507
   526
}
alpar@507
   527
alpar@507
   528
template <typename Graph, typename CoordMap>
alpar@507
   529
class LengthSquareMap {
alpar@507
   530
public:
alpar@507
   531
  typedef typename Graph::Edge Key;
alpar@507
   532
  typedef typename CoordMap::Value::Value Value;
alpar@507
   533
alpar@507
   534
  LengthSquareMap(const Graph& graph, const CoordMap& coords)
alpar@507
   535
    : _graph(graph), _coords(coords) {}
alpar@507
   536
alpar@507
   537
  Value operator[](const Key& key) const {
alpar@507
   538
    return (_coords[_graph.v(key)] -
alpar@507
   539
            _coords[_graph.u(key)]).normSquare();
alpar@507
   540
  }
alpar@507
   541
alpar@507
   542
private:
alpar@507
   543
alpar@507
   544
  const Graph& _graph;
alpar@507
   545
  const CoordMap& _coords;
alpar@507
   546
};
alpar@507
   547
alpar@507
   548
void minTree() {
alpar@507
   549
  std::vector<Parc> pedges;
alpar@507
   550
  Timer T;
alpar@507
   551
  std::cout << T.realTime() << "s: Creating delaunay triangulation...\n";
alpar@507
   552
  delaunay();
alpar@507
   553
  std::cout << T.realTime() << "s: Calculating spanning tree...\n";
alpar@507
   554
  LengthSquareMap<ListGraph, ListGraph::NodeMap<Point> > ls(g, coords);
alpar@507
   555
  ListGraph::EdgeMap<bool> tree(g);
alpar@507
   556
  kruskal(g, ls, tree);
alpar@507
   557
  std::cout << T.realTime() << "s: Removing non tree arcs...\n";
alpar@507
   558
  std::vector<Edge> remove;
alpar@507
   559
  for (EdgeIt e(g); e != INVALID; ++e) {
alpar@507
   560
    if (!tree[e]) remove.push_back(e);
alpar@507
   561
  }
alpar@507
   562
  for(int i = 0; i < int(remove.size()); ++i) {
alpar@507
   563
    g.erase(remove[i]);
alpar@507
   564
  }
alpar@507
   565
  std::cout << T.realTime() << "s: Done\n";
alpar@507
   566
}
alpar@507
   567
alpar@507
   568
void tsp2()
alpar@507
   569
{
alpar@507
   570
  std::cout << "Find a tree..." << std::endl;
alpar@507
   571
alpar@507
   572
  minTree();
alpar@507
   573
alpar@507
   574
  std::cout << "Total arc length (tree) : " << totalLen() << std::endl;
alpar@507
   575
alpar@507
   576
  std::cout << "Make it Euler..." << std::endl;
alpar@507
   577
alpar@507
   578
  {
alpar@507
   579
    std::vector<Node> leafs;
alpar@507
   580
    for(NodeIt n(g);n!=INVALID;++n)
alpar@507
   581
      if(countIncEdges(g,n)%2==1) leafs.push_back(n);
alpar@507
   582
alpar@507
   583
//    for(unsigned int i=0;i<leafs.size();i+=2)
alpar@507
   584
//       g.addArc(leafs[i],leafs[i+1]);
alpar@507
   585
alpar@507
   586
    std::vector<Parc> pedges;
alpar@507
   587
    for(unsigned int i=0;i<leafs.size()-1;i++)
alpar@507
   588
      for(unsigned int j=i+1;j<leafs.size();j++)
alpar@507
   589
        {
alpar@507
   590
          Node n=leafs[i];
alpar@507
   591
          Node m=leafs[j];
alpar@507
   592
          Parc p;
alpar@507
   593
          p.a=n;
alpar@507
   594
          p.b=m;
alpar@507
   595
          p.len=(coords[m]-coords[n]).normSquare();
alpar@507
   596
          pedges.push_back(p);
alpar@507
   597
        }
alpar@507
   598
    std::sort(pedges.begin(),pedges.end(),pedgeLess);
alpar@507
   599
    for(unsigned int i=0;i<pedges.size();i++)
alpar@507
   600
      if(countIncEdges(g,pedges[i].a)%2 &&
alpar@507
   601
         countIncEdges(g,pedges[i].b)%2)
alpar@507
   602
        g.addEdge(pedges[i].a,pedges[i].b);
alpar@507
   603
  }
alpar@507
   604
alpar@507
   605
  for(NodeIt n(g);n!=INVALID;++n)
alpar@507
   606
    if(countIncEdges(g,n)%2 || countIncEdges(g,n)==0 )
alpar@507
   607
      std::cout << "GEBASZ!!!" << std::endl;
alpar@507
   608
alpar@507
   609
  for(EdgeIt e(g);e!=INVALID;++e)
alpar@507
   610
    if(g.u(e)==g.v(e))
alpar@507
   611
      std::cout << "LOOP GEBASZ!!!" << std::endl;
alpar@507
   612
alpar@507
   613
  std::cout << "Number of arcs : " << countEdges(g) << std::endl;
alpar@507
   614
alpar@507
   615
  std::cout << "Total arc length (euler) : " << totalLen() << std::endl;
alpar@507
   616
alpar@507
   617
  ListGraph::EdgeMap<Arc> enext(g);
alpar@507
   618
  {
alpar@507
   619
    EulerIt<ListGraph> e(g);
alpar@507
   620
    Arc eo=e;
alpar@507
   621
    Arc ef=e;
alpar@507
   622
//     std::cout << "Tour arc: " << g.id(Edge(e)) << std::endl;
alpar@507
   623
    for(++e;e!=INVALID;++e)
alpar@507
   624
      {
alpar@507
   625
//         std::cout << "Tour arc: " << g.id(Edge(e)) << std::endl;
alpar@507
   626
        enext[eo]=e;
alpar@507
   627
        eo=e;
alpar@507
   628
      }
alpar@507
   629
    enext[eo]=ef;
alpar@507
   630
  }
alpar@507
   631
alpar@507
   632
  std::cout << "Creating a tour from that..." << std::endl;
alpar@507
   633
alpar@507
   634
  int nnum = countNodes(g);
alpar@507
   635
  int ednum = countEdges(g);
alpar@507
   636
alpar@507
   637
  for(Arc p=enext[EdgeIt(g)];ednum>nnum;p=enext[p])
alpar@507
   638
    {
alpar@507
   639
//       std::cout << "Checking arc " << g.id(p) << std::endl;
alpar@507
   640
      Arc e=enext[p];
alpar@507
   641
      Arc f=enext[e];
alpar@507
   642
      Node n2=g.source(f);
alpar@507
   643
      Node n1=g.oppositeNode(n2,e);
alpar@507
   644
      Node n3=g.oppositeNode(n2,f);
alpar@507
   645
      if(countIncEdges(g,n2)>2)
alpar@507
   646
        {
alpar@507
   647
//           std::cout << "Remove an Arc" << std::endl;
alpar@507
   648
          Arc ff=enext[f];
alpar@507
   649
          g.erase(e);
alpar@507
   650
          g.erase(f);
alpar@507
   651
          if(n1!=n3)
alpar@507
   652
            {
alpar@507
   653
              Arc ne=g.direct(g.addEdge(n1,n3),n1);
alpar@507
   654
              enext[p]=ne;
alpar@507
   655
              enext[ne]=ff;
alpar@507
   656
              ednum--;
alpar@507
   657
            }
alpar@507
   658
          else {
alpar@507
   659
            enext[p]=ff;
alpar@507
   660
            ednum-=2;
alpar@507
   661
          }
alpar@507
   662
        }
alpar@507
   663
    }
alpar@507
   664
alpar@507
   665
  std::cout << "Total arc length (tour) : " << totalLen() << std::endl;
alpar@507
   666
alpar@507
   667
  std::cout << "2-opt the tour..." << std::endl;
alpar@507
   668
alpar@507
   669
  tsp_improve();
alpar@507
   670
alpar@507
   671
  std::cout << "Total arc length (2-opt tour) : " << totalLen() << std::endl;
alpar@507
   672
}
alpar@507
   673
alpar@507
   674
alpar@507
   675
int main(int argc,const char **argv)
alpar@507
   676
{
alpar@507
   677
  ArgParser ap(argc,argv);
alpar@507
   678
alpar@507
   679
//   bool eps;
alpar@507
   680
  bool disc_d, square_d, gauss_d;
alpar@507
   681
//   bool tsp_a,two_a,tree_a;
alpar@507
   682
  int num_of_cities=1;
alpar@507
   683
  double area=1;
alpar@507
   684
  N=100;
alpar@507
   685
//   girth=10;
alpar@507
   686
  std::string ndist("disc");
alpar@507
   687
  ap.refOption("n", "Number of nodes (default is 100)", N)
alpar@507
   688
    .intOption("g", "Girth parameter (default is 10)", 10)
alpar@507
   689
    .refOption("cities", "Number of cities (default is 1)", num_of_cities)
alpar@507
   690
    .refOption("area", "Full relative area of the cities (default is 1)", area)
alpar@507
   691
    .refOption("disc", "Nodes are evenly distributed on a unit disc (default)",disc_d)
alpar@507
   692
    .optionGroup("dist", "disc")
alpar@507
   693
    .refOption("square", "Nodes are evenly distributed on a unit square", square_d)
alpar@507
   694
    .optionGroup("dist", "square")
alpar@507
   695
    .refOption("gauss",
alpar@507
   696
            "Nodes are located according to a two-dim gauss distribution",
alpar@507
   697
            gauss_d)
alpar@507
   698
    .optionGroup("dist", "gauss")
alpar@507
   699
//     .mandatoryGroup("dist")
alpar@507
   700
    .onlyOneGroup("dist")
alpar@507
   701
    .boolOption("eps", "Also generate .eps output (prefix.eps)")
alpar@508
   702
    .boolOption("nonodes", "Draw the edges only in the generated .eps")
alpar@507
   703
    .boolOption("dir", "Directed digraph is generated (each arcs are replaced by two directed ones)")
alpar@507
   704
    .boolOption("2con", "Create a two connected planar digraph")
alpar@507
   705
    .optionGroup("alg","2con")
alpar@507
   706
    .boolOption("tree", "Create a min. cost spanning tree")
alpar@507
   707
    .optionGroup("alg","tree")
alpar@507
   708
    .boolOption("tsp", "Create a TSP tour")
alpar@507
   709
    .optionGroup("alg","tsp")
alpar@507
   710
    .boolOption("tsp2", "Create a TSP tour (tree based)")
alpar@507
   711
    .optionGroup("alg","tsp2")
alpar@507
   712
    .boolOption("dela", "Delaunay triangulation digraph")
alpar@507
   713
    .optionGroup("alg","dela")
alpar@507
   714
    .onlyOneGroup("alg")
alpar@507
   715
    .boolOption("rand", "Use time seed for random number generator")
alpar@507
   716
    .optionGroup("rand", "rand")
alpar@507
   717
    .intOption("seed", "Random seed", -1)
alpar@507
   718
    .optionGroup("rand", "seed")
alpar@507
   719
    .onlyOneGroup("rand")
alpar@507
   720
    .other("[prefix]","Prefix of the output files. Default is 'lgf-gen-out'")
alpar@507
   721
    .run();
alpar@507
   722
alpar@507
   723
  if (ap["rand"]) {
alpar@507
   724
    int seed = time(0);
alpar@507
   725
    std::cout << "Random number seed: " << seed << std::endl;
alpar@507
   726
    rnd = Random(seed);
alpar@507
   727
  }
alpar@507
   728
  if (ap.given("seed")) {
alpar@507
   729
    int seed = ap["seed"];
alpar@507
   730
    std::cout << "Random number seed: " << seed << std::endl;
alpar@507
   731
    rnd = Random(seed);
alpar@507
   732
  }
alpar@507
   733
alpar@507
   734
  std::string prefix;
alpar@507
   735
  switch(ap.files().size())
alpar@507
   736
    {
alpar@507
   737
    case 0:
alpar@507
   738
      prefix="lgf-gen-out";
alpar@507
   739
      break;
alpar@507
   740
    case 1:
alpar@507
   741
      prefix=ap.files()[0];
alpar@507
   742
      break;
alpar@507
   743
    default:
alpar@507
   744
      std::cerr << "\nAt most one prefix can be given\n\n";
alpar@507
   745
      exit(1);
alpar@507
   746
    }
alpar@507
   747
alpar@507
   748
  double sum_sizes=0;
alpar@507
   749
  std::vector<double> sizes;
alpar@507
   750
  std::vector<double> cum_sizes;
alpar@507
   751
  for(int s=0;s<num_of_cities;s++)
alpar@507
   752
    {
alpar@507
   753
      //         sum_sizes+=rnd.exponential();
alpar@507
   754
      double d=rnd();
alpar@507
   755
      sum_sizes+=d;
alpar@507
   756
      sizes.push_back(d);
alpar@507
   757
      cum_sizes.push_back(sum_sizes);
alpar@507
   758
    }
alpar@507
   759
  int i=0;
alpar@507
   760
  for(int s=0;s<num_of_cities;s++)
alpar@507
   761
    {
alpar@507
   762
      Point center=(num_of_cities==1?Point(0,0):rnd.disc());
alpar@507
   763
      if(gauss_d)
alpar@507
   764
        for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
alpar@507
   765
          Node n=g.addNode();
alpar@507
   766
          nodes.push_back(n);
alpar@507
   767
          coords[n]=center+rnd.gauss2()*area*
alpar@507
   768
            std::sqrt(sizes[s]/sum_sizes);
alpar@507
   769
        }
alpar@507
   770
      else if(square_d)
alpar@507
   771
        for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
alpar@507
   772
          Node n=g.addNode();
alpar@507
   773
          nodes.push_back(n);
alpar@507
   774
          coords[n]=center+Point(rnd()*2-1,rnd()*2-1)*area*
alpar@507
   775
            std::sqrt(sizes[s]/sum_sizes);
alpar@507
   776
        }
alpar@507
   777
      else if(disc_d || true)
alpar@507
   778
        for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
alpar@507
   779
          Node n=g.addNode();
alpar@507
   780
          nodes.push_back(n);
alpar@507
   781
          coords[n]=center+rnd.disc()*area*
alpar@507
   782
            std::sqrt(sizes[s]/sum_sizes);
alpar@507
   783
        }
alpar@507
   784
    }
alpar@507
   785
alpar@507
   786
//   for (ListGraph::NodeIt n(g); n != INVALID; ++n) {
alpar@507
   787
//     std::cerr << coords[n] << std::endl;
alpar@507
   788
//   }
alpar@507
   789
alpar@507
   790
  if(ap["tsp"]) {
alpar@507
   791
    tsp();
alpar@507
   792
    std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
alpar@507
   793
  }
alpar@507
   794
  if(ap["tsp2"]) {
alpar@507
   795
    tsp2();
alpar@507
   796
    std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
alpar@507
   797
  }
alpar@507
   798
  else if(ap["2con"]) {
alpar@507
   799
    std::cout << "Make triangles\n";
alpar@507
   800
    //   triangle();
alpar@507
   801
    sparseTriangle(ap["g"]);
alpar@507
   802
    std::cout << "Make it sparser\n";
alpar@507
   803
    sparse2(ap["g"]);
alpar@507
   804
  }
alpar@507
   805
  else if(ap["tree"]) {
alpar@507
   806
    minTree();
alpar@507
   807
  }
alpar@507
   808
  else if(ap["dela"]) {
alpar@507
   809
    delaunay();
alpar@507
   810
  }
alpar@507
   811
alpar@507
   812
alpar@507
   813
  std::cout << "Number of nodes    : " << countNodes(g) << std::endl;
alpar@507
   814
  std::cout << "Number of arcs    : " << countEdges(g) << std::endl;
alpar@507
   815
  double tlen=0;
alpar@507
   816
  for(EdgeIt e(g);e!=INVALID;++e)
alpar@507
   817
    tlen+=sqrt((coords[g.v(e)]-coords[g.u(e)]).normSquare());
alpar@507
   818
  std::cout << "Total arc length  : " << tlen << std::endl;
alpar@507
   819
alpar@507
   820
  if(ap["eps"])
alpar@507
   821
    graphToEps(g,prefix+".eps").scaleToA4().
alpar@507
   822
      scale(600).nodeScale(.005).arcWidthScale(.001).preScale(false).
alpar@508
   823
      coords(coords).hideNodes(ap.given("nonodes")).run();
alpar@507
   824
alpar@507
   825
  if(ap["dir"])
alpar@507
   826
    DigraphWriter<ListGraph>(g,prefix+".lgf").
alpar@507
   827
      nodeMap("coordinates_x",scaleMap(xMap(coords),600)).
alpar@507
   828
      nodeMap("coordinates_y",scaleMap(yMap(coords),600)).
alpar@507
   829
      run();
alpar@507
   830
  else GraphWriter<ListGraph>(g,prefix+".lgf").
alpar@507
   831
         nodeMap("coordinates_x",scaleMap(xMap(coords),600)).
alpar@507
   832
         nodeMap("coordinates_y",scaleMap(yMap(coords),600)).
alpar@507
   833
         run();
alpar@507
   834
}
alpar@507
   835