COIN-OR::LEMON - Graph Library

source: lemon-0.x/tools/lgf-gen.cc @ 2448:ab899ae3505f

Last change on this file since 2448:ab899ae3505f was 2448:ab899ae3505f, checked in by Alpar Juttner, 17 years ago

Bugfix and improvement in -tsp2 algorithm

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