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.
35 #include <lemon/list_graph.h>
36 #include <lemon/random.h>
37 #include <lemon/dim2.h>
38 #include <lemon/bfs.h>
39 #include <lemon/counter.h>
40 #include <lemon/suurballe.h>
41 #include <lemon/graph_to_eps.h>
42 #include <lemon/lgf_writer.h>
43 #include <lemon/arg_parser.h>
44 #include <lemon/euler.h>
45 #include <lemon/math.h>
46 #include <lemon/kruskal.h>
47 #include <lemon/time_measure.h>
49 using namespace lemon;
51 typedef dim2::Point<double> Point;
53 GRAPH_TYPEDEFS(ListGraph);
62 std::vector<Node> nodes;
63 ListGraph::NodeMap<Point> coords(g);
68 for(EdgeIt e(g);e!=INVALID;++e)
69 tlen+=sqrt((coords[g.v(e)]-coords[g.u(e)]).normSquare());
75 const double EPSILON=1e-8;
76 bool tsp_improve(Node u, Node v)
78 double luv=std::sqrt((coords[v]-coords[u]).normSquare());
83 for(IncEdgeIt e(g,v2);(n=g.runningNode(e))==u2;++e) { }
86 if(luv+std::sqrt((coords[v2]-coords[u2]).normSquare())-EPSILON>
87 std::sqrt((coords[u]-coords[u2]).normSquare())+
88 std::sqrt((coords[v]-coords[v2]).normSquare()))
90 g.erase(findEdge(g,u,v));
91 g.erase(findEdge(g,u2,v2));
101 bool tsp_improve(Node u)
103 for(IncEdgeIt e(g,u);e!=INVALID;++e)
104 if(tsp_improve(u,g.runningNode(e))) return true;
113 for(NodeIt n(g);n!=INVALID;++n)
114 if(tsp_improve(n)) b=true;
120 for(int i=0;i<N;i++) g.addEdge(nodes[i],nodes[(i+1)%N]);
129 Line(Point _a,Point _b) :a(_a),b(_b) {}
130 Line(Node _a,Node _b) : a(coords[_a]),b(coords[_b]) {}
131 Line(const Arc &e) : a(coords[g.source(e)]),b(coords[g.target(e)]) {}
132 Line(const Edge &e) : a(coords[g.u(e)]),b(coords[g.v(e)]) {}
135 inline std::ostream& operator<<(std::ostream &os, const Line &l)
137 os << l.a << "->" << l.b;
141 bool cross(Line a, Line b)
143 Point ao=rot90(a.b-a.a);
144 Point bo=rot90(b.b-b.a);
145 return (ao*(b.a-a.a))*(ao*(b.b-a.a))<0 &&
146 (bo*(a.a-b.a))*(bo*(a.b-b.a))<0;
156 bool pedgeLess(Parc a,Parc b)
161 std::vector<Edge> arcs;
163 namespace _delaunay_bits {
166 int prev, curr, next;
168 Part(int p, int c, int n) : prev(p), curr(c), next(n) {}
171 inline std::ostream& operator<<(std::ostream& os, const Part& part) {
172 os << '(' << part.prev << ',' << part.curr << ',' << part.next << ')';
176 inline double circle_point(const Point& p, const Point& q, const Point& r) {
177 double a = p.x * (q.y - r.y) + q.x * (r.y - p.y) + r.x * (p.y - q.y);
178 if (a == 0) return std::numeric_limits<double>::quiet_NaN();
180 double d = (p.x * p.x + p.y * p.y) * (q.y - r.y) +
181 (q.x * q.x + q.y * q.y) * (r.y - p.y) +
182 (r.x * r.x + r.y * r.y) * (p.y - q.y);
184 double e = (p.x * p.x + p.y * p.y) * (q.x - r.x) +
185 (q.x * q.x + q.y * q.y) * (r.x - p.x) +
186 (r.x * r.x + r.y * r.y) * (p.x - q.x);
188 double f = (p.x * p.x + p.y * p.y) * (q.x * r.y - r.x * q.y) +
189 (q.x * q.x + q.y * q.y) * (r.x * p.y - p.x * r.y) +
190 (r.x * r.x + r.y * r.y) * (p.x * q.y - q.x * p.y);
192 return d / (2 * a) + sqrt((d * d + e * e) / (4 * a * a) + f / a);
195 inline bool circle_form(const Point& p, const Point& q, const Point& r) {
196 return rot90(q - p) * (r - q) < 0.0;
199 inline double intersection(const Point& p, const Point& q, double sx) {
200 const double epsilon = 1e-8;
202 if (p.x == q.x) return (p.y + q.y) / 2.0;
204 if (sx < p.x + epsilon) return p.y;
205 if (sx < q.x + epsilon) return q.y;
207 double a = q.x - p.x;
208 double b = (q.x - sx) * p.y - (p.x - sx) * q.y;
209 double d = (q.x - sx) * (p.x - sx) * (p - q).normSquare();
210 return (b - sqrt(d)) / a;
216 YLess(const std::vector<Point>& points, double& sweep)
217 : _points(points), _sweep(sweep) {}
219 bool operator()(const Part& l, const Part& r) const {
220 const double epsilon = 1e-8;
222 // std::cerr << l << " vs " << r << std::endl;
223 double lbx = l.prev != -1 ?
224 intersection(_points[l.prev], _points[l.curr], _sweep) :
225 - std::numeric_limits<double>::infinity();
226 double rbx = r.prev != -1 ?
227 intersection(_points[r.prev], _points[r.curr], _sweep) :
228 - std::numeric_limits<double>::infinity();
229 double lex = l.next != -1 ?
230 intersection(_points[l.curr], _points[l.next], _sweep) :
231 std::numeric_limits<double>::infinity();
232 double rex = r.next != -1 ?
233 intersection(_points[r.curr], _points[r.next], _sweep) :
234 std::numeric_limits<double>::infinity();
236 if (lbx > lex) std::swap(lbx, lex);
237 if (rbx > rex) std::swap(rbx, rex);
239 if (lex < epsilon + rex && lbx + epsilon < rex) return true;
240 if (rex < epsilon + lex && rbx + epsilon < lex) return false;
244 const std::vector<Point>& _points;
250 typedef std::multimap<double, BeachIt> SpikeHeap;
252 typedef std::multimap<Part, SpikeHeap::iterator, YLess> Beach;
257 BeachIt(Beach::iterator iter) : it(iter) {}
262 inline void delaunay() {
263 Counter cnt("Number of arcs added: ");
265 using namespace _delaunay_bits;
267 typedef _delaunay_bits::Part Part;
268 typedef std::vector<std::pair<double, int> > SiteHeap;
271 std::vector<Point> points;
272 std::vector<Node> nodes;
274 for (NodeIt it(g); it != INVALID; ++it) {
276 points.push_back(coords[it]);
279 SiteHeap siteheap(points.size());
284 for (int i = 0; i < int(siteheap.size()); ++i) {
285 siteheap[i] = std::make_pair(points[i].x, i);
288 std::sort(siteheap.begin(), siteheap.end());
289 sweep = siteheap.front().first;
291 YLess yless(points, sweep);
296 std::set<std::pair<int, int> > arcs;
302 while (siteindex < int(siteheap.size()) &&
303 siteheap[0].first == siteheap[siteindex].first) {
304 front.push_back(std::make_pair(points[siteheap[siteindex].second].y,
305 siteheap[siteindex].second));
309 std::sort(front.begin(), front.end());
311 for (int i = 0; i < int(front.size()); ++i) {
312 int prev = (i == 0 ? -1 : front[i - 1].second);
313 int curr = front[i].second;
314 int next = (i + 1 == int(front.size()) ? -1 : front[i + 1].second);
316 beach.insert(std::make_pair(Part(prev, curr, next),
321 while (siteindex < int(points.size()) || !spikeheap.empty()) {
323 SpikeHeap::iterator spit = spikeheap.begin();
325 if (siteindex < int(points.size()) &&
326 (spit == spikeheap.end() || siteheap[siteindex].first < spit->first)) {
327 int site = siteheap[siteindex].second;
328 sweep = siteheap[siteindex].first;
330 Beach::iterator bit = beach.upper_bound(Part(site, site, site));
332 if (bit->second != spikeheap.end()) {
333 spikeheap.erase(bit->second);
336 int prev = bit->first.prev;
337 int curr = bit->first.curr;
338 int next = bit->first.next;
342 SpikeHeap::iterator pit = spikeheap.end();
344 circle_form(points[prev], points[curr], points[site])) {
345 double x = circle_point(points[prev], points[curr], points[site]);
346 pit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
348 beach.insert(std::make_pair(Part(prev, curr, site), pit));
350 beach.insert(std::make_pair(Part(prev, curr, site), pit));
353 beach.insert(std::make_pair(Part(curr, site, curr), spikeheap.end()));
355 SpikeHeap::iterator nit = spikeheap.end();
357 circle_form(points[site], points[curr],points[next])) {
358 double x = circle_point(points[site], points[curr], points[next]);
359 nit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
361 beach.insert(std::make_pair(Part(site, curr, next), nit));
363 beach.insert(std::make_pair(Part(site, curr, next), nit));
370 Beach::iterator bit = spit->second.it;
372 int prev = bit->first.prev;
373 int curr = bit->first.curr;
374 int next = bit->first.next;
377 std::pair<int, int> arc;
380 std::make_pair(prev, curr) : std::make_pair(curr, prev);
382 if (arcs.find(arc) == arcs.end()) {
384 g.addEdge(nodes[prev], nodes[curr]);
389 std::make_pair(curr, next) : std::make_pair(next, curr);
391 if (arcs.find(arc) == arcs.end()) {
393 g.addEdge(nodes[curr], nodes[next]);
398 Beach::iterator pbit = bit; --pbit;
399 int ppv = pbit->first.prev;
400 Beach::iterator nbit = bit; ++nbit;
401 int nnt = nbit->first.next;
403 if (bit->second != spikeheap.end()) spikeheap.erase(bit->second);
404 if (pbit->second != spikeheap.end()) spikeheap.erase(pbit->second);
405 if (nbit->second != spikeheap.end()) spikeheap.erase(nbit->second);
411 SpikeHeap::iterator pit = spikeheap.end();
412 if (ppv != -1 && ppv != next &&
413 circle_form(points[ppv], points[prev], points[next])) {
414 double x = circle_point(points[ppv], points[prev], points[next]);
415 if (x < sweep) x = sweep;
416 pit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
418 beach.insert(std::make_pair(Part(ppv, prev, next), pit));
420 beach.insert(std::make_pair(Part(ppv, prev, next), pit));
423 SpikeHeap::iterator nit = spikeheap.end();
424 if (nnt != -1 && prev != nnt &&
425 circle_form(points[prev], points[next], points[nnt])) {
426 double x = circle_point(points[prev], points[next], points[nnt]);
427 if (x < sweep) x = sweep;
428 nit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
430 beach.insert(std::make_pair(Part(prev, next, nnt), nit));
432 beach.insert(std::make_pair(Part(prev, next, nnt), nit));
438 for (Beach::iterator it = beach.begin(); it != beach.end(); ++it) {
439 int curr = it->first.curr;
440 int next = it->first.next;
442 if (next == -1) continue;
444 std::pair<int, int> arc;
447 std::make_pair(curr, next) : std::make_pair(next, curr);
449 if (arcs.find(arc) == arcs.end()) {
451 g.addEdge(nodes[curr], nodes[next]);
459 Counter cnt("Number of arcs removed: ");
460 Bfs<ListGraph> bfs(g);
461 for(std::vector<Edge>::reverse_iterator ei=arcs.rbegin();
462 ei!=arcs.rend();++ei)
468 if(bfs.predArc(b)==INVALID || bfs.dist(b)>d)
476 Counter cnt("Number of arcs removed: ");
477 for(std::vector<Edge>::reverse_iterator ei=arcs.rbegin();
478 ei!=arcs.rend();++ei)
483 ConstMap<Arc,int> cegy(1);
484 Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy,a,b);
486 if(k<2 || sur.totalLength()>d)
489 // else std::cout << "Remove arc " << g.id(a) << "-" << g.id(b) << '\n';
493 void sparseTriangle(int d)
495 Counter cnt("Number of arcs added: ");
496 std::vector<Parc> pedges;
497 for(NodeIt n(g);n!=INVALID;++n)
498 for(NodeIt m=++(NodeIt(n));m!=INVALID;++m)
503 p.len=(coords[m]-coords[n]).normSquare();
506 std::sort(pedges.begin(),pedges.end(),pedgeLess);
507 for(std::vector<Parc>::iterator pi=pedges.begin();pi!=pedges.end();++pi)
509 Line li(pi->a,pi->b);
511 for(;e!=INVALID && !cross(e,li);++e) ;
514 ConstMap<Arc,int> cegy(1);
515 Suurballe<ListGraph,ConstMap<Arc,int> >
516 sur(g,cegy,pi->a,pi->b);
518 if(k<2 || sur.totalLength()>d)
520 ne=g.addEdge(pi->a,pi->b);
528 template <typename Graph, typename CoordMap>
529 class LengthSquareMap {
531 typedef typename Graph::Edge Key;
532 typedef typename CoordMap::Value::Value Value;
534 LengthSquareMap(const Graph& graph, const CoordMap& coords)
535 : _graph(graph), _coords(coords) {}
537 Value operator[](const Key& key) const {
538 return (_coords[_graph.v(key)] -
539 _coords[_graph.u(key)]).normSquare();
545 const CoordMap& _coords;
549 std::vector<Parc> pedges;
551 std::cout << T.realTime() << "s: Creating delaunay triangulation...\n";
553 std::cout << T.realTime() << "s: Calculating spanning tree...\n";
554 LengthSquareMap<ListGraph, ListGraph::NodeMap<Point> > ls(g, coords);
555 ListGraph::EdgeMap<bool> tree(g);
556 kruskal(g, ls, tree);
557 std::cout << T.realTime() << "s: Removing non tree arcs...\n";
558 std::vector<Edge> remove;
559 for (EdgeIt e(g); e != INVALID; ++e) {
560 if (!tree[e]) remove.push_back(e);
562 for(int i = 0; i < int(remove.size()); ++i) {
565 std::cout << T.realTime() << "s: Done\n";
570 std::cout << "Find a tree..." << std::endl;
574 std::cout << "Total arc length (tree) : " << totalLen() << std::endl;
576 std::cout << "Make it Euler..." << std::endl;
579 std::vector<Node> leafs;
580 for(NodeIt n(g);n!=INVALID;++n)
581 if(countIncEdges(g,n)%2==1) leafs.push_back(n);
583 // for(unsigned int i=0;i<leafs.size();i+=2)
584 // g.addArc(leafs[i],leafs[i+1]);
586 std::vector<Parc> pedges;
587 for(unsigned int i=0;i<leafs.size()-1;i++)
588 for(unsigned int j=i+1;j<leafs.size();j++)
595 p.len=(coords[m]-coords[n]).normSquare();
598 std::sort(pedges.begin(),pedges.end(),pedgeLess);
599 for(unsigned int i=0;i<pedges.size();i++)
600 if(countIncEdges(g,pedges[i].a)%2 &&
601 countIncEdges(g,pedges[i].b)%2)
602 g.addEdge(pedges[i].a,pedges[i].b);
605 for(NodeIt n(g);n!=INVALID;++n)
606 if(countIncEdges(g,n)%2 || countIncEdges(g,n)==0 )
607 std::cout << "GEBASZ!!!" << std::endl;
609 for(EdgeIt e(g);e!=INVALID;++e)
611 std::cout << "LOOP GEBASZ!!!" << std::endl;
613 std::cout << "Number of arcs : " << countEdges(g) << std::endl;
615 std::cout << "Total arc length (euler) : " << totalLen() << std::endl;
617 ListGraph::EdgeMap<Arc> enext(g);
619 EulerIt<ListGraph> e(g);
622 // std::cout << "Tour arc: " << g.id(Edge(e)) << std::endl;
623 for(++e;e!=INVALID;++e)
625 // std::cout << "Tour arc: " << g.id(Edge(e)) << std::endl;
632 std::cout << "Creating a tour from that..." << std::endl;
634 int nnum = countNodes(g);
635 int ednum = countEdges(g);
637 for(Arc p=enext[EdgeIt(g)];ednum>nnum;p=enext[p])
639 // std::cout << "Checking arc " << g.id(p) << std::endl;
643 Node n1=g.oppositeNode(n2,e);
644 Node n3=g.oppositeNode(n2,f);
645 if(countIncEdges(g,n2)>2)
647 // std::cout << "Remove an Arc" << std::endl;
653 Arc ne=g.direct(g.addEdge(n1,n3),n1);
665 std::cout << "Total arc length (tour) : " << totalLen() << std::endl;
667 std::cout << "2-opt the tour..." << std::endl;
671 std::cout << "Total arc length (2-opt tour) : " << totalLen() << std::endl;
675 int main(int argc,const char **argv)
677 ArgParser ap(argc,argv);
680 bool disc_d, square_d, gauss_d;
681 // bool tsp_a,two_a,tree_a;
686 std::string ndist("disc");
687 ap.refOption("n", "Number of nodes (default is 100)", N)
688 .intOption("g", "Girth parameter (default is 10)", 10)
689 .refOption("cities", "Number of cities (default is 1)", num_of_cities)
690 .refOption("area", "Full relative area of the cities (default is 1)", area)
691 .refOption("disc", "Nodes are evenly distributed on a unit disc (default)",disc_d)
692 .optionGroup("dist", "disc")
693 .refOption("square", "Nodes are evenly distributed on a unit square", square_d)
694 .optionGroup("dist", "square")
696 "Nodes are located according to a two-dim gauss distribution",
698 .optionGroup("dist", "gauss")
699 // .mandatoryGroup("dist")
700 .onlyOneGroup("dist")
701 .boolOption("eps", "Also generate .eps output (prefix.eps)")
702 .boolOption("nonodes", "Draw the edges only in the generated .eps")
703 .boolOption("dir", "Directed digraph is generated (each arcs are replaced by two directed ones)")
704 .boolOption("2con", "Create a two connected planar digraph")
705 .optionGroup("alg","2con")
706 .boolOption("tree", "Create a min. cost spanning tree")
707 .optionGroup("alg","tree")
708 .boolOption("tsp", "Create a TSP tour")
709 .optionGroup("alg","tsp")
710 .boolOption("tsp2", "Create a TSP tour (tree based)")
711 .optionGroup("alg","tsp2")
712 .boolOption("dela", "Delaunay triangulation digraph")
713 .optionGroup("alg","dela")
715 .boolOption("rand", "Use time seed for random number generator")
716 .optionGroup("rand", "rand")
717 .intOption("seed", "Random seed", -1)
718 .optionGroup("rand", "seed")
719 .onlyOneGroup("rand")
720 .other("[prefix]","Prefix of the output files. Default is 'lgf-gen-out'")
725 std::cout << "Random number seed: " << seed << std::endl;
728 if (ap.given("seed")) {
729 int seed = ap["seed"];
730 std::cout << "Random number seed: " << seed << std::endl;
735 switch(ap.files().size())
738 prefix="lgf-gen-out";
741 prefix=ap.files()[0];
744 std::cerr << "\nAt most one prefix can be given\n\n";
749 std::vector<double> sizes;
750 std::vector<double> cum_sizes;
751 for(int s=0;s<num_of_cities;s++)
753 // sum_sizes+=rnd.exponential();
757 cum_sizes.push_back(sum_sizes);
760 for(int s=0;s<num_of_cities;s++)
762 Point center=(num_of_cities==1?Point(0,0):rnd.disc());
764 for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
767 coords[n]=center+rnd.gauss2()*area*
768 std::sqrt(sizes[s]/sum_sizes);
771 for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
774 coords[n]=center+Point(rnd()*2-1,rnd()*2-1)*area*
775 std::sqrt(sizes[s]/sum_sizes);
777 else if(disc_d || true)
778 for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
781 coords[n]=center+rnd.disc()*area*
782 std::sqrt(sizes[s]/sum_sizes);
786 // for (ListGraph::NodeIt n(g); n != INVALID; ++n) {
787 // std::cerr << coords[n] << std::endl;
792 std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
796 std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
798 else if(ap["2con"]) {
799 std::cout << "Make triangles\n";
801 sparseTriangle(ap["g"]);
802 std::cout << "Make it sparser\n";
805 else if(ap["tree"]) {
808 else if(ap["dela"]) {
813 std::cout << "Number of nodes : " << countNodes(g) << std::endl;
814 std::cout << "Number of arcs : " << countEdges(g) << std::endl;
816 for(EdgeIt e(g);e!=INVALID;++e)
817 tlen+=sqrt((coords[g.v(e)]-coords[g.u(e)]).normSquare());
818 std::cout << "Total arc length : " << tlen << std::endl;
821 graphToEps(g,prefix+".eps").scaleToA4().
822 scale(600).nodeScale(.005).arcWidthScale(.001).preScale(false).
823 coords(coords).hideNodes(ap.given("nonodes")).run();
826 DigraphWriter<ListGraph>(g,prefix+".lgf").
827 nodeMap("coordinates_x",scaleMap(xMap(coords),600)).
828 nodeMap("coordinates_y",scaleMap(yMap(coords),600)).
830 else GraphWriter<ListGraph>(g,prefix+".lgf").
831 nodeMap("coordinates_x",scaleMap(xMap(coords),600)).
832 nodeMap("coordinates_y",scaleMap(yMap(coords),600)).