tools/lgf-gen.cc
author alpar
Tue, 05 Jun 2007 17:24:35 +0000
changeset 2449 1d685ac667ec
parent 2447 260ce674cc65
child 2453 2800d9efb01d
permissions -rw-r--r--
Minor improvement in Tutorial
     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 
    35 using namespace lemon;
    36 
    37 typedef dim2::Point<double> Point;
    38 
    39 UGRAPH_TYPEDEFS(ListUGraph);
    40 
    41 bool progress=true;
    42 
    43 int N;
    44 // int girth;
    45 
    46 ListUGraph g;
    47 
    48 std::vector<Node> nodes;
    49 ListUGraph::NodeMap<Point> coords(g);
    50 
    51 
    52 double 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 
    59 int tsp_impr_num=0;
    60 
    61 const double EPSILON=1e-8; 
    62 bool 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 
    87 bool 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 
    94 void 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 
   104 void tsp()
   105 {
   106   for(int i=0;i<N;i++) g.addEdge(nodes[i],nodes[(i+1)%N]);
   107   tsp_improve();
   108 }
   109 
   110 class Line
   111 {
   112 public:
   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   
   121 inline std::ostream& operator<<(std::ostream &os, const Line &l)
   122 {
   123   os << l.a << "->" << l.b;
   124   return os;
   125 }
   126 
   127 bool 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 
   135 struct Pedge
   136 {
   137   Node a;
   138   Node b;
   139   double len;
   140 };
   141 
   142 bool pedgeLess(Pedge a,Pedge b)
   143 {
   144   return a.len<b.len;
   145 }
   146 
   147 std::vector<UEdge> edges;
   148 
   149 namespace _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 
   248 inline 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 
   424 void 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 
   441 void 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 
   460 void 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 
   495 template <typename UGraph, typename CoordMap>
   496 class LengthSquareMap {
   497 public:
   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 
   509 private:
   510 
   511   const UGraph& _ugraph;
   512   const CoordMap& _coords;
   513 };
   514 
   515 void 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 
   535 void 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 
   642 int 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