1.1 --- a/Makefile.am Sat Mar 03 12:05:05 2007 +0000
1.2 +++ b/Makefile.am Sat Mar 03 16:04:50 2007 +0000
1.3 @@ -22,6 +22,7 @@
1.4 concept_HEADERS =
1.5 noinst_HEADERS =
1.6 noinst_PROGRAMS =
1.7 +bin_PROGRAMS =
1.8 check_PROGRAMS =
1.9 TESTS =
1.10 XFAIL_TESTS =
1.11 @@ -31,6 +32,7 @@
1.12 include doc/Makefile.am
1.13 include demo/Makefile.am
1.14 include benchmark/Makefile.am
1.15 +include tools/Makefile.am
1.16
1.17 MRPROPERFILES = \
1.18 aclocal.m4 \
2.1 --- a/configure.ac Sat Mar 03 12:05:05 2007 +0000
2.2 +++ b/configure.ac Sat Mar 03 16:04:50 2007 +0000
2.3 @@ -17,7 +17,7 @@
2.4 AC_PROG_LIBTOOL
2.5
2.6 if test x"$lx_cmdline_cxxflags_set" != x"set" -a "$GXX" = yes; then
2.7 - CXXFLAGS="$CXXFLAGS -Wall -W -Wall -W -Wunused -Wformat=2 -Wctor-dtor-privacy -Wnon-virtual-dtor -Wno-char-subscripts -Wwrite-strings -Wno-char-subscripts -Wreturn-type -Wcast-qual -Wcast-align -Wsign-promo -Woverloaded-virtual -Woverloaded-virtual -Wshadow -ansi -fno-strict-aliasing -Wold-style-cast -Wno-unknown-pragmas"
2.8 + CXXFLAGS="$CXXFLAGS -Wall -W -Wall -W -Wunused -Wformat=2 -Wctor-dtor-privacy -Wnon-virtual-dtor -Wno-char-subscripts -Wwrite-strings -Wno-char-subscripts -Wreturn-type -Wcast-qual -Wcast-align -Wsign-promo -Woverloaded-virtual -Woverloaded-virtual -ansi -fno-strict-aliasing -Wold-style-cast -Wno-unknown-pragmas"
2.9 fi
2.10
2.11 AC_CHECK_PROG([doxygen_found],[doxygen],[yes],[no])
2.12 @@ -67,6 +67,19 @@
2.13 fi
2.14 AM_CONDITIONAL([WANT_DEMO], [test x"$enable_demo" != x"no"])
2.15
2.16 +dnl Disable/enable building the binary tools
2.17 +AC_ARG_ENABLE([tools],
2.18 +AS_HELP_STRING([--enable-tools], [build additional tools @<:@default@:>@])
2.19 +AS_HELP_STRING([--disable-tools], [do not build additional tools]),
2.20 + [], [enable_tools=yes])
2.21 +AC_MSG_CHECKING([whether to build the additional tools])
2.22 +if test x"$enable_tools" != x"no"; then
2.23 + AC_MSG_RESULT([yes])
2.24 +else
2.25 + AC_MSG_RESULT([no])
2.26 +fi
2.27 +AM_CONDITIONAL([WANT_TOOLS], [test x"$enable_tools" != x"no"])
2.28 +
2.29 dnl Disable/enable building the benchmarks
2.30 AC_ARG_ENABLE([benchmark],
2.31 AS_HELP_STRING([--enable-benchmark], [build the benchmarks])
2.32 @@ -118,6 +131,7 @@
2.33 echo
2.34 echo build benchmarks.............. : $enable_benchmark
2.35 echo build demo programs........... : $enable_demo
2.36 +echo build additional tools........ : $enable_tools
2.37 echo
2.38 echo The packace will be installed in
2.39 echo -n ' '
3.1 --- a/doc/dirs.dox Sat Mar 03 12:05:05 2007 +0000
3.2 +++ b/doc/dirs.dox Sat Mar 03 16:04:50 2007 +0000
3.3 @@ -21,6 +21,13 @@
3.4 of the code.
3.5 */
3.6
3.7 +/**
3.8 +\dir tools
3.9 +\brief Some useful executables
3.10 +
3.11 +This directory contains the sources of some useful complete executables.
3.12 +
3.13 +*/
3.14
3.15
3.16
4.1 --- a/lemon/arg_parser.cc Sat Mar 03 12:05:05 2007 +0000
4.2 +++ b/lemon/arg_parser.cc Sat Mar 03 16:04:50 2007 +0000
4.3 @@ -20,7 +20,7 @@
4.4
4.5 void ArgParser::_showHelp(void *p)
4.6 {
4.7 - ((ArgParser*)p)->showHelp();
4.8 + (static_cast<ArgParser*>(p))->showHelp();
4.9 exit(1);
4.10 }
4.11
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/tools/Makefile Sat Mar 03 16:04:50 2007 +0000
5.3 @@ -0,0 +1,2 @@
5.4 +all:
5.5 + $(MAKE) -C ..
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/tools/Makefile.am Sat Mar 03 16:04:50 2007 +0000
6.3 @@ -0,0 +1,12 @@
6.4 +EXTRA_DIST += \
6.5 + tools/Makefile
6.6 +
6.7 +
6.8 +if WANT_TOOLS
6.9 +
6.10 +bin_PROGRAMS += \
6.11 + tools/lgf-gen
6.12 +
6.13 +endif WANT_TOOLS
6.14 +
6.15 +tools_lgf_gen_SOURCES = tools/lgf-gen.cc
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/tools/lgf-gen.cc Sat Mar 03 16:04:50 2007 +0000
7.3 @@ -0,0 +1,369 @@
7.4 +#include <lemon/list_graph.h>
7.5 +#include <lemon/graph_utils.h>
7.6 +#include <lemon/random.h>
7.7 +#include <lemon/dim2.h>
7.8 +#include <lemon/bfs.h>
7.9 +#include <lemon/counter.h>
7.10 +#include <lemon/suurballe.h>
7.11 +#include <lemon/graph_to_eps.h>
7.12 +#include <lemon/graph_writer.h>
7.13 +#include <lemon/arg_parser.h>
7.14 +#include <cmath>
7.15 +#include <algorithm>
7.16 +#include <lemon/unionfind.h>
7.17 +
7.18 +using namespace lemon;
7.19 +
7.20 +typedef dim2::Point<double> Point;
7.21 +
7.22 +UGRAPH_TYPEDEFS(ListUGraph);
7.23 +
7.24 +int N;
7.25 +int girth;
7.26 +
7.27 +ListUGraph g;
7.28 +
7.29 +std::vector<Node> nodes;
7.30 +ListUGraph::NodeMap<Point> coords(g);
7.31 +
7.32 +int tsp_impr_num=0;
7.33 +
7.34 +const double EPSILON=1e-8;
7.35 +bool tsp_improve(Node u, Node v)
7.36 +{
7.37 + double luv=std::sqrt((coords[v]-coords[u]).normSquare());
7.38 + Node u2=u;
7.39 + Node v2=v;
7.40 + do {
7.41 + Node n;
7.42 + for(IncEdgeIt e(g,v2);(n=g.runningNode(e))==u2;++e);
7.43 + u2=v2;
7.44 + v2=n;
7.45 + if(luv+std::sqrt((coords[v2]-coords[u2]).normSquare())-EPSILON>
7.46 + std::sqrt((coords[u]-coords[u2]).normSquare())+
7.47 + std::sqrt((coords[v]-coords[v2]).normSquare()))
7.48 + {
7.49 + g.erase(findUEdge(g,u,v));
7.50 + g.erase(findUEdge(g,u2,v2));
7.51 + g.addEdge(u2,u);
7.52 + g.addEdge(v,v2);
7.53 + tsp_impr_num++;
7.54 + return true;
7.55 + }
7.56 + } while(v2!=u);
7.57 + return false;
7.58 +}
7.59 +
7.60 +bool tsp_improve(Node u)
7.61 +{
7.62 + for(IncEdgeIt e(g,u);e!=INVALID;++e)
7.63 + if(tsp_improve(u,g.runningNode(e))) return true;
7.64 + return false;
7.65 +}
7.66 +
7.67 +void tsp_improve()
7.68 +{
7.69 + bool b;
7.70 + do {
7.71 + b=false;
7.72 + for(NodeIt n(g);n!=INVALID;++n)
7.73 + if(tsp_improve(n)) b=true;
7.74 + } while(b);
7.75 +}
7.76 +
7.77 +void tsp()
7.78 +{
7.79 + for(int i=0;i<N;i++) g.addEdge(nodes[i],nodes[(i+1)%N]);
7.80 + tsp_improve();
7.81 +}
7.82 +
7.83 +class Line
7.84 +{
7.85 +public:
7.86 + Point a;
7.87 + Point b;
7.88 + Line(Point _a,Point _b) :a(_a),b(_b) {}
7.89 + Line(Node _a,Node _b) : a(coords[_a]),b(coords[_b]) {}
7.90 + Line(const Edge &e) : a(coords[g.source(e)]),b(coords[g.target(e)]) {}
7.91 + Line(const UEdge &e) : a(coords[g.source(e)]),b(coords[g.target(e)]) {}
7.92 +};
7.93 +
7.94 +inline std::ostream& operator<<(std::ostream &os, const Line &l)
7.95 +{
7.96 + os << l.a << "->" << l.b;
7.97 + return os;
7.98 +}
7.99 +
7.100 +bool cross(Line a, Line b)
7.101 +{
7.102 + Point ao=rot90(a.b-a.a);
7.103 + Point bo=rot90(b.b-b.a);
7.104 + return (ao*(b.a-a.a))*(ao*(b.b-a.a))<0 &&
7.105 + (bo*(a.a-b.a))*(bo*(a.b-b.a))<0;
7.106 +}
7.107 +
7.108 +struct Pedge
7.109 +{
7.110 + Node a;
7.111 + Node b;
7.112 + double len;
7.113 +};
7.114 +
7.115 +bool pedgeLess(Pedge a,Pedge b)
7.116 +{
7.117 + return a.len<b.len;
7.118 +}
7.119 +
7.120 +std::vector<UEdge> edges;
7.121 +
7.122 +void triangle()
7.123 +{
7.124 + Counter cnt("Number of edges added: ");
7.125 + std::vector<Pedge> pedges;
7.126 + for(NodeIt n(g);n!=INVALID;++n)
7.127 + for(NodeIt m=++(NodeIt(n));m!=INVALID;++m)
7.128 + {
7.129 + Pedge p;
7.130 + p.a=n;
7.131 + p.b=m;
7.132 + p.len=(coords[m]-coords[n]).normSquare();
7.133 + pedges.push_back(p);
7.134 + }
7.135 + std::sort(pedges.begin(),pedges.end(),pedgeLess);
7.136 + for(std::vector<Pedge>::iterator pi=pedges.begin();pi!=pedges.end();++pi)
7.137 + {
7.138 + Line li(pi->a,pi->b);
7.139 + UEdgeIt e(g);
7.140 + for(;e!=INVALID && !cross(e,li);++e) ;
7.141 + UEdge ne;
7.142 + if(e==INVALID) {
7.143 + ne=g.addEdge(pi->a,pi->b);
7.144 + edges.push_back(ne);
7.145 + cnt++;
7.146 + }
7.147 + }
7.148 +}
7.149 +
7.150 +void sparse(int d)
7.151 +{
7.152 + Counter cnt("Number of edges removed: ");
7.153 + Bfs<ListUGraph> bfs(g);
7.154 + for(std::vector<UEdge>::reverse_iterator ei=edges.rbegin();
7.155 + ei!=edges.rend();++ei)
7.156 + {
7.157 + Node a=g.source(*ei);
7.158 + Node b=g.target(*ei);
7.159 + g.erase(*ei);
7.160 + bfs.run(a,b);
7.161 + if(bfs.predEdge(b)==INVALID || bfs.dist(b)>d)
7.162 + g.addEdge(a,b);
7.163 + else cnt++;
7.164 + }
7.165 +}
7.166 +
7.167 +void sparse2(int d)
7.168 +{
7.169 + Counter cnt("Number of edges removed: ");
7.170 + for(std::vector<UEdge>::reverse_iterator ei=edges.rbegin();
7.171 + ei!=edges.rend();++ei)
7.172 + {
7.173 + Node a=g.source(*ei);
7.174 + Node b=g.target(*ei);
7.175 + g.erase(*ei);
7.176 + ConstMap<Edge,int> cegy(1);
7.177 + Suurballe<ListUGraph,ConstMap<Edge,int> > sur(g,cegy,a,b);
7.178 + int k=sur.run(2);
7.179 + if(k<2 || sur.totalLength()>d)
7.180 + g.addEdge(a,b);
7.181 + else cnt++;
7.182 +// else std::cout << "Remove edge " << g.id(a) << "-" << g.id(b) << '\n';
7.183 + }
7.184 +}
7.185 +
7.186 +void sparseTriangle(int d)
7.187 +{
7.188 + Counter cnt("Number of edges added: ");
7.189 + std::vector<Pedge> pedges;
7.190 + for(NodeIt n(g);n!=INVALID;++n)
7.191 + for(NodeIt m=++(NodeIt(n));m!=INVALID;++m)
7.192 + {
7.193 + Pedge p;
7.194 + p.a=n;
7.195 + p.b=m;
7.196 + p.len=(coords[m]-coords[n]).normSquare();
7.197 + pedges.push_back(p);
7.198 + }
7.199 + std::sort(pedges.begin(),pedges.end(),pedgeLess);
7.200 + for(std::vector<Pedge>::iterator pi=pedges.begin();pi!=pedges.end();++pi)
7.201 + {
7.202 + Line li(pi->a,pi->b);
7.203 + UEdgeIt e(g);
7.204 + for(;e!=INVALID && !cross(e,li);++e) ;
7.205 + UEdge ne;
7.206 + if(e==INVALID) {
7.207 + ConstMap<Edge,int> cegy(1);
7.208 + Suurballe<ListUGraph,ConstMap<Edge,int> >
7.209 + sur(g,cegy,pi->a,pi->b);
7.210 + int k=sur.run(2);
7.211 + if(k<2 || sur.totalLength()>d)
7.212 + {
7.213 + ne=g.addEdge(pi->a,pi->b);
7.214 + edges.push_back(ne);
7.215 + cnt++;
7.216 + }
7.217 + }
7.218 + }
7.219 +}
7.220 +
7.221 +void minTree() {
7.222 + std::vector<Pedge> pedges;
7.223 + for(NodeIt n(g);n!=INVALID;++n)
7.224 + for(NodeIt m=++(NodeIt(n));m!=INVALID;++m)
7.225 + {
7.226 + Pedge p;
7.227 + p.a=n;
7.228 + p.b=m;
7.229 + p.len=(coords[m]-coords[n]).normSquare();
7.230 + pedges.push_back(p);
7.231 + }
7.232 + std::sort(pedges.begin(),pedges.end(),pedgeLess);
7.233 + ListUGraph::NodeMap<int> comp(g);
7.234 + UnionFind<ListUGraph::NodeMap<int> > uf(comp);
7.235 + for (NodeIt it(g); it != INVALID; ++it)
7.236 + uf.insert(it);
7.237 +
7.238 + int en=0;
7.239 + for(std::vector<Pedge>::iterator pi=pedges.begin();pi!=pedges.end();++pi)
7.240 + {
7.241 + if ( uf.join(pi->a,pi->b) ) {
7.242 + g.addEdge(pi->a,pi->b);
7.243 + en++;
7.244 + if(en>=N-1) return;
7.245 + }
7.246 + }
7.247 +}
7.248 +
7.249 +
7.250 +
7.251 +int main(int argc,char **argv)
7.252 +{
7.253 + ArgParser ap(argc,argv);
7.254 +
7.255 + bool eps;
7.256 + bool disc_d, square_d, gauss_d;
7.257 + bool tsp_a,two_a,tree_a;
7.258 + int num_of_cities=1;
7.259 + double area=1;
7.260 + N=100;
7.261 + girth=10;
7.262 + std::string ndist("disc");
7.263 + ap.option("n", "Number of nodes (default is 100)", N)
7.264 + .option("g", "Girth parameter (default is 10)", girth)
7.265 + .option("cities", "Number of cities (default is 1)", num_of_cities)
7.266 + .option("area", "Full relative area of the cities (default is 1)", area)
7.267 + .option("disc", "Nodes are evenly distributed on a unit disc (default)",disc_d)
7.268 + .optionGroup("dist", "disc")
7.269 + .option("square", "Nodes are evenly distributed on a unit square", square_d)
7.270 + .optionGroup("dist", "square")
7.271 + .option("gauss",
7.272 + "Nodes are located according to a two-dim gauss distribution",
7.273 + gauss_d)
7.274 + .optionGroup("dist", "gauss")
7.275 +// .mandatoryGroup("dist")
7.276 + .onlyOneGroup("dist")
7.277 + .option("eps", "Also generate .eps output (prefix.eps)",eps)
7.278 + .option("2con", "Create a two connected planar graph",two_a)
7.279 + .optionGroup("alg","2con")
7.280 + .option("tree", "Create a min. cost spanning tree",tree_a)
7.281 + .optionGroup("alg","tree")
7.282 + .option("tsp", "Create a TSP tour",tsp_a)
7.283 + .optionGroup("alg","tsp")
7.284 + .onlyOneGroup("alg")
7.285 + .other("[prefix]","Prefix of the output files. Default is 'lgf-gen-out'")
7.286 + .run();
7.287 +
7.288 + std::string prefix;
7.289 + switch(ap.files().size())
7.290 + {
7.291 + case 0:
7.292 + prefix="lgf-gen-out";
7.293 + break;
7.294 + case 1:
7.295 + prefix=ap.files()[0];
7.296 + break;
7.297 + default:
7.298 + std::cerr << "\nAt most one prefix can be given\n\n";
7.299 + exit(1);
7.300 + }
7.301 +
7.302 + double sum_sizes=0;
7.303 + std::vector<double> sizes;
7.304 + std::vector<double> cum_sizes;
7.305 + for(int s=0;s<num_of_cities;s++)
7.306 + {
7.307 + // sum_sizes+=rnd.exponential();
7.308 + double d=rnd();
7.309 + sum_sizes+=d;
7.310 + sizes.push_back(d);
7.311 + cum_sizes.push_back(sum_sizes);
7.312 + }
7.313 + int i=0;
7.314 + for(int s=0;s<num_of_cities;s++)
7.315 + {
7.316 + Point center=(num_of_cities==1?Point(0,0):rnd.disc());
7.317 + if(gauss_d)
7.318 + for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
7.319 + Node n=g.addNode();
7.320 + nodes.push_back(n);
7.321 + coords[n]=center+rnd.gauss2()*area*
7.322 + std::sqrt(sizes[s]/sum_sizes);
7.323 + }
7.324 + else if(square_d)
7.325 + for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
7.326 + Node n=g.addNode();
7.327 + nodes.push_back(n);
7.328 + coords[n]=center+Point(rnd()*2-1,rnd()*2-1)*area*
7.329 + std::sqrt(sizes[s]/sum_sizes);
7.330 + }
7.331 + else if(disc_d || true)
7.332 + for(;i<N*(cum_sizes[s]/sum_sizes);i++) {
7.333 + Node n=g.addNode();
7.334 + nodes.push_back(n);
7.335 + coords[n]=center+rnd.disc()*area*
7.336 + std::sqrt(sizes[s]/sum_sizes);
7.337 + }
7.338 + }
7.339 +
7.340 + if(tsp_a) {
7.341 + tsp();
7.342 + std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl;
7.343 + }
7.344 + else if(two_a) {
7.345 + std::cout << "Make triangles\n";
7.346 + // triangle();
7.347 + sparseTriangle(girth);
7.348 + std::cout << "Make it sparser\n";
7.349 + sparse2(girth);
7.350 + }
7.351 + else if(tree_a) {
7.352 + minTree();
7.353 + }
7.354 +
7.355 +
7.356 + std::cout << "Number of nodes : " << countNodes(g) << std::endl;
7.357 + std::cout << "Number of edges : " << countUEdges(g) << std::endl;
7.358 + double tlen=0;
7.359 + for(UEdgeIt e(g);e!=INVALID;++e)
7.360 + tlen+=sqrt((coords[g.source(e)]-coords[g.target(e)]).normSquare());
7.361 + std::cout << "Total edge length : " << tlen << std::endl;
7.362 + if(eps)
7.363 + graphToEps(g,prefix+".eps").
7.364 + scale(600).nodeScale(.2).edgeWidthScale(.001).preScale(false).
7.365 + coords(coords).run();
7.366 +
7.367 + UGraphWriter<ListUGraph>(prefix+".lgf",g).
7.368 + writeNodeMap("coordinates_x",scaleMap(xMap(coords),600)).
7.369 + writeNodeMap("coordinates_y",scaleMap(yMap(coords),600)).
7.370 + run();
7.371 +}
7.372 +