tools/lgf-gen.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 623 7c1324b35d89
child 1109 89e1877e335f
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

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