COIN-OR::LEMON - Graph Library

source: lemon-0.x/tools/lgf-gen.cc @ 2391:14a343be7a5a

Last change on this file since 2391:14a343be7a5a was 2391:14a343be7a5a, checked in by Alpar Juttner, 17 years ago

Happy New Year to all source files!

File size: 9.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 <cmath>
30#include <algorithm>
31#include <lemon/unionfind.h>
32
33using namespace lemon;
34
35typedef dim2::Point<double> Point;
36
37UGRAPH_TYPEDEFS(ListUGraph);
38
39int N;
40int girth;
41
42ListUGraph g;
43
44std::vector<Node> nodes;
45ListUGraph::NodeMap<Point> coords(g);
46
47int tsp_impr_num=0;
48
49const double EPSILON=1e-8;
50bool tsp_improve(Node u, Node v)
51{
52  double luv=std::sqrt((coords[v]-coords[u]).normSquare());
53  Node u2=u;
54  Node v2=v;
55  do {
56    Node n;
57    for(IncEdgeIt e(g,v2);(n=g.runningNode(e))==u2;++e);
58    u2=v2;
59    v2=n;
60    if(luv+std::sqrt((coords[v2]-coords[u2]).normSquare())-EPSILON>
61       std::sqrt((coords[u]-coords[u2]).normSquare())+
62       std::sqrt((coords[v]-coords[v2]).normSquare()))
63      {
64        g.erase(findUEdge(g,u,v));
65        g.erase(findUEdge(g,u2,v2));
66        g.addEdge(u2,u);
67        g.addEdge(v,v2);
68        tsp_impr_num++;
69        return true;
70      }
71  } while(v2!=u);
72  return false;
73}
74
75bool tsp_improve(Node u)
76{
77  for(IncEdgeIt e(g,u);e!=INVALID;++e)
78    if(tsp_improve(u,g.runningNode(e))) return true;
79  return false;
80}
81
82void tsp_improve()
83{
84  bool b;
85  do {
86    b=false;
87    for(NodeIt n(g);n!=INVALID;++n)
88      if(tsp_improve(n)) b=true;
89  } while(b);
90}
91
92void tsp()
93{
94  for(int i=0;i<N;i++) g.addEdge(nodes[i],nodes[(i+1)%N]);
95  tsp_improve();
96}
97
98class Line
99{
100public:
101  Point a;
102  Point b;
103  Line(Point _a,Point _b) :a(_a),b(_b) {}
104  Line(Node _a,Node _b) : a(coords[_a]),b(coords[_b]) {}
105  Line(const Edge &e) : a(coords[g.source(e)]),b(coords[g.target(e)]) {}
106  Line(const UEdge &e) : a(coords[g.source(e)]),b(coords[g.target(e)]) {}
107};
108 
109inline std::ostream& operator<<(std::ostream &os, const Line &l)
110{
111  os << l.a << "->" << l.b;
112  return os;
113}
114
115bool cross(Line a, Line b)
116{
117  Point ao=rot90(a.b-a.a);
118  Point bo=rot90(b.b-b.a);
119  return (ao*(b.a-a.a))*(ao*(b.b-a.a))<0 &&
120    (bo*(a.a-b.a))*(bo*(a.b-b.a))<0;
121}
122
123struct Pedge
124{
125  Node a;
126  Node b;
127  double len;
128};
129
130bool pedgeLess(Pedge a,Pedge b)
131{
132  return a.len<b.len;
133}
134
135std::vector<UEdge> edges;
136
137void triangle()
138{
139  Counter cnt("Number of edges added: ");
140  std::vector<Pedge> pedges;
141  for(NodeIt n(g);n!=INVALID;++n)
142    for(NodeIt m=++(NodeIt(n));m!=INVALID;++m)
143      {
144        Pedge p;
145        p.a=n;
146        p.b=m;
147        p.len=(coords[m]-coords[n]).normSquare();
148        pedges.push_back(p);
149      }
150  std::sort(pedges.begin(),pedges.end(),pedgeLess);
151  for(std::vector<Pedge>::iterator pi=pedges.begin();pi!=pedges.end();++pi)
152    {
153      Line li(pi->a,pi->b);
154      UEdgeIt e(g);
155      for(;e!=INVALID && !cross(e,li);++e) ;
156      UEdge ne;
157      if(e==INVALID) {
158        ne=g.addEdge(pi->a,pi->b);
159        edges.push_back(ne);
160        cnt++;
161      }
162    }
163}
164
165void sparse(int d)
166{
167  Counter cnt("Number of edges removed: ");
168  Bfs<ListUGraph> bfs(g);
169  for(std::vector<UEdge>::reverse_iterator ei=edges.rbegin();
170      ei!=edges.rend();++ei)
171    {
172      Node a=g.source(*ei);
173      Node b=g.target(*ei);
174      g.erase(*ei);
175      bfs.run(a,b);
176      if(bfs.predEdge(b)==INVALID || bfs.dist(b)>d)
177        g.addEdge(a,b);
178      else cnt++;
179    }
180}
181
182void sparse2(int d)
183{
184  Counter cnt("Number of edges removed: ");
185  for(std::vector<UEdge>::reverse_iterator ei=edges.rbegin();
186      ei!=edges.rend();++ei)
187    {
188      Node a=g.source(*ei);
189      Node b=g.target(*ei);
190      g.erase(*ei);
191      ConstMap<Edge,int> cegy(1);
192      Suurballe<ListUGraph,ConstMap<Edge,int> > sur(g,cegy,a,b);
193      int k=sur.run(2);
194      if(k<2 || sur.totalLength()>d)
195        g.addEdge(a,b);
196      else cnt++;
197//       else std::cout << "Remove edge " << g.id(a) << "-" << g.id(b) << '\n';
198    }
199}
200
201void sparseTriangle(int d)
202{
203  Counter cnt("Number of edges added: ");
204  std::vector<Pedge> pedges;
205  for(NodeIt n(g);n!=INVALID;++n)
206    for(NodeIt m=++(NodeIt(n));m!=INVALID;++m)
207      {
208        Pedge p;
209        p.a=n;
210        p.b=m;
211        p.len=(coords[m]-coords[n]).normSquare();
212        pedges.push_back(p);
213      }
214  std::sort(pedges.begin(),pedges.end(),pedgeLess);
215  for(std::vector<Pedge>::iterator pi=pedges.begin();pi!=pedges.end();++pi)
216    {
217      Line li(pi->a,pi->b);
218      UEdgeIt e(g);
219      for(;e!=INVALID && !cross(e,li);++e) ;
220      UEdge ne;
221      if(e==INVALID) {
222        ConstMap<Edge,int> cegy(1);
223        Suurballe<ListUGraph,ConstMap<Edge,int> >
224          sur(g,cegy,pi->a,pi->b);
225        int k=sur.run(2);
226        if(k<2 || sur.totalLength()>d)
227          {
228            ne=g.addEdge(pi->a,pi->b);
229            edges.push_back(ne);
230            cnt++;
231          }
232      }
233    }
234}
235
236void minTree() {
237  std::vector<Pedge> pedges;
238  for(NodeIt n(g);n!=INVALID;++n)
239    for(NodeIt m=++(NodeIt(n));m!=INVALID;++m)
240      {
241        Pedge p;
242        p.a=n;
243        p.b=m;
244        p.len=(coords[m]-coords[n]).normSquare();
245        pedges.push_back(p);
246      }
247  std::sort(pedges.begin(),pedges.end(),pedgeLess);
248  ListUGraph::NodeMap<int> comp(g);
249  UnionFind<ListUGraph::NodeMap<int> > uf(comp);
250  for (NodeIt it(g); it != INVALID; ++it)
251    uf.insert(it);
252
253  int en=0;
254  for(std::vector<Pedge>::iterator pi=pedges.begin();pi!=pedges.end();++pi)
255    {
256      if ( uf.join(pi->a,pi->b) ) {
257        g.addEdge(pi->a,pi->b);
258        en++;
259        if(en>=N-1) return;
260      }
261    }
262}
263
264
265
266int main(int argc,char **argv)
267{
268  ArgParser ap(argc,argv);
269
270  bool eps;
271  bool disc_d, square_d, gauss_d;
272  bool tsp_a,two_a,tree_a;
273  int num_of_cities=1;
274  double area=1;
275  N=100;
276  girth=10;
277  std::string ndist("disc");
278  ap.option("n", "Number of nodes (default is 100)", N)
279    .option("g", "Girth parameter (default is 10)", girth)
280    .option("cities", "Number of cities (default is 1)", num_of_cities)
281    .option("area", "Full relative area of the cities (default is 1)", area)
282    .option("disc", "Nodes are evenly distributed on a unit disc (default)",disc_d)
283    .optionGroup("dist", "disc")
284    .option("square", "Nodes are evenly distributed on a unit square", square_d)
285    .optionGroup("dist", "square")
286    .option("gauss",
287            "Nodes are located according to a two-dim gauss distribution",
288            gauss_d)
289    .optionGroup("dist", "gauss")
290//     .mandatoryGroup("dist")
291    .onlyOneGroup("dist")
292    .option("eps", "Also generate .eps output (prefix.eps)",eps)
293    .option("2con", "Create a two connected planar graph",two_a)
294    .optionGroup("alg","2con")
295    .option("tree", "Create a min. cost spanning tree",tree_a)
296    .optionGroup("alg","tree")
297    .option("tsp", "Create a TSP tour",tsp_a)
298    .optionGroup("alg","tsp")
299    .onlyOneGroup("alg")
300    .other("[prefix]","Prefix of the output files. Default is 'lgf-gen-out'")
301    .run();
302 
303  std::string prefix;
304  switch(ap.files().size())
305    {
306    case 0:
307      prefix="lgf-gen-out";
308      break;
309    case 1:
310      prefix=ap.files()[0];
311      break;
312    default:
313      std::cerr << "\nAt most one prefix can be given\n\n";
314      exit(1);
315    }
316 
317  double sum_sizes=0;
318  std::vector<double> sizes;
319  std::vector<double> cum_sizes;
320  for(int s=0;s<num_of_cities;s++)
321    {
322      //        sum_sizes+=rnd.exponential();
323      double d=rnd();
324      sum_sizes+=d;
325      sizes.push_back(d);
326      cum_sizes.push_back(sum_sizes);
327    }
328  int i=0;
329  for(int s=0;s<num_of_cities;s++)
330    {
331      Point center=(num_of_cities==1?Point(0,0):rnd.disc());
332      if(gauss_d)
333        for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
334          Node n=g.addNode();
335          nodes.push_back(n);
336          coords[n]=center+rnd.gauss2()*area*
337            std::sqrt(sizes[s]/sum_sizes);
338        }
339      else if(square_d)
340        for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
341          Node n=g.addNode();
342          nodes.push_back(n);
343          coords[n]=center+Point(rnd()*2-1,rnd()*2-1)*area*
344            std::sqrt(sizes[s]/sum_sizes);
345        }
346      else if(disc_d || true)
347        for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
348          Node n=g.addNode();
349          nodes.push_back(n);
350          coords[n]=center+rnd.disc()*area*
351            std::sqrt(sizes[s]/sum_sizes);
352        }
353    }
354 
355  if(tsp_a) {
356    tsp();
357    std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
358  }
359  else if(two_a) {
360    std::cout << "Make triangles\n";
361    //   triangle();
362    sparseTriangle(girth);
363    std::cout << "Make it sparser\n";
364    sparse2(girth);
365  }
366  else if(tree_a) {
367    minTree();
368  }
369 
370
371  std::cout << "Number of nodes    : " << countNodes(g) << std::endl;
372  std::cout << "Number of edges    : " << countUEdges(g) << std::endl;
373  double tlen=0;
374  for(UEdgeIt e(g);e!=INVALID;++e)
375    tlen+=sqrt((coords[g.source(e)]-coords[g.target(e)]).normSquare());
376  std::cout << "Total edge length  : " << tlen << std::endl;
377  if(eps)
378    graphToEps(g,prefix+".eps").
379      scale(600).nodeScale(.2).edgeWidthScale(.001).preScale(false).
380      coords(coords).run();
381
382  UGraphWriter<ListUGraph>(prefix+".lgf",g).
383    writeNodeMap("coordinates_x",scaleMap(xMap(coords),600)).
384    writeNodeMap("coordinates_y",scaleMap(yMap(coords),600)).
385    run();
386}
387
Note: See TracBrowser for help on using the repository browser.