COIN-OR::LEMON - Graph Library

source: lemon-0.x/tools/lgf-gen.cc @ 2447:260ce674cc65

Last change on this file since 2447:260ce674cc65 was 2447:260ce674cc65, checked in by Balazs Dezso, 17 years ago

Delaunay triangulation
Faster geometric minimum spanning tree

File size: 20.2 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
535Node common(UEdge e, UEdge f)
536{
537  return (g.source(e)==g.source(f)||g.source(e)==g.target(f))?
538        g.source(e):g.target(e);
539}
540
541void tsp2()
542{
543  std::cout << "Find a tree..." << std::endl;
544
545  minTree();
546
547  std::cout << "Total edge length (tree) : " << totalLen() << std::endl;
548
549  std::cout << "Make it Euler..." << std::endl;
550
551  {
552    std::vector<Node> leafs;
553    for(NodeIt n(g);n!=INVALID;++n)
554      if(countIncEdges(g,n)%2==1) leafs.push_back(n);
555    for(unsigned int i=0;i<leafs.size();i+=2)
556      g.addEdge(leafs[i],leafs[i+1]);
557  }
558
559  for(NodeIt n(g);n!=INVALID;++n)
560    if(countIncEdges(g,n)%2)
561      std::cout << "GEBASZ!!!" << std::endl;
562 
563  std::cout << "Number of edges : " << countUEdges(g) << std::endl;
564
565//   for(NodeIt n(g);n!=INVALID;++n)
566//     if(countIncEdges(g,n)>2)
567//       std::cout << "+";
568//   std::cout << std::endl;
569 
570  std::cout << "Total edge length (euler) : " << totalLen() << std::endl;
571
572  ListUGraph::UEdgeMap<UEdge> enext(g);
573  {
574    UEulerIt<ListUGraph> e(g);
575    UEdge eo=e;
576    UEdge ef=e;
577//     std::cout << "Tour edge: " << g.id(UEdge(e)) << std::endl;     
578    for(++e;e!=INVALID;++e)
579      {
580//      std::cout << "Tour edge: " << g.id(UEdge(e)) << std::endl;     
581        enext[eo]=e;
582        eo=e;
583      }
584    enext[eo]=ef;
585  }
586 
587  std::cout << "Creating a tour from that..." << std::endl;
588 
589  int nnum = countNodes(g);
590  int ednum = countUEdges(g);
591 
592  for(UEdge p=UEdgeIt(g);ednum>nnum;p=enext[p])
593    {
594//       std::cout << "Checking edge " << g.id(p) << std::endl;     
595      UEdge e=enext[p];
596      UEdge f=enext[e];
597      Node n2=common(e,f);
598      Node n1=g.oppositeNode(n2,e);
599      Node n3=g.oppositeNode(n2,f);
600      if(countIncEdges(g,n2)>2)
601        {
602//        std::cout << "Remove an Edge" << std::endl;
603          UEdge ff=enext[f];
604          g.erase(e);
605          g.erase(f);
606          UEdge ne=g.addEdge(n1,n3);
607          enext[p]=ne;
608          enext[ne]=ff;
609          ednum--;
610        }
611    }
612
613  std::cout << "Total edge length (tour) : " << totalLen() << std::endl;
614
615  tsp_improve();
616 
617  std::cout << "Total edge length (2-opt tour) : " << totalLen() << std::endl;
618}
619
620
621int main(int argc,const char **argv)
622{
623  ArgParser ap(argc,argv);
624
625//   bool eps;
626  bool disc_d, square_d, gauss_d;
627//   bool tsp_a,two_a,tree_a;
628  int num_of_cities=1;
629  double area=1;
630  N=100;
631//   girth=10;
632  std::string ndist("disc");
633  ap.refOption("n", "Number of nodes (default is 100)", N)
634    .intOption("g", "Girth parameter (default is 10)", 10)
635    .refOption("cities", "Number of cities (default is 1)", num_of_cities)
636    .refOption("area", "Full relative area of the cities (default is 1)", area)
637    .refOption("disc", "Nodes are evenly distributed on a unit disc (default)",disc_d)
638    .optionGroup("dist", "disc")
639    .refOption("square", "Nodes are evenly distributed on a unit square", square_d)
640    .optionGroup("dist", "square")
641    .refOption("gauss",
642            "Nodes are located according to a two-dim gauss distribution",
643            gauss_d)
644    .optionGroup("dist", "gauss")
645//     .mandatoryGroup("dist")
646    .onlyOneGroup("dist")
647    .boolOption("eps", "Also generate .eps output (prefix.eps)")
648    .boolOption("dir", "Directed graph is generated (each edges are replaced by two directed ones)")
649    .boolOption("2con", "Create a two connected planar graph")
650    .optionGroup("alg","2con")
651    .boolOption("tree", "Create a min. cost spanning tree")
652    .optionGroup("alg","tree")
653    .boolOption("tsp", "Create a TSP tour")
654    .optionGroup("alg","tsp")
655    .boolOption("tsp2", "Create a TSP tour (tree based)")
656    .optionGroup("alg","tsp2")
657    .boolOption("dela", "Delaunay triangulation graph")
658    .optionGroup("alg","dela")
659    .onlyOneGroup("alg")
660    .boolOption("rand", "Use time seed for random number generator")
661    .optionGroup("rand", "rand")
662    .intOption("seed", "Random seed", -1)
663    .optionGroup("rand", "seed")
664    .onlyOneGroup("rand")
665    .other("[prefix]","Prefix of the output files. Default is 'lgf-gen-out'")
666    .run();
667
668  if (ap["rand"]) {
669    int seed = time(0);
670    std::cout << "Random number seed: " << seed << std::endl;
671    rnd = Random(seed);
672  }
673  if (ap.given("seed")) {
674    int seed = ap["seed"];
675    std::cout << "Random number seed: " << seed << std::endl;
676    rnd = Random(seed);
677  }
678 
679  std::string prefix;
680  switch(ap.files().size())
681    {
682    case 0:
683      prefix="lgf-gen-out";
684      break;
685    case 1:
686      prefix=ap.files()[0];
687      break;
688    default:
689      std::cerr << "\nAt most one prefix can be given\n\n";
690      exit(1);
691    }
692 
693  double sum_sizes=0;
694  std::vector<double> sizes;
695  std::vector<double> cum_sizes;
696  for(int s=0;s<num_of_cities;s++)
697    {
698      //        sum_sizes+=rnd.exponential();
699      double d=rnd();
700      sum_sizes+=d;
701      sizes.push_back(d);
702      cum_sizes.push_back(sum_sizes);
703    }
704  int i=0;
705  for(int s=0;s<num_of_cities;s++)
706    {
707      Point center=(num_of_cities==1?Point(0,0):rnd.disc());
708      if(gauss_d)
709        for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
710          Node n=g.addNode();
711          nodes.push_back(n);
712          coords[n]=center+rnd.gauss2()*area*
713            std::sqrt(sizes[s]/sum_sizes);
714        }
715      else if(square_d)
716        for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
717          Node n=g.addNode();
718          nodes.push_back(n);
719          coords[n]=center+Point(rnd()*2-1,rnd()*2-1)*area*
720            std::sqrt(sizes[s]/sum_sizes);
721        }
722      else if(disc_d || true)
723        for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
724          Node n=g.addNode();
725          nodes.push_back(n);
726          coords[n]=center+rnd.disc()*area*
727            std::sqrt(sizes[s]/sum_sizes);
728        }
729    }
730
731//   for (ListUGraph::NodeIt n(g); n != INVALID; ++n) {
732//     std::cerr << coords[n] << std::endl;
733//   }
734 
735  if(ap["tsp"]) {
736    tsp();
737    std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
738  }
739  if(ap["tsp2"]) {
740    tsp2();
741    std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
742  }
743  else if(ap["2con"]) {
744    std::cout << "Make triangles\n";
745    //   triangle();
746    sparseTriangle(ap["g"]);
747    std::cout << "Make it sparser\n";
748    sparse2(ap["g"]);
749  }
750  else if(ap["tree"]) {
751    minTree();
752  }
753  else if(ap["dela"]) {
754    delaunay();
755  }
756 
757
758  std::cout << "Number of nodes    : " << countNodes(g) << std::endl;
759  std::cout << "Number of edges    : " << countUEdges(g) << std::endl;
760  double tlen=0;
761  for(UEdgeIt e(g);e!=INVALID;++e)
762    tlen+=sqrt((coords[g.source(e)]-coords[g.target(e)]).normSquare());
763  std::cout << "Total edge length  : " << tlen << std::endl;
764  if(ap["eps"])
765    graphToEps(g,prefix+".eps").
766      scale(600).nodeScale(.2).edgeWidthScale(.001).preScale(false).
767      coords(coords).run();
768
769  if(ap["dir"])
770    GraphWriter<ListUGraph>(prefix+".lgf",g).
771      writeNodeMap("coordinates_x",scaleMap(xMap(coords),600)).
772      writeNodeMap("coordinates_y",scaleMap(yMap(coords),600)).
773      run();
774  else UGraphWriter<ListUGraph>(prefix+".lgf",g).
775         writeNodeMap("coordinates_x",scaleMap(xMap(coords),600)).
776         writeNodeMap("coordinates_y",scaleMap(yMap(coords),600)).
777         run();
778}
779
Note: See TracBrowser for help on using the repository browser.