1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2009
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
21 /// \brief Special plane digraph generator.
23 /// Graph generator application for various types of plane graphs.
29 /// for more info on the usage.
36 #include <lemon/list_graph.h>
37 #include <lemon/random.h>
38 #include <lemon/dim2.h>
39 #include <lemon/bfs.h>
40 #include <lemon/counter.h>
41 #include <lemon/suurballe.h>
42 #include <lemon/graph_to_eps.h>
43 #include <lemon/lgf_writer.h>
44 #include <lemon/arg_parser.h>
45 #include <lemon/euler.h>
46 #include <lemon/math.h>
47 #include <lemon/kruskal.h>
48 #include <lemon/time_measure.h>
50 using namespace lemon;
52 typedef dim2::Point<double> Point;
54 GRAPH_TYPEDEFS(ListGraph);
63 std::vector<Node> nodes;
64 ListGraph::NodeMap<Point> coords(g);
69 for(EdgeIt e(g);e!=INVALID;++e)
70 tlen+=sqrt((coords[g.v(e)]-coords[g.u(e)]).normSquare());
76 const double EPSILON=1e-8;
77 bool tsp_improve(Node u, Node v)
79 double luv=std::sqrt((coords[v]-coords[u]).normSquare());
84 for(IncEdgeIt e(g,v2);(n=g.runningNode(e))==u2;++e) { }
87 if(luv+std::sqrt((coords[v2]-coords[u2]).normSquare())-EPSILON>
88 std::sqrt((coords[u]-coords[u2]).normSquare())+
89 std::sqrt((coords[v]-coords[v2]).normSquare()))
91 g.erase(findEdge(g,u,v));
92 g.erase(findEdge(g,u2,v2));
102 bool tsp_improve(Node u)
104 for(IncEdgeIt e(g,u);e!=INVALID;++e)
105 if(tsp_improve(u,g.runningNode(e))) return true;
114 for(NodeIt n(g);n!=INVALID;++n)
115 if(tsp_improve(n)) b=true;
121 for(int i=0;i<N;i++) g.addEdge(nodes[i],nodes[(i+1)%N]);
130 Line(Point _a,Point _b) :a(_a),b(_b) {}
131 Line(Node _a,Node _b) : a(coords[_a]),b(coords[_b]) {}
132 Line(const Arc &e) : a(coords[g.source(e)]),b(coords[g.target(e)]) {}
133 Line(const Edge &e) : a(coords[g.u(e)]),b(coords[g.v(e)]) {}
136 inline std::ostream& operator<<(std::ostream &os, const Line &l)
138 os << l.a << "->" << l.b;
142 bool cross(Line a, Line b)
144 Point ao=rot90(a.b-a.a);
145 Point bo=rot90(b.b-b.a);
146 return (ao*(b.a-a.a))*(ao*(b.b-a.a))<0 &&
147 (bo*(a.a-b.a))*(bo*(a.b-b.a))<0;
157 bool pedgeLess(Parc a,Parc b)
162 std::vector<Edge> arcs;
164 namespace _delaunay_bits {
167 int prev, curr, next;
169 Part(int p, int c, int n) : prev(p), curr(c), next(n) {}
172 inline std::ostream& operator<<(std::ostream& os, const Part& part) {
173 os << '(' << part.prev << ',' << part.curr << ',' << part.next << ')';
177 inline double circle_point(const Point& p, const Point& q, const Point& r) {
178 double a = p.x * (q.y - r.y) + q.x * (r.y - p.y) + r.x * (p.y - q.y);
179 if (a == 0) return std::numeric_limits<double>::quiet_NaN();
181 double d = (p.x * p.x + p.y * p.y) * (q.y - r.y) +
182 (q.x * q.x + q.y * q.y) * (r.y - p.y) +
183 (r.x * r.x + r.y * r.y) * (p.y - q.y);
185 double e = (p.x * p.x + p.y * p.y) * (q.x - r.x) +
186 (q.x * q.x + q.y * q.y) * (r.x - p.x) +
187 (r.x * r.x + r.y * r.y) * (p.x - q.x);
189 double f = (p.x * p.x + p.y * p.y) * (q.x * r.y - r.x * q.y) +
190 (q.x * q.x + q.y * q.y) * (r.x * p.y - p.x * r.y) +
191 (r.x * r.x + r.y * r.y) * (p.x * q.y - q.x * p.y);
193 return d / (2 * a) + sqrt((d * d + e * e) / (4 * a * a) + f / a);
196 inline bool circle_form(const Point& p, const Point& q, const Point& r) {
197 return rot90(q - p) * (r - q) < 0.0;
200 inline double intersection(const Point& p, const Point& q, double sx) {
201 const double epsilon = 1e-8;
203 if (p.x == q.x) return (p.y + q.y) / 2.0;
205 if (sx < p.x + epsilon) return p.y;
206 if (sx < q.x + epsilon) return q.y;
208 double a = q.x - p.x;
209 double b = (q.x - sx) * p.y - (p.x - sx) * q.y;
210 double d = (q.x - sx) * (p.x - sx) * (p - q).normSquare();
211 return (b - sqrt(d)) / a;
217 YLess(const std::vector<Point>& points, double& sweep)
218 : _points(points), _sweep(sweep) {}
220 bool operator()(const Part& l, const Part& r) const {
221 const double epsilon = 1e-8;
223 // std::cerr << l << " vs " << r << std::endl;
224 double lbx = l.prev != -1 ?
225 intersection(_points[l.prev], _points[l.curr], _sweep) :
226 - std::numeric_limits<double>::infinity();
227 double rbx = r.prev != -1 ?
228 intersection(_points[r.prev], _points[r.curr], _sweep) :
229 - std::numeric_limits<double>::infinity();
230 double lex = l.next != -1 ?
231 intersection(_points[l.curr], _points[l.next], _sweep) :
232 std::numeric_limits<double>::infinity();
233 double rex = r.next != -1 ?
234 intersection(_points[r.curr], _points[r.next], _sweep) :
235 std::numeric_limits<double>::infinity();
237 if (lbx > lex) std::swap(lbx, lex);
238 if (rbx > rex) std::swap(rbx, rex);
240 if (lex < epsilon + rex && lbx + epsilon < rex) return true;
241 if (rex < epsilon + lex && rbx + epsilon < lex) return false;
245 const std::vector<Point>& _points;
251 typedef std::multimap<double, BeachIt> SpikeHeap;
253 typedef std::multimap<Part, SpikeHeap::iterator, YLess> Beach;
258 BeachIt(Beach::iterator iter) : it(iter) {}
263 inline void delaunay() {
264 Counter cnt("Number of arcs added: ");
266 using namespace _delaunay_bits;
268 typedef _delaunay_bits::Part Part;
269 typedef std::vector<std::pair<double, int> > SiteHeap;
272 std::vector<Point> points;
273 std::vector<Node> nodes;
275 for (NodeIt it(g); it != INVALID; ++it) {
277 points.push_back(coords[it]);
280 SiteHeap siteheap(points.size());
285 for (int i = 0; i < int(siteheap.size()); ++i) {
286 siteheap[i] = std::make_pair(points[i].x, i);
289 std::sort(siteheap.begin(), siteheap.end());
290 sweep = siteheap.front().first;
292 YLess yless(points, sweep);
297 std::set<std::pair<int, int> > arcs;
303 while (siteindex < int(siteheap.size()) &&
304 siteheap[0].first == siteheap[siteindex].first) {
305 front.push_back(std::make_pair(points[siteheap[siteindex].second].y,
306 siteheap[siteindex].second));
310 std::sort(front.begin(), front.end());
312 for (int i = 0; i < int(front.size()); ++i) {
313 int prev = (i == 0 ? -1 : front[i - 1].second);
314 int curr = front[i].second;
315 int next = (i + 1 == int(front.size()) ? -1 : front[i + 1].second);
317 beach.insert(std::make_pair(Part(prev, curr, next),
322 while (siteindex < int(points.size()) || !spikeheap.empty()) {
324 SpikeHeap::iterator spit = spikeheap.begin();
326 if (siteindex < int(points.size()) &&
327 (spit == spikeheap.end() || siteheap[siteindex].first < spit->first)) {
328 int site = siteheap[siteindex].second;
329 sweep = siteheap[siteindex].first;
331 Beach::iterator bit = beach.upper_bound(Part(site, site, site));
333 if (bit->second != spikeheap.end()) {
334 spikeheap.erase(bit->second);
337 int prev = bit->first.prev;
338 int curr = bit->first.curr;
339 int next = bit->first.next;
343 SpikeHeap::iterator pit = spikeheap.end();
345 circle_form(points[prev], points[curr], points[site])) {
346 double x = circle_point(points[prev], points[curr], points[site]);
347 pit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
349 beach.insert(std::make_pair(Part(prev, curr, site), pit));
351 beach.insert(std::make_pair(Part(prev, curr, site), pit));
354 beach.insert(std::make_pair(Part(curr, site, curr), spikeheap.end()));
356 SpikeHeap::iterator nit = spikeheap.end();
358 circle_form(points[site], points[curr],points[next])) {
359 double x = circle_point(points[site], points[curr], points[next]);
360 nit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
362 beach.insert(std::make_pair(Part(site, curr, next), nit));
364 beach.insert(std::make_pair(Part(site, curr, next), nit));
371 Beach::iterator bit = spit->second.it;
373 int prev = bit->first.prev;
374 int curr = bit->first.curr;
375 int next = bit->first.next;
378 std::pair<int, int> arc;
381 std::make_pair(prev, curr) : std::make_pair(curr, prev);
383 if (arcs.find(arc) == arcs.end()) {
385 g.addEdge(nodes[prev], nodes[curr]);
390 std::make_pair(curr, next) : std::make_pair(next, curr);
392 if (arcs.find(arc) == arcs.end()) {
394 g.addEdge(nodes[curr], nodes[next]);
399 Beach::iterator pbit = bit; --pbit;
400 int ppv = pbit->first.prev;
401 Beach::iterator nbit = bit; ++nbit;
402 int nnt = nbit->first.next;
404 if (bit->second != spikeheap.end()) spikeheap.erase(bit->second);
405 if (pbit->second != spikeheap.end()) spikeheap.erase(pbit->second);
406 if (nbit->second != spikeheap.end()) spikeheap.erase(nbit->second);
412 SpikeHeap::iterator pit = spikeheap.end();
413 if (ppv != -1 && ppv != next &&
414 circle_form(points[ppv], points[prev], points[next])) {
415 double x = circle_point(points[ppv], points[prev], points[next]);
416 if (x < sweep) x = sweep;
417 pit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
419 beach.insert(std::make_pair(Part(ppv, prev, next), pit));
421 beach.insert(std::make_pair(Part(ppv, prev, next), pit));
424 SpikeHeap::iterator nit = spikeheap.end();
425 if (nnt != -1 && prev != nnt &&
426 circle_form(points[prev], points[next], points[nnt])) {
427 double x = circle_point(points[prev], points[next], points[nnt]);
428 if (x < sweep) x = sweep;
429 nit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
431 beach.insert(std::make_pair(Part(prev, next, nnt), nit));
433 beach.insert(std::make_pair(Part(prev, next, nnt), nit));
439 for (Beach::iterator it = beach.begin(); it != beach.end(); ++it) {
440 int curr = it->first.curr;
441 int next = it->first.next;
443 if (next == -1) continue;
445 std::pair<int, int> arc;
448 std::make_pair(curr, next) : std::make_pair(next, curr);
450 if (arcs.find(arc) == arcs.end()) {
452 g.addEdge(nodes[curr], nodes[next]);
460 Counter cnt("Number of arcs removed: ");
461 Bfs<ListGraph> bfs(g);
462 for(std::vector<Edge>::reverse_iterator ei=arcs.rbegin();
463 ei!=arcs.rend();++ei)
469 if(bfs.predArc(b)==INVALID || bfs.dist(b)>d)
477 Counter cnt("Number of arcs removed: ");
478 for(std::vector<Edge>::reverse_iterator ei=arcs.rbegin();
479 ei!=arcs.rend();++ei)
484 ConstMap<Arc,int> cegy(1);
485 Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy,a,b);
487 if(k<2 || sur.totalLength()>d)
490 // else std::cout << "Remove arc " << g.id(a) << "-" << g.id(b) << '\n';
494 void sparseTriangle(int d)
496 Counter cnt("Number of arcs added: ");
497 std::vector<Parc> pedges;
498 for(NodeIt n(g);n!=INVALID;++n)
499 for(NodeIt m=++(NodeIt(n));m!=INVALID;++m)
504 p.len=(coords[m]-coords[n]).normSquare();
507 std::sort(pedges.begin(),pedges.end(),pedgeLess);
508 for(std::vector<Parc>::iterator pi=pedges.begin();pi!=pedges.end();++pi)
510 Line li(pi->a,pi->b);
512 for(;e!=INVALID && !cross(e,li);++e) ;
515 ConstMap<Arc,int> cegy(1);
516 Suurballe<ListGraph,ConstMap<Arc,int> >
517 sur(g,cegy,pi->a,pi->b);
519 if(k<2 || sur.totalLength()>d)
521 ne=g.addEdge(pi->a,pi->b);
529 template <typename Graph, typename CoordMap>
530 class LengthSquareMap {
532 typedef typename Graph::Edge Key;
533 typedef typename CoordMap::Value::Value Value;
535 LengthSquareMap(const Graph& graph, const CoordMap& coords)
536 : _graph(graph), _coords(coords) {}
538 Value operator[](const Key& key) const {
539 return (_coords[_graph.v(key)] -
540 _coords[_graph.u(key)]).normSquare();
546 const CoordMap& _coords;
550 std::vector<Parc> pedges;
552 std::cout << T.realTime() << "s: Creating delaunay triangulation...\n";
554 std::cout << T.realTime() << "s: Calculating spanning tree...\n";
555 LengthSquareMap<ListGraph, ListGraph::NodeMap<Point> > ls(g, coords);
556 ListGraph::EdgeMap<bool> tree(g);
557 kruskal(g, ls, tree);
558 std::cout << T.realTime() << "s: Removing non tree arcs...\n";
559 std::vector<Edge> remove;
560 for (EdgeIt e(g); e != INVALID; ++e) {
561 if (!tree[e]) remove.push_back(e);
563 for(int i = 0; i < int(remove.size()); ++i) {
566 std::cout << T.realTime() << "s: Done\n";
571 std::cout << "Find a tree..." << std::endl;
575 std::cout << "Total arc length (tree) : " << totalLen() << std::endl;
577 std::cout << "Make it Euler..." << std::endl;
580 std::vector<Node> leafs;
581 for(NodeIt n(g);n!=INVALID;++n)
582 if(countIncEdges(g,n)%2==1) leafs.push_back(n);
584 // for(unsigned int i=0;i<leafs.size();i+=2)
585 // g.addArc(leafs[i],leafs[i+1]);
587 std::vector<Parc> pedges;
588 for(unsigned int i=0;i<leafs.size()-1;i++)
589 for(unsigned int j=i+1;j<leafs.size();j++)
596 p.len=(coords[m]-coords[n]).normSquare();
599 std::sort(pedges.begin(),pedges.end(),pedgeLess);
600 for(unsigned int i=0;i<pedges.size();i++)
601 if(countIncEdges(g,pedges[i].a)%2 &&
602 countIncEdges(g,pedges[i].b)%2)
603 g.addEdge(pedges[i].a,pedges[i].b);
606 for(NodeIt n(g);n!=INVALID;++n)
607 if(countIncEdges(g,n)%2 || countIncEdges(g,n)==0 )
608 std::cout << "GEBASZ!!!" << std::endl;
610 for(EdgeIt e(g);e!=INVALID;++e)
612 std::cout << "LOOP GEBASZ!!!" << std::endl;
614 std::cout << "Number of arcs : " << countEdges(g) << std::endl;
616 std::cout << "Total arc length (euler) : " << totalLen() << std::endl;
618 ListGraph::EdgeMap<Arc> enext(g);
620 EulerIt<ListGraph> e(g);
623 // std::cout << "Tour arc: " << g.id(Edge(e)) << std::endl;
624 for(++e;e!=INVALID;++e)
626 // std::cout << "Tour arc: " << g.id(Edge(e)) << std::endl;
633 std::cout << "Creating a tour from that..." << std::endl;
635 int nnum = countNodes(g);
636 int ednum = countEdges(g);
638 for(Arc p=enext[EdgeIt(g)];ednum>nnum;p=enext[p])
640 // std::cout << "Checking arc " << g.id(p) << std::endl;
644 Node n1=g.oppositeNode(n2,e);
645 Node n3=g.oppositeNode(n2,f);
646 if(countIncEdges(g,n2)>2)
648 // std::cout << "Remove an Arc" << std::endl;
654 Arc ne=g.direct(g.addEdge(n1,n3),n1);
666 std::cout << "Total arc length (tour) : " << totalLen() << std::endl;
668 std::cout << "2-opt the tour..." << std::endl;
672 std::cout << "Total arc length (2-opt tour) : " << totalLen() << std::endl;
676 int main(int argc,const char **argv)
678 ArgParser ap(argc,argv);
681 bool disc_d, square_d, gauss_d;
682 // bool tsp_a,two_a,tree_a;
687 std::string ndist("disc");
688 ap.refOption("n", "Number of nodes (default is 100)", N)
689 .intOption("g", "Girth parameter (default is 10)", 10)
690 .refOption("cities", "Number of cities (default is 1)", num_of_cities)
691 .refOption("area", "Full relative area of the cities (default is 1)", area)
692 .refOption("disc", "Nodes are evenly distributed on a unit disc (default)",disc_d)
693 .optionGroup("dist", "disc")
694 .refOption("square", "Nodes are evenly distributed on a unit square", square_d)
695 .optionGroup("dist", "square")
697 "Nodes are located according to a two-dim gauss distribution",
699 .optionGroup("dist", "gauss")
700 // .mandatoryGroup("dist")
701 .onlyOneGroup("dist")
702 .boolOption("eps", "Also generate .eps output (prefix.eps)")
703 .boolOption("nonodes", "Draw the edges only in the generated .eps")
704 .boolOption("dir", "Directed digraph is generated (each arcs are replaced by two directed ones)")
705 .boolOption("2con", "Create a two connected planar digraph")
706 .optionGroup("alg","2con")
707 .boolOption("tree", "Create a min. cost spanning tree")
708 .optionGroup("alg","tree")
709 .boolOption("tsp", "Create a TSP tour")
710 .optionGroup("alg","tsp")
711 .boolOption("tsp2", "Create a TSP tour (tree based)")
712 .optionGroup("alg","tsp2")
713 .boolOption("dela", "Delaunay triangulation digraph")
714 .optionGroup("alg","dela")
716 .boolOption("rand", "Use time seed for random number generator")
717 .optionGroup("rand", "rand")
718 .intOption("seed", "Random seed", -1)
719 .optionGroup("rand", "seed")
720 .onlyOneGroup("rand")
721 .other("[prefix]","Prefix of the output files. Default is 'lgf-gen-out'")
726 std::cout << "Random number seed: " << seed << std::endl;
729 if (ap.given("seed")) {
730 int seed = ap["seed"];
731 std::cout << "Random number seed: " << seed << std::endl;
736 switch(ap.files().size())
739 prefix="lgf-gen-out";
742 prefix=ap.files()[0];
745 std::cerr << "\nAt most one prefix can be given\n\n";
750 std::vector<double> sizes;
751 std::vector<double> cum_sizes;
752 for(int s=0;s<num_of_cities;s++)
754 // sum_sizes+=rnd.exponential();
758 cum_sizes.push_back(sum_sizes);
761 for(int s=0;s<num_of_cities;s++)
763 Point center=(num_of_cities==1?Point(0,0):rnd.disc());
765 for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
768 coords[n]=center+rnd.gauss2()*area*
769 std::sqrt(sizes[s]/sum_sizes);
772 for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
775 coords[n]=center+Point(rnd()*2-1,rnd()*2-1)*area*
776 std::sqrt(sizes[s]/sum_sizes);
778 else if(disc_d || true)
779 for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
782 coords[n]=center+rnd.disc()*area*
783 std::sqrt(sizes[s]/sum_sizes);
787 // for (ListGraph::NodeIt n(g); n != INVALID; ++n) {
788 // std::cerr << coords[n] << std::endl;
793 std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
797 std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
799 else if(ap["2con"]) {
800 std::cout << "Make triangles\n";
802 sparseTriangle(ap["g"]);
803 std::cout << "Make it sparser\n";
806 else if(ap["tree"]) {
809 else if(ap["dela"]) {
814 std::cout << "Number of nodes : " << countNodes(g) << std::endl;
815 std::cout << "Number of arcs : " << countEdges(g) << std::endl;
817 for(EdgeIt e(g);e!=INVALID;++e)
818 tlen+=sqrt((coords[g.v(e)]-coords[g.u(e)]).normSquare());
819 std::cout << "Total arc length : " << tlen << std::endl;
822 graphToEps(g,prefix+".eps").scaleToA4().
823 scale(600).nodeScale(.005).arcWidthScale(.001).preScale(false).
824 coords(coords).hideNodes(ap.given("nonodes")).run();
827 DigraphWriter<ListGraph>(g,prefix+".lgf").
828 nodeMap("coordinates_x",scaleMap(xMap(coords),600)).
829 nodeMap("coordinates_y",scaleMap(yMap(coords),600)).
831 else GraphWriter<ListGraph>(g,prefix+".lgf").
832 nodeMap("coordinates_x",scaleMap(xMap(coords),600)).
833 nodeMap("coordinates_y",scaleMap(yMap(coords),600)).