alpar@2391: /* -*- C++ -*- alpar@2391: * alpar@2391: * This file is a part of LEMON, a generic C++ optimization library alpar@2391: * alpar@2391: * Copyright (C) 2003-2007 alpar@2391: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@2391: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@2391: * alpar@2391: * Permission to use, modify and distribute this software is granted alpar@2391: * provided that this copyright notice appears in all copies. For alpar@2391: * precise terms see the accompanying LICENSE file. alpar@2391: * alpar@2391: * This software is provided "AS IS" with no warranty of any kind, alpar@2391: * express or implied, and with no claim as to its suitability for any alpar@2391: * purpose. alpar@2391: * alpar@2391: */ alpar@2391: alpar@2390: #include alpar@2390: #include alpar@2390: #include alpar@2390: #include alpar@2390: #include alpar@2390: #include alpar@2390: #include alpar@2390: #include alpar@2390: #include alpar@2390: #include alpar@2390: #include alpar@2390: #include alpar@2390: #include alpar@2402: #include alpar@2390: alpar@2390: using namespace lemon; alpar@2390: alpar@2390: typedef dim2::Point Point; alpar@2390: alpar@2390: UGRAPH_TYPEDEFS(ListUGraph); alpar@2390: alpar@2402: bool progress=true; alpar@2402: alpar@2390: int N; alpar@2402: // int girth; alpar@2390: alpar@2390: ListUGraph g; alpar@2390: alpar@2390: std::vector nodes; alpar@2390: ListUGraph::NodeMap coords(g); alpar@2390: alpar@2390: int tsp_impr_num=0; alpar@2390: alpar@2390: const double EPSILON=1e-8; alpar@2390: bool tsp_improve(Node u, Node v) alpar@2390: { alpar@2390: double luv=std::sqrt((coords[v]-coords[u]).normSquare()); alpar@2390: Node u2=u; alpar@2390: Node v2=v; alpar@2390: do { alpar@2390: Node n; alpar@2390: for(IncEdgeIt e(g,v2);(n=g.runningNode(e))==u2;++e); alpar@2390: u2=v2; alpar@2390: v2=n; alpar@2390: if(luv+std::sqrt((coords[v2]-coords[u2]).normSquare())-EPSILON> alpar@2390: std::sqrt((coords[u]-coords[u2]).normSquare())+ alpar@2390: std::sqrt((coords[v]-coords[v2]).normSquare())) alpar@2390: { alpar@2390: g.erase(findUEdge(g,u,v)); alpar@2390: g.erase(findUEdge(g,u2,v2)); alpar@2390: g.addEdge(u2,u); alpar@2390: g.addEdge(v,v2); alpar@2390: tsp_impr_num++; alpar@2390: return true; alpar@2390: } alpar@2390: } while(v2!=u); alpar@2390: return false; alpar@2390: } alpar@2390: alpar@2390: bool tsp_improve(Node u) alpar@2390: { alpar@2390: for(IncEdgeIt e(g,u);e!=INVALID;++e) alpar@2390: if(tsp_improve(u,g.runningNode(e))) return true; alpar@2390: return false; alpar@2390: } alpar@2390: alpar@2390: void tsp_improve() alpar@2390: { alpar@2390: bool b; alpar@2390: do { alpar@2390: b=false; alpar@2390: for(NodeIt n(g);n!=INVALID;++n) alpar@2390: if(tsp_improve(n)) b=true; alpar@2390: } while(b); alpar@2390: } alpar@2390: alpar@2390: void tsp() alpar@2390: { alpar@2390: for(int i=0;i" << l.b; alpar@2390: return os; alpar@2390: } alpar@2390: alpar@2390: bool cross(Line a, Line b) alpar@2390: { alpar@2390: Point ao=rot90(a.b-a.a); alpar@2390: Point bo=rot90(b.b-b.a); alpar@2390: return (ao*(b.a-a.a))*(ao*(b.b-a.a))<0 && alpar@2390: (bo*(a.a-b.a))*(bo*(a.b-b.a))<0; alpar@2390: } alpar@2390: alpar@2390: struct Pedge alpar@2390: { alpar@2390: Node a; alpar@2390: Node b; alpar@2390: double len; alpar@2390: }; alpar@2390: alpar@2390: bool pedgeLess(Pedge a,Pedge b) alpar@2390: { alpar@2390: return a.len edges; alpar@2390: alpar@2390: void triangle() alpar@2390: { alpar@2390: Counter cnt("Number of edges added: "); alpar@2390: std::vector pedges; alpar@2390: for(NodeIt n(g);n!=INVALID;++n) alpar@2390: for(NodeIt m=++(NodeIt(n));m!=INVALID;++m) alpar@2390: { alpar@2390: Pedge p; alpar@2390: p.a=n; alpar@2390: p.b=m; alpar@2390: p.len=(coords[m]-coords[n]).normSquare(); alpar@2390: pedges.push_back(p); alpar@2390: } alpar@2390: std::sort(pedges.begin(),pedges.end(),pedgeLess); alpar@2390: for(std::vector::iterator pi=pedges.begin();pi!=pedges.end();++pi) alpar@2390: { alpar@2390: Line li(pi->a,pi->b); alpar@2390: UEdgeIt e(g); alpar@2390: for(;e!=INVALID && !cross(e,li);++e) ; alpar@2390: UEdge ne; alpar@2390: if(e==INVALID) { alpar@2390: ne=g.addEdge(pi->a,pi->b); alpar@2390: edges.push_back(ne); alpar@2390: cnt++; alpar@2390: } alpar@2390: } alpar@2390: } alpar@2390: alpar@2390: void sparse(int d) alpar@2390: { alpar@2390: Counter cnt("Number of edges removed: "); alpar@2390: Bfs bfs(g); alpar@2390: for(std::vector::reverse_iterator ei=edges.rbegin(); alpar@2390: ei!=edges.rend();++ei) alpar@2390: { alpar@2390: Node a=g.source(*ei); alpar@2390: Node b=g.target(*ei); alpar@2390: g.erase(*ei); alpar@2390: bfs.run(a,b); alpar@2390: if(bfs.predEdge(b)==INVALID || bfs.dist(b)>d) alpar@2390: g.addEdge(a,b); alpar@2390: else cnt++; alpar@2390: } alpar@2390: } alpar@2390: alpar@2390: void sparse2(int d) alpar@2390: { alpar@2390: Counter cnt("Number of edges removed: "); alpar@2390: for(std::vector::reverse_iterator ei=edges.rbegin(); alpar@2390: ei!=edges.rend();++ei) alpar@2390: { alpar@2390: Node a=g.source(*ei); alpar@2390: Node b=g.target(*ei); alpar@2390: g.erase(*ei); alpar@2390: ConstMap cegy(1); alpar@2390: Suurballe > sur(g,cegy,a,b); alpar@2390: int k=sur.run(2); alpar@2390: if(k<2 || sur.totalLength()>d) alpar@2390: g.addEdge(a,b); alpar@2390: else cnt++; alpar@2390: // else std::cout << "Remove edge " << g.id(a) << "-" << g.id(b) << '\n'; alpar@2390: } alpar@2390: } alpar@2390: alpar@2390: void sparseTriangle(int d) alpar@2390: { alpar@2390: Counter cnt("Number of edges added: "); alpar@2390: std::vector pedges; alpar@2390: for(NodeIt n(g);n!=INVALID;++n) alpar@2390: for(NodeIt m=++(NodeIt(n));m!=INVALID;++m) alpar@2390: { alpar@2390: Pedge p; alpar@2390: p.a=n; alpar@2390: p.b=m; alpar@2390: p.len=(coords[m]-coords[n]).normSquare(); alpar@2390: pedges.push_back(p); alpar@2390: } alpar@2390: std::sort(pedges.begin(),pedges.end(),pedgeLess); alpar@2390: for(std::vector::iterator pi=pedges.begin();pi!=pedges.end();++pi) alpar@2390: { alpar@2390: Line li(pi->a,pi->b); alpar@2390: UEdgeIt e(g); alpar@2390: for(;e!=INVALID && !cross(e,li);++e) ; alpar@2390: UEdge ne; alpar@2390: if(e==INVALID) { alpar@2390: ConstMap cegy(1); alpar@2390: Suurballe > alpar@2390: sur(g,cegy,pi->a,pi->b); alpar@2390: int k=sur.run(2); alpar@2390: if(k<2 || sur.totalLength()>d) alpar@2390: { alpar@2390: ne=g.addEdge(pi->a,pi->b); alpar@2390: edges.push_back(ne); alpar@2390: cnt++; alpar@2390: } alpar@2390: } alpar@2390: } alpar@2390: } alpar@2390: alpar@2390: void minTree() { alpar@2402: int en=0; alpar@2402: int pr=0; alpar@2390: std::vector pedges; alpar@2402: Timer T; alpar@2402: std::cout << T.realTime() << "s: Setting up the edges...\n"; alpar@2390: for(NodeIt n(g);n!=INVALID;++n) alpar@2402: { alpar@2402: for(NodeIt m=++(NodeIt(n));m!=INVALID;++m) alpar@2402: { alpar@2402: Pedge p; alpar@2402: p.a=n; alpar@2402: p.b=m; alpar@2402: p.len=(coords[m]-coords[n]).normSquare(); alpar@2402: pedges.push_back(p); alpar@2402: } alpar@2402: en++; alpar@2402: if(progress && en>=pr*double(N)/100) alpar@2402: { alpar@2402: std::cout << pr << "% \r" << std::flush; alpar@2402: pr++; alpar@2402: } alpar@2402: } alpar@2402: std::cout << T.realTime() << "s: Sorting the edges...\n"; alpar@2390: std::sort(pedges.begin(),pedges.end(),pedgeLess); alpar@2402: std::cout << T.realTime() << "s: Creating the tree...\n"; alpar@2390: ListUGraph::NodeMap comp(g); alpar@2390: UnionFind > uf(comp); alpar@2390: for (NodeIt it(g); it != INVALID; ++it) alpar@2402: uf.insert(it); alpar@2390: for(std::vector::iterator pi=pedges.begin();pi!=pedges.end();++pi) alpar@2390: { alpar@2390: if ( uf.join(pi->a,pi->b) ) { alpar@2390: g.addEdge(pi->a,pi->b); alpar@2402: if(en>=N-1) alpar@2402: break; alpar@2390: } alpar@2390: } alpar@2402: std::cout << T.realTime() << "s: Done\n"; alpar@2390: } alpar@2390: alpar@2390: alpar@2390: deba@2410: int main(int argc,const char **argv) alpar@2390: { alpar@2390: ArgParser ap(argc,argv); alpar@2390: alpar@2402: // bool eps; alpar@2390: bool disc_d, square_d, gauss_d; alpar@2402: // bool tsp_a,two_a,tree_a; alpar@2390: int num_of_cities=1; alpar@2390: double area=1; alpar@2390: N=100; alpar@2402: // girth=10; alpar@2390: std::string ndist("disc"); alpar@2402: ap.refOption("n", "Number of nodes (default is 100)", N) alpar@2402: .intOption("g", "Girth parameter (default is 10)", 10) alpar@2402: .refOption("cities", "Number of cities (default is 1)", num_of_cities) alpar@2402: .refOption("area", "Full relative area of the cities (default is 1)", area) alpar@2402: .refOption("disc", "Nodes are evenly distributed on a unit disc (default)",disc_d) alpar@2390: .optionGroup("dist", "disc") alpar@2402: .refOption("square", "Nodes are evenly distributed on a unit square", square_d) alpar@2390: .optionGroup("dist", "square") alpar@2402: .refOption("gauss", alpar@2390: "Nodes are located according to a two-dim gauss distribution", alpar@2390: gauss_d) alpar@2390: .optionGroup("dist", "gauss") alpar@2390: // .mandatoryGroup("dist") alpar@2390: .onlyOneGroup("dist") alpar@2402: .boolOption("eps", "Also generate .eps output (prefix.eps)") alpar@2402: .boolOption("2con", "Create a two connected planar graph") alpar@2390: .optionGroup("alg","2con") alpar@2402: .boolOption("tree", "Create a min. cost spanning tree") alpar@2390: .optionGroup("alg","tree") alpar@2402: .boolOption("tsp", "Create a TSP tour") alpar@2390: .optionGroup("alg","tsp") alpar@2390: .onlyOneGroup("alg") alpar@2390: .other("[prefix]","Prefix of the output files. Default is 'lgf-gen-out'") alpar@2390: .run(); alpar@2390: alpar@2390: std::string prefix; alpar@2390: switch(ap.files().size()) alpar@2390: { alpar@2390: case 0: alpar@2390: prefix="lgf-gen-out"; alpar@2390: break; alpar@2390: case 1: alpar@2390: prefix=ap.files()[0]; alpar@2390: break; alpar@2390: default: alpar@2390: std::cerr << "\nAt most one prefix can be given\n\n"; alpar@2390: exit(1); alpar@2390: } alpar@2390: alpar@2390: double sum_sizes=0; alpar@2390: std::vector sizes; alpar@2390: std::vector cum_sizes; alpar@2390: for(int s=0;s(prefix+".lgf",g). alpar@2390: writeNodeMap("coordinates_x",scaleMap(xMap(coords),600)). alpar@2390: writeNodeMap("coordinates_y",scaleMap(yMap(coords),600)). alpar@2390: run(); alpar@2390: } alpar@2390: