# HG changeset patch # User ladanyi # Date 1116823694 0 # Node ID 8e85e6bbefdf4719317de6fc067815f128310dc5 # Parent d8475431bbbb65794b3728915ad53ab9437bca3e trunk/src/* move to trunk/ diff -r d8475431bbbb -r 8e85e6bbefdf Makefile.am --- a/Makefile.am Sat May 21 21:04:57 2005 +0000 +++ b/Makefile.am Mon May 23 04:48:14 2005 +0000 @@ -9,7 +9,10 @@ if WANT_DOCS MAYBE_DOC = doc endif -SUBDIRS = src $(MAYBE_DOC) +if WANT_GUI + MAYBE_GUI = gui +endif +SUBDIRS = lemon benchmark demo test $(MAYBE_GUI) $(MAYBE_DOC) MRPROPERFILES = \ aclocal.m4 \ @@ -26,19 +29,18 @@ config/mkinstalldirs \ doc/Makefile.in \ doc/doxygen.log \ - src/Makefile.in \ - src/lemon/Makefile.in \ - src/test/Makefile.in \ - src/benchmark/Makefile.in \ - src/demo/Makefile.in \ - src/gui/Makefile.in \ - src/gui/src/Makefile.in + Makefile.in \ + lemon/Makefile.in \ + test/Makefile.in \ + benchmark/Makefile.in \ + demo/Makefile.in \ + gui/Makefile.in docs: $(MAKE) -C doc $(AM_MAKEFLAGS) clean html benchmark: - $(MAKE) -C src/benchmark $(AM_MAKEFLAGS) + $(MAKE) -C benchmark $(AM_MAKEFLAGS) mrproper: $(MAKE) $(AM_MAKEFLAGS) maintainer-clean diff -r d8475431bbbb -r 8e85e6bbefdf benchmark/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/benchmark/Makefile.am Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,11 @@ +AM_CPPFLAGS = -I$(top_srcdir) + +noinst_HEADERS = bench_tools.h + +noinst_PROGRAMS = graph-bench hcube bfs-bench + +graph_bench_SOURCES = graph-bench.cc + +hcube_SOURCES = hcube.cc + +bfs_bench_SOURCES = bfs-bench.cc diff -r d8475431bbbb -r 8e85e6bbefdf benchmark/bench_tools.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/benchmark/bench_tools.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,128 @@ +// -*- mode:C++ -*- +#ifndef LEMON_BENCH_TEST_H +#define LEMON_BENCH_TEST_H + +#include +#include + +#include + +///An experimental typedef factory +#define GRAPH_TYPEDEF_FACTORY(Graph) \ + typedef typename Graph:: Node Node;\ + typedef typename Graph:: NodeIt NodeIt;\ + typedef typename Graph:: Edge Edge;\ + typedef typename Graph:: EdgeIt EdgeIt;\ + typedef typename Graph:: InEdgeIt InEdgeIt;\ + typedef typename Graph::OutEdgeIt OutEdgeIt; + +#define GRAPH_TYPEDEF_FACTORY_NOTYPENAME(Graph) \ + typedef Graph:: Node Node;\ + typedef Graph:: NodeIt NodeIt;\ + typedef Graph:: Edge Edge;\ + typedef Graph:: EdgeIt EdgeIt;\ + typedef Graph:: InEdgeIt InEdgeIt;\ + typedef Graph::OutEdgeIt OutEdgeIt; + + +///A primitive primtest + +///\bug 2 is not a prime according to this function! +/// +///\bug This function should go out of header file. I'm making it +/// inline for now. +inline bool isPrim(int n) +{ + if(n%2) { + for(int k=3;n/k>=k;k+=2) + if(!(n%k)) return false; + return true; + } + return false; +} + +///Finds the smallest prime not less then \c n. + +///\bug This function should go out of header file. I'm making it +/// inline for now. +inline int nextPrim(int n) +{ + for(n+=!(n%2);!isPrim(n);n+=2) ; + return n; +} + + +/// Class to generate consecutive primes +class Primes +{ + std::vector primes; + int n; + + bool isPrime(int m) + { + for(int i=0;m +void addHiperCube(Graph &G,int dim,std::vector &nodes) +{ + GRAPH_TYPEDEF_FACTORY(Graph); + + std::vector bits(dim+1); + bits[0]=1; + for(int i=1;i<=dim;i++) bits[i]=2*bits[i-1]; + + for(int i=0;i +void addBiDirHiperCube(Graph &G,int dim,std::vector&nodes) +{ + GRAPH_TYPEDEF_FACTORY(Graph); + + std::vector bits(dim+1); + bits[0]=1; + for(int i=1;i<=dim;i++) bits[i]=2*bits[i-1]; + + for(int i=0;i&2 + $2 $3 $4 $5 $6 $7 $8 $9 >/dev/null; + for ((i=1;i<=3;i++)) + do + $2 $3 $4 $5 $6 $7 $8 $9; + done | + awk '{print "'$1'",$0}' +} + +function runalltest() #postfix, CXX, CXXFLAGS +{ + echo $1 1>&2 + make clean >/dev/null + make CXX="$2" CXXFLAGS="$3" >/dev/null + { + runtest HCUBE19 hcube 19 + runtest BFS13-5000 hcube 13 5000 + runtest BFS10-50000 hcube 10 50000 + runtest GRBENCH graph-bench + } | awk "{print \$0, \"$1\"}" +} + +runalltest "gcc-3.3 -O2" g++ "-O2" +runalltest "gcc-3.3 -O2-march=pentium-m" g++ "-O2 -march=pentium-m" +runalltest "gcc-3.3 -O3" g++ "-O3" +runalltest "gcc-3.3 -O3-march=pentium-m" g++ "-O3 -march=pentium-m" + +runalltest "gcc-3.4 -O2" g++-3.4 "-O2" +runalltest "gcc-3.4 -O2-march=pentium-m" g++-3.4 "-O2 -march=pentium-m" +runalltest "gcc-3.4 -O3" g++-3.4 "-O3" +runalltest "gcc-3.4 -O3-march=pentium-m" g++-3.4 "-O3 -march=pentium-m" + +runalltest "icc -O2" icc "-O2" +runalltest "icc -O2-march=pentium-m" icc "-O2 -march=pentium-m" +runalltest "icc -O3" icc "-O3" +runalltest "icc -O3-march=pentium-m" icc "-O3 -march=pentium-m" + diff -r d8475431bbbb -r 8e85e6bbefdf benchmark/bfs-bench.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/benchmark/bfs-bench.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,144 @@ +// -*- mode:C++ -*- + +#include +#include +#include +#include"bench_tools.h" + +using namespace std; +using namespace lemon; + +inline int numOfOnes(int n,int dim) +{ + int s=0; + for(int i=0;i>=1; + } + return s; +} + +inline int numOfZeros(int n,int dim) +{ + int s=dim; + for(int i=0;i>=1; + } + return s; +} + +template +void bfsStlQueue(Graph &G,typename Graph::Node source) +{ + GRAPH_TYPEDEF_FACTORY(Graph); + + using namespace std; + + typename Graph::template NodeMap visited(G,false); + + queue Q; + + Q.push(source); + visited[source]=true; + do { + Node n(Q.front()); + Node m; + Q.pop(); + for(OutEdgeIt e(G,n);e!=INVALID;++e) + if(!visited[m=G.target(e)]) { + Q.push(m); + visited.set(m,true); + } + } while(!Q.empty()); +} + +template +void bfsOwnQueue(Graph &G,typename Graph::Node source) +{ + GRAPH_TYPEDEF_FACTORY(Graph); + + using namespace std; + + typename Graph::template NodeMap visited(G,false); + + int N=G.nodeNum(); + vector Q(N); + int Qh=0; + int Qt=0; + + + Q[Qh++]=source; + visited.set(source,true); + do { + Node m; + Node n=Q[Qt++]; + for(OutEdgeIt e(G,n);e!=INVALID;++e) + if(!visited[m=G.target(e)]) { + Q[Qh++]=m; + visited.set(m,true); + } + } while(Qt!=Qh); +} + +template +void iteratorBench(Graph &G) +{ + GRAPH_TYPEDEF_FACTORY(Graph); + + int i=0; + + for(NodeIt n(G);n!=INVALID;++n) + for(OutEdgeIt e(G,n);e!=INVALID;++e) + i++; +} + +int main(int argc, char *argv[]) +{ + typedef SmartGraph Graph; + + ///\bug GRAPH_TYPEDEF_FACTORY(Graph); + GRAPH_TYPEDEF_FACTORY_NOTYPENAME(Graph); + + Graph G; + + Timer T; + + if(argc!=3) { + cout << "Usage: " << argv[0] << " dim mul\n"; + return 1; + } + + int dim=atoi(argv[1]); + int mul=atoi(argv[2]); + +// cout << "Creating Hipercube ("<< (1< nodes; + addBiDirHiperCube(G,dim,nodes); + + PrintTime("GENGRAPH",T); + + T.reset(); + { + for(int i=0;i + +#include"bench_tools.h" + +using namespace lemon; + +///Makes a full graph by adding and deleting a lot of edges; + +///\param n Number of nodes. +///\param rat The funcion will make \f$rat\timesn^2\f$ edge addition and +///\f$(rat-1)\timesn^2\f$ deletion. +///\param p Tuning parameters. +///\warning \c rat, \c p, and \c n must be pairwise relative primes. +template +void makeFullGraph(int n, int rat, int p) +{ + GRAPH_TYPEDEF_FACTORY(Graph); + + Graph G; + + // Node nodes[n]; + std::vector nodes(n); + for(int i=0;i equ(rat); + + long long int count; + + for(count=0;count(nextPrim(1000),nextPrim(300),nextPrim(100)); + + PrintTime("BIG",T); + T.reset(); + makeFullGraph(nextPrim(100),nextPrim(30000),nextPrim(150)); + + PrintTime("SMALL",T); +} diff -r d8475431bbbb -r 8e85e6bbefdf benchmark/hcube.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/benchmark/hcube.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,106 @@ +// -*- mode:C++ -*- + +#include +#include +#include +#include +#include + +#include"bench_tools.h" + +using namespace std; +using namespace lemon; + +inline int numOfOnes(int n,int dim) +{ + int s=0; + for(int i=0;i>=1; + } + return s; +} + +inline int numOfZeros(int n,int dim) +{ + int s=dim; + for(int i=0;i>=1; + } + return s; +} + +int main(int argc, char *argv[]) +{ + // typedef ListGraph Graph; + typedef SmartGraph Graph; + + ///\bug GRAPH_TYPEDEF_FACTORY(Graph); + GRAPH_TYPEDEF_FACTORY_NOTYPENAME(Graph); + + Graph G; + + Timer T; + + if(argc!=2) { + cout << "Usage: " << argv[0] << " dim\n"; + return 1; + } + + int dim=atoi(argv[1]); + +// cout << "Creating Hipercube ("<< (1< nodes; + addBiDirHiperCube(G,dim,nodes); + + PrintTime("GENGRAPH",T); + + T.reset(); + Graph::EdgeMap map(G); + for(int i=0;i<5;i++) { + Primes P; + for(int i=0;i Dij(G,map); + for(int i=0;i<10;i++) + Dij.run(nodes[0]); + } + PrintTime("DIJKSTRA",T); + + T.reset(); + { + Graph::EdgeMap flow(G); + + Preflow MF(G,nodes[0],nodes[1< + +#include +#include +#include +#include + +using namespace std; +using namespace lemon; + +int main() { + typedef UndirSmartGraph Graph; + typedef Graph::Node Node; + typedef Graph::NodeIt NodeIt; + typedef Graph::UndirEdge UndirEdge; + typedef Graph::IncEdgeIt IncEdgeIt; + + Graph graph; + + UndirGraphReader reader(std::cin, graph); + Graph::NodeMap > coords(graph); + reader.readNodeMap("coords", coords); + + reader.run(); + + Graph::NodeMap color(graph, -2); + + Graph::NodeMap heapMap(graph, -1); + BinHeap > heap(heapMap); + + for (NodeIt it(graph); it != INVALID; ++it) { + heap.push(it, countOutEdges(graph, it)); + } + + vector order; + + while (!heap.empty()) { + Node node = heap.top(); + heap.pop(); + color[node] = -1; + order.push_back(node); + for (IncEdgeIt it(graph, node); it != INVALID; ++it) { + Node target = graph.runningNode(it); + if (color[target] == -2) { + heap.decrease(target, heap[target] - 1); + } + } + } + + for (int i = order.size() - 1; i >= 0; --i) { + set forbidden; + for (IncEdgeIt it(graph, order[i]); it != INVALID; ++it) { + Node target = graph.runningNode(it); + if (color[target] != -1) { + forbidden.insert(color[target]); + } + } + int current = 0; + while (forbidden.find(current) != forbidden.end()) ++current; + color[order[i]] = current; + } + + ColorSet colorSet; + + graphToEps(graph, "six_coloring.eps"). + title("Six Colored Graph").copyright("(C) 2005 LEMON Project"). + coords(coords).nodeColors(composeMap(colorSet, color)). + scaleToA4().run(); + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf demo/dijkstra_demo.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/dijkstra_demo.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,75 @@ +#include + +#include +#include + +using namespace lemon; + + +int main (int, char*[]) +{ + + typedef ListGraph Graph; + typedef Graph::Node Node; + typedef Graph::Edge Edge; + typedef Graph::EdgeMap LengthMap; + + Graph g; + + //An example from Ahuja's book + + Node s=g.addNode(); + Node v2=g.addNode(); + Node v3=g.addNode(); + Node v4=g.addNode(); + Node v5=g.addNode(); + Node t=g.addNode(); + + Edge s_v2=g.addEdge(s, v2); + Edge s_v3=g.addEdge(s, v3); + Edge v2_v4=g.addEdge(v2, v4); + Edge v2_v5=g.addEdge(v2, v5); + Edge v3_v5=g.addEdge(v3, v5); + Edge v4_t=g.addEdge(v4, t); + Edge v5_t=g.addEdge(v5, t); + + LengthMap len(g); + + len.set(s_v2, 10); + len.set(s_v3, 10); + len.set(v2_v4, 5); + len.set(v2_v5, 8); + len.set(v3_v5, 5); + len.set(v4_t, 8); + len.set(v5_t, 8); + + std::cout << "The id of s is " << g.id(s)<< ", the id of t is " << g.id(t)<<"."< dijkstra_test(g,len); + + dijkstra_test.run(s); + + + std::cout << "The distance of node t from node s: " << dijkstra_test.dist(t)< dot_output_file +// This program makes a dot file from a dimacs max flow file. +// This program can be an aid in making up to date visualized documantation +// of demo programs. + +#include +#include + +#include +#include + +using namespace lemon; + +using std::cout; +using std::endl; + +int main() +{ + typedef SmartGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef Graph::EdgeMap LengthMap; + + Graph g; + Node s, t; + LengthMap length(g); + + readDimacs(std::cin, g, length, s, t); + + cout << "digraph lemon_dot_example {" << endl; + cout << " node [ shape=ellipse, fontname=Helvetica, fontsize=10 ];" << endl; + for(NodeIt n(g); n!=INVALID; ++n) { + if (n==s) { + cout << " n" << g.id(n) + << " [ label=\"" << g.id(n) << " (s)\" ]; " << endl; + } else { + if (n==t) { + cout << " n" << g.id(n) + << " [ label=\"" << g.id(n) << " (t)\" ]; " << endl; + } else { + cout << " n" << g.id(n) + << " [ label=\"" << g.id(n) << "\" ]; " << endl; + } + } + } + cout << " edge [ shape=ellipse, fontname=Helvetica, fontsize=10 ];" << endl; + for(EdgeIt e(g); e!=INVALID; ++e) { + cout << " n" << g.id(g.source(e)) << " -> " << " n" << g.id(g.target(e)) + << " [ label=\"" << g.id(e) + << ", length:" << length[e] << "\" ]; " << endl; + } + cout << "}" << endl; +} diff -r d8475431bbbb -r 8e85e6bbefdf demo/dim_to_lgf.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/dim_to_lgf.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,166 @@ +#include +#include +#include + +#include +#include +#include + +using namespace std; +using namespace lemon; + +const char* versionString = +"dim_to_lgf - part of lemon library\n"; + +const char* helpString = +"Dimacs to LGF converter\n" +"Usage: dim_to_lgf [OPTIONS]\n" +"\n" +"Examples:\n" +" dim_to_lgf --type shortestpath --input graph.dim --output graph.lgf\n" +"\n" +"Options:\n" +" -i FILE, --input FILE use FILE as input instead of standard input\n" +" -o FILE, --output FILE use FILE as output instead of standard output\n" +" -t TYPE, --type TYPE set up the type of the graph\n" +" Possible types:\n" +" mincostflow\n" +" maxflow (default)\n" +" shortestpath\n" +" capacitated\n" +" plain\n" +" -v, --version shows the version of the converter\n" +" -h, --help shows the help of the converter\n"; + + +int main(int argc, const char *argv[]) { + typedef SmartGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef Graph::EdgeMap StringMap; + + std::string inputName; + std::string outputName; + std::string typeName; + + bool help = false; + bool version = false; + + for (int arg = 1; arg < argc; ++arg) { + if (strcmp(argv[arg], "--type") == 0 || + strcmp(argv[arg], "-t") == 0) { + if (!typeName.empty()) { + cerr << "Multiple type description" << endl; + return -1; + } + if (arg + 1 == argc) { + cerr << "Parameter without value" << endl; + return -1; + } + typeName = argv[++arg]; + } + else if (strcmp(argv[arg], "--input") == 0 || + strcmp(argv[arg], "-i") == 0) { + if (!inputName.empty()) { + cerr << "Multiple input description" << endl; + return -1; + } + if (arg + 1 == argc) { + cerr << "Parameter without value" << endl; + return -1; + } + inputName = argv[++arg]; + } + else if (strcmp(argv[arg], "--output") == 0 || + strcmp(argv[arg], "-o") == 0) { + if (!outputName.empty()) { + cerr << "Multiple input description" << endl; + return -1; + } + if (arg + 1 == argc) { + cerr << "Parameter without value" << endl; + return -1; + } + outputName = argv[++arg]; + } else if (strcmp(argv[arg], "--help") == 0 || + strcmp(argv[arg], "-h") == 0) { + help = true; + } else if (strcmp(argv[arg], "--version") == 0 || + strcmp(argv[arg], "-v") == 0) { + version = true; + } else { + cerr << "Invalid option: " << argv[arg] << endl; + return -1; + } + } + + if (version) { + cout << versionString; + } + if (help) { + cout << helpString; + } + if (help || version) { + return 0; + } + + ifstream input; + if (!inputName.empty()) { + input.open(inputName.c_str()); + if (!input) { + cerr << "File open error" << endl; + return -1; + } + } + istream& is = (inputName.empty() ? cin : input); + + ofstream output; + if (!outputName.empty()) { + output.open(outputName.c_str()); + if (!output) { + cerr << "File open error" << endl; + return -1; + } + } + ostream& os = (outputName.empty() ? cout : output); + + if (typeName.empty()) { + typeName = "maxflow"; + } + + if (typeName == "mincostflow") { + Graph graph; + Node s, t; + StringMap cost(graph), capacity(graph); + readDimacs(is, graph, capacity, s, t, cost); + writeGraph(os, graph, capacity, s, t, cost); + } else if (typeName == "maxflow") { + Graph graph; + Node s, t; + StringMap capacity(graph); + readDimacs(is, graph, capacity, s, t); + writeGraph(os, graph, capacity, s, t); + } else if (typeName == "shortestpath") { + Graph graph; + Node s; + StringMap capacity(graph); + readDimacs(is, graph, capacity, s); + writeGraph(os, graph, capacity, s); + } else if (typeName == "capacitated") { + Graph graph; + StringMap capacity(graph); + readDimacs(is, graph, capacity); + writeGraph(os, graph, capacity); + } else if (typeName == "plain") { + Graph graph; + readDimacs(is, graph); + writeGraph(os, graph); + } else { + cerr << "Invalid type error" << endl; + return -1; + } + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf demo/graph_to_eps_demo.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/graph_to_eps_demo.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,168 @@ +/* -*- C++ -*- + * demo/graph_to_eps.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include +#include +#include + +#include + + +using namespace std; +using namespace lemon; + +int main() +{ + ColorSet colorSet; + + ListGraph g; + typedef ListGraph::Node Node; + typedef ListGraph::NodeIt NodeIt; + typedef ListGraph::Edge Edge; + typedef xy Xy; + + Node n1=g.addNode(); + Node n2=g.addNode(); + Node n3=g.addNode(); + Node n4=g.addNode(); + Node n5=g.addNode(); + + ListGraph::NodeMap coords(g); + ListGraph::NodeMap sizes(g); + ListGraph::NodeMap colors(g); + ListGraph::NodeMap shapes(g); + ListGraph::EdgeMap ecolors(g); + ListGraph::EdgeMap widths(g); + + coords[n1]=Xy(50,50); sizes[n1]=1; colors[n1]=1; shapes[n1]=0; + coords[n2]=Xy(50,70); sizes[n2]=2; colors[n2]=2; shapes[n2]=2; + coords[n3]=Xy(70,70); sizes[n3]=1; colors[n3]=3; shapes[n3]=0; + coords[n4]=Xy(70,50); sizes[n4]=2; colors[n4]=4; shapes[n4]=1; + coords[n5]=Xy(85,60); sizes[n5]=3; colors[n5]=5; shapes[n5]=2; + + Edge e; + + e=g.addEdge(n1,n2); ecolors[e]=0; widths[e]=1; + e=g.addEdge(n2,n3); ecolors[e]=0; widths[e]=1; + e=g.addEdge(n3,n5); ecolors[e]=0; widths[e]=3; + e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1; + e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1; + e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2; + e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1; + + IdMap id(g); + + graphToEps(g,"graph_to_eps_demo_out.eps").scale(10).coords(coords). + title("Sample .eps figure"). + copyright("(C) 2005 LEMON Project"). + nodeScale(2).nodeSizes(sizes). + nodeShapes(shapes). + nodeColors(composeMap(colorSet,colors)). + edgeColors(composeMap(colorSet,ecolors)). + edgeWidthScale(.4).edgeWidths(widths). + nodeTexts(id).nodeTextSize(3). + run(); + + graphToEps(g,"graph_to_eps_demo_out_arr.eps").scale(10). + title("Sample .eps figure (with arrowheads)"). + copyright("(C) 2005 LEMON Project"). + nodeColors(composeMap(colorSet,colors)). + coords(coords). + nodeScale(2).nodeSizes(sizes). + nodeShapes(shapes). + edgeColors(composeMap(colorSet,ecolors)). + edgeWidthScale(.4).edgeWidths(widths). + nodeTexts(id).nodeTextSize(3). + drawArrows().arrowWidth(1).arrowLength(1). + run(); + + e=g.addEdge(n1,n4); ecolors[e]=2; widths[e]=1; + e=g.addEdge(n4,n1); ecolors[e]=1; widths[e]=2; + + e=g.addEdge(n1,n2); ecolors[e]=1; widths[e]=1; + e=g.addEdge(n1,n2); ecolors[e]=2; widths[e]=1; + e=g.addEdge(n1,n2); ecolors[e]=3; widths[e]=1; + e=g.addEdge(n1,n2); ecolors[e]=4; widths[e]=1; + e=g.addEdge(n1,n2); ecolors[e]=5; widths[e]=1; + e=g.addEdge(n1,n2); ecolors[e]=6; widths[e]=1; + e=g.addEdge(n1,n2); ecolors[e]=7; widths[e]=1; + + graphToEps(g,"graph_to_eps_demo_out_par.eps").scale(10). + title("Sample .eps figure (parallel edges)"). + copyright("(C) 2005 LEMON Project"). + nodeShapes(shapes). + coords(coords). + nodeScale(2).nodeSizes(sizes). + nodeColors(composeMap(colorSet,colors)). + edgeColors(composeMap(colorSet,ecolors)). + edgeWidthScale(.4).edgeWidths(widths). + nodeTexts(id).nodeTextSize(3). + enableParallel().parEdgeDist(1.5). + run(); + + graphToEps(g,"graph_to_eps_demo_out_par_arr.eps").scale(10). + title("Sample .eps figure (parallel edges and arrowheads)"). + copyright("(C) 2005 LEMON Project"). + nodeScale(2).nodeSizes(sizes). + coords(coords). + nodeShapes(shapes). + nodeColors(composeMap(colorSet,colors)). + edgeColors(composeMap(colorSet,ecolors)). + edgeWidthScale(.3).edgeWidths(widths). + nodeTexts(id).nodeTextSize(3). + enableParallel().parEdgeDist(1). + drawArrows().arrowWidth(1).arrowLength(1). + run(); + + graphToEps(g,"graph_to_eps_demo_out_a4.eps").scaleToA4(). + title("Sample .eps figure (fits to A4)"). + copyright("(C) 2005 LEMON Project"). + nodeScale(2).nodeSizes(sizes). + coords(coords). + nodeShapes(shapes). + nodeColors(composeMap(colorSet,colors)). + edgeColors(composeMap(colorSet,ecolors)). + edgeWidthScale(.3).edgeWidths(widths). + nodeTexts(id).nodeTextSize(3). + enableParallel().parEdgeDist(1). + drawArrows().arrowWidth(1).arrowLength(1). + run(); + + ListGraph h; + ListGraph::NodeMap hcolors(h); + ListGraph::NodeMap hcoords(h); + + int cols=int(sqrt(double(colorSet.size()))); + for(int i=0;i +#include + +using namespace lemon; + +int main() +{ + typedef ListGraph Graph; + typedef Graph::Edge Edge; + typedef Graph::InEdgeIt InEdgeIt; + typedef Graph::OutEdgeIt OutEdgeIt; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::Node Node; + typedef Graph::NodeIt NodeIt; + + Graph g; + + for (int i = 0; i < 3; i++) + g.addNode(); + + for (NodeIt i(g); i!=INVALID; ++i) + for (NodeIt j(g); j!=INVALID; ++j) + if (i != j) g.addEdge(i, j); + + std::cout << "Nodes:"; + for (NodeIt i(g); i!=INVALID; ++i) + std::cout << " " << g.id(i); + std::cout << std::endl; + + std::cout << "Edges:"; + for (EdgeIt i(g); i!=INVALID; ++i) + std::cout << " (" << g.id(g.source(i)) << "," << g.id(g.target(i)) << ")"; + std::cout << std::endl; +} diff -r d8475431bbbb -r 8e85e6bbefdf demo/kruskal_demo.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/kruskal_demo.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,95 @@ +#include +#include + +#include +#include +#include + + +using namespace std; +using namespace lemon; + + +int main() { + + typedef ListGraph::Node Node; + typedef ListGraph::Edge Edge; + typedef ListGraph::NodeIt NodeIt; + typedef ListGraph::EdgeIt EdgeIt; + + ListGraph G; + + Node s=G.addNode(); + Node v1=G.addNode(); + Node v2=G.addNode(); + Node v3=G.addNode(); + Node v4=G.addNode(); + Node t=G.addNode(); + + Edge e1 = G.addEdge(s, v1); + Edge e2 = G.addEdge(s, v2); + Edge e3 = G.addEdge(v1, v2); + Edge e4 = G.addEdge(v2, v1); + Edge e5 = G.addEdge(v1, v3); + Edge e6 = G.addEdge(v3, v2); + Edge e7 = G.addEdge(v2, v4); + Edge e8 = G.addEdge(v4, v3); + Edge e9 = G.addEdge(v3, t); + Edge e10 = G.addEdge(v4, t); + + typedef ListGraph::EdgeMap ECostMap; + typedef ListGraph::EdgeMap EBoolMap; + + ECostMap edge_cost_map(G, 2); + EBoolMap tree_map(G); + + + //Test with const map. + std::cout << "The weight of the minimum spanning tree is " << kruskalEdgeMap(G, ConstMap(2), tree_map)< tree_edge_vec; + + //Test with a edge map and inserter. + check(kruskalEdgeMap_IteratorOut(G, edge_cost_map, + back_inserter(tree_edge_vec)) + ==-31, + "Total cost should be -31."); + + tree_edge_vec.clear(); + + //The above test could also be coded like this: + check(kruskal(G, + makeKruskalMapInput(G, edge_cost_map), + makeKruskalSequenceOutput(back_inserter(tree_edge_vec))) + ==-31, + "Total cost should be -31."); + + check(tree_edge_vec.size()==5,"The tree should have 5 edges."); + + check(tree_edge_vec[0]==e1 && + tree_edge_vec[1]==e2 && + tree_edge_vec[2]==e5 && + tree_edge_vec[3]==e7 && + tree_edge_vec[4]==e9, + "Wrong tree."); +*/ + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf demo/lp_demo.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/lp_demo.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,113 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + + +#ifdef HAVE_GLPK +#include +#elif HAVE_CPLEX +#include +#endif + +using namespace lemon; + +#ifdef HAVE_GLPK +typedef LpGlpk LpDefault; +#elif HAVE_CPLEX +typedef LpCplex LpDefault; +#endif + +int main() +{ + //The following example is taken from the documentation of the GLPK library. + //See it in the GLPK reference manual and among the GLPK sample files (sample.c) + LpDefault lp; + typedef LpDefault::Row Row; + typedef LpDefault::Col Col; + + lp.max(); + + Col x1 = lp.addCol(); + Col x2 = lp.addCol(); + Col x3 = lp.addCol(); + + //One solution + // Row p = lp.addRow(); + // Row q = lp.addRow(); + // Row r = lp.addRow(); + // lp.setRow(p,x1+x2+x3 <=100); + // lp.setRow(q,10*x1+4*x2+5*x3<=600); + // lp.setRow(r,2*x1+2*x2+6*x3<=300); + + //A more elegant one + //Constraints + lp.addRow(x1+x2+x3 <=100); + lp.addRow(10*x1+4*x2+5*x3<=600); + lp.addRow(2*x1+2*x2+6*x3<=300); + //Nonnegativity of the variables + lp.colLowerBound(x1, 0); + lp.colLowerBound(x2, 0); + lp.colLowerBound(x3, 0); + //Objective function + lp.setObj(10*x1+6*x2+4*x3); + + lp.solve(); + + if (lp.primalStatus()==LpSolverBase::OPTIMAL){ + printf("Z = %g; x1 = %g; x2 = %g; x3 = %g\n", + lp.primalValue(), + lp.primal(x1), lp.primal(x2), lp.primal(x3)); + } + else{ + std::cout<<"Optimal solution not found!"< +#endif + +#include +#include + + +#ifdef HAVE_GLPK +#include +#elif HAVE_CPLEX +#include +#endif + +using namespace lemon; + +#ifdef HAVE_GLPK +typedef LpGlpk LpDefault; +#elif HAVE_CPLEX +typedef LpCplex LpDefault; +#endif + + +template +double maxFlow(const G &g,const C &cap,typename G::Node s,typename G::Node t) +{ + LpDefault lp; + + typedef G Graph; + typedef typename G::Node Node; + typedef typename G::NodeIt NodeIt; + typedef typename G::Edge Edge; + typedef typename G::EdgeIt EdgeIt; + typedef typename G::OutEdgeIt OutEdgeIt; + typedef typename G::InEdgeIt InEdgeIt; + + typename G::template EdgeMap x(g); + lp.addColSet(x); + + for(EdgeIt e(g);e!=INVALID;++e) { + lp.colUpperBound(x[e],cap[e]); + lp.colLowerBound(x[e],0); + } + + for(NodeIt n(g);n!=INVALID;++n) if(n!=s&&n!=t) { + LpDefault::Expr ex; + for(InEdgeIt e(g,n);e!=INVALID;++e) ex+=x[e]; + for(OutEdgeIt e(g,n);e!=INVALID;++e) ex-=x[e]; + lp.addRow(ex==0); + } + { + LpDefault::Expr ex; + for(InEdgeIt e(g,t);e!=INVALID;++e) ex+=x[e]; + for(OutEdgeIt e(g,t);e!=INVALID;++e) ex-=x[e]; + lp.setObj(ex); + } + lp.max(); + +#ifdef HAVE_GLPK + lp.presolver(true); + lp.messageLevel(3); +#endif + + lp.solve(); + + return lp.primalValue(); +} + +int main() +{ + ListGraph g; + ListGraph::Node s; + ListGraph::Node t; + + ListGraph::EdgeMap cap(g); + + GraphReader reader(std::cin,g); + reader.readNode("source",s).readNode("target",t) + .readEdgeMap("capacity",cap).run(); + + // std::ifstream file("../test/preflow_"); +// readDimacs(file, g, cap, s, t); + + std::cout << "Max flow value = " << maxFlow(g,cap,s,t) << std::endl; + +} diff -r d8475431bbbb -r 8e85e6bbefdf demo/min_route.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/min_route.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,114 @@ +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + + +using namespace lemon; + +template +class PotentialMap { +public: + typedef double Value; + typedef typename CoordMap::Key Key; + + PotentialMap(const CoordMap& _coord, const xy& _target) + : coord(_coord), target(_target) {} + + double operator[](const Key& node) const { + return std::sqrt((coord[node].x - target.x) * (coord[node].x - target.x) + + (coord[node].y - target.y) * (coord[node].y - target.y)); + } +private: + const CoordMap& coord; + xy target; +}; + +template +class ReducedLengthMap { +public: + typedef double Value; + typedef typename LengthMap::Key Key; + + ReducedLengthMap(const Graph& _graph, const LengthMap& _length, + const PotentialMap& _pot) + : graph(_graph), length(_length), pot(_pot) {} + + Value operator[](const Key& edge) const { + return length[edge] - (pot[graph.source(edge)] - pot[graph.target(edge)]); + } + +private: + const Graph& graph; + const LengthMap& length; + const PotentialMap& pot; +}; + +int main() { + typedef SmartGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef Graph::EdgeMap LengthMap; + typedef Graph::NodeMap > CoordMap; + + SmartGraph graph; + + std::ifstream is("route.lgf"); + GraphReader reader(is, graph); + + CoordMap coord(graph); + XMap xcoord = xMap(coord); + reader.readNodeMap("coordinates_x", xcoord); + YMap ycoord = yMap(coord); + reader.readNodeMap("coordinates_y", ycoord); + + LengthMap length(graph); + reader.readEdgeMap("length", length); + + Node source, target; + reader.readNode("source", source); + reader.readNode("target", target); + + reader.run(); + + { + Timer timer; + Dijkstra dijkstra(graph, length); + dijkstra.init(); + dijkstra.addSource(source); + dijkstra.start(target); + + std::cout << dijkstra.dist(target) << std::endl; + std::cout << timer << std::endl; + } + { + Timer timer; + typedef PotentialMap Potential; + Potential potential(coord, coord[target]); + + typedef ReducedLengthMap ReducedLength; + ReducedLength reduced(graph, length, potential); + + Dijkstra dijkstra(graph, reduced); + + dijkstra.init(); + dijkstra.addSource(source); + dijkstra.start(target); + + std::cout << dijkstra.dist(target) + potential[source] << std::endl; + std::cout << timer << std::endl; + } + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf demo/route.lgf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/route.lgf Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,41 @@ +@nodeset +id coordinates_x coordinates_y +9 447.907 578.328 +8 79.2573 909.464 +7 878.677 960.04 +6 11.5504 938.413 +5 327.398 815.035 +4 427.002 954.002 +3 148.549 753.748 +2 903.889 326.476 +1 408.248 577.327 +0 189.239 92.5316 +@edgeset + length +2 3 901.074 +8 5 270.85 +6 9 601.553 +5 9 285.022 +9 4 408.091 +3 0 719.712 +7 5 612.836 +0 4 933.353 +5 0 778.871 +5 5 0 +7 1 664.049 +5 5 0 +0 9 560.464 +4 8 352.36 +4 9 399.625 +4 1 402.171 +1 2 591.688 +3 8 182.376 +4 5 180.254 +3 1 345.283 +5 4 184.511 +6 2 1112.45 +0 1 556.624 +@nodes +source 1 +target 8 +@end diff -r d8475431bbbb -r 8e85e6bbefdf demo/sub_graph_adaptor_demo.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/sub_graph_adaptor_demo.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,80 @@ +// -*- c++ -*- + +// Use a DIMACS max flow file as stdin. +// sub_graph_adaptor_demo < dimacs_max_flow_file +// This program computes a maximum number of edge-disjoint shortest paths +// between s and t. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace lemon; + +using std::cout; +using std::endl; + +int main() +{ + typedef SmartGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef Graph::EdgeMap LengthMap; + + Graph g; + Node s, t; + LengthMap length(g); + + readDimacs(std::cin, g, length, s, t); + + cout << "edges with lengths (of form id, source--length->target): " << endl; + for(EdgeIt e(g); e!=INVALID; ++e) + cout << " " << g.id(e) << ", " << g.id(g.source(e)) << "--" + << length[e] << "->" << g.id(g.target(e)) << endl; + + cout << "s: " << g.id(s) << " t: " << g.id(t) << endl; + + typedef Dijkstra Dijkstra; + Dijkstra dijkstra(g, length); + dijkstra.run(s); + + // This map returns true exactly for those edges which are + // tight w.r.t the length funcion and the potential + // given by the dijkstra algorithm. + typedef TightEdgeFilterMap + TightEdgeFilter; + TightEdgeFilter tight_edge_filter(g, dijkstra.distMap(), length); + +// ConstMap const_true_map(true); + // This graph contains exaclty the tight edges. +// typedef SubGraphAdaptor, TightEdgeFilter> SubGW; + typedef EdgeSubGraphAdaptor SubGW; + SubGW gw(g, tight_edge_filter); + + ConstMap const_1_map(1); + Graph::EdgeMap flow(g, 0); + // Max flow between s and t in the graph of tight edges. + Preflow, Graph::EdgeMap > + preflow(gw, s, t, const_1_map, flow); + preflow.run(); + + cout << "maximum number of edge-disjoint shortest path: " + << preflow.flowValue() << endl; + cout << "edges of the maximum number of edge-disjoint shortest s-t paths: " + << endl; + for(EdgeIt e(g); e!=INVALID; ++e) + if (flow[e]) + cout << " " << g.id(e) << ", " + << g.id(g.source(e)) << "--" + << length[e] << "->" << g.id(g.target(e)) << endl; +} diff -r d8475431bbbb -r 8e85e6bbefdf demo/sub_graph_adaptor_demo.dim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/sub_graph_adaptor_demo.dim Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,14 @@ +c LEMON max flow problem +p max 7 9 +n 1 s +n 7 t +a 1 2 3 +a 1 3 2 +a 1 4 1 +a 2 5 3 +a 3 5 2 +a 3 7 5 +a 3 6 3 +a 4 6 1 +a 5 7 2 +a 6 7 4 diff -r d8475431bbbb -r 8e85e6bbefdf demo/tight_edge_filter_map.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demo/tight_edge_filter_map.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,68 @@ +/* -*- C++ -*- + * demo/tight_edge_filter_map.h - Part of LEMON, a generic C++ optimization + * library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_TIGHT_EDGE_FILTER_MAP_H +#define LEMON_TIGHT_EDGE_FILTER_MAP_H + +#include + +// /// \file +// /// \brief Maximum flow algorithms. +// /// \ingroup galgs + +namespace lemon { + + /*! + \brief A map for filtering the edge-set to those edges + which are tight w.r.t. a node-potential and + edge-distance. + + Let \f$G=(V,A)\f$ be a directed graph (graph for short) and + let \f$\mathbb{F}\f$ be a number type. + Given a distance function + \f$d:E\to\mathbb{F}\f$, + \f$\pi:V\to\mathbb{F}\f$ is said to be a potetial + w.r.t. \f$d\f$ + if and only if + \f$\pi(v)\le d(uv)+\pi(u)\f$ holds for each edge \f$uv\in E\f$ + (or the reverse inequality holds for each edge). + An edge is said to be tight if this inequality holds with equality, + and the map returns \c true exactly for those edges. + To avoid rounding errors, it is recommended to use this class with exact + number types, e.g. with \c int. + */ + template + class TightEdgeFilterMap : public MapBase { + protected: + const Graph* g; + NodePotentialMap* node_potential; + EdgeDistanceMap* edge_distance; + public: + TightEdgeFilterMap(Graph& _g, NodePotentialMap& _node_potential, + EdgeDistanceMap& _edge_distance) : + g(&_g), node_potential(&_node_potential), + edge_distance(&_edge_distance) { } + bool operator[](const typename Graph::Edge& e) const { + return ((*node_potential)[g->target(e)] == + (*edge_distance)[e]+(*node_potential)[g->source(e)]); + } + }; + +} //namespace lemon + +#endif //LEMON_TIGHT_EDGE_FILTER_MAP_H diff -r d8475431bbbb -r 8e85e6bbefdf doc/Doxyfile.in --- a/doc/Doxyfile.in Sat May 21 21:04:57 2005 +0000 +++ b/doc/Doxyfile.in Mon May 23 04:48:14 2005 +0000 @@ -115,7 +115,7 @@ # If left blank the directory from which doxygen is run is used as the # path to strip. -STRIP_FROM_PATH = @abs_top_srcdir@/src +STRIP_FROM_PATH = @abs_top_srcdir@ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells @@ -124,7 +124,7 @@ # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. -STRIP_FROM_INC_PATH = @abs_top_srcdir@/src +STRIP_FROM_INC_PATH = @abs_top_srcdir@ # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems @@ -451,11 +451,11 @@ # with spaces. INPUT = @abs_top_srcdir@/doc \ - @abs_top_srcdir@/src/lemon \ - @abs_top_srcdir@/src/lemon/bits \ - @abs_top_srcdir@/src/lemon/concept \ - @abs_top_srcdir@/src/demo \ - @abs_top_srcdir@/src/test/test_tools.h + @abs_top_srcdir@/lemon \ + @abs_top_srcdir@/lemon/bits \ + @abs_top_srcdir@/lemon/concept \ + @abs_top_srcdir@/demo \ + @abs_top_srcdir@/test/test_tools.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp @@ -494,7 +494,7 @@ # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = ../src/demo \ +EXAMPLE_PATH = ../demo \ ../LICENSE \ . diff -r d8475431bbbb -r 8e85e6bbefdf doc/template.h --- a/doc/template.h Sat May 21 21:04:57 2005 +0000 +++ b/doc/template.h Mon May 23 04:48:14 2005 +0000 @@ -1,5 +1,5 @@ /* -*- C++ -*- - * src/lemon/template.h - Part of LEMON, a generic C++ optimization library + * lemon/template.h - Part of LEMON, a generic C++ optimization library * * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). diff -r d8475431bbbb -r 8e85e6bbefdf gui/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/Makefile.am Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,19 @@ +AM_CPPFLAGS = -I$(top_srcdir) +LDADD = $(top_builddir)/lemon/libemon.la + +bin_PROGRAMS = gd + +gd_SOURCES = \ + all_include.h \ + graph_displayer_canvas.cc \ + graph_displayer_canvas.h \ + graph-displayer.cc \ + main_win.cc \ + main_win.h \ + mapstorage.cc \ + mapstorage.h \ + map_win.cc \ + map_win.h + +gd_CXXFLAGS = $(GTK_CFLAGS) +gd_LDFLAGS = $(GTK_LIBS) diff -r d8475431bbbb -r 8e85e6bbefdf gui/all_include.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/all_include.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,39 @@ +// -*- C++ -*- // + +#ifndef ALL_INCLUDE_H +#define ALL_INCLUDE_H + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +enum {WIDTH, COLOR, TEXT, PROPERTY_NUM};// properties; +#define RANGE 3 +#define WIN_WIDTH 900 +#define WIN_HEIGHT 600 + + +#ifndef MAIN_PART +extern std::string * property_strings; +extern double * property_defaults; +#endif //MAIN_PART + +using namespace lemon; + +typedef xy Coordinates; +typedef ListGraph Graph; +typedef Graph::NodeMap CoordinatesMap; +typedef Graph::Node Node; +typedef Graph::EdgeIt EdgeIt; +typedef Graph::NodeIt NodeIt; + +#endif // ALL_INCLUDE_H diff -r d8475431bbbb -r 8e85e6bbefdf gui/graph-displayer.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/graph-displayer.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include + +#define MAIN_PART + +std::string * property_strings; +double * property_defaults; + + +int main(int argc, char *argv[]) +{ + property_strings=new std::string[PROPERTY_NUM]; + property_strings[WIDTH]="Width"; + property_strings[COLOR]="Color"; + property_strings[TEXT]="Text"; + + property_defaults=new double[PROPERTY_NUM]; + property_defaults[WIDTH]=10.0; + property_defaults[COLOR]=100; + property_defaults[TEXT]=0; + + if(argc<2) + { + std::cerr << "USAGE: gd " << std::endl; + return 0; + } + + Coordinates coosvector; + + Graph g; + + CoordinatesMap cm(g); + Graph::EdgeMap cap(g), map1(g), map2(g), map3(g), map4(g); + + //we create one object to read x coordinates + //and one to read y coordinate of nodes and write them to cm NodeMap. + + XMap xreader (cm); + YMap yreader (cm); + Graph::NodeMap nodedata (g); + + std::ifstream is(argv[1]); + + GraphReader reader(is, g); + reader.readNodeMap("coordinates_x", xreader); + reader.readNodeMap("coordinates_y", yreader); + reader.readNodeMap("data", nodedata); + reader.readEdgeMap("cap", cap); + reader.readEdgeMap("map1", map1); + reader.readEdgeMap("map2", map2); + reader.readEdgeMap("map3", map3); + reader.readEdgeMap("map4", map4); + reader.run(); + + MapStorage ms(g); + ms.addNodeMap("data",&nodedata); + ms.addEdgeMap("cap",&cap); + ms.addEdgeMap("map1",&map1); + ms.addEdgeMap("map2",&map2); + ms.addEdgeMap("map3",&map3); + ms.addEdgeMap("map4",&map4); + + Gnome::Canvas::init(); + Gtk::Main app(argc, argv); + + MainWin mainwin("Displayed Graph", g, cm, ms); + app.run(mainwin); + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf gui/graph_displayer_canvas.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/graph_displayer_canvas.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,259 @@ +#include + +GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & gr, CoordinatesMap & cm, MapStorage & ms):g(gr),nodesmap(g),edgesmap(g),edgetextmap(g),displayed_graph(*(root()), 0, 0),mapstorage(ms),isbutton(false),active_item(NULL) +{ + + for (EdgeIt i(g); i!=INVALID; ++i) + { + Gnome::Canvas::Points coos; + coos.push_back(Gnome::Art::Point(cm[g.source(i)].x,cm[g.source(i)].y)); + coos.push_back(Gnome::Art::Point(cm[g.target(i)].x,cm[g.target(i)].y)); + + edgesmap[i]=new Gnome::Canvas::Line(displayed_graph, coos); + *(edgesmap[i]) << Gnome::Canvas::Properties::fill_color("green"); + edgesmap[i]->property_width_pixels().set_value(10); + + + double x1, x2, y1, y2; + edgesmap[i]->get_bounds(x1, y1, x2, y2); + + edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph,(x1+x2)/2, (y1+y2)/2, ""); + edgetextmap[i]->property_fill_color().set_value("black"); + } + + NodeIt i(g); + int maxx=0, maxy=0, minx=(int)cm[i].x, miny=(int)cm[i].y; + + for (; i!=INVALID; ++i) + { + if(cm[i].x>maxx)maxx=(int)cm[i].x; + if(cm[i].y>maxy)maxy=(int)cm[i].y; + if(cm[i].xsignal_event().connect(sigc::bind(sigc::mem_fun(*this, &GraphDisplayerCanvas::event_handler),i)); + } + + double biggest_x=(abs(maxx)>abs(minx))?(abs(maxx)+80):(abs(minx)+80); + double biggest_y=(abs(maxy)>abs(miny))?(abs(maxy)+80):(abs(miny)+80); + + set_pixels_per_unit((biggest_x>biggest_y)?(WIN_WIDTH/biggest_x/2):(WIN_HEIGHT/biggest_y/2)); + std::cout< id(g); + Graph::NodeMap xc(g); + Graph::NodeMap yc(g); + + int j=1; + + for (NodeIt i(g); i!=INVALID; ++i) + { + double x1,y1,x2,y2; + nodesmap[i]->get_bounds(x1, y1, x2, y2); + + id[i]=j++; + xc[i]=(x1+x2)/2; + yc[i]=(y1+y2)/2; + } + + GraphWriter writer(std::cout,g); + + writer.writeNodeMap("id", id); + writer.writeNodeMap("coordinates_x", xc); + writer.writeNodeMap("coordinates_y", yc); + writer.run(); +} + +int GraphDisplayerCanvas::changeLineWidth (std::string mapname) +{ + for (EdgeIt i(g); i!=INVALID; ++i) + { + int w=(int)(*(mapstorage.edgemap_storage)[mapname])[i]; + edgesmap[i]->property_width_pixels().set_value(w); + } + return 0; +}; + +int GraphDisplayerCanvas::changeColor (std::string mapname) +{ + for (EdgeIt i(g); i!=INVALID; ++i) + { + double w=(*(mapstorage.edgemap_storage)[mapname])[i]; + double max=mapstorage.maxOfEdgeMap(mapname); + double min=mapstorage.minOfEdgeMap(mapname); + + //std::cout<property_fill_color_gdk().set_value(color); + } + return 0; +}; + +int GraphDisplayerCanvas::changeText (std::string mapname) +{ + for (EdgeIt i(g); i!=INVALID; ++i) + { + if(mapname!="Text") + { + double number=(*(mapstorage.edgemap_storage)[mapname])[i]; + int length=(int)(floor(log(number)/log(10)))+1; + int maxpos=(int)(pow(10,length-1)); + int strl=length+1+RANGE; + char * str=new char[strl]; + str[length]='.'; + str[strl]='\0'; + + for(int j=0;jproperty_text().set_value(str); + } + else + { + edgetextmap[i]->property_text().set_value(""); + } + } + return 0; +}; + + +int GraphDisplayerCanvas::rezoom () +{ + double x1, x2, y1, y2; + int x,y; + + NodeIt i(g); + nodesmap[i]->get_bounds(x1, y1, x2, y2); + + x=(int)((x1+x2)/2); + y=(int)((y1+y2)/2); + + int maxx=0, maxy=0, minx=(int)x, miny=(int)y; + + for (; i!=INVALID; ++i) + { + nodesmap[i]->get_bounds(x1, y1, x2, y2); + + x=(int)((x1+x2)/2); + y=(int)((y1+y2)/2); + + if(x>maxx)maxx=x; + if(y>maxy)maxy=y; + if(xabs(minx))?(abs(maxx)+80):(abs(minx)+80); + double biggest_y=(abs(maxy)>abs(miny))?(abs(maxy)+80):(abs(miny)+80); + + set_pixels_per_unit((biggest_x-WIN_WIDTH>biggest_y-WIN_HEIGHT)?(WIN_WIDTH/biggest_x/2):(WIN_HEIGHT/biggest_y/2)); + return 0; +}; + + +///This function moves only one node of displayed_graph, +///but recalculate the location of weight point, +///and also redraw the sides of the planefigure. +bool GraphDisplayerCanvas::event_handler(GdkEvent* e, Node n) +{ + switch(e->type) + { + case GDK_BUTTON_PRESS: + clicked_x=e->button.x; + clicked_y=e->button.y; + active_item=(get_item_at(e->button.x, e->button.y)); + isbutton=true; + break; + case GDK_BUTTON_RELEASE: + isbutton=false; + active_item=NULL; + break; + case GDK_MOTION_NOTIFY: + if(isbutton) + { + double dx=e->motion.x-clicked_x; + double dy=e->motion.y-clicked_y; + active_item->move(dx, dy); + clicked_x=e->motion.x; + clicked_y=e->motion.y; + + EdgeIt e; + + g.firstOut(e,n); + for(;e!=INVALID;g.nextOut(e)) + { + Gnome::Canvas::Points coos; + double x1, x2, y1, y2; + + nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2); + coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); + + nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2); + coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); + + edgesmap[e]->property_points().set_value(coos); + + edgesmap[e]->get_bounds(x1, y1, x2, y2); + + edgetextmap[e]->property_x().set_value((x1+x2)/2); + edgetextmap[e]->property_y().set_value((y1+y2)/2); + } + + g.firstIn(e,n); + for(;e!=INVALID;g.nextIn(e)) + { + Gnome::Canvas::Points coos; + double x1, x2, y1, y2; + + nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2); + coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); + + nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2); + coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); + + edgesmap[e]->property_points().set_value(coos); + + edgesmap[e]->get_bounds(x1, y1, x2, y2); + + edgetextmap[e]->property_x().set_value((x1+x2)/2); + edgetextmap[e]->property_y().set_value((y1+y2)/2); + } + } + default: break; + } + return true; +} + +bool GraphDisplayerCanvas::on_expose_event(GdkEventExpose *event) +{ + Gnome::Canvas::CanvasAA::on_expose_event(event); + //usleep(10000); + //rezoom(); + return true; +} diff -r d8475431bbbb -r 8e85e6bbefdf gui/graph_displayer_canvas.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/graph_displayer_canvas.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,65 @@ +// -*- C++ -*- // + +#ifndef GRAPH_DISPLAYER_CANVAS_H +#define GRAPH_DISPLAYER_CANVAS_H + +#include +#include +#include +#include + +class GraphDisplayerCanvas : public Gnome::Canvas::CanvasAA +{ + typedef Gnome::Canvas::CanvasAA Parent; + +public: + GraphDisplayerCanvas(Graph &, CoordinatesMap &, MapStorage &); + virtual ~GraphDisplayerCanvas(); + + int changeLineWidth (std::string mapname); + int changeColor (std::string mapname); + int changeText (std::string mapname); + int rezoom(); + +protected: + + virtual bool on_expose_event(GdkEventExpose *); + +private: + + ///Event handler function that handles dragging nodes of displayed_graph + bool event_handler(GdkEvent* e, Node n); + + ///The graph, on which we work + Graph g; + ///Map of nodes of planefigure + Graph::NodeMap nodesmap; + ///Map of edges of planefigure + Graph::EdgeMap edgesmap; + + ///Map of texts to write on edges + Graph::EdgeMap edgetextmap; + + ///Group of graphical elements of displayed_graph + Gnome::Canvas::Group displayed_graph; + + ///Here we store the maps that can be displayed through properties. + MapStorage mapstorage; + + ///Indicates whether the button of mouse is pressed or not + bool isbutton; + + ///At this location was the mousebutton pressed. + ///It helps to calculate the distance of dragging. + double clicked_x, clicked_y; + + ///Remembers which Gnome::Canvas::Item was pressed. + ///this variable is needed, because + ///1. we cannot query the item at he cursor as fast as it could not cause a Segmentation Fault + ///2. we would like to handle only ony item per movement, therefore quering it is not a working solution + Gnome::Canvas::Item * active_item; + + +}; + +#endif //GRAPH_DISPLAYER_CANVAS_H diff -r d8475431bbbb -r 8e85e6bbefdf gui/graphocska.lgf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/graphocska.lgf Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,39 @@ +@nodeset +id coordinates_x coordinates_y data +1 230 -80 1 +2 230 100 3 +3 120 -80 5 +4 120 100 7 +5 20 100 9 +6 20 -80 11 +7 -40 10 13 +8 -100 100 15 +9 -100 10 17 +10 -100 -80 19 +11 -200 -80 21 +12 -200 10 23 +13 -200 100 25 +14 -300 100 27 +15 -300 -80 29 + +@edgeset + cap map1 map2 map3 map4 +15 14 1 21 111 231 3 +14 13 2 22 112 232 6 +13 12 3 23 113 233 9 +13 8 4 24 114 234 12 +12 11 5 25 115 235 15 +12 9 6 26 116 236 18 +11 10 7 27 117 237 21 +10 9 8 28 118 238 24 +10 7 9 29 119 239 27 +9 8 10 30 120 230 30 +7 6 11 31 121 241 33 +6 5 12 32 122 242 36 +6 3 13 33 123 243 39 +5 4 14 34 124 244 42 +4 3 15 35 125 245 45 +3 2 16 36 126 246 48 +2 1 17 37 127 247 51 + +@end \ No newline at end of file diff -r d8475431bbbb -r 8e85e6bbefdf gui/main_win.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/main_win.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,69 @@ +#include + +MainWin::MainWin(const std::string& title, Graph & graph, CoordinatesMap & cm, MapStorage & ms):mapwin("Map Setup", ms, gd_canvas),gd_canvas(graph, cm, ms) +{ + set_title (title); + set_default_size(WIN_WIDTH,WIN_HEIGHT); + add(vbox); + + ag=Gtk::ActionGroup::create(); + ag->add( Gtk::Action::create("ShowMenu", "_Show") ); + ag->add( Gtk::Action::create("ShowMaps", "_Maps"), sigc::mem_fun(*this, &MainWin::showMaps)); + ag->add( Gtk::Action::create("FileMenu", "_File") ); + ag->add( Gtk::Action::create("FileQuit", "_Quit"), sigc::mem_fun(*this, &MainWin::quit)); + ag->add( Gtk::Action::create("ZoomMenu", "_Zoom") ); + ag->add( Gtk::Action::create("ZoomRezoom", "_Rezoom"), sigc::mem_fun(*this, &MainWin::rezoom)); //!!!!!! + + uim=Gtk::UIManager::create(); + uim->insert_action_group(ag); + add_accel_group(uim->get_accel_group()); + + try + { + + Glib::ustring ui_info = + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; + + uim->add_ui_from_string(ui_info); + + } + catch(const Glib::Error& ex) + { + std::cerr << "building menus failed: " << ex.what(); + } + + Gtk::Widget* menubar = uim->get_widget("/MenuBar"); + if(menubar)vbox.pack_start(*menubar, Gtk::PACK_SHRINK); + + vbox.pack_start(gd_canvas); + + show_all_children(); +} + +void MainWin::showMaps() +{ + mapwin.show(); +} + +void MainWin::quit() +{ + hide(); +} + +void MainWin::rezoom() +{ + gd_canvas.rezoom(); +} + diff -r d8475431bbbb -r 8e85e6bbefdf gui/main_win.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/main_win.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,44 @@ +// -*- C++ -*- // + +#ifndef MAIN_WIN_H +#define MAIN_WIN_H + +#include +#include +#include +#include +#include + +class MainWin : public Gtk::Window +{ +public: + MainWin(const std::string& title, Graph &, CoordinatesMap &, MapStorage &); + +protected: + //Window of map-showing setup + MapWin mapwin; + + //Member widgets: + GraphDisplayerCanvas gd_canvas; + + //ActionGroup for menu + Glib::RefPtr ag; + + //UIManager for menu + Glib::RefPtr uim; + + //Container + Gtk::VBox vbox; + + //Pops up map-setup window + virtual void showMaps(); + + //Exit + virtual void quit(); + + //Refit screen + virtual void rezoom(); + +}; + +#endif //MAIN_WIN_H diff -r d8475431bbbb -r 8e85e6bbefdf gui/map_win.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/map_win.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,116 @@ +#include +#include + +MapWin::MapWin(const std::string& title, MapStorage & mapst, GraphDisplayerCanvas & grdispc):gdc(grdispc),ms(mapst) +{ + set_title(title); + set_default_size(400, 200); + + rb_array=new Gtk::RadioButton * [PROPERTY_NUM]; + vbox_r1=new Gtk::VBox[PROPERTY_NUM]; + vbox_r2=new Gtk::VBox[PROPERTY_NUM]; + radios=new Gtk::HBox[PROPERTY_NUM]; + for(int i=0;i * >::iterator emsi=ms.beginOfEdgeMaps(); + std::set props; + + int actprop; + for(int j=0;jsecond==&(ms.default_edgemaps[i])) + { + actprop=j; + } + for(int k=0;ksecond==&(ms.default_edgemaps[k])) + { + props.insert(j); + } + } + emsi++; + } + + rb_array[i][0].set_group(group); + rb_array[i][0].set_label("Default"); + rb_array[i][0].signal_clicked().connect( sigc::bind( sigc::bind( sigc::mem_fun(*this, &MapWin::radio_click), 0), i) ); + vbox_r1[i].pack_start(rb_array[i][0]); + + + emsi=ms.beginOfEdgeMaps(); + int actpos=1; + for(int j=0;jfirst); + rb_array[i][actpos].signal_clicked().connect + ( + sigc::bind( + sigc::bind( + sigc::mem_fun(*this, &MapWin::radio_click), + actpos + ), + i + ) + ); + + if(actpos<(ms.numOfEdgeMaps()-PROPERTY_NUM+1)/2) + { + vbox_r1[i].pack_start(rb_array[i][actpos]); + } + else + { + vbox_r2[i].pack_start(rb_array[i][actpos]); + } + actpos++; + } + emsi++; + } + radios[i].pack_start(vbox_r1[i]); + radios[i].pack_start(vbox_r2[i]); + notebook.append_page(radios[i], property_strings[i]); + } + + add(vbox_b); + vbox_b.pack_start(notebook); + + show_all_children(); + +} + +void MapWin::radio_click(int prop, int actpos) +{ + if(rb_array[prop][actpos].get_active()) + { + + std::string mapname=rb_array[prop][actpos].get_label(); + + if(mapname=="Default") + { + mapname=property_strings[prop]; + } + + switch(prop) + { + case WIDTH: + gdc.changeLineWidth(mapname); + break; + case COLOR: + gdc.changeColor(mapname); + break; + case TEXT: + gdc.changeText(mapname); + break; + default: + std::cout<<"Error\n"; + } + } +}; diff -r d8475431bbbb -r 8e85e6bbefdf gui/map_win.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/map_win.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,30 @@ +// -*- C++ -*- // + +#ifndef MAP_WIN_H +#define MAP_WIN_H + +#include +#include +#include +#include +#include + +class MapWin : public Gtk::Window +{ +protected: + GraphDisplayerCanvas & gdc; + MapStorage & ms; + + Gtk::HBox * radios; + Gtk::RadioButton ** rb_array; + + Gtk::VBox vbox_b, * vbox_r1, * vbox_r2; + Gtk::Notebook notebook; + Gtk::Label * labels; + +public: + MapWin(const std::string& title, MapStorage &, GraphDisplayerCanvas &); + virtual void radio_click(int, int); +}; + +#endif //MAP_WIN_H diff -r d8475431bbbb -r 8e85e6bbefdf gui/mapstorage.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/mapstorage.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,89 @@ +#include + +MapStorage::MapStorage(Graph & graph):g(graph) +{ + for(int i=0;i emd(g); + default_edgemaps.push_back(emd); + Graph::NodeMap nmd(g); + default_nodemaps.push_back(nmd); + } + + //std::string defaultstr="Default "; + for(int i=0;i *nodemap) +{ + nodemap_storage[name]=nodemap; + return 0; +} +int MapStorage::addEdgeMap(const std::string & name, Graph::EdgeMap *edgemap) +{ + edgemap_storage[name]=edgemap; + return 0; +} + +double MapStorage::maxOfNodeMap(const std::string & name) +{ + double max=0; + for (NodeIt j(g); j!=INVALID; ++j) + { + if( (*nodemap_storage[name])[j]>max ) + { + max=(*nodemap_storage[name])[j]; + } + } + return max; +} + +double MapStorage::maxOfEdgeMap(const std::string & name) +{ + double max=0; + for (EdgeIt j(g); j!=INVALID; ++j) + { + if( (*edgemap_storage[name])[j]>max ) + { + max=(*edgemap_storage[name])[j]; + } + } + return max; +} + +double MapStorage::minOfNodeMap(const std::string & name) +{ + NodeIt j(g); + double min=(*nodemap_storage[name])[j]; + for (; j!=INVALID; ++j) + { + if( (*nodemap_storage[name])[j] + +class MapStorage +{ + +public: ///!!!!!!!! + Graph g; + std::map< std::string,Graph::NodeMap * > nodemap_storage; + std::map< std::string,Graph::EdgeMap * > edgemap_storage; + + std::vector > default_nodemaps; + std::vector > default_edgemaps; + +public: + MapStorage(Graph &); + int addNodeMap(const std::string &,Graph::NodeMap *); + int addEdgeMap(const std::string &,Graph::EdgeMap *); + + int numOfNodeMaps() {return nodemap_storage.size();}; + int numOfEdgeMaps() {return edgemap_storage.size();}; + + double maxOfNodeMap(const std::string &); + double maxOfEdgeMap(const std::string &); + + double minOfNodeMap(const std::string &); + double minOfEdgeMap(const std::string &); + + std::map< std::string,Graph::NodeMap * >::iterator beginOfNodeMaps(){return nodemap_storage.begin();}; + std::map< std::string,Graph::EdgeMap * >::iterator beginOfEdgeMaps(){return edgemap_storage.begin();}; +}; + +#endif //MAPSTORAGE_H diff -r d8475431bbbb -r 8e85e6bbefdf gui/xml.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/xml.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,442 @@ +/* -*- C++ -*- */ + +#include +#include +#include +#include +#include +#include + +class XmlWriter +{ + std::ostream& os; + int level; + +protected: + void indent(int level) { + os << std::endl; + for(int i=0;i'; + } + void etag(const std::string &_tag) { + os << "'; + } + void itag(const std::string &_tag) { indent();tag(_tag); } + void ietag(const std::string &_tag) { indent();etag(_tag); } + + void beginTag(const std::string &_tag) { + itag(_tag); + level++; + } + void endTag(const std::string &_tag) { + level--; + ietag(_tag); + } + +public: + + void indent() + { + if(level>=0) indent(level); + else level=0; + } + + ///\e + + ///\e + /// + class ContTag + { + XmlWriter &ix; + const std::string _tag; + public: + ///\e + + ///\e + /// + ContTag(XmlWriter &_ix,const std::string &_t) : + ix(_ix), _tag(_t) + { + ix.tag(_tag); + } + ~ContTag() { ix.etag(_tag);} + }; + + class LineTag + { + XmlWriter &ix; + const std::string _tag; + public: + ///\e + + ///\e + /// + LineTag(XmlWriter &_ix,const std::string &_t) : + ix(_ix), _tag(_t) + { + ix.itag(_tag); + } + ~LineTag() { ix.etag(_tag);} + }; + + ///\e + + ///\e + /// + class Tag + { + XmlWriter &ix; + const std::string _tag; + public: + ///\e + + ///\e + /// + Tag(XmlWriter &_ix,const std::string &_t) : + ix(_ix), _tag(_t) + { + ix.beginTag(_tag); + } + ~Tag() { + ix.endTag(_tag); + } + }; + + ///\e + + ///\e + /// + XmlWriter(std::ostream& _os) : os(_os),level(-1) {} + ~XmlWriter() { os<< std::endl; } + + XmlWriter &operator()(int v) + { + if(!(os << v)) throw (std::ios::failure ("data format error")); + return *this; + } + XmlWriter &operator()(const std::string &_tag,int v) + { + LineTag t(*this,_tag); + if(!(os << v)) throw (std::ios::failure ("data format error")); + return *this; + } + XmlWriter &operator()(const std::string &_tag,double v) + { + LineTag t(*this,_tag); + if(os << v) throw (std::ios::failure ("data format error")); + return *this; + } + XmlWriter &operator()(double v) + { + os << v; + return *this; + } + XmlWriter &operator()(const std::string &v) + { + for(std::string::const_iterator i=v.begin();i!=v.end();++i) + switch(*i) { + case '\\': + os << "\\\\"; + break; + case '<': + os << "\\<"; + break; + case '&': + os << "\\&"; + break; + case '\n': + os << "\\n"; + break; + default: + os<<*i; + break; + } + return *this; + } + XmlWriter &operator()(const std::string &_tag,const std::string &v) + { + LineTag t(*this,_tag); + (*this)(v); + return *this; + } + ///\e + + ///\e + /// + template + XmlWriter &operator()(const std::string &_tag,const V &v) + { + Tag t(*this,_tag); + out(*this,v); + return *this; + } + ///\e + + ///\e + /// + template + XmlWriter &operator()(const V &v) + { + out(*this,v); + return *this; + } +}; + +////////////////////////////////////////////////////////////////////// + +class XmlReader +{ + std::istream& is; + + std::string next_tag; + void skipWhiteSpaces() + { + char c; + while (is.get(c) && std::isspace(c,is.getloc())); + is.unget(); + } +protected: + ///\e + + ///\e + /// + void useTag() {next_tag.clear();} + + void useTag(const std::string &_tag) { + if(nextTag()==_tag) useTag(); + else throw (std::ios::failure ("data format error")); + } +public: + ///\e + + ///\e + /// + const std::string &nextTag() + { + if(next_tag.empty()) { + char c; + skipWhiteSpaces(); + if(!is.get(c) || c!='<') + throw (std::ios::failure ("data format error")); + next_tag.clear(); + while (is.get(c) && c!='>') next_tag.push_back(c); + if(c!='>') + throw (std::ios::failure ("data format error")); + } + return next_tag; + } + + ///\e + + ///\e + /// + class Tag + { + XmlReader &ix; + const std::string tag; + public: + ///\e + + ///\e + /// + Tag(XmlReader &_ix,const std::string &_tag) : + ix(_ix), tag(_tag) + { + ix.useTag(_tag); + } + ~Tag() { + if(!std::uncaught_exception()) + ix.useTag('/'+tag); + } + }; + + ///\e + + ///\e + /// + XmlReader(std::istream& _is) : is(_is) {} + + int operator()(const std::string &tag,int &v) + { + Tag t(*this,tag); + if(!(is >> v)) throw (std::ios::failure ("data format error")); + return v; + } + double operator()(const std::string &tag,double &v) + { + Tag t(*this,tag); + if(!(is >> v)) throw (std::ios::failure ("data format error")); + return v; + } + std::string &operator()(const std::string &tag,std::string &v) + { + Tag t(*this,tag); + v.clear(); + char c; + while (is.get(c) && c!='<') + if(c=='\\') + if(!is.get(c)) throw (std::ios::failure ("data format error")); + else switch(c) { + case 'n': + v.push_back('\n'); + break; + default: + v.push_back(c); + break; + } + else v.push_back(c); + if(c!='<') + throw (std::ios::failure ("data format error")); + is.unget(); + return v; + } + ///\e + + ///\e + /// + template + V &operator()(const std::string &tag,V &v) + { + Tag t(*this,tag); + in(*this,v); + return v; + } + ///\e + + ///\e + /// + template + V &operator()(V &v) + { + in(*this,v); + return v; + } + ///\e + + ///\e + /// + template + V load(const std::string &tag) + { + Tag t(*this,tag); + V v; + (*this)(tag,v); + return v; + } +}; + +////////////////////////////////////////////////////////////////////// + +template +void out(XmlWriter &i,const std::pair &v) +{ + i("first",v.first); + i("second",v.second); +} + +template +void in(XmlReader &i,std::pair &v) +{ + i("first",v.first); + i("second",v.second); +} + +////////////////////////////// + +template +void out(XmlWriter &i,const std::list &v) +{ + for(typename std::list::const_iterator it=v.begin(); + it!=v.end();++it) i("item",*it); +} + +template +void in(XmlReader &i,std::list &v) +{ + while(i.nextTag()=="item") + { + v.push_back(T()); + i("item",v.back()); + } +} + +////////////////////////////// + +template +void out(XmlWriter &i,const std::vector &v) +{ + for(typename std::vector::const_iterator it=v.begin(); + it!=v.end();++it) i("item",*it); +} + +template +void in(XmlReader &i,std::vector &v) +{ + while(i.nextTag()=="item") + { + v.push_back(T()); + i("item",v.back()); + } +} + +////////////////////////////// + +template +void out(XmlWriter &i,const std::map &v) +{ + for(typename std::map::const_iterator it=v.begin(); + it!=v.end();++it) i("item",*it); +} + +template +void in(XmlReader &i,std::map &v) +{ + while(i.nextTag()=="item") + { + typename std::map::value_type it; + i("item",it); + v.insert(it); + } +} + +////////////////////////////// + +template +void out(XmlWriter &i,const lemon::xy &v) +{ +// i("x",v.x); +// i("y",v.y); + { XmlWriter::LineTag t(i,"x"); i(v.x); } + { XmlWriter::ContTag t(i,"y"); i(v.y); } +} + +template +void in(XmlReader &i,lemon::xy &v) +{ + i("x",v.x); + i("y",v.y); +} + +////////////////////////////// + +template +void out(XmlWriter &i,const lemon::BoundingBox &v) +{ + if(!v.empty()) { + i("point",v.bottomLeft()); + if(v.bottomLeft()!=v.topRight()) i("point",v.topRight()); + } +} + +template +void in(XmlReader &i,lemon::BoundingBox &v) +{ + v.clear(); + while(i.nextTag()=="point") { + lemon::xy co; + i("point",co); + v+=co; + } +} diff -r d8475431bbbb -r 8e85e6bbefdf lemon/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/Makefile.am Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,81 @@ +AM_CPPFLAGS = -I$(top_srcdir) + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = lemon.pc + +lib_LTLIBRARIES = libemon.la + +libemon_la_SOURCES = \ + lp_base.cc \ + lp_skeleton.cc +libemon_la_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) +libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) + +if HAVE_GLPK +libemon_la_SOURCES += lp_glpk.cc +endif + +if HAVE_CPLEX +libemon_la_SOURCES += lp_cplex.cc +endif + +nobase_pkginclude_HEADERS = \ + bezier.h \ + bfs.h \ + dfs.h \ + bin_heap.h \ + config.h \ + dijkstra.h \ + dimacs.h \ + error.h \ + fib_heap.h \ + full_graph.h \ + graph_adaptor.h \ + graph_utils.h \ + graph_to_eps.h \ + invalid.h \ + kruskal.h \ + list_graph.h \ + lp_base.h \ + lp_cplex.h \ + lp_glpk.h \ + lp_skeleton.h \ + maps.h \ + max_matching.h \ + min_cost_flow.h \ + suurballe.h \ + preflow.h \ + path.h \ + radix_heap.h \ + smart_graph.h \ + time_measure.h \ + unionfind.h \ + xy.h \ + concept_check.h \ + utility.h \ + lemon_reader.h \ + lemon_writer.h \ + graph_reader.h \ + graph_writer.h \ + bits/alteration_notifier.h \ + bits/map_iterator.h \ + bits/array_map.h \ + bits/default_map.h \ + bits/extended_pair.h \ + bits/vector_map.h \ + bits/iterable_graph_extender.h \ + bits/extendable_graph_extender.h \ + bits/clearable_graph_extender.h \ + bits/erasable_graph_extender.h \ + bits/undir_graph_extender.h \ + bits/item_reader.h \ + bits/item_writer.h + +noinst_HEADERS = \ + concept/graph.h \ + concept/graph_component.h \ + concept/undir_graph.h \ + concept/sym_graph.h \ + concept/maps.h \ + concept/heap.h \ + concept/path.h diff -r d8475431bbbb -r 8e85e6bbefdf lemon/attic/debug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/attic/debug.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,70 @@ +/* -*- C++ -*- + * lemon/debug.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_DEBUG_H +#define LEMON_DEBUG_H + +//! \file +//! \brief Basic definitions for debug control. + +namespace lemon { + + //! Debug mode for testing/debugging + + //! Use this debug mode if you want exhaustive range and consistency checks. + //! It also produces verbose debug messages. + struct DebugOn { + //! Example: check whether the edges added to a path are adjacent + static const bool consistensy_check = true; + + static const bool range_check = true; + + //! Examples: initialize maps with some value; + //! after deleting an item from UnionFindEnum set its value in the + //! corresponding map to NULL... + static const bool ensure_safe_state = true; + + static const int verbose = 5; + }; + + //! Debug mode for turning off debug aids. + + //! This debud mode switches off all range and consistency checks, + //! as well as the debug messages. + //! + struct DebugOff { + static const bool consistensy_check = false; + static const bool range_check = false; + static const bool ensure_safe_state = false; + static const int verbose = 0; + }; + +#ifdef DEBUG + //! The default debug mode. + + //! The default debug mode. + //! + typedef DebugOn DefaultDebugMode; +#else + //! The default debug mode. + + //! The default debug mode. + //! + typedef DebugOff DefaultDebugMode; +#endif + +} +#endif // LEMON_DEBUG_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bezier.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bezier.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,147 @@ +/* -*- C++ -*- + * lemon/bezier.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_BEZIER_H +#define LEMON_BEZIER_H + +///\ingroup misc +///\file +///\brief Classes to compute with Bezier curves. +/// +///Up to now this file is used internally by \ref graph_to_eps.h +/// +///\author Alpar Juttner + +#include + +namespace lemon { + +class BezierBase { +public: + typedef xy xy; +protected: + static xy conv(xy x,xy y,double t) {return (1-t)*x+t*y;} +}; + +class Bezier1 : public BezierBase +{ +public: + xy p1,p2; + + Bezier1() {} + Bezier1(xy _p1, xy _p2) :p1(_p1), p2(_p2) {} + + xy operator()(double t) const + { + // return conv(conv(p1,p2,t),conv(p2,p3,t),t); + return conv(p1,p2,t); + } + Bezier1 before(double t) const + { + return Bezier1(p1,conv(p1,p2,t)); + } + + Bezier1 after(double t) const + { + return Bezier1(conv(p1,p2,t),p2); + } + Bezier1 revert() { return Bezier1(p2,p1);} + Bezier1 operator()(double a,double b) { return before(b).after(a/b); } + xy grad() { return p2-p1; } + xy grad(double t) { return grad(); } + +}; + +class Bezier2 : public BezierBase +{ +public: + xy p1,p2,p3; + + Bezier2() {} + Bezier2(xy _p1, xy _p2, xy _p3) :p1(_p1), p2(_p2), p3(_p3) {} + Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {} + xy operator()(double t) const + { + // return conv(conv(p1,p2,t),conv(p2,p3,t),t); + return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3; + } + Bezier2 before(double t) const + { + xy q(conv(p1,p2,t)); + xy r(conv(p2,p3,t)); + return Bezier2(p1,q,conv(q,r,t)); + } + + Bezier2 after(double t) const + { + xy q(conv(p1,p2,t)); + xy r(conv(p2,p3,t)); + return Bezier2(conv(q,r,t),r,p3); + } + Bezier2 revert() { return Bezier2(p3,p2,p1);} + Bezier2 operator()(double a,double b) { return before(b).after(a/b); } + Bezier1 grad() { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); } + xy grad(double t) { return grad()(t); } +}; + +class Bezier3 : public BezierBase +{ +public: + xy p1,p2,p3,p4; + + Bezier3() {} + Bezier3(xy _p1, xy _p2, xy _p3, xy _p4) :p1(_p1), p2(_p2), p3(_p3), p4(_p4) {} + Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)), + p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {} + Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)), + p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {} + + xy operator()(double t) const + { + // return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t); + return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+ + (3*t*t*(1-t))*p3+(t*t*t)*p4; + } + Bezier3 before(double t) const + { + xy p(conv(p1,p2,t)); + xy q(conv(p2,p3,t)); + xy r(conv(p3,p4,t)); + xy a(conv(p,q,t)); + xy b(conv(q,r,t)); + xy c(conv(a,b,t)); + return Bezier3(p1,p,a,c); + } + + Bezier3 after(double t) const + { + xy p(conv(p1,p2,t)); + xy q(conv(p2,p3,t)); + xy r(conv(p3,p4,t)); + xy a(conv(p,q,t)); + xy b(conv(q,r,t)); + xy c(conv(a,b,t)); + return Bezier3(c,b,r,p4); + } + Bezier3 revert() { return Bezier3(p4,p3,p2,p1);} + Bezier3 operator()(double a,double b) { return before(b).after(a/b); } + Bezier2 grad() { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); } + xy grad(double t) { return grad()(t); } +}; + +} //END OF NAMESPACE LEMON + +#endif // LEMON_BEZIER_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bfs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bfs.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,1130 @@ +/* -*- C++ -*- + * lemon/bfs.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_BFS_H +#define LEMON_BFS_H + +///\ingroup flowalgs +///\file +///\brief Bfs algorithm. + +#include +#include +#include +#include +#include + +namespace lemon { + + + + ///Default traits class of Bfs class. + + ///Default traits class of Bfs class. + ///\param GR Graph type. + template + struct BfsDefaultTraits + { + ///The graph type the algorithm runs on. + typedef GR Graph; + ///\brief The type of the map that stores the last + ///edges of the shortest paths. + /// + ///The type of the map that stores the last + ///edges of the shortest paths. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef typename Graph::template NodeMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \ref PredMap. + ///\param G is the graph, to which we would like to define the PredMap. + ///\todo The graph alone may be insufficient to initialize + static PredMap *createPredMap(const GR &G) + { + return new PredMap(G); + } +// ///\brief The type of the map that stores the last but one +// ///nodes of the shortest paths. +// /// +// ///The type of the map that stores the last but one +// ///nodes of the shortest paths. +// ///It must meet the \ref concept::WriteMap "WriteMap" concept. +// /// +// typedef NullMap PredNodeMap; +// ///Instantiates a PredNodeMap. + +// ///This function instantiates a \ref PredNodeMap. +// ///\param G is the graph, to which +// ///we would like to define the \ref PredNodeMap +// static PredNodeMap *createPredNodeMap(const GR &G) +// { +// return new PredNodeMap(); +// } + + ///The type of the map that indicates which nodes are processed. + + ///The type of the map that indicates which nodes are processed. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \ref ProcessedMap. + ///\param G is the graph, to which + ///we would like to define the \ref ProcessedMap + static ProcessedMap *createProcessedMap(const GR &) + { + return new ProcessedMap(); + } + ///The type of the map that indicates which nodes are reached. + + ///The type of the map that indicates which nodes are reached. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef typename Graph::template NodeMap ReachedMap; + ///Instantiates a ReachedMap. + + ///This function instantiates a \ref ReachedMap. + ///\param G is the graph, to which + ///we would like to define the \ref ReachedMap. + static ReachedMap *createReachedMap(const GR &G) + { + return new ReachedMap(G); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef typename Graph::template NodeMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param G is the graph, to which we would like to define the \ref DistMap + static DistMap *createDistMap(const GR &G) + { + return new DistMap(G); + } + }; + + ///%BFS algorithm class. + + ///\ingroup flowalgs + ///This class provides an efficient implementation of the %BFS algorithm. + /// + ///\param GR The graph type the algorithm runs on. The default value is + ///\ref ListGraph. The value of GR is not used directly by Bfs, it + ///is only passed to \ref BfsDefaultTraits. + ///\param TR Traits class to set various data types used by the algorithm. + ///The default traits class is + ///\ref BfsDefaultTraits "BfsDefaultTraits". + ///See \ref BfsDefaultTraits for the documentation of + ///a Bfs traits class. + /// + ///\author Alpar Juttner + ///\todo A compare object would be nice. + +#ifdef DOXYGEN + template +#else + template > +#endif + class Bfs { + public: + /** + * \brief \ref Exception for uninitialized parameters. + * + * This error represents problems in the initialization + * of the parameters of the algorithms. + */ + class UninitializedParameter : public lemon::UninitializedParameter { + public: + virtual const char* exceptionName() const { + return "lemon::Bfs::UninitializedParameter"; + } + }; + + typedef TR Traits; + ///The type of the underlying graph. + typedef typename TR::Graph Graph; + ///\e + typedef typename Graph::Node Node; + ///\e + typedef typename Graph::NodeIt NodeIt; + ///\e + typedef typename Graph::Edge Edge; + ///\e + typedef typename Graph::OutEdgeIt OutEdgeIt; + + ///\brief The type of the map that stores the last + ///edges of the shortest paths. + typedef typename TR::PredMap PredMap; +// ///\brief The type of the map that stores the last but one +// ///nodes of the shortest paths. +// typedef typename TR::PredNodeMap PredNodeMap; + ///The type of the map indicating which nodes are reached. + typedef typename TR::ReachedMap ReachedMap; + ///The type of the map indicating which nodes are processed. + typedef typename TR::ProcessedMap ProcessedMap; + ///The type of the map that stores the dists of the nodes. + typedef typename TR::DistMap DistMap; + private: + /// Pointer to the underlying graph. + const Graph *G; + ///Pointer to the map of predecessors edges. + PredMap *_pred; + ///Indicates if \ref _pred is locally allocated (\c true) or not. + bool local_pred; +// ///Pointer to the map of predecessors nodes. +// PredNodeMap *_predNode; +// ///Indicates if \ref _predNode is locally allocated (\c true) or not. +// bool local_predNode; + ///Pointer to the map of distances. + DistMap *_dist; + ///Indicates if \ref _dist is locally allocated (\c true) or not. + bool local_dist; + ///Pointer to the map of reached status of the nodes. + ReachedMap *_reached; + ///Indicates if \ref _reached is locally allocated (\c true) or not. + bool local_reached; + ///Pointer to the map of processed status of the nodes. + ProcessedMap *_processed; + ///Indicates if \ref _processed is locally allocated (\c true) or not. + bool local_processed; + + std::vector _queue; + int _queue_head,_queue_tail,_queue_next_dist; + int _curr_dist; +// ///The source node of the last execution. +// Node source; + + ///Creates the maps if necessary. + + ///\todo Error if \c G are \c NULL. + ///\todo Better memory allocation (instead of new). + void create_maps() + { + if(!_pred) { + local_pred = true; + _pred = Traits::createPredMap(*G); + } +// if(!_predNode) { +// local_predNode = true; +// _predNode = Traits::createPredNodeMap(*G); +// } + if(!_dist) { + local_dist = true; + _dist = Traits::createDistMap(*G); + } + if(!_reached) { + local_reached = true; + _reached = Traits::createReachedMap(*G); + } + if(!_processed) { + local_processed = true; + _processed = Traits::createProcessedMap(*G); + } + } + + public : + + ///\name Named template parameters + + ///@{ + + template + struct DefPredMapTraits : public Traits { + typedef T PredMap; + static PredMap *createPredMap(const Graph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting PredMap type + + ///\ref named-templ-param "Named parameter" for setting PredMap type + /// + template + class DefPredMap : public Bfs< Graph, + DefPredMapTraits > { }; + +// template +// struct DefPredNodeMapTraits : public Traits { +// typedef T PredNodeMap; +// static PredNodeMap *createPredNodeMap(const Graph &G) +// { +// throw UninitializedParameter(); +// } +// }; +// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type + +// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type +// /// +// template +// class DefPredNodeMap : public Bfs< Graph, +// LengthMap, +// DefPredNodeMapTraits > { }; + + template + struct DefDistMapTraits : public Traits { + typedef T DistMap; + static DistMap *createDistMap(const Graph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting DistMap type + + ///\ref named-templ-param "Named parameter" for setting DistMap type + /// + template + class DefDistMap : public Bfs< Graph, + DefDistMapTraits > { }; + + template + struct DefReachedMapTraits : public Traits { + typedef T ReachedMap; + static ReachedMap *createReachedMap(const Graph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting ReachedMap type + + ///\ref named-templ-param "Named parameter" for setting ReachedMap type + /// + template + class DefReachedMap : public Bfs< Graph, + DefReachedMapTraits > { }; + + struct DefGraphReachedMapTraits : public Traits { + typedef typename Graph::template NodeMap ReachedMap; + static ReachedMap *createReachedMap(const Graph &G) + { + return new ReachedMap(G); + } + }; + template + struct DefProcessedMapTraits : public Traits { + typedef T ProcessedMap; + static ProcessedMap *createProcessedMap(const Graph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting ProcessedMap type + + ///\ref named-templ-param "Named parameter" for setting ProcessedMap type + /// + template + class DefProcessedMap : public Bfs< Graph, + DefProcessedMapTraits > { }; + + struct DefGraphProcessedMapTraits : public Traits { + typedef typename Graph::template NodeMap ProcessedMap; + static ProcessedMap *createProcessedMap(const Graph &G) + { + return new ProcessedMap(G); + } + }; + ///\brief \ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Graph::NodeMap. + /// + ///\ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Graph::NodeMap. + ///If you don't set it explicitly, it will be automatically allocated. + template + class DefProcessedMapToBeDefaultMap : + public Bfs< Graph, + DefGraphProcessedMapTraits> { }; + + ///@} + + public: + + ///Constructor. + + ///\param _G the graph the algorithm will run on. + /// + Bfs(const Graph& _G) : + G(&_G), + _pred(NULL), local_pred(false), +// _predNode(NULL), local_predNode(false), + _dist(NULL), local_dist(false), + _reached(NULL), local_reached(false), + _processed(NULL), local_processed(false) + { } + + ///Destructor. + ~Bfs() + { + if(local_pred) delete _pred; +// if(local_predNode) delete _predNode; + if(local_dist) delete _dist; + if(local_reached) delete _reached; + if(local_processed) delete _processed; + } + + ///Sets the map storing the predecessor edges. + + ///Sets the map storing the predecessor edges. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destructor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Bfs &predMap(PredMap &m) + { + if(local_pred) { + delete _pred; + local_pred=false; + } + _pred = &m; + return *this; + } + + ///Sets the map indicating the reached nodes. + + ///Sets the map indicating the reached nodes. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destructor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Bfs &reachedMap(ReachedMap &m) + { + if(local_reached) { + delete _reached; + local_reached=false; + } + _reached = &m; + return *this; + } + + ///Sets the map indicating the processed nodes. + + ///Sets the map indicating the processed nodes. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destructor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Bfs &processedMap(ProcessedMap &m) + { + if(local_processed) { + delete _processed; + local_processed=false; + } + _processed = &m; + return *this; + } + +// ///Sets the map storing the predecessor nodes. + +// ///Sets the map storing the predecessor nodes. +// ///If you don't use this function before calling \ref run(), +// ///it will allocate one. The destructor deallocates this +// ///automatically allocated map, of course. +// ///\return (*this) +// Bfs &predNodeMap(PredNodeMap &m) +// { +// if(local_predNode) { +// delete _predNode; +// local_predNode=false; +// } +// _predNode = &m; +// return *this; +// } + + ///Sets the map storing the distances calculated by the algorithm. + + ///Sets the map storing the distances calculated by the algorithm. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destructor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Bfs &distMap(DistMap &m) + { + if(local_dist) { + delete _dist; + local_dist=false; + } + _dist = &m; + return *this; + } + + public: + ///\name Execution control + ///The simplest way to execute the algorithm is to use + ///one of the member functions called \c run(...). + ///\n + ///If you need more control on the execution, + ///first you must call \ref init(), then you can add several source nodes + ///with \ref addSource(). + ///Finally \ref start() will perform the actual path + ///computation. + + ///@{ + + ///Initializes the internal data structures. + + ///Initializes the internal data structures. + /// + void init() + { + create_maps(); + _queue.resize(countNodes(*G)); + _queue_head=_queue_tail=0; + _curr_dist=1; + for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { + _pred->set(u,INVALID); +// _predNode->set(u,INVALID); + _reached->set(u,false); + _processed->set(u,false); + } + } + + ///Adds a new source node. + + ///Adds a new source node to the set of nodes to be processed. + /// + void addSource(Node s) + { + if(!(*_reached)[s]) + { + _reached->set(s,true); + _pred->set(s,INVALID); + _dist->set(s,0); + _queue[_queue_head++]=s; + _queue_next_dist=_queue_head; + } + } + + ///Processes the next node. + + ///Processes the next node. + /// + ///\warning The queue must not be empty! + void processNextNode() + { + if(_queue_tail==_queue_next_dist) { + _curr_dist++; + _queue_next_dist=_queue_head; + } + Node n=_queue[_queue_tail++]; + _processed->set(n,true); + Node m; + for(OutEdgeIt e(*G,n);e!=INVALID;++e) + if(!(*_reached)[m=G->target(e)]) { + _queue[_queue_head++]=m; + _reached->set(m,true); + _pred->set(m,e); +// _pred_node->set(m,n); + _dist->set(m,_curr_dist); + } + } + + ///\brief Returns \c false if there are nodes + ///to be processed in the queue + /// + ///Returns \c false if there are nodes + ///to be processed in the queue + bool emptyQueue() { return _queue_tail==_queue_head; } + ///Returns the number of the nodes to be processed. + + ///Returns the number of the nodes to be processed in the queue. + /// + int queueSize() { return _queue_head-_queue_tail; } + + ///Executes the algorithm. + + ///Executes the algorithm. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %BFS algorithm from the root node(s) + ///in order to + ///compute the + ///shortest path to each node. The algorithm computes + ///- The shortest path tree. + ///- The distance of each node from the root(s). + /// + void start() + { + while ( !emptyQueue() ) processNextNode(); + } + + ///Executes the algorithm until \c dest is reached. + + ///Executes the algorithm until \c dest is reached. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %BFS algorithm from the root node(s) + ///in order to + ///compute the + ///shortest path to \c dest. The algorithm computes + ///- The shortest path to \c dest. + ///- The distance of \c dest from the root(s). + /// + void start(Node dest) + { + while ( !emptyQueue() && _queue[_queue_tail]!=dest ) processNextNode(); + } + + ///Executes the algorithm until a condition is met. + + ///Executes the algorithm until a condition is met. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///\param nm must be a bool (or convertible) node map. The algorithm + ///will stop when it reaches a node \c v with nm[v]==true. + template + void start(const NM &nm) + { + while ( !emptyQueue() && !nm[_queue[_queue_tail]] ) processNextNode(); + } + + ///Runs %BFS algorithm from node \c s. + + ///This method runs the %BFS algorithm from a root node \c s + ///in order to + ///compute the + ///shortest path to each node. The algorithm computes + ///- The shortest path tree. + ///- The distance of each node from the root. + /// + ///\note d.run(s) is just a shortcut of the following code. + ///\code + /// d.init(); + /// d.addSource(s); + /// d.start(); + ///\endcode + void run(Node s) { + init(); + addSource(s); + start(); + } + + ///Finds the shortest path between \c s and \c t. + + ///Finds the shortest path between \c s and \c t. + /// + ///\return The length of the shortest s---t path if there exists one, + ///0 otherwise. + ///\note Apart from the return value, d.run(s) is + ///just a shortcut of the following code. + ///\code + /// d.init(); + /// d.addSource(s); + /// d.start(t); + ///\endcode + int run(Node s,Node t) { + init(); + addSource(s); + start(t); + return reached(t)?_curr_dist-1+(_queue_tail==_queue_next_dist):0; + } + + ///@} + + ///\name Query Functions + ///The result of the %BFS algorithm can be obtained using these + ///functions.\n + ///Before the use of these functions, + ///either run() or start() must be called. + + ///@{ + + ///Copies the shortest path to \c t into \c p + + ///This function copies the shortest path to \c t into \c p. + ///If it \c \t is a source itself or unreachable, then it does not + ///alter \c p. + ///\todo Is it the right way to handle unreachable nodes? + ///\return Returns \c true if a path to \c t was actually copied to \c p, + ///\c false otherwise. + ///\sa DirPath + template + bool getPath(P &p,Node t) + { + if(reached(t)) { + p.clear(); + typename P::Builder b(p); + for(b.setStartNode(t);pred(t)!=INVALID;t=predNode(t)) + b.pushFront(pred(t)); + b.commit(); + return true; + } + return false; + } + + ///The distance of a node from the root(s). + + ///Returns the distance of a node from the root(s). + ///\pre \ref run() must be called before using this function. + ///\warning If node \c v in unreachable from the root(s) the return value + ///of this function is undefined. + int dist(Node v) const { return (*_dist)[v]; } + + ///Returns the 'previous edge' of the shortest path tree. + + ///For a node \c v it returns the 'previous edge' + ///of the shortest path tree, + ///i.e. it returns the last edge of a shortest path from the root(s) to \c + ///v. It is \ref INVALID + ///if \c v is unreachable from the root(s) or \c v is a root. The + ///shortest path tree used here is equal to the shortest path tree used in + ///\ref predNode(Node v). + ///\pre Either \ref run() or \ref start() must be called before using + ///this function. + ///\todo predEdge could be a better name. + Edge pred(Node v) const { return (*_pred)[v];} + + ///Returns the 'previous node' of the shortest path tree. + + ///For a node \c v it returns the 'previous node' + ///of the shortest path tree, + ///i.e. it returns the last but one node from a shortest path from the + ///root(a) to \c /v. + ///It is INVALID if \c v is unreachable from the root(s) or + ///if \c v itself a root. + ///The shortest path tree used here is equal to the shortest path + ///tree used in \ref pred(Node v). + ///\pre Either \ref run() or \ref start() must be called before + ///using this function. + Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID: + G->source((*_pred)[v]); } + + ///Returns a reference to the NodeMap of distances. + + ///Returns a reference to the NodeMap of distances. + ///\pre Either \ref run() or \ref init() must + ///be called before using this function. + const DistMap &distMap() const { return *_dist;} + + ///Returns a reference to the shortest path tree map. + + ///Returns a reference to the NodeMap of the edges of the + ///shortest path tree. + ///\pre Either \ref run() or \ref init() + ///must be called before using this function. + const PredMap &predMap() const { return *_pred;} + +// ///Returns a reference to the map of nodes of shortest paths. + +// ///Returns a reference to the NodeMap of the last but one nodes of the +// ///shortest path tree. +// ///\pre \ref run() must be called before using this function. +// const PredNodeMap &predNodeMap() const { return *_predNode;} + + ///Checks if a node is reachable from the root. + + ///Returns \c true if \c v is reachable from the root. + ///\warning The source nodes are indicated as unreached. + ///\pre Either \ref run() or \ref start() + ///must be called before using this function. + /// + bool reached(Node v) { return (*_reached)[v]; } + + ///@} + }; + + ///Default traits class of Bfs function. + + ///Default traits class of Bfs function. + ///\param GR Graph type. + template + struct BfsWizardDefaultTraits + { + ///The graph type the algorithm runs on. + typedef GR Graph; + ///\brief The type of the map that stores the last + ///edges of the shortest paths. + /// + ///The type of the map that stores the last + ///edges of the shortest paths. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef NullMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \ref PredMap. + ///\param G is the graph, to which we would like to define the PredMap. + ///\todo The graph alone may be insufficient to initialize + static PredMap *createPredMap(const GR &) + { + return new PredMap(); + } +// ///\brief The type of the map that stores the last but one +// ///nodes of the shortest paths. +// /// +// ///The type of the map that stores the last but one +// ///nodes of the shortest paths. +// ///It must meet the \ref concept::WriteMap "WriteMap" concept. +// /// +// typedef NullMap PredNodeMap; +// ///Instantiates a PredNodeMap. + +// ///This function instantiates a \ref PredNodeMap. +// ///\param G is the graph, to which +// ///we would like to define the \ref PredNodeMap +// static PredNodeMap *createPredNodeMap(const GR &G) +// { +// return new PredNodeMap(); +// } + + ///The type of the map that indicates which nodes are processed. + + ///The type of the map that indicates which nodes are processed. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \ref ProcessedMap. + ///\param G is the graph, to which + ///we would like to define the \ref ProcessedMap + static ProcessedMap *createProcessedMap(const GR &) + { + return new ProcessedMap(); + } + ///The type of the map that indicates which nodes are reached. + + ///The type of the map that indicates which nodes are reached. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef typename Graph::template NodeMap ReachedMap; + ///Instantiates a ReachedMap. + + ///This function instantiates a \ref ReachedMap. + ///\param G is the graph, to which + ///we would like to define the \ref ReachedMap. + static ReachedMap *createReachedMap(const GR &G) + { + return new ReachedMap(G); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef NullMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param G is the graph, to which we would like to define the \ref DistMap + static DistMap *createDistMap(const GR &) + { + return new DistMap(); + } + }; + + /// Default traits used by \ref BfsWizard + + /// To make it easier to use Bfs algorithm + ///we have created a wizard class. + /// This \ref BfsWizard class needs default traits, + ///as well as the \ref Bfs class. + /// The \ref BfsWizardBase is a class to be the default traits of the + /// \ref BfsWizard class. + template + class BfsWizardBase : public BfsWizardDefaultTraits + { + + typedef BfsWizardDefaultTraits Base; + protected: + /// Type of the nodes in the graph. + typedef typename Base::Graph::Node Node; + + /// Pointer to the underlying graph. + void *_g; + ///Pointer to the map of reached nodes. + void *_reached; + ///Pointer to the map of processed nodes. + void *_processed; + ///Pointer to the map of predecessors edges. + void *_pred; +// ///Pointer to the map of predecessors nodes. +// void *_predNode; + ///Pointer to the map of distances. + void *_dist; + ///Pointer to the source node. + Node _source; + + public: + /// Constructor. + + /// This constructor does not require parameters, therefore it initiates + /// all of the attributes to default values (0, INVALID). + BfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), +// _predNode(0), + _dist(0), _source(INVALID) {} + + /// Constructor. + + /// This constructor requires some parameters, + /// listed in the parameters list. + /// Others are initiated to 0. + /// \param g is the initial value of \ref _g + /// \param s is the initial value of \ref _source + BfsWizardBase(const GR &g, Node s=INVALID) : + _g((void *)&g), _reached(0), _processed(0), _pred(0), +// _predNode(0), + _dist(0), _source(s) {} + + }; + + /// A class to make the usage of Bfs algorithm easier + + /// This class is created to make it easier to use Bfs algorithm. + /// It uses the functions and features of the plain \ref Bfs, + /// but it is much simpler to use it. + /// + /// Simplicity means that the way to change the types defined + /// in the traits class is based on functions that returns the new class + /// and not on templatable built-in classes. + /// When using the plain \ref Bfs + /// the new class with the modified type comes from + /// the original class by using the :: + /// operator. In the case of \ref BfsWizard only + /// a function have to be called and it will + /// return the needed class. + /// + /// It does not have own \ref run method. When its \ref run method is called + /// it initiates a plain \ref Bfs class, and calls the \ref Bfs::run + /// method of it. + template + class BfsWizard : public TR + { + typedef TR Base; + + ///The type of the underlying graph. + typedef typename TR::Graph Graph; + //\e + typedef typename Graph::Node Node; + //\e + typedef typename Graph::NodeIt NodeIt; + //\e + typedef typename Graph::Edge Edge; + //\e + typedef typename Graph::OutEdgeIt OutEdgeIt; + + ///\brief The type of the map that stores + ///the reached nodes + typedef typename TR::ReachedMap ReachedMap; + ///\brief The type of the map that stores + ///the processed nodes + typedef typename TR::ProcessedMap ProcessedMap; + ///\brief The type of the map that stores the last + ///edges of the shortest paths. + typedef typename TR::PredMap PredMap; +// ///\brief The type of the map that stores the last but one +// ///nodes of the shortest paths. +// typedef typename TR::PredNodeMap PredNodeMap; + ///The type of the map that stores the dists of the nodes. + typedef typename TR::DistMap DistMap; + +public: + /// Constructor. + BfsWizard() : TR() {} + + /// Constructor that requires parameters. + + /// Constructor that requires parameters. + /// These parameters will be the default values for the traits class. + BfsWizard(const Graph &g, Node s=INVALID) : + TR(g,s) {} + + ///Copy constructor + BfsWizard(const TR &b) : TR(b) {} + + ~BfsWizard() {} + + ///Runs Bfs algorithm from a given node. + + ///Runs Bfs algorithm from a given node. + ///The node can be given by the \ref source function. + void run() + { + if(Base::_source==INVALID) throw UninitializedParameter(); + Bfs alg(*(Graph*)Base::_g); + if(Base::_reached) + alg.reachedMap(*(ReachedMap*)Base::_reached); + if(Base::_processed) alg.processedMap(*(ProcessedMap*)Base::_processed); + if(Base::_pred) alg.predMap(*(PredMap*)Base::_pred); +// if(Base::_predNode) alg.predNodeMap(*(PredNodeMap*)Base::_predNode); + if(Base::_dist) alg.distMap(*(DistMap*)Base::_dist); + alg.run(Base::_source); + } + + ///Runs Bfs algorithm from the given node. + + ///Runs Bfs algorithm from the given node. + ///\param s is the given source. + void run(Node s) + { + Base::_source=s; + run(); + } + + template + struct DefPredMapBase : public Base { + typedef T PredMap; + static PredMap *createPredMap(const Graph &) { return 0; }; + DefPredMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting PredMap + /// + /// \ref named-templ-param "Named parameter" + ///function for setting PredMap + /// + template + BfsWizard > predMap(const T &t) + { + Base::_pred=(void *)&t; + return BfsWizard >(*this); + } + + + template + struct DefReachedMapBase : public Base { + typedef T ReachedMap; + static ReachedMap *createReachedMap(const Graph &) { return 0; }; + DefReachedMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting ReachedMap + /// + /// \ref named-templ-param "Named parameter" + ///function for setting ReachedMap + /// + template + BfsWizard > reachedMap(const T &t) + { + Base::_pred=(void *)&t; + return BfsWizard >(*this); + } + + + template + struct DefProcessedMapBase : public Base { + typedef T ProcessedMap; + static ProcessedMap *createProcessedMap(const Graph &) { return 0; }; + DefProcessedMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting ProcessedMap + /// + /// \ref named-templ-param "Named parameter" + ///function for setting ProcessedMap + /// + template + BfsWizard > processedMap(const T &t) + { + Base::_pred=(void *)&t; + return BfsWizard >(*this); + } + + +// template +// struct DefPredNodeMapBase : public Base { +// typedef T PredNodeMap; +// static PredNodeMap *createPredNodeMap(const Graph &G) { return 0; }; +// DefPredNodeMapBase(const TR &b) : TR(b) {} +// }; + +// ///\brief \ref named-templ-param "Named parameter" +// ///function for setting PredNodeMap type +// /// +// /// \ref named-templ-param "Named parameter" +// ///function for setting PredNodeMap type +// /// +// template +// BfsWizard > predNodeMap(const T &t) +// { +// Base::_predNode=(void *)&t; +// return BfsWizard >(*this); +// } + + template + struct DefDistMapBase : public Base { + typedef T DistMap; + static DistMap *createDistMap(const Graph &) { return 0; }; + DefDistMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + /// \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + template + BfsWizard > distMap(const T &t) + { + Base::_dist=(void *)&t; + return BfsWizard >(*this); + } + + /// Sets the source node, from which the Bfs algorithm runs. + + /// Sets the source node, from which the Bfs algorithm runs. + /// \param s is the source node. + BfsWizard &source(Node s) + { + Base::_source=s; + return *this; + } + + }; + + ///Function type interface for Bfs algorithm. + + /// \ingroup flowalgs + ///Function type interface for Bfs algorithm. + /// + ///This function also has several + ///\ref named-templ-func-param "named parameters", + ///they are declared as the members of class \ref BfsWizard. + ///The following + ///example shows how to use these parameters. + ///\code + /// bfs(g,source).predMap(preds).run(); + ///\endcode + ///\warning Don't forget to put the \ref BfsWizard::run() "run()" + ///to the end of the parameter list. + ///\sa BfsWizard + ///\sa Bfs + template + BfsWizard > + bfs(const GR &g,typename GR::Node s=INVALID) + { + return BfsWizard >(g,s); + } + +} //END OF NAMESPACE LEMON + +#endif + diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bin_heap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bin_heap.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,303 @@ +/* -*- C++ -*- + * lemon/bin_heap.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_BIN_HEAP_H +#define LEMON_BIN_HEAP_H + +///\ingroup auxdat +///\file +///\brief Binary Heap implementation. + +#include +#include +#include + +namespace lemon { + + /// \addtogroup auxdat + /// @{ + + /// A Binary Heap implementation. + + ///This class implements the \e binary \e heap data structure. A \e heap + ///is a data structure for storing items with specified values called \e + ///priorities in such a way that finding the item with minimum priority is + ///efficient. \c Compare specifies the ordering of the priorities. In a heap + ///one can change the priority of an item, add or erase an item, etc. + /// + ///\param Item Type of the items to be stored. + ///\param Prio Type of the priority of the items. + ///\param ItemIntMap A read and writable Item int map, used internally + ///to handle the cross references. + ///\param Compare A class for the ordering of the priorities. The + ///default is \c std::less. + /// + ///\sa FibHeap + ///\sa Dijkstra + template > + class BinHeap { + + public: + typedef Item ItemType; + // FIXME: stl-ben nem ezt hivjak value_type -nak, hanem a kovetkezot... + typedef Prio PrioType; + typedef std::pair PairType; + typedef ItemIntMap ItemIntMapType; + typedef Compare PrioCompare; + + /// \brief Type to represent the items states. + /// + /// Each Item element have a state associated to it. It may be "in heap", + /// "pre heap" or "post heap". The latter two are indifferent from the + /// heap's point of view, but may be useful to the user. + /// + /// The ItemIntMap \e should be initialized in such way that it maps + /// PRE_HEAP (-1) to any element to be put in the heap... + enum state_enum { + IN_HEAP = 0, + PRE_HEAP = -1, + POST_HEAP = -2 + }; + + private: + std::vector data; + Compare comp; + ItemIntMap &iim; + + public: + /// \brief The constructor. + /// + /// The constructor. + /// \param _iim should be given to the constructor, since it is used + /// internally to handle the cross references. The value of the map + /// should be PRE_HEAP (-1) for each element. + explicit BinHeap(ItemIntMap &_iim) : iim(_iim) {} + + /// \brief The constructor. + /// + /// The constructor. + /// \param _iim should be given to the constructor, since it is used + /// internally to handle the cross references. The value of the map + /// should be PRE_HEAP (-1) for each element. + /// + /// \param _comp The comparator function object. + BinHeap(ItemIntMap &_iim, const Compare &_comp) + : iim(_iim), comp(_comp) {} + + + /// The number of items stored in the heap. + /// + /// \brief Returns the number of items stored in the heap. + int size() const { return data.size(); } + + /// \brief Checks if the heap stores no items. + /// + /// Returns \c true if and only if the heap stores no items. + bool empty() const { return data.empty(); } + + private: + static int parent(int i) { return (i-1)/2; } + static int second_child(int i) { return 2*i+2; } + bool less(const PairType &p1, const PairType &p2) const { + return comp(p1.second, p2.second); + } + + int bubble_up(int hole, PairType p); + int bubble_down(int hole, PairType p, int length); + + void move(const PairType &p, int i) { + data[i] = p; + iim.set(p.first, i); + } + + void rmidx(int h) { + int n = data.size()-1; + if( h>=0 && h<=n ) { + iim.set(data[h].first, POST_HEAP); + if ( h=0 ) + s=0; + return state_enum(s); + } + + }; // class BinHeap + + + template + int BinHeap::bubble_up(int hole, PairType p) { + int par = parent(hole); + while( hole>0 && less(p,data[par]) ) { + move(data[par],hole); + hole = par; + par = parent(hole); + } + move(p, hole); + return hole; + } + + template + int BinHeap::bubble_down(int hole, PairType p, int length) { + int child = second_child(hole); + while(child < length) { + if( less(data[child-1], data[child]) ) { + --child; + } + if( !less(data[child], p) ) + goto ok; + move(data[child], hole); + hole = child; + child = second_child(hole); + } + child--; + if( child +#include + +///\ingroup graphmaps +///\file +///\brief Observer registry for graph alteration observers. + +namespace lemon { + + /// \addtogroup graphmaps + /// @{ + + /// \brief Registry class to register objects observes alterations in + /// the graph. + /// + /// This class is a registry for the objects which observe the + /// alterations in a container. The alteration observers can be attached + /// to and detached from the registry. The observers have to inherit + /// from the \ref AlterationNotifier::ObserverBase and override + /// the virtual functions in that. + /// + /// The most important application of the alteration observing is the + /// dynamic map implementation. + /// + /// \param _Item The item type what the observers are observing, usually + /// edge or node. + /// + /// \author Balazs Dezso + + template + class AlterationNotifier { + public: + typedef _Item Item; + + /// ObserverBase is the base class for the observers. + + /// ObserverBase is the abstract base class for the observers. + /// It will be notified about an item was inserted into or + /// erased from the graph. + /// + /// The observer interface contains some pure virtual functions + /// to override. The add() and erase() functions are + /// to notify the oberver when one item is added or + /// erased. + /// + /// The build() and clear() members are to notify the observer + /// about the container is built from an empty container or + /// is cleared to an empty container. + /// + /// \author Balazs Dezso + + class ObserverBase { + protected: + typedef AlterationNotifier Registry; + + friend class AlterationNotifier; + + /// \brief Default constructor. + /// + /// Default constructor for ObserverBase. + /// + ObserverBase() : registry(0) {} + + virtual ~ObserverBase() {} + + /// \brief Attaches the observer into an AlterationNotifier. + /// + /// This member attaches the observer into an AlterationNotifier. + /// + void attach(AlterationNotifier& r) { + registry = &r; + registry->attach(*this); + } + + /// \brief Detaches the observer into an AlterationNotifier. + /// + /// This member detaches the observer from an AlterationNotifier. + /// + void detach() { + if (registry) { + registry->detach(*this); + } + } + + + /// Gives back a pointer to the registry what the map attached into. + + /// This function gives back a pointer to the registry what the map + /// attached into. + /// + Registry* getRegistry() const { return const_cast(registry); } + + /// Gives back true when the observer is attached into a registry. + bool attached() const { return registry != 0; } + + private: + + ObserverBase(const ObserverBase& copy); + ObserverBase& operator=(const ObserverBase& copy); + + protected: + + Registry* registry; + int registry_index; + + public: + + /// \brief The member function to notificate the observer about an + /// item is added to the container. + /// + /// The add() member function notificates the observer about an item + /// is added to the container. It have to be overrided in the + /// subclasses. + + virtual void add(const Item&) = 0; + + /// \brief The member function to notificate the observer about + /// simulitem is added to the container. + /// + /// The add() member function notificates the observer about an item + /// is added to the container. It have to be overrided in the + /// subclasses. + + virtual void add(const std::vector& items) { + for (int i = 0; i < (int)items.size(); ++i) { + add(items[i]); + } + } + + /// \brief The member function to notificate the observer about an + /// item is erased from the container. + /// + /// The erase() member function notificates the observer about an + /// item is erased from the container. It have to be overrided in + /// the subclasses. + + virtual void erase(const Item&) = 0; + + virtual void erase(const std::vector& items) { + for (int i = 0; i < (int)items.size(); ++i) { + add(items[i]); + } + } + + /// \brief The member function to notificate the observer about the + /// container is built. + /// + /// The build() member function notificates the observer about the + /// container is built from an empty container. It have to be + /// overrided in the subclasses. + + virtual void build() = 0; + + /// \brief The member function to notificate the observer about all + /// items are erased from the container. + /// + /// The clear() member function notificates the observer about all + /// items are erased from the container. It have to be overrided in + /// the subclasses. + + virtual void clear() = 0; + + }; + + protected: + + + typedef std::vector Container; + + Container container; + + + public: + + /// Default constructor. + + /// + /// The default constructor of the AlterationNotifier. + /// It creates an empty registry. + AlterationNotifier() {} + + /// Copy Constructor of the AlterationNotifier. + + /// Copy constructor of the AlterationNotifier. + /// It creates only an empty registry because the copiable + /// registry's observers have to be registered still into that registry. + AlterationNotifier(const AlterationNotifier&) {} + + /// Assign operator. + + /// Assign operator for the AlterationNotifier. + /// It makes the notifier only empty because the copiable + /// notifier's observers have to be registered still into that registry. + AlterationNotifier& operator=(const AlterationNotifier&) { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->registry = 0; + } + } + + /// Destructor. + + /// Destructor of the AlterationNotifier. + /// + ~AlterationNotifier() { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->registry = 0; + } + } + + + protected: + + void attach(ObserverBase& observer) { + container.push_back(&observer); + observer.registry = this; + observer.registry_index = container.size()-1; + } + + void detach(ObserverBase& base) { + container.back()->registry_index = base.registry_index; + container[base.registry_index] = container.back(); + container.pop_back(); + base.registry = 0; + } + + public: + + /// \brief Notifies all the registered observers about an Item added to + /// the container. + /// + /// It notifies all the registered observers about an Item added to + /// the container. + /// + void add(const Item& item) { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->add(item); + } + } + + /// \brief Notifies all the registered observers about more Item added to + /// the container. + /// + /// It notifies all the registered observers about more Item added to + /// the container. + /// + void add(const std::vector& items) { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->add(items); + } + } + + /// \brief Notifies all the registered observers about an Item erased from + /// the container. + /// + /// It notifies all the registered observers about an Item erased from + /// the container. + /// + void erase(const Item& key) { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->erase(key); + } + } + + /// \brief Notifies all the registered observers about more Item erased + /// from the container. + /// + /// It notifies all the registered observers about more Item erased from + /// the container. + /// + void erase(const std::vector& items) { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->erase(items); + } + } + + + /// \brief Notifies all the registered observers about the container is + /// built. + /// + /// Notifies all the registered observers about the container is built + /// from an empty container. + void build() { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->build(); + } + } + + + /// \brief Notifies all the registered observers about all Items are + /// erased. + /// + /// Notifies all the registered observers about all Items are erased + /// from the container. + void clear() { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->clear(); + } + } + }; + + + /// \brief Class to extend a graph with the functionality of alteration + /// observing. + /// + /// AlterableGraphExtender extends the _Base graphs functionality with + /// the possibility of alteration observing. It defines two observer + /// registrys for the nodes and mapes. + /// + /// \todo Document what "alteration observing" is. And probably find a + /// better (shorter) name. + /// + /// \param _Base is the base class to extend. + /// + /// \pre _Base is conform to the BaseGraphComponent concept. + /// + /// \post AlterableGraphExtender<_Base> is conform to the + /// AlterableGraphComponent concept. + /// + /// \author Balazs Dezso + + template + class AlterableGraphExtender : public _Base { + public: + + typedef AlterableGraphExtender Graph; + typedef _Base Parent; + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + /// The edge observer registry. + typedef AlterationNotifier EdgeNotifier; + /// The node observer registry. + typedef AlterationNotifier NodeNotifier; + + + protected: + + mutable EdgeNotifier edge_notifier; + + mutable NodeNotifier node_notifier; + + public: + + /// \brief Gives back the edge alteration notifier. + /// + /// Gives back the edge alteration notifier. + EdgeNotifier& getNotifier(Edge) const { + return edge_notifier; + } + + /// \brief Gives back the node alteration notifier. + /// + /// Gives back the node alteration notifier. + NodeNotifier& getNotifier(Node) const { + return node_notifier; + } + + ~AlterableGraphExtender() { + node_notifier.clear(); + edge_notifier.clear(); + } + + }; + + /// \brief Class to extend an undirected graph with the functionality of + /// alteration observing. + /// + /// \todo Document. + /// + /// \sa AlterableGraphExtender + /// + /// \bug This should be done some other way. Possibilities: template + /// specialization (not very easy, if at all possible); some kind of + /// enable_if boost technique? + + template + class AlterableUndirGraphExtender + : public AlterableGraphExtender<_Base> { + public: + + typedef AlterableUndirGraphExtender Graph; + typedef AlterableGraphExtender<_Base> Parent; + + typedef typename Parent::UndirEdge UndirEdge; + + /// The edge observer registry. + typedef AlterationNotifier UndirEdgeNotifier; + + protected: + + mutable UndirEdgeNotifier undir_edge_notifier; + + public: + + using Parent::getNotifier; + UndirEdgeNotifier& getNotifier(UndirEdge) const { + return undir_edge_notifier; + } + + ~AlterableUndirGraphExtender() { + undir_edge_notifier.clear(); + } + }; + +/// @} + + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/array_map.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/array_map.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,369 @@ +/* -*- C++ -*- + * lemon/bits/array_map.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_ARRAY_MAP_H +#define LEMON_ARRAY_MAP_H + +#include +#include + +///\ingroup graphmaps +///\file +///\brief Graph maps that construates and destruates +///their elements dynamically. + +namespace lemon { + + + /// \addtogroup graphmaps + /// @{ + + /// The ArrayMap template class is graph map structure what + /// automatically updates the map when a key is added to or erased from + /// the map. This map factory uses the allocators to implement + /// the container functionality. + /// + /// The template parameter is the AlterationNotifier that the maps + /// will belong to and the Value. + + + template + class ArrayMap : public AlterationNotifier<_Item>::ObserverBase { + + typedef _Item Item; + public: + + /// The graph type of the maps. + typedef _Graph Graph; + /// The key type of the maps. + typedef _Item Key; + + typedef AlterationNotifier<_Item> Registry; + + /// The MapBase of the Map which imlements the core regisitry function. + typedef typename Registry::ObserverBase Parent; + + /// The value type of the map. + typedef _Value Value; + + + private: + typedef std::allocator Allocator; + + + public: + + /// Graph and Registry initialized map constructor. + + ArrayMap(const Graph& _g) : graph(&_g) { + Item it; + attach(_g.getNotifier(Item())); + allocate_memory(); + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it);; + allocator.construct(&(values[id]), Value()); + } + } + + /// Constructor to use default value to initialize the map. + + /// It constrates a map and initialize all of the the map. + + ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) { + Item it; + attach(_g.getNotifier(_Item())); + allocate_memory(); + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it);; + allocator.construct(&(values[id]), _v); + } + } + + /// Constructor to copy a map of the same map type. + + ArrayMap(const ArrayMap& copy) : Parent() { + if (copy.attached()) { + attach(*copy.getRegistry()); + } + capacity = copy.capacity; + if (capacity == 0) return; + values = allocator.allocate(capacity); + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it);; + allocator.construct(&(values[id]), copy.values[id]); + } + } + + using Parent::attach; + using Parent::detach; + using Parent::attached; + + /// Assign operator to copy a map of the same map type. + + ArrayMap& operator=(const ArrayMap& copy) { + if (© == this) return *this; + + if (graph != copy.graph) { + if (attached()) { + clear(); + detach(); + } + if (copy.attached()) { + attach(*copy.getRegistry()); + } + capacity = copy.capacity; + if (capacity == 0) return *this; + values = allocator.allocate(capacity); + } + + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it);; + allocator.construct(&(values[id]), copy.values[id]); + } + + return *this; + } + + /// The destructor of the map. + + virtual ~ArrayMap() { + if (attached()) { + clear(); + detach(); + } + } + + + ///The subscript operator. The map can be subscripted by the + ///actual keys of the graph. + + Value& operator[](const Key& key) { + int id = graph->id(key); + return values[id]; + } + + + ///The const subscript operator. The map can be subscripted by the + ///actual keys of the graph. + + const Value& operator[](const Key& key) const { + int id = graph->id(key); + return values[id]; + } + + /// Setter function of the map. Equivalent with map[key] = val. + /// This is a compatibility feature with the not dereferable maps. + + void set(const Key& key, const Value& val) { + (*this)[key] = val; + } + + /// Add a new key to the map. It called by the map registry. + + void add(const Key& key) { + int id = graph->id(key); + if (id >= capacity) { + int new_capacity = (capacity == 0 ? 1 : capacity); + while (new_capacity <= id) { + new_capacity <<= 1; + } + Value* new_values = allocator.allocate(new_capacity); + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int jd = graph->id(it);; + if (id != jd) { + allocator.construct(&(new_values[jd]), values[jd]); + allocator.destroy(&(values[jd])); + } + } + if (capacity != 0) allocator.deallocate(values, capacity); + values = new_values; + capacity = new_capacity; + } + allocator.construct(&(values[id]), Value()); + } + + void add(const std::vector& keys) { + int max_id = -1; + for (int i = 0; i < (int)keys.size(); ++i) { + int id = graph->id(keys[i]); + if (id > max_id) { + max_id = id; + } + } + if (max_id >= capacity) { + int new_capacity = (capacity == 0 ? 1 : capacity); + while (new_capacity <= max_id) { + new_capacity <<= 1; + } + Value* new_values = allocator.allocate(new_capacity); + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it); + bool found = false; + for (int i = 0; i < (int)keys.size(); ++i) { + int jd = graph->id(keys[i]); + if (id == jd) { + found = true; + break; + } + } + if (found) continue; + allocator.construct(&(new_values[id]), values[id]); + allocator.destroy(&(values[id])); + } + if (capacity != 0) allocator.deallocate(values, capacity); + values = new_values; + capacity = new_capacity; + } + for (int i = 0; i < (int)keys.size(); ++i) { + int id = graph->id(keys[i]); + allocator.construct(&(values[id]), Value()); + } + } + + /// Erase a key from the map. It called by the map registry. + + void erase(const Key& key) { + int id = graph->id(key); + allocator.destroy(&(values[id])); + } + + void erase(const std::vector& keys) { + for (int i = 0; i < (int)keys.size(); ++i) { + int id = graph->id(keys[i]); + allocator.destroy(&(values[id])); + } + } + + void build() { + allocate_memory(); + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it);; + allocator.construct(&(values[id]), Value()); + } + } + + void clear() { + if (capacity != 0) { + Item it; + for (graph->first(it); it != INVALID; graph->next(it)) { + int id = graph->id(it); + allocator.destroy(&(values[id])); + } + allocator.deallocate(values, capacity); + capacity = 0; + } + } + + const Graph* getGraph() { + return graph; + } + + private: + + void allocate_memory() { + int max_id = graph->maxId(_Item()); + if (max_id == -1) { + capacity = 0; + values = 0; + return; + } + capacity = 1; + while (capacity <= max_id) { + capacity <<= 1; + } + values = allocator.allocate(capacity); + } + + const Graph* graph; + int capacity; + Value* values; + Allocator allocator; + + }; + + template + class ArrayMappableGraphExtender : public _Base { + public: + + typedef ArrayMappableGraphExtender<_Base> Graph; + typedef _Base Parent; + + typedef typename Parent::Node Node; + typedef typename Parent::NodeIt NodeIt; + typedef typename Parent::NodeNotifier NodeObserverRegistry; + + typedef typename Parent::Edge Edge; + typedef typename Parent::EdgeIt EdgeIt; + typedef typename Parent::EdgeNotifier EdgeObserverRegistry; + + + + template + class NodeMap + : public IterableMapExtender > { + public: + typedef ArrayMappableGraphExtender<_Base> Graph; + + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + + typedef IterableMapExtender > Parent; + + //typedef typename Parent::Graph Graph; + typedef typename Parent::Value Value; + + NodeMap(const Graph& g) + : Parent(g) {} + NodeMap(const Graph& g, const Value& v) + : Parent(g, v) {} + + }; + + template + class EdgeMap + : public IterableMapExtender > { + public: + typedef ArrayMappableGraphExtender<_Base> Graph; + + typedef typename Graph::Edge Edge; + typedef typename Graph::EdgeIt EdgeIt; + + typedef IterableMapExtender > Parent; + + //typedef typename Parent::Graph Graph; + typedef typename Parent::Value Value; + + EdgeMap(const Graph& g) + : Parent(g) {} + EdgeMap(const Graph& g, const Value& v) + : Parent(g, v) {} + + }; + + }; + +/// @} + +} + +#endif //LEMON_ARRAY_MAP_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/clearable_graph_extender.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/clearable_graph_extender.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,49 @@ +// -*- c++ -*- + +#ifndef LEMON_CLEARABLE_GRAPH_EXTENDER_H +#define LEMON_CLEARABLE_GRAPH_EXTENDER_H + +#include + + +namespace lemon { + + template + class ClearableGraphExtender : public _Base { + public: + + typedef ClearableGraphExtender Graph; + typedef _Base Parent; + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + void clear() { + Parent::getNotifier(Node()).clear(); + Parent::getNotifier(Edge()).clear(); + Parent::clear(); + } + + }; + + template + class ClearableUndirGraphExtender : public _Base { + public: + + typedef ClearableUndirGraphExtender Graph; + typedef _Base Parent; + typedef typename Parent::Node Node; + typedef typename Parent::UndirEdge UndirEdge; + typedef typename Parent::Edge Edge; + + void clear() { + Parent::getNotifier(Node()).clear(); + Parent::getNotifier(UndirEdge()).clear(); + Parent::getNotifier(Edge()).clear(); + Parent::clear(); + } + + }; + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/default_map.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/default_map.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,230 @@ +/* -*- C++ -*- + * lemon/default_map.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_DEFAULT_MAP_H +#define LEMON_DEFAULT_MAP_H + + +#include +#include + +///\ingroup graphmaps +///\file +///\brief Graph maps that construct and destruct +///their elements dynamically. + +namespace lemon { + +/// \addtogroup graphmaps +/// @{ + + /** The ArrayMap template class is graph map structure what + * automatically updates the map when a key is added to or erased from + * the map. This map uses the VectorMap if the Value is a primitive + * type and the ArrayMap for the other cases. + * + * The template parameter is the MapRegistry that the maps + * will belong to and the Value. + */ + + + + template + struct DefaultMapSelector { + typedef ArrayMap<_Graph, _Item, _Value> Map; + }; + + // bool + template + struct DefaultMapSelector<_Graph, _Item, bool> { + typedef VectorMap<_Graph, _Item, bool> Map; + }; + + // char + template + struct DefaultMapSelector<_Graph, _Item, char> { + typedef VectorMap<_Graph, _Item, char> Map; + }; + + template + struct DefaultMapSelector<_Graph, _Item, signed char> { + typedef VectorMap<_Graph, _Item, signed char> Map; + }; + + template + struct DefaultMapSelector<_Graph, _Item, unsigned char> { + typedef VectorMap<_Graph, _Item, unsigned char> Map; + }; + + + // int + template + struct DefaultMapSelector<_Graph, _Item, signed int> { + typedef VectorMap<_Graph, _Item, signed int> Map; + }; + + template + struct DefaultMapSelector<_Graph, _Item, unsigned int> { + typedef VectorMap<_Graph, _Item, unsigned int> Map; + }; + + + // short + template + struct DefaultMapSelector<_Graph, _Item, signed short> { + typedef VectorMap<_Graph, _Item, signed short> Map; + }; + + template + struct DefaultMapSelector<_Graph, _Item, unsigned short> { + typedef VectorMap<_Graph, _Item, unsigned short> Map; + }; + + + // long + template + struct DefaultMapSelector<_Graph, _Item, signed long> { + typedef VectorMap<_Graph, _Item, signed long> Map; + }; + + template + struct DefaultMapSelector<_Graph, _Item, unsigned long> { + typedef VectorMap<_Graph, _Item, unsigned long> Map; + }; + + // \todo handling long long type + + + // float + template + struct DefaultMapSelector<_Graph, _Item, float> { + typedef VectorMap<_Graph, _Item, float> Map; + }; + + + // double + template + struct DefaultMapSelector<_Graph, _Item, double> { + typedef VectorMap<_Graph, _Item, double> Map; + }; + + + // long double + template + struct DefaultMapSelector<_Graph, _Item, long double> { + typedef VectorMap<_Graph, _Item, long double> Map; + }; + + + // pointer + template + struct DefaultMapSelector<_Graph, _Item, _Ptr*> { + typedef VectorMap<_Graph, _Item, _Ptr*> Map; + }; + + + + template < + typename _Graph, + typename _Item, + typename _Value> + class DefaultMap + : public DefaultMapSelector<_Graph, _Item, _Value>::Map { + public: + typedef typename DefaultMapSelector<_Graph, _Item, _Value>::Map Parent; + typedef DefaultMap<_Graph, _Item, _Value> Map; + + typedef typename Parent::Graph Graph; + typedef typename Parent::Value Value; + + DefaultMap(const Graph& _g) : Parent(_g) {} + DefaultMap(const Graph& _g, const Value& _v) : Parent(_g, _v) {} + }; + + + + template + class DefaultMappableGraphExtender : public _Base { + public: + + typedef DefaultMappableGraphExtender<_Base> Graph; + typedef _Base Parent; + + typedef typename Parent::Node Node; + typedef typename Parent::NodeIt NodeIt; + + typedef typename Parent::Edge Edge; + typedef typename Parent::EdgeIt EdgeIt; + + + template + class NodeMap + : public IterableMapExtender > { + public: + typedef DefaultMappableGraphExtender Graph; + typedef IterableMapExtender > Parent; + + NodeMap(const Graph& _g) + : Parent(_g) {} + NodeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + }; + + template + class EdgeMap + : public IterableMapExtender > { + public: + typedef DefaultMappableGraphExtender Graph; + typedef IterableMapExtender > Parent; + + EdgeMap(const Graph& _g) + : Parent(_g) {} + EdgeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + }; + + }; + + template + class MappableUndirGraphExtender : + public DefaultMappableGraphExtender<_Base> { + public: + + typedef MappableUndirGraphExtender Graph; + typedef DefaultMappableGraphExtender<_Base> Parent; + + typedef typename Parent::UndirEdge UndirEdge; + + template + class UndirEdgeMap + : public IterableMapExtender > { + public: + typedef MappableUndirGraphExtender Graph; + typedef IterableMapExtender< + DefaultMap > Parent; + + UndirEdgeMap(const Graph& _g) + : Parent(_g) {} + UndirEdgeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + }; + + + }; + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/erasable_graph_extender.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/erasable_graph_extender.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,84 @@ +// -*- c++ -*- + +#ifndef LEMON_ERASABLE_GRAPH_EXTENDER_H +#define LEMON_ERASABLE_GRAPH_EXTENDER_H + +#include + +#include + + +namespace lemon { + + template + class ErasableGraphExtender : public _Base { + public: + + typedef ErasableGraphExtender Graph; + typedef _Base Parent; + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + void erase(const Node& node) { + Edge edge; + Parent::firstOut(edge, node); + while (edge != INVALID ) { + erase(edge); + Parent::firstOut(edge, node); + } + + Parent::firstIn(edge, node); + while (edge != INVALID ) { + erase(edge); + Parent::firstIn(edge, node); + } + + Parent::getNotifier(Node()).erase(node); + Parent::erase(node); + } + + void erase(const Edge& edge) { + Parent::getNotifier(Edge()).erase(edge); + Parent::erase(edge); + } + + }; + + template + class ErasableUndirGraphExtender : public _Base { + public: + + typedef ErasableUndirGraphExtender Graph; + typedef _Base Parent; + + typedef typename Parent::Node Node; + typedef typename Parent::UndirEdge UndirEdge; + typedef typename Parent::Edge Edge; + + void erase(const Node& node) { + Edge edge; + Parent::firstOut(edge, node); + while (edge != INVALID ) { + erase(edge); + Parent::firstOut(edge, node); + } + + Parent::getNotifier(Node()).erase(node); + Parent::erase(node); + } + + void erase(const UndirEdge& uedge) { + std::vector edges; + edges.push_back(Edge(uedge,true)); + edges.push_back(Edge(uedge,false)); + Parent::getNotifier(Edge()).erase(edges); + Parent::getNotifier(UndirEdge()).erase(uedge); + Parent::erase(uedge); + } + + }; + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/extendable_graph_extender.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/extendable_graph_extender.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,65 @@ +// -*- c++ -*- + +#ifndef LEMON_EXTENDABLE_GRAPH_EXTENDER_H +#define LEMON_EXTENDABLE_GRAPH_EXTENDER_H + +namespace lemon { + + template + class ExtendableGraphExtender : public _Base { + public: + + typedef ExtendableGraphExtender Graph; + typedef _Base Parent; + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + Node addNode() { + Node node = Parent::addNode(); + Parent::getNotifier(Node()).add(node); + return node; + } + + Edge addEdge(const Node& from, const Node& to) { + Edge edge = Parent::addEdge(from, to); + Parent::getNotifier(Edge()).add(edge); + return edge; + } + + }; + + template + class ExtendableUndirGraphExtender : public _Base { + public: + + typedef ExtendableUndirGraphExtender Graph; + typedef _Base Parent; + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + typedef typename Parent::UndirEdge UndirEdge; + + Node addNode() { + Node node = Parent::addNode(); + Parent::getNotifier(Node()).add(node); + return node; + } + + UndirEdge addEdge(const Node& from, const Node& to) { + UndirEdge uedge = Parent::addEdge(from, to); + Parent::getNotifier(UndirEdge()).add(uedge); + + std::vector edges; + edges.push_back(Edge(uedge, true)); + edges.push_back(Edge(uedge, false)); + Parent::getNotifier(Edge()).add(edges); + + return uedge; + } + + }; + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/extended_pair.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/extended_pair.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,146 @@ +/* -*- C++ -*- + * lemon/bits/extended_pair.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_EXTENDED_PAIR_H +#define LEMON_EXTENDED_PAIR_H + +///\ingroup misc +///\file +///\brief A more customizable pair type than std::pair. + +namespace lemon { + + /// \brief A more customizable pair type than std::pair. + /// + /// This type is a customizable pair type. The main goal + /// is that the constructor's parameter type does not depend + /// on the stored data type. This way it is possible to store + /// references in the extended_pair. + /// \code + /// int a; char b; + /// typedef extended_pair ICPair; + /// ICPair p(a, b); + /// // like a real reference to an std::pair + /// // but the pair does not exist + /// p.first = 42; + /// p.second = '@'; + /// \endcode + /// \param T1 The type of first. + /// \param A1 The parameter type for first. + /// \param T2 The type of second. + /// \param A2 The parameter type for second. + template + struct extended_pair { + /// \brief The type of first. + /// + /// The type of first. + typedef T1 first_type; + /// \brief The type of second. + /// + /// The type of second. + typedef T2 second_type; + + /// \brief Default constructor. + /// + /// Default constructor. It calls the default constructor of + /// first and second. + extended_pair() : first(), second() {} + + /// \brief Constructor. + /// + /// Constructor. + extended_pair(A1 f, A2 s) : first(f), second(s) {} + + /// \brief Template constructor. + /// + /// Template constructor. It copies everything which has + /// \c first and \c second member. + template + extended_pair(const Pair& pair) : first(pair.first), second(pair.second) {} + + /// \brief The first value + /// + /// The first value + T1 first; + /// \brief The second value + /// + /// The second value + T2 second; + }; + + /// \brief Equality operator + /// + /// Equality operator + template + bool operator==(const extended_pair& left, + const extended_pair& right) { + return left.first == right.first && left.second == right.second; + } + + /// \brief Inequality operator. + /// + /// Inequality operator. + template + bool operator!=(const extended_pair& left, + const extended_pair& right) { + return !(left == right); + } + + /// \brief Less operator. + /// + /// Less operator. + template + bool operator<(const extended_pair& left, + const extended_pair& right) { + return left.first < right.first || + (!(right.first + bool operator>(const extended_pair& left, + const extended_pair& right) { + return right < left; + } + + /// \brief Less or equal operator. + /// + /// Less or equal operator. + template + bool operator<=(const extended_pair& left, + const extended_pair& right) { + return !(right > left); + } + + /// \brief Greater or equal operator. + /// + /// Greater or equal operator. + template + bool operator>=(const extended_pair& left, + const extended_pair& right) { + return !(right < left); + } + +} +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/item_reader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/item_reader.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,414 @@ +/* -*- C++ -*- + * lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +/// @defgroup item_io Item Readers and Writers +/// @ingroup io_group +/// \brief Item Readers and Writers +/// +/// The Input-Output classes can handle more data type by example +/// as map or attribute value. Each of these should be written and +/// read some way. The module make possible to do this. + +/// \ingroup item_io +/// \file +/// \brief Item reader bits for lemon input. + +#ifndef LEMON_BITS_ITEM_READER_H +#define LEMON_BITS_ITEM_READER_H + +#include +#include + +#include +#include +#include +#include + +namespace lemon { + + template + class DefaultReader; + + /// \ingroup item_io + /// + /// \brief Reader class for quoted strings. + /// + /// Reader class for quoted strings. It can process the escape + /// sequences in the string. + /// + /// \author Balazs Dezso + class QuotedStringReader { + public: + /// \brief The value type of reader. + /// + /// The value type of reader. + typedef std::string Value; + + /// \brief Constructor for the reader. + /// + /// Constructor for the reader. If the given parameter is true + /// the reader processes the escape sequences. + QuotedStringReader(bool _escaped = true) + : escaped(_escaped) {} + + /// \brief Reads a quoted string from the given stream. + /// + /// Reads a quoted string from the given stream. + void read(std::istream& is, std::string& value) const { + char c; + value.clear(); + is >> std::ws; + if (!is.get(c) || c != '\"') + throw DataFormatError("Quoted string format error"); + while (is.get(c) && c != '\"') { + if (escaped && c == '\\') { + value += readEscape(is); + } else { + value += c; + } + } + if (!is) throw DataFormatError("Quoted string format error"); + } + + private: + + static char readEscape(std::istream& is) { + char c; + switch (is.get(c), c) { + case '\\': + return '\\'; + case '\"': + return '\"'; + case '\'': + return '\''; + case '\?': + return '\?'; + case 'a': + return '\a'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'v': + return '\v'; + case 'x': + { + int code; + if (!is.get(c) || !isHex(c)) + throw DataFormatError("Escape format error"); + else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c); + else code = code * 16 + valueHex(c); + return code; + } + default: + { + int code; + if (!isOct(c)) + throw DataFormatError("Escape format error"); + else if (code = valueOct(c), !is.get(c) || !isOct(c)) + is.putback(c); + else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) + is.putback(c); + else code = code * 8 + valueOct(c); + return code; + } + } + } + + static bool isOct(char c) { + return '0' <= c && c <='7'; + } + + static int valueOct(char c) { + return c - '0'; + } + + static bool isHex(char c) { + return ('0' <= c && c <= '9') || + ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z'); + } + + static int valueHex(char c) { + if ('0' <= c && c <= '9') return c - '0'; + if ('a' <= c && c <= 'z') return c - 'a' + 10; + return c - 'A' + 10; + } + + bool escaped; + }; + + /// \ingroup item_io + /// \brief Reader for standard containers. + /// + /// Reader for back insertable standard containers. The representation + /// of the container is the values enumerated between an open and a + /// close parse. + /// + /// \author Balazs Dezso + template < + typename _Container, + typename _ItemReader = DefaultReader + > + class PushBackReader { + public: + typedef _Container Value; + typedef _ItemReader ItemReader; + + private: + + ItemReader item_reader; + + public: + + /// \brief Reads the values into the container from the given stream. + /// + /// Reads the values into the container from the given stream. + void read(std::istream& is, Value& value) const { + char c; + if (!(is >> c) || c != '(') + throw DataFormatError("PushBackReader format error"); + while (is >> c && c != ')') { + is.putback(c); + typename ItemReader::Value item; + item_reader.read(is, item); + value.push_back(item); + } + if (!is) throw DataFormatError("PushBackReader format error"); + is.putback(c); + } + + }; + + /// \ingroup item_io + /// + /// \brief Reader for standard containers. + /// + /// Reader for insertable standard containers. The representation + /// of the container is the values enumerated between an open and a + /// close parse. + /// + /// \author Balazs Dezso + template < + typename _Container, + typename _ItemReader = DefaultReader + > + class InsertReader { + public: + typedef _Container Value; + typedef _ItemReader ItemReader; + + private: + + ItemReader item_reader; + + public: + + /// \brief Reads the values into the container from the given stream. + /// + /// Reads the values into the container from the given stream. + void read(std::istream& is, Value& value) const { + char c; + if (!(is >> c) || c != '(') + throw DataFormatError("InsertReader format error"); + while (is >> c && c != ')') { + is.putback(c); + typename ItemReader::Value item; + item_reader.read(is, item); + value.insert(item); + } + if (!is) throw DataFormatError("PushBackReader format error"); + is.putback(c); + } + + }; + + /// \ingroup item_io + /// \brief Reader for parsed string. + /// + /// Reader for parsed strings. You can give the open and close + /// parse characters. + /// + /// \author Balazs Dezso + class ParsedStringReader { + public: + typedef std::string Value; + + /// \brief Constructor. + /// + /// Constructor for ParsedStringReader. You can give as parameter + /// the open and close parse characters. + ParsedStringReader(char _open = '(', char _close = ')') + : open(_open), close(_close) {} + + + /// \brief Reads the parsed string from the given stream. + /// + /// Reads the parsed string from the given stream. + void read(std::istream& is, Value& value) const { + char c; + if (!(is >> c) || c != open) { + throw DataFormatError("ParsedStringReader format error"); + } + value += c; + int counter = 1; + while (counter > 0 && is >> c) { + if (c == close) { + --counter; + } else if (c == open) { + ++counter; + } + value += c; + } + if (!is) { + throw DataFormatError("ParsedStrinReader format error"); + } + } + + private: + char open, close; + + }; + + /// \ingroup item_io + /// \brief Reader for read the whole line. + /// + /// Reader for read the whole line. + /// + /// \author Balazs Dezso + class LineReader { + public: + typedef std::string Value; + + /// \brief Constructor. + /// + /// Constructor for the LineReader. If the given parameter is + /// true then the spaces before the first not space character are + /// skipped. + LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {} + + /// \brief Reads the line from the given stream. + /// + /// Reads the line from the given stream. + void read(std::istream& is, Value& value) { + if (skipSpaces) is >> std::ws; + if (!getline(is, value)) { + throw DataFormatError("LineReader forma error"); + } + } + private: + bool skipSpaces; + }; + + /// \ingroup item_io + /// + /// \brief The default item reader template class. + /// + /// The default item reader template class. If some section reader + /// needs to read a value from a stream it will give the default way for it. + /// + /// \author Balazs Dezso + template + class DefaultReader { + public: + /// The value type. + typedef _Value Value; + /// \brief Reads a value from the given stream. + /// + /// Reads a value from the given stream. + void read(std::istream& is, Value& value) const { + if (!(is >> value)) + throw DataFormatError("DefaultReader format error"); + } + }; + + template <> + class DefaultReader { + public: + typedef std::string Value; + + void read(std::istream& is, Value& value) const { + char c; + if (!(is >> std::ws >> c)) return; + is.putback(c); + switch (c) { + case '\"': + QuotedStringReader().read(is, value); + break; + case '(': + ParsedStringReader().read(is, value); + break; + default: + is >> value; + break; + } + } + + }; + + template + class DefaultReader > + : public PushBackReader > {}; + + template + class DefaultReader > + : public PushBackReader > {}; + + template + class DefaultReader > + : public PushBackReader > {}; + + template + class DefaultReader > + : public InsertReader > {}; + + template + class DefaultReader > + : public InsertReader > {}; + + /// \ingroup item_io + /// + /// \brief The default item reader for skipping a value in the stream. + /// + /// The default item reader for skipping a value in the stream. + /// + /// \author Balazs Dezso + class DefaultSkipper : public DefaultReader {}; + + /// \ingroup item_io + /// \brief Standard ReaderTraits for the GraphReader class. + /// + /// Standard ReaderTraits for the GraphReader class. + /// It defines standard reading method for all type of value. + /// \author Balazs Dezso + struct DefaultReaderTraits { + + template + struct Reader : DefaultReader<_Value> {}; + + typedef DefaultSkipper Skipper; + + }; + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/item_writer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/item_writer.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,219 @@ +/* -*- C++ -*- + * lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +/// \ingroup item_io +/// \file +/// \brief Item writer bits for lemon output. + +#ifndef LEMON_BITS_ITEM_WRITER_H +#define LEMON_BITS_ITEM_WRITER_H + +#include +#include + +#include +#include +#include +#include + +namespace lemon { + + template + class DefaultWriter; + + /// \ingroup item_io + /// \brief Writer class for quoted strings. + /// + /// Writer class for quoted strings. It can process the escape + /// sequences in the string. + /// \author Balazs Dezso + class QuotedStringWriter { + public: + typedef std::string Value; + + /// \brief Constructor for the writer. + /// + /// Constructor for the writer. If the given parameter is true + /// the writer creates escape sequences from special characters. + QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {} + + /// \brief Writes a quoted string to the given stream. + /// + /// Writes a quoted string to the given stream. + void write(std::ostream& os, const std::string& value) { + os << "\""; + if (escaped) { + std::ostringstream ls; + for (int i = 0; i < (int)value.size(); ++i) { + writeEscape(ls, value[i]); + } + os << ls.str(); + } else { + os << value; + } + os << "\""; + } + + private: + + static void writeEscape(std::ostream& os, char c) { + switch (c) { + case '\\': + os << "\\\\"; + return; + case '\"': + os << "\\\""; + return; + case '\'': + os << "\\\'"; + return; + case '\?': + os << "\\\?"; + return; + case '\a': + os << "\\a"; + return; + case '\b': + os << "\\b"; + return; + case '\f': + os << "\\f"; + return; + case '\r': + os << "\\r"; + return; + case '\n': + os << "\\n"; + return; + case '\t': + os << "\\t"; + return; + case '\v': + os << "\\v"; + return; + default: + if (c < 0x20) { + os << '\\' << std::oct << (int)c; + } else { + os << c; + } + return; + } + } + private: + bool escaped; + }; + + /// \ingroup item_io + /// + /// \brief Writer for standard containers. + /// + /// Writer for each iterable standard containers. The representation + /// of the container is the values enumerated between an open and a + /// close parse. + /// + /// \author Balazs Dezso + template < + typename _Container, + typename _ItemWriter = DefaultWriter + > + class IterableWriter { + public: + typedef _Container Value; + typedef _ItemWriter ItemWriter; + + private: + + ItemWriter item_writer; + + public: + + /// \brief Writes the values of the container to the given stream. + /// + /// Writes the values of the container to the given stream. + void write(std::ostream& os, const Value& value) const { + typename Value::const_iterator it; + os << '('; + for (it = value.begin(); it != value.end(); ++it) { + item_writer.write(os, *it); + os << ' '; + } + os << ')'; + } + + }; + + /// \ingroup item_io + /// + /// \brief The default item writer template class. + /// + /// The default item writer template class. If some section writer + /// needs to write a value to the stream it will give the default way for it. + /// + /// \author Balazs Dezso + template + class DefaultWriter { + public: + /// The value type. + typedef _Value Value; + /// \brief Writes the value to the given stream. + /// + /// Writes the value to the given stream. + void write(std::ostream& os, const Value& value) const { + os << value; + } + }; + + template <> + class DefaultWriter + : public QuotedStringWriter {}; + + template + class DefaultWriter > + : public IterableWriter > {}; + + template + class DefaultWriter > + : public IterableWriter > {}; + + template + class DefaultWriter > + : public IterableWriter > {}; + + template + class DefaultWriter > + : public IterableWriter > {}; + + template + class DefaultWriter > + : public IterableWriter > {}; + + /// \ingroup item_io + /// \brief Standard WriterTraits for the section writers. + /// + /// Standard WriterTraits for the section writers. + /// It defines standard writing method for all type of value. + /// \author Balazs Dezso + struct DefaultWriterTraits { + + template + struct Writer : DefaultWriter<_Value> {}; + + }; + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/iterable_graph_extender.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/iterable_graph_extender.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,250 @@ +// -*- c++ -*- +#ifndef LEMON_ITERABLE_GRAPH_EXTENDER_H +#define LEMON_ITERABLE_GRAPH_EXTENDER_H + +#include + +namespace lemon { + + template + class IterableGraphExtender : public _Base { + public: + + typedef _Base Parent; + typedef IterableGraphExtender<_Base> Graph; + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + + class NodeIt : public Node { + const Graph* graph; + public: + + NodeIt() {} + + NodeIt(Invalid i) : Node(i) { } + + explicit NodeIt(const Graph& _graph) : graph(&_graph) { + _graph.first(*static_cast(this)); + } + + NodeIt(const Graph& _graph, const Node& node) + : Node(node), graph(&_graph) {} + + NodeIt& operator++() { + graph->next(*this); + return *this; + } + + }; + + + class EdgeIt : public Edge { + const Graph* graph; + public: + + EdgeIt() { } + + EdgeIt(Invalid i) : Edge(i) { } + + explicit EdgeIt(const Graph& _graph) : graph(&_graph) { + _graph.first(*static_cast(this)); + } + + EdgeIt(const Graph& _graph, const Edge& e) : + Edge(e), graph(&_graph) { } + + EdgeIt& operator++() { + graph->next(*this); + return *this; + } + + }; + + + class OutEdgeIt : public Edge { + const Graph* graph; + public: + + OutEdgeIt() { } + + OutEdgeIt(Invalid i) : Edge(i) { } + + OutEdgeIt(const Graph& _graph, const Node& node) + : graph(&_graph) { + _graph.firstOut(*this, node); + } + + OutEdgeIt(const Graph& _graph, const Edge& edge) + : Edge(edge), graph(&_graph) {} + + OutEdgeIt& operator++() { + graph->nextOut(*this); + return *this; + } + + }; + + + class InEdgeIt : public Edge { + const Graph* graph; + public: + + InEdgeIt() { } + + InEdgeIt(Invalid i) : Edge(i) { } + + InEdgeIt(const Graph& _graph, const Node& node) + : graph(&_graph) { + _graph.firstIn(*this, node); + } + + InEdgeIt(const Graph& _graph, const Edge& edge) : + Edge(edge), graph(&_graph) {} + + InEdgeIt& operator++() { + graph->nextIn(*this); + return *this; + } + + }; + + /// Base node of the iterator + /// + /// Returns the base node (ie. the source in this case) of the iterator + /// + /// \todo Document in the concept! + Node baseNode(const OutEdgeIt &e) const { + return source(e); + } + /// Running node of the iterator + /// + /// Returns the running node (ie. the target in this case) of the + /// iterator + /// + /// \todo Document in the concept! + Node runningNode(const OutEdgeIt &e) const { + return target(e); + } + + /// Base node of the iterator + /// + /// Returns the base node (ie. the target in this case) of the iterator + /// + /// \todo Document in the concept! + Node baseNode(const InEdgeIt &e) const { + return target(e); + } + /// Running node of the iterator + /// + /// Returns the running node (ie. the source in this case) of the + /// iterator + /// + /// \todo Document in the concept! + Node runningNode(const InEdgeIt &e) const { + return source(e); + } + + using Parent::first; + + private: + + // /// \todo When (and if) we change the iterators concept to use operator*, + // /// then the following shadowed methods will become superfluous. + // /// But for now these are important safety measures. + + // void first(NodeIt &) const; + // void first(EdgeIt &) const; + // void first(OutEdgeIt &) const; + // void first(InEdgeIt &) const; + + }; + + + + + + + template + class IterableUndirGraphExtender : public IterableGraphExtender<_Base> { + public: + + typedef IterableGraphExtender<_Base> Parent; + typedef IterableUndirGraphExtender<_Base> Graph; + typedef typename Parent::Node Node; + + typedef typename Parent::UndirEdge UndirEdge; + + class UndirEdgeIt : public Parent::UndirEdge { + const Graph* graph; + public: + + UndirEdgeIt() { } + + UndirEdgeIt(Invalid i) : UndirEdge(i) { } + + explicit UndirEdgeIt(const Graph& _graph) : graph(&_graph) { + _graph.first(*static_cast(this)); + } + + UndirEdgeIt(const Graph& _graph, const UndirEdge& e) : + UndirEdge(e), graph(&_graph) { } + + UndirEdgeIt& operator++() { + graph->next(*this); + return *this; + } + + }; + + class IncEdgeIt : public Parent::UndirEdge { + const Graph* graph; + bool forward; + friend class IterableUndirGraphExtender; + template + friend class UndirGraphExtender; + public: + + IncEdgeIt() { } + + IncEdgeIt(Invalid i) : UndirEdge(i), forward(false) { } + + IncEdgeIt(const Graph& _graph, const Node &n) + : graph(&_graph) + { + _graph._dirFirstOut(*this, n); + } + + IncEdgeIt(const Graph& _graph, const UndirEdge &ue, const Node &n) + : graph(&_graph), UndirEdge(ue) + { + forward = (_graph.source(ue) == n); + } + + IncEdgeIt& operator++() { + graph->_dirNextOut(*this); + return *this; + } + }; + + using Parent::baseNode; + using Parent::runningNode; + + /// Base node of the iterator + /// + /// Returns the base node of the iterator + Node baseNode(const IncEdgeIt &e) const { + return _dirSource(e); + } + /// Running node of the iterator + /// + /// Returns the running node of the iterator + Node runningNode(const IncEdgeIt &e) const { + return _dirTarget(e); + } + + }; +} + +#endif // LEMON_GRAPH_EXTENDER_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/map_iterator.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/map_iterator.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,855 @@ +/* -*- C++ -*- + * lemon/map_iterator.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_MAP_ITERATOR_H +#define LEMON_MAP_ITERATOR_H + +#include + +#include +#include + +///\ingroup graphmaps +///\file +///\brief Iterators on the maps. + +namespace lemon { + + /// \addtogroup graphmaps + /// @{ + + /** The base class all of the map iterators. + * The class defines the typedefs of the iterators, + * simple step functions and equality operators. + */ + + template < + typename _Graph, + typename _Item> + class MapIteratorBase { + + protected: + + /// The key type of the iterator. + typedef typename ItemSetTraits<_Graph, _Item>::ItemIt ItemIt; + + ItemIt it; + + /// Default constructor. + MapIteratorBase() {} + + /// ItemIt initialized MapIteratorBase constructor. + MapIteratorBase(const ItemIt _it) : it(_it) {} + + public: + + /// Stepping forward in the map. + void increment() { + ++it; + } + + /// The equality operator of the map. + bool operator==(const MapIteratorBase& _it) const { + return _it.it == it; + } + + /// The not-equality operator of the map. + bool operator!=(const MapIteratorBase& _it) const { + return !(*this == _it); + } + }; + + + template < + typename _Graph, + typename _Item, + typename _Map> + class MapConstIterator; + + /** Compatible iterator with the stl maps' iterators. + * It iterates on pairs of a key and a value. + */ + template < + typename _Graph, + typename _Item, + typename _Map> + class MapIterator : public MapIteratorBase<_Graph, _Item> { + + friend class MapConstIterator<_Graph, _Item, _Map>; + + + public: + + /// The iterator base class. + typedef MapIteratorBase<_Graph, _Item> Parent; + + typedef _Item Item; + typedef _Map Map; + typedef _Graph Graph; + + protected: + + typedef typename Parent::ItemIt ItemIt; + + typedef typename ReferenceMapTraits<_Map>::Value MapValue; + typedef typename ReferenceMapTraits<_Map>::Reference MapReference; + + public: + + /// The value type of the iterator. + typedef extended_pair Value; + + /// The reference type of the iterator. + typedef extended_pair Reference; + + /// Default constructor. + MapIterator() {} + + /// Constructor to initalize the iterators returned + /// by the begin() and end(). + MapIterator(Map& _map, const ItemIt& _it) + : Parent(_it), map(&_map) {} + + /// Dereference operator for the iterator. + Reference operator*() { + return Reference(Parent::it, (*map)[Parent::it]); + } + + /// The pointer type of the iterator. + class Pointer { + friend class MapIterator; + protected: + Reference data; + Pointer(const Item& item, MapReference val) + : data(item, val) {} + public: + Reference* operator->() {return &data;} + }; + + /// Arrow operator for the iterator. + Pointer operator->() { + return Pointer(Parent::it, (*map)[Parent::it]); + } + + /// The pre increment operator of the iterator. + MapIterator& operator++() { + Parent::increment(); + return *this; + } + + /// The post increment operator of the iterator. + MapIterator operator++(int) { + MapIterator tmp(*this); + Parent::increment(); + return tmp; + } + + protected: + + Map* map; + + public: + // STL compatibility typedefs. + typedef std::forward_iterator_tag iterator_category; + typedef int difference_type; + typedef Value value_type; + typedef Reference reference; + typedef Pointer pointer; + }; + + /** Compatible iterator with the stl maps' iterators. + * It iterates on pairs of a key and a value. + */ + template < + typename _Graph, + typename _Item, + typename _Map> + class MapConstIterator : public MapIteratorBase<_Graph, _Item> { + + public: + + /// The iterator base class. + typedef MapIteratorBase<_Graph, _Item> Parent; + + typedef _Graph Graph; + typedef _Item Item; + typedef _Map Map; + + protected: + + typedef typename Parent::ItemIt ItemIt; + + typedef typename ReferenceMapTraits<_Map>::Value MapValue; + typedef typename ReferenceMapTraits<_Map>::ConstReference + MapReference; + + public: + + /// The value type of the iterator. + typedef extended_pair Value; + + /// The reference type of the iterator. + typedef extended_pair Reference; + + /// Default constructor. + MapConstIterator() {} + + /// Constructor to initalize the iterators returned + /// by the begin() and end(). + MapConstIterator(const Map& _map, const ItemIt& _it) + : Parent(_it), map(&_map) {} + + /// Dereference operator for the iterator. + Reference operator*() { + return Reference(Parent::it, (*map)[Parent::it]); + } + + /// The pointer type of the iterator. + class Pointer { + friend class MapConstIterator; + protected: + Reference data; + Pointer(const Item& item, MapReference val) + : data(item, val) {} + public: + Reference* operator->() {return &data;} + }; + + /// Arrow operator for the iterator. + Pointer operator->() { + return Pointer(Parent::it, ((*map)[Parent::it])); + } + + /// The pre increment operator of the iterator. + MapConstIterator& operator++() { + Parent::increment(); + return *this; + } + + /// The post increment operator of the iterator. + MapConstIterator operator++(int) { + MapConstIterator tmp(*this); + Parent::increment(); + return tmp; + } + + protected: + const Map* map; + + public: + // STL compatibility typedefs. + typedef std::forward_iterator_tag iterator_category; + typedef int difference_type; + typedef Value value_type; + typedef Reference reference; + typedef Pointer pointer; + }; + + /** The class makes the ItemIt to an stl compatible iterator + * with dereferencing operator. + */ + template < + typename _Graph, + typename _Item> + class MapConstKeyIterator : public MapIteratorBase<_Graph, _Item> { + + public: + + /// The iterator base class. + typedef MapIteratorBase<_Graph, _Item> Parent; + + typedef _Graph Graph; + typedef _Item Item; + + protected: + /// The iterator to iterate on the keys. + typedef typename Parent::ItemIt ItemIt; + + public: + + typedef Item Value; + typedef const Item& Reference; + typedef const Item* Pointer; + + /// Default constructor. + MapConstKeyIterator() {} + + /// ItemIt initialized iterator. + MapConstKeyIterator(const ItemIt& pit) : Parent(pit) {} + + /// The pre increment operator of the iterator. + MapConstKeyIterator& operator++() { + Parent::increment(); + return *this; + } + + /// The post increment operator of the iterator. + MapConstKeyIterator operator++(int) { + MapConstKeyIterator tmp(*this); + Parent::increment(); + return tmp; + } + + /// The dereferencing operator of the iterator. + Item operator*() const { + return static_cast(Parent::it); + } + + public: + // STL compatibility typedefs. + typedef std::input_iterator_tag iterator_category; + typedef int difference_type; + typedef Value value_type; + typedef Reference reference; + typedef Pointer pointer; + }; + + template < + typename _Graph, + typename _Item, + typename _Map> + class MapConstValueIterator; + + /** MapValueIterator creates an stl compatible iterator + * for the values. + */ + template < + typename _Graph, + typename _Item, + typename _Map> + class MapValueIterator : public MapIteratorBase<_Graph, _Item> { + + friend class MapConstValueIterator<_Graph, _Item, _Map>; + + public: + + /// The iterator base class. + typedef MapIteratorBase<_Graph, _Item> Parent; + + typedef _Graph Graph; + typedef _Item Item; + typedef _Map Map; + + protected: + + /// The iterator to iterate on the keys. + typedef typename Parent::ItemIt ItemIt; + + /// The value type of the iterator. + typedef typename ReferenceMapTraits::Value MapValue; + /// The reference type of the iterator. + typedef typename ReferenceMapTraits::Reference MapReference; + /// The pointer type of the iterator. + typedef typename ReferenceMapTraits::Pointer MapPointer; + + public: + + typedef MapValue Value; + typedef MapReference Reference; + typedef MapPointer Pointer; + + /// Default constructor. + MapValueIterator() {} + + /// Map and ItemIt initialized iterator. + MapValueIterator(Map& _map, const ItemIt& _it) + : Parent(_it), map(&_map) {} + + + /// The pre increment operator of the iterator. + MapValueIterator& operator++() { + Parent::increment(); + return *this; + } + + /// The post increment operator of the iterator. + MapValueIterator operator++(int) { + MapValueIterator tmp(*this); + Parent::increment(); + return tmp; + } + + /// The dereferencing operator of the iterator. + Reference operator*() const { + return (*map)[Parent::it]; + } + + /// The arrow operator of the iterator. + Pointer operator->() const { + return &(operator*()); + } + + protected: + + Map* map; + + public: + // STL compatibility typedefs. + typedef std::forward_iterator_tag iterator_category; + typedef int difference_type; + typedef Value value_type; + typedef Reference reference; + typedef Pointer pointer; + }; + + /** MapValueIterator creates an stl compatible iterator + * for the values. + */ + template < + typename _Graph, + typename _Item, + typename _Map> + class MapConstValueIterator : public MapIteratorBase<_Graph, _Item> { + + public: + + /// The iterator base class. + typedef MapIteratorBase<_Graph, _Item> Parent; + + typedef _Graph Graph; + typedef _Item Item; + typedef _Map Map; + + protected: + + /// The iterator to iterate on the keys. + typedef typename Parent::ItemIt ItemIt; + + /// The value type of the iterator. + typedef typename ReferenceMapTraits::Value MapValue; + /// The reference type of the iterator. + typedef typename ReferenceMapTraits::ConstReference MapReference; + /// The pointer type of the iterator. + typedef typename ReferenceMapTraits::ConstPointer MapPointer; + + public: + + typedef MapValue Value; + typedef MapReference Reference; + typedef MapPointer Pointer; + + /// Default constructor. + MapConstValueIterator() {} + + /// Map and ItemIt initialized iterator. + MapConstValueIterator(const Map& _map, const ItemIt& _it) + : Parent(_it), map(&_map) {} + + + /// The pre increment operator of the iterator. + MapConstValueIterator& operator++() { + Parent::increment(); + return *this; + } + + /// The post increment operator of the iterator. + MapConstValueIterator operator++(int) { + MapConstValueIterator tmp(*this); + Parent::increment(); + return tmp; + } + + /// The dereferencing operator of the iterator. + Reference operator*() const { + return (*map)[Parent::it]; + } + + /// The arrow operator of the iterator. + Pointer operator->() const { + return &(operator*()); + } + + protected: + + const Map* map; + + public: + // STL compatibility typedefs. + typedef std::forward_iterator_tag iterator_category; + typedef int difference_type; + typedef Value value_type; + typedef Reference reference; + typedef Pointer pointer; + }; + + + /** This class makes from a map an iteratable set + * which contains all the keys of the map. + */ + template + class MapConstKeySet { + + public: + + typedef _Graph Graph; + /// The key type of the iterator. + typedef _Item Item; + /// The iterator to iterate on the keys. + + protected: + + typedef typename ItemSetTraits<_Graph, _Item>::ItemIt ItemIt; + + public: + + /// The map initialized const key set. + MapConstKeySet(const Graph& _graph) : graph(&_graph) {} + + /// The const iterator of the set. + typedef MapConstKeyIterator<_Graph, _Item> ConstIterator; + + typedef typename ConstIterator::Value Value; + /// The reference type of the iterator. + typedef typename ConstIterator::Reference ConstReference; + /// The pointer type of the iterator. + typedef typename ConstIterator::Pointer ConstPointer; + + /// It gives back the const iterator pointed to the first element. + ConstIterator begin() const { + return ConstIterator(ItemIt(*graph)); + } + + /// It gives back the const iterator pointed to the first ivalid element. + ConstIterator end() const { + return ConstIterator(ItemIt(INVALID)); + } + + protected: + + const Graph* graph; + + public: + // STL compatibility typedefs. + typedef Value value_type; + typedef ConstIterator const_iterator; + typedef ConstReference const_reference; + typedef ConstPointer const_pointer; + typedef int difference_type; + }; + + /** This class makes from a map an iteratable set + * which contains all the values of the map. + * The values cannot be modified. + */ + template + class MapConstValueSet { + + public: + + typedef _Graph Graph; + typedef _Item Item; + typedef _Map Map; + + protected: + + /// The iterator to iterate on the keys. + typedef typename ItemSetTraits::ItemIt ItemIt; + + public: + + /// The map initialized const value set. + MapConstValueSet(const Graph& _graph, const Map& _map) + : graph(&_graph), map(&_map) {} + + /// The const iterator of the set. + typedef MapConstValueIterator<_Graph, _Item, _Map> ConstIterator; + + typedef typename ConstIterator::Value Value; + typedef typename ConstIterator::Reference ConstReference; + typedef typename ConstIterator::Pointer ConstPointer; + + /// It gives back the const iterator pointed to the first element. + ConstIterator begin() const { + return ConstIterator(*map, ItemIt(*graph)); + } + + /// It gives back the const iterator pointed to the first invalid element. + ConstIterator end() const { + return ConstIterator(*map, ItemIt(INVALID)); + } + + protected: + + const Map* map; + const Graph * graph; + + public: + // STL compatibility typedefs. + typedef Value value_type; + typedef ConstIterator const_iterator; + typedef ConstReference const_reference; + typedef ConstPointer const_pointer; + typedef int difference_type; + }; + + + /** This class makes from a map an iteratable set + * which contains all the values of the map. + * The values can be modified. + */ + template + class MapValueSet { + + public: + + typedef _Graph Graph; + typedef _Item Item; + typedef _Map Map; + + protected: + + /// The iterator to iterate on the keys. + typedef typename ItemSetTraits::ItemIt ItemIt; + + public: + + /// The map initialized const value set. + MapValueSet(const Graph& _graph, Map& _map) + : map(&_map), graph(&_graph) {} + + /// The const iterator of the set. + typedef MapValueIterator<_Graph, _Item, _Map> Iterator; + /// The const iterator of the set. + typedef MapConstValueIterator<_Graph, _Item, _Map> ConstIterator; + + typedef typename ConstIterator::Value Value; + typedef typename Iterator::Reference Reference; + typedef typename Iterator::Pointer Pointer; + typedef typename ConstIterator::Reference ConstReference; + typedef typename ConstIterator::Pointer ConstPointer; + + /// It gives back the const iterator pointed to the first element. + ConstIterator begin() const { + return ConstIterator(*map, ItemIt(*graph)); + } + + /// It gives back the const iterator pointed to the first invalid element. + ConstIterator end() const { + return ConstIterator(*map, ItemIt(INVALID)); + } + + /// It gives back the iterator pointed to the first element. + Iterator begin() { + return Iterator(*map, ItemIt(*graph)); + } + + /// It gives back the iterator pointed to the first invalid element. + Iterator end() { + return Iterator(*map, ItemIt(INVALID)); + } + + protected: + + Map* map; + const Graph * graph; + + public: + // STL compatibility typedefs. + typedef Value value_type; + typedef Iterator iterator; + typedef ConstIterator const_iterator; + typedef Reference reference; + typedef ConstReference const_reference; + typedef Pointer pointer; + typedef ConstPointer const_pointer; + typedef int difference_type; + + }; + + /** This class makes from a map an iteratable set + * which contains all the values of the map. + * The values can be modified. + */ + template < + typename _Graph, + typename _Item, + typename _Map + > + class MapSet { + public: + + typedef _Graph Graph; + typedef _Item Item; + typedef _Map Map; + + protected: + + typedef typename ItemSetTraits<_Graph, _Item>::ItemIt ItemIt; + + public: + + /// The map initialized value set. + MapSet(const Graph& _graph, Map& _map) : graph(&_graph), map(&_map) {} + + /// The const iterator of the set. + typedef MapIterator<_Graph, _Item, _Map> Iterator; + typedef MapConstIterator<_Graph, _Item, _Map> ConstIterator; + + typedef typename ConstIterator::Value Value; + typedef typename Iterator::Reference Reference; + typedef typename Iterator::Pointer Pointer; + typedef typename ConstIterator::Reference ConstReference; + typedef typename ConstIterator::Pointer ConstPointer; + + + /// It gives back the const iterator pointed to the first element. + ConstIterator begin() const { + return ConstIterator(*map, ItemIt(*graph)); + } + + /// It gives back the const iterator pointed to the first invalid element. + ConstIterator end() const { + return ConstIterator(*map, ItemIt(INVALID)); + } + + /// The iterator of the set. + + /// It gives back the iterator pointed to the first element. + Iterator begin() { + return Iterator(*map, ItemIt(*graph)); + } + + /// It gives back the iterator pointed to the first invalid element. + Iterator end() { + return Iterator(*map, ItemIt(INVALID)); + } + + protected: + + const Graph* graph; + Map* map; + + public: + // STL compatibility typedefs. + typedef Value value_type; + typedef Iterator iterator; + typedef ConstIterator const_iterator; + typedef Reference reference; + typedef ConstReference const_reference; + typedef Pointer pointer; + typedef ConstPointer const_pointer; + typedef int difference_type; + + }; + + template < + typename _Graph, + typename _Item, + typename _Map + > + class ConstMapSet { + + typedef _Graph Graph; + typedef _Map Map; + + const Graph* graph; + const Map* map; + + public: + + typedef typename ItemSetTraits<_Graph, _Item>::ItemIt ItemIt; + + + /// The map initialized value set. + ConstMapSet(const Graph& _graph, const Map& _map) + : graph(&_graph), map(&_map) {} + + /// The const iterator of the set. + typedef MapConstIterator<_Graph, _Item, _Map> ConstIterator; + + typedef typename ConstIterator::Value Value; + typedef typename ConstIterator::Reference ConstReference; + typedef typename ConstIterator::Pointer ConstPointer; + + + /// It gives back the const iterator pointed to the first element. + ConstIterator begin() const { + return ConstIterator(*map, ItemIt(*graph)); + } + + /// It gives back the const iterator pointed to the first invalid element. + ConstIterator end() const { + return ConstIterator(*map, ItemIt(INVALID)); + } + + public: + // STL compatibility typedefs. + typedef Value value_type; + typedef ConstIterator const_iterator; + typedef ConstReference const_reference; + typedef ConstPointer const_pointer; + typedef int difference_type; + + }; + + template + class IterableMapExtender : public _Map { + public: + + typedef _Map Parent; + typedef Parent Map; + typedef typename Map::Graph Graph; + typedef typename Map::Key Item; + typedef typename Map::Value Value; + + typedef MapSet MapSet; + + IterableMapExtender() : Parent() {} + + IterableMapExtender(const Graph& graph) : Parent(graph) {} + + IterableMapExtender(const Graph& graph, const Value& value) + : Parent(graph, value) {} + + MapSet mapSet() { + return MapSet(*Parent::getGraph(), *this); + } + + typedef ConstMapSet ConstMapSet; + + ConstMapSet mapSet() const { + return ConstMapSet(*Parent::getGraph(), *this); + } + + typedef MapConstKeySet ConstKeySet; + + ConstKeySet keySet() const { + return ConstKeySet(*Parent::getGraph()); + } + + typedef MapValueSet ValueSet; + + ValueSet valueSet() { + return ValueSet(*Parent::getGraph(), *this); + } + + typedef MapConstValueSet ConstValueSet; + + ConstValueSet valueSet() const { + return ConstValueSet(*Parent::getGraph(), *this); + } + + }; + + /// @} + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/undir_graph_extender.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/undir_graph_extender.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,278 @@ +/* -*- C++ -*- + * + * lemon/undir_graph_extender.h - Part of LEMON, a generic C++ + * optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi + * Kutatocsoport (Egervary Research Group on Combinatorial Optimization, + * EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_UNDIR_GRAPH_EXTENDER_H +#define LEMON_UNDIR_GRAPH_EXTENDER_H + +#include + +namespace lemon { + + template + class UndirGraphExtender : public _Base { + typedef _Base Parent; + typedef UndirGraphExtender Graph; + + public: + + typedef typename Parent::Edge UndirEdge; + typedef typename Parent::Node Node; + + class Edge : public UndirEdge { + friend class UndirGraphExtender; + + protected: + // FIXME: Marci use opposite logic in his graph adaptors. It would + // be reasonable to syncronize... + bool forward; + + public: + Edge() {} + + /// \brief Directed edge from undirected edge and a direction. + /// + /// This constructor is not a part of the concept interface of + /// undirected graph, so please avoid using it if possible! + Edge(const UndirEdge &ue, bool _forward) : + UndirEdge(ue), forward(_forward) {} + + /// \brief Directed edge from undirected edge and a source node. + /// + /// Constructs a directed edge from undirected edge and a source node. + /// + /// \note You have to specify the graph for this constructor. + Edge(const Graph &g, const UndirEdge &ue, const Node &n) : + UndirEdge(ue) { forward = (g.source(ue) == n); } + + /// Invalid edge constructor + Edge(Invalid i) : UndirEdge(i), forward(true) {} + + bool operator==(const Edge &that) const { + return forward==that.forward && UndirEdge(*this)==UndirEdge(that); + } + bool operator!=(const Edge &that) const { + return forward!=that.forward || UndirEdge(*this)!=UndirEdge(that); + } + bool operator<(const Edge &that) const { + return forward + Node _dirSource(const E &e) const { + return e.forward ? Parent::source(e) : Parent::target(e); + } + + template + Node _dirTarget(const E &e) const { + return e.forward ? Parent::target(e) : Parent::source(e); + } + + public: + /// \todo Shouldn't the "source" of an undirected edge be called "aNode" + /// or something??? + using Parent::source; + + /// Source of the given Edge. + Node source(const Edge &e) const { + return _dirSource(e); + } + + /// \todo Shouldn't the "target" of an undirected edge be called "bNode" + /// or something??? + using Parent::target; + + /// Target of the given Edge. + Node target(const Edge &e) const { + return _dirTarget(e); + } + + /// Returns whether the given directed edge is same orientation as the + /// corresponding undirected edge. + /// + /// \todo reference to the corresponding point of the undirected graph + /// concept. "What does the direction of an undirected edge mean?" + bool forward(const Edge &e) const { return e.forward; } + + Node oppositeNode(const Node &n, const UndirEdge &e) const { + if( n == Parent::source(e)) + return Parent::target(e); + else if( n == Parent::target(e)) + return Parent::source(e); + else + return INVALID; + } + + /// Directed edge from an undirected edge and a source node. + /// + /// Returns a (directed) Edge corresponding to the specified UndirEdge + /// and source Node. + /// + ///\todo Do we need this? + /// + ///\todo Better name... + Edge edgeWithSource(const UndirEdge &ue, const Node &s) const { + return Edge(*this, ue, s); + } + + using Parent::first; + void first(Edge &e) const { + Parent::first(e); + e.forward=true; + } + + using Parent::next; + void next(Edge &e) const { + if( e.forward ) { + e.forward = false; + } + else { + Parent::next(e); + e.forward = true; + } + } + + + protected: + + template + void _dirFirstOut(E &e, const Node &n) const { + Parent::firstIn(e,n); + if( UndirEdge(e) != INVALID ) { + e.forward = false; + } + else { + Parent::firstOut(e,n); + e.forward = true; + } + } + template + void _dirFirstIn(E &e, const Node &n) const { + Parent::firstOut(e,n); + if( UndirEdge(e) != INVALID ) { + e.forward = false; + } + else { + Parent::firstIn(e,n); + e.forward = true; + } + } + + template + void _dirNextOut(E &e) const { + if( ! e.forward ) { + Node n = Parent::target(e); + Parent::nextIn(e); + if( UndirEdge(e) == INVALID ) { + Parent::firstOut(e, n); + e.forward = true; + } + } + else { + Parent::nextOut(e); + } + } + template + void _dirNextIn(E &e) const { + if( ! e.forward ) { + Node n = Parent::source(e); + Parent::nextOut(e); + if( UndirEdge(e) == INVALID ) { + Parent::firstIn(e, n); + e.forward = true; + } + } + else { + Parent::nextIn(e); + } + } + + public: + + void firstOut(Edge &e, const Node &n) const { + _dirFirstOut(e, n); + } + void firstIn(Edge &e, const Node &n) const { + _dirFirstIn(e, n); + } + + void nextOut(Edge &e) const { + _dirNextOut(e); + } + void nextIn(Edge &e) const { + _dirNextIn(e); + } + + // Miscellaneous stuff: + + /// \todo these methods (id, maxEdgeId) should be moved into separate + /// Extender + + // using Parent::id; + // Using "using" is not a good idea, cause it could be that there is + // no "id" in Parent... + + int id(const Node &n) const { + return Parent::id(n); + } + + int id(const UndirEdge &e) const { + return Parent::id(e); + } + + int id(const Edge &e) const { + return 2 * Parent::id(e) + int(e.forward); + } + + + int maxId(Node) const { + return Parent::maxId(Node()); + } + + int maxId(Edge) const { + return 2 * Parent::maxId(typename Parent::Edge()) + 1; + } + int maxId(UndirEdge) const { + return Parent::maxId(typename Parent::Edge()); + } + + + int edgeNum() const { + return 2 * Parent::edgeNum(); + } + int undirEdgeNum() const { + return Parent::edgeNum(); + } + + }; + +} + +#endif // LEMON_UNDIR_GRAPH_EXTENDER_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/vector_map.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/vector_map.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,288 @@ +/* -*- C++ -*- + * lemon/vector_map.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_VECTOR_MAP_H +#define LEMON_VECTOR_MAP_H + +#include +#include + +#include +#include +#include + +///\ingroup graphmaps +///\file +///\brief Vector based graph maps. + +namespace lemon { + + /// \addtogroup graphmaps + /// @{ + + /// The VectorMap template class is graph map structure what + /// automatically updates the map when a key is added to or erased from + /// the map. This map factory uses the allocators to implement + /// the container functionality. This map factory + /// uses the std::vector to implement the container function. + /// + /// \param Registry The AlterationNotifier that will notify this map. + /// \param IdMap The IdMap type of the graph items. + /// \param Value The value type of the map. + /// + /// \author Balazs Dezso + + + template < + typename _Graph, + typename _Item, + typename _Value + > + class VectorMap : public AlterationNotifier<_Item>::ObserverBase { + public: + + /// The graph type of the map. + typedef _Graph Graph; + /// The key type of the map. + typedef _Item Key; + /// The id map type of the map. + typedef AlterationNotifier<_Item> Registry; + /// The value type of the map. + typedef _Value Value; + + /// The map type. + typedef VectorMap Map; + /// The base class of the map. + typedef typename Registry::ObserverBase Parent; + + private: + + /// The container type of the map. + typedef std::vector Container; + + public: + + /// The reference type of the map; + typedef typename Container::reference Reference; + /// The pointer type of the map; + typedef typename Container::pointer Pointer; + + /// The const value type of the map. + typedef const Value ConstValue; + /// The const reference type of the map; + typedef typename Container::const_reference ConstReference; + /// The pointer type of the map; + typedef typename Container::const_pointer ConstPointer; + + typedef True FullTypeTag; + + /// Constructor to attach the new map into the registry. + + /// It construates a map and attachs it into the registry. + /// It adds all the items of the graph to the map. + + VectorMap(const Graph& _g) : graph(&_g) { + attach(_g.getNotifier(_Item())); + build(); + } + + /// Constructor uses given value to initialize the map. + + /// It construates a map uses a given value to initialize the map. + /// It adds all the items of the graph to the map. + + VectorMap(const Graph& _g, const Value& _v) : graph(&_g) { + attach(_g.getNotifier(_Item())); + container.resize(graph->maxId(_Item()) + 1, _v); + } + + VectorMap(const VectorMap& _copy) + : Parent(), graph(_copy.getGraph()) { + if (_copy.attached()) { + attach(*_copy.getRegistry()); + container = _copy.container; + } + } + + using Parent::attach; + using Parent::detach; + using Parent::attached; + + /** Assign operator to copy a map of the same map type. + */ + VectorMap& operator=(const VectorMap& copy) { + if (© == this) return *this; + + if (graph != copy.graph) { + if (attached()) { + detach(); + } + if (copy.attached()) { + attach(*copy.getRegistry()); + } + } + container = copy.container; + + return *this; + } + + + virtual ~VectorMap() { + if (attached()) { + detach(); + } + } + + const Graph* getGraph() const { + return graph; + } + + /// The subcript operator. + + /// The subscript operator. The map can be subscripted by the + /// actual items of the graph. + + Reference operator[](const Key& key) { + return container[graph->id(key)]; + } + + /// The const subcript operator. + + /// The const subscript operator. The map can be subscripted by the + /// actual items of the graph. + + ConstReference operator[](const Key& key) const { + return container[graph->id(key)]; + } + + + /// The setter function of the map. + + /// It the same as operator[](key) = value expression. + /// + + void set(const Key& key, const Value& value) { + (*this)[key] = value; + } + + /// Adds a new key to the map. + + /// It adds a new key to the map. It called by the observer registry + /// and it overrides the add() member function of the observer base. + + void add(const Key& key) { + int id = graph->id(key); + if (id >= (int)container.size()) { + container.resize(id + 1); + } + } + + /// Erases a key from the map. + + /// Erase a key from the map. It called by the observer registry + /// and it overrides the erase() member function of the observer base. + void erase(const Key&) {} + + /// Buildes the map. + + /// It buildes the map. It called by the observer registry + /// and it overrides the build() member function of the observer base. + + void build() { + container.resize(graph->maxId(_Item()) + 1); + } + + /// Clear the map. + + /// It erase all items from the map. It called by the observer registry + /// and it overrides the clear() member function of the observer base. + void clear() { + container.clear(); + } + + private: + + Container container; + const Graph *graph; + + }; + + + template + class VectorMappableGraphExtender : public _Base { + public: + + typedef VectorMappableGraphExtender<_Base> Graph; + typedef _Base Parent; + + typedef typename Parent::Node Node; + typedef typename Parent::NodeIt NodeIt; + typedef typename Parent::NodeIdMap NodeIdMap; + typedef typename Parent::NodeNotifier NodeObserverRegistry; + + typedef typename Parent::Edge Edge; + typedef typename Parent::EdgeIt EdgeIt; + typedef typename Parent::EdgeIdMap EdgeIdMap; + typedef typename Parent::EdgeNotifier EdgeObserverRegistry; + + + template + class NodeMap : + public IterableMapExtender > { + public: + typedef VectorMappableGraphExtender<_Base> Graph; + + typedef typename Graph::Node Node; + + typedef IterableMapExtender > Parent; + + //typedef typename Parent::Graph Graph; + typedef typename Parent::Value Value; + + NodeMap(const Graph& g) + : Parent(g) {} + NodeMap(const Graph& g, const Value& v) + : Parent(g, v) {} + + }; + + template + class EdgeMap + : public IterableMapExtender > { + public: + typedef VectorMappableGraphExtender<_Base> Graph; + + typedef typename Graph::Edge Edge; + + typedef IterableMapExtender > Parent; + + //typedef typename Parent::Graph Graph; + typedef typename Parent::Value Value; + + EdgeMap(const Graph& g) + : Parent(g) {} + EdgeMap(const Graph& g, const Value& v) + : Parent(g, v) {} + + }; + + }; + + /// @} + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/concept/graph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/concept/graph.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,578 @@ +/* -*- C++ -*- + * lemon/concept/graph.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_CONCEPT_GRAPH_H +#define LEMON_CONCEPT_GRAPH_H + +///\ingroup graph_concepts +///\file +///\brief Declaration of Graph. + +#include +#include +#include +#include + +namespace lemon { + namespace concept { + + + /// \addtogroup graph_concepts + /// @{ + + /**************** The full-featured graph concepts ****************/ + + + /// \brief Modular static graph class. + /// + /// It should be the same as the \c StaticGraph class. + class _StaticGraph + : virtual public BaseGraphComponent, + public IterableGraphComponent, public MappableGraphComponent { + public: + typedef BaseGraphComponent::Node Node; + typedef BaseGraphComponent::Edge Edge; + + template + struct Constraints { + void constraints() { + checkConcept(); + checkConcept(); + } + }; + }; + + /// \brief Modular extendable graph class. + /// + /// It should be the same as the \c ExtendableGraph class. + class _ExtendableGraph + : virtual public BaseGraphComponent, public _StaticGraph, + public ExtendableGraphComponent, public ClearableGraphComponent { + public: + typedef BaseGraphComponent::Node Node; + typedef BaseGraphComponent::Edge Edge; + + template + struct Constraints { + void constraints() { + checkConcept<_StaticGraph, _Graph >(); + checkConcept(); + checkConcept(); + } + }; + }; + + /// \brief Modular erasable graph class. + /// + /// It should be the same as the \c ErasableGraph class. + class _ErasableGraph + : virtual public BaseGraphComponent, public _ExtendableGraph, + public ErasableGraphComponent { + public: + typedef BaseGraphComponent::Node Node; + typedef BaseGraphComponent::Edge Edge; + + template + struct Constraints { + void constraints() { + checkConcept<_ExtendableGraph, _Graph >(); + checkConcept(); + } + }; + }; + + /// An empty static graph class. + + /// This class provides all the common features of a graph structure, + /// however completely without implementations and real data structures + /// behind the interface. + /// All graph algorithms should compile with this class, but it will not + /// run properly, of course. + /// + /// It can be used for checking the interface compatibility, + /// or it can serve as a skeleton of a new graph structure. + /// + /// Also, you will find here the full documentation of a certain graph + /// feature, the documentation of a real graph imlementation + /// like @ref ListGraph or + /// @ref SmartGraph will just refer to this structure. + /// + /// \todo A pages describing the concept of concept description would + /// be nice. + class StaticGraph + { + public: + /// Defalult constructor. + + /// Defalult constructor. + /// + StaticGraph() { } + ///Copy consructor. + +// ///\todo It is not clear, what we expect from a copy constructor. +// ///E.g. How to assign the nodes/edges to each other? What about maps? +// StaticGraph(const StaticGraph& g) { } + + /// The base type of node iterators, + /// or in other words, the trivial node iterator. + + /// This is the base type of each node iterator, + /// thus each kind of node iterator converts to this. + /// More precisely each kind of node iterator should be inherited + /// from the trivial node iterator. + class Node { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + Node() { } + /// Copy constructor. + + /// Copy constructor. + /// + Node(const Node&) { } + + /// Invalid constructor \& conversion. + + /// This constructor initializes the iterator to be invalid. + /// \sa Invalid for more details. + Node(Invalid) { } + /// Equality operator + + /// Two iterators are equal if and only if they point to the + /// same object or both are invalid. + bool operator==(Node) const { return true; } + + /// Inequality operator + + /// \sa operator==(Node n) + /// + bool operator!=(Node) const { return true; } + + }; + + /// This iterator goes through each node. + + /// This iterator goes through each node. + /// Its usage is quite simple, for example you can count the number + /// of nodes in graph \c g of type \c Graph like this: + /// \code + /// int count=0; + /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count; + /// \endcode + class NodeIt : public Node { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + NodeIt() { } + /// Copy constructor. + + /// Copy constructor. + /// + NodeIt(const NodeIt& n) : Node(n) { } + /// Invalid constructor \& conversion. + + /// Initialize the iterator to be invalid. + /// \sa Invalid for more details. + NodeIt(Invalid) { } + /// Sets the iterator to the first node. + + /// Sets the iterator to the first node of \c g. + /// + NodeIt(const StaticGraph&) { } + /// Node -> NodeIt conversion. + + /// Sets the iterator to the node of \c g pointed by the trivial + /// iterator n. + /// This feature necessitates that each time we + /// iterate the edge-set, the iteration order is the same. + NodeIt(const StaticGraph& g, const Node& n) { } + /// Next node. + + /// Assign the iterator to the next node. + /// + NodeIt& operator++() { return *this; } + }; + + + /// The base type of the edge iterators. + + /// The base type of the edge iterators. + /// + class Edge { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + Edge() { } + /// Copy constructor. + + /// Copy constructor. + /// + Edge(const Edge&) { } + /// Initialize the iterator to be invalid. + + /// Initialize the iterator to be invalid. + /// + Edge(Invalid) { } + /// Equality operator + + /// Two iterators are equal if and only if they point to the + /// same object or both are invalid. + bool operator==(Edge) const { return true; } + /// Inequality operator + + /// \sa operator==(Node n) + /// + bool operator!=(Edge) const { return true; } + }; + + /// This iterator goes trough the outgoing edges of a node. + + /// This iterator goes trough the \e outgoing edges of a certain node + /// of a graph. + /// Its usage is quite simple, for example you can count the number + /// of outgoing edges of a node \c n + /// in graph \c g of type \c Graph as follows. + /// \code + /// int count=0; + /// for (Graph::OutEdgeIt e(g, n); e!=INVALID; ++e) ++count; + /// \endcode + + class OutEdgeIt : public Edge { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + OutEdgeIt() { } + /// Copy constructor. + + /// Copy constructor. + /// + OutEdgeIt(const OutEdgeIt& e) : Edge(e) { } + /// Initialize the iterator to be invalid. + + /// Initialize the iterator to be invalid. + /// + OutEdgeIt(Invalid) { } + /// This constructor sets the iterator to the first outgoing edge. + + /// This constructor sets the iterator to the first outgoing edge of + /// the node. + ///@param n the node + ///@param g the graph + OutEdgeIt(const StaticGraph&, const Node&) { } + /// Edge -> OutEdgeIt conversion + + /// Sets the iterator to the value of the trivial iterator \c e. + /// This feature necessitates that each time we + /// iterate the edge-set, the iteration order is the same. + OutEdgeIt(const StaticGraph& g, const Edge& e) { } + ///Next outgoing edge + + /// Assign the iterator to the next + /// outgoing edge of the corresponding node. + OutEdgeIt& operator++() { return *this; } + }; + + /// This iterator goes trough the incoming edges of a node. + + /// This iterator goes trough the \e incoming edges of a certain node + /// of a graph. + /// Its usage is quite simple, for example you can count the number + /// of outgoing edges of a node \c n + /// in graph \c g of type \c Graph as follows. + /// \code + /// int count=0; + /// for(Graph::InEdgeIt e(g, n); e!=INVALID; ++e) ++count; + /// \endcode + + class InEdgeIt : public Edge { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + InEdgeIt() { } + /// Copy constructor. + + /// Copy constructor. + /// + InEdgeIt(const InEdgeIt& e) : Edge(e) { } + /// Initialize the iterator to be invalid. + + /// Initialize the iterator to be invalid. + /// + InEdgeIt(Invalid) { } + /// This constructor sets the iterator to first incoming edge. + + /// This constructor set the iterator to the first incoming edge of + /// the node. + ///@param n the node + ///@param g the graph + InEdgeIt(const StaticGraph&, const Node&) { } + /// Edge -> InEdgeIt conversion + + /// Sets the iterator to the value of the trivial iterator \c e. + /// This feature necessitates that each time we + /// iterate the edge-set, the iteration order is the same. + InEdgeIt(const StaticGraph&, const Edge&) { } + /// Next incoming edge + + /// Assign the iterator to the next inedge of the corresponding node. + /// + InEdgeIt& operator++() { return *this; } + }; + /// This iterator goes through each edge. + + /// This iterator goes through each edge of a graph. + /// Its usage is quite simple, for example you can count the number + /// of edges in a graph \c g of type \c Graph as follows: + /// \code + /// int count=0; + /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count; + /// \endcode + class EdgeIt : public Edge { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + EdgeIt() { } + /// Copy constructor. + + /// Copy constructor. + /// + EdgeIt(const EdgeIt& e) : Edge(e) { } + /// Initialize the iterator to be invalid. + + /// Initialize the iterator to be invalid. + /// + EdgeIt(Invalid) { } + /// This constructor sets the iterator to the first edge. + + /// This constructor sets the iterator to the first edge of \c g. + ///@param g the graph + EdgeIt(const StaticGraph&) { } + /// Edge -> EdgeIt conversion + + /// Sets the iterator to the value of the trivial iterator \c e. + /// This feature necessitates that each time we + /// iterate the edge-set, the iteration order is the same. + EdgeIt(const StaticGraph&, const Edge&) { } + ///Next edge + + /// Assign the iterator to the next edge. + EdgeIt& operator++() { return *this; } + }; + ///Gives back the target node of an edge. + + ///Gives back the target node of an edge. + /// + Node target(Edge) const { return INVALID; } + ///Gives back the source node of an edge. + + ///Gives back the source node of an edge. + /// + Node source(Edge) const { return INVALID; } + /// Read write map of the nodes to type \c T. + + /// \ingroup concept + /// ReadWrite map of the nodes to type \c T. + /// \sa Reference + /// \warning Making maps that can handle bool type (NodeMap) + /// needs some extra attention! + template + class NodeMap : public ReadWriteMap< Node, T > + { + public: + + ///\e + NodeMap(const StaticGraph&) { } + ///\e + NodeMap(const StaticGraph&, T) { } + + ///Copy constructor + NodeMap(const NodeMap& nm) : ReadWriteMap< Node, T >(nm) { } + ///Assignment operator + NodeMap& operator=(const NodeMap&) { return *this; } + // \todo fix this concept + }; + + /// Read write map of the edges to type \c T. + + /// \ingroup concept + ///Reference map of the edges to type \c T. + /// \sa Reference + /// \warning Making maps that can handle bool type (EdgeMap) + /// needs some extra attention! + template + class EdgeMap : public ReadWriteMap + { + public: + + ///\e + EdgeMap(const StaticGraph&) { } + ///\e + EdgeMap(const StaticGraph&, T) { } + ///Copy constructor + EdgeMap(const EdgeMap& em) : ReadWriteMap(em) { } + ///Assignment operator + EdgeMap& operator=(const EdgeMap&) { return *this; } + // \todo fix this concept + }; + + template + struct Constraints : public _StaticGraph::Constraints<_Graph> {}; + + }; + + /// An empty non-static graph class. + + /// This class provides everything that \ref StaticGraph does. + /// Additionally it enables building graphs from scratch. + class ExtendableGraph : public StaticGraph + { + public: + /// Defalult constructor. + + /// Defalult constructor. + /// + ExtendableGraph() { } + ///Add a new node to the graph. + + /// \return the new node. + /// + Node addNode() { return INVALID; } + ///Add a new edge to the graph. + + ///Add a new edge to the graph with source node \c s + ///and target node \c t. + ///\return the new edge. + Edge addEdge(Node, Node) { return INVALID; } + + /// Resets the graph. + + /// This function deletes all edges and nodes of the graph. + /// It also frees the memory allocated to store them. + /// \todo It might belong to \ref ErasableGraph. + void clear() { } + + template + struct Constraints : public _ExtendableGraph::Constraints<_Graph> {}; + + }; + + /// An empty erasable graph class. + + /// This class is an extension of \ref ExtendableGraph. It makes it + /// possible to erase edges or nodes. + class ErasableGraph : public ExtendableGraph + { + public: + /// Defalult constructor. + + /// Defalult constructor. + /// + ErasableGraph() { } + /// Deletes a node. + + /// Deletes node \c n node. + /// + void erase(Node) { } + /// Deletes an edge. + + /// Deletes edge \c e edge. + /// + void erase(Edge) { } + + template + struct Constraints : public _ErasableGraph::Constraints<_Graph> {}; + + }; + + + /************* New GraphBase stuff **************/ + + +// /// A minimal GraphBase concept + +// /// This class describes a minimal concept which can be extended to a +// /// full-featured graph with \ref GraphFactory. +// class GraphBase { +// public: + +// GraphBase() {} + +// /// \bug Should we demand that Node and Edge be subclasses of the +// /// Graph class??? + +// typedef GraphItem<'n'> Node; +// typedef GraphItem<'e'> Edge; + +// // class Node : public BaseGraphItem<'n'> {}; +// // class Edge : public BaseGraphItem<'e'> {}; + +// // Graph operation +// void firstNode(Node &n) const { } +// void firstEdge(Edge &e) const { } + +// void firstOutEdge(Edge &e, Node) const { } +// void firstInEdge(Edge &e, Node) const { } + +// void nextNode(Node &n) const { } +// void nextEdge(Edge &e) const { } + + +// // Question: isn't it reasonable if this methods have a Node +// // parameter? Like this: +// // Edge& nextOut(Edge &e, Node) const { return e; } +// void nextOutEdge(Edge &e) const { } +// void nextInEdge(Edge &e) const { } + +// Node target(Edge) const { return Node(); } +// Node source(Edge) const { return Node(); } + + +// // Do we need id, nodeNum, edgeNum and co. in this basic graphbase +// // concept? + + +// // Maps. +// // +// // We need a special slimer concept which does not provide maps (it +// // wouldn't be strictly slimer, cause for map-factory id() & friends +// // a required...) + +// template +// class NodeMap : public GraphMap {}; + +// template +// class EdgeMap : public GraphMap {}; +// }; + + // @} + } //namespace concept +} //namespace lemon + + + +#endif // LEMON_CONCEPT_GRAPH_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/concept/graph_component.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/concept/graph_component.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,982 @@ +/* -*- C++ -*- + * lemon/concept/graph_component.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\ingroup graph_concepts +///\file +///\brief The graph components. + + +#ifndef LEMON_CONCEPT_GRAPH_COMPONENT_H +#define LEMON_CONCEPT_GRAPH_COMPONENT_H + +#include +#include + +#include + +namespace lemon { + namespace concept { + + /// \addtogroup graph_concepts + /// @{ + + /**************** Graph iterator concepts ****************/ + + /// Skeleton class for graph Node and Edge types + + /// This class describes the interface of Node and Edge (and UndirEdge + /// in undirected graphs) subtypes of graph types. + /// + /// \note This class is a template class so that we can use it to + /// create graph skeleton classes. The reason for this is than Node + /// and Edge types should \em not derive from the same base class. + /// For Node you should instantiate it with character 'n' and for Edge + /// with 'e'. + +#ifndef DOXYGEN + template +#endif + class GraphItem { + public: + /// Default constructor. + + /// \warning The default constructor is not required to set + /// the item to some well-defined value. So you should consider it + /// as uninitialized. + GraphItem() {} + /// Copy constructor. + + /// Copy constructor. + /// + GraphItem(GraphItem const&) {} + /// Invalid constructor \& conversion. + + /// This constructor initializes the item to be invalid. + /// \sa Invalid for more details. + GraphItem(Invalid) {} + /// Assign operator for nodes. + + /// The nodes are assignable. + /// + GraphItem& operator=(GraphItem const&) { return *this; } + /// Equality operator. + + /// Two iterators are equal if and only if they represents the + /// same node in the graph or both are invalid. + bool operator==(GraphItem) const { return false; } + /// Inequality operator. + + /// \sa operator==(const Node& n) + /// + bool operator!=(GraphItem) const { return false; } + + /// Artificial ordering operator. + + /// To allow the use of graph descriptors as key type in std::map or + /// similar associative container we require this. + /// + /// \note This operator only have to define some strict ordering of + /// the items; this order has nothing to do with the iteration + /// ordering of the items. + /// + /// \bug This is a technical requirement. Do we really need this? + bool operator<(GraphItem) const { return false; } + + template + struct Constraints { + void constraints() { + _GraphItem i1; + _GraphItem i2 = i1; + _GraphItem i3 = INVALID; + + i1 = i2 = i3; + + bool b; + // b = (ia == ib) && (ia != ib) && (ia < ib); + b = (ia == ib) && (ia != ib); + b = (ia == INVALID) && (ib != INVALID); + // b = (ia < ib); + } + + const _GraphItem &ia; + const _GraphItem &ib; + }; + }; + + /// A type describing the concept of graph node + + /// This is an instantiation of \ref GraphItem which can be used as a + /// Node subtype in graph skeleton definitions + typedef GraphItem<'n'> GraphNode; + + /// A type describing the concept of graph edge + + /// This is an instantiation of \ref GraphItem which can be used as a + /// Edge subtype in graph skeleton definitions + typedef GraphItem<'e'> GraphEdge; + + + /**************** Basic features of graphs ****************/ + + /// An empty base graph class. + + /// This class provides the minimal set of features needed for a graph + /// structure. All graph concepts have to be conform to this base + /// graph. + /// + /// \bug This is not true. The minimal graph concept is the + /// BaseIterableGraphComponent. + + class BaseGraphComponent { + public: + + typedef BaseGraphComponent Graph; + + /// Node class of the graph. + + /// This class represents the Nodes of the graph. + /// + typedef GraphItem<'n'> Node; + + /// Edge class of the graph. + + /// This class represents the Edges of the graph. + /// + typedef GraphItem<'e'> Edge; + + ///Gives back the target node of an edge. + + ///Gives back the target node of an edge. + /// + Node target(const Edge&) const { return INVALID;} + + ///Gives back the source node of an edge. + + ///Gives back the source node of an edge. + /// + Node source(const Edge&) const { return INVALID;} + + + template + struct Constraints { + typedef typename _Graph::Node Node; + typedef typename _Graph::Edge Edge; + + void constraints() { + checkConcept, Node>(); + checkConcept, Edge>(); + { + Node n; + Edge e; + n = graph.source(e); + n = graph.target(e); + } + } + + const _Graph& graph; + }; + }; + + /// An empty iterable base graph class. + + /// This class provides beside the core graph features + /// core iterable interface for the graph structure. + /// Most of the base graphs should be conform to this concept. + + class BaseIterableGraphComponent : virtual public BaseGraphComponent { + public: + + typedef BaseGraphComponent::Node Node; + typedef BaseGraphComponent::Edge Edge; + + /// Gives back the first Node in the iterating order. + + /// Gives back the first Node in the iterating order. + /// + void first(Node&) const {} + + /// Gives back the next Node in the iterating order. + + /// Gives back the next Node in the iterating order. + /// + void next(Node&) const {} + + /// Gives back the first Edge in the iterating order. + + /// Gives back the first Edge in the iterating order. + /// + void first(Edge&) const {} + /// Gives back the next Edge in the iterating order. + + /// Gives back the next Edge in the iterating order. + /// + void next(Edge&) const {} + + + /// Gives back the first of the Edges point to the given Node. + + /// Gives back the first of the Edges point to the given Node. + /// + void firstIn(Edge&, const Node&) const {} + + /// Gives back the next of the Edges points to the given Node. + + + /// Gives back the next of the Edges points to the given Node. + /// + void nextIn(Edge&) const {} + + /// Gives back the first of the Edges start from the given Node. + + /// Gives back the first of the Edges start from the given Node. + /// + void firstOut(Edge&, const Node&) const {} + + /// Gives back the next of the Edges start from the given Node. + + /// Gives back the next of the Edges start from the given Node. + /// + void nextOut(Edge&) const {} + + + template + struct Constraints { + + void constraints() { + checkConcept< BaseGraphComponent, _Graph >(); + typename _Graph::Node node; + typename _Graph::Edge edge; + { + graph.first(node); + graph.next(node); + } + { + graph.first(edge); + graph.next(edge); + } + { + graph.firstIn(edge, node); + graph.nextIn(edge); + } + { + graph.firstOut(edge, node); + graph.nextOut(edge); + } + } + + const _Graph& graph; + }; + }; + + /// An empty idable base graph class. + + /// This class provides beside the core graph features + /// core id functions for the graph structure. + /// The most of the base graphs should be conform to this concept. + /// The id's are unique and immutable. + class IDableGraphComponent : virtual public BaseGraphComponent { + public: + + typedef BaseGraphComponent::Node Node; + typedef BaseGraphComponent::Edge Edge; + + /// Gives back an unique integer id for the Node. + + /// Gives back an unique integer id for the Node. + /// + int id(const Node&) const { return -1;} + + /// \brief Gives back the node by the unique id. + /// + /// Gives back the node by the unique id. + /// If the graph does not contain node with the given id + /// then the result of the function is undetermined. + Node fromId(int , Node) const { return INVALID;} + + /// \brief Gives back an unique integer id for the Edge. + /// + /// Gives back an unique integer id for the Edge. + /// + int id(const Edge&) const { return -1;} + + /// \brief Gives back the edge by the unique id. + /// + /// Gives back the edge by the unique id. + /// If the graph does not contain edge with the given id + /// then the result of the function is undetermined. + Edge fromId(int, Edge) const { return INVALID;} + + template + struct Constraints { + + void constraints() { + checkConcept< BaseGraphComponent, _Graph >(); + typename _Graph::Node node; + int nid = graph.id(node); + nid = graph.id(node); + node = graph.fromId(nid, Node()); + typename _Graph::Edge edge; + int eid = graph.id(edge); + eid = graph.id(edge); + edge = graph.fromId(eid, Edge()); + } + + const _Graph& graph; + }; + }; + + + /// An empty max-idable base graph class. + + /// This class provides beside the core graph features + /// core max id functions for the graph structure. + /// The most of the base graphs should be conform to this concept. + /// The id's are unique and immutable. + class MaxIDableGraphComponent : virtual public BaseGraphComponent { + public: + + /// Gives back an integer greater or equal to the maximum Node id. + + /// Gives back an integer greater or equal to the maximum Node id. + /// + int maxId(Node = INVALID) const { return -1;} + + /// Gives back an integer greater or equal to the maximum Edge id. + + /// Gives back an integer greater or equal to the maximum Edge id. + /// + int maxId(Edge = INVALID) const { return -1;} + + template + struct Constraints { + + void constraints() { + checkConcept(); + int nid = graph.maxId(typename _Graph::Node()); + ignore_unused_variable_warning(nid); + int eid = graph.maxId(typename _Graph::Edge()); + ignore_unused_variable_warning(eid); + } + + const _Graph& graph; + }; + }; + + /// An empty extendable base graph class. + + /// This class provides beside the core graph features + /// core graph extend interface for the graph structure. + /// The most of the base graphs should be conform to this concept. + class BaseExtendableGraphComponent : virtual public BaseGraphComponent { + public: + + typedef BaseGraphComponent::Node Node; + typedef BaseGraphComponent::Edge Edge; + + /// Adds a new Node to the graph. + + /// Adds a new Node to the graph. + /// + Node addNode() { + return INVALID; + } + + /// Adds a new Edge connects the two Nodes to the graph. + + /// Adds a new Edge connects the two Nodes to the graph. + /// + Edge addEdge(const Node&, const Node&) { + return INVALID; + } + + template + struct Constraints { + void constraints() { + checkConcept(); + typename _Graph::Node node_a, node_b; + node_a = graph.addNode(); + typename _Graph::Edge edge; + edge = graph.addEdge(node_a, node_b); + } + + _Graph& graph; + }; + }; + + /// An empty erasable base graph class. + + /// This class provides beside the core graph features + /// core erase functions for the graph structure. + /// The most of the base graphs should be conform to this concept. + class BaseErasableGraphComponent : virtual public BaseGraphComponent { + public: + + typedef BaseGraphComponent::Node Node; + typedef BaseGraphComponent::Edge Edge; + + /// Erase a Node from the graph. + + /// Erase a Node from the graph. This function should not + /// erase edges connecting to the Node. + void erase(const Node&) {} + + /// Erase an Edge from the graph. + + /// Erase an Edge from the graph. + /// + void erase(const Edge&) {} + + template + struct Constraints { + void constraints() { + checkConcept(); + typename _Graph::Node node; + graph.erase(node); + typename _Graph::Edge edge; + graph.erase(edge); + } + + _Graph& graph; + }; + }; + + /// An empty clearable base graph class. + + /// This class provides beside the core graph features + /// core clear functions for the graph structure. + /// The most of the base graphs should be conform to this concept. + class ClearableGraphComponent : virtual public BaseGraphComponent { + public: + + /// Erase all the Nodes and Edges from the graph. + + /// Erase all the Nodes and Edges from the graph. + /// + void clear() {} + + template + struct Constraints { + void constraints() { + checkConcept(); + graph.clear(); + } + + _Graph graph; + }; + }; + + + /// Skeleton class for graph NodeIt and EdgeIt + + /// Skeleton class for graph NodeIt and EdgeIt. + /// + template + class GraphIterator : public _Item { + public: + /// \todo Don't we need the Item type as typedef? + + /// Default constructor. + + /// @warning The default constructor sets the iterator + /// to an undefined value. + GraphIterator() {} + /// Copy constructor. + + /// Copy constructor. + /// + GraphIterator(GraphIterator const&) {} + /// Sets the iterator to the first item. + + /// Sets the iterator to the first item of \c the graph. + /// + explicit GraphIterator(const _Graph&) {} + /// Invalid constructor \& conversion. + + /// This constructor initializes the item to be invalid. + /// \sa Invalid for more details. + GraphIterator(Invalid) {} + /// Assign operator for items. + + /// The items are assignable. + /// + GraphIterator& operator=(GraphIterator const&) { return *this; } + /// Next item. + + /// Assign the iterator to the next item. + /// + GraphIterator& operator++() { return *this; } + // Node operator*() const { return INVALID; } + /// Equality operator + + /// Two iterators are equal if and only if they point to the + /// same object or both are invalid. + bool operator==(const GraphIterator&) const { return true;} + /// Inequality operator + + /// \sa operator==(Node n) + /// + bool operator!=(const GraphIterator&) const { return true;} + + template + struct Constraints { + void constraints() { + // checkConcept< Item, _GraphIterator >(); + _GraphIterator it1(g); + + /// \todo Do we need NodeIt(Node) kind of constructor? + // _GraphIterator it2(bj); + _GraphIterator it2; + + it2 = ++it1; + ++it2 = it1; + ++(++it1); + /// \bug This should be: is_base_and_derived + _Item bi = it1; + bi = it2; + } + _Graph& g; + }; + }; + + /// Skeleton class for graph InEdgeIt and OutEdgeIt + + /// \note Because InEdgeIt and OutEdgeIt may not inherit from the same + /// base class, the _selector is a additional template parameter. For + /// InEdgeIt you should instantiate it with character 'i' and for + /// OutEdgeIt with 'o'. + /// \todo Is this a good name for this concept? + template + class GraphIncIterator : public Edge { + public: + /// Default constructor. + + /// @warning The default constructor sets the iterator + /// to an undefined value. + GraphIncIterator() {} + /// Copy constructor. + + /// Copy constructor. + /// + GraphIncIterator(GraphIncIterator const& gi) :Edge(gi) {} + /// Sets the iterator to the first edge incoming into or outgoing + /// from the node. + + /// Sets the iterator to the first edge incoming into or outgoing + /// from the node. + /// + explicit GraphIncIterator(const Graph&, const typename Graph::Node&) {} + /// Invalid constructor \& conversion. + + /// This constructor initializes the item to be invalid. + /// \sa Invalid for more details. + GraphIncIterator(Invalid) {} + /// Assign operator for nodes. + + /// The nodes are assignable. + /// + GraphIncIterator& operator=(GraphIncIterator const&) { return *this; } + /// Next edge. + + /// Assign the iterator to the next node. + /// + GraphIncIterator& operator++() { return *this; } + + // Node operator*() const { return INVALID; } + + /// Equality operator + + /// Two iterators are equal if and only if they point to the + /// same object or both are invalid. + bool operator==(const GraphIncIterator&) const { return true;} + + /// Inequality operator + + /// \sa operator==(Node n) + /// + bool operator!=(const GraphIncIterator&) const { return true;} + + template + struct Constraints { + typedef typename Graph::Node Node; + void constraints() { + checkConcept, _GraphIncIterator>(); + _GraphIncIterator it1(graph, node); + /// \todo Do we need OutEdgeIt(Edge) kind of constructor? + // _GraphIncIterator it2(edge); + _GraphIncIterator it2; + + it2 = ++it1; + ++it2 = it1; + ++(++it1); + Edge e = it1; + e = it2; + + const_constraits(); + } + + void const_constraits() { + Node n = graph.baseNode(it); + n = graph.runningNode(it); + } + + Edge edge; + Node node; + Graph graph; + _GraphIncIterator it; + }; + }; + + + /// An empty iterable base graph class. + + /// This class provides beside the core graph features + /// iterator based iterable interface for the graph structure. + /// This concept is part of the StaticGraphConcept. + class IterableGraphComponent : virtual public BaseGraphComponent { + + public: + + typedef IterableGraphComponent Graph; + + typedef BaseGraphComponent::Node Node; + typedef BaseGraphComponent::Edge Edge; + + /// This iterator goes through each node. + + /// This iterator goes through each node. + /// + typedef GraphIterator NodeIt; + /// This iterator goes through each node. + + /// This iterator goes through each node. + /// + typedef GraphIterator EdgeIt; + /// This iterator goes trough the incoming edges of a node. + + /// This iterator goes trough the \e inccoming edges of a certain node + /// of a graph. + typedef GraphIncIterator InEdgeIt; + /// This iterator goes trough the outgoing edges of a node. + + /// This iterator goes trough the \e outgoing edges of a certain node + /// of a graph. + typedef GraphIncIterator OutEdgeIt; + }; + + template + struct Constraints { + void constraints() { + checkConcept< BaseGraphComponent, _Graph>(); + + checkConcept, + typename _Graph::EdgeIt >(); + checkConcept, + typename _Graph::NodeIt >(); + checkConcept, typename _Graph::InEdgeIt >(); + checkConcept, typename _Graph::OutEdgeIt >(); + } + }; + + /// An empty alteration notifier base graph class. + + /// This class provides beside the core graph features + /// alteration notifier interface for the graph structure. + /// This is an observer-notifier pattern. More Obsevers can + /// be registered into the notifier and whenever an alteration + /// occured in the graph all the observers will notified about it. + class AlterableGraphComponent : virtual public BaseGraphComponent { + public: + + /// The edge observer registry. + typedef AlterationNotifier EdgeNotifier; + /// The node observer registry. + typedef AlterationNotifier NodeNotifier; + + /// \brief Gives back the edge alteration notifier. + /// + /// Gives back the edge alteration notifier. + EdgeNotifier getNotifier(Edge) const { + return EdgeNotifier(); + } + + /// \brief Gives back the node alteration notifier. + /// + /// Gives back the node alteration notifier. + NodeNotifier getNotifier(Node) const { + return NodeNotifier(); + } + + }; + + + /// Class describing the concept of graph maps + + /// This class describes the common interface of the graph maps + /// (NodeMap, EdgeMap), that is \ref maps-pages "maps" which can be used to + /// associate data to graph descriptors (nodes or edges). + template + class GraphMap : public ReadWriteMap { + protected: + GraphMap() {} + public: + /// \brief Construct a new map. + /// + /// Construct a new map for the graph. + explicit GraphMap(const Graph&) {} + /// \brief Construct a new map with default value. + /// + /// Construct a new map for the graph and initalise the values. + GraphMap(const Graph&, const _Value&) {} + /// \brief Copy constructor. + /// + /// Copy Constructor. + GraphMap(const GraphMap& gm) :ReadWriteMap(gm) {} + + /// \brief Assign operator. + /// + /// Assign operator. + GraphMap& operator=(const GraphMap&) { return *this;} + + template + struct Constraints { + void constraints() { + checkConcept, _Map >(); + // Construction with a graph parameter + _Map a(g); + // Constructor with a graph and a default value parameter + _Map a2(g,t); + // Copy constructor. Do we need it? + _Map b=c; + // Copy operator. Do we need it? + a=b; + + ignore_unused_variable_warning(a2); + } + + const _Map &c; + const Graph &g; + const typename GraphMap::Value &t; + }; + + }; + + /// An empty mappable base graph class. + + /// This class provides beside the core graph features + /// map interface for the graph structure. + /// This concept is part of the StaticGraphConcept. + class MappableGraphComponent : virtual public BaseGraphComponent { + public: + + typedef MappableGraphComponent Graph; + + typedef BaseGraphComponent::Node Node; + typedef BaseGraphComponent::Edge Edge; + + /// ReadWrite map of the nodes. + + /// ReadWrite map of the nodes. + /// + template + class NodeMap : public GraphMap { + private: + NodeMap(); + public: + /// \brief Construct a new map. + /// + /// Construct a new map for the graph. + /// \todo call the right parent class constructor + explicit NodeMap(const Graph&) {} + /// \brief Construct a new map with default value. + /// + /// Construct a new map for the graph and initalise the values. + NodeMap(const Graph&, const _Value&) {} + /// \brief Copy constructor. + /// + /// Copy Constructor. + NodeMap(const NodeMap& nm) : GraphMap(nm) {} + + /// \brief Assign operator. + /// + /// Assign operator. + NodeMap& operator=(const NodeMap&) { return *this;} + + }; + + /// ReadWrite map of the edges. + + /// ReadWrite map of the edges. + /// + template + class EdgeMap : public GraphMap { + private: + EdgeMap(); + public: + /// \brief Construct a new map. + /// + /// Construct a new map for the graph. + /// \todo call the right parent class constructor + explicit EdgeMap(const Graph&) {} + /// \brief Construct a new map with default value. + /// + /// Construct a new map for the graph and initalise the values. + EdgeMap(const Graph&, const _Value&) {} + /// \brief Copy constructor. + /// + /// Copy Constructor. + EdgeMap(const EdgeMap& em) :GraphMap(em) {} + + /// \brief Assign operator. + /// + /// Assign operator. + EdgeMap& operator=(const EdgeMap&) { return *this;} + + }; + + template + struct Constraints { + + struct Type { + int value; + Type() : value(0) {} + Type(int _v) : value(_v) {} + }; + + void constraints() { + checkConcept(); + { // int map test + typedef typename _Graph::template NodeMap IntNodeMap; + checkConcept, + IntNodeMap >(); + } { // bool map test + typedef typename _Graph::template NodeMap BoolNodeMap; + checkConcept, + BoolNodeMap >(); + } { // Type map test + typedef typename _Graph::template NodeMap TypeNodeMap; + checkConcept, + TypeNodeMap >(); + } + + { // int map test + typedef typename _Graph::template EdgeMap IntEdgeMap; + checkConcept, + IntEdgeMap >(); + } { // bool map test + typedef typename _Graph::template EdgeMap BoolEdgeMap; + checkConcept, + BoolEdgeMap >(); + } { // Type map test + typedef typename _Graph::template EdgeMap TypeEdgeMap; + checkConcept, + TypeEdgeMap >(); + } + } + + _Graph& graph; + }; + }; + + /// \brief An empty extendable extended graph class. + /// + /// This class provides beside the core graph features + /// item addition interface for the graph structure. + /// The difference between this class and the + /// \c BaseExtendableGraphComponent is that it should + /// notify the item alteration observers. + class ExtendableGraphComponent : virtual public BaseGraphComponent { + public: + + typedef ExtendableGraphComponent Graph; + + typedef BaseGraphComponent::Node Node; + typedef BaseGraphComponent::Edge Edge; + + /// \brief Add a node to the graph. + /// + /// Add a node to the graph and notify the observers. + Node addNode() { + return INVALID; + } + + /// \brief Add an edge to the graph. + /// + /// Add an edge to the graph and notify the observers. + Edge addEdge(const Node&, const Node&) { + return INVALID; + } + + template + struct Constraints { + void constraints() { + checkConcept(); + typename _Graph::Node node_a, node_b; + node_a = graph.addNode(); + typename _Graph::Edge edge; + edge = graph.addEdge(node_a, node_b); + } + _Graph& graph; + }; + }; + + /// \brief An empty erasable extended graph class. + /// + /// This class provides beside the core graph features + /// item erase interface for the graph structure. + /// The difference between this class and the + /// \c BaseErasableGraphComponent is that it should + /// notify the item alteration observers. + class ErasableGraphComponent : virtual public BaseGraphComponent { + public: + + typedef ErasableGraphComponent Graph; + + typedef BaseGraphComponent::Node Node; + typedef BaseGraphComponent::Edge Edge; + + /// \brief Erase the Node and notify the node alteration observers. + /// + /// Erase the Node and notify the node alteration observers. + void erase(const Node&) {} + + /// \brief Erase the Edge and notify the edge alteration observers. + /// + /// Erase the Edge and notify the edge alteration observers. + void erase(const Edge&) {} + + template + struct Constraints { + void constraints() { + checkConcept(); + typename _Graph::Node node; + graph.erase(node); + typename _Graph::Edge edge; + graph.erase(edge); + } + + _Graph& graph; + }; + }; + + /// @} + + } + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/concept/heap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/concept/heap.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,201 @@ +/* -*- C++ -*- + * lemon/concept/heap.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\ingroup concept +///\file +///\brief Classes for representing heaps. +/// + +#ifndef LEMON_CONCEPT_HEAP_H +#define LEMON_CONCEPT_HEAP_H + +#include + +namespace lemon { + namespace concept { + /// \addtogroup concept + /// @{ + + + /// \brief A concept structure describes the main interface of heaps. + /// + /// A concept structure describes the main interface of heaps. + /// + template + class Heap { + public: + + + /// \brief Type to represent the items states. + /// + /// Each Item element have a state associated to it. It may be "in heap", + /// "pre heap" or "post heap". The later two are indifferent from the + /// heap's point of view, but may be useful to the user. + /// + /// The ItemIntMap _should_ be initialized in such way, that it maps + /// PRE_HEAP (-1) to any element to be put in the heap... + enum state_enum { + IN_HEAP = 0, + PRE_HEAP = -1, + POST_HEAP = -2 + }; + + /// \brief The constructor. + /// + /// The constructor. + /// \param _iim should be given to the constructor, since it is used + /// internally to handle the cross references. The value of the map + /// should be PRE_HEAP (-1) for each element. + explicit Heap(ItemIntMap &_iim) {} + + /// The number of items stored in the heap. + /// + /// \brief Returns the number of items stored in the heap. + int size() const { return 0; } + /// \brief Checks if the heap stores no items. + /// + /// Returns \c true if and only if the heap stores no items. + bool empty() const { return false; } + + /// \brief Insert an item into the heap with the given heap. + /// + /// Adds \c i to the heap with priority \c p. + /// \param i The item to insert. + /// \param p The priority of the item. + void push(const Item &i, const Prio &p) {} + + /// \brief Returns the item with minimum priority. + /// + /// This method returns the item with minimum priority. + /// \pre The heap must be nonempty. + Item top() const {} + + /// \brief Returns the minimum priority. + /// + /// It returns the minimum priority. + /// \pre The heap must be nonempty. + Prio prio() const {} + + /// \brief Deletes the item with minimum priority. + /// + /// This method deletes the item with minimum priority. + /// \pre The heap must be non-empty. + void pop() {} + + /// \brief Deletes \c i from the heap. + /// + /// This method deletes item \c i from the heap, if \c i was + /// already stored in the heap. + /// \param i The item to erase. + void erase(const Item &i) {} + + /// \brief Returns the priority of \c i. + /// + /// This function returns the priority of item \c i. + /// \pre \c i must be in the heap. + /// \param i The item. + Prio operator[](const Item &i) const {} + + /// \brief \c i gets to the heap with priority \c p independently + /// if \c i was already there. + /// + /// This method calls \ref push(\c i, \c p) if \c i is not stored + /// in the heap and sets the priority of \c i to \c p otherwise. + /// It may throw an \e UnderFlowPriorityException. + /// \param i The item. + /// \param p The priority. + void set(const Item &i, const Prio &p) {} + + /// \brief Decreases the priority of \c i to \c p. + /// + /// This method decreases the priority of item \c i to \c p. + /// \pre \c i must be stored in the heap with priority at least \c p. + /// \param i The item. + /// \param p The priority. + void decrease(const Item &i, const Prio &p) {} + + /// \brief Increases the priority of \c i to \c p. + /// + /// This method sets the priority of item \c i to \c p. + /// \pre \c i must be stored in the heap with priority at most \c + /// p relative to \c Compare. + /// \param i The item. + /// \param p The priority. + void increase(const Item &i, const Prio &p) {} + + /// \brief Returns if \c item is in, has already been in, or has + /// never been in the heap. + /// + /// This method returns PRE_HEAP if \c item has never been in the + /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP + /// otherwise. In the latter case it is possible that \c item will + /// get back to the heap again. + /// \param i The item. + state_enum state(const Item &i) const {} + + + template + struct Constraints { + public: + + void constraints() { + Item item; + Prio prio; + + ignore_unused_variable_warning(item); + ignore_unused_variable_warning(prio); + + typedef typename _Heap::state_enum state_enum; + state_enum state; + + ignore_unused_variable_warning(state); + + _Heap heap1 = _Heap(map); + + ignore_unused_variable_warning(heap1); + + heap.push(item, prio); + + prio = heap.prio(); + item = heap.top(); + + heap.pop(); + + heap.set(item, prio); + heap.decrease(item, prio); + heap.increase(item, prio); + prio = heap[item]; + + heap.erase(item); + + state = heap.state(item); + + state = _Heap::PRE_HEAP; + state = _Heap::IN_HEAP; + state = _Heap::POST_HEAP; + } + + _Heap& heap; + ItemIntMap& map; + + Constraints() : heap(0), map(0) {} + }; + }; + + /// @} + } // namespace lemon +} +#endif // LEMON_CONCEPT_PATH_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/concept/maps.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/concept/maps.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,187 @@ +/* -*- C++ -*- + * lemon/concept/maps.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_CONCEPT_MAPS_H +#define LEMON_CONCEPT_MAPS_H + +#include + +///\ingroup concept +///\file +///\brief Map concepts checking classes for testing and documenting. + +namespace lemon { + + namespace concept { + + /// \addtogroup concept + /// @{ + + /// Readable map concept + template + class ReadMap + { + public: + /// Map's key type. + typedef K Key; + /// Map's value type. (The type of objects associated with the keys). + typedef T Value; + + // \bug Value don't need to be default constructible. + /// Returns the value associated with a key. + Value operator[](const Key &) const {return Value();} + + template + struct Constraints { + + void constraints() { + Value val = m[key]; + val = m[key]; + typename _ReadMap::Value own_val = m[own_key]; + own_val = m[own_key]; + + ignore_unused_variable_warning(val); + ignore_unused_variable_warning(own_val); + ignore_unused_variable_warning(key); + } + Key& key; + typename _ReadMap::Key& own_key; + _ReadMap& m; + }; + + }; + + + /// Writable map concept + template + class WriteMap + { + public: + /// Map's key type. + typedef K Key; + /// Map's value type. (The type of objects associated with the keys). + typedef T Value; + + /// Sets the value associated with a key. + void set(const Key &,const Value &) {} + + ///Default constructor + WriteMap() {} + + template + struct Constraints { + void constraints() { + // No constraints for constructor. + m.set(key, val); + m.set(own_key, own_val); + ignore_unused_variable_warning(key); + ignore_unused_variable_warning(val); + ignore_unused_variable_warning(own_key); + ignore_unused_variable_warning(own_val); + } + + Value& val; + typename _WriteMap::Value own_val; + Key& key; + typename _WriteMap::Key& own_key; + WriteMap& m; + + }; + }; + + ///Read/Writable map concept + template + class ReadWriteMap : public ReadMap, + public WriteMap + { + public: + /// Map's key type. + typedef K Key; + /// Map's value type. (The type of objects associated with the keys). + typedef T Value; + + /// Returns the value associated with a key. + Value operator[](const Key &) const {return Value();} + /// Sets the value associated with a key. + void set(const Key & ,const Value &) {} + + template + struct Constraints { + void constraints() { + checkConcept, _ReadWriteMap >(); + checkConcept, _ReadWriteMap >(); + } + }; + }; + + + ///Dereferable map concept + template + class ReferenceMap : public ReadWriteMap + { + public: + /// Map's key type. + typedef K Key; + /// Map's value type. (The type of objects associated with the keys). + typedef T Value; + /// Map's reference type. + typedef R Reference; + /// Map's const reference type. + typedef CR ConstReference; + + protected: + Value tmp; + public: + + ///Returns a reference to the value associated to a key. + Reference operator[](const Key &) { return tmp; } + ///Returns a const reference to the value associated to a key. + ConstReference operator[](const Key &) const + { return tmp; } + /// Sets the value associated with a key. + void set(const Key &k,const Value &t) { operator[](k)=t; } + + // \todo rethink this concept + template + struct ReferenceMapConcept { + + void constraints() { + checkConcept(); + m[key] = val; + val = m[key]; + m[key] = ref; + ref = m[key]; + m[own_key] = own_val; + own_val = m[own_key]; + m[own_key] = own_ref; + own_ref = m[own_key]; + } + + typename _ReferenceMap::Key& own_key; + typename _ReferenceMap::Value& own_val; + typename _ReferenceMap::Reference& own_ref; + Key& key; + Value& val; + Reference& ref; + ReferenceMap& m; + }; + }; + + // @} + + } //namespace concept +} //namespace lemon +#endif // LEMON_CONCEPT_MAPS_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/concept/path.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/concept/path.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,236 @@ +/* -*- C++ -*- + * lemon/concept/path.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\ingroup concept +///\file +///\brief Classes for representing paths in graphs. +/// +///\todo Iterators have obsolete style + +#ifndef LEMON_CONCEPT_PATH_H +#define LEMON_CONCEPT_PATH_H + +#include + +namespace lemon { + namespace concept { + /// \addtogroup concept + /// @{ + + + //! \brief A skeleton structure for representing directed paths in a graph. + //! + //! A skeleton structure for representing directed paths in a graph. + //! \param GR The graph type in which the path is. + //! + //! In a sense, the path can be treated as a graph, for it has \c NodeIt + //! and \c EdgeIt with the same usage. These types converts to the \c Node + //! and \c Edge of the original graph. + template + class Path { + public: + + /// Type of the underlying graph. + typedef /*typename*/ GR Graph; + /// Edge type of the underlying graph. + typedef typename Graph::Edge GraphEdge; + /// Node type of the underlying graph. + typedef typename Graph::Node GraphNode; + class NodeIt; + class EdgeIt; + + /// \param _G The graph in which the path is. + /// + Path(const Graph &) {} + + /// Length of the path. + int length() const {return 0;} + /// Returns whether the path is empty. + bool empty() const { return true;} + + /// Resets the path to an empty path. + void clear() {} + + /// \brief Starting point of the path. + /// + /// Starting point of the path. + /// Returns INVALID if the path is empty. + GraphNode/*It*/ target() const {return INVALID;} + /// \brief End point of the path. + /// + /// End point of the path. + /// Returns INVALID if the path is empty. + GraphNode/*It*/ source() const {return INVALID;} + + /// \brief First NodeIt/EdgeIt. + /// + /// Initializes node or edge iterator to point to the first + /// node or edge. + template + It& first(It &i) const { return i=It(*this); } + + /// \brief The target of an edge. + /// + /// Returns node iterator pointing to the target node of the + /// given edge iterator. + NodeIt target(const EdgeIt&) const {return INVALID;} + + /// \brief The source of an edge. + /// + /// Returns node iterator pointing to the source node of the + /// given edge iterator. + NodeIt source(const EdgeIt&) const {return INVALID;} + + + /* Iterator classes */ + + /** + * \brief Iterator class to iterate on the edges of the paths + * + * This class is used to iterate on the edges of the paths + * + * Of course it converts to Graph::Edge + * + */ + class EdgeIt { + public: + /// Default constructor + EdgeIt() {} + /// Invalid constructor + EdgeIt(Invalid) {} + /// Constructor with starting point + EdgeIt(const Path &) {} + + operator GraphEdge () const {} + + /// Next edge + EdgeIt& operator++() {return *this;} + + /// Comparison operator + bool operator==(const EdgeIt&) const {return true;} + /// Comparison operator + bool operator!=(const EdgeIt&) const {return true;} +// /// Comparison operator +// /// \todo It is not clear what is the "natural" ordering. +// bool operator<(const EdgeIt& e) const {} + + }; + + /** + * \brief Iterator class to iterate on the nodes of the paths + * + * This class is used to iterate on the nodes of the paths + * + * Of course it converts to Graph::Node. + * + */ + class NodeIt { + public: + /// Default constructor + NodeIt() {} + /// Invalid constructor + NodeIt(Invalid) {} + /// Constructor with starting point + NodeIt(const Path &) {} + + ///Conversion to Graph::Node + operator const GraphNode& () const {} + /// Next node + NodeIt& operator++() {return *this;} + + /// Comparison operator + bool operator==(const NodeIt&) const {return true;} + /// Comparison operator + bool operator!=(const NodeIt&) const {return true;} +// /// Comparison operator +// /// \todo It is not clear what is the "natural" ordering. +// bool operator<(const NodeIt& e) const {} + + }; + + friend class Builder; + + /** + * \brief Class to build paths + * + * This class is used to fill a path with edges. + * + * You can push new edges to the front and to the back of the path in + * arbitrary order then you should commit these changes to the graph. + * + * While the builder is active (after the first modifying + * operation and until the call of \ref commit()) the + * underlining Path is in a "transitional" state (operations on + * it have undefined result). + */ + class Builder { + public: + + Path &P; + + ///\param _P the path you want to fill in. + /// + + Builder(Path &_p) : P(_p) {} + + /// Sets the starting node of the path. + + /// Sets the starting node of the path. Edge added to the path + /// afterwards have to be incident to this node. + /// You \em must start building an empty path with these functions. + /// (And you \em must \em not use it later). + /// \sa pushFront() + /// \sa pushBack() + void setStartNode(const GraphNode &) {} + + ///Push a new edge to the front of the path + + ///Push a new edge to the front of the path. + ///If the path is empty, you \em must call \ref setStartNode() before + ///the first use of \ref pushFront(). + void pushFront(const GraphEdge&) {} + + ///Push a new edge to the back of the path + + ///Push a new edge to the back of the path. + ///If the path is empty, you \em must call \ref setStartNode() before + ///the first use of \ref pushBack(). + void pushBack(const GraphEdge&) {} + + ///Commit the changes to the path. + void commit() {} + + ///Reserve (front) storage for the builder in advance. + + ///If you know a reasonable upper bound on the number of the edges + ///to add to the front of the path, + ///using this function you may speed up the building. + void reserveFront(size_t) {} + ///Reserve (back) storage for the builder in advance. + + ///If you know a reasonable upper bound on the number of the edges + ///to add to the back of the path, + ///using this function you may speed up the building. + void reserveBack(size_t) {} + }; + }; + + ///@} + } + +} // namespace lemon + +#endif // LEMON_CONCEPT_PATH_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/concept/sym_graph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/concept/sym_graph.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,653 @@ +/* -*- C++ -*- + * lemon/concept/graph.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_CONCEPT_SYM_GRAPH_H +#define LEMON_CONCEPT_SYM_GRAPH_H + +///\ingroup concept +///\file +///\brief Declaration of SymGraph. + +#include +#include +#include + +namespace lemon { + namespace concept { + + /// \addtogroup concept + /// @{ + + /// An empty static graph class. + + /// This class provides all the common features of a symmetric + /// graph structure, however completely without implementations and + /// real data structures behind the interface. + /// All graph algorithms should compile with this class, but it will not + /// run properly, of course. + /// + /// It can be used for checking the interface compatibility, + /// or it can serve as a skeleton of a new symmetric graph structure. + /// + /// Also, you will find here the full documentation of a certain graph + /// feature, the documentation of a real symmetric graph imlementation + /// like @ref SymListGraph or + /// @ref lemon::SymSmartGraph will just refer to this structure. + class StaticSymGraph + { + public: + /// Defalult constructor. + + /// Defalult constructor. + /// + StaticSymGraph() { } + ///Copy consructor. + +// ///\todo It is not clear, what we expect from a copy constructor. +// ///E.g. How to assign the nodes/edges to each other? What about maps? +// StaticGraph(const StaticGraph& g) { } + + /// The base type of node iterators, + /// or in other words, the trivial node iterator. + + /// This is the base type of each node iterator, + /// thus each kind of node iterator converts to this. + /// More precisely each kind of node iterator should be inherited + /// from the trivial node iterator. + class Node { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + Node() { } + /// Copy constructor. + + /// Copy constructor. + /// + Node(const Node&) { } + + /// Invalid constructor \& conversion. + + /// This constructor initializes the iterator to be invalid. + /// \sa Invalid for more details. + Node(Invalid) { } + /// Equality operator + + /// Two iterators are equal if and only if they point to the + /// same object or both are invalid. + bool operator==(Node) const { return true; } + + /// Inequality operator + + /// \sa operator==(Node n) + /// + bool operator!=(Node) const { return true; } + + ///Comparison operator. + + ///This is a strict ordering between the nodes. + /// + ///This ordering can be different from the order in which NodeIt + ///goes through the nodes. + ///\todo Possibly we don't need it. + bool operator<(Node) const { return true; } + }; + + /// This iterator goes through each node. + + /// This iterator goes through each node. + /// Its usage is quite simple, for example you can count the number + /// of nodes in graph \c g of type \c Graph like this: + /// \code + /// int count=0; + /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count; + /// \endcode + class NodeIt : public Node { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + NodeIt() { } + /// Copy constructor. + + /// Copy constructor. + /// + NodeIt(const NodeIt&) { } + /// Invalid constructor \& conversion. + + /// Initialize the iterator to be invalid. + /// \sa Invalid for more details. + NodeIt(Invalid) { } + /// Sets the iterator to the first node. + + /// Sets the iterator to the first node of \c g. + /// + NodeIt(const StaticSymGraph& g) { } + /// Node -> NodeIt conversion. + + /// Sets the iterator to the node of \c g pointed by the trivial + /// iterator n. + /// This feature necessitates that each time we + /// iterate the edge-set, the iteration order is the same. + NodeIt(const StaticSymGraph& g, const Node& n) { } + /// Next node. + + /// Assign the iterator to the next node. + /// + NodeIt& operator++() { return *this; } + }; + + + /// The base type of the symmetric edge iterators. + + /// The base type of the symmetric edge iterators. + /// + class SymEdge { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + SymEdge() { } + /// Copy constructor. + + /// Copy constructor. + /// + SymEdge(const SymEdge&) { } + /// Initialize the iterator to be invalid. + + /// Initialize the iterator to be invalid. + /// + SymEdge(Invalid) { } + /// Equality operator + + /// Two iterators are equal if and only if they point to the + /// same object or both are invalid. + bool operator==(SymEdge) const { return true; } + /// Inequality operator + + /// \sa operator==(Node n) + /// + bool operator!=(SymEdge) const { return true; } + ///Comparison operator. + + ///This is a strict ordering between the nodes. + /// + ///This ordering can be different from the order in which NodeIt + ///goes through the nodes. + ///\todo Possibly we don't need it. + bool operator<(SymEdge) const { return true; } + }; + + + /// The base type of the edge iterators. + + /// The base type of the edge iterators. + /// + class Edge : public SymEdge { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + Edge() { } + /// Copy constructor. + + /// Copy constructor. + /// + Edge(const Edge&) { } + /// Initialize the iterator to be invalid. + + /// Initialize the iterator to be invalid. + /// + Edge(Invalid) { } + /// Equality operator + + /// Two iterators are equal if and only if they point to the + /// same object or both are invalid. + bool operator==(Edge) const { return true; } + /// Inequality operator + + /// \sa operator==(Node n) + /// + bool operator!=(Edge) const { return true; } + ///Comparison operator. + + ///This is a strict ordering between the nodes. + /// + ///This ordering can be different from the order in which NodeIt + ///goes through the nodes. + ///\todo Possibly we don't need it. + bool operator<(Edge) const { return true; } + }; + + /// This iterator goes trough the outgoing edges of a node. + + /// This iterator goes trough the \e outgoing edges of a certain node + /// of a graph. + /// Its usage is quite simple, for example you can count the number + /// of outgoing edges of a node \c n + /// in graph \c g of type \c Graph as follows. + /// \code + /// int count=0; + /// for (Graph::OutEdgeIt e(g, n); e!=INVALID; ++e) ++count; + /// \endcode + + class OutEdgeIt : public Edge { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + OutEdgeIt() { } + /// Copy constructor. + + /// Copy constructor. + /// + OutEdgeIt(const OutEdgeIt&) { } + /// Initialize the iterator to be invalid. + + /// Initialize the iterator to be invalid. + /// + OutEdgeIt(Invalid) { } + /// This constructor sets the iterator to first outgoing edge. + + /// This constructor set the iterator to the first outgoing edge of + /// node + ///@param n the node + ///@param g the graph + OutEdgeIt(const StaticSymGraph& g, const Node& n) { } + /// Edge -> OutEdgeIt conversion + + /// Sets the iterator to the value of the trivial iterator \c e. + /// This feature necessitates that each time we + /// iterate the edge-set, the iteration order is the same. + OutEdgeIt(const StaticSymGraph& g, const Edge& e) { } + ///Next outgoing edge + + /// Assign the iterator to the next + /// outgoing edge of the corresponding node. + OutEdgeIt& operator++() { return *this; } + }; + + /// This iterator goes trough the incoming edges of a node. + + /// This iterator goes trough the \e incoming edges of a certain node + /// of a graph. + /// Its usage is quite simple, for example you can count the number + /// of outgoing edges of a node \c n + /// in graph \c g of type \c Graph as follows. + /// \code + /// int count=0; + /// for(Graph::InEdgeIt e(g, n); e!=INVALID; ++e) ++count; + /// \endcode + + class InEdgeIt : public Edge { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + InEdgeIt() { } + /// Copy constructor. + + /// Copy constructor. + /// + InEdgeIt(const InEdgeIt&) { } + /// Initialize the iterator to be invalid. + + /// Initialize the iterator to be invalid. + /// + InEdgeIt(Invalid) { } + /// This constructor sets the iterator to first incoming edge. + + /// This constructor set the iterator to the first incoming edge of + /// node + ///@param n the node + ///@param g the graph + InEdgeIt(const StaticSymGraph& g, const Node& n) { } + /// Edge -> InEdgeIt conversion + + /// Sets the iterator to the value of the trivial iterator \c e. + /// This feature necessitates that each time we + /// iterate the edge-set, the iteration order is the same. + InEdgeIt(const StaticSymGraph& g, const Edge& n) { } + /// Next incoming edge + + /// Assign the iterator to the next inedge of the corresponding node. + /// + InEdgeIt& operator++() { return *this; } + }; + /// This iterator goes through each symmetric edge. + + /// This iterator goes through each symmetric edge of a graph. + /// Its usage is quite simple, for example you can count the number + /// of symmetric edges in a graph \c g of type \c Graph as follows: + /// \code + /// int count=0; + /// for(Graph::SymEdgeIt e(g); e!=INVALID; ++e) ++count; + /// \endcode + class SymEdgeIt : public SymEdge { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + SymEdgeIt() { } + /// Copy constructor. + + /// Copy constructor. + /// + SymEdgeIt(const SymEdgeIt&) { } + /// Initialize the iterator to be invalid. + + /// Initialize the iterator to be invalid. + /// + SymEdgeIt(Invalid) { } + /// This constructor sets the iterator to first edge. + + /// This constructor set the iterator to the first edge of + /// node + ///@param g the graph + SymEdgeIt(const StaticSymGraph& g) { } + /// Edge -> EdgeIt conversion + + /// Sets the iterator to the value of the trivial iterator \c e. + /// This feature necessitates that each time we + /// iterate the edge-set, the iteration order is the same. + SymEdgeIt(const StaticSymGraph&, const SymEdge&) { } + ///Next edge + + /// Assign the iterator to the next + /// edge of the corresponding node. + SymEdgeIt& operator++() { return *this; } + }; + /// This iterator goes through each edge. + + /// This iterator goes through each edge of a graph. + /// Its usage is quite simple, for example you can count the number + /// of edges in a graph \c g of type \c Graph as follows: + /// \code + /// int count=0; + /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count; + /// \endcode + class EdgeIt : public Edge { + public: + /// Default constructor + + /// @warning The default constructor sets the iterator + /// to an undefined value. + EdgeIt() { } + /// Copy constructor. + + /// Copy constructor. + /// + EdgeIt(const EdgeIt&) { } + /// Initialize the iterator to be invalid. + + /// Initialize the iterator to be invalid. + /// + EdgeIt(Invalid) { } + /// This constructor sets the iterator to first edge. + + /// This constructor set the iterator to the first edge of + /// node + ///@param g the graph + EdgeIt(const StaticSymGraph& g) { } + /// Edge -> EdgeIt conversion + + /// Sets the iterator to the value of the trivial iterator \c e. + /// This feature necessitates that each time we + /// iterate the edge-set, the iteration order is the same. + EdgeIt(const StaticSymGraph&, const Edge&) { } + ///Next edge + + /// Assign the iterator to the next + /// edge of the corresponding node. + EdgeIt& operator++() { return *this; } + }; + + /// First node of the graph. + + /// \retval i the first node. + /// \return the first node. + /// + NodeIt& first(NodeIt& i) const { return i; } + + /// The first incoming edge. + + /// The first incoming edge. + /// + InEdgeIt& first(InEdgeIt &i, Node) const { return i; } + /// The first outgoing edge. + + /// The first outgoing edge. + /// + OutEdgeIt& first(OutEdgeIt& i, Node) const { return i; } + /// The first edge of the Graph. + + /// The first edge of the Graph. + /// + EdgeIt& first(EdgeIt& i) const { return i; } + /// The first symmetric edge of the Graph. + + /// The first symmetric edge of the Graph. + /// + SymEdgeIt& first(SymEdgeIt& i) const { return i; } + + ///Gives back the target node of an edge. + + ///Gives back the target node of an edge. + /// + Node target(Edge) const { return INVALID; } + ///Gives back the source node of an edge. + + ///Gives back the source node of an edge. + /// + Node source(Edge) const { return INVALID; } + + ///Gives back the first node of an symmetric edge. + + ///Gives back the first node of an symmetric edge. + /// + Node target(SymEdge) const { return INVALID; } + ///Gives back the second node of an symmetric edge. + + ///Gives back the second node of an symmetric edge. + /// + Node source(SymEdge) const { return INVALID; } + ///Gives back the \e id of a node. + + ///\warning Not all graph structures provide this feature. + /// + ///\todo Should each graph provide \c id? + int id(const Node&) const { return 0; } + ///Gives back the \e id of an edge. + + ///\warning Not all graph structures provide this feature. + /// + ///\todo Should each graph provide \c id? + int id(const Edge&) const { return 0; } + + ///\warning Not all graph structures provide this feature. + /// + ///\todo Should each graph provide \c id? + int id(const SymEdge&) const { return 0; } + + ///\e + + ///\todo Should it be in the concept? + /// + int nodeNum() const { return 0; } + ///\e + + ///\todo Should it be in the concept? + /// + int edgeNum() const { return 0; } + + ///\todo Should it be in the concept? + /// + int symEdgeNum() const { return 0; } + + + /// Gives back the forward directed edge of the symmetric edge. + Edge forward(SymEdge) const {return INVALID;} + + /// Gives back the backward directed edge of the symmetric edge. + Edge backward(SymEdge) const {return INVALID;}; + + /// Gives back the opposite of the edge. + Edge opposite(Edge) const {return INVALID;} + + ///Reference map of the nodes to type \c T. + /// \ingroup concept + ///Reference map of the nodes to type \c T. + /// \sa Reference + /// \warning Making maps that can handle bool type (NodeMap) + /// needs some extra attention! + template class NodeMap : public ReferenceMap< Node, T > + { + public: + + ///\e + NodeMap(const StaticSymGraph&) { } + ///\e + NodeMap(const StaticSymGraph&, T) { } + + ///Copy constructor + template NodeMap(const NodeMap&) { } + ///Assignment operator + template NodeMap& operator=(const NodeMap&) + { return *this; } + }; + + ///Reference map of the edges to type \c T. + + /// \ingroup concept + ///Reference map of the edges to type \c T. + /// \sa Reference + /// \warning Making maps that can handle bool type (EdgeMap) + /// needs some extra attention! + template class EdgeMap + : public ReferenceMap + { + public: + + ///\e + EdgeMap(const StaticSymGraph&) { } + ///\e + EdgeMap(const StaticSymGraph&, T) { } + + ///Copy constructor + template EdgeMap(const EdgeMap&) { } + ///Assignment operator + template EdgeMap &operator=(const EdgeMap&) + { return *this; } + }; + + ///Reference map of the edges to type \c T. + + /// \ingroup concept + ///Reference map of the symmetric edges to type \c T. + /// \sa Reference + /// \warning Making maps that can handle bool type (EdgeMap) + /// needs some extra attention! + template class SymEdgeMap + : public ReferenceMap + { + public: + + ///\e + SymEdgeMap(const StaticSymGraph&) { } + ///\e + SymEdgeMap(const StaticSymGraph&, T) { } + + ///Copy constructor + template SymEdgeMap(const SymEdgeMap&) { } + ///Assignment operator + template SymEdgeMap &operator=(const SymEdgeMap&) + { return *this; } + }; + }; + + + + /// An empty non-static graph class. + + /// This class provides everything that \ref StaticGraph + /// with additional functionality which enables to build a + /// graph from scratch. + class ExtendableSymGraph : public StaticSymGraph + { + public: + /// Defalult constructor. + + /// Defalult constructor. + /// + ExtendableSymGraph() { } + ///Add a new node to the graph. + + /// \return the new node. + /// + Node addNode() { return INVALID; } + ///Add a new edge to the graph. + + ///Add a new symmetric edge to the graph with source node \c t + ///and target node \c h. + ///\return the new edge. + SymEdge addEdge(Node h, Node t) { return INVALID; } + + /// Resets the graph. + + /// This function deletes all edges and nodes of the graph. + /// It also frees the memory allocated to store them. + /// \todo It might belong to \ref ErasableGraph. + void clear() { } + }; + + /// An empty erasable graph class. + + /// This class is an extension of \ref ExtendableGraph. It also makes it + /// possible to erase edges or nodes. + class ErasableSymGraph : public ExtendableSymGraph + { + public: + /// Defalult constructor. + + /// Defalult constructor. + /// + ErasableSymGraph() { } + /// Deletes a node. + + /// Deletes node \c n node. + /// + void erase(Node n) { } + /// Deletes an edge. + + /// Deletes edge \c e edge. + /// + void erase(SymEdge e) { } + }; + + // @} + } //namespace concept +} //namespace lemon + + + +#endif // LEMON_CONCEPT_GRAPH_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/concept/undir_graph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/concept/undir_graph.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,531 @@ +/* -*- C++ -*- + * + * lemon/concept/undir_graph_component.h - Part of LEMON, a generic + * C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi + * Kutatocsoport (Egervary Research Group on Combinatorial Optimization, + * EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\ingroup graph_concepts +///\file +///\brief Undirected graphs and components of. + + +#ifndef LEMON_CONCEPT_UNDIR_GRAPH_H +#define LEMON_CONCEPT_UNDIR_GRAPH_H + +#include + +namespace lemon { + namespace concept { + + /// \addtogroup graph_concepts + /// @{ + + + /// Skeleton class which describes an edge with direction in \ref + /// UndirGraph "undirected graph". + template + class UndirGraphEdge : public UndirGraph::UndirEdge { + typedef typename UndirGraph::UndirEdge UndirEdge; + typedef typename UndirGraph::Node Node; + public: + + /// \e + UndirGraphEdge() {} + + /// \e + UndirGraphEdge(const UndirGraphEdge& e) : UndirGraph::UndirEdge(e) {} + + /// \e + UndirGraphEdge(Invalid) {} + + /// \brief Directed edge from undirected edge and a source node. + /// + /// Constructs a directed edge from undirected edge and a source node. + /// + /// \note You have to specify the graph for this constructor. + UndirGraphEdge(const UndirGraph &g, + UndirEdge undir_edge, Node n) { + ignore_unused_variable_warning(undir_edge); + ignore_unused_variable_warning(g); + ignore_unused_variable_warning(n); + } + + /// \e + UndirGraphEdge& operator=(UndirGraphEdge) { return *this; } + + /// \e + bool operator==(UndirGraphEdge) const { return true; } + /// \e + bool operator!=(UndirGraphEdge) const { return false; } + + /// \e + bool operator<(UndirGraphEdge) const { return false; } + + template + struct Constraints { + void constraints() { + const_constraints(); + } + void const_constraints() const { + /// \bug This should be is_base_and_derived ... + UndirEdge ue = e; + ue = e; + + Edge e_with_source(graph,ue,n); + ignore_unused_variable_warning(e_with_source); + } + Edge e; + UndirEdge ue; + UndirGraph graph; + Node n; + }; + }; + + + struct BaseIterableUndirGraphConcept { + + template + struct Constraints { + + typedef typename Graph::UndirEdge UndirEdge; + typedef typename Graph::Edge Edge; + typedef typename Graph::Node Node; + + void constraints() { + checkConcept(); + checkConcept, UndirEdge>(); + checkConcept, Edge>(); + + graph.first(ue); + graph.next(ue); + + const_constraints(); + } + void const_constraints() { + Node n; + n = graph.target(ue); + n = graph.source(ue); + n = graph.oppositeNode(n0, ue); + + bool b; + b = graph.forward(e); + ignore_unused_variable_warning(b); + } + + Graph graph; + Edge e; + Node n0; + UndirEdge ue; + }; + + }; + + + struct IterableUndirGraphConcept { + + template + struct Constraints { + void constraints() { + /// \todo we don't need the iterable component to be base iterable + /// Don't we really??? + //checkConcept< BaseIterableUndirGraphConcept, Graph > (); + + checkConcept (); + + typedef typename Graph::UndirEdge UndirEdge; + typedef typename Graph::UndirEdgeIt UndirEdgeIt; + typedef typename Graph::IncEdgeIt IncEdgeIt; + + checkConcept, UndirEdgeIt>(); + checkConcept, IncEdgeIt>(); + } + }; + + }; + + struct MappableUndirGraphConcept { + + template + struct Constraints { + + struct Dummy { + int value; + Dummy() : value(0) {} + Dummy(int _v) : value(_v) {} + }; + + void constraints() { + checkConcept(); + + typedef typename Graph::template UndirEdgeMap IntMap; + checkConcept, + IntMap >(); + + typedef typename Graph::template UndirEdgeMap BoolMap; + checkConcept, + BoolMap >(); + + typedef typename Graph::template UndirEdgeMap DummyMap; + checkConcept, + DummyMap >(); + } + }; + + }; + + struct ExtendableUndirGraphConcept { + + template + struct Constraints { + void constraints() { + node_a = graph.addNode(); + uedge = graph.addEdge(node_a, node_b); + } + typename Graph::Node node_a, node_b; + typename Graph::UndirEdge uedge; + Graph graph; + }; + + }; + + struct ErasableUndirGraphConcept { + + template + struct Constraints { + void constraints() { + graph.erase(n); + graph.erase(e); + } + Graph graph; + typename Graph::Node n; + typename Graph::UndirEdge e; + }; + + }; + + /// Class describing the concept of Undirected Graphs. + + /// This class describes the common interface of all Undirected + /// Graphs. + /// + /// As all concept describing classes it provides only interface + /// without any sensible implementation. So any algorithm for + /// undirected graph should compile with this class, but it will not + /// run properly, of couse. + /// + /// In LEMON undirected graphs also fulfill the concept of directed + /// graphs (\ref lemon::concept::Graph "Graph Concept"). For + /// explanation of this and more see also the page \ref undir_graphs, + /// a tutorial about undirected graphs. + + class UndirGraph { + public: + + /// Type describing a node in the graph + typedef GraphNode Node; + + /// Type describing an undirected edge + typedef GraphItem<'u'> UndirEdge; + + /// Type describing an UndirEdge with direction +#ifndef DOXYGEN + typedef UndirGraphEdge Edge; +#else + typedef UndirGraphEdge Edge; +#endif + + /// Iterator type which iterates over all nodes +#ifndef DOXYGEN + typedef GraphIterator NodeIt; +#else + typedef GraphIterator NodeIt; +#endif + + /// Iterator type which iterates over all undirected edges +#ifndef DOXYGEN + typedef GraphIterator UndirEdgeIt; +#else + typedef GraphIterator UndirEdgeIt; +#endif + + /// Iterator type which iterates over all directed edges. + + /// Iterator type which iterates over all edges (each undirected + /// edge occurs twice with both directions. +#ifndef DOXYGEN + typedef GraphIterator EdgeIt; +#else + typedef GraphIterator EdgeIt; +#endif + + + /// Iterator of undirected edges incident to a node +#ifndef DOXYGEN + typedef GraphIncIterator IncEdgeIt; +#else + typedef GraphIncIterator IncEdgeIt; +#endif + + /// Iterator of edges incoming to a node +#ifndef DOXYGEN + typedef GraphIncIterator InEdgeIt; +#else + typedef GraphIncIterator InEdgeIt; +#endif + + /// Iterator of edges outgoing from a node +#ifndef DOXYGEN + typedef GraphIncIterator OutEdgeIt; +#else + typedef GraphIncIterator OutEdgeIt; +#endif + + /// NodeMap template +#ifdef DOXYGEN + typedef GraphMap NodeMap; +#endif + + /// UndirEdgeMap template +#ifdef DOXYGEN + typedef GraphMap UndirEdgeMap; +#endif + + /// EdgeMap template +#ifdef DOXYGEN + typedef GraphMap EdgeMap; +#endif + + template + class NodeMap : public GraphMap { + typedef GraphMap Parent; + public: + + explicit NodeMap(const UndirGraph &g) : Parent(g) {} + NodeMap(const UndirGraph &g, T t) : Parent(g, t) {} + }; + + template + class UndirEdgeMap : public GraphMap { + typedef GraphMap Parent; + public: + + explicit UndirEdgeMap(const UndirGraph &g) : Parent(g) {} + UndirEdgeMap(const UndirGraph &g, T t) : Parent(g, t) {} + }; + + template + class EdgeMap : public GraphMap { + typedef GraphMap Parent; + public: + + explicit EdgeMap(const UndirGraph &g) : Parent(g) {} + EdgeMap(const UndirGraph &g, T t) : Parent(g, t) {} + }; + + /// Is the Edge oriented "forward"? + + /// Returns whether the given directed edge is same orientation as + /// the corresponding undirected edge. + /// + /// \todo "What does the direction of an undirected edge mean?" + bool forward(Edge) const { return true; } + + /// Opposite node on an edge + + /// \return the opposite of the given Node on the given Edge + /// + /// \todo What should we do if given Node and Edge are not incident? + Node oppositeNode(Node, UndirEdge) const { return INVALID; } + + /// First node of the undirected edge. + + /// \return the first node of the given UndirEdge. + /// + /// Naturally undirectected edges don't have direction and thus + /// don't have source and target node. But we use these two methods + /// to query the two endnodes of the edge. The direction of the edge + /// which arises this way is called the inherent direction of the + /// undirected edge, and is used to define the "forward" direction + /// of the directed versions of the edges. + /// \sa forward + Node source(UndirEdge) const { return INVALID; } + + /// Second node of the undirected edge. + Node target(UndirEdge) const { return INVALID; } + + /// Source node of the directed edge. + Node source(Edge) const { return INVALID; } + + /// Target node of the directed edge. + Node target(Edge) const { return INVALID; } + + /// First node of the graph + + /// \note This method is part of so called \ref + /// developpers_interface "Developpers' interface", so it shouldn't + /// be used in an end-user program. + void first(Node&) const {} + /// Next node of the graph + + /// \note This method is part of so called \ref + /// developpers_interface "Developpers' interface", so it shouldn't + /// be used in an end-user program. + void next(Node&) const {} + + /// First undirected edge of the graph + + /// \note This method is part of so called \ref + /// developpers_interface "Developpers' interface", so it shouldn't + /// be used in an end-user program. + void first(UndirEdge&) const {} + /// Next undirected edge of the graph + + /// \note This method is part of so called \ref + /// developpers_interface "Developpers' interface", so it shouldn't + /// be used in an end-user program. + void next(UndirEdge&) const {} + + /// First directed edge of the graph + + /// \note This method is part of so called \ref + /// developpers_interface "Developpers' interface", so it shouldn't + /// be used in an end-user program. + void first(Edge&) const {} + /// Next directed edge of the graph + + /// \note This method is part of so called \ref + /// developpers_interface "Developpers' interface", so it shouldn't + /// be used in an end-user program. + void next(Edge&) const {} + + /// First outgoing edge from a given node + + /// \note This method is part of so called \ref + /// developpers_interface "Developpers' interface", so it shouldn't + /// be used in an end-user program. + void firstOut(Edge&, Node) const {} + /// Next outgoing edge to a node + + /// \note This method is part of so called \ref + /// developpers_interface "Developpers' interface", so it shouldn't + /// be used in an end-user program. + void nextOut(Edge&) const {} + + /// First incoming edge to a given node + + /// \note This method is part of so called \ref + /// developpers_interface "Developpers' interface", so it shouldn't + /// be used in an end-user program. + void firstIn(Edge&, Node) const {} + /// Next incoming edge to a node + + /// \note This method is part of so called \ref + /// developpers_interface "Developpers' interface", so it shouldn't + /// be used in an end-user program. + void nextIn(Edge&) const {} + + + /// Base node of the iterator + /// + /// Returns the base node (the source in this case) of the iterator + Node baseNode(OutEdgeIt e) const { + return source(e); + } + /// Running node of the iterator + /// + /// Returns the running node (the target in this case) of the + /// iterator + Node runningNode(OutEdgeIt e) const { + return target(e); + } + + /// Base node of the iterator + /// + /// Returns the base node (the target in this case) of the iterator + Node baseNode(InEdgeIt e) const { + return target(e); + } + /// Running node of the iterator + /// + /// Returns the running node (the source in this case) of the + /// iterator + Node runningNode(InEdgeIt e) const { + return source(e); + } + + /// Base node of the iterator + /// + /// Returns the base node of the iterator + Node baseNode(IncEdgeIt) const { + return INVALID; + } + /// Running node of the iterator + /// + /// Returns the running node of the iterator + Node runningNode(IncEdgeIt) const { + return INVALID; + } + + + template + struct Constraints { + void constraints() { + checkConcept(); + checkConcept(); + checkConcept(); + } + }; + + }; + + class ExtendableUndirGraph : public UndirGraph { + public: + + template + struct Constraints { + void constraints() { + checkConcept(); + checkConcept(); + checkConcept(); + + checkConcept(); + checkConcept(); + checkConcept(); + } + }; + + }; + + class ErasableUndirGraph : public ExtendableUndirGraph { + public: + + template + struct Constraints { + void constraints() { + checkConcept(); + checkConcept(); + } + }; + + }; + + /// @} + + } + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/concept_check.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/concept_check.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,89 @@ +// -*- C++ -*- +// Modified for use in LEMON. +// We should really consider using Boost... + + +// +// (C) Copyright Jeremy Siek 2000. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Revision History: +// 05 May 2001: Workarounds for HP aCC from Thomas Matelich. (Jeremy Siek) +// 02 April 2001: Removed limits header altogether. (Jeremy Siek) +// 01 April 2001: Modified to use new header. (JMaddock) +// + +// See http://www.boost.org/libs/concept_check for documentation. + +#ifndef LEMON_BOOST_CONCEPT_CHECKS_HPP +#define LEMON_BOOST_CONCEPT_CHECKS_HPP + +namespace lemon { + + /* + "inline" is used for ignore_unused_variable_warning() + and function_requires() to make sure there is no + overtarget with g++. + */ + + template inline void ignore_unused_variable_warning(const T&) { } + + template + inline void function_requires() + { +#if !defined(NDEBUG) + void (Concept::*x)() = & Concept::constraints; + ignore_unused_variable_warning(x); +#endif + } + + template + inline void checkConcept() { +#if !defined(NDEBUG) + typedef typename Concept::template Constraints ConceptCheck; + void (ConceptCheck::*x)() = & ConceptCheck::constraints; + ignore_unused_variable_warning(x); +#endif + } + +#define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ + typedef void (ns::concept ::* func##type_var##concept)(); \ + template \ + struct concept_checking_##type_var##concept { }; \ + typedef concept_checking_##type_var##concept< \ + BOOST_FPTR ns::concept::constraints> \ + concept_checking_typedef_##type_var##concept + +#define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \ + typedef void (ns::concept ::* \ + func##type_var1##type_var2##concept)(); \ + template \ + struct concept_checking_##type_var1##type_var2##concept { }; \ + typedef concept_checking_##type_var1##type_var2##concept< \ + BOOST_FPTR ns::concept::constraints> \ + concept_checking_typedef_##type_var1##type_var2##concept + +#define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \ + typedef void (ns::concept ::* \ + func##tv1##tv2##tv3##concept)(); \ + template \ + struct concept_checking_##tv1##tv2##tv3##concept { }; \ + typedef concept_checking_##tv1##tv2##tv3##concept< \ + BOOST_FPTR ns::concept::constraints> \ + concept_checking_typedef_##tv1##tv2##tv3##concept + +#define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \ + typedef void (ns::concept ::* \ + func##tv1##tv2##tv3##tv4##concept)(); \ + template \ + struct concept_checking_##tv1##tv2##tv3##tv4##concept { }; \ + typedef concept_checking_##tv1##tv2##tv3##tv4##concept< \ + BOOST_FPTR ns::concept::constraints> \ + concept_checking_typedef_##tv1##tv2##tv3##tv4##concept + + +} // namespace lemon + +#endif // LEMON_BOOST_CONCEPT_CHECKS_HPP diff -r d8475431bbbb -r 8e85e6bbefdf lemon/config.h.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/config.h.in Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,5 @@ +/* Define to 1 if you have CPLEX. */ +#undef HAVE_CPLEX + +/* Define to 1 if you have GLPK. */ +#undef HAVE_GLPK diff -r d8475431bbbb -r 8e85e6bbefdf lemon/dfs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/dfs.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,1136 @@ +/* -*- C++ -*- + * lemon/dfs.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_DFS_H +#define LEMON_DFS_H + +///\ingroup flowalgs +///\file +///\brief Dfs algorithm. + +#include +#include +#include +#include +#include + +namespace lemon { + + + + ///Default traits class of Dfs class. + + ///Default traits class of Dfs class. + ///\param GR Graph type. + template + struct DfsDefaultTraits + { + ///The graph type the algorithm runs on. + typedef GR Graph; + ///\brief The type of the map that stores the last + ///edges of the %DFS paths. + /// + ///The type of the map that stores the last + ///edges of the %DFS paths. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef typename Graph::template NodeMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \ref PredMap. + ///\param G is the graph, to which we would like to define the PredMap. + ///\todo The graph alone may be insufficient to initialize + static PredMap *createPredMap(const GR &G) + { + return new PredMap(G); + } +// ///\brief The type of the map that stores the last but one +// ///nodes of the %DFS paths. +// /// +// ///The type of the map that stores the last but one +// ///nodes of the %DFS paths. +// ///It must meet the \ref concept::WriteMap "WriteMap" concept. +// /// +// typedef NullMap PredNodeMap; +// ///Instantiates a PredNodeMap. + +// ///This function instantiates a \ref PredNodeMap. +// ///\param G is the graph, to which +// ///we would like to define the \ref PredNodeMap +// static PredNodeMap *createPredNodeMap(const GR &G) +// { +// return new PredNodeMap(); +// } + + ///The type of the map that indicates which nodes are processed. + + ///The type of the map that indicates which nodes are processed. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \ref ProcessedMap. + ///\param G is the graph, to which + ///we would like to define the \ref ProcessedMap + static ProcessedMap *createProcessedMap(const GR &) + { + return new ProcessedMap(); + } + ///The type of the map that indicates which nodes are reached. + + ///The type of the map that indicates which nodes are reached. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef typename Graph::template NodeMap ReachedMap; + ///Instantiates a ReachedMap. + + ///This function instantiates a \ref ReachedMap. + ///\param G is the graph, to which + ///we would like to define the \ref ReachedMap. + static ReachedMap *createReachedMap(const GR &G) + { + return new ReachedMap(G); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef typename Graph::template NodeMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param G is the graph, to which we would like to define the \ref DistMap + static DistMap *createDistMap(const GR &G) + { + return new DistMap(G); + } + }; + + ///%DFS algorithm class. + + ///\ingroup flowalgs + ///This class provides an efficient implementation of the %DFS algorithm. + /// + ///\param GR The graph type the algorithm runs on. The default value is + ///\ref ListGraph. The value of GR is not used directly by Dfs, it + ///is only passed to \ref DfsDefaultTraits. + ///\param TR Traits class to set various data types used by the algorithm. + ///The default traits class is + ///\ref DfsDefaultTraits "DfsDefaultTraits". + ///See \ref DfsDefaultTraits for the documentation of + ///a Dfs traits class. + /// + ///\author Jacint Szabo and Alpar Juttner + ///\todo A compare object would be nice. + +#ifdef DOXYGEN + template +#else + template > +#endif + class Dfs { + public: + /** + * \brief \ref Exception for uninitialized parameters. + * + * This error represents problems in the initialization + * of the parameters of the algorithms. + */ + class UninitializedParameter : public lemon::UninitializedParameter { + public: + virtual const char* exceptionName() const { + return "lemon::Dfs::UninitializedParameter"; + } + }; + + typedef TR Traits; + ///The type of the underlying graph. + typedef typename TR::Graph Graph; + ///\e + typedef typename Graph::Node Node; + ///\e + typedef typename Graph::NodeIt NodeIt; + ///\e + typedef typename Graph::Edge Edge; + ///\e + typedef typename Graph::OutEdgeIt OutEdgeIt; + + ///\brief The type of the map that stores the last + ///edges of the %DFS paths. + typedef typename TR::PredMap PredMap; +// ///\brief The type of the map that stores the last but one +// ///nodes of the %DFS paths. +// typedef typename TR::PredNodeMap PredNodeMap; + ///The type of the map indicating which nodes are reached. + typedef typename TR::ReachedMap ReachedMap; + ///The type of the map indicating which nodes are processed. + typedef typename TR::ProcessedMap ProcessedMap; + ///The type of the map that stores the dists of the nodes. + typedef typename TR::DistMap DistMap; + private: + /// Pointer to the underlying graph. + const Graph *G; + ///Pointer to the map of predecessors edges. + PredMap *_pred; + ///Indicates if \ref _pred is locally allocated (\c true) or not. + bool local_pred; +// ///Pointer to the map of predecessors nodes. +// PredNodeMap *_predNode; +// ///Indicates if \ref _predNode is locally allocated (\c true) or not. +// bool local_predNode; + ///Pointer to the map of distances. + DistMap *_dist; + ///Indicates if \ref _dist is locally allocated (\c true) or not. + bool local_dist; + ///Pointer to the map of reached status of the nodes. + ReachedMap *_reached; + ///Indicates if \ref _reached is locally allocated (\c true) or not. + bool local_reached; + ///Pointer to the map of processed status of the nodes. + ProcessedMap *_processed; + ///Indicates if \ref _processed is locally allocated (\c true) or not. + bool local_processed; + + std::vector _stack; + int _stack_head; +// ///The source node of the last execution. +// Node source; + + ///Creates the maps if necessary. + + ///\todo Error if \c G are \c NULL. + ///\todo Better memory allocation (instead of new). + void create_maps() + { + if(!_pred) { + local_pred = true; + _pred = Traits::createPredMap(*G); + } +// if(!_predNode) { +// local_predNode = true; +// _predNode = Traits::createPredNodeMap(*G); +// } + if(!_dist) { + local_dist = true; + _dist = Traits::createDistMap(*G); + } + if(!_reached) { + local_reached = true; + _reached = Traits::createReachedMap(*G); + } + if(!_processed) { + local_processed = true; + _processed = Traits::createProcessedMap(*G); + } + } + + public : + + ///\name Named template parameters + + ///@{ + + template + struct DefPredMapTraits : public Traits { + typedef T PredMap; + static PredMap *createPredMap(const Graph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting PredMap type + + ///\ref named-templ-param "Named parameter" for setting PredMap type + /// + template + class DefPredMap : public Dfs< Graph, + DefPredMapTraits > { }; + +// template +// struct DefPredNodeMapTraits : public Traits { +// typedef T PredNodeMap; +// static PredNodeMap *createPredNodeMap(const Graph &G) +// { +// throw UninitializedParameter(); +// } +// }; +// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type + +// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type +// /// +// template +// class DefPredNodeMap : public Dfs< Graph, +// LengthMap, +// DefPredNodeMapTraits > { }; + + template + struct DefDistMapTraits : public Traits { + typedef T DistMap; + static DistMap *createDistMap(const Graph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting DistMap type + + ///\ref named-templ-param "Named parameter" for setting DistMap type + /// + template + class DefDistMap : public Dfs< Graph, + DefDistMapTraits > { }; + + template + struct DefReachedMapTraits : public Traits { + typedef T ReachedMap; + static ReachedMap *createReachedMap(const Graph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting ReachedMap type + + ///\ref named-templ-param "Named parameter" for setting ReachedMap type + /// + template + class DefReachedMap : public Dfs< Graph, + DefReachedMapTraits > { }; + + struct DefGraphReachedMapTraits : public Traits { + typedef typename Graph::template NodeMap ReachedMap; + static ReachedMap *createReachedMap(const Graph &G) + { + return new ReachedMap(G); + } + }; + template + struct DefProcessedMapTraits : public Traits { + typedef T ProcessedMap; + static ProcessedMap *createProcessedMap(const Graph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting ProcessedMap type + + ///\ref named-templ-param "Named parameter" for setting ProcessedMap type + /// + template + class DefProcessedMap : public Dfs< Graph, + DefProcessedMapTraits > { }; + + struct DefGraphProcessedMapTraits : public Traits { + typedef typename Graph::template NodeMap ProcessedMap; + static ProcessedMap *createProcessedMap(const Graph &G) + { + return new ProcessedMap(G); + } + }; + ///\brief \ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Graph::NodeMap. + /// + ///\ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Graph::NodeMap. + ///If you don't set it explicitely, it will be automatically allocated. + template + class DefProcessedMapToBeDefaultMap : + public Dfs< Graph, + DefGraphProcessedMapTraits> { }; + + ///@} + + public: + + ///Constructor. + + ///\param _G the graph the algorithm will run on. + /// + Dfs(const Graph& _G) : + G(&_G), + _pred(NULL), local_pred(false), +// _predNode(NULL), local_predNode(false), + _dist(NULL), local_dist(false), + _reached(NULL), local_reached(false), + _processed(NULL), local_processed(false) + { } + + ///Destructor. + ~Dfs() + { + if(local_pred) delete _pred; +// if(local_predNode) delete _predNode; + if(local_dist) delete _dist; + if(local_reached) delete _reached; + if(local_processed) delete _processed; + } + + ///Sets the map storing the predecessor edges. + + ///Sets the map storing the predecessor edges. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dfs &predMap(PredMap &m) + { + if(local_pred) { + delete _pred; + local_pred=false; + } + _pred = &m; + return *this; + } + +// ///Sets the map storing the predecessor nodes. + +// ///Sets the map storing the predecessor nodes. +// ///If you don't use this function before calling \ref run(), +// ///it will allocate one. The destuctor deallocates this +// ///automatically allocated map, of course. +// ///\return (*this) +// Dfs &predNodeMap(PredNodeMap &m) +// { +// if(local_predNode) { +// delete _predNode; +// local_predNode=false; +// } +// _predNode = &m; +// return *this; +// } + + ///Sets the map storing the distances calculated by the algorithm. + + ///Sets the map storing the distances calculated by the algorithm. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dfs &distMap(DistMap &m) + { + if(local_dist) { + delete _dist; + local_dist=false; + } + _dist = &m; + return *this; + } + + ///Sets the map indicating if a node is reached. + + ///Sets the map indicating if a node is reached. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dfs &reachedMap(ReachedMap &m) + { + if(local_reached) { + delete _reached; + local_reached=false; + } + _reached = &m; + return *this; + } + + ///Sets the map indicating if a node is processed. + + ///Sets the map indicating if a node is processed. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dfs &processedMap(ProcessedMap &m) + { + if(local_processed) { + delete _processed; + local_processed=false; + } + _processed = &m; + return *this; + } + + public: + ///\name Execution control + ///The simplest way to execute the algorithm is to use + ///one of the member functions called \c run(...). + ///\n + ///If you need more control on the execution, + ///first you must call \ref init(), then you can add several source nodes + ///with \ref addSource(). + ///Finally \ref start() will perform the actual path + ///computation. + + ///@{ + + ///Initializes the internal data structures. + + ///Initializes the internal data structures. + /// + void init() + { + create_maps(); + _stack.resize(countNodes(*G)); + _stack_head=-1; + for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { + _pred->set(u,INVALID); + // _predNode->set(u,INVALID); + _reached->set(u,false); + _processed->set(u,false); + } + } + + ///Adds a new source node. + + ///Adds a new source node to the set of nodes to be processed. + /// + ///\bug dist's are wrong (or at least strange) in case of multiple sources. + void addSource(Node s) + { + if(!(*_reached)[s]) + { + _reached->set(s,true); + _pred->set(s,INVALID); + // _predNode->set(u,INVALID); + _stack[++_stack_head]=OutEdgeIt(*G,s); + _dist->set(s,_stack_head); + } + } + + ///Processes the next node. + + ///Processes the next node. + /// + ///\warning The stack must not be empty! + void processNextEdge() + { + Node m; + Edge e=_stack[_stack_head]; + if(!(*_reached)[m=G->target(e)]) { + _pred->set(m,e); + _reached->set(m,true); + // _pred_node->set(m,G->source(e)); + ++_stack_head; + _stack[_stack_head] = OutEdgeIt(*G, m); + _dist->set(m,_stack_head); + } + else { + Node n; + while(_stack_head>=0 && + (n=G->source(_stack[_stack_head]), + ++_stack[_stack_head]==INVALID)) + { + _processed->set(n,true); + --_stack_head; + } + } + } + + ///\brief Returns \c false if there are nodes + ///to be processed in the queue + /// + ///Returns \c false if there are nodes + ///to be processed in the queue + bool emptyQueue() { return _stack_head<0; } + ///Returns the number of the nodes to be processed. + + ///Returns the number of the nodes to be processed in the queue. + /// + int queueSize() { return _stack_head+1; } + + ///Executes the algorithm. + + ///Executes the algorithm. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %DFS algorithm from the root node(s) + ///in order to + ///compute the + ///%DFS path to each node. The algorithm computes + ///- The %DFS tree. + ///- The distance of each node from the root(s). + /// + void start() + { + while ( !emptyQueue() ) processNextEdge(); + } + + ///Executes the algorithm until \c dest is reached. + + ///Executes the algorithm until \c dest is reached. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %DFS algorithm from the root node(s) + ///in order to + ///compute the + ///%DFS path to \c dest. The algorithm computes + ///- The %DFS path to \c dest. + ///- The distance of \c dest from the root(s). + /// + void start(Node dest) + { + while ( !emptyQueue() && G->target(_stack[_stack_head])!=dest ) + processNextEdge(); + } + + ///Executes the algorithm until a condition is met. + + ///Executes the algorithm until a condition is met. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///\param nm must be a bool (or convertible) edge map. The algorithm + ///will stop when it reaches a edge \c v with nm[v]==true. + ///\warning Contrary to \ref Dfs and \ref Dijkstra, \c mn is an edge map, + ///not a node map. + template + void start(const NM &nm) + { + while ( !emptyQueue() && !nm[_stack[_stack_head]] ) processNextEdge(); + } + + ///Runs %DFS algorithm from node \c s. + + ///This method runs the %DFS algorithm from a root node \c s + ///in order to + ///compute the + ///%DFS path to each node. The algorithm computes + ///- The %DFS tree. + ///- The distance of each node from the root. + /// + ///\note d.run(s) is just a shortcut of the following code. + ///\code + /// d.init(); + /// d.addSource(s); + /// d.start(); + ///\endcode + void run(Node s) { + init(); + addSource(s); + start(); + } + + ///Finds the %DFS path between \c s and \c t. + + ///Finds the %DFS path between \c s and \c t. + /// + ///\return The length of the %DFS s---t path if there exists one, + ///0 otherwise. + ///\note Apart from the return value, d.run(s) is + ///just a shortcut of the following code. + ///\code + /// d.init(); + /// d.addSource(s); + /// d.start(t); + ///\endcode + int run(Node s,Node t) { + init(); + addSource(s); + start(t); + return reached(t)?_stack_head+1:0; + } + + ///@} + + ///\name Query Functions + ///The result of the %DFS algorithm can be obtained using these + ///functions.\n + ///Before the use of these functions, + ///either run() or start() must be called. + + ///@{ + + ///Copies the path to \c t on the DFS tree into \c p + + ///This function copies the path on the DFS tree to \c t into \c p. + ///If it \c \t is a source itself or unreachable, then it does not + ///alter \c p. + ///\todo Is it the right way to handle unreachable nodes? + ///\return Returns \c true if a path to \c t was actually copied to \c p, + ///\c false otherwise. + ///\sa DirPath + template + bool getPath(P &p,Node t) + { + if(reached(t)) { + p.clear(); + typename P::Builder b(p); + for(b.setStartNode(t);pred(t)!=INVALID;t=predNode(t)) + b.pushFront(pred(t)); + b.commit(); + return true; + } + return false; + } + + ///The distance of a node from the root(s). + + ///Returns the distance of a node from the root(s). + ///\pre \ref run() must be called before using this function. + ///\warning If node \c v in unreachable from the root(s) the return value + ///of this funcion is undefined. + int dist(Node v) const { return (*_dist)[v]; } + + ///Returns the 'previous edge' of the %DFS tree. + + ///For a node \c v it returns the 'previous edge' + ///of the %DFS path, + ///i.e. it returns the last edge of a %DFS path from the root(s) to \c + ///v. It is \ref INVALID + ///if \c v is unreachable from the root(s) or \c v is a root. The + ///%DFS tree used here is equal to the %DFS tree used in + ///\ref predNode(Node v). + ///\pre Either \ref run() or \ref start() must be called before using + ///this function. + ///\todo predEdge could be a better name. + Edge pred(Node v) const { return (*_pred)[v];} + + ///Returns the 'previous node' of the %DFS tree. + + ///For a node \c v it returns the 'previous node' + ///of the %DFS tree, + ///i.e. it returns the last but one node from a %DFS path from the + ///root(a) to \c /v. + ///It is INVALID if \c v is unreachable from the root(s) or + ///if \c v itself a root. + ///The %DFS tree used here is equal to the %DFS + ///tree used in \ref pred(Node v). + ///\pre Either \ref run() or \ref start() must be called before + ///using this function. + Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID: + G->source((*_pred)[v]); } + + ///Returns a reference to the NodeMap of distances. + + ///Returns a reference to the NodeMap of distances. + ///\pre Either \ref run() or \ref init() must + ///be called before using this function. + const DistMap &distMap() const { return *_dist;} + + ///Returns a reference to the %DFS edge-tree map. + + ///Returns a reference to the NodeMap of the edges of the + ///%DFS tree. + ///\pre Either \ref run() or \ref init() + ///must be called before using this function. + const PredMap &predMap() const { return *_pred;} + +// ///Returns a reference to the map of nodes of %DFS paths. + +// ///Returns a reference to the NodeMap of the last but one nodes of the +// ///%DFS tree. +// ///\pre \ref run() must be called before using this function. +// const PredNodeMap &predNodeMap() const { return *_predNode;} + + ///Checks if a node is reachable from the root. + + ///Returns \c true if \c v is reachable from the root. + ///\warning The source nodes are inditated as unreached. + ///\pre Either \ref run() or \ref start() + ///must be called before using this function. + /// + bool reached(Node v) { return (*_reached)[v]; } + + ///@} + }; + + ///Default traits class of Dfs function. + + ///Default traits class of Dfs function. + ///\param GR Graph type. + template + struct DfsWizardDefaultTraits + { + ///The graph type the algorithm runs on. + typedef GR Graph; + ///\brief The type of the map that stores the last + ///edges of the %DFS paths. + /// + ///The type of the map that stores the last + ///edges of the %DFS paths. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef NullMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \ref PredMap. + ///\param G is the graph, to which we would like to define the PredMap. + ///\todo The graph alone may be insufficient to initialize + static PredMap *createPredMap(const GR &) + { + return new PredMap(); + } +// ///\brief The type of the map that stores the last but one +// ///nodes of the %DFS paths. +// /// +// ///The type of the map that stores the last but one +// ///nodes of the %DFS paths. +// ///It must meet the \ref concept::WriteMap "WriteMap" concept. +// /// +// typedef NullMap PredNodeMap; +// ///Instantiates a PredNodeMap. + +// ///This function instantiates a \ref PredNodeMap. +// ///\param G is the graph, to which +// ///we would like to define the \ref PredNodeMap +// static PredNodeMap *createPredNodeMap(const GR &G) +// { +// return new PredNodeMap(); +// } + + ///The type of the map that indicates which nodes are processed. + + ///The type of the map that indicates which nodes are processed. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \ref ProcessedMap. + ///\param G is the graph, to which + ///we would like to define the \ref ProcessedMap + static ProcessedMap *createProcessedMap(const GR &) + { + return new ProcessedMap(); + } + ///The type of the map that indicates which nodes are reached. + + ///The type of the map that indicates which nodes are reached. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + ///\todo named parameter to set this type, function to read and write. + typedef typename Graph::template NodeMap ReachedMap; + ///Instantiates a ReachedMap. + + ///This function instantiates a \ref ReachedMap. + ///\param G is the graph, to which + ///we would like to define the \ref ReachedMap. + static ReachedMap *createReachedMap(const GR &G) + { + return new ReachedMap(G); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef NullMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param G is the graph, to which we would like to define the \ref DistMap + static DistMap *createDistMap(const GR &) + { + return new DistMap(); + } + }; + + /// Default traits used by \ref DfsWizard + + /// To make it easier to use Dfs algorithm + ///we have created a wizard class. + /// This \ref DfsWizard class needs default traits, + ///as well as the \ref Dfs class. + /// The \ref DfsWizardBase is a class to be the default traits of the + /// \ref DfsWizard class. + template + class DfsWizardBase : public DfsWizardDefaultTraits + { + + typedef DfsWizardDefaultTraits Base; + protected: + /// Type of the nodes in the graph. + typedef typename Base::Graph::Node Node; + + /// Pointer to the underlying graph. + void *_g; + ///Pointer to the map of reached nodes. + void *_reached; + ///Pointer to the map of processed nodes. + void *_processed; + ///Pointer to the map of predecessors edges. + void *_pred; +// ///Pointer to the map of predecessors nodes. +// void *_predNode; + ///Pointer to the map of distances. + void *_dist; + ///Pointer to the source node. + Node _source; + + public: + /// Constructor. + + /// This constructor does not require parameters, therefore it initiates + /// all of the attributes to default values (0, INVALID). + DfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), +// _predNode(0), + _dist(0), _source(INVALID) {} + + /// Constructor. + + /// This constructor requires some parameters, + /// listed in the parameters list. + /// Others are initiated to 0. + /// \param g is the initial value of \ref _g + /// \param s is the initial value of \ref _source + DfsWizardBase(const GR &g, Node s=INVALID) : + _g((void *)&g), _reached(0), _processed(0), _pred(0), +// _predNode(0), + _dist(0), _source(s) {} + + }; + + /// A class to make the usage of Dfs algorithm easier + + /// This class is created to make it easier to use Dfs algorithm. + /// It uses the functions and features of the plain \ref Dfs, + /// but it is much simpler to use it. + /// + /// Simplicity means that the way to change the types defined + /// in the traits class is based on functions that returns the new class + /// and not on templatable built-in classes. + /// When using the plain \ref Dfs + /// the new class with the modified type comes from + /// the original class by using the :: + /// operator. In the case of \ref DfsWizard only + /// a function have to be called and it will + /// return the needed class. + /// + /// It does not have own \ref run method. When its \ref run method is called + /// it initiates a plain \ref Dfs class, and calls the \ref Dfs::run + /// method of it. + template + class DfsWizard : public TR + { + typedef TR Base; + + ///The type of the underlying graph. + typedef typename TR::Graph Graph; + //\e + typedef typename Graph::Node Node; + //\e + typedef typename Graph::NodeIt NodeIt; + //\e + typedef typename Graph::Edge Edge; + //\e + typedef typename Graph::OutEdgeIt OutEdgeIt; + + ///\brief The type of the map that stores + ///the reached nodes + typedef typename TR::ReachedMap ReachedMap; + ///\brief The type of the map that stores + ///the processed nodes + typedef typename TR::ProcessedMap ProcessedMap; + ///\brief The type of the map that stores the last + ///edges of the %DFS paths. + typedef typename TR::PredMap PredMap; +// ///\brief The type of the map that stores the last but one +// ///nodes of the %DFS paths. +// typedef typename TR::PredNodeMap PredNodeMap; + ///The type of the map that stores the dists of the nodes. + typedef typename TR::DistMap DistMap; + +public: + /// Constructor. + DfsWizard() : TR() {} + + /// Constructor that requires parameters. + + /// Constructor that requires parameters. + /// These parameters will be the default values for the traits class. + DfsWizard(const Graph &g, Node s=INVALID) : + TR(g,s) {} + + ///Copy constructor + DfsWizard(const TR &b) : TR(b) {} + + ~DfsWizard() {} + + ///Runs Dfs algorithm from a given node. + + ///Runs Dfs algorithm from a given node. + ///The node can be given by the \ref source function. + void run() + { + if(Base::_source==INVALID) throw UninitializedParameter(); + Dfs alg(*(Graph*)Base::_g); + if(Base::_reached) alg.reachedMap(*(ReachedMap*)Base::_reached); + if(Base::_processed) alg.processedMap(*(ProcessedMap*)Base::_processed); + if(Base::_pred) alg.predMap(*(PredMap*)Base::_pred); +// if(Base::_predNode) alg.predNodeMap(*(PredNodeMap*)Base::_predNode); + if(Base::_dist) alg.distMap(*(DistMap*)Base::_dist); + alg.run(Base::_source); + } + + ///Runs Dfs algorithm from the given node. + + ///Runs Dfs algorithm from the given node. + ///\param s is the given source. + void run(Node s) + { + Base::_source=s; + run(); + } + + template + struct DefPredMapBase : public Base { + typedef T PredMap; + static PredMap *createPredMap(const Graph &) { return 0; }; + DefPredMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting PredMap type + /// + /// \ref named-templ-param "Named parameter" + ///function for setting PredMap type + /// + template + DfsWizard > predMap(const T &t) + { + Base::_pred=(void *)&t; + return DfsWizard >(*this); + } + + + template + struct DefReachedMapBase : public Base { + typedef T ReachedMap; + static ReachedMap *createReachedMap(const Graph &) { return 0; }; + DefReachedMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting ReachedMap + /// + /// \ref named-templ-param "Named parameter" + ///function for setting ReachedMap + /// + template + DfsWizard > reachedMap(const T &t) + { + Base::_pred=(void *)&t; + return DfsWizard >(*this); + } + + + template + struct DefProcessedMapBase : public Base { + typedef T ProcessedMap; + static ProcessedMap *createProcessedMap(const Graph &) { return 0; }; + DefProcessedMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting ProcessedMap + /// + /// \ref named-templ-param "Named parameter" + ///function for setting ProcessedMap + /// + template + DfsWizard > processedMap(const T &t) + { + Base::_pred=(void *)&t; + return DfsWizard >(*this); + } + + +// template +// struct DefPredNodeMapBase : public Base { +// typedef T PredNodeMap; +// static PredNodeMap *createPredNodeMap(const Graph &G) { return 0; }; +// DefPredNodeMapBase(const TR &b) : TR(b) {} +// }; + +// ///\brief \ref named-templ-param "Named parameter" +// ///function for setting PredNodeMap type +// /// +// /// \ref named-templ-param "Named parameter" +// ///function for setting PredNodeMap type +// /// +// template +// DfsWizard > predNodeMap(const T &t) +// { +// Base::_predNode=(void *)&t; +// return DfsWizard >(*this); +// } + + template + struct DefDistMapBase : public Base { + typedef T DistMap; + static DistMap *createDistMap(const Graph &) { return 0; }; + DefDistMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + /// \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + template + DfsWizard > distMap(const T &t) + { + Base::_dist=(void *)&t; + return DfsWizard >(*this); + } + + /// Sets the source node, from which the Dfs algorithm runs. + + /// Sets the source node, from which the Dfs algorithm runs. + /// \param s is the source node. + DfsWizard &source(Node s) + { + Base::_source=s; + return *this; + } + + }; + + ///Function type interface for Dfs algorithm. + + /// \ingroup flowalgs + ///Function type interface for Dfs algorithm. + /// + ///This function also has several + ///\ref named-templ-func-param "named parameters", + ///they are declared as the members of class \ref DfsWizard. + ///The following + ///example shows how to use these parameters. + ///\code + /// dfs(g,source).predMap(preds).run(); + ///\endcode + ///\warning Don't forget to put the \ref DfsWizard::run() "run()" + ///to the end of the parameter list. + ///\sa DfsWizard + ///\sa Dfs + template + DfsWizard > + dfs(const GR &g,typename GR::Node s=INVALID) + { + return DfsWizard >(g,s); + } + +} //END OF NAMESPACE LEMON + +#endif + diff -r d8475431bbbb -r 8e85e6bbefdf lemon/dijkstra.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/dijkstra.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,1074 @@ +/* -*- C++ -*- + * lemon/dijkstra.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_DIJKSTRA_H +#define LEMON_DIJKSTRA_H + +///\ingroup flowalgs +///\file +///\brief Dijkstra algorithm. +/// +///\todo getPath() should be implemented! (also for BFS and DFS) + +#include +#include +#include +#include +#include + +namespace lemon { + + + + ///Default traits class of Dijkstra class. + + ///Default traits class of Dijkstra class. + ///\param GR Graph type. + ///\param LM Type of length map. + template + struct DijkstraDefaultTraits + { + ///The graph type the algorithm runs on. + typedef GR Graph; + ///The type of the map that stores the edge lengths. + + ///The type of the map that stores the edge lengths. + ///It must meet the \ref concept::ReadMap "ReadMap" concept. + typedef LM LengthMap; + //The type of the length of the edges. + typedef typename LM::Value Value; + ///The heap type used by Dijkstra algorithm. + + ///The heap type used by Dijkstra algorithm. + /// + ///\sa BinHeap + ///\sa Dijkstra + typedef BinHeap, + std::less > Heap; + + ///\brief The type of the map that stores the last + ///edges of the shortest paths. + /// + ///The type of the map that stores the last + ///edges of the shortest paths. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef typename Graph::template NodeMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \ref PredMap. + ///\param G is the graph, to which we would like to define the PredMap. + ///\todo The graph alone may be insufficient for the initialization + static PredMap *createPredMap(const GR &G) + { + return new PredMap(G); + } +// ///\brief The type of the map that stores the last but one +// ///nodes of the shortest paths. +// /// +// ///The type of the map that stores the last but one +// ///nodes of the shortest paths. +// ///It must meet the \ref concept::WriteMap "WriteMap" concept. +// /// +// typedef NullMap PredNodeMap; +// ///Instantiates a PredNodeMap. + +// ///This function instantiates a \ref PredNodeMap. +// ///\param G is the graph, to which +// ///we would like to define the \ref PredNodeMap +// static PredNodeMap *createPredNodeMap(const GR &G) +// { +// return new PredNodeMap(); +// } + + ///The type of the map that stores whether a nodes is processed. + + ///The type of the map that stores whether a nodes is processed. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + ///By default it is a NullMap. + ///\todo If it is set to a real map, + ///Dijkstra::processed() should read this. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \ref ProcessedMap. + ///\param G is the graph, to which + ///we would like to define the \ref ProcessedMap + static ProcessedMap *createProcessedMap(const GR &) + { + return new ProcessedMap(); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef typename Graph::template NodeMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param G is the graph, to which we would like to define the \ref DistMap + static DistMap *createDistMap(const GR &G) + { + return new DistMap(G); + } + }; + + ///%Dijkstra algorithm class. + + /// \ingroup flowalgs + ///This class provides an efficient implementation of %Dijkstra algorithm. + ///The edge lengths are passed to the algorithm using a + ///\ref concept::ReadMap "ReadMap", + ///so it is easy to change it to any kind of length. + /// + ///The type of the length is determined by the + ///\ref concept::ReadMap::Value "Value" of the length map. + /// + ///It is also possible to change the underlying priority heap. + /// + ///\param GR The graph type the algorithm runs on. The default value + ///is \ref ListGraph. The value of GR is not used directly by + ///Dijkstra, it is only passed to \ref DijkstraDefaultTraits. + ///\param LM This read-only EdgeMap determines the lengths of the + ///edges. It is read once for each edge, so the map may involve in + ///relatively time consuming process to compute the edge length if + ///it is necessary. The default map type is \ref + ///concept::StaticGraph::EdgeMap "Graph::EdgeMap". The value + ///of LM is not used directly by Dijkstra, it is only passed to \ref + ///DijkstraDefaultTraits. \param TR Traits class to set + ///various data types used by the algorithm. The default traits + ///class is \ref DijkstraDefaultTraits + ///"DijkstraDefaultTraits". See \ref + ///DijkstraDefaultTraits for the documentation of a Dijkstra traits + ///class. + /// + ///\author Jacint Szabo and Alpar Juttner + ///\todo A compare object would be nice. + +#ifdef DOXYGEN + template +#else + template , + typename TR=DijkstraDefaultTraits > +#endif + class Dijkstra { + public: + /** + * \brief \ref Exception for uninitialized parameters. + * + * This error represents problems in the initialization + * of the parameters of the algorithms. + */ + class UninitializedParameter : public lemon::UninitializedParameter { + public: + virtual const char* exceptionName() const { + return "lemon::Dijkstra::UninitializedParameter"; + } + }; + + typedef TR Traits; + ///The type of the underlying graph. + typedef typename TR::Graph Graph; + ///\e + typedef typename Graph::Node Node; + ///\e + typedef typename Graph::NodeIt NodeIt; + ///\e + typedef typename Graph::Edge Edge; + ///\e + typedef typename Graph::OutEdgeIt OutEdgeIt; + + ///The type of the length of the edges. + typedef typename TR::LengthMap::Value Value; + ///The type of the map that stores the edge lengths. + typedef typename TR::LengthMap LengthMap; + ///\brief The type of the map that stores the last + ///edges of the shortest paths. + typedef typename TR::PredMap PredMap; +// ///\brief The type of the map that stores the last but one +// ///nodes of the shortest paths. +// typedef typename TR::PredNodeMap PredNodeMap; + ///The type of the map indicating if a node is processed. + typedef typename TR::ProcessedMap ProcessedMap; + ///The type of the map that stores the dists of the nodes. + typedef typename TR::DistMap DistMap; + ///The heap type used by the dijkstra algorithm. + typedef typename TR::Heap Heap; + private: + /// Pointer to the underlying graph. + const Graph *G; + /// Pointer to the length map + const LengthMap *length; + ///Pointer to the map of predecessors edges. + PredMap *_pred; + ///Indicates if \ref _pred is locally allocated (\c true) or not. + bool local_pred; +// ///Pointer to the map of predecessors nodes. +// PredNodeMap *_predNode; +// ///Indicates if \ref _predNode is locally allocated (\c true) or not. +// bool local_predNode; + ///Pointer to the map of distances. + DistMap *_dist; + ///Indicates if \ref _dist is locally allocated (\c true) or not. + bool local_dist; + ///Pointer to the map of processed status of the nodes. + ProcessedMap *_processed; + ///Indicates if \ref _processed is locally allocated (\c true) or not. + bool local_processed; + +// ///The source node of the last execution. +// Node source; + + ///Creates the maps if necessary. + + ///\todo Error if \c G or are \c NULL. What about \c length? + ///\todo Better memory allocation (instead of new). + void create_maps() + { + if(!_pred) { + local_pred = true; + _pred = Traits::createPredMap(*G); + } +// if(!_predNode) { +// local_predNode = true; +// _predNode = Traits::createPredNodeMap(*G); +// } + if(!_dist) { + local_dist = true; + _dist = Traits::createDistMap(*G); + } + if(!_processed) { + local_processed = true; + _processed = Traits::createProcessedMap(*G); + } + } + + public : + + ///\name Named template parameters + + ///@{ + + template + struct DefPredMapTraits : public Traits { + typedef T PredMap; + static PredMap *createPredMap(const Graph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting PredMap type + + ///\ref named-templ-param "Named parameter" for setting PredMap type + /// + template + class DefPredMap : public Dijkstra< Graph, + LengthMap, + DefPredMapTraits > { }; + +// template +// struct DefPredNodeMapTraits : public Traits { +// typedef T PredNodeMap; +// static PredNodeMap *createPredNodeMap(const Graph &G) +// { +// throw UninitializedParameter(); +// } +// }; +// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type + +// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type +// /// +// template +// class DefPredNodeMap : public Dijkstra< Graph, +// LengthMap, +// DefPredNodeMapTraits > { }; + + template + struct DefDistMapTraits : public Traits { + typedef T DistMap; + static DistMap *createDistMap(const Graph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting DistMap type + + ///\ref named-templ-param "Named parameter" for setting DistMap type + /// + template + class DefDistMap : public Dijkstra< Graph, + LengthMap, + DefDistMapTraits > { }; + + template + struct DefProcessedMapTraits : public Traits { + typedef T ProcessedMap; + static ProcessedMap *createProcessedMap(const Graph &G) + { + throw UninitializedParameter(); + } + }; + ///\ref named-templ-param "Named parameter" for setting ProcessedMap type + + ///\ref named-templ-param "Named parameter" for setting ProcessedMap type + /// + template + class DefProcessedMap : public Dijkstra< Graph, + LengthMap, + DefProcessedMapTraits > { }; + + struct DefGraphProcessedMapTraits : public Traits { + typedef typename Graph::template NodeMap ProcessedMap; + static ProcessedMap *createProcessedMap(const Graph &G) + { + return new ProcessedMap(G); + } + }; + ///\brief \ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Graph::NodeMap. + /// + ///\ref named-templ-param "Named parameter" + ///for setting the ProcessedMap type to be Graph::NodeMap. + ///If you don't set it explicitely, it will be automatically allocated. + template + class DefProcessedMapToBeDefaultMap : + public Dijkstra< Graph, + LengthMap, + DefGraphProcessedMapTraits> { }; + + ///@} + + + private: + typename Graph::template NodeMap _heap_map; + Heap _heap; + public: + + ///Constructor. + + ///\param _G the graph the algorithm will run on. + ///\param _length the length map used by the algorithm. + Dijkstra(const Graph& _G, const LengthMap& _length) : + G(&_G), length(&_length), + _pred(NULL), local_pred(false), +// _predNode(NULL), local_predNode(false), + _dist(NULL), local_dist(false), + _processed(NULL), local_processed(false), + _heap_map(*G,-1),_heap(_heap_map) + { } + + ///Destructor. + ~Dijkstra() + { + if(local_pred) delete _pred; +// if(local_predNode) delete _predNode; + if(local_dist) delete _dist; + if(local_processed) delete _processed; + } + + ///Sets the length map. + + ///Sets the length map. + ///\return (*this) + Dijkstra &lengthMap(const LengthMap &m) + { + length = &m; + return *this; + } + + ///Sets the map storing the predecessor edges. + + ///Sets the map storing the predecessor edges. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dijkstra &predMap(PredMap &m) + { + if(local_pred) { + delete _pred; + local_pred=false; + } + _pred = &m; + return *this; + } + +// ///Sets the map storing the predecessor nodes. + +// ///Sets the map storing the predecessor nodes. +// ///If you don't use this function before calling \ref run(), +// ///it will allocate one. The destuctor deallocates this +// ///automatically allocated map, of course. +// ///\return (*this) +// Dijkstra &predNodeMap(PredNodeMap &m) +// { +// if(local_predNode) { +// delete _predNode; +// local_predNode=false; +// } +// _predNode = &m; +// return *this; +// } + + ///Sets the map storing the distances calculated by the algorithm. + + ///Sets the map storing the distances calculated by the algorithm. + ///If you don't use this function before calling \ref run(), + ///it will allocate one. The destuctor deallocates this + ///automatically allocated map, of course. + ///\return (*this) + Dijkstra &distMap(DistMap &m) + { + if(local_dist) { + delete _dist; + local_dist=false; + } + _dist = &m; + return *this; + } + + private: + void finalizeNodeData(Node v,Value dst) + { + _processed->set(v,true); + _dist->set(v, dst); +// if((*_pred)[v]!=INVALID) +// _predNode->set(v,G->source((*_pred)[v])); ///\todo What to do? + } + + public: + ///\name Execution control + ///The simplest way to execute the algorithm is to use + ///one of the member functions called \c run(...). + ///\n + ///If you need more control on the execution, + ///first you must call \ref init(), then you can add several source nodes + ///with \ref addSource(). + ///Finally \ref start() will perform the actual path + ///computation. + + ///@{ + + ///Initializes the internal data structures. + + ///Initializes the internal data structures. + /// + ///\todo _heap_map's type could also be in the traits class. + ///\todo The heaps should be able to make themselves empty directly. + void init() + { + create_maps(); + while(!_heap.empty()) _heap.pop(); + for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { + _pred->set(u,INVALID); +// _predNode->set(u,INVALID); + _processed->set(u,false); + _heap_map.set(u,Heap::PRE_HEAP); + } + } + + ///Adds a new source node. + + ///Adds a new source node to the priority heap. + /// + ///The optional second parameter is the initial distance of the node. + /// + ///It checks if the node has already been added to the heap and + ///It is pushed to the heap only if either it was not in the heap + ///or the shortest path found till then is longer then \c dst. + void addSource(Node s,Value dst=0) + { +// source = s; + if(_heap.state(s) != Heap::IN_HEAP) _heap.push(s,dst); + else if(_heap[s]set(s,INVALID); + } + } + + ///Processes the next node in the priority heap + + ///Processes the next node in the priority heap. + /// + ///\warning The priority heap must not be empty! + void processNextNode() + { + Node v=_heap.top(); + Value oldvalue=_heap[v]; + _heap.pop(); + finalizeNodeData(v,oldvalue); + + for(OutEdgeIt e(*G,v); e!=INVALID; ++e) { + Node w=G->target(e); + switch(_heap.state(w)) { + case Heap::PRE_HEAP: + _heap.push(w,oldvalue+(*length)[e]); + _pred->set(w,e); +// _predNode->set(w,v); + break; + case Heap::IN_HEAP: + if ( oldvalue+(*length)[e] < _heap[w] ) { + _heap.decrease(w, oldvalue+(*length)[e]); + _pred->set(w,e); +// _predNode->set(w,v); + } + break; + case Heap::POST_HEAP: + break; + } + } + } + + ///\brief Returns \c false if there are nodes + ///to be processed in the priority heap + /// + ///Returns \c false if there are nodes + ///to be processed in the priority heap + bool emptyQueue() { return _heap.empty(); } + ///Returns the number of the nodes to be processed in the priority heap + + ///Returns the number of the nodes to be processed in the priority heap + /// + int queueSize() { return _heap.size(); } + + ///Executes the algorithm. + + ///Executes the algorithm. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %Dijkstra algorithm from the root node(s) + ///in order to + ///compute the + ///shortest path to each node. The algorithm computes + ///- The shortest path tree. + ///- The distance of each node from the root(s). + /// + void start() + { + while ( !_heap.empty() ) processNextNode(); + } + + ///Executes the algorithm until \c dest is reached. + + ///Executes the algorithm until \c dest is reached. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///This method runs the %Dijkstra algorithm from the root node(s) + ///in order to + ///compute the + ///shortest path to \c dest. The algorithm computes + ///- The shortest path to \c dest. + ///- The distance of \c dest from the root(s). + /// + void start(Node dest) + { + while ( !_heap.empty() && _heap.top()!=dest ) processNextNode(); + if ( !_heap.empty() ) finalizeNodeData(_heap.top(),_heap.prio()); + } + + ///Executes the algorithm until a condition is met. + + ///Executes the algorithm until a condition is met. + /// + ///\pre init() must be called and at least one node should be added + ///with addSource() before using this function. + /// + ///\param nm must be a bool (or convertible) node map. The algorithm + ///will stop when it reaches a node \c v with nm[v]==true. + template + void start(const NodeBoolMap &nm) + { + while ( !_heap.empty() && !nm[_heap.top()] ) processNextNode(); + if ( !_heap.empty() ) finalizeNodeData(_heap.top(),_heap.prio()); + } + + ///Runs %Dijkstra algorithm from node \c s. + + ///This method runs the %Dijkstra algorithm from a root node \c s + ///in order to + ///compute the + ///shortest path to each node. The algorithm computes + ///- The shortest path tree. + ///- The distance of each node from the root. + /// + ///\note d.run(s) is just a shortcut of the following code. + ///\code + /// d.init(); + /// d.addSource(s); + /// d.start(); + ///\endcode + void run(Node s) { + init(); + addSource(s); + start(); + } + + ///Finds the shortest path between \c s and \c t. + + ///Finds the shortest path between \c s and \c t. + /// + ///\return The length of the shortest s---t path if there exists one, + ///0 otherwise. + ///\note Apart from the return value, d.run(s) is + ///just a shortcut of the following code. + ///\code + /// d.init(); + /// d.addSource(s); + /// d.start(t); + ///\endcode + Value run(Node s,Node t) { + init(); + addSource(s); + start(t); + return (*_pred)[t]==INVALID?0:(*_dist)[t]; + } + + ///@} + + ///\name Query Functions + ///The result of the %Dijkstra algorithm can be obtained using these + ///functions.\n + ///Before the use of these functions, + ///either run() or start() must be called. + + ///@{ + + ///Copies the shortest path to \c t into \c p + + ///This function copies the shortest path to \c t into \c p. + ///If it \c \t is a source itself or unreachable, then it does not + ///alter \c p. + ///\todo Is it the right way to handle unreachable nodes? + ///\return Returns \c true if a path to \c t was actually copied to \c p, + ///\c false otherwise. + ///\sa DirPath + template + bool getPath(P &p,Node t) + { + if(reached(t)) { + p.clear(); + typename P::Builder b(p); + for(b.setStartNode(t);pred(t)!=INVALID;t=predNode(t)) + b.pushFront(pred(t)); + b.commit(); + return true; + } + return false; + } + + ///The distance of a node from the root. + + ///Returns the distance of a node from the root. + ///\pre \ref run() must be called before using this function. + ///\warning If node \c v in unreachable from the root the return value + ///of this funcion is undefined. + Value dist(Node v) const { return (*_dist)[v]; } + + ///Returns the 'previous edge' of the shortest path tree. + + ///For a node \c v it returns the 'previous edge' of the shortest path tree, + ///i.e. it returns the last edge of a shortest path from the root to \c + ///v. It is \ref INVALID + ///if \c v is unreachable from the root or if \c v=s. The + ///shortest path tree used here is equal to the shortest path tree used in + ///\ref predNode(Node v). \pre \ref run() must be called before using + ///this function. + ///\todo predEdge could be a better name. + Edge pred(Node v) const { return (*_pred)[v]; } + + ///Returns the 'previous node' of the shortest path tree. + + ///For a node \c v it returns the 'previous node' of the shortest path tree, + ///i.e. it returns the last but one node from a shortest path from the + ///root to \c /v. It is INVALID if \c v is unreachable from the root or if + ///\c v=s. The shortest path tree used here is equal to the shortest path + ///tree used in \ref pred(Node v). \pre \ref run() must be called before + ///using this function. + Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID: + G->source((*_pred)[v]); } + + ///Returns a reference to the NodeMap of distances. + + ///Returns a reference to the NodeMap of distances. \pre \ref run() must + ///be called before using this function. + const DistMap &distMap() const { return *_dist;} + + ///Returns a reference to the shortest path tree map. + + ///Returns a reference to the NodeMap of the edges of the + ///shortest path tree. + ///\pre \ref run() must be called before using this function. + const PredMap &predMap() const { return *_pred;} + +// ///Returns a reference to the map of nodes of shortest paths. + +// ///Returns a reference to the NodeMap of the last but one nodes of the +// ///shortest path tree. +// ///\pre \ref run() must be called before using this function. +// const PredNodeMap &predNodeMap() const { return *_predNode;} + + ///Checks if a node is reachable from the root. + + ///Returns \c true if \c v is reachable from the root. + ///\warning The source nodes are inditated as unreached. + ///\pre \ref run() must be called before using this function. + /// + bool reached(Node v) { return _heap_map[v]!=Heap::PRE_HEAP; } + + ///@} + }; + + + + + + ///Default traits class of Dijkstra function. + + ///Default traits class of Dijkstra function. + ///\param GR Graph type. + ///\param LM Type of length map. + template + struct DijkstraWizardDefaultTraits + { + ///The graph type the algorithm runs on. + typedef GR Graph; + ///The type of the map that stores the edge lengths. + + ///The type of the map that stores the edge lengths. + ///It must meet the \ref concept::ReadMap "ReadMap" concept. + typedef LM LengthMap; + //The type of the length of the edges. + typedef typename LM::Value Value; + ///The heap type used by Dijkstra algorithm. + + ///The heap type used by Dijkstra algorithm. + /// + ///\sa BinHeap + ///\sa Dijkstra + typedef BinHeap, + std::less > Heap; + + ///\brief The type of the map that stores the last + ///edges of the shortest paths. + /// + ///The type of the map that stores the last + ///edges of the shortest paths. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef NullMap PredMap; + ///Instantiates a PredMap. + + ///This function instantiates a \ref PredMap. + ///\param G is the graph, to which we would like to define the PredMap. + ///\todo The graph alone may be insufficient for the initialization + static PredMap *createPredMap(const GR &) + { + return new PredMap(); + } + ///The type of the map that stores whether a nodes is processed. + + ///The type of the map that stores whether a nodes is processed. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + ///By default it is a NullMap. + ///\todo If it is set to a real map, + ///Dijkstra::processed() should read this. + ///\todo named parameter to set this type, function to read and write. + typedef NullMap ProcessedMap; + ///Instantiates a ProcessedMap. + + ///This function instantiates a \ref ProcessedMap. + ///\param G is the graph, to which + ///we would like to define the \ref ProcessedMap + static ProcessedMap *createProcessedMap(const GR &) + { + return new ProcessedMap(); + } + ///The type of the map that stores the dists of the nodes. + + ///The type of the map that stores the dists of the nodes. + ///It must meet the \ref concept::WriteMap "WriteMap" concept. + /// + typedef NullMap DistMap; + ///Instantiates a DistMap. + + ///This function instantiates a \ref DistMap. + ///\param G is the graph, to which we would like to define the \ref DistMap + static DistMap *createDistMap(const GR &) + { + return new DistMap(); + } + }; + + /// Default traits used by \ref DijkstraWizard + + /// To make it easier to use Dijkstra algorithm + ///we have created a wizard class. + /// This \ref DijkstraWizard class needs default traits, + ///as well as the \ref Dijkstra class. + /// The \ref DijkstraWizardBase is a class to be the default traits of the + /// \ref DijkstraWizard class. + /// \todo More named parameters are required... + template + class DijkstraWizardBase : public DijkstraWizardDefaultTraits + { + + typedef DijkstraWizardDefaultTraits Base; + protected: + /// Type of the nodes in the graph. + typedef typename Base::Graph::Node Node; + + /// Pointer to the underlying graph. + void *_g; + /// Pointer to the length map + void *_length; + ///Pointer to the map of predecessors edges. + void *_pred; +// ///Pointer to the map of predecessors nodes. +// void *_predNode; + ///Pointer to the map of distances. + void *_dist; + ///Pointer to the source node. + Node _source; + + public: + /// Constructor. + + /// This constructor does not require parameters, therefore it initiates + /// all of the attributes to default values (0, INVALID). + DijkstraWizardBase() : _g(0), _length(0), _pred(0), +// _predNode(0), + _dist(0), _source(INVALID) {} + + /// Constructor. + + /// This constructor requires some parameters, + /// listed in the parameters list. + /// Others are initiated to 0. + /// \param g is the initial value of \ref _g + /// \param l is the initial value of \ref _length + /// \param s is the initial value of \ref _source + DijkstraWizardBase(const GR &g,const LM &l, Node s=INVALID) : + _g((void *)&g), _length((void *)&l), _pred(0), +// _predNode(0), + _dist(0), _source(s) {} + + }; + + /// A class to make the usage of Dijkstra algorithm easier + + /// This class is created to make it easier to use Dijkstra algorithm. + /// It uses the functions and features of the plain \ref Dijkstra, + /// but it is much simpler to use it. + /// + /// Simplicity means that the way to change the types defined + /// in the traits class is based on functions that returns the new class + /// and not on templatable built-in classes. + /// When using the plain \ref Dijkstra + /// the new class with the modified type comes from + /// the original class by using the :: + /// operator. In the case of \ref DijkstraWizard only + /// a function have to be called and it will + /// return the needed class. + /// + /// It does not have own \ref run method. When its \ref run method is called + /// it initiates a plain \ref Dijkstra class, and calls the \ref Dijkstra::run + /// method of it. + template + class DijkstraWizard : public TR + { + typedef TR Base; + + ///The type of the underlying graph. + typedef typename TR::Graph Graph; + //\e + typedef typename Graph::Node Node; + //\e + typedef typename Graph::NodeIt NodeIt; + //\e + typedef typename Graph::Edge Edge; + //\e + typedef typename Graph::OutEdgeIt OutEdgeIt; + + ///The type of the map that stores the edge lengths. + typedef typename TR::LengthMap LengthMap; + ///The type of the length of the edges. + typedef typename LengthMap::Value Value; + ///\brief The type of the map that stores the last + ///edges of the shortest paths. + typedef typename TR::PredMap PredMap; +// ///\brief The type of the map that stores the last but one +// ///nodes of the shortest paths. +// typedef typename TR::PredNodeMap PredNodeMap; + ///The type of the map that stores the dists of the nodes. + typedef typename TR::DistMap DistMap; + + ///The heap type used by the dijkstra algorithm. + typedef typename TR::Heap Heap; +public: + /// Constructor. + DijkstraWizard() : TR() {} + + /// Constructor that requires parameters. + + /// Constructor that requires parameters. + /// These parameters will be the default values for the traits class. + DijkstraWizard(const Graph &g,const LengthMap &l, Node s=INVALID) : + TR(g,l,s) {} + + ///Copy constructor + DijkstraWizard(const TR &b) : TR(b) {} + + ~DijkstraWizard() {} + + ///Runs Dijkstra algorithm from a given node. + + ///Runs Dijkstra algorithm from a given node. + ///The node can be given by the \ref source function. + void run() + { + if(Base::_source==INVALID) throw UninitializedParameter(); + Dijkstra + dij(*(Graph*)Base::_g,*(LengthMap*)Base::_length); + if(Base::_pred) dij.predMap(*(PredMap*)Base::_pred); +// if(Base::_predNode) Dij.predNodeMap(*(PredNodeMap*)Base::_predNode); + if(Base::_dist) dij.distMap(*(DistMap*)Base::_dist); + dij.run(Base::_source); + } + + ///Runs Dijkstra algorithm from the given node. + + ///Runs Dijkstra algorithm from the given node. + ///\param s is the given source. + void run(Node s) + { + Base::_source=s; + run(); + } + + template + struct DefPredMapBase : public Base { + typedef T PredMap; + static PredMap *createPredMap(const Graph &) { return 0; }; + DefPredMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting PredMap type + /// + /// \ref named-templ-param "Named parameter" + ///function for setting PredMap type + /// + template + DijkstraWizard > predMap(const T &t) + { + Base::_pred=(void *)&t; + return DijkstraWizard >(*this); + } + + +// template +// struct DefPredNodeMapBase : public Base { +// typedef T PredNodeMap; +// static PredNodeMap *createPredNodeMap(const Graph &G) { return 0; }; +// DefPredNodeMapBase(const TR &b) : TR(b) {} +// }; + +// ///\brief \ref named-templ-param "Named parameter" +// ///function for setting PredNodeMap type +// /// +// /// \ref named-templ-param "Named parameter" +// ///function for setting PredNodeMap type +// /// +// template +// DijkstraWizard > predNodeMap(const T &t) +// { +// Base::_predNode=(void *)&t; +// return DijkstraWizard >(*this); +// } + + template + struct DefDistMapBase : public Base { + typedef T DistMap; + static DistMap *createDistMap(const Graph &) { return 0; }; + DefDistMapBase(const TR &b) : TR(b) {} + }; + + ///\brief \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + /// \ref named-templ-param "Named parameter" + ///function for setting DistMap type + /// + template + DijkstraWizard > distMap(const T &t) + { + Base::_dist=(void *)&t; + return DijkstraWizard >(*this); + } + + /// Sets the source node, from which the Dijkstra algorithm runs. + + /// Sets the source node, from which the Dijkstra algorithm runs. + /// \param s is the source node. + DijkstraWizard &source(Node s) + { + Base::_source=s; + return *this; + } + + }; + + ///Function type interface for Dijkstra algorithm. + + /// \ingroup flowalgs + ///Function type interface for Dijkstra algorithm. + /// + ///This function also has several + ///\ref named-templ-func-param "named parameters", + ///they are declared as the members of class \ref DijkstraWizard. + ///The following + ///example shows how to use these parameters. + ///\code + /// dijkstra(g,length,source).predMap(preds).run(); + ///\endcode + ///\warning Don't forget to put the \ref DijkstraWizard::run() "run()" + ///to the end of the parameter list. + ///\sa DijkstraWizard + ///\sa Dijkstra + template + DijkstraWizard > + dijkstra(const GR &g,const LM &l,typename GR::Node s=INVALID) + { + return DijkstraWizard >(g,l,s); + } + +} //END OF NAMESPACE LEMON + +#endif + diff -r d8475431bbbb -r 8e85e6bbefdf lemon/dimacs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/dimacs.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,228 @@ +/* -*- C++ -*- + * lemon/dimacs.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_DIMACS_H +#define LEMON_DIMACS_H + +#include +#include +#include +#include +#include + +/// \ingroup dimacs_group +/// \file +/// \brief Dimacs file format reader. + +namespace lemon { + + /// + ///@defgroup dimacs_group DIMACS format + ///\brief Read and write files in DIMACS format + /// + ///Tools to read a graph from or write it to a file in DIMACS format + ///data + ///\ingroup io_group + + /// \addtogroup dimacs_group + /// @{ + + /// Dimacs min cost flow reader function. + + /// This function reads a min cost flow instance from dimacs format, + /// i.e. from dimacs files having a line starting with + /// \code + /// p "min" + /// \endcode + /// At the beginning \c g is cleared by \c g.clear(). The edge + /// capacities are written to \c capacity, \c s and \c t are set to + /// the source and the target nodes resp. and the cost of the edges + /// are written to \c cost. + /// + /// \author Marton Makai + template + void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity, + typename Graph::Node &s, typename Graph::Node &t, + CostMap& cost) { + g.clear(); + typename CapacityMap::Value _cap; + typename CostMap::Value _cost; + char d; + std::string problem; + char c; + int i, j; + std::string str; + int n, m; + typename Graph::Edge e; + std::vector nodes; + while (is>>c) { + switch (c) { + case 'c': //comment + getline(is, str); + break; + case 'p': //problem definition + is >> problem >> n >> m; + getline(is, str); + nodes.resize(n+1); + for (int k=1; k<=n; ++k) nodes[k]=g.addNode(); + break; + case 'n': //node definition + if (problem=="sp") { //shortest path problem + is >> i; + getline(is, str); + s=nodes[i]; + } + if (problem=="max" || problem=="min") { //((max) or (min cost)) flow problem + is >> i >> d; + getline(is, str); + if (d=='s') s=nodes[i]; + if (d=='t') t=nodes[i]; + } + break; + case 'a': + if ( problem == "max" || problem == "sp") { + is >> i >> j >> _cap; + getline(is, str); + e=g.addEdge(nodes[i], nodes[j]); + //capacity.update(); + capacity.set(e, _cap); + } else { + if ( problem == "min" ) { + is >> i >> j >> _cap >> _cost; + getline(is, str); + e=g.addEdge(nodes[i], nodes[j]); + //capacity.update(); + capacity.set(e, _cap); + //cost.update(); + cost.set(e, _cost); + } else { + is >> i >> j; + getline(is, str); + g.addEdge(nodes[i], nodes[j]); + } + } + break; + } + } + } + + + /// Dimacs max flow reader function. + + /// This function reads a max flow instance from dimacs format, + /// i.e. from dimacs files having a line starting with + /// \code + /// p "max" + /// \endcode + ///At the beginning \c g is cleared by \c g.clear(). The + /// edge capacities are written to \c capacity and \c s and \c t are + /// set to the source and the target nodes. + /// + /// \author Marton Makai + template + void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity, + typename Graph::Node &s, typename Graph::Node &t) { + NullMap n; + readDimacs(is, g, capacity, s, t, n); + } + + + /// Dimacs shortest path reader function. + + /// This function reads a shortest path instance from dimacs format, + /// i.e. from dimacs files having a line starting with + /// \code + /// p "sp" + /// \endcode + /// At the beginning \c g is cleared by \c g.clear(). The edge + /// capacities are written to \c capacity and \c s is set to the + /// source node. + /// + /// \author Marton Makai + template + void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity, + typename Graph::Node &s) { + NullMap n; + readDimacs(is, g, capacity, s, s, n); + } + + + /// Dimacs capacitated graph reader function. + + /// This function reads an edge capacitated graph instance from + /// dimacs format. At the beginning \c g is cleared by \c g.clear() + /// and the edge capacities are written to \c capacity. + /// + /// \author Marton Makai + template + void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity) { + typename Graph::Node u; + NullMap n; + readDimacs(is, g, capacity, u, u, n); + } + + + /// Dimacs plain graph reader function. + + /// This function reads a graph without any designated nodes and + /// maps from dimacs format, i.e. from dimacs files having a line + /// starting with + /// \code + /// p "mat" + /// \endcode + /// At the beginning \c g is cleared + /// by \c g.clear(). + /// + /// \author Marton Makai + template + void readDimacs(std::istream& is, Graph &g) { + typename Graph::Node u; + NullMap n; + readDimacs(is, g, n, u, u, n); + } + + + + + /// write matching problem + template + void writeDimacs(std::ostream& os, const Graph &g) { + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::EdgeIt EdgeIt; + + typename Graph::template NodeMap nodes(g); + + os << "c matching problem" << std::endl; + + int i=1; + for(NodeIt v(g); v!=INVALID; ++v) { + nodes.set(v, i); + ++i; + } + + os << "p mat " << g.nodeNum() << " " << g.edgeNum() << std::endl; + + for(EdgeIt e(g); e!=INVALID; ++e) { + os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)] << std::endl; + } + + } + + /// @} + +} //namespace lemon + +#endif //LEMON_DIMACS_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/error.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/error.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,539 @@ +/* -*- C++ -*- + * lemon/error.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi + * Kutatocsoport (Egervary Research Group on Combinatorial Optimization, + * EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_ERROR_H +#define LEMON_ERROR_H + +//! \ingroup exceptions +//! \file +//! \brief Basic exception classes and error handling. + +#include +#include +#include +#include +#include +#include + +namespace lemon { + + /// \addtogroup exceptions + /// @{ + + /// \brief Exception safe wrapper class. + /// + /// Exception safe wrapper class to implement the members of exceptions. + template + class ExceptionMember { + public: + typedef _Type Type; + + ExceptionMember() throw () { + try { + ptr.reset(new Type()); + } catch (...) {} + } + + ExceptionMember(const Type& type) throw () { + try { + ptr.reset(new Type()); + if (ptr.get() == 0) return; + *ptr = type; + } catch (...) {} + } + + ExceptionMember(const ExceptionMember& copy) throw() { + try { + if (!copy.valid()) return; + ptr.reset(new Type()); + if (ptr.get() == 0) return; + *ptr = copy.get(); + } catch (...) {} + } + + ExceptionMember& operator=(const ExceptionMember& copy) { + if (ptr.get() == 0) return; + try { + if (!copy.valid()) return; + *ptr = copy.get(); + } catch (...) {} + } + + void set(const Type& type) { + if (ptr.get() == 0) return; + try { + *ptr = type; + } catch (...) {} + } + + const Type& get() const { + return *ptr; + } + + bool valid() const { + return ptr.get() != 0; + } + + private: + std::auto_ptr<_Type> ptr; + }; + + /// Exception-safe convenient "error message" class. + + /// Helper class which provides a convenient ostream-like (operator << + /// based) interface to create a string message. Mostly useful in + /// exception classes (therefore the name). + class ErrorMessage { + protected: + ///\e + ///\todo The good solution is boost:shared_ptr... + mutable + std::auto_ptr buf; + + ///\e + bool init() throw() { + try { + buf.reset(new std::ostringstream); + } + catch(...) { + buf.reset(); + } + return buf.get(); + } + + public: + + ///\e + ErrorMessage() throw() { init(); } + + ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { } + + ///\e + ErrorMessage(const char *message) throw() { + init(); + *this << message; + } + + ///\e + ErrorMessage(const std::string &message) throw() { + init(); + *this << message; + } + + ///\e + template + ErrorMessage& operator<<(const T &t) throw() { + if( ! buf.get() ) return *this; + + try { + *buf << t; + } + catch(...) { + buf.reset(); + } + return *this; + } + + ///\e + const char* message() throw() { + if( ! buf.get() ) return 0; + + const char* mes = 0; + try { + mes = buf->str().c_str(); + } + catch(...) {} + return mes; + } + + }; + + /** + * \brief Generic exception class. + * + * Base class for exceptions used in LEMON. + */ + class Exception : public std::exception { + public: + ///\e + Exception() {} + ///\e + virtual ~Exception() throw() {} + + ///\e + virtual const char* exceptionName() const { + return "lemon::Exception"; + } + + ///\e + virtual const char* what() const throw() { + return exceptionName(); + } + }; + + /** + * \brief One of the two main subclasses of \ref Exception. + * + * Logic errors represent problems in the internal logic of a program; + * in theory, these are preventable, and even detectable before the + * program runs (e.g., violations of class invariants). + * + * A typical example for this is \ref UninitializedParameter. + */ + class LogicError : public Exception { + public: + virtual const char* exceptionName() const { + return "lemon::LogicError"; + } + }; + + /** + * \brief \ref Exception for uninitialized parameters. + * + * This error represents problems in the initialization + * of the parameters of the algorithms. + */ + class UninitializedParameter : public LogicError { + public: + virtual const char* exceptionName() const { + return "lemon::UninitializedParameter"; + } + }; + + + /** + * \brief One of the two main subclasses of \ref Exception. + * + * Runtime errors represent problems outside the scope of a program; + * they cannot be easily predicted and can generally only be caught as + * the program executes. + */ + class RuntimeError : public Exception { + public: + virtual const char* exceptionName() const { + return "lemon::RuntimeError"; + } + }; + + ///\e + class RangeError : public RuntimeError { + public: + virtual const char* exceptionName() const { + return "lemon::RangeError"; + } + }; + + ///\e + class IOError : public RuntimeError { + public: + virtual const char* exceptionName() const { + return "lemon::IOError"; + } + }; + + ///\e + class DataFormatError : public IOError { + protected: + ExceptionMember _message; + ExceptionMember _file; + int _line; + + mutable ExceptionMember _message_holder; + public: + + DataFormatError(const DataFormatError &dfe) : + IOError(dfe), _message(dfe._message), _file(dfe._file), + _line(dfe._line) {} + + ///\e + explicit DataFormatError(const char *the_message) + : _message(the_message), _line(0) {} + + ///\e + DataFormatError(const std::string &file_name, int line_num, + const char *the_message) + : _message(the_message), _line(line_num) { file(file_name); } + + ///\e + void line(int line) { _line = line; } + ///\e + void message(const std::string& message) { _message.set(message); } + ///\e + void file(const std::string &file) { _file.set(file); } + + ///\e + int line() const { return _line; } + ///\e + const char* message() const { + if (_message.valid() && !_message.get().empty()) { + return _message.get().c_str(); + } else { + return 0; + } + } + + /// \brief Returns the filename. + /// + /// Returns \e null if the filename was not specified. + const char* file() const { + if (_file.valid() && !_file.get().empty()) { + return _file.get().c_str(); + } else { + return 0; + } + } + + ///\e + virtual const char* what() const throw() { + try { + std::ostringstream ostr; + ostr << exceptionName() << ": "; + if (message()) ostr << message(); + if( file() || line() != 0 ) { + ostr << " ("; + if( file() ) ostr << "in file '" << file() << "'"; + if( file() && line() != 0 ) ostr << " "; + if( line() != 0 ) ostr << "at line " << line(); + ostr << ")"; + } + _message_holder.set(ostr.str()); + } + catch (...) {} + if( _message_holder.valid()) return _message_holder.get().c_str(); + return exceptionName(); + } + + virtual const char* exceptionName() const { + return "lemon::DataFormatError"; + } + + virtual ~DataFormatError() throw() {} + }; + + class IOParameterError : public LogicError { + protected: + ExceptionMember _message; + ExceptionMember _file; + + mutable ExceptionMember _message_holder; + public: + + IOParameterError(const IOParameterError &ile) : + LogicError(ile), _message(ile._message), _file(ile._file) {} + + ///\e + explicit IOParameterError(const char *the_message) + : _message(the_message) {} + + ///\e + IOParameterError(const char *file_name, const char *the_message) + : _message(the_message), _file(file_name) {} + + ///\e + void message(const std::string& message) { _message.set(message); } + ///\e + void file(const std::string &file) { _file.set(file); } + + ///\e + const char* message() const { + if (_message.valid()) { + return _message.get().c_str(); + } else { + return 0; + } + } + + /// \brief Returns the filename. + /// + /// Returns \e null if the filename was not specified. + const char* file() const { + if (_file.valid()) { + return _file.get().c_str(); + } else { + return 0; + } + } + + ///\e + virtual const char* what() const throw() { + try { + std::ostringstream ostr; + if (message()) ostr << message(); + if (file()) ostr << "(when reading file '" << file() << "')"; + _message_holder.set(ostr.str()); + } + catch (...) {} + if( _message_holder.valid() ) return _message_holder.get().c_str(); + return exceptionName(); + } + + virtual const char* exceptionName() const { + return "lemon::IOParameterError"; + } + + virtual ~IOParameterError() throw() {} + }; + + + ///\e + class AssertionFailedError : public LogicError { + protected: + const char *assertion; + const char *file; + int line; + const char *function; + const char *message; + + mutable ExceptionMember _message_holder; + public: + ///\e + AssertionFailedError(const char *_file, int _line, const char *func, + const char *msg, const char *_assertion = 0) : + assertion(_assertion), file(_file), line(_line), function(func), + message(msg) {} + + ///\e + const char* get_assertion() const { return assertion; } + ///\e + const char* get_message() const { return message; } + ///\e + const char* get_file() const { return file; } + ///\e + const char* get_function() const { return function; } + ///\e + int get_line() const { return line; } + + + virtual const char* what() const throw() { + try { + std::ostringstream ostr; + ostr << file << ":" << line << ": "; + if( function ) + ostr << function << ": "; + ostr << message; + if( assertion ) + ostr << " (assertion '" << assertion << "' failed)"; + _message_holder.set(ostr.str()); + return ostr.str().c_str(); + } + catch(...) {} + if( _message_holder.valid() ) return _message_holder.get().c_str(); + return exceptionName(); + } + + virtual const char* exceptionName() const { + return "lemon::AssertionFailedError"; + } + + virtual ~AssertionFailedError() throw() {} + }; + + + /**************** Macros ****************/ + + + inline + void assert_fail(const char *file, int line, const char *func, + const char *message, const char *assertion = 0, + bool do_abort=true) + { + using namespace std; + cerr << file << ":" << line << ": "; + if( func ) + cerr << func << ": "; + cerr << message; + if( assertion ) + cerr << " (assertion '" << assertion << "' failed)"; + cerr << endl; + if(do_abort) + abort(); + } + + inline + void assert_fail_throw(const char *file, int line, const char *func, + const char *message, const char *assertion = 0, + bool = true) + { + throw AssertionFailedError(file, line, func, message, assertion); + } + +/// @} + +} +#endif // LEMON_ERROR_H + +#undef LEMON_ASSERT +#undef LEMON_FIXME + +#ifndef LEMON_ASSERT_ABORT +# define LEMON_ASSERT_ABORT 1 +#endif + +#ifndef LEMON_ASSERT_HANDLER +# ifdef LEMON_ASSERT_EXCEPTION +# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw +# else +# define LEMON_ASSERT_HANDLER ::lemon::assert_fail +# endif +#endif + +#if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS) + +# define LEMON_ASSERT(exp, msg) (static_cast (0)) + +#else + +/** + * \brief Macro for assertions with customizable message + * + * Macro for assertions with customizable message. + * + * The behaviour can be customized with LEMON_ASSERT_HANDLER, + * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be + * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros. + * + * \todo We should provide some way to reset to the default behaviour, + * shouldn't we? + * + * \todo This whole 'assert' business should be placed in a separate + * include file. + * + * \todo __PRETTY_FUNCTION__ should be replaced by something + * compiler-independent, like BOOST_CURRENT_FUNCTION + */ + +# define LEMON_ASSERT(exp, msg) \ + (static_cast (!!(exp) ? 0 : ( \ + LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ + __PRETTY_FUNCTION__, \ + (msg), #exp, LEMON_ASSERT_ABORT), 0))) + +#endif // NDEBUG || LEMON_DISABLE_ASSERTS + +/** + * \brief Macro for mark not yet implemented features. + * + * \todo Is this the right place for this? It should be used only in + * modules under development. + * + * \todo __PRETTY_FUNCTION__ should be replaced by something + * compiler-independent, like BOOST_CURRENT_FUNCTION + */ + +# define LEMON_FIXME(msg) \ + (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \ + "FIXME: " msg)) diff -r d8475431bbbb -r 8e85e6bbefdf lemon/fib_heap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/fib_heap.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,531 @@ +/* -*- C++ -*- + * lemon/fib_heap.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_FIB_HEAP_H +#define LEMON_FIB_HEAP_H + +///\file +///\ingroup auxdat +///\brief Fibonacci Heap implementation. + +#include +#include +#include + +namespace lemon { + + /// \addtogroup auxdat + /// @{ + + /// Fibonacci Heap. + + ///This class implements the \e Fibonacci \e heap data structure. A \e heap + ///is a data structure for storing items with specified values called \e + ///priorities in such a way that finding the item with minimum priority is + ///efficient. \c Compare specifies the ordering of the priorities. In a heap + ///one can change the priority of an item, add or erase an item, etc. + /// + ///The methods \ref increase and \ref erase are not efficient in a Fibonacci + ///heap. In case of many calls to these operations, it is better to use a + ///\e binary \e heap. + /// + ///\param Item Type of the items to be stored. + ///\param Prio Type of the priority of the items. + ///\param ItemIntMap A read and writable Item int map, used internally + ///to handle the cross references. + ///\param Compare A class for the ordering of the priorities. The + ///default is \c std::less. + /// + ///\sa BinHeap + ///\sa Dijkstra + ///\author Jacint Szabo + +#ifdef DOXYGEN + template +#else + template > +#endif + class FibHeap { + public: + typedef Prio PrioType; + + private: + class store; + + std::vector container; + int minimum; + ItemIntMap &iimap; + Compare comp; + int num_items; + + public: + ///Status of the nodes + enum state_enum { + ///The node is in the heap + IN_HEAP = 0, + ///The node has never been in the heap + PRE_HEAP = -1, + ///The node was in the heap but it got out of it + POST_HEAP = -2 + }; + + ///The constructor + + /** + \c _iimap should be given to the constructor, since it is + used internally to handle the cross references. + */ + explicit FibHeap(ItemIntMap &_iimap) + : minimum(0), iimap(_iimap), num_items() {} + + ///The constructor + + /** + \c _iimap should be given to the constructor, since it is used + internally to handle the cross references. \c _comp is an + object for ordering of the priorities. + */ + FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(0), + iimap(_iimap), comp(_comp), num_items() {} + + ///The number of items stored in the heap. + + /** + Returns the number of items stored in the heap. + */ + int size() const { return num_items; } + + ///Checks if the heap stores no items. + + /** + Returns \c true if and only if the heap stores no items. + */ + bool empty() const { return num_items==0; } + + ///\c item gets to the heap with priority \c value independently if \c item was already there. + + /** + This method calls \ref push(\c item, \c value) if \c item is not + stored in the heap and it calls \ref decrease(\c item, \c value) or + \ref increase(\c item, \c value) otherwise. + */ + void set (Item const item, PrioType const value); + + ///Adds \c item to the heap with priority \c value. + + /** + Adds \c item to the heap with priority \c value. + \pre \c item must not be stored in the heap. + */ + void push (Item const item, PrioType const value); + + ///Returns the item with minimum priority relative to \c Compare. + + /** + This method returns the item with minimum priority relative to \c + Compare. + \pre The heap must be nonempty. + */ + Item top() const { return container[minimum].name; } + + ///Returns the minimum priority relative to \c Compare. + + /** + It returns the minimum priority relative to \c Compare. + \pre The heap must be nonempty. + */ + PrioType prio() const { return container[minimum].prio; } + + ///Returns the priority of \c item. + + /** + This function returns the priority of \c item. + \pre \c item must be in the heap. + */ + PrioType& operator[](const Item& item) { + return container[iimap[item]].prio; + } + + ///Returns the priority of \c item. + + /** + It returns the priority of \c item. + \pre \c item must be in the heap. + */ + const PrioType& operator[](const Item& item) const { + return container[iimap[item]].prio; + } + + + ///Deletes the item with minimum priority relative to \c Compare. + + /** + This method deletes the item with minimum priority relative to \c + Compare from the heap. + \pre The heap must be non-empty. + */ + void pop(); + + ///Deletes \c item from the heap. + + /** + This method deletes \c item from the heap, if \c item was already + stored in the heap. It is quite inefficient in Fibonacci heaps. + */ + void erase (const Item& item); + + ///Decreases the priority of \c item to \c value. + + /** + This method decreases the priority of \c item to \c value. + \pre \c item must be stored in the heap with priority at least \c + value relative to \c Compare. + */ + void decrease (Item item, PrioType const value); + + ///Increases the priority of \c item to \c value. + + /** + This method sets the priority of \c item to \c value. Though + there is no precondition on the priority of \c item, this + method should be used only if it is indeed necessary to increase + (relative to \c Compare) the priority of \c item, because this + method is inefficient. + */ + void increase (Item item, PrioType const value) { + erase(item); + push(item, value); + } + + + ///Returns if \c item is in, has already been in, or has never been in the heap. + + /** + This method returns PRE_HEAP if \c item has never been in the + heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP + otherwise. In the latter case it is possible that \c item will + get back to the heap again. + */ + state_enum state(const Item &item) const { + int i=iimap[item]; + if( i>=0 ) { + if ( container[i].in ) i=0; + else i=-2; + } + return state_enum(i); + } + + private: + + void balance(); + void makeroot(int c); + void cut(int a, int b); + void cascade(int a); + void fuse(int a, int b); + void unlace(int a); + + + class store { + friend class FibHeap; + + Item name; + int parent; + int left_neighbor; + int right_neighbor; + int child; + int degree; + bool marked; + bool in; + PrioType prio; + + store() : parent(-1), child(-1), degree(), marked(false), in(true) {} + }; + }; + + + + // ********************************************************************** + // IMPLEMENTATIONS + // ********************************************************************** + + template + void FibHeap::set + (Item const item, PrioType const value) + { + int i=iimap[item]; + if ( i >= 0 && container[i].in ) { + if ( comp(value, container[i].prio) ) decrease(item, value); + if ( comp(container[i].prio, value) ) increase(item, value); + } else push(item, value); + } + + template + void FibHeap::push + (Item const item, PrioType const value) { + int i=iimap[item]; + if ( i < 0 ) { + int s=container.size(); + iimap.set( item, s ); + store st; + st.name=item; + container.push_back(st); + i=s; + } else { + container[i].parent=container[i].child=-1; + container[i].degree=0; + container[i].in=true; + container[i].marked=false; + } + + if ( num_items ) { + container[container[minimum].right_neighbor].left_neighbor=i; + container[i].right_neighbor=container[minimum].right_neighbor; + container[minimum].right_neighbor=i; + container[i].left_neighbor=minimum; + if ( comp( value, container[minimum].prio) ) minimum=i; + } else { + container[i].right_neighbor=container[i].left_neighbor=i; + minimum=i; + } + container[i].prio=value; + ++num_items; + } + + template + void FibHeap::pop() { + /*The first case is that there are only one root.*/ + if ( container[minimum].left_neighbor==minimum ) { + container[minimum].in=false; + if ( container[minimum].degree!=0 ) { + makeroot(container[minimum].child); + minimum=container[minimum].child; + balance(); + } + } else { + int right=container[minimum].right_neighbor; + unlace(minimum); + container[minimum].in=false; + if ( container[minimum].degree > 0 ) { + int left=container[minimum].left_neighbor; + int child=container[minimum].child; + int last_child=container[child].left_neighbor; + + makeroot(child); + + container[left].right_neighbor=child; + container[child].left_neighbor=left; + container[right].left_neighbor=last_child; + container[last_child].right_neighbor=right; + } + minimum=right; + balance(); + } // the case where there are more roots + --num_items; + } + + + template + void FibHeap::erase + (const Item& item) { + int i=iimap[item]; + + if ( i >= 0 && container[i].in ) { + if ( container[i].parent!=-1 ) { + int p=container[i].parent; + cut(i,p); + cascade(p); + } + minimum=i; //As if its prio would be -infinity + pop(); + } + } + + template + void FibHeap::decrease + (Item item, PrioType const value) { + int i=iimap[item]; + container[i].prio=value; + int p=container[i].parent; + + if ( p!=-1 && comp(value, container[p].prio) ) { + cut(i,p); + cascade(p); + } + if ( comp(value, container[minimum].prio) ) minimum=i; + } + + + template + void FibHeap::balance() { + + int maxdeg=int( std::floor( 2.08*log(double(container.size()))))+1; + + std::vector A(maxdeg,-1); + + /* + *Recall that now minimum does not point to the minimum prio element. + *We set minimum to this during balance(). + */ + int anchor=container[minimum].left_neighbor; + int next=minimum; + bool end=false; + + do { + int active=next; + if ( anchor==active ) end=true; + int d=container[active].degree; + next=container[active].right_neighbor; + + while (A[d]!=-1) { + if( comp(container[active].prio, container[A[d]].prio) ) { + fuse(active,A[d]); + } else { + fuse(A[d],active); + active=A[d]; + } + A[d]=-1; + ++d; + } + A[d]=active; + } while ( !end ); + + + while ( container[minimum].parent >=0 ) minimum=container[minimum].parent; + int s=minimum; + int m=minimum; + do { + if ( comp(container[s].prio, container[minimum].prio) ) minimum=s; + s=container[s].right_neighbor; + } while ( s != m ); + } + + template + void FibHeap::makeroot + (int c) { + int s=c; + do { + container[s].parent=-1; + s=container[s].right_neighbor; + } while ( s != c ); + } + + + template + void FibHeap::cut + (int a, int b) { + /* + *Replacing a from the children of b. + */ + --container[b].degree; + + if ( container[b].degree !=0 ) { + int child=container[b].child; + if ( child==a ) + container[b].child=container[child].right_neighbor; + unlace(a); + } + + + /*Lacing a to the roots.*/ + int right=container[minimum].right_neighbor; + container[minimum].right_neighbor=a; + container[a].left_neighbor=minimum; + container[a].right_neighbor=right; + container[right].left_neighbor=a; + + container[a].parent=-1; + container[a].marked=false; + } + + + template + void FibHeap::cascade + (int a) + { + if ( container[a].parent!=-1 ) { + int p=container[a].parent; + + if ( container[a].marked==false ) container[a].marked=true; + else { + cut(a,p); + cascade(p); + } + } + } + + + template + void FibHeap::fuse + (int a, int b) { + unlace(b); + + /*Lacing b under a.*/ + container[b].parent=a; + + if (container[a].degree==0) { + container[b].left_neighbor=b; + container[b].right_neighbor=b; + container[a].child=b; + } else { + int child=container[a].child; + int last_child=container[child].left_neighbor; + container[child].left_neighbor=b; + container[b].right_neighbor=child; + container[last_child].right_neighbor=b; + container[b].left_neighbor=last_child; + } + + ++container[a].degree; + + container[b].marked=false; + } + + + /* + *It is invoked only if a has siblings. + */ + template + void FibHeap::unlace + (int a) { + int leftn=container[a].left_neighbor; + int rightn=container[a].right_neighbor; + container[leftn].right_neighbor=rightn; + container[rightn].left_neighbor=leftn; + } + + ///@} + +} //namespace lemon + +#endif //LEMON_FIB_HEAP_H + diff -r d8475431bbbb -r 8e85e6bbefdf lemon/full_graph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/full_graph.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,385 @@ +/* -*- C++ -*- + * lemon/full_graph.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_FULL_GRAPH_H +#define LEMON_FULL_GRAPH_H + +#include + + +#include +#include +#include + +#include +#include + + +///\ingroup graphs +///\file +///\brief FullGraph and SymFullGraph classes. + + +namespace lemon { + +/// \addtogroup graphs +/// @{ + + class FullGraphBase { + int NodeNum; + int EdgeNum; + public: + + typedef FullGraphBase Graph; + + class Node; + class Edge; + + public: + + FullGraphBase() {} + + + ///Creates a full graph with \c n nodes. + void construct(int n) { NodeNum = n; EdgeNum = n * n; } + /// + // FullGraphBase(const FullGraphBase &_g) + // : NodeNum(_g.nodeNum()), EdgeNum(NodeNum*NodeNum) { } + + typedef True NodeNumTag; + typedef True EdgeNumTag; + + ///Number of nodes. + int nodeNum() const { return NodeNum; } + ///Number of edges. + int edgeNum() const { return EdgeNum; } + + /// Maximum node ID. + + /// Maximum node ID. + ///\sa id(Node) + int maxId(Node = INVALID) const { return NodeNum-1; } + /// Maximum edge ID. + + /// Maximum edge ID. + ///\sa id(Edge) + int maxId(Edge = INVALID) const { return EdgeNum-1; } + + Node source(Edge e) const { return e.id % NodeNum; } + Node target(Edge e) const { return e.id / NodeNum; } + + + /// Node ID. + + /// The ID of a valid Node is a nonnegative integer not greater than + /// \ref maxNodeId(). The range of the ID's is not surely continuous + /// and the greatest node ID can be actually less then \ref maxNodeId(). + /// + /// The ID of the \ref INVALID node is -1. + ///\return The ID of the node \c v. + + static int id(Node v) { return v.id; } + /// Edge ID. + + /// The ID of a valid Edge is a nonnegative integer not greater than + /// \ref maxEdgeId(). The range of the ID's is not surely continuous + /// and the greatest edge ID can be actually less then \ref maxEdgeId(). + /// + /// The ID of the \ref INVALID edge is -1. + ///\return The ID of the edge \c e. + static int id(Edge e) { return e.id; } + + static Node fromId(int id, Node) { return Node(id);} + + static Edge fromId(int id, Edge) { return Edge(id);} + + /// Finds an edge between two nodes. + + /// Finds an edge from node \c u to node \c v. + /// + /// If \c prev is \ref INVALID (this is the default value), then + /// It finds the first edge from \c u to \c v. Otherwise it looks for + /// the next edge from \c u to \c v after \c prev. + /// \return The found edge or INVALID if there is no such an edge. + Edge findEdge(Node u,Node v, Edge prev = INVALID) + { + return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID; + } + + + class Node { + friend class FullGraphBase; + + protected: + int id; + Node(int _id) { id = _id;} + public: + Node() {} + Node (Invalid) { id = -1; } + bool operator==(const Node node) const {return id == node.id;} + bool operator!=(const Node node) const {return id != node.id;} + bool operator<(const Node node) const {return id < node.id;} + }; + + + + class Edge { + friend class FullGraphBase; + + protected: + int id; // NodeNum * target + source; + + Edge(int _id) : id(_id) {} + + Edge(const FullGraphBase& _graph, int source, int target) + : id(_graph.NodeNum * target+source) {} + public: + Edge() { } + Edge (Invalid) { id = -1; } + bool operator==(const Edge edge) const {return id == edge.id;} + bool operator!=(const Edge edge) const {return id != edge.id;} + bool operator<(const Edge edge) const {return id < edge.id;} + }; + + void first(Node& node) const { + node.id = NodeNum-1; + } + + static void next(Node& node) { + --node.id; + } + + void first(Edge& edge) const { + edge.id = EdgeNum-1; + } + + static void next(Edge& edge) { + --edge.id; + } + + void firstOut(Edge& edge, const Node& node) const { + edge.id = EdgeNum + node.id - NodeNum; + } + + void nextOut(Edge& edge) const { + edge.id -= NodeNum; + if (edge.id < 0) edge.id = -1; + } + + void firstIn(Edge& edge, const Node& node) const { + edge.id = node.id * NodeNum; + } + + void nextIn(Edge& edge) const { + ++edge.id; + if (edge.id % NodeNum == 0) edge.id = -1; + } + + }; + + + typedef AlterableGraphExtender AlterableFullGraphBase; + typedef IterableGraphExtender IterableFullGraphBase; + typedef DefaultMappableGraphExtender MappableFullGraphBase; + + ///A full graph class. + + ///This is a simple and fast directed full graph implementation. + ///It is completely static, so you can neither add nor delete either + ///edges or nodes. + ///Thus it conforms to + ///the \ref concept::StaticGraph "StaticGraph" concept + ///\sa concept::StaticGraph. + /// + ///\author Alpar Juttner + class FullGraph : public MappableFullGraphBase { + public: + + FullGraph(int n) { construct(n); } + }; + + + // Base graph class for UndirFullGraph. + class UndirFullGraphBase { + int NodeNum; + int EdgeNum; + public: + + typedef UndirFullGraphBase Graph; + + class Node; + class Edge; + + public: + + UndirFullGraphBase() {} + + + ///Creates a full graph with \c n nodes. + void construct(int n) { NodeNum = n; EdgeNum = n * (n - 1) / 2; } + /// + // FullGraphBase(const FullGraphBase &_g) + // : NodeNum(_g.nodeNum()), EdgeNum(NodeNum*NodeNum) { } + + typedef True NodeNumTag; + typedef True EdgeNumTag; + + ///Number of nodes. + int nodeNum() const { return NodeNum; } + ///Number of edges. + int edgeNum() const { return EdgeNum; } + + /// Maximum node ID. + + /// Maximum node ID. + ///\sa id(Node) + int maxId(Node = INVALID) const { return NodeNum-1; } + /// Maximum edge ID. + + /// Maximum edge ID. + ///\sa id(Edge) + int maxId(Edge = INVALID) const { return EdgeNum-1; } + + Node source(Edge e) const { + /// \todo we may do it faster + return ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2; + } + + Node target(Edge e) const { + int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;; + return e.id - (source) * (source - 1) / 2; + } + + + /// Node ID. + + /// The ID of a valid Node is a nonnegative integer not greater than + /// \ref maxNodeId(). The range of the ID's is not surely continuous + /// and the greatest node ID can be actually less then \ref maxNodeId(). + /// + /// The ID of the \ref INVALID node is -1. + ///\return The ID of the node \c v. + + static int id(Node v) { return v.id; } + /// Edge ID. + + /// The ID of a valid Edge is a nonnegative integer not greater than + /// \ref maxEdgeId(). The range of the ID's is not surely continuous + /// and the greatest edge ID can be actually less then \ref maxEdgeId(). + /// + /// The ID of the \ref INVALID edge is -1. + ///\return The ID of the edge \c e. + static int id(Edge e) { return e.id; } + + /// Finds an edge between two nodes. + + /// Finds an edge from node \c u to node \c v. + /// + /// If \c prev is \ref INVALID (this is the default value), then + /// It finds the first edge from \c u to \c v. Otherwise it looks for + /// the next edge from \c u to \c v after \c prev. + /// \return The found edge or INVALID if there is no such an edge. + Edge findEdge(Node u,Node v, Edge prev = INVALID) + { + return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID; + } + + + class Node { + friend class UndirFullGraphBase; + + protected: + int id; + Node(int _id) { id = _id;} + public: + Node() {} + Node (Invalid) { id = -1; } + bool operator==(const Node node) const {return id == node.id;} + bool operator!=(const Node node) const {return id != node.id;} + bool operator<(const Node node) const {return id < node.id;} + }; + + + + class Edge { + friend class UndirFullGraphBase; + + protected: + int id; // NodeNum * target + source; + + Edge(int _id) : id(_id) {} + + Edge(const UndirFullGraphBase& _graph, int source, int target) + : id(_graph.NodeNum * target+source) {} + public: + Edge() { } + Edge (Invalid) { id = -1; } + bool operator==(const Edge edge) const {return id == edge.id;} + bool operator!=(const Edge edge) const {return id != edge.id;} + bool operator<(const Edge edge) const {return id < edge.id;} + }; + + void first(Node& node) const { + node.id = NodeNum-1; + } + + static void next(Node& node) { + --node.id; + } + + void first(Edge& edge) const { + edge.id = EdgeNum-1; + } + + static void next(Edge& edge) { + --edge.id; + } + + void firstOut(Edge& edge, const Node& node) const { + edge.id = node.id != 0 ? node.id * (node.id - 1) / 2 : -1; + } + + /// \todo with specialized iterators we can make faster iterating + void nextOut(Edge& e) const { + int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;; + int target = e.id - (source) * (source - 1) / 2; + ++target; + e.id = target < source ? source * (source - 1) / 2 + target : -1; + } + + void firstIn(Edge& edge, const Node& node) const { + edge.id = node.id * (node.id + 1) / 2 - 1; + } + + void nextIn(Edge& e) const { + int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;; + int target = e.id - (source) * (source - 1) / 2; ++target; + ++source; + e.id = source < NodeNum ? source * (source - 1) / 2 + target : -1; + } + + }; + + /// \todo UndirFullGraph from the UndirFullGraphBase + + + + /// @} + +} //namespace lemon + + +#endif //LEMON_FULL_GRAPH_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/graph_adaptor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/graph_adaptor.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,1218 @@ +/* -*- C++ -*- + * lemon/graph_adaptor.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_GRAPH_ADAPTOR_H +#define LEMON_GRAPH_ADAPTOR_H + +///\ingroup graph_adaptors +///\file +///\brief Several graph adaptors. +/// +///This file contains several useful graph adaptor functions. +/// +///\author Marton Makai + +#include +#include +#include +#include +#include + +namespace lemon { + + // Graph adaptors + + /*! + \addtogroup graph_adaptors + @{ + */ + + /*! + Base type for the Graph Adaptors + + \warning Graph adaptors are in even more experimental state than the other + parts of the lib. Use them at you own risk. + + This is the base type for most of LEMON graph adaptors. + This class implements a trivial graph adaptor i.e. it only wraps the + functions and types of the graph. The purpose of this class is to + make easier implementing graph adaptors. E.g. if an adaptor is + considered which differs from the wrapped graph only in some of its + functions or types, then it can be derived from GraphAdaptor, and only the + differences should be implemented. + + \author Marton Makai + */ + template + class GraphAdaptorBase { + public: + typedef _Graph Graph; + /// \todo Is it needed? + typedef Graph BaseGraph; + typedef Graph ParentGraph; + + protected: + Graph* graph; + GraphAdaptorBase() : graph(0) { } + void setGraph(Graph& _graph) { graph=&_graph; } + + public: + GraphAdaptorBase(Graph& _graph) : graph(&_graph) { } + + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + + void first(Node& i) const { graph->first(i); } + void first(Edge& i) const { graph->first(i); } + void firstIn(Edge& i, const Node& n) const { graph->firstIn(i, n); } + void firstOut(Edge& i, const Node& n ) const { graph->firstOut(i, n); } + + void next(Node& i) const { graph->next(i); } + void next(Edge& i) const { graph->next(i); } + void nextIn(Edge& i) const { graph->nextIn(i); } + void nextOut(Edge& i) const { graph->nextOut(i); } + + Node source(const Edge& e) const { return graph->source(e); } + Node target(const Edge& e) const { return graph->target(e); } + + int nodeNum() const { return graph->nodeNum(); } + int edgeNum() const { return graph->edgeNum(); } + + Node addNode() const { return Node(graph->addNode()); } + Edge addEdge(const Node& source, const Node& target) const { + return Edge(graph->addEdge(source, target)); } + + void erase(const Node& i) const { graph->erase(i); } + void erase(const Edge& i) const { graph->erase(i); } + + void clear() const { graph->clear(); } + + bool forward(const Edge& e) const { return graph->forward(e); } + bool backward(const Edge& e) const { return graph->backward(e); } + + int id(const Node& v) const { return graph->id(v); } + int id(const Edge& e) const { return graph->id(e); } + + Edge opposite(const Edge& e) const { return Edge(graph->opposite(e)); } + + template + class NodeMap : public _Graph::template NodeMap<_Value> { + public: + typedef typename _Graph::template NodeMap<_Value> Parent; + NodeMap(const GraphAdaptorBase<_Graph>& gw) : Parent(*gw.graph) { } + NodeMap(const GraphAdaptorBase<_Graph>& gw, const _Value& value) + : Parent(*gw.graph, value) { } + }; + + template + class EdgeMap : public _Graph::template EdgeMap<_Value> { + public: + typedef typename _Graph::template EdgeMap<_Value> Parent; + EdgeMap(const GraphAdaptorBase<_Graph>& gw) : Parent(*gw.graph) { } + EdgeMap(const GraphAdaptorBase<_Graph>& gw, const _Value& value) + : Parent(*gw.graph, value) { } + }; + + }; + + template + class GraphAdaptor : + public IterableGraphExtender > { + public: + typedef _Graph Graph; + typedef IterableGraphExtender > Parent; + protected: + GraphAdaptor() : Parent() { } + + public: + GraphAdaptor(Graph& _graph) { setGraph(_graph); } + }; + + template + class RevGraphAdaptorBase : public GraphAdaptorBase<_Graph> { + public: + typedef _Graph Graph; + typedef GraphAdaptorBase<_Graph> Parent; + protected: + RevGraphAdaptorBase() : Parent() { } + public: + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + // using Parent::first; + void firstIn(Edge& i, const Node& n) const { Parent::firstOut(i, n); } + void firstOut(Edge& i, const Node& n ) const { Parent::firstIn(i, n); } + + // using Parent::next; + void nextIn(Edge& i) const { Parent::nextOut(i); } + void nextOut(Edge& i) const { Parent::nextIn(i); } + + Node source(const Edge& e) const { return Parent::target(e); } + Node target(const Edge& e) const { return Parent::source(e); } + }; + + + /// A graph adaptor which reverses the orientation of the edges. + + ///\warning Graph adaptors are in even more experimental state than the other + ///parts of the lib. Use them at you own risk. + /// + /// Let \f$G=(V, A)\f$ be a directed graph and + /// suppose that a graph instange \c g of type + /// \c ListGraph implements \f$G\f$. + /// \code + /// ListGraph g; + /// \endcode + /// For each directed edge + /// \f$e\in A\f$, let \f$\bar e\f$ denote the edge obtained by + /// reversing its orientation. + /// Then RevGraphAdaptor implements the graph structure with node-set + /// \f$V\f$ and edge-set + /// \f$\{\bar e : e\in A \}\f$, i.e. the graph obtained from \f$G\f$ be + /// reversing the orientation of its edges. The following code shows how + /// such an instance can be constructed. + /// \code + /// RevGraphAdaptor gw(g); + /// \endcode + ///\author Marton Makai + template + class RevGraphAdaptor : + public IterableGraphExtender > { + public: + typedef _Graph Graph; + typedef IterableGraphExtender< + RevGraphAdaptorBase<_Graph> > Parent; + protected: + RevGraphAdaptor() { } + public: + RevGraphAdaptor(_Graph& _graph) { setGraph(_graph); } + }; + + + template + class SubGraphAdaptorBase : public GraphAdaptorBase<_Graph> { + public: + typedef _Graph Graph; + typedef GraphAdaptorBase<_Graph> Parent; + protected: + NodeFilterMap* node_filter_map; + EdgeFilterMap* edge_filter_map; + SubGraphAdaptorBase() : Parent(), + node_filter_map(0), edge_filter_map(0) { } + + void setNodeFilterMap(NodeFilterMap& _node_filter_map) { + node_filter_map=&_node_filter_map; + } + void setEdgeFilterMap(EdgeFilterMap& _edge_filter_map) { + edge_filter_map=&_edge_filter_map; + } + + public: +// SubGraphAdaptorBase(Graph& _graph, +// NodeFilterMap& _node_filter_map, +// EdgeFilterMap& _edge_filter_map) : +// Parent(&_graph), +// node_filter_map(&node_filter_map), +// edge_filter_map(&edge_filter_map) { } + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + void first(Node& i) const { + Parent::first(i); + while (i!=INVALID && !(*node_filter_map)[i]) Parent::next(i); + } + void first(Edge& i) const { + Parent::first(i); + while (i!=INVALID && !(*edge_filter_map)[i]) Parent::next(i); + } + void firstIn(Edge& i, const Node& n) const { + Parent::firstIn(i, n); + while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextIn(i); + } + void firstOut(Edge& i, const Node& n) const { + Parent::firstOut(i, n); + while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextOut(i); + } + + void next(Node& i) const { + Parent::next(i); + while (i!=INVALID && !(*node_filter_map)[i]) Parent::next(i); + } + void next(Edge& i) const { + Parent::next(i); + while (i!=INVALID && !(*edge_filter_map)[i]) Parent::next(i); + } + void nextIn(Edge& i) const { + Parent::nextIn(i); + while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextIn(i); + } + void nextOut(Edge& i) const { + Parent::nextOut(i); + while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextOut(i); + } + + /// This function hides \c n in the graph, i.e. the iteration + /// jumps over it. This is done by simply setting the value of \c n + /// to be false in the corresponding node-map. + void hide(const Node& n) const { node_filter_map->set(n, false); } + + /// This function hides \c e in the graph, i.e. the iteration + /// jumps over it. This is done by simply setting the value of \c e + /// to be false in the corresponding edge-map. + void hide(const Edge& e) const { edge_filter_map->set(e, false); } + + /// The value of \c n is set to be true in the node-map which stores + /// hide information. If \c n was hidden previuosly, then it is shown + /// again + void unHide(const Node& n) const { node_filter_map->set(n, true); } + + /// The value of \c e is set to be true in the edge-map which stores + /// hide information. If \c e was hidden previuosly, then it is shown + /// again + void unHide(const Edge& e) const { edge_filter_map->set(e, true); } + + /// Returns true if \c n is hidden. + bool hidden(const Node& n) const { return !(*node_filter_map)[n]; } + + /// Returns true if \c n is hidden. + bool hidden(const Edge& e) const { return !(*edge_filter_map)[e]; } + + /// \warning This is a linear time operation and works only if s + /// \c Graph::NodeIt is defined. + /// \todo assign tags. + int nodeNum() const { + int i=0; + Node n; + for (first(n); n!=INVALID; next(n)) ++i; + return i; + } + + /// \warning This is a linear time operation and works only if + /// \c Graph::EdgeIt is defined. + /// \todo assign tags. + int edgeNum() const { + int i=0; + Edge e; + for (first(e); e!=INVALID; next(e)) ++i; + return i; + } + + + }; + + /*! \brief A graph adaptor for hiding nodes and edges from a graph. + + \warning Graph adaptors are in even more experimental state than the other + parts of the lib. Use them at you own risk. + + SubGraphAdaptor shows the graph with filtered node-set and + edge-set. + Let \f$G=(V, A)\f$ be a directed graph + and suppose that the graph instance \c g of type ListGraph implements + \f$G\f$. + Let moreover \f$b_V\f$ and + \f$b_A\f$ be bool-valued functions resp. on the node-set and edge-set. + SubGraphAdaptor<...>::NodeIt iterates + on the node-set \f$\{v\in V : b_V(v)=true\}\f$ and + SubGraphAdaptor<...>::EdgeIt iterates + on the edge-set \f$\{e\in A : b_A(e)=true\}\f$. Similarly, + SubGraphAdaptor<...>::OutEdgeIt and SubGraphAdaptor<...>::InEdgeIt iterates + only on edges leaving and entering a specific node which have true value. + + We have to note that this does not mean that an + induced subgraph is obtained, the node-iterator cares only the filter + on the node-set, and the edge-iterators care only the filter on the + edge-set. + \code + typedef ListGraph Graph; + Graph g; + typedef Graph::Node Node; + typedef Graph::Edge Edge; + Node u=g.addNode(); //node of id 0 + Node v=g.addNode(); //node of id 1 + Node e=g.addEdge(u, v); //edge of id 0 + Node f=g.addEdge(v, u); //edge of id 1 + Graph::NodeMap nm(g, true); + nm.set(u, false); + Graph::EdgeMap em(g, true); + em.set(e, false); + typedef SubGraphAdaptor, Graph::EdgeMap > SubGW; + SubGW gw(g, nm, em); + for (SubGW::NodeIt n(gw); n!=INVALID; ++n) std::cout << g.id(n) << std::endl; + std::cout << ":-)" << std::endl; + for (SubGW::EdgeIt e(gw); e!=INVALID; ++e) std::cout << g.id(e) << std::endl; + \endcode + The output of the above code is the following. + \code + 1 + :-) + 1 + \endcode + Note that \c n is of type \c SubGW::NodeIt, but it can be converted to + \c Graph::Node that is why \c g.id(n) can be applied. + + For other examples see also the documentation of NodeSubGraphAdaptor and + EdgeSubGraphAdaptor. + + \author Marton Makai + */ + template + class SubGraphAdaptor : + public IterableGraphExtender< + SubGraphAdaptorBase<_Graph, NodeFilterMap, EdgeFilterMap> > { + public: + typedef _Graph Graph; + typedef IterableGraphExtender< + SubGraphAdaptorBase<_Graph, NodeFilterMap, EdgeFilterMap> > Parent; + protected: + SubGraphAdaptor() { } + public: + SubGraphAdaptor(_Graph& _graph, NodeFilterMap& _node_filter_map, + EdgeFilterMap& _edge_filter_map) { + setGraph(_graph); + setNodeFilterMap(_node_filter_map); + setEdgeFilterMap(_edge_filter_map); + } + }; + + + + /*! \brief An adaptor for hiding nodes from a graph. + + \warning Graph adaptors are in even more experimental state than the other + parts of the lib. Use them at you own risk. + + An adaptor for hiding nodes from a graph. + This adaptor specializes SubGraphAdaptor in the way that only the node-set + can be filtered. Note that this does not mean of considering induced + subgraph, the edge-iterators consider the original edge-set. + \author Marton Makai + */ + template + class NodeSubGraphAdaptor : + public SubGraphAdaptor > { + public: + typedef SubGraphAdaptor > Parent; + protected: + ConstMap const_true_map; + public: + NodeSubGraphAdaptor(Graph& _graph, NodeFilterMap& _node_filter_map) : + Parent(), const_true_map(true) { + Parent::setGraph(_graph); + Parent::setNodeFilterMap(_node_filter_map); + Parent::setEdgeFilterMap(const_true_map); + } + }; + + + /*! \brief An adaptor for hiding edges from a graph. + + \warning Graph adaptors are in even more experimental state than the other + parts of the lib. Use them at you own risk. + + An adaptor for hiding edges from a graph. + This adaptor specializes SubGraphAdaptor in the way that only the edge-set + can be filtered. The usefulness of this adaptor is demonstrated in the + problem of searching a maximum number of edge-disjoint shortest paths + between + two nodes \c s and \c t. Shortest here means being shortest w.r.t. + non-negative edge-lengths. Note that + the comprehension of the presented solution + need's some elementary knowledge from combinatorial optimization. + + If a single shortest path is to be + searched between \c s and \c t, then this can be done easily by + applying the Dijkstra algorithm. What happens, if a maximum number of + edge-disjoint shortest paths is to be computed. It can be proved that an + edge can be in a shortest path if and only if it is tight with respect to + the potential function computed by Dijkstra. Moreover, any path containing + only such edges is a shortest one. Thus we have to compute a maximum number + of edge-disjoint paths between \c s and \c t in the graph which has edge-set + all the tight edges. The computation will be demonstrated on the following + graph, which is read from the dimacs file \ref sub_graph_adaptor_demo.dim. + The full source code is available in \ref sub_graph_adaptor_demo.cc. + If you are interested in more demo programs, you can use + \ref dim_to_dot.cc to generate .dot files from dimacs files. + The .dot file of the following figure of was generated generated by + the demo program \ref dim_to_dot.cc. + + \dot + digraph lemon_dot_example { + node [ shape=ellipse, fontname=Helvetica, fontsize=10 ]; + n0 [ label="0 (s)" ]; + n1 [ label="1" ]; + n2 [ label="2" ]; + n3 [ label="3" ]; + n4 [ label="4" ]; + n5 [ label="5" ]; + n6 [ label="6 (t)" ]; + edge [ shape=ellipse, fontname=Helvetica, fontsize=10 ]; + n5 -> n6 [ label="9, length:4" ]; + n4 -> n6 [ label="8, length:2" ]; + n3 -> n5 [ label="7, length:1" ]; + n2 -> n5 [ label="6, length:3" ]; + n2 -> n6 [ label="5, length:5" ]; + n2 -> n4 [ label="4, length:2" ]; + n1 -> n4 [ label="3, length:3" ]; + n0 -> n3 [ label="2, length:1" ]; + n0 -> n2 [ label="1, length:2" ]; + n0 -> n1 [ label="0, length:3" ]; + } + \enddot + + \code + Graph g; + Node s, t; + LengthMap length(g); + + readDimacs(std::cin, g, length, s, t); + + cout << "edges with lengths (of form id, source--length->target): " << endl; + for(EdgeIt e(g); e!=INVALID; ++e) + cout << g.id(e) << ", " << g.id(g.source(e)) << "--" + << length[e] << "->" << g.id(g.target(e)) << endl; + + cout << "s: " << g.id(s) << " t: " << g.id(t) << endl; + \endcode + Next, the potential function is computed with Dijkstra. + \code + typedef Dijkstra Dijkstra; + Dijkstra dijkstra(g, length); + dijkstra.run(s); + \endcode + Next, we consrtruct a map which filters the edge-set to the tight edges. + \code + typedef TightEdgeFilterMap + TightEdgeFilter; + TightEdgeFilter tight_edge_filter(g, dijkstra.distMap(), length); + + typedef EdgeSubGraphAdaptor SubGW; + SubGW gw(g, tight_edge_filter); + \endcode + Then, the maximum nimber of edge-disjoint \c s-\c t paths are computed + with a max flow algorithm Preflow. + \code + ConstMap const_1_map(1); + Graph::EdgeMap flow(g, 0); + + Preflow, Graph::EdgeMap > + preflow(gw, s, t, const_1_map, flow); + preflow.run(); + \endcode + Last, the output is: + \code + cout << "maximum number of edge-disjoint shortest path: " + << preflow.flowValue() << endl; + cout << "edges of the maximum number of edge-disjoint shortest s-t paths: " + << endl; + for(EdgeIt e(g); e!=INVALID; ++e) + if (flow[e]) + cout << " " << g.id(g.source(e)) << "--" + << length[e] << "->" << g.id(g.target(e)) << endl; + \endcode + The program has the following (expected :-)) output: + \code + edges with lengths (of form id, source--length->target): + 9, 5--4->6 + 8, 4--2->6 + 7, 3--1->5 + 6, 2--3->5 + 5, 2--5->6 + 4, 2--2->4 + 3, 1--3->4 + 2, 0--1->3 + 1, 0--2->2 + 0, 0--3->1 + s: 0 t: 6 + maximum number of edge-disjoint shortest path: 2 + edges of the maximum number of edge-disjoint shortest s-t paths: + 9, 5--4->6 + 8, 4--2->6 + 7, 3--1->5 + 4, 2--2->4 + 2, 0--1->3 + 1, 0--2->2 + \endcode + + \author Marton Makai + */ + template + class EdgeSubGraphAdaptor : + public SubGraphAdaptor, + EdgeFilterMap> { + public: + typedef SubGraphAdaptor, + EdgeFilterMap> Parent; + protected: + ConstMap const_true_map; + public: + EdgeSubGraphAdaptor(Graph& _graph, EdgeFilterMap& _edge_filter_map) : + Parent(), const_true_map(true) { + Parent::setGraph(_graph); + Parent::setNodeFilterMap(const_true_map); + Parent::setEdgeFilterMap(_edge_filter_map); + } + }; + + template + class UndirGraphAdaptorBase : + public UndirGraphExtender > { + public: + typedef _Graph Graph; + typedef UndirGraphExtender > Parent; + protected: + UndirGraphAdaptorBase() : Parent() { } + public: + typedef typename Parent::UndirEdge UndirEdge; + typedef typename Parent::Edge Edge; + + /// \bug Why cant an edge say that it is forward or not??? + /// By this, a pointer to the graph have to be stored + /// The implementation + template + class EdgeMap { + protected: + const UndirGraphAdaptorBase<_Graph>* g; + template friend class EdgeMap; + typename _Graph::template EdgeMap forward_map, backward_map; + public: + typedef T Value; + typedef Edge Key; + + EdgeMap(const UndirGraphAdaptorBase<_Graph>& _g) : g(&_g), + forward_map(*(g->graph)), backward_map(*(g->graph)) { } + + EdgeMap(const UndirGraphAdaptorBase<_Graph>& _g, T a) : g(&_g), + forward_map(*(g->graph), a), backward_map(*(g->graph), a) { } + + void set(Edge e, T a) { + if (g->forward(e)) + forward_map.set(e, a); + else + backward_map.set(e, a); + } + + T operator[](Edge e) const { + if (g->forward(e)) + return forward_map[e]; + else + return backward_map[e]; + } + }; + + template + class UndirEdgeMap { + template friend class UndirEdgeMap; + typename _Graph::template EdgeMap map; + public: + typedef T Value; + typedef UndirEdge Key; + + UndirEdgeMap(const UndirGraphAdaptorBase<_Graph>& g) : + map(*(g.graph)) { } + + UndirEdgeMap(const UndirGraphAdaptorBase<_Graph>& g, T a) : + map(*(g.graph), a) { } + + void set(UndirEdge e, T a) { + map.set(e, a); + } + + T operator[](UndirEdge e) const { + return map[e]; + } + }; + + }; + + /// \brief An undirected graph is made from a directed graph by an adaptor + /// + /// Undocumented, untested!!! + /// If somebody knows nice demo application, let's polulate it. + /// + /// \author Marton Makai + template + class UndirGraphAdaptor : + public IterableUndirGraphExtender< + UndirGraphAdaptorBase<_Graph> > { + public: + typedef _Graph Graph; + typedef IterableUndirGraphExtender< + UndirGraphAdaptorBase<_Graph> > Parent; + protected: + UndirGraphAdaptor() { } + public: + UndirGraphAdaptor(_Graph& _graph) { + setGraph(_graph); + } + }; + + + template + class SubBidirGraphAdaptorBase : public GraphAdaptorBase<_Graph> { + public: + typedef _Graph Graph; + typedef GraphAdaptorBase<_Graph> Parent; + protected: + ForwardFilterMap* forward_filter; + BackwardFilterMap* backward_filter; + SubBidirGraphAdaptorBase() : Parent(), + forward_filter(0), backward_filter(0) { } + + void setForwardFilterMap(ForwardFilterMap& _forward_filter) { + forward_filter=&_forward_filter; + } + void setBackwardFilterMap(BackwardFilterMap& _backward_filter) { + backward_filter=&_backward_filter; + } + + public: +// SubGraphAdaptorBase(Graph& _graph, +// NodeFilterMap& _node_filter_map, +// EdgeFilterMap& _edge_filter_map) : +// Parent(&_graph), +// node_filter_map(&node_filter_map), +// edge_filter_map(&edge_filter_map) { } + + typedef typename Parent::Node Node; + typedef typename _Graph::Edge GraphEdge; + template class EdgeMap; + /// SubBidirGraphAdaptorBase<..., ..., ...>::Edge is inherited from + /// _Graph::Edge. It contains an extra bool flag which is true + /// if and only if the + /// edge is the backward version of the original edge. + class Edge : public _Graph::Edge { + friend class SubBidirGraphAdaptorBase< + Graph, ForwardFilterMap, BackwardFilterMap>; + template friend class EdgeMap; + protected: + bool backward; //true, iff backward + public: + Edge() { } + /// \todo =false is needed, or causes problems? + /// If \c _backward is false, then we get an edge corresponding to the + /// original one, otherwise its oppositely directed pair is obtained. + Edge(const typename _Graph::Edge& e, bool _backward/*=false*/) : + _Graph::Edge(e), backward(_backward) { } + Edge(Invalid i) : _Graph::Edge(i), backward(true) { } + bool operator==(const Edge& v) const { + return (this->backward==v.backward && + static_cast(*this)== + static_cast(v)); + } + bool operator!=(const Edge& v) const { + return (this->backward!=v.backward || + static_cast(*this)!= + static_cast(v)); + } + }; + + void first(Node& i) const { + Parent::first(i); + } + + void first(Edge& i) const { + Parent::first(i); + i.backward=false; + while (*static_cast(&i)!=INVALID && + !(*forward_filter)[i]) Parent::next(i); + if (*static_cast(&i)==INVALID) { + Parent::first(i); + i.backward=true; + while (*static_cast(&i)!=INVALID && + !(*backward_filter)[i]) Parent::next(i); + } + } + + void firstIn(Edge& i, const Node& n) const { + Parent::firstIn(i, n); + i.backward=false; + while (*static_cast(&i)!=INVALID && + !(*forward_filter)[i]) Parent::nextIn(i); + if (*static_cast(&i)==INVALID) { + Parent::firstOut(i, n); + i.backward=true; + while (*static_cast(&i)!=INVALID && + !(*backward_filter)[i]) Parent::nextOut(i); + } + } + + void firstOut(Edge& i, const Node& n) const { + Parent::firstOut(i, n); + i.backward=false; + while (*static_cast(&i)!=INVALID && + !(*forward_filter)[i]) Parent::nextOut(i); + if (*static_cast(&i)==INVALID) { + Parent::firstIn(i, n); + i.backward=true; + while (*static_cast(&i)!=INVALID && + !(*backward_filter)[i]) Parent::nextIn(i); + } + } + + void next(Node& i) const { + Parent::next(i); + } + + void next(Edge& i) const { + if (!(i.backward)) { + Parent::next(i); + while (*static_cast(&i)!=INVALID && + !(*forward_filter)[i]) Parent::next(i); + if (*static_cast(&i)==INVALID) { + Parent::first(i); + i.backward=true; + while (*static_cast(&i)!=INVALID && + !(*backward_filter)[i]) Parent::next(i); + } + } else { + Parent::next(i); + while (*static_cast(&i)!=INVALID && + !(*backward_filter)[i]) Parent::next(i); + } + } + + void nextIn(Edge& i) const { + if (!(i.backward)) { + Node n=Parent::target(i); + Parent::nextIn(i); + while (*static_cast(&i)!=INVALID && + !(*forward_filter)[i]) Parent::nextIn(i); + if (*static_cast(&i)==INVALID) { + Parent::firstOut(i, n); + i.backward=true; + while (*static_cast(&i)!=INVALID && + !(*backward_filter)[i]) Parent::nextOut(i); + } + } else { + Parent::nextOut(i); + while (*static_cast(&i)!=INVALID && + !(*backward_filter)[i]) Parent::nextOut(i); + } + } + + void nextOut(Edge& i) const { + if (!(i.backward)) { + Node n=Parent::source(i); + Parent::nextOut(i); + while (*static_cast(&i)!=INVALID && + !(*forward_filter)[i]) Parent::nextOut(i); + if (*static_cast(&i)==INVALID) { + Parent::firstIn(i, n); + i.backward=true; + while (*static_cast(&i)!=INVALID && + !(*backward_filter)[i]) Parent::nextIn(i); + } + } else { + Parent::nextIn(i); + while (*static_cast(&i)!=INVALID && + !(*backward_filter)[i]) Parent::nextIn(i); + } + } + + Node source(Edge e) const { + return ((!e.backward) ? this->graph->source(e) : this->graph->target(e)); } + Node target(Edge e) const { + return ((!e.backward) ? this->graph->target(e) : this->graph->source(e)); } + + /// Gives back the opposite edge. + Edge opposite(const Edge& e) const { + Edge f=e; + f.backward=!f.backward; + return f; + } + + /// \warning This is a linear time operation and works only if + /// \c Graph::EdgeIt is defined. + /// \todo hmm + int edgeNum() const { + int i=0; + Edge e; + for (first(e); e!=INVALID; next(e)) ++i; + return i; + } + + bool forward(const Edge& e) const { return !e.backward; } + bool backward(const Edge& e) const { return e.backward; } + + template + /// \c SubBidirGraphAdaptorBase<..., ..., ...>::EdgeMap contains two + /// _Graph::EdgeMap one for the forward edges and + /// one for the backward edges. + class EdgeMap { + template friend class EdgeMap; + typename _Graph::template EdgeMap forward_map, backward_map; + public: + typedef T Value; + typedef Edge Key; + + EdgeMap(const SubBidirGraphAdaptorBase<_Graph, + ForwardFilterMap, BackwardFilterMap>& g) : + forward_map(*(g.graph)), backward_map(*(g.graph)) { } + + EdgeMap(const SubBidirGraphAdaptorBase<_Graph, + ForwardFilterMap, BackwardFilterMap>& g, T a) : + forward_map(*(g.graph), a), backward_map(*(g.graph), a) { } + + void set(Edge e, T a) { + if (!e.backward) + forward_map.set(e, a); + else + backward_map.set(e, a); + } + +// typename _Graph::template EdgeMap::ConstReference +// operator[](Edge e) const { +// if (!e.backward) +// return forward_map[e]; +// else +// return backward_map[e]; +// } + +// typename _Graph::template EdgeMap::Reference + T operator[](Edge e) const { + if (!e.backward) + return forward_map[e]; + else + return backward_map[e]; + } + + void update() { + forward_map.update(); + backward_map.update(); + } + }; + + }; + + + ///\brief An adaptor for composing a subgraph of a + /// bidirected graph made from a directed one. + /// + /// An adaptor for composing a subgraph of a + /// bidirected graph made from a directed one. + /// + ///\warning Graph adaptors are in even more experimental state than the other + ///parts of the lib. Use them at you own risk. + /// + /// Let \f$G=(V, A)\f$ be a directed graph and for each directed edge + /// \f$e\in A\f$, let \f$\bar e\f$ denote the edge obtained by + /// reversing its orientation. We are given moreover two bool valued + /// maps on the edge-set, + /// \f$forward\_filter\f$, and \f$backward\_filter\f$. + /// SubBidirGraphAdaptor implements the graph structure with node-set + /// \f$V\f$ and edge-set + /// \f$\{e : e\in A \mbox{ and } forward\_filter(e) \mbox{ is true}\}+\{\bar e : e\in A \mbox{ and } backward\_filter(e) \mbox{ is true}\}\f$. + /// The purpose of writing + instead of union is because parallel + /// edges can arise. (Similarly, antiparallel edges also can arise). + /// In other words, a subgraph of the bidirected graph obtained, which + /// is given by orienting the edges of the original graph in both directions. + /// As the oppositely directed edges are logically different, + /// the maps are able to attach different values for them. + /// + /// An example for such a construction is \c RevGraphAdaptor where the + /// forward_filter is everywhere false and the backward_filter is + /// everywhere true. We note that for sake of efficiency, + /// \c RevGraphAdaptor is implemented in a different way. + /// But BidirGraphAdaptor is obtained from + /// SubBidirGraphAdaptor by considering everywhere true + /// valued maps both for forward_filter and backward_filter. + /// + /// The most important application of SubBidirGraphAdaptor + /// is ResGraphAdaptor, which stands for the residual graph in directed + /// flow and circulation problems. + /// As adaptors usually, the SubBidirGraphAdaptor implements the + /// above mentioned graph structure without its physical storage, + /// that is the whole stuff is stored in constant memory. + template + class SubBidirGraphAdaptor : + public IterableGraphExtender< + SubBidirGraphAdaptorBase<_Graph, ForwardFilterMap, BackwardFilterMap> > { + public: + typedef _Graph Graph; + typedef IterableGraphExtender< + SubBidirGraphAdaptorBase< + _Graph, ForwardFilterMap, BackwardFilterMap> > Parent; + protected: + SubBidirGraphAdaptor() { } + public: + SubBidirGraphAdaptor(_Graph& _graph, ForwardFilterMap& _forward_filter, + BackwardFilterMap& _backward_filter) { + setGraph(_graph); + setForwardFilterMap(_forward_filter); + setBackwardFilterMap(_backward_filter); + } + }; + + + + ///\brief An adaptor for composing bidirected graph from a directed one. + /// + ///\warning Graph adaptors are in even more experimental state than the other + ///parts of the lib. Use them at you own risk. + /// + /// An adaptor for composing bidirected graph from a directed one. + /// A bidirected graph is composed over the directed one without physical + /// storage. As the oppositely directed edges are logically different ones + /// the maps are able to attach different values for them. + template + class BidirGraphAdaptor : + public SubBidirGraphAdaptor< + Graph, + ConstMap, + ConstMap > { + public: + typedef SubBidirGraphAdaptor< + Graph, + ConstMap, + ConstMap > Parent; + protected: + ConstMap cm; + + BidirGraphAdaptor() : Parent(), cm(true) { + Parent::setForwardFilterMap(cm); + Parent::setBackwardFilterMap(cm); + } + public: + BidirGraphAdaptor(Graph& _graph) : Parent(), cm(true) { + Parent::setGraph(_graph); + Parent::setForwardFilterMap(cm); + Parent::setBackwardFilterMap(cm); + } + + int edgeNum() const { + return 2*this->graph->edgeNum(); + } + // KEEP_MAPS(Parent, BidirGraphAdaptor); + }; + + + template + class ResForwardFilter { + // const Graph* graph; + const CapacityMap* capacity; + const FlowMap* flow; + public: + ResForwardFilter(/*const Graph& _graph, */ + const CapacityMap& _capacity, const FlowMap& _flow) : + /*graph(&_graph),*/ capacity(&_capacity), flow(&_flow) { } + ResForwardFilter() : /*graph(0),*/ capacity(0), flow(0) { } + void setCapacity(const CapacityMap& _capacity) { capacity=&_capacity; } + void setFlow(const FlowMap& _flow) { flow=&_flow; } + bool operator[](const typename Graph::Edge& e) const { + return (Number((*flow)[e]) < Number((*capacity)[e])); + } + }; + + template + class ResBackwardFilter { + const CapacityMap* capacity; + const FlowMap* flow; + public: + ResBackwardFilter(/*const Graph& _graph,*/ + const CapacityMap& _capacity, const FlowMap& _flow) : + /*graph(&_graph),*/ capacity(&_capacity), flow(&_flow) { } + ResBackwardFilter() : /*graph(0),*/ capacity(0), flow(0) { } + void setCapacity(const CapacityMap& _capacity) { capacity=&_capacity; } + void setFlow(const FlowMap& _flow) { flow=&_flow; } + bool operator[](const typename Graph::Edge& e) const { + return (Number(0) < Number((*flow)[e])); + } + }; + + + /*! \brief An adaptor for composing the residual graph for directed flow and circulation problems. + + An adaptor for composing the residual graph for directed flow and circulation problems. + Let \f$G=(V, A)\f$ be a directed graph and let \f$F\f$ be a + number type. Let moreover + \f$f,c:A\to F\f$, be functions on the edge-set. + In the appications of ResGraphAdaptor, \f$f\f$ usually stands for a flow + and \f$c\f$ for a capacity function. + Suppose that a graph instange \c g of type + \c ListGraph implements \f$G\f$. + \code + ListGraph g; + \endcode + Then RevGraphAdaptor implements the graph structure with node-set + \f$V\f$ and edge-set \f$A_{forward}\cup A_{backward}\f$, where + \f$A_{forward}=\{uv : uv\in A, f(uv)0\}\f$, + i.e. the so called residual graph. + When we take the union \f$A_{forward}\cup A_{backward}\f$, + multilicities are counted, i.e. if an edge is in both + \f$A_{forward}\f$ and \f$A_{backward}\f$, then in the adaptor it + appears twice. + The following code shows how + such an instance can be constructed. + \code + typedef ListGraph Graph; + Graph::EdgeMap f(g); + Graph::EdgeMap c(g); + ResGraphAdaptor, Graph::EdgeMap > gw(g); + \endcode + \author Marton Makai + */ + template + class ResGraphAdaptor : + public SubBidirGraphAdaptor< + Graph, + ResForwardFilter, + ResBackwardFilter > { + public: + typedef SubBidirGraphAdaptor< + Graph, + ResForwardFilter, + ResBackwardFilter > Parent; + protected: + const CapacityMap* capacity; + FlowMap* flow; + ResForwardFilter forward_filter; + ResBackwardFilter backward_filter; + ResGraphAdaptor() : Parent(), + capacity(0), flow(0) { } + void setCapacityMap(const CapacityMap& _capacity) { + capacity=&_capacity; + forward_filter.setCapacity(_capacity); + backward_filter.setCapacity(_capacity); + } + void setFlowMap(FlowMap& _flow) { + flow=&_flow; + forward_filter.setFlow(_flow); + backward_filter.setFlow(_flow); + } + public: + ResGraphAdaptor(Graph& _graph, const CapacityMap& _capacity, + FlowMap& _flow) : + Parent(), capacity(&_capacity), flow(&_flow), + forward_filter(/*_graph,*/ _capacity, _flow), + backward_filter(/*_graph,*/ _capacity, _flow) { + Parent::setGraph(_graph); + Parent::setForwardFilterMap(forward_filter); + Parent::setBackwardFilterMap(backward_filter); + } + + typedef typename Parent::Edge Edge; + + void augment(const Edge& e, Number a) const { + if (Parent::forward(e)) + flow->set(e, (*flow)[e]+a); + else + flow->set(e, (*flow)[e]-a); + } + + /// \brief Residual capacity map. + /// + /// In generic residual graphs the residual capacity can be obtained + /// as a map. + class ResCap { + protected: + const ResGraphAdaptor* res_graph; + public: + typedef Number Value; + typedef Edge Key; + ResCap(const ResGraphAdaptor& + _res_graph) : res_graph(&_res_graph) { } + Number operator[](const Edge& e) const { + if (res_graph->forward(e)) + return (*(res_graph->capacity))[e]-(*(res_graph->flow))[e]; + else + return (*(res_graph->flow))[e]; + } + }; + + // KEEP_MAPS(Parent, ResGraphAdaptor); + }; + + + + template + class ErasingFirstGraphAdaptorBase : public GraphAdaptorBase<_Graph> { + public: + typedef _Graph Graph; + typedef GraphAdaptorBase<_Graph> Parent; + protected: + FirstOutEdgesMap* first_out_edges; + ErasingFirstGraphAdaptorBase() : Parent(), + first_out_edges(0) { } + + void setFirstOutEdgesMap(FirstOutEdgesMap& _first_out_edges) { + first_out_edges=&_first_out_edges; + } + + public: + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + void firstOut(Edge& i, const Node& n) const { + i=(*first_out_edges)[n]; + } + + void erase(const Edge& e) const { + Node n=source(e); + Edge f=e; + Parent::nextOut(f); + first_out_edges->set(n, f); + } + }; + + + /// For blocking flows. + + ///\warning Graph adaptors are in even more experimental state than the other + ///parts of the lib. Use them at you own risk. + /// + /// This graph adaptor is used for on-the-fly + /// Dinits blocking flow computations. + /// For each node, an out-edge is stored which is used when the + /// \code + /// OutEdgeIt& first(OutEdgeIt&, const Node&) + /// \endcode + /// is called. + /// + /// \author Marton Makai + template + class ErasingFirstGraphAdaptor : + public IterableGraphExtender< + ErasingFirstGraphAdaptorBase<_Graph, FirstOutEdgesMap> > { + public: + typedef _Graph Graph; + typedef IterableGraphExtender< + ErasingFirstGraphAdaptorBase<_Graph, FirstOutEdgesMap> > Parent; + ErasingFirstGraphAdaptor(Graph& _graph, + FirstOutEdgesMap& _first_out_edges) { + setGraph(_graph); + setFirstOutEdgesMap(_first_out_edges); + } + + }; + + ///@} + +} //namespace lemon + +#endif //LEMON_GRAPH_ADAPTOR_H + diff -r d8475431bbbb -r 8e85e6bbefdf lemon/graph_reader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/graph_reader.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,808 @@ +/* -*- C++ -*- + * lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\ingroup io_group +///\file +///\brief Lemon Graph Format reader. + +#ifndef LEMON_GRAPH_READER_H +#define LEMON_GRAPH_READER_H + +#include + +#include +#include + +namespace lemon { + + /// \addtogroup io_group + /// @{ + + /// \brief The graph reader class. + /// + /// The given file format may contain several maps and labeled nodes or + /// edges. + /// + /// If you read a graph you need not read all the maps and items just those + /// that you need. The interface of the \c GraphReader is very similar to + /// the GraphWriter but the reading method does not depend on the order the + /// given commands. + /// + /// The reader object suppose that each not readed value does not contain + /// whitespaces, therefore it has some extra possibilities to control how + /// it should skip the values when the string representation contains spaces. + /// + /// \code + /// GraphReader reader(std::cin, graph); + /// \endcode + /// + /// The \c readNodeMap() function reads a map from the \c \@nodeset section. + /// If there is a map that you do not want to read from the file and there is + /// whitespace in the string represenation of the values then you should + /// call the \c skipNodeMap() template member function with proper + /// parameters. + /// + /// \code + /// reader.readNodeMap("coords", coords); + /// + /// reader.readNodeMap("label", labelMap); + /// reader.skipNodeMap("description"); + /// + /// reader.readNodeMap("color", colorMap); + /// \endcode + /// + /// With the \c readEdgeMap() member function you can give an edge map + /// reading command similar to the NodeMaps. + /// + /// \code + /// reader.readEdgeMap("weight", weightMap); + /// reader.readEdgeMap("label", labelMap); + /// \endcode + /// + /// With \c readNode() and \c readEdge() functions you can read + /// labeled Nodes and Edges. + /// + /// \code + /// reader.readNode("source", sourceNode); + /// reader.readNode("target", targetNode); + /// + /// reader.readEdge("observed", edge); + /// \endcode + /// + /// With the \c readAttribute() functions you can read an attribute + /// in a variable. You can specify the reader for the attribute as + /// the nodemaps. + /// + /// After you give all read commands you must call the \c run() member + /// function, which execute all the commands. + /// + /// \code + /// reader.run(); + /// \endcode + /// + /// \see DefaultReaderTraits + /// \see QuotedStringReader + /// \see \ref GraphWriter + /// \see \ref graph-io-page + /// \author Balazs Dezso + template + class GraphReader { + public: + + typedef _Graph Graph; + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + + typedef _ReaderTraits ReaderTraits; + typedef typename ReaderTraits::Skipper DefaultSkipper; + + /// \brief Construct a new GraphReader. + /// + /// Construct a new GraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + GraphReader(std::istream& _is, + typename SmartParameter::Type _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + edge_reader(*reader, edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Construct a new GraphReader. + /// + /// Construct a new GraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + GraphReader(const std::string& _filename, + typename SmartParameter::Type _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(new LemonReader(_filename)), own_reader(true), + skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + edge_reader(*reader, edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Construct a new GraphReader. + /// + /// Construct a new GraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + GraphReader(LemonReader& _reader, + typename SmartParameter::Type _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(_reader), own_reader(false), skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + edge_reader(*reader, edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Destruct the graph reader. + /// + /// Destruct the graph reader. + ~GraphReader() { + if (own_reader) + delete reader; + } + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + GraphReader& readNodeMap(std::string name, Map& map) { + nodeset_reader.readNodeMap(name, map); + return *this; + } + + template + GraphReader& readNodeMap(std::string name, const Map& map) { + nodeset_reader.readNodeMap(name, map); + return *this; + } + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + GraphReader& readNodeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + nodeset_reader.readNodeMap(name, map, reader); + return *this; + } + + template + GraphReader& readNodeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + nodeset_reader.readNodeMap(name, map, reader); + return *this; + } + + /// \brief Add a new node map skipper command for the reader. + /// + /// Add a new node map skipper command for the reader. + template + GraphReader& skipNodeMap(std::string name, + const Reader& reader = Reader()) { + nodeset_reader.skipNodeMap(name, reader); + return *this; + } + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + GraphReader& readEdgeMap(std::string name, Map& map) { + edgeset_reader.readEdgeMap(name, map); + return *this; + } + + template + GraphReader& readEdgeMap(std::string name, const Map& map) { + edgeset_reader.readEdgeMap(name, map); + return *this; + } + + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + GraphReader& readEdgeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + edgeset_reader.readEdgeMap(name, map, reader); + return *this; + } + + template + GraphReader& readEdgeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + edgeset_reader.readEdgeMap(name, map, reader); + return *this; + } + + /// \brief Add a new edge map skipper command for the reader. + /// + /// Add a new edge map skipper command for the reader. + template + GraphReader& skipEdgeMap(std::string name, + const Reader& reader = Reader()) { + edgeset_reader.skipEdgeMap(name, reader); + return *this; + } + + /// \brief Add a new labeled node reader for the reader. + /// + /// Add a new labeled node reader for the reader. + GraphReader& readNode(std::string name, Node& node) { + node_reader.readNode(name, node); + return *this; + } + + /// \brief Add a new labeled edge reader for the reader. + /// + /// Add a new labeled edge reader for the reader. + GraphReader& readEdge(std::string name, Edge& edge) { + edge_reader.readEdge(name, edge); + } + + /// \brief Add a new attribute reader command. + /// + /// Add a new attribute reader command. + template + GraphReader& readAttribute(std::string name, Value& value) { + attribute_reader.readAttribute(name, value); + return *this; + } + + /// \brief Add a new attribute reader command. + /// + /// Add a new attribute reader command. + template + GraphReader& readAttribute(std::string name, Value& value, + const Reader& reader) { + attribute_reader.readAttribute(name, value, reader); + return *this; + } + + /// \brief Conversion operator to LemonReader. + /// + /// Conversion operator to LemonReader. It make possible + /// to access the encapsulated \e LemonReader, this way + /// you can attach to this reader new instances of + /// \e LemonReader::SectionReader. + operator LemonReader&() { + return *reader; + } + + /// \brief Executes the reader commands. + /// + /// Executes the reader commands. + void run() { + reader->run(); + } + + /// \brief Gives back the node by its id. + /// + /// It reads an id from the stream and gives back which node belongs to + /// it. It is possible only if there was read an "id" named node map. + Node readId(std::istream& is, Node) const { + return nodeset_reader.readId(is, Node()); + } + + /// \brief Gives back the edge by its id. + /// + /// It reads an id from the stream and gives back which edge belongs to + /// it. It is possible only if there was read an "id" named edge map. + Edge readId(std::istream& is, Edge) const { + return edgeset_reader.readId(is, Edge()); + } + + private: + + LemonReader* reader; + bool own_reader; + + DefaultSkipper skipper; + + NodeSetReader nodeset_reader; + EdgeSetReader edgeset_reader; + + NodeReader node_reader; + EdgeReader edge_reader; + + AttributeReader attribute_reader; + }; + + /// \brief Read a graph from the input. + /// + /// Read a graph from the input. + /// \param is The input stream. + /// \param g The graph. + /// \param capacity The capacity map. + /// \param s The source node. + /// \param t The target node. + /// \param cost The cost map. + template + void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, + typename Graph::Node &s, typename Graph::Node &t, + CostMap& cost) { + GraphReader reader(is, g); + reader.readEdgeMap("capacity", capacity); + reader.readEdgeMap("cost", cost); + reader.readNode("source", s); + reader.readNode("target", t); + reader.run(); + } + + /// \brief Read a graph from the input. + /// + /// Read a graph from the input. + /// \param is The input stream. + /// \param g The graph. + /// \param capacity The capacity map. + /// \param s The source node. + /// \param t The target node. + template + void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, + typename Graph::Node &s, typename Graph::Node &t) { + GraphReader reader(is, g); + reader.readEdgeMap("capacity", capacity); + reader.readNode("source", s); + reader.readNode("target", t); + reader.run(); + } + + /// \brief Read a graph from the input. + /// + /// Read a graph from the input. + /// \param is The input stream. + /// \param g The graph. + /// \param capacity The capacity map. + /// \param s The source node. + template + void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, + typename Graph::Node &s) { + GraphReader reader(is, g); + reader.readEdgeMap("capacity", capacity); + reader.readNode("source", s); + reader.run(); + } + + /// \brief Read a graph from the input. + /// + /// Read a graph from the input. + /// \param is The input stream. + /// \param g The graph. + /// \param capacity The capacity map. + template + void readGraph(std::istream& is, Graph &g, CapacityMap& capacity) { + GraphReader reader(is, g); + reader.readEdgeMap("capacity", capacity); + reader.run(); + } + + /// \brief Read a graph from the input. + /// + /// Read a graph from the input. + /// \param is The input stream. + /// \param g The graph. + template + void readGraph(std::istream& is, Graph &g) { + GraphReader reader(is, g); + reader.run(); + } + + /// \brief The undir graph reader class. + /// + /// The given file format may contain several maps and labeled nodes or + /// edges. + /// + /// If you read a graph you need not read all the maps and items just those + /// that you need. The interface of the \c GraphReader is very similar to + /// the GraphWriter but the reading method does not depend on the order the + /// given commands. + /// + /// The reader object suppose that each not readed value does not contain + /// whitespaces, therefore it has some extra possibilities to control how + /// it should skip the values when the string representation contains spaces. + /// + /// \code + /// UndirGraphReader reader(std::cin, graph); + /// \endcode + /// + /// The \c readNodeMap() function reads a map from the \c \@nodeset section. + /// If there is a map that you do not want to read from the file and there is + /// whitespace in the string represenation of the values then you should + /// call the \c skipNodeMap() template member function with proper + /// parameters. + /// + /// \code + /// reader.readNodeMap("coords", coords); + /// + /// reader.readNodeMap("label", labelMap); + /// reader.skipNodeMap("description"); + /// + /// reader.readNodeMap("color", colorMap); + /// \endcode + /// + /// With the \c readUndirEdgeMap() member function you can give an + /// undir edge map reading command similar to the NodeMaps. + /// + /// \code + /// reader.readUndirEdgeMap("capacity", capacityMap); + /// \endcode + /// + /// The reading of the directed edge maps is just a syntactical sugar. + /// It reads two undirected edgemaps into a directed edge map. The + /// undirected edge maps' name should be start with the \c '+' and the + /// \c '-' character and the same. + /// + /// \code + /// reader.readEdgeMap("flow", flowMap); + /// \endcode + /// + /// With \c readNode() and \c readUndirEdge() functions you can read + /// labeled Nodes and UndirEdges. + /// + /// \code + /// reader.readNode("source", sourceNode); + /// reader.readNode("target", targetNode); + /// + /// reader.readUndirEdge("observed", undirEdge); + /// \endcode + /// + /// With the \c readAttribute() functions you can read an attribute + /// in a variable. You can specify the reader for the attribute as + /// the nodemaps. + /// + /// After you give all read commands you must call the \c run() member + /// function, which execute all the commands. + /// + /// \code + /// reader.run(); + /// \endcode + /// + /// \see GraphReader + /// \see DefaultReaderTraits + /// \see \ref UndirGraphWriter + /// \see \ref graph-io-page + /// + /// \author Balazs Dezso + template + class UndirGraphReader { + public: + + typedef _Graph Graph; + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + typedef typename Graph::UndirEdge UndirEdge; + + typedef _ReaderTraits ReaderTraits; + typedef typename ReaderTraits::Skipper DefaultSkipper; + + /// \brief Construct a new UndirGraphReader. + /// + /// Construct a new UndirGraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + UndirGraphReader(std::istream& _is, Graph& _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + undir_edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + undir_edge_reader(*reader, undir_edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Construct a new UndirGraphReader. + /// + /// Construct a new UndirGraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + UndirGraphReader(const std::string& _filename, Graph& _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(new LemonReader(_filename)), own_reader(true), + skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + undir_edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + undir_edge_reader(*reader, undir_edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Construct a new UndirGraphReader. + /// + /// Construct a new UndirGraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + UndirGraphReader(LemonReader& _reader, Graph& _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(_reader), own_reader(false), skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + undir_edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + undir_edge_reader(*reader, undir_edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Destruct the graph reader. + /// + /// Destruct the graph reader. + ~UndirGraphReader() { + if (own_reader) + delete reader; + } + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + UndirGraphReader& readNodeMap(std::string name, Map& map) { + nodeset_reader.readNodeMap(name, map); + return *this; + } + + template + UndirGraphReader& readNodeMap(std::string name, const Map& map) { + nodeset_reader.readNodeMap(name, map); + return *this; + } + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + UndirGraphReader& readNodeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + nodeset_reader.readNodeMap(name, map, reader); + return *this; + } + + template + UndirGraphReader& readNodeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + nodeset_reader.readNodeMap(name, map, reader); + return *this; + } + + /// \brief Add a new node map skipper command for the reader. + /// + /// Add a new node map skipper command for the reader. + template + UndirGraphReader& skipNodeMap(std::string name, + const Reader& reader = Reader()) { + nodeset_reader.skipNodeMap(name, reader); + return *this; + } + + /// \brief Add a new undirected edge map reader command for the reader. + /// + /// Add a new undirected edge map reader command for the reader. + template + UndirGraphReader& readUndirEdgeMap(std::string name, Map& map) { + undir_edgeset_reader.readUndirEdgeMap(name, map); + return *this; + } + + template + UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map) { + undir_edgeset_reader.readUndirEdgeMap(name, map); + return *this; + } + + + /// \brief Add a new undirected edge map reader command for the reader. + /// + /// Add a new undirected edge map reader command for the reader. + template + UndirGraphReader& readUndirEdgeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + undir_edgeset_reader.readUndirEdgeMap(name, map, reader); + return *this; + } + + template + UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + undir_edgeset_reader.readUndirEdgeMap(name, map, reader); + return *this; + } + + /// \brief Add a new undirected edge map skipper command for the reader. + /// + /// Add a new undirected edge map skipper command for the reader. + template + UndirGraphReader& skipUndirEdgeMap(std::string name, + const Reader& reader = Reader()) { + undir_edgeset_reader.skipUndirMap(name, reader); + return *this; + } + + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + UndirGraphReader& readEdgeMap(std::string name, Map& map) { + undir_edgeset_reader.readEdgeMap(name, map); + return *this; + } + + template + UndirGraphReader& readEdgeMap(std::string name, const Map& map) { + undir_edgeset_reader.readEdgeMap(name, map); + return *this; + } + + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + UndirGraphReader& readEdgeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + undir_edgeset_reader.readEdgeMap(name, map, reader); + return *this; + } + + template + UndirGraphReader& readEdgeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + undir_edgeset_reader.readEdgeMap(name, map, reader); + return *this; + } + + /// \brief Add a new edge map skipper command for the reader. + /// + /// Add a new edge map skipper command for the reader. + template + UndirGraphReader& skipEdgeMap(std::string name, + const Reader& reader = Reader()) { + undir_edgeset_reader.skipEdgeMap(name, reader); + return *this; + } + + /// \brief Add a new labeled node reader for the reader. + /// + /// Add a new labeled node reader for the reader. + UndirGraphReader& readNode(std::string name, Node& node) { + node_reader.readNode(name, node); + return *this; + } + + /// \brief Add a new labeled edge reader for the reader. + /// + /// Add a new labeled edge reader for the reader. + UndirGraphReader& readEdge(std::string name, Edge& edge) { + undir_edge_reader.readEdge(name, edge); + } + + /// \brief Add a new labeled undirected edge reader for the reader. + /// + /// Add a new labeled undirected edge reader for the reader. + UndirGraphReader& readUndirEdge(std::string name, UndirEdge& edge) { + undir_edge_reader.readUndirEdge(name, edge); + } + + /// \brief Add a new attribute reader command. + /// + /// Add a new attribute reader command. + template + UndirGraphReader& readAttribute(std::string name, Value& value) { + attribute_reader.readAttribute(name, value); + return *this; + } + + /// \brief Add a new attribute reader command. + /// + /// Add a new attribute reader command. + template + UndirGraphReader& readAttribute(std::string name, Value& value, + const Reader& reader) { + attribute_reader.readAttribute(name, value, reader); + return *this; + } + + /// \brief Conversion operator to LemonReader. + /// + /// Conversion operator to LemonReader. It make possible + /// to access the encapsulated \e LemonReader, this way + /// you can attach to this reader new instances of + /// \e LemonReader::SectionReader. + operator LemonReader&() { + return *reader; + } + + /// \brief Executes the reader commands. + /// + /// Executes the reader commands. + void run() { + reader->run(); + } + + /// \brief Gives back the node by its id. + /// + /// It reads an id from the stream and gives back which node belongs to + /// it. It is possible only if there was read an "id" named node map. + Node readId(std::istream& is, Node) const { + return nodeset_reader.readId(is, Node()); + } + + /// \brief Gives back the edge by its id. + /// + /// It reads an id from the stream and gives back which edge belongs to + /// it. It is possible only if there was read an "id" named edge map. + Edge readId(std::istream& is, Edge) const { + return undir_edgeset_reader.readId(is, Edge()); + } + + /// \brief Gives back the undirected edge by its id. + /// + /// It reads an id from the stream and gives back which undirected edge + /// belongs to it. It is possible only if there was read an "id" named + /// edge map. + UndirEdge readId(std::istream& is, UndirEdge) const { + return undir_edgeset_reader.readId(is, UndirEdge()); + } + + + private: + + LemonReader* reader; + bool own_reader; + + DefaultSkipper skipper; + + NodeSetReader nodeset_reader; + UndirEdgeSetReader undir_edgeset_reader; + + NodeReader node_reader; + UndirEdgeReader undir_edge_reader; + + AttributeReader attribute_reader; + }; + + /// \brief Read an undir graph from the input. + /// + /// Read an undir graph from the input. + /// \param is The input stream. + /// \param g The graph. + /// \param capacity The capacity map. + template + void readUndirGraph(std::istream& is, Graph &g, CapacityMap& capacity) { + UndirGraphReader reader(is, g); + reader.readUndirEdgeMap("capacity", capacity); + reader.run(); + } + + /// \brief Read an undir graph from the input. + /// + /// Read an undir graph from the input. + /// \param is The input stream. + /// \param g The graph. + template + void readUndirGraph(std::istream& is, Graph &g) { + UndirGraphReader reader(is, g); + reader.run(); + } + + /// @} +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/graph_to_eps.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/graph_to_eps.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,1026 @@ +/* -*- C++ -*- + * lemon/graph_to_eps.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_GRAPH_TO_EPS_H +#define LEMON_GRAPH_TO_EPS_H + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +///\ingroup io_group +///\file +///\brief Simple graph drawer +/// +///\author Alpar Juttner + +namespace lemon { + +///Data structure representing RGB colors. + +///Data structure representing RGB colors. +///\ingroup misc +class Color +{ + double _r,_g,_b; +public: + ///Default constructor + Color() {} + ///Constructor + Color(double r,double g,double b) :_r(r),_g(g),_b(b) {}; + ///Returns the red component + + ///\todo \c red() could be a better name... + double getR() const {return _r;} + ///Returns the green component + double getG() const {return _g;} + ///Returns the blue component + double getB() const {return _b;} + ///Set the color components + void set(double r,double g,double b) { _r=r;_g=g;_b=b; }; +}; + +///Maps ints to different \ref Color "Color"s + +///This map assing one of the predefined \ref Color "Color"s +///to each int. It is possible to change the colors as well as their +///number. The integer range is cyclically mapped to the provided set of colors. +/// +///This is a true \ref concept::ReferenceMap "reference map", so you can also +///change the actual colors. + +class ColorSet : public MapBase +{ + std::vector colors; +public: + ///Constructor + + ///Constructor + ///\param have_white indicates wheter white is + ///amongst the provided color (\c true) or not (\c false). If it is true, + ///white will be assigned to \c 0. + ///\param num the number of the allocated colors. If it is \c 0 + ///the default color configuration is set up (26 color plus the while). + ///If \c num is less then 26/27 then the default color list is cut. Otherwise + ///the color list is filled repeatedly with the default color list. + ColorSet(bool have_white=false,int num=0) + { + do { + if(have_white) colors.push_back(Color(1,1,1)); + + colors.push_back(Color(0,0,0)); + colors.push_back(Color(1,0,0)); + colors.push_back(Color(0,1,0)); + colors.push_back(Color(0,0,1)); + colors.push_back(Color(1,1,0)); + colors.push_back(Color(1,0,1)); + colors.push_back(Color(0,1,1)); + + colors.push_back(Color(.5,0,0)); + colors.push_back(Color(0,.5,0)); + colors.push_back(Color(0,0,.5)); + colors.push_back(Color(.5,.5,0)); + colors.push_back(Color(.5,0,.5)); + colors.push_back(Color(0,.5,.5)); + + colors.push_back(Color(.5,.5,.5)); + colors.push_back(Color(1,.5,.5)); + colors.push_back(Color(.5,1,.5)); + colors.push_back(Color(.5,.5,1)); + colors.push_back(Color(1,1,.5)); + colors.push_back(Color(1,.5,1)); + colors.push_back(Color(.5,1,1)); + + colors.push_back(Color(1,.5,0)); + colors.push_back(Color(.5,1,0)); + colors.push_back(Color(1,0,.5)); + colors.push_back(Color(0,1,.5)); + colors.push_back(Color(0,.5,1)); + colors.push_back(Color(.5,0,1)); + } while(int(colors.size())0) colors.resize(num); + } + ///\e + Color &operator[](int i) + { + return colors[i%colors.size()]; + } + ///\e + const Color &operator[](int i) const + { + return colors[i%colors.size()]; + } + ///\e + void set(int i,const Color &c) + { + colors[i%colors.size()]=c; + } + ///Sets the number of the exiting colors. + void resize(int s) { colors.resize(s);} + ///Returns the munber of the existing colors. + std::size_t size() { return colors.size();} +}; + +///Returns a visible distinct \ref Color + +///Returns a \ref Color which is as different from the given parameter +///as it is possible. +inline Color distantColor(const Color &c) +{ + return Color(c.getR()<.5?1:0,c.getG()<.5?1:0,c.getB()<.5?1:0); +} +///Returns black for light colors and white for the dark ones. + +///Returns black for light colors and white for the dark ones. +///\todo weighted average would be better +inline Color distantBW(const Color &c){ + double v=(.2125*c.getR()+.7154*c.getG()+.0721*c.getB())<.5?1:0; + return Color(v,v,v); +} + +///Default traits class of \ref GraphToEps + +///Default traits class of \ref GraphToEps +/// +///\c G is the type of the underlying graph. +template +struct DefaultGraphToEpsTraits +{ + typedef G Graph; + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::Edge Edge; + typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::InEdgeIt InEdgeIt; + typedef typename Graph::OutEdgeIt OutEdgeIt; + + + const Graph &g; + + std::ostream& os; + + ConstMap > _coords; + ConstMap _nodeSizes; + ConstMap _nodeShapes; + + ConstMap _nodeColors; + ConstMap _edgeColors; + + ConstMap _edgeWidths; + + double _edgeWidthScale; + + double _nodeScale; + double _xBorder, _yBorder; + double _scale; + double _nodeBorderQuotient; + + bool _drawArrows; + double _arrowLength, _arrowWidth; + + bool _showNodes, _showEdges; + + bool _enableParallel; + double _parEdgeDist; + + bool _showNodeText; + ConstMap _nodeTexts; + double _nodeTextSize; + + bool _showNodePsText; + ConstMap _nodePsTexts; + char *_nodePsTextsPreamble; + + bool _undir; + bool _pleaseRemoveOsStream; + + bool _scaleToA4; + + std::string _title; + std::string _copyright; + + enum NodeTextColorType + { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType; + ConstMap _nodeTextColors; + + ///Constructor + + ///Constructor + ///\param _g is a reference to the graph to be printed + ///\param _os is a reference to the output stream. + ///\param _os is a reference to the output stream. + ///\param _pros If it is \c true, then the \c ostream referenced by \c _os + ///will be explicitly deallocated by the destructor. + ///By default it is std::cout + DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout, + bool _pros=false) : + g(_g), os(_os), + _coords(xy(1,1)), _nodeSizes(1.0), _nodeShapes(0), + _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)), + _edgeWidths(1), _edgeWidthScale(0.3), + _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0), + _nodeBorderQuotient(.1), + _drawArrows(false), _arrowLength(1), _arrowWidth(0.3), + _showNodes(true), _showEdges(true), + _enableParallel(false), _parEdgeDist(1), + _showNodeText(false), _nodeTexts(false), _nodeTextSize(1), + _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0), + _undir(false), + _pleaseRemoveOsStream(_pros), _scaleToA4(false), + _nodeTextColorType(SAME_COL), _nodeTextColors(Color(0,0,0)) + {} +}; + +///Helper class to implement the named parameters of \ref graphToEps() + +///Helper class to implement the named parameters of \ref graphToEps() +///\todo Is 'helper class' a good name for this? +/// +///\todo Follow PostScript's DSC. +/// Use own dictionary. +///\todo Useful new features. +/// - Linestyles: dotted, dashed etc. +/// - A second color and percent value for the lines. +template class GraphToEps : public T +{ + // Can't believe it is required by the C++ standard + using T::g; + using T::os; + + using T::_coords; + using T::_nodeSizes; + using T::_nodeShapes; + using T::_nodeColors; + using T::_edgeColors; + using T::_edgeWidths; + + using T::_edgeWidthScale; + using T::_nodeScale; + using T::_xBorder; + using T::_yBorder; + using T::_scale; + using T::_nodeBorderQuotient; + + using T::_drawArrows; + using T::_arrowLength; + using T::_arrowWidth; + + using T::_showNodes; + using T::_showEdges; + + using T::_enableParallel; + using T::_parEdgeDist; + + using T::_showNodeText; + using T::_nodeTexts; + using T::_nodeTextSize; + + using T::_showNodePsText; + using T::_nodePsTexts; + using T::_nodePsTextsPreamble; + + using T::_undir; + using T::_pleaseRemoveOsStream; + + using T::_scaleToA4; + + using T::_title; + using T::_copyright; + + using T::NodeTextColorType; + using T::CUST_COL; + using T::DIST_COL; + using T::DIST_BW; + using T::_nodeTextColorType; + using T::_nodeTextColors; + // dradnats ++C eht yb deriuqer si ti eveileb t'naC + + typedef typename T::Graph Graph; + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::Edge Edge; + typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::InEdgeIt InEdgeIt; + typedef typename Graph::OutEdgeIt OutEdgeIt; + + static const int INTERPOL_PREC=20; + static const double A4HEIGHT = 841.8897637795276; + static const double A4WIDTH = 595.275590551181; + static const double A4BORDER = 15; + + bool dontPrint; + +public: + ///Node shapes + + ///Node shapes + /// + enum NodeShapes { + /// = 0 + ///\image html nodeshape_0.png + ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm + CIRCLE=0, + /// = 1 + ///\image html nodeshape_1.png + ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm + /// + SQUARE=1, + /// = 2 + ///\image html nodeshape_2.png + ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm + /// + DIAMOND=2 + }; + +private: + class edgeLess { + const Graph &g; + public: + edgeLess(const Graph &_g) : g(_g) {} + bool operator()(Edge a,Edge b) const + { + Node ai=std::min(g.source(a),g.target(a)); + Node aa=std::max(g.source(a),g.target(a)); + Node bi=std::min(g.source(b),g.target(b)); + Node ba=std::max(g.source(b),g.target(b)); + return ai + static std::string psOut(const xy &p) + { + std::ostringstream os; + os << p.x << ' ' << p.y; + return os.str(); + } + static std::string psOut(const Color &c) + { + std::ostringstream os; + os << c.getR() << ' ' << c.getG() << ' ' << c.getB(); + return os.str(); + } + +public: + GraphToEps(const T &t) : T(t), dontPrint(false) {}; + + template struct CoordsTraits : public T { + const X &_coords; + CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {} + }; + ///Sets the map of the node coordinates + + ///Sets the map of the node coordinates. + ///\param x must be a node map with xy or \ref xy "xy" values. + template GraphToEps > coords(const X &x) { + dontPrint=true; + return GraphToEps >(CoordsTraits(*this,x)); + } + template struct NodeSizesTraits : public T { + const X &_nodeSizes; + NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {} + }; + ///Sets the map of the node sizes + + ///Sets the map of the node sizes + ///\param x must be a node map with \c double (or convertible) values. + template GraphToEps > nodeSizes(const X &x) + { + dontPrint=true; + return GraphToEps >(NodeSizesTraits(*this,x)); + } + template struct NodeShapesTraits : public T { + const X &_nodeShapes; + NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {} + }; + ///Sets the map of the node shapes + + ///Sets the map of the node shapes. + ///The availabe shape values + ///can be found in \ref NodeShapes "enum NodeShapes". + ///\param x must be a node map with \c int (or convertible) values. + ///\sa NodeShapes + template GraphToEps > nodeShapes(const X &x) + { + dontPrint=true; + return GraphToEps >(NodeShapesTraits(*this,x)); + } + template struct NodeTextsTraits : public T { + const X &_nodeTexts; + NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {} + }; + ///Sets the text printed on the nodes + + ///Sets the text printed on the nodes + ///\param x must be a node map with type that can be pushed to a standard + ///ostream. + template GraphToEps > nodeTexts(const X &x) + { + dontPrint=true; + _showNodeText=true; + return GraphToEps >(NodeTextsTraits(*this,x)); + } + template struct NodePsTextsTraits : public T { + const X &_nodePsTexts; + NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {} + }; + ///Inserts a PostScript block to the nodes + + ///With this command it is possible to insert a verbatim PostScript + ///block to the nodes. + ///The PS current point will be moved to the centre of the node before + ///the PostScript block inserted. + /// + ///Before and after the block a newline character is inserted to you + ///don't have to bother with the separators. + /// + ///\param x must be a node map with type that can be pushed to a standard + ///ostream. + /// + ///\sa nodePsTextsPreamble() + ///\todo Offer the choise not to move to the centre but pass the coordinates + ///to the Postscript block inserted. + template GraphToEps > nodePsTexts(const X &x) + { + dontPrint=true; + _showNodePsText=true; + return GraphToEps >(NodePsTextsTraits(*this,x)); + } + template struct EdgeWidthsTraits : public T { + const X &_edgeWidths; + EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {} + }; + ///Sets the map of the edge widths + + ///Sets the map of the edge widths + ///\param x must be a edge map with \c double (or convertible) values. + template GraphToEps > edgeWidths(const X &x) + { + dontPrint=true; + return GraphToEps >(EdgeWidthsTraits(*this,x)); + } + + template struct NodeColorsTraits : public T { + const X &_nodeColors; + NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {} + }; + ///Sets the map of the node colors + + ///Sets the map of the node colors + ///\param x must be a node map with \ref Color values. + template GraphToEps > + nodeColors(const X &x) + { + dontPrint=true; + return GraphToEps >(NodeColorsTraits(*this,x)); + } + template struct NodeTextColorsTraits : public T { + const X &_nodeTextColors; + NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {} + }; + ///Sets the map of the node text colors + + ///Sets the map of the node text colors + ///\param x must be a node map with \ref Color values. + template GraphToEps > + nodeTextColors(const X &x) + { + dontPrint=true; + _nodeTextColorType=CUST_COL; + return GraphToEps > + (NodeTextColorsTraits(*this,x)); + } + template struct EdgeColorsTraits : public T { + const X &_edgeColors; + EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {} + }; + ///Sets the map of the edge colors + + ///Sets the map of the edge colors + ///\param x must be a edge map with \ref Color values. + template GraphToEps > + edgeColors(const X &x) + { + dontPrint=true; + return GraphToEps >(EdgeColorsTraits(*this,x)); + } + ///Sets a global scale factor for node sizes + + ///Sets a global scale factor for node sizes + /// + GraphToEps &nodeScale(double d) {_nodeScale=d;return *this;} + ///Sets a global scale factor for edge widths + + ///Sets a global scale factor for edge widths + /// + GraphToEps &edgeWidthScale(double d) {_edgeWidthScale=d;return *this;} + ///Sets a global scale factor for the whole picture + + ///Sets a global scale factor for the whole picture + /// + GraphToEps &scale(double d) {_scale=d;return *this;} + ///Sets the width of the border around the picture + + ///Sets the width of the border around the picture + /// + GraphToEps &border(double b) {_xBorder=_yBorder=b;return *this;} + ///Sets the width of the border around the picture + + ///Sets the width of the border around the picture + /// + GraphToEps &border(double x, double y) { + _xBorder=x;_yBorder=y;return *this; + } + ///Sets whether to draw arrows + + ///Sets whether to draw arrows + /// + GraphToEps &drawArrows(bool b=true) {_drawArrows=b;return *this;} + ///Sets the length of the arrowheads + + ///Sets the length of the arrowheads + /// + GraphToEps &arrowLength(double d) {_arrowLength*=d;return *this;} + ///Sets the width of the arrowheads + + ///Sets the width of the arrowheads + /// + GraphToEps &arrowWidth(double d) {_arrowWidth*=d;return *this;} + + ///Scales the drawing to fit to A4 page + + ///Scales the drawing to fit to A4 page + /// + GraphToEps &scaleToA4() {_scaleToA4=true;return *this;} + + ///Enables parallel edges + + ///Enables parallel edges + ///\todo Partially implemented + GraphToEps &enableParallel(bool b=true) {_enableParallel=b;return *this;} + + ///Sets the distance + + ///Sets the distance + /// + GraphToEps &parEdgeDist(double d) {_parEdgeDist*=d;return *this;} + + ///Hides the edges + + ///Hides the edges + /// + GraphToEps &hideEdges(bool b=true) {_showEdges=!b;return *this;} + ///Hides the nodes + + ///Hides the nodes + /// + GraphToEps &hideNodes(bool b=true) {_showNodes=!b;return *this;} + + ///Sets the size of the node texts + + ///Sets the size of the node texts + /// + GraphToEps &nodeTextSize(double d) {_nodeTextSize=d;return *this;} + + ///Sets the color of the node texts to be different from the node color + + ///Sets the color of the node texts to be as different from the node color + ///as it is possible + /// + GraphToEps &distantColorNodeTexts() + {_nodeTextColorType=DIST_COL;return *this;} + ///Sets the color of the node texts to be black or white and always visible. + + ///Sets the color of the node texts to be black or white according to + ///which is more + ///different from the node color + /// + GraphToEps &distantBWNodeTexts() + {_nodeTextColorType=DIST_BW;return *this;} + + ///Gives a preamble block for node Postscript block. + + ///Gives a preamble block for node Postscript block. + /// + ///\sa nodePsTexts() + GraphToEps & nodePsTextsPreamble(const char *str) { + _nodePsTextsPreamble=str ;return *this; + } + ///Sets whether the the graph is undirected + + ///Sets whether the the graph is undirected + /// + GraphToEps &undir(bool b=true) {_undir=b;return *this;} + ///Sets whether the the graph is directed + + ///Sets whether the the graph is directed. + ///Use it to show the undirected edges as a pair of directed ones. + GraphToEps &bidir(bool b=true) {_undir=!b;return *this;} + + ///Sets the title. + + ///Sets the title of the generated image, + ///namely it inserts a %%Title: DSC field to the header of + ///the EPS file. + GraphToEps &title(const std::string &t) {_title=t;return *this;} + ///Sets the copyright statement. + + ///Sets the copyright statement of the generated image, + ///namely it inserts a %%Copyright: DSC field to the header of + ///the EPS file. + ///\todo Multiline copyright notice could be supported. + GraphToEps ©right(const std::string &t) {_copyright=t;return *this;} + +protected: + bool isInsideNode(xy p, double r,int t) + { + switch(t) { + case CIRCLE: + return p.normSquare()<=r*r; + case SQUARE: + return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r; + case DIAMOND: + return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r; + } + return false; + } + +public: + ~GraphToEps() { } + + ///Draws the graph. + + ///Like other functions using + ///\ref named-templ-func-param "named template parameters", + ///this function calles the algorithm itself, i.e. in this case + ///it draws the graph. + void run() { + if(dontPrint) return; + + os << "%!PS-Adobe-2.0 EPSF-2.0\n"; + if(_title.size()>0) os << "%%Title: " << _title << '\n'; + if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n'; +// << "%%Copyright: XXXX\n" + os << "%%Creator: LEMON GraphToEps function\n"; + + { + char cbuf[50]; + timeval tv; + gettimeofday(&tv, 0); + ctime_r(&tv.tv_sec,cbuf); + os << "%%CreationDate: " << cbuf; + } + ///\todo: Chech whether the graph is empty. + BoundingBox bb; + for(NodeIt n(g);n!=INVALID;++n) { + double ns=_nodeSizes[n]*_nodeScale; + xy p(ns,ns); + bb+=p+_coords[n]; + bb+=-p+_coords[n]; + } + if(_scaleToA4) + os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n"; + else os << "%%BoundingBox: " + << bb.left()* _scale-_xBorder << ' ' + << bb.bottom()*_scale-_yBorder << ' ' + << bb.right()* _scale+_xBorder << ' ' + << bb.top()* _scale+_yBorder << '\n'; + + os << "%%EndComments\n"; + + //x1 y1 x2 y2 x3 y3 cr cg cb w + os << "/lb { setlinewidth setrgbcolor newpath moveto\n" + << " 4 2 roll 1 index 1 index curveto stroke } bind def\n"; + os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n"; + //x y r + os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n"; + //x y r + os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n" + << " 2 index 1 index sub 2 index 2 index add lineto\n" + << " 2 index 1 index sub 2 index 2 index sub lineto\n" + << " 2 index 1 index add 2 index 2 index sub lineto\n" + << " closepath pop pop pop} bind def\n"; + //x y r + os << "/di { newpath 2 index 1 index add 2 index moveto\n" + << " 2 index 2 index 2 index add lineto\n" + << " 2 index 1 index sub 2 index lineto\n" + << " 2 index 2 index 2 index sub lineto\n" + << " closepath pop pop pop} bind def\n"; + // x y r cr cg cb + os << "/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill\n" + << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n" + << " } bind def\n"; + os << "/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill\n" + << " setrgbcolor " << 1+_nodeBorderQuotient << " div sq fill\n" + << " } bind def\n"; + os << "/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill\n" + << " setrgbcolor " << 1+_nodeBorderQuotient << " div di fill\n" + << " } bind def\n"; + os << "/arrl " << _arrowLength << " def\n"; + os << "/arrw " << _arrowWidth << " def\n"; + // l dx_norm dy_norm + os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n"; + //len w dx_norm dy_norm x1 y1 cr cg cb + os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n" + << " /w exch def /len exch def\n" + // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke" + << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n" + << " len w sub arrl sub dx dy lrl\n" + << " arrw dy dx neg lrl\n" + << " dx arrl w add mul dy w 2 div arrw add mul sub\n" + << " dy arrl w add mul dx w 2 div arrw add mul add rlineto\n" + << " dx arrl w add mul neg dy w 2 div arrw add mul sub\n" + << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n" + << " arrw dy dx neg lrl\n" + << " len w sub arrl sub neg dx dy lrl\n" + << " closepath fill } bind def\n"; + os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n" + << " neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n"; + + os << "\ngsave\n"; + if(_scaleToA4) + if(bb.height()>bb.width()) { + double sc= min((A4HEIGHT-2*A4BORDER)/bb.height(), + (A4WIDTH-2*A4BORDER)/bb.width()); + os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' ' + << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER << " translate\n" + << sc << " dup scale\n" + << -bb.left() << ' ' << -bb.bottom() << " translate\n"; + } + else { + //\todo Verify centering + double sc= min((A4HEIGHT-2*A4BORDER)/bb.width(), + (A4WIDTH-2*A4BORDER)/bb.height()); + os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' ' + << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER << " translate\n" + << sc << " dup scale\n90 rotate\n" + << -bb.left() << ' ' << -bb.top() << " translate\n"; + } + else if(_scale!=1.0) os << _scale << " dup scale\n"; + + if(_showEdges) { + os << "%Edges:\ngsave\n"; + if(_enableParallel) { + std::vector el; + for(EdgeIt e(g);e!=INVALID;++e) + if((!_undir||g.source(e)0) + el.push_back(e); + sort(el.begin(),el.end(),edgeLess(g)); + + typename std::vector::iterator j; + for(typename std::vector::iterator i=el.begin();i!=el.end();i=j) { + for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ; + + double sw=0; + for(typename std::vector::iterator e=i;e!=j;++e) + sw+=_edgeWidths[*e]*_edgeWidthScale+_parEdgeDist; + sw-=_parEdgeDist; + sw/=-2.0; + xy dvec(_coords[g.target(*i)]-_coords[g.source(*i)]); + double l=std::sqrt(dvec.normSquare()); + ///\todo better 'epsilon' would be nice here. + xy d(dvec/std::max(l,1e-9)); + xy m; +// m=xy(_coords[g.target(*i)]+_coords[g.source(*i)])/2.0; + +// m=xy(_coords[g.source(*i)])+ +// dvec*(double(_nodeSizes[g.source(*i)])/ +// (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)])); + + m=xy(_coords[g.source(*i)])+ + d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0; + + for(typename std::vector::iterator e=i;e!=j;++e) { + sw+=_edgeWidths[*e]*_edgeWidthScale/2.0; + xy mm=m+rot90(d)*sw/.75; + if(_drawArrows) { + int node_shape; + xy s=_coords[g.source(*e)]; + xy t=_coords[g.target(*e)]; + double rn=_nodeSizes[g.target(*e)]*_nodeScale; + node_shape=_nodeShapes[g.target(*e)]; + Bezier3 bez(s,mm,mm,t); + double t1=0,t2=1; + for(int i=0;i apoint=bez((t1+t2)/2); + rn = _arrowLength+_edgeWidths[*e]*_edgeWidthScale; + rn*=rn; + t2=(t1+t2)/2;t1=0; + for(int i=0;irn) t1=(t1+t2)/2; + else t2=(t1+t2)/2; + xy linend=bez((t1+t2)/2); + bez=bez.before((t1+t2)/2); +// rn=_nodeSizes[g.source(*e)]*_nodeScale; +// node_shape=_nodeShapes[g.source(*e)]; +// t1=0;t2=1; +// for(int i=0;i dd(rot90(linend-apoint)); + dd*=(.5*_edgeWidths[*e]*_edgeWidthScale+_arrowWidth)/ + std::sqrt(dd.normSquare()); + os << "newpath " << psOut(apoint) << " moveto " + << psOut(linend+dd) << " lineto " + << psOut(linend-dd) << " lineto closepath fill\n"; + } + else { + os << _coords[g.source(*e)].x << ' ' + << _coords[g.source(*e)].y << ' ' + << mm.x << ' ' << mm.y << ' ' + << _coords[g.target(*e)].x << ' ' + << _coords[g.target(*e)].y << ' ' + << _edgeColors[*e].getR() << ' ' + << _edgeColors[*e].getG() << ' ' + << _edgeColors[*e].getB() << ' ' + << _edgeWidths[*e]*_edgeWidthScale << " lb\n"; + } + sw+=_edgeWidths[*e]*_edgeWidthScale/2.0+_parEdgeDist; + } + } + } + else for(EdgeIt e(g);e!=INVALID;++e) + if((!_undir||g.source(e)0) + if(_drawArrows) { + xy d(_coords[g.target(e)]-_coords[g.source(e)]); + double rn=_nodeSizes[g.target(e)]*_nodeScale; + int node_shape=_nodeShapes[g.target(e)]; + double t1=0,t2=1; + for(int i=0;istd::cout +/// +///This function also has a lot of +///\ref named-templ-func-param "named parameters", +///they are declared as the members of class \ref GraphToEps. The following +///example shows how to use these parameters. +///\code +/// graphToEps(g,os).scale(10).coords(coords) +/// .nodeScale(2).nodeSizes(sizes) +/// .edgeWidthScale(.4).run(); +///\endcode +///\warning Don't forget to put the \ref GraphToEps::run() "run()" +///to the end of the parameter list. +///\sa GraphToEps +///\sa graphToEps(G &g, char *file_name) +template +GraphToEps > +graphToEps(G &g, std::ostream& os=std::cout) +{ + return + GraphToEps >(DefaultGraphToEpsTraits(g,os)); +} + +///Generates an EPS file from a graph + +///\ingroup misc +///This function does the same as +///\ref graphToEps(G &g,std::ostream& os) +///but it writes its output into the file \c file_name +///instead of a stream. +///\sa graphToEps(G &g, std::ostream& os) +template +GraphToEps > +graphToEps(G &g,const char *file_name) +{ + return GraphToEps > + (DefaultGraphToEpsTraits(g,*new std::ofstream(file_name),true)); +} + +} //END OF NAMESPACE LEMON + +#endif // LEMON_GRAPH_TO_EPS_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/graph_utils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/graph_utils.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,861 @@ +/* -*- C++ -*- + * lemon/graph_utils.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_GRAPH_UTILS_H +#define LEMON_GRAPH_UTILS_H + +#include +#include +#include + +#include +#include +#include + +///\ingroup gutils +///\file +///\brief Graph utilities. +/// +///\todo Please +///revise the documentation. +/// + + +namespace lemon { + + /// \addtogroup gutils + /// @{ + + /// \brief Function to count the items in the graph. + /// + /// This function counts the items in the graph. + /// The complexity of the function is O(n) because + /// it iterates on all of the items. + + template + inline int countItems(const Graph& g) { + int num = 0; + for (ItemIt it(g); it != INVALID; ++it) { + ++num; + } + return num; + } + + // Node counting: + + template + inline + typename enable_if::type + _countNodes(const Graph &g) { + return g.nodeNum(); + } + + template + inline int _countNodes(Wrap w) { + return countItems(w.value); + } + + /// \brief Function to count the nodes in the graph. + /// + /// This function counts the nodes in the graph. + /// The complexity of the function is O(n) but for some + /// graph structure it is specialized to run in O(1). + /// + /// \todo refer how to specialize it + + template + inline int countNodes(const Graph& g) { + return _countNodes(g); + } + + // Edge counting: + + template + inline + typename enable_if::type + _countEdges(const Graph &g) { + return g.edgeNum(); + } + + template + inline int _countEdges(Wrap w) { + return countItems(w.value); + } + + /// \brief Function to count the edges in the graph. + /// + /// This function counts the edges in the graph. + /// The complexity of the function is O(e) but for some + /// graph structure it is specialized to run in O(1). + + template + inline int countEdges(const Graph& g) { + return _countEdges(g); + } + + // Undirected edge counting: + + template + inline + typename enable_if::type + _countUndirEdges(const Graph &g) { + return g.undirEdgeNum(); + } + + template + inline int _countUndirEdges(Wrap w) { + return countItems(w.value); + } + + /// \brief Function to count the edges in the graph. + /// + /// This function counts the edges in the graph. + /// The complexity of the function is O(e) but for some + /// graph structure it is specialized to run in O(1). + + template + inline int countUndirEdges(const Graph& g) { + return _countUndirEdges(g); + } + + + + template + inline int countNodeDegree(const Graph& _g, const typename Graph::Node& _n) { + int num = 0; + for (DegIt it(_g, _n); it != INVALID; ++it) { + ++num; + } + return num; + } + + /// Finds an edge between two nodes of a graph. + + /// Finds an edge from node \c u to node \c v in graph \c g. + /// + /// If \c prev is \ref INVALID (this is the default value), then + /// it finds the first edge from \c u to \c v. Otherwise it looks for + /// the next edge from \c u to \c v after \c prev. + /// \return The found edge or \ref INVALID if there is no such an edge. + /// + /// Thus you can iterate through each edge from \c u to \c v as it follows. + /// \code + /// for(Edge e=findEdge(g,u,v);e!=INVALID;e=findEdge(g,u,v,e)) { + /// ... + /// } + /// \endcode + /// \todo We may want to use the \ref concept::GraphBase "GraphBase" + /// interface here... + /// \bug Untested ... + template + typename Graph::Edge findEdge(const Graph &g, + typename Graph::Node u, typename Graph::Node v, + typename Graph::Edge prev = INVALID) + { + typename Graph::OutEdgeIt e(g,prev); + // if(prev==INVALID) g.first(e,u); + if(prev==INVALID) e=typename Graph::OutEdgeIt(g,u); + else ++e; + while(e!=INVALID && g.target(e)!=v) ++e; + return e; + } + + ///\e + + ///\todo Please document. + /// + template + inline int countOutEdges(const Graph& _g, const typename Graph::Node& _n) { + return countNodeDegree(_g, _n); + } + + ///\e + + ///\todo Please document. + /// + template + inline int countInEdges(const Graph& _g, const typename Graph::Node& _n) { + return countNodeDegree(_g, _n); + } + + // graph copy + + template < + typename DestinationGraph, + typename SourceGraph, + typename NodeBijection> + void copyNodes(DestinationGraph& _d, const SourceGraph& _s, + NodeBijection& _nb) { + for (typename SourceGraph::NodeIt it(_s); it != INVALID; ++it) { + _nb[it] = _d.addNode(); + } + } + + template < + typename DestinationGraph, + typename SourceGraph, + typename NodeBijection, + typename EdgeBijection> + void copyEdges(DestinationGraph& _d, const SourceGraph& _s, + const NodeBijection& _nb, EdgeBijection& _eb) { + for (typename SourceGraph::EdgeIt it(_s); it != INVALID; ++it) { + _eb[it] = _d.addEdge(_nb[_s.source(it)], _nb[_s.target(it)]); + } + } + + template < + typename DestinationGraph, + typename SourceGraph, + typename NodeBijection, + typename EdgeBijection> + void copyGraph(DestinationGraph& _d, const SourceGraph& _s, + NodeBijection& _nb, EdgeBijection& _eb) { + nodeCopy(_d, _s, _nb); + edgeCopy(_d, _s, _nb, _eb); + } + + template < + typename _DestinationGraph, + typename _SourceGraph, + typename _NodeBijection + =typename _SourceGraph::template NodeMap, + typename _EdgeBijection + = typename _SourceGraph::template EdgeMap + > + class GraphCopy { + public: + + typedef _DestinationGraph DestinationGraph; + typedef _SourceGraph SourceGraph; + + typedef _NodeBijection NodeBijection; + typedef _EdgeBijection EdgeBijection; + + protected: + + NodeBijection node_bijection; + EdgeBijection edge_bijection; + + public: + + GraphCopy(DestinationGraph& _d, const SourceGraph& _s) { + copyGraph(_d, _s, node_bijection, edge_bijection); + } + + const NodeBijection& getNodeBijection() const { + return node_bijection; + } + + const EdgeBijection& getEdgeBijection() const { + return edge_bijection; + } + + }; + + + template + class ItemSetTraits {}; + + template + class ItemSetTraits<_Graph, typename _Graph::Node> { + public: + + typedef _Graph Graph; + + typedef typename Graph::Node Item; + typedef typename Graph::NodeIt ItemIt; + + template + class Map : public Graph::template NodeMap<_Value> { + public: + typedef typename Graph::template NodeMap<_Value> Parent; + typedef typename Parent::Value Value; + + Map(const Graph& _graph) : Parent(_graph) {} + Map(const Graph& _graph, const Value& _value) + : Parent(_graph, _value) {} + }; + + }; + + template + class ItemSetTraits<_Graph, typename _Graph::Edge> { + public: + + typedef _Graph Graph; + + typedef typename Graph::Edge Item; + typedef typename Graph::EdgeIt ItemIt; + + template + class Map : public Graph::template EdgeMap<_Value> { + public: + typedef typename Graph::template EdgeMap<_Value> Parent; + typedef typename Parent::Value Value; + + Map(const Graph& _graph) : Parent(_graph) {} + Map(const Graph& _graph, const Value& _value) + : Parent(_graph, _value) {} + }; + + }; + + template + class ItemSetTraits<_Graph, typename _Graph::UndirEdge> { + public: + + typedef _Graph Graph; + + typedef typename Graph::UndirEdge Item; + typedef typename Graph::UndirEdgeIt ItemIt; + + template + class Map : public Graph::template UndirEdgeMap<_Value> { + public: + typedef typename Graph::template UndirEdgeMap<_Value> Parent; + typedef typename Parent::Value Value; + + Map(const Graph& _graph) : Parent(_graph) {} + Map(const Graph& _graph, const Value& _value) + : Parent(_graph, _value) {} + }; + + }; + + /// @} + + /// \addtogroup graph_maps + /// @{ + + template + struct ReferenceMapTraits { + typedef typename Map::Value Value; + typedef typename Map::Value& Reference; + typedef const typename Map::Value& ConstReference; + typedef typename Map::Value* Pointer; + typedef const typename Map::Value* ConstPointer; + }; + + template + struct ReferenceMapTraits< + Map, + typename enable_if::type + > { + typedef typename Map::Value Value; + typedef typename Map::Reference Reference; + typedef typename Map::ConstReference ConstReference; + typedef typename Map::Pointer Pointer; + typedef typename Map::ConstPointer ConstPointer; + }; + + /// Provides an immutable and unique id for each item in the graph. + + /// The IdMap class provides an unique and immutable mapping for each item + /// in the graph. + /// + template + class IdMap { + public: + typedef _Graph Graph; + typedef int Value; + typedef _Item Item; + typedef _Item Key; + + typedef True NeedCopy; + + /// \brief Constructor. + /// + /// Constructor for creating id map. + IdMap(const Graph& _graph) : graph(&_graph) {} + + /// \brief Gives back the \e id of the item. + /// + /// Gives back the immutable and unique \e id of the map. + int operator[](const Item& item) const { return graph->id(item);} + + + private: + const Graph* graph; + + public: + + /// \brief The class represents the inverse of the map. + /// + /// The class represents the inverse of the map. + /// \see inverse() + class InverseMap { + public: + + typedef True NeedCopy; + + /// \brief Constructor. + /// + /// Constructor for creating an id-to-item map. + InverseMap(const Graph& _graph) : graph(&_graph) {} + + /// \brief Constructor. + /// + /// Constructor for creating an id-to-item map. + InverseMap(const IdMap& idMap) : graph(idMap.graph) {} + + /// \brief Gives back the given item from its id. + /// + /// Gives back the given item from its id. + /// + Item operator[](int id) const { return graph->fromId(id, Item());} + private: + const Graph* graph; + }; + + /// \brief Gives back the inverse of the map. + /// + /// Gives back the inverse of the map. + InverseMap inverse() const { return InverseMap(*graph);} + + }; + + + /// \brief General inversable graph-map type. + + /// This type provides simple inversable map functions. + /// The InversableMap wraps an arbitrary ReadWriteMap + /// and if a key is setted to a new value then store it + /// in the inverse map. + /// \param _Graph The graph type. + /// \param _Map The map to extend with inversable functionality. + template < + typename _Graph, + typename _Item, + typename _Value, + typename _Map + = typename ItemSetTraits<_Graph, _Item>::template Map<_Value>::Parent + > + class InvertableMap : protected _Map { + + public: + + typedef _Map Map; + typedef _Graph Graph; + + /// The key type of InvertableMap (Node, Edge, UndirEdge). + typedef typename _Map::Key Key; + /// The value type of the InvertableMap. + typedef typename _Map::Value Value; + + /// \brief Constructor. + /// + /// Construct a new InvertableMap for the graph. + /// + InvertableMap(const Graph& graph) : Map(graph) {} + + /// \brief The setter function of the map. + /// + /// Sets the mapped value. + void set(const Key& key, const Value& val) { + Value oldval = Map::operator[](key); + typename Container::iterator it = invMap.find(oldval); + if (it != invMap.end() && it->second == key) { + invMap.erase(it); + } + invMap.insert(make_pair(val, key)); + Map::set(key, val); + } + + /// \brief The getter function of the map. + /// + /// It gives back the value associated with the key. + const Value operator[](const Key& key) const { + return Map::operator[](key); + } + + /// \brief Add a new key to the map. + /// + /// Add a new key to the map. It is called by the + /// \c AlterationNotifier. + virtual void add(const Key& key) { + Map::add(key); + } + + /// \brief Erase the key from the map. + /// + /// Erase the key to the map. It is called by the + /// \c AlterationNotifier. + virtual void erase(const Key& key) { + Value val = Map::operator[](key); + typename Container::iterator it = invMap.find(val); + if (it != invMap.end() && it->second == key) { + invMap.erase(it); + } + Map::erase(key); + } + + /// \brief Clear the keys from the map and inverse map. + /// + /// Clear the keys from the map and inverse map. It is called by the + /// \c AlterationNotifier. + virtual void clear() { + invMap.clear(); + Map::clear(); + } + + private: + + typedef std::map Container; + Container invMap; + + public: + + /// \brief The inverse map type. + /// + /// The inverse of this map. The subscript operator of the map + /// gives back always the item what was last assigned to the value. + class InverseMap { + public: + /// \brief Constructor of the InverseMap. + /// + /// Constructor of the InverseMap. + InverseMap(const InvertableMap& _inverted) : inverted(_inverted) {} + + /// The value type of the InverseMap. + typedef typename InvertableMap::Key Value; + /// The key type of the InverseMap. + typedef typename InvertableMap::Value Key; + + /// \brief Subscript operator. + /// + /// Subscript operator. It gives back always the item + /// what was last assigned to the value. + Value operator[](const Key& key) const { + typename Container::const_iterator it = inverted.invMap.find(key); + return it->second; + } + + private: + const InvertableMap& inverted; + }; + + /// \brief It gives back the just readeable inverse map. + /// + /// It gives back the just readeable inverse map. + InverseMap inverse() const { + return InverseMap(*this); + } + + + + }; + + /// \brief Provides a mutable, continuous and unique descriptor for each + /// item in the graph. + /// + /// The DescriptorMap class provides a mutable, continuous and immutable + /// mapping for each item in the graph. The value for an item may mutated + /// on each operation when the an item erased or added to graph. + /// + /// \param _Graph The graph class the \c DescriptorMap belongs to. + /// \param _Item The Item is the Key of the Map. It may be Node, Edge or + /// UndirEdge. + /// \param _Map A ReadWriteMap mapping from the item type to integer. + template < + typename _Graph, + typename _Item, + typename _Map + = typename ItemSetTraits<_Graph, _Item>::template Map::Parent + > + class DescriptorMap : protected _Map { + + typedef _Item Item; + typedef _Map Map; + + public: + /// The graph class of DescriptorMap. + typedef _Graph Graph; + + /// The key type of DescriptorMap (Node, Edge, UndirEdge). + typedef typename _Map::Key Key; + /// The value type of DescriptorMap. + typedef typename _Map::Value Value; + + /// \brief Constructor. + /// + /// Constructor for descriptor map. + DescriptorMap(const Graph& _graph) : Map(_graph) { + build(); + } + + /// \brief Add a new key to the map. + /// + /// Add a new key to the map. It is called by the + /// \c AlterationNotifier. + virtual void add(const Item& item) { + Map::add(item); + Map::set(item, invMap.size()); + invMap.push_back(item); + } + + /// \brief Erase the key from the map. + /// + /// Erase the key to the map. It is called by the + /// \c AlterationNotifier. + virtual void erase(const Item& item) { + Map::set(invMap.back(), Map::operator[](item)); + invMap[Map::operator[](item)] = invMap.back(); + invMap.pop_back(); + Map::erase(item); + } + + /// \brief Build the unique map. + /// + /// Build the unique map. It is called by the + /// \c AlterationNotifier. + virtual void build() { + Map::build(); + Item it; + const typename Map::Graph* graph = Map::getGraph(); + for (graph->first(it); it != INVALID; graph->next(it)) { + Map::set(it, invMap.size()); + invMap.push_back(it); + } + } + + /// \brief Clear the keys from the map. + /// + /// Clear the keys from the map. It is called by the + /// \c AlterationNotifier. + virtual void clear() { + invMap.clear(); + Map::clear(); + } + + /// \brief Gives back the \e descriptor of the item. + /// + /// Gives back the mutable and unique \e descriptor of the map. + int operator[](const Item& item) const { + return Map::operator[](item); + } + + private: + + typedef std::vector Container; + Container invMap; + + public: + /// \brief The inverse map type. + /// + /// The inverse map type. + class InverseMap { + public: + /// \brief Constructor of the InverseMap. + /// + /// Constructor of the InverseMap. + InverseMap(const DescriptorMap& _inverted) + : inverted(_inverted) {} + + + /// The value type of the InverseMap. + typedef typename DescriptorMap::Key Value; + /// The key type of the InverseMap. + typedef typename DescriptorMap::Value Key; + + /// \brief Subscript operator. + /// + /// Subscript operator. It gives back the item + /// that the descriptor belongs to currently. + Value operator[](const Key& key) const { + return inverted.invMap[key]; + } + + private: + const DescriptorMap& inverted; + }; + + /// \brief Gives back the inverse of the map. + /// + /// Gives back the inverse of the map. + const InverseMap inverse() const { + return InverseMap(*this); + } + }; + + /// \brief Returns the source of the given edge. + /// + /// The SourceMap gives back the source Node of the given edge. + /// \author Balazs Dezso + template + class SourceMap { + public: + + typedef True NeedCopy; + + typedef typename Graph::Node Value; + typedef typename Graph::Edge Key; + + /// \brief Constructor + /// + /// Constructor + /// \param _graph The graph that the map belongs to. + SourceMap(const Graph& _graph) : graph(_graph) {} + + /// \brief The subscript operator. + /// + /// The subscript operator. + /// \param edge The edge + /// \return The source of the edge + Value operator[](const Key& edge) { + return graph.source(edge); + } + + private: + const Graph& graph; + }; + + /// \brief Returns a \ref SourceMap class + /// + /// This function just returns an \ref SourceMap class. + /// \relates SourceMap + template + inline SourceMap sourceMap(const Graph& graph) { + return SourceMap(graph); + } + + /// \brief Returns the target of the given edge. + /// + /// The TargetMap gives back the target Node of the given edge. + /// \author Balazs Dezso + template + class TargetMap { + public: + + typedef True NeedCopy; + + typedef typename Graph::Node Value; + typedef typename Graph::Edge Key; + + /// \brief Constructor + /// + /// Constructor + /// \param _graph The graph that the map belongs to. + TargetMap(const Graph& _graph) : graph(_graph) {} + + /// \brief The subscript operator. + /// + /// The subscript operator. + /// \param edge The edge + /// \return The target of the edge + Value operator[](const Key& key) { + return graph.target(key); + } + + private: + const Graph& graph; + }; + + /// \brief Returns a \ref TargetMap class + + /// This function just returns an \ref TargetMap class. + /// \relates TargetMap + template + inline TargetMap targetMap(const Graph& graph) { + return TargetMap(graph); + } + + /// \brief Returns the "forward" directed edge view of undirected edge. + /// + /// Returns the "forward" directed edge view of undirected edge. + /// \author Balazs Dezso + template + class ForwardMap { + public: + + typedef True NeedCopy; + + typedef typename Graph::Edge Value; + typedef typename Graph::UndirEdge Key; + + /// \brief Constructor + /// + /// Constructor + /// \param _graph The graph that the map belongs to. + ForwardMap(const Graph& _graph) : graph(_graph) {} + + /// \brief The subscript operator. + /// + /// The subscript operator. + /// \param key An undirected edge + /// \return The "forward" directed edge view of undirected edge + Value operator[](const Key& key) const { + return graph.edgeWithSource(key, graph.source(key)); + } + + private: + const Graph& graph; + }; + + /// \brief Returns a \ref ForwardMap class + + /// This function just returns an \ref ForwardMap class. + /// \relates ForwardMap + template + inline ForwardMap forwardMap(const Graph& graph) { + return ForwardMap(graph); + } + + /// \brief Returns the "backward" directed edge view of undirected edge. + /// + /// Returns the "backward" directed edge view of undirected edge. + /// \author Balazs Dezso + template + class BackwardMap { + public: + typedef True NeedCopy; + + typedef typename Graph::Edge Value; + typedef typename Graph::UndirEdge Key; + + /// \brief Constructor + /// + /// Constructor + /// \param _graph The graph that the map belongs to. + BackwardMap(const Graph& _graph) : graph(_graph) {} + + /// \brief The subscript operator. + /// + /// The subscript operator. + /// \param key An undirected edge + /// \return The "backward" directed edge view of undirected edge + Value operator[](const Key& key) const { + return graph.edgeWithSource(key, graph.target(key)); + } + + private: + const Graph& graph; + }; + + /// \brief Returns a \ref BackwardMap class + + /// This function just returns an \ref BackwardMap class. + /// \relates BackwardMap + template + inline BackwardMap backwardMap(const Graph& graph) { + return BackwardMap(graph); + } + + + /// @} + +} //END OF NAMESPACE LEMON + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/graph_writer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/graph_writer.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,683 @@ +/* -*- C++ -*- + * lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\ingroup io_group +///\file +///\brief Lemon Graph Format writer. + +#ifndef LEMON_GRAPH_WRITER_H +#define LEMON_GRAPH_WRITER_H + +#include + +#include +#include + +namespace lemon { + + /// \addtogroup io_group + /// @{ + + /// \brief The graph writer class. + /// + /// The \c GraphWriter class provides the graph output. To write a graph + /// you should first give writing commands for the writer. You can declare + /// write command as \c NodeMap or \c EdgeMap writing and labeled Node and + /// Edge writing. + /// + /// \code + /// GraphWriter writer(std::cout, graph); + /// \endcode + /// + /// The \c writeNodeMap() function declares a \c NodeMap writing + /// command in the \c GraphWriter. You should give as parameter + /// the name of the map and the map object. The NodeMap writing + /// command with name "id" should write a unique map because it + /// is regarded as ID map. + /// + /// \code + /// IdMap nodeIdMap; + /// writer.writeNodeMap("id", nodeIdMap); + /// + /// writer.writeNodeMap("coords", coords); + /// writer.writeNodeMap("color", colorMap); + /// \endcode + /// + /// With the \c writeEdgeMap() member function you can give an edge map + /// writing command similar to the NodeMaps. + /// + /// \code + /// DescriptorMap > + /// edgeDescMap(graph); + /// writer.writeEdgeMap("descriptor", edgeDescMap); + /// + /// writer.writeEdgeMap("weight", weightMap); + /// writer.writeEdgeMap("label", labelMap); + /// \endcode + /// + /// With \c writeNode() and \c writeEdge() functions you can + /// point out Nodes and Edges in the graph. By example, you can + /// write out the source and target of the graph. + /// + /// \code + /// writer.writeNode("source", sourceNode); + /// writer.writeNode("target", targetNode); + /// + /// writer.writeEdge("observed", edge); + /// \endcode + /// + /// After you give all write commands you must call the \c run() member + /// function, which execute all the writer commands. + /// + /// \code + /// writer.run(); + /// \endcode + /// + /// \see DefaultWriterTraits + /// \see QuotedStringWriter + /// \see IdMap + /// \see DescriptorMap + /// \see \ref GraphReader + /// \see \ref graph-io-page + /// \author Balazs Dezso + template + class GraphWriter { + public: + + typedef _Graph Graph; + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + + typedef _WriterTraits WriterTraits; + + /// \brief Construct a new GraphWriter. + /// + /// Construct a new GraphWriter. It writes the given graph + /// to the given stream. + GraphWriter(std::ostream& _os, const Graph& _graph) + : writer(new LemonWriter(_os)), own_writer(true), + nodeset_writer(*writer, _graph, std::string()), + edgeset_writer(*writer, _graph, nodeset_writer, std::string()), + node_writer(*writer, nodeset_writer, std::string()), + edge_writer(*writer, edgeset_writer, std::string()), + attribute_writer(*writer, std::string()) {} + + /// \brief Construct a new GraphWriter. + /// + /// Construct a new GraphWriter. It writes into the given graph + /// to the given file. + GraphWriter(const std::string& _filename, const Graph& _graph) + : writer(new LemonWriter(_filename)), own_writer(true), + nodeset_writer(*writer, _graph, std::string()), + edgeset_writer(*writer, _graph, nodeset_writer, std::string()), + node_writer(*writer, nodeset_writer, std::string()), + edge_writer(*writer, edgeset_writer, std::string()), + attribute_writer(*writer, std::string()) {} + + /// \brief Construct a new GraphWriter. + /// + /// Construct a new GraphWriter. It writes into the given graph + /// to given LemonReader. + GraphWriter(LemonWriter& _writer, const Graph& _graph) + : writer(_writer), own_writer(false), + nodeset_writer(*writer, _graph, std::string()), + edgeset_writer(*writer, _graph, nodeset_writer, std::string()), + node_writer(*writer, nodeset_writer, std::string()), + edge_writer(*writer, edgeset_writer, std::string()), + attribute_writer(*writer, std::string()) {} + + /// \brief Destruct the graph writer. + /// + /// Destruct the graph writer. + ~GraphWriter() { + if (own_writer) + delete writer; + } + + /// \brief Add a new node map writer command for the writer. + /// + /// Add a new node map writer command for the writer. + template + GraphWriter& writeNodeMap(std::string name, const Map& map) { + nodeset_writer.writeNodeMap(name, map); + return *this; + } + + /// \brief Add a new node map writer command for the writer. + /// + /// Add a new node map writer command for the writer. + template + GraphWriter& writeNodeMap(std::string name, const Map& map, + const Writer& writer = Writer()) { + nodeset_writer.writeNodeMap(name, map, writer); + return *this; + } + + + /// \brief Add a new edge map writer command for the writer. + /// + /// Add a new edge map writer command for the writer. + template + GraphWriter& writeEdgeMap(std::string name, const Map& map) { + edgeset_writer.writeEdgeMap(name, map); + return *this; + } + + + /// \brief Add a new edge map writer command for the writer. + /// + /// Add a new edge map writer command for the writer. + template + GraphWriter& writeEdgeMap(std::string name, const Map& map, + const Writer& writer = Writer()) { + edgeset_writer.writeEdgeMap(name, map, writer); + return *this; + } + + /// \brief Add a new labeled node writer for the writer. + /// + /// Add a new labeled node writer for the writer. + GraphWriter& writeNode(std::string name, const Node& node) { + node_writer.writeNode(name, node); + return *this; + } + + /// \brief Add a new labeled edge writer for the writer. + /// + /// Add a new labeled edge writer for the writer. + GraphWriter& writeEdge(std::string name, const Edge& edge) { + edge_writer.writeEdge(name, edge); + } + + /// \brief Add a new attribute writer command. + /// + /// Add a new attribute writer command. + template + GraphWriter& writeAttribute(std::string name, const Value& value) { + attribute_writer.writeAttribute(name, value); + return *this; + } + + /// \brief Add a new attribute writer command. + /// + /// Add a new attribute writer command. + template + GraphWriter& writeAttribute(std::string name, const Value& value, + const Writer& writer) { + attribute_writer.writeAttribute(name, value, writer); + return *this; + } + + /// \brief Conversion operator to LemonWriter. + /// + /// Conversion operator to LemonWriter. It make possible + /// to access the encapsulated \e LemonWriter, this way + /// you can attach to this writer new instances of + /// \e LemonWriter::SectionWriter. + operator LemonWriter&() { + return *writer; + } + + /// \brief Executes the writer commands. + /// + /// Executes the writer commands. + void run() { + writer->run(); + } + + /// \brief Write the id of the given node. + /// + /// It writes the id of the given node. If there was written an "id" + /// named node map then it will write the map value belongs to the node. + void writeId(std::ostream& os, const Node& item) const { + nodeset_writer.writeId(os, item); + } + + /// \brief Write the id of the given edge. + /// + /// It writes the id of the given edge. If there was written an "id" + /// named edge map then it will write the map value belongs to the edge. + void writeId(std::ostream& os, const Edge& item) const { + edgeset_writer.writeId(os, item); + } + + private: + + LemonWriter* writer; + bool own_writer; + + NodeSetWriter nodeset_writer; + EdgeSetWriter edgeset_writer; + + NodeWriter node_writer; + EdgeWriter edge_writer; + + AttributeWriter attribute_writer; + }; + + + /// \brief Write a graph to the output. + /// + /// Write a graph to the output. + /// \param os The output stream. + /// \param g The graph. + /// \param capacity The capacity map. + /// \param s The source node. + /// \param t The target node. + /// \param cost The cost map. + template + void writeGraph(std::ostream& os, const Graph &g, + const CapacityMap& capacity, const typename Graph::Node &s, + const typename Graph::Node &t, const CostMap& cost) { + GraphWriter writer(os, g); + IdMap nodeIdMap(g); + writer.writeNodeMap("id", nodeIdMap); + IdMap edgeIdMap(g); + writer.writeEdgeMap("id", edgeIdMap); + writer.writeEdgeMap("capacity", capacity); + writer.writeEdgeMap("cost", cost); + writer.writeNode("source", s); + writer.writeNode("target", t); + writer.run(); + } + + /// \brief Write a graph to the output. + /// + /// Write a graph to the output. + /// \param os The output stream. + /// \param g The graph. + /// \param capacity The capacity map. + /// \param s The source node. + /// \param t The target node. + template + void writeGraph(std::ostream& os, const Graph &g, + const CapacityMap& capacity, const typename Graph::Node &s, + const typename Graph::Node &t) { + GraphWriter writer(os, g); + IdMap nodeIdMap(g); + writer.writeNodeMap("id", nodeIdMap); + IdMap edgeIdMap(g); + writer.writeEdgeMap("id", edgeIdMap); + writer.writeEdgeMap("capacity", capacity); + writer.writeNode("source", s); + writer.writeNode("target", t); + writer.run(); + } + + /// \brief Write a graph to the output. + /// + /// Write a graph to the output. + /// \param os The output stream. + /// \param g The graph. + /// \param capacity The capacity map. + /// \param s The source node. + template + void writeGraph(std::ostream& os, const Graph &g, + const CapacityMap& capacity, const typename Graph::Node &s) { + GraphWriter writer(os, g); + IdMap nodeIdMap(g); + writer.writeNodeMap("id", nodeIdMap); + IdMap edgeIdMap(g); + writer.writeEdgeMap("id", edgeIdMap); + writer.writeEdgeMap("capacity", capacity); + writer.writeNode("source", s); + writer.run(); + } + + /// \brief Write a graph to the output. + /// + /// Write a graph to the output. + /// \param os The output stream. + /// \param g The graph. + /// \param capacity The capacity map. + template + void writeGraph(std::ostream& os, const Graph &g, + const CapacityMap& capacity) { + GraphWriter writer(os, g); + IdMap nodeIdMap(g); + writer.writeNodeMap("id", nodeIdMap); + IdMap edgeIdMap(g); + writer.writeEdgeMap("id", edgeIdMap); + writer.writeEdgeMap("capacity", capacity); + writer.run(); + } + + /// \brief Write a graph to the output. + /// + /// Write a graph to the output. + /// \param os The output stream. + /// \param g The graph. + template + void writeGraph(std::ostream& os, const Graph &g) { + GraphWriter writer(os, g); + IdMap nodeIdMap(g); + writer.writeNodeMap("id", nodeIdMap); + IdMap edgeIdMap(g); + writer.writeEdgeMap("id", edgeIdMap); + writer.run(); + } + + /// \brief The undirected graph writer class. + /// + /// The \c UndirGraphWriter class provides the undir graph output. To write + /// a graph you should first give writing commands for the writer. You can + /// declare write command as \c NodeMap, \c EdgeMap or \c UndirEdgeMap + /// writing and labeled Node, Edge or UndirEdge writing. + /// + /// \code + /// UndirGraphWriter writer(std::cout, graph); + /// \endcode + /// + /// The \c writeNodeMap() function declares a \c NodeMap writing + /// command in the \c UndirGraphWriter. You should give as parameter + /// the name of the map and the map object. The NodeMap writing + /// command with name "id" should write a unique map because it + /// is regarded as ID map. + /// + /// \code + /// IdMap nodeIdMap; + /// writer.writeNodeMap("id", nodeIdMap); + /// + /// writer.writeNodeMap("coords", coords); + /// writer.writeNodeMap("color", colorMap); + /// \endcode + /// + /// With the \c writeUndirEdgeMap() member function you can give an + /// undirected edge map writing command similar to the NodeMaps. + /// + /// \code + /// DescriptorMap > + /// edgeDescMap(graph); + /// writer.writeUndirEdgeMap("descriptor", edgeDescMap); + /// + /// writer.writeUndirEdgeMap("weight", weightMap); + /// writer.writeUndirEdgeMap("label", labelMap); + /// \endcode + /// + /// The EdgeMap handling is just a syntactical sugar. It writes + /// two undirected edge map with '+' and '-' prefix in the name. + /// + /// \code + /// writer.writeEdgeMap("capacity", capacityMap); + /// \endcode + /// + /// + /// With \c writeNode() and \c writeUndirEdge() functions you can + /// point out nodes and undirected edges in the graph. By example, you can + /// write out the source and target of the graph. + /// + /// \code + /// writer.writeNode("source", sourceNode); + /// writer.writeNode("target", targetNode); + /// + /// writer.writeUndirEdge("observed", undirEdge); + /// \endcode + /// + /// After you give all write commands you must call the \c run() member + /// function, which execute all the writer commands. + /// + /// \code + /// writer.run(); + /// \endcode + /// + /// \see DefaultWriterTraits + /// \see QuotedStringWriter + /// \see IdMap + /// \see DescriptorMap + /// \see \ref GraphWriter + /// \see \ref graph-io-page + /// \author Balazs Dezso + template + class UndirGraphWriter { + public: + + typedef _Graph Graph; + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + typedef typename Graph::UndirEdge UndirEdge; + + typedef _WriterTraits WriterTraits; + + /// \brief Construct a new UndirGraphWriter. + /// + /// Construct a new UndirGraphWriter. It writes the given graph + /// to the given stream. + UndirGraphWriter(std::ostream& _os, const Graph& _graph) + : writer(new LemonWriter(_os)), own_writer(true), + nodeset_writer(*writer, _graph, std::string()), + undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), + node_writer(*writer, nodeset_writer, std::string()), + undir_edge_writer(*writer, undir_edgeset_writer, std::string()), + attribute_writer(*writer, std::string()) {} + + /// \brief Construct a new UndirGraphWriter. + /// + /// Construct a new UndirGraphWriter. It writes into the given graph + /// to the given file. + UndirGraphWriter(const std::string& _filename, const Graph& _graph) + : writer(new LemonWriter(_filename)), own_writer(true), + nodeset_writer(*writer, _graph, std::string()), + undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), + node_writer(*writer, nodeset_writer, std::string()), + undir_edge_writer(*writer, undir_edgeset_writer, std::string()), + attribute_writer(*writer, std::string()) {} + + /// \brief Construct a new UndirGraphWriter. + /// + /// Construct a new UndirGraphWriter. It writes into the given graph + /// to given LemonReader. + UndirGraphWriter(LemonWriter& _writer, const Graph& _graph) + : writer(_writer), own_writer(false), + nodeset_writer(*writer, _graph, std::string()), + undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), + node_writer(*writer, nodeset_writer, std::string()), + undir_edge_writer(*writer, undir_edgeset_writer, std::string()), + attribute_writer(*writer, std::string()) {} + + /// \brief Destruct the graph writer. + /// + /// Destruct the graph writer. + ~UndirGraphWriter() { + if (own_writer) + delete writer; + } + + /// \brief Add a new node map writer command for the writer. + /// + /// Add a new node map writer command for the writer. + template + UndirGraphWriter& writeNodeMap(std::string name, const Map& map) { + nodeset_writer.writeNodeMap(name, map); + return *this; + } + + /// \brief Add a new node map writer command for the writer. + /// + /// Add a new node map writer command for the writer. + template + UndirGraphWriter& writeNodeMap(std::string name, const Map& map, + const Writer& writer = Writer()) { + nodeset_writer.writeNodeMap(name, map, writer); + return *this; + } + + /// \brief Add a new edge map writer command for the writer. + /// + /// Add a new edge map writer command for the writer. + template + UndirGraphWriter& writeEdgeMap(std::string name, const Map& map) { + undir_edgeset_writer.writeEdgeMap(name, map); + return *this; + } + + /// \brief Add a new edge map writer command for the writer. + /// + /// Add a new edge map writer command for the writer. + template + UndirGraphWriter& writeEdgeMap(std::string name, const Map& map, + const Writer& writer = Writer()) { + undir_edgeset_writer.writeEdgeMap(name, map, writer); + return *this; + } + + /// \brief Add a new undirected edge map writer command for the writer. + /// + /// Add a new undirected edge map writer command for the writer. + template + UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map) { + undir_edgeset_writer.writeUndirEdgeMap(name, map); + return *this; + } + + /// \brief Add a new undirected edge map writer command for the writer. + /// + /// Add a new edge undirected map writer command for the writer. + template + UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map, + const Writer& writer = Writer()) { + undir_edgeset_writer.writeUndirEdgeMap(name, map, writer); + return *this; + } + + /// \brief Add a new labeled node writer for the writer. + /// + /// Add a new labeled node writer for the writer. + UndirGraphWriter& writeNode(std::string name, const Node& node) { + node_writer.writeNode(name, node); + return *this; + } + + /// \brief Add a new labeled edge writer for the writer. + /// + /// Add a new labeled edge writer for the writer. + UndirGraphWriter& writeEdge(std::string name, const Edge& edge) { + undir_edge_writer.writeEdge(name, edge); + } + + /// \brief Add a new labeled undirected edge writer for the writer. + /// + /// Add a new labeled undirected edge writer for the writer. + UndirGraphWriter& writeUndirEdge(std::string name, const UndirEdge& edge) { + undir_edge_writer.writeUndirEdge(name, edge); + } + + /// \brief Add a new attribute writer command. + /// + /// Add a new attribute writer command. + template + UndirGraphWriter& writeAttribute(std::string name, const Value& value) { + attribute_writer.writeAttribute(name, value); + return *this; + } + + /// \brief Add a new attribute writer command. + /// + /// Add a new attribute writer command. + template + UndirGraphWriter& writeAttribute(std::string name, const Value& value, + const Writer& writer) { + attribute_writer.writeAttribute(name, value, writer); + return *this; + } + + /// \brief Conversion operator to LemonWriter. + /// + /// Conversion operator to LemonWriter. It make possible + /// to access the encapsulated \e LemonWriter, this way + /// you can attach to this writer new instances of + /// \e LemonWriter::SectionWriter. + operator LemonWriter&() { + return *writer; + } + + /// \brief Executes the writer commands. + /// + /// Executes the writer commands. + void run() { + writer->run(); + } + + /// \brief Write the id of the given node. + /// + /// It writes the id of the given node. If there was written an "id" + /// named node map then it will write the map value belongs to the node. + void writeId(std::ostream& os, const Node& item) const { + nodeset_writer.writeId(os, item); + } + + /// \brief Write the id of the given edge. + /// + /// It writes the id of the given edge. If there was written an "id" + /// named edge map then it will write the map value belongs to the edge. + void writeId(std::ostream& os, const Edge& item) const { + undir_edgeset_writer.writeId(os, item); + } + + /// \brief Write the id of the given undirected edge. + /// + /// It writes the id of the given undirected edge. If there was written + /// an "id" named edge map then it will write the map value belongs to + /// the edge. + void writeId(std::ostream& os, const UndirEdge& item) const { + undir_edgeset_writer.writeId(os, item); + } + + + private: + + LemonWriter* writer; + bool own_writer; + + NodeSetWriter nodeset_writer; + UndirEdgeSetWriter undir_edgeset_writer; + + NodeWriter node_writer; + UndirEdgeWriter undir_edge_writer; + + AttributeWriter attribute_writer; + }; + + + /// \brief Write an undirected graph to the output. + /// + /// Write an undirected graph to the output. + /// \param os The output stream. + /// \param g The graph. + /// \param capacity The capacity undirected map. + template + void writeUndirGraph(std::ostream& os, const Graph &g, + const CapacityMap& capacity) { + UndirGraphWriter writer(os, g); + writer.writeUndirEdgeMap("capacity", capacity); + writer.run(); + } + + /// \brief Write an undirected graph to the output. + /// + /// Write an undirected graph to the output. + /// \param os The output stream. + /// \param g The graph. + template + void writeUndirGraph(std::ostream& os, const Graph &g) { + UndirGraphWriter writer(os, g); + writer.run(); + } + + /// @} + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/invalid.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/invalid.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,52 @@ +/* -*- C++ -*- + * lemon/invalid.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_INVALID_H +#define LEMON_INVALID_H + +///\file +///\brief Definition of INVALID. + +namespace lemon { + + /// Dummy type to make it easier to make invalid iterators. + + /// See \ref INVALID, how to use it. + + struct Invalid { + public: + bool operator==(Invalid) { return true; } + bool operator!=(Invalid) { return false; } + bool operator< (Invalid) { return false; } + }; + + /// Invalid iterators. + + /// \ref Invalid is a global type that converts to each iterator + /// in such a way that the value of the target iterator will be invalid. + + // It is also used to convert the \c INVALID constant to the + // node iterator that makes is possible to write + + //extern Invalid INVALID; + + //const Invalid &INVALID = *(Invalid *)0; + const Invalid INVALID = Invalid(); + +} //namespace lemon + +#endif + diff -r d8475431bbbb -r 8e85e6bbefdf lemon/kruskal.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/kruskal.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,348 @@ +/* -*- C++ -*- + * lemon/kruskal.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_KRUSKAL_H +#define LEMON_KRUSKAL_H + +#include +#include + +/** +@defgroup spantree Minimum Cost Spanning Tree Algorithms +@ingroup galgs +\brief This group containes the algorithms for finding a minimum cost spanning +tree in a graph + +This group containes the algorithms for finding a minimum cost spanning +tree in a graph +*/ + +///\ingroup spantree +///\file +///\brief Kruskal's algorithm to compute a minimum cost tree +/// +///Kruskal's algorithm to compute a minimum cost tree. + +namespace lemon { + + /// \addtogroup spantree + /// @{ + + /// Kruskal's algorithm to find a minimum cost tree of a graph. + + /// This function runs Kruskal's algorithm to find a minimum cost tree. + /// \param G The graph the algorithm runs on. The algorithm considers the + /// graph to be undirected, the direction of the edges are not used. + /// + /// \param in This object is used to describe the edge costs. It must + /// be an STL compatible 'Forward Container' + /// with std::pair as its value_type, + /// where X is the type of the costs. It must contain every edge in + /// cost-ascending order. + ///\par + /// For the sake of simplicity, there is a helper class KruskalMapInput, + /// which converts a + /// simple edge map to an input of this form. Alternatively, you can use + /// the function \ref kruskalEdgeMap to compute the minimum cost tree if + /// the edge costs are given by an edge map. + /// + /// \retval out This must be a writable \c bool edge map. + /// After running the algorithm + /// this will contain the found minimum cost spanning tree: the value of an + /// edge will be set to \c true if it belongs to the tree, otherwise it will + /// be set to \c false. The value of each edge will be set exactly once. + /// + /// \return The cost of the found tree. + + template + typename IN::value_type::second_type + kruskal(GR const& G, IN const& in, + OUT& out) + { + typedef typename IN::value_type::second_type EdgeCost; + typedef typename GR::template NodeMap NodeIntMap; + typedef typename GR::Node Node; + + NodeIntMap comp(G, -1); + UnionFind uf(comp); + + EdgeCost tot_cost = 0; + for (typename IN::const_iterator p = in.begin(); + p!=in.end(); ++p ) { + if ( uf.join(G.target((*p).first), + G.source((*p).first)) ) { + out.set((*p).first, true); + tot_cost += (*p).second; + } + else { + out.set((*p).first, false); + } + } + return tot_cost; + } + + /* A work-around for running Kruskal with const-reference bool maps... */ + + /// Helper class for calling kruskal with "constant" output map. + + /// Helper class for calling kruskal with output maps constructed + /// on-the-fly. + /// + /// A typical examle is the following call: + /// kruskal(G, some_input, makeSequenceOutput(iterator)). + /// Here, the third argument is a temporary object (which wraps around an + /// iterator with a writable bool map interface), and thus by rules of C++ + /// is a \c const object. To enable call like this exist this class and + /// the prototype of the \ref kruskal() function with const& OUT + /// third argument. + template + class NonConstMapWr { + const Map &m; + public: + typedef typename Map::Value Value; + + NonConstMapWr(const Map &_m) : m(_m) {} + + template + void set(Key const& k, Value const &v) const { m.set(k,v); } + }; + + template + inline + typename IN::value_type::second_type + kruskal(GR const& G, IN const& edges, OUT const& out_map) + { + NonConstMapWr map_wr(out_map); + return kruskal(G, edges, map_wr); + } + + /* ** ** Input-objects ** ** */ + + /// Kruskal's input source. + + /// Kruskal's input source. + /// + /// In most cases you possibly want to use the \ref kruskalEdgeMap() instead. + /// + /// \sa makeKruskalMapInput() + /// + ///\param GR The type of the graph the algorithm runs on. + ///\param Map An edge map containing the cost of the edges. + ///\par + ///The cost type can be any type satisfying + ///the STL 'LessThan comparable' + ///concept if it also has an operator+() implemented. (It is necessary for + ///computing the total cost of the tree). + /// + template + class KruskalMapInput + : public std::vector< std::pair > { + + public: + typedef std::vector< std::pair > Parent; + typedef typename Parent::value_type value_type; + + private: + class comparePair { + public: + bool operator()(const value_type& a, + const value_type& b) { + return a.second < b.second; + } + }; + + public: + + void sort() { + std::sort(this->begin(), this->end(), comparePair()); + } + + KruskalMapInput(GR const& G, Map const& m) { + typedef typename GR::EdgeIt EdgeIt; + + for(EdgeIt e(G);e!=INVALID;++e) push_back(value_type(e, m[e])); + sort(); + } + }; + + /// Creates a KruskalMapInput object for \ref kruskal() + + /// It makes easier to use + /// \ref KruskalMapInput by making it unnecessary + /// to explicitly give the type of the parameters. + /// + /// In most cases you possibly + /// want to use the function kruskalEdgeMap() instead. + /// + ///\param G The type of the graph the algorithm runs on. + ///\param m An edge map containing the cost of the edges. + ///\par + ///The cost type can be any type satisfying the + ///STL 'LessThan Comparable' + ///concept if it also has an operator+() implemented. (It is necessary for + ///computing the total cost of the tree). + /// + ///\return An appropriate input source for \ref kruskal(). + /// + template + inline + KruskalMapInput makeKruskalMapInput(const GR &G,const Map &m) + { + return KruskalMapInput(G,m); + } + + + + /* ** ** Output-objects: simple writable bool maps ** ** */ + + + + /// A writable bool-map that makes a sequence of "true" keys + + /// A writable bool-map that creates a sequence out of keys that receives + /// the value "true". + /// + /// \sa makeKruskalSequenceOutput() + /// + /// Very often, when looking for a min cost spanning tree, we want as + /// output a container containing the edges of the found tree. For this + /// purpose exist this class that wraps around an STL iterator with a + /// writable bool map interface. When a key gets value "true" this key + /// is added to sequence pointed by the iterator. + /// + /// A typical usage: + /// \code + /// std::vector v; + /// kruskal(g, input, makeKruskalSequenceOutput(back_inserter(v))); + /// \endcode + /// + /// For the most common case, when the input is given by a simple edge + /// map and the output is a sequence of the tree edges, a special + /// wrapper function exists: \ref kruskalEdgeMap_IteratorOut(). + /// + /// \warning Not a regular property map, as it doesn't know its Key + + template + class KruskalSequenceOutput { + mutable Iterator it; + + public: + typedef bool Value; + + KruskalSequenceOutput(Iterator const &_it) : it(_it) {} + + template + void set(Key const& k, bool v) const { if(v) {*it=k; ++it;} } + }; + + template + inline + KruskalSequenceOutput + makeKruskalSequenceOutput(Iterator it) { + return KruskalSequenceOutput(it); + } + + + + /* ** ** Wrapper funtions ** ** */ + + + + /// \brief Wrapper function to kruskal(). + /// Input is from an edge map, output is a plain bool map. + /// + /// Wrapper function to kruskal(). + /// Input is from an edge map, output is a plain bool map. + /// + ///\param G The type of the graph the algorithm runs on. + ///\param in An edge map containing the cost of the edges. + ///\par + ///The cost type can be any type satisfying the + ///STL 'LessThan Comparable' + ///concept if it also has an operator+() implemented. (It is necessary for + ///computing the total cost of the tree). + /// + /// \retval out This must be a writable \c bool edge map. + /// After running the algorithm + /// this will contain the found minimum cost spanning tree: the value of an + /// edge will be set to \c true if it belongs to the tree, otherwise it will + /// be set to \c false. The value of each edge will be set exactly once. + /// + /// \return The cost of the found tree. + + template + inline + typename IN::Value + kruskalEdgeMap(GR const& G, + IN const& in, + RET &out) { + return kruskal(G, + KruskalMapInput(G,in), + out); + } + + /// \brief Wrapper function to kruskal(). + /// Input is from an edge map, output is an STL Sequence. + /// + /// Wrapper function to kruskal(). + /// Input is from an edge map, output is an STL Sequence. + /// + ///\param G The type of the graph the algorithm runs on. + ///\param in An edge map containing the cost of the edges. + ///\par + ///The cost type can be any type satisfying the + ///STL 'LessThan Comparable' + ///concept if it also has an operator+() implemented. (It is necessary for + ///computing the total cost of the tree). + /// + /// \retval out This must be an iteraror of an STL Container with + /// GR::Edge as its value_type. + /// The algorithm copies the elements of the found tree into this sequence. + /// For example, if we know that the spanning tree of the graph \c G has + /// say 53 edges then + /// we can put its edges into a STL vector \c tree with a code like this. + /// \code + /// std::vector tree(53); + /// kruskalEdgeMap_IteratorOut(G,cost,tree.begin()); + /// \endcode + /// Or if we don't know in advance the size of the tree, we can write this. + /// \code + /// std::vector tree; + /// kruskalEdgeMap_IteratorOut(G,cost,std::back_inserter(tree)); + /// \endcode + /// + /// \return The cost of the found tree. + /// + /// \bug its name does not follow the coding style. + + template + inline + typename IN::Value + kruskalEdgeMap_IteratorOut(const GR& G, + const IN& in, + RET out) + { + KruskalSequenceOutput _out(out); + return kruskal(G, KruskalMapInput(G, in), _out); + } + + /// @} + +} //namespace lemon + +#endif //LEMON_KRUSKAL_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lemon.pc.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lemon.pc.in Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: @PACKAGE_NAME@ +Description: a Library of Efficient Models and Optimization in Networks +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lemon +Cflags: -I${includedir} diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lemon_reader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lemon_reader.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,1977 @@ +/* -*- C++ -*- + * lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\ingroup io_group +///\file +///\brief Lemon Format reader. + + +#ifndef LEMON_LEMON_READER_H +#define LEMON_LEMON_READER_H + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +namespace lemon { + + namespace _reader_bits { + + template + bool operator<(T, T) { + throw DataFormatError("Id is not comparable"); + } + + template + struct Less { + bool operator()(const T& p, const T& q) const { + return p < q; + } + }; + + template + class WriteComposeMap { + public: + typedef True NeedCopy; + + typedef typename M2::Key Key; + typedef typename M1::Value Value; + + WriteComposeMap(typename SmartParameter::Type _m1, const M2& _m2) + : m1(_m1), m2(_m2) {} + + void set(const Key& key, const Value& value) { + m1.set(m2[key], value); + } + + private: + + typename SmartReference::Type m1; + typename SmartConstReference::Type m2; + + }; + + template + WriteComposeMap writeComposeMap(M1& m1, const M2& m2) { + return WriteComposeMap(m1, m2); + } + + template + WriteComposeMap writeComposeMap(const M1& m1, const M2& m2) { + return WriteComposeMap(m1, m2); + } + + } + + /// \ingroup io_group + /// \brief Lemon Format reader class. + /// + /// The Lemon Format contains several sections. We do not want to + /// determine what sections are in a lemon file we give only a framework + /// to read a section oriented format. + /// + /// In the Lemon Format each section starts with a line contains a \c \@ + /// character on the first not white space position. This line is the + /// header line of the section. Each next lines belong to this section + /// while it does not starts with \c \@ character. This line can start a + /// new section or if it can close the file with the \c \@end line. + /// The file format ignore the empty and comment lines. The line is + /// comment line if it starts with a \c # character. + /// + /// The framework provides an abstract LemonReader::SectionReader class + /// what defines the interface of a SectionReader. The SectionReader + /// has the \c header() member function what get a header line string and + /// decides if it want to process the next section. Several SectionReaders + /// can be attached to an LemonReader and the first attached what can + /// process the section will be used. Its \c read() member will called + /// with a stream contains the section. From this stream the empty and + /// comment lines are filtered out. + /// + /// \relates GraphReader + /// \relates NodeSetReader + /// \relates EdgeSetReader + /// \relates NodesReader + /// \relates EdgesReader + /// \relates AttributeReader + class LemonReader { + private: + + class FilterStreamBuf : public std::streambuf { + public: + + typedef std::streambuf Parent; + typedef Parent::char_type char_type; + FilterStreamBuf(std::istream& is, int& num) + : _is(is), _base(0), _eptr(0), + _num(num), skip_state(after_endl) {} + + protected: + + enum skip_state_type { + no_skip, + after_endl, + comment_line + }; + + char_type small_buf[1]; + + + std::istream& _is; + + char_type* _base; + char_type* _eptr; + + int& _num; + + skip_state_type skip_state; + + + char_type* base() { return _base; } + + char_type* eptr() { return _eptr; } + + int blen() { return _eptr - _base; } + + void setb(char_type* buf, int len) { + _base = buf; + _eptr = buf + len; + } + + virtual std::streambuf* setbuf(char *buf, int len) { + if (base()) return 0; + if (buf != 0 && len >= (int)sizeof(small_buf)) { + setb(buf, len); + } else { + setb(small_buf, sizeof(small_buf)); + } + setg(0, 0, 0); + return this; + } + + bool put_char(char c) { + switch (skip_state) { + case no_skip: + switch (c) { + case '\n': + skip_state = after_endl; + return true; + default: + return true; + } + case after_endl: + switch (c) { + case '@': + return false; + case '\n': + return false; + case '#': + skip_state = comment_line; + return false; + default: + if (!isspace(c)) { + skip_state = no_skip; + return true; + } else { + return false; + } + } + break; + case comment_line: + switch (c) { + case '\n': + skip_state = after_endl; + return false; + default: + return false; + } + } + return false; + } + + virtual int underflow() { + char c; + if (_is.read(&c, 1)) { + _is.putback(c); + if (c == '@') { + return EOF; + } + } else { + return EOF; + } + char_type *ptr; + for (ptr = base(); ptr != eptr(); ++ptr) { + if (_is.read(&c, 1)) { + if (c == '\n') ++_num; + if (put_char(c)) { + *ptr = c; + } else { + if (skip_state == after_endl && c == '@') { + _is.putback('@'); + break; + } + --ptr; + } + } else { + break; + } + } + setg(base(), base(), ptr); + return *base(); + } + + virtual int sync() { + return EOF; + } + }; + + public: + + /// \brief Abstract base class for reading a section. + /// + /// This class has an \c header() member function what get a + /// header line string and decides if it want to process the next + /// section. Several SectionReaders can be attached to an LemonReader + /// and the first attached what can process the section will be used. + /// Its \c read() member will called with a stream contains the section. + /// From this stream the empty lines and comments are filtered out. + class SectionReader { + friend class LemonReader; + protected: + /// \brief Constructor for SectionReader. + /// + /// Constructor for SectionReader. It attach this reader to + /// the given LemonReader. + SectionReader(LemonReader& reader) { + reader.attach(*this); + } + + /// \brief Gives back true when the SectionReader can process + /// the section with the given header line. + /// + /// It gives back true when the SectionReader can process + /// the section with the given header line. + virtual bool header(const std::string& line) = 0; + + /// \brief Reader function of the section. + /// + /// It reads the content of the section. + virtual void read(std::istream& is) = 0; + }; + + /// \brief Constructor for LemonReader. + /// + /// Constructor for LemonReader which reads from the given stream. + LemonReader(std::istream& _is) + : is(&_is), own_is(false) {} + + /// \brief Constructor for LemonReader. + /// + /// Constructor for LemonReader which reads from the given file. + LemonReader(const std::string& filename) + : is(0), own_is(true) { + is = new std::ifstream(filename.c_str()); + } + + /// \brief Desctructor for LemonReader. + /// + /// Desctructor for LemonReader. + ~LemonReader() { + if (own_is) { + delete is; + } + } + + private: + LemonReader(const LemonReader&); + void operator=(const LemonReader&); + + void attach(SectionReader& reader) { + readers.push_back(&reader); + } + + public: + /// \brief Executes the LemonReader. + /// + /// It executes the LemonReader. + void run() { + int line_num = 0; + std::string line; + try { + while ((++line_num, getline(*is, line)) && line.find("@end") != 0) { + SectionReaders::iterator it; + for (it = readers.begin(); it != readers.end(); ++it) { + if ((*it)->header(line)) { + char buf[2048]; + FilterStreamBuf buffer(*is, line_num); + buffer.pubsetbuf(buf, sizeof(buf)); + std::istream is(&buffer); + (*it)->read(is); + break; + } + } + } + } catch (DataFormatError& error) { + error.line(line_num); + throw error; + } + } + + + private: + + std::istream* is; + bool own_is; + + typedef std::vector SectionReaders; + SectionReaders readers; + + }; + + /// \brief Helper class for implementing the common SectionReaders. + /// + /// Helper class for implementing the common SectionReaders. + class CommonSectionReaderBase : public LemonReader::SectionReader { + typedef LemonReader::SectionReader Parent; + protected: + + /// \brief Constructor for CommonSectionReaderBase. + /// + /// Constructor for CommonSectionReaderBase. It attach this reader to + /// the given LemonReader. + CommonSectionReaderBase(LemonReader& _reader) + : Parent(_reader) {} + + template + class ReaderBase; + + template + class InverterBase : public ReaderBase<_Item> { + public: + typedef _Item Item; + virtual void read(std::istream&, const Item&) = 0; + virtual Item read(std::istream&) const = 0; + + virtual InverterBase<_Item>* getInverter() { + return this; + } + }; + + template + class MapReaderInverter : public InverterBase<_Item> { + public: + typedef _Item Item; + typedef _Reader Reader; + typedef typename Reader::Value Value; + typedef _Map Map; + typedef std::map > Inverse; + + typename SmartReference::Type map; + Reader reader; + Inverse inverse; + + MapReaderInverter(typename SmartParameter::Type _map, + const Reader& _reader) + : map(_map), reader(_reader) {} + + virtual ~MapReaderInverter() {} + + virtual void read(std::istream& is, const Item& item) { + Value value; + reader.read(is, value); + map.set(item, value); + typename Inverse::iterator it = inverse.find(value); + if (it == inverse.end()) { + inverse.insert(std::make_pair(value, item)); + } else { + throw DataFormatError("Multiple ID occurence"); + } + } + + virtual Item read(std::istream& is) const { + Value value; + reader.read(is, value); + typename Inverse::const_iterator it = inverse.find(value); + if (it != inverse.end()) { + return it->second; + } else { + throw DataFormatError("Invalid ID error"); + } + } + }; + + template + class SkipReaderInverter : public InverterBase<_Item> { + public: + typedef _Item Item; + typedef _Reader Reader; + typedef typename Reader::Value Value; + typedef std::map > Inverse; + + Reader reader; + + SkipReaderInverter(const Reader& _reader) + : reader(_reader) {} + + virtual ~SkipReaderInverter() {} + + virtual void read(std::istream& is, const Item& item) { + Value value; + reader.read(is, value); + typename Inverse::iterator it = inverse.find(value); + if (it == inverse.end()) { + inverse.insert(std::make_pair(value, item)); + } else { + throw DataFormatError("Multiple ID occurence error"); + } + } + + virtual Item read(std::istream& is) const { + Value value; + reader.read(is, value); + typename Inverse::const_iterator it = inverse.find(value); + if (it != inverse.end()) { + return it->second; + } else { + throw DataFormatError("Invalid ID error"); + } + } + + private: + Inverse inverse; + }; + + template + class ReaderBase { + public: + typedef _Item Item; + + virtual ~ReaderBase() {} + + virtual void read(std::istream& is, const Item& item) = 0; + virtual InverterBase<_Item>* getInverter() = 0; + }; + + template + class MapReader : public ReaderBase<_Item> { + public: + typedef _Map Map; + typedef _Reader Reader; + typedef typename Reader::Value Value; + typedef _Item Item; + + typename SmartReference::Type map; + Reader reader; + + MapReader(typename SmartParameter::Type _map, + const Reader& _reader) + : map(_map), reader(_reader) {} + + virtual ~MapReader() {} + + virtual void read(std::istream& is, const Item& item) { + Value value; + reader.read(is, value); + map.set(item, value); + } + + virtual InverterBase<_Item>* getInverter() { + return new MapReaderInverter(map, reader); + } + }; + + + template + class SkipReader : public ReaderBase<_Item> { + public: + typedef _Reader Reader; + typedef typename Reader::Value Value; + typedef _Item Item; + + Reader reader; + SkipReader(const Reader& _reader) : reader(_reader) {} + + virtual ~SkipReader() {} + + virtual void read(std::istream& is, const Item&) { + Value value; + reader.read(is, value); + } + + virtual InverterBase* getInverter() { + return new SkipReaderInverter(reader); + } + }; + + template + class IdReaderBase { + public: + typedef _Item Item; + virtual Item read(std::istream& is) const = 0; + }; + + template + class IdReader : public IdReaderBase<_Item> { + public: + typedef _Item Item; + typedef _BoxedIdReader BoxedIdReader; + + const BoxedIdReader& boxedIdReader; + + IdReader(const BoxedIdReader& _boxedIdReader) + : boxedIdReader(_boxedIdReader) {} + + virtual Item read(std::istream& is) const { + return boxedIdReader.readId(is, Item()); + } + }; + + class ValueReaderBase { + public: + virtual void read(std::istream&) {}; + }; + + template + class ValueReader : public ValueReaderBase { + public: + typedef _Value Value; + typedef _Reader Reader; + + ValueReader(Value& _value, const Reader& _reader) + : value(_value), reader(_reader) {} + + virtual void read(std::istream& is) { + reader.read(is, value); + } + private: + Value& value; + Reader reader; + }; + + }; + + /// \ingroup io_group + /// \brief SectionReader for reading a graph's nodeset. + /// + /// The lemon format can store multiple graph nodesets with several maps. + /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the + /// \c nodeset_id may be empty. + /// + /// The first line of the section contains the names of the maps separated + /// with white spaces. Each next lines describes a node in the nodeset, and + /// contains the mapped values for each map. + /// + /// If the nodeset contains an \c "id" named map then it will be regarded + /// as id map. This map should contain only unique values and when the + /// \c readId() member will read a value from the given stream it will + /// give back that node which is mapped to this value. + /// + /// \relates LemonReader + template + class NodeSetReader : public CommonSectionReaderBase { + typedef CommonSectionReaderBase Parent; + public: + + typedef _Graph Graph; + typedef _Traits Traits; + typedef typename Graph::Node Node; + typedef typename Traits::Skipper DefaultSkipper; + + /// \brief Constructor. + /// + /// Constructor for NodeSetReader. It creates the NodeSetReader and + /// attach it into the given LemonReader. The nodeset reader will + /// add the readed nodes to the given Graph. The reader will read + /// the section when the \c section_id and the \c _id are the same. + NodeSetReader(LemonReader& _reader, + typename SmartParameter::Type _graph, + const std::string& _id = std::string(), + const DefaultSkipper& _skipper = DefaultSkipper()) + : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} + + + /// \brief Destructor. + /// + /// Destructor for NodeSetReader. + virtual ~NodeSetReader() { + for (typename MapReaders::iterator it = readers.begin(); + it != readers.end(); ++it) { + delete it->second; + } + } + + private: + NodeSetReader(const NodeSetReader&); + void operator=(const NodeSetReader&); + + public: + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + NodeSetReader& readNodeMap(std::string name, Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename SmartParameter::Type>(name, map); + } + + template + NodeSetReader& readNodeMap(std::string name, const Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename SmartParameter::Type>(name, map); + } + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + NodeSetReader& readNodeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + return _readMap::Type> + (name, map, reader); + } + + template + NodeSetReader& readNodeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + return _readMap::Type> + (name, map, reader); + } + + private: + + template + NodeSetReader& _readMap(std::string name, MapParameter map, + const Reader& reader = Reader()) { + if (readers.find(name) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for node map: " << name; + throw IOParameterError(msg.message()); + } + readers.insert( + make_pair(name, new MapReader(map, reader))); + return *this; + } + + public: + + /// \brief Add a new node map skipper command for the reader. + /// + /// Add a new node map skipper command for the reader. + template + NodeSetReader& skipNodeMap(std::string name, + const Reader& reader = Reader()) { + if (readers.find(name) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for node map: " << name; + throw IOParameterError(msg.message()); + } + readers.insert(make_pair(name, new SkipReader(reader))); + return *this; + } + + protected: + + /// \brief Gives back true when the SectionReader can process + /// the section with the given header line. + /// + /// It gives back true when the header line starts with \c \@nodeset, + /// and the header line's id and the nodeset's id are the same. + virtual bool header(const std::string& line) { + std::istringstream ls(line); + std::string command; + std::string name; + ls >> command >> name; + return command == "@nodeset" && name == id; + } + + /// \brief Reader function of the section. + /// + /// It reads the content of the section. + virtual void read(std::istream& is) { + std::vector* > index; + std::string line; + + getline(is, line); + std::istringstream ls(line); + while (ls >> id) { + typename MapReaders::iterator it = readers.find(id); + if (it != readers.end()) { + index.push_back(it->second); + } else { + index.push_back(&skipper); + } + if (id == "id" && inverter.get() == 0) { + inverter.reset(index.back()->getInverter()); + index.back() = inverter.get(); + } + } + while (getline(is, line)) { + Node node = graph.addNode(); + std::istringstream ls(line); + for (int i = 0; i < (int)index.size(); ++i) { + index[i]->read(ls, node); + } + } + } + + public: + + /// \brief Returns true if the nodeset can give back the node by its id. + /// + /// Returns true if the nodeset can give back the node by its id. + /// It is possible only if an "id" named map was read. + bool isIdReader() const { + return inverter.get() != 0; + } + + /// \brief Gives back the node by its id. + /// + /// It reads an id from the stream and gives back which node belongs to + /// it. It is possible only if there was read an "id" named map. + Node readId(std::istream& is, Node = Node()) const { + return inverter->read(is); + } + + private: + + typedef std::map*> MapReaders; + MapReaders readers; + + typename SmartReference::Type graph; + std::string id; + SkipReader skipper; + + std::auto_ptr > inverter; + }; + + /// \ingroup io_group + /// \brief SectionReader for reading a graph's edgeset. + /// + /// The lemon format can store multiple graph edgesets with several maps. + /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the + /// \c edgeset_id may be empty. + /// + /// The first line of the section contains the names of the maps separated + /// with white spaces. Each next lines describes an edge in the edgeset. The + /// line contains the source and the target nodes' id and the mapped + /// values for each map. + /// + /// If the edgeset contains an \c "id" named map then it will be regarded + /// as id map. This map should contain only unique values and when the + /// \c readId() member will read a value from the given stream it will + /// give back that edge which is mapped to this value. + /// + /// The edgeset reader needs a node id reader to identify which nodes + /// have to be connected. If a NodeSetReader reads an "id" named map, + /// it will be able to resolve the nodes by ids. + /// + /// \relates LemonReader + template + class EdgeSetReader : public CommonSectionReaderBase { + typedef CommonSectionReaderBase Parent; + public: + + typedef _Graph Graph; + typedef _Traits Traits; + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + typedef typename Traits::Skipper DefaultSkipper; + + /// \brief Constructor. + /// + /// Constructor for EdgeSetReader. It creates the EdgeSetReader and + /// attach it into the given LemonReader. The edgeset reader will + /// add the readed edges to the given Graph. It will use the given + /// node id reader to read the source and target nodes of the edges. + /// The reader will read the section only if the \c _id and the + /// \c edgset_id are the same. + template + EdgeSetReader(LemonReader& _reader, + typename SmartParameter::Type _graph, + const NodeIdReader& _nodeIdReader, + const std::string& _id = std::string(), + const DefaultSkipper& _skipper = DefaultSkipper()) + : Parent(_reader), graph(_graph), id(_id), skipper(_skipper), + nodeIdReader(new IdReader(_nodeIdReader)) {} + + /// \brief Destructor. + /// + /// Destructor for EdgeSetReader. + virtual ~EdgeSetReader() { + for (typename MapReaders::iterator it = readers.begin(); + it != readers.end(); ++it) { + delete it->second; + } + } + + private: + EdgeSetReader(const EdgeSetReader&); + void operator=(const EdgeSetReader&); + + public: + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + EdgeSetReader& readEdgeMap(std::string name, Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename SmartParameter::Type>(name, map); + } + + template + EdgeSetReader& readEdgeMap(std::string name, const Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename SmartParameter::Type>(name, map); + } + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + EdgeSetReader& readEdgeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + return _readMap::Type>(name, map, reader); + } + + template + EdgeSetReader& readEdgeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + return _readMap::Type>(name, map, reader); + } + + private: + + template + EdgeSetReader& _readMap(std::string name, MapParameter map, + const Reader& reader = Reader()) { + if (readers.find(name) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for edge map: " << name; + throw IOParameterError(msg.message()); + } + readers.insert( + make_pair(name, new MapReader(map, reader))); + return *this; + } + + public: + + /// \brief Add a new edge map skipper command for the reader. + /// + /// Add a new edge map skipper command for the reader. + template + EdgeSetReader& skipEdgeMap(std::string name, + const Reader& reader = Reader()) { + if (readers.find(name) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for edge map: " << name; + throw IOParameterError(msg.message()); + } + readers.insert(make_pair(name, new SkipReader(reader))); + return *this; + } + + protected: + + /// \brief Gives back true when the SectionReader can process + /// the section with the given header line. + /// + /// It gives back true when the header line starts with \c \@edgeset, + /// and the header line's id and the edgeset's id are the same. + virtual bool header(const std::string& line) { + std::istringstream ls(line); + std::string command; + std::string name; + ls >> command >> name; + return command == "@edgeset" && name == id; + } + + /// \brief Reader function of the section. + /// + /// It reads the content of the section. + virtual void read(std::istream& is) { + std::vector* > index; + std::string line; + + getline(is, line); + std::istringstream ls(line); + while (ls >> id) { + typename MapReaders::iterator it = readers.find(id); + if (it != readers.end()) { + index.push_back(it->second); + } else { + index.push_back(&skipper); + } + if (id == "id" && inverter.get() == 0) { + inverter.reset(index.back()->getInverter()); + index.back() = inverter.get(); + } + } + while (getline(is, line)) { + std::istringstream ls(line); + Node from = nodeIdReader->read(ls); + Node to = nodeIdReader->read(ls); + Edge edge = graph.addEdge(from, to); + for (int i = 0; i < (int)index.size(); ++i) { + index[i]->read(ls, edge); + } + } + } + + public: + + /// \brief Returns true if the edgeset can give back the edge by its id. + /// + /// Returns true if the edgeset can give back the edge by its id. + /// It is possible only if an "id" named map was read. + bool isIdReader() const { + return inverter.get() != 0; + } + + /// \brief Gives back the edge by its id. + /// + /// It reads an id from the stream and gives back which edge belongs to + /// it. It is possible only if there was read an "id" named map. + Edge readId(std::istream& is, Edge = Edge()) const { + return inverter->read(is); + } + + private: + + typedef std::map*> MapReaders; + MapReaders readers; + + typename SmartReference::Type graph; + std::string id; + SkipReader skipper; + + std::auto_ptr > inverter; + std::auto_ptr > nodeIdReader; + }; + + /// \ingroup io_group + /// \brief SectionReader for reading a undirected graph's edgeset. + /// + /// The lemon format can store multiple undirected edgesets with several + /// maps. The undirected edgeset section's header line is \c \@undiredgeset + /// \c undiredgeset_id, but the \c undiredgeset_id may be empty. + /// + /// The first line of the section contains the names of the maps separated + /// with white spaces. Each next lines describes an edge in the edgeset. The + /// line contains the connected nodes' id and the mapped values for each map. + /// + /// The section can handle the directed as a syntactical sugar. Two + /// undirected edge map describes one directed edge map. This two maps + /// are the forward map and the backward map and the names of this map + /// is near the same just with a prefix \c '+' or \c '-' character + /// difference. + /// + /// If the edgeset contains an \c "id" named map then it will be regarded + /// as id map. This map should contain only unique values and when the + /// \c readId() member will read a value from the given stream it will + /// give back that undiricted edge which is mapped to this value. + /// + /// The undirected edgeset reader needs a node id reader to identify which + /// nodes have to be connected. If a NodeSetReader reads an "id" named map, + /// it will be able to resolve the nodes by ids. + /// + /// \relates LemonReader + template + class UndirEdgeSetReader : public CommonSectionReaderBase { + typedef CommonSectionReaderBase Parent; + public: + + typedef _Graph Graph; + typedef _Traits Traits; + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + typedef typename Graph::UndirEdge UndirEdge; + typedef typename Traits::Skipper DefaultSkipper; + + /// \brief Constructor. + /// + /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader + /// and attach it into the given LemonReader. The undirected edgeset + /// reader will add the readed undirected edges to the given Graph. It + /// will use the given node id reader to read the source and target + /// nodes of the edges. The reader will read the section only if the + /// \c _id and the \c undiredgset_id are the same. + template + UndirEdgeSetReader(LemonReader& _reader, + typename SmartParameter::Type _graph, + const NodeIdReader& _nodeIdReader, + const std::string& _id = std::string(), + const DefaultSkipper& _skipper = DefaultSkipper()) + : Parent(_reader), graph(_graph), id(_id), skipper(_skipper), + nodeIdReader(new IdReader(_nodeIdReader)) {} + + /// \brief Destructor. + /// + /// Destructor for UndirEdgeSetReader. + virtual ~UndirEdgeSetReader() { + for (typename MapReaders::iterator it = readers.begin(); + it != readers.end(); ++it) { + delete it->second; + } + } + + private: + UndirEdgeSetReader(const UndirEdgeSetReader&); + void operator=(const UndirEdgeSetReader&); + + public: + + /// \brief Add a new undirected edge map reader command for the reader. + /// + /// Add a new edge undirected map reader command for the reader. + template + UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename SmartParameter::Type>(name, map); + } + + template + UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) { + return _readMap< + typename Traits::template Reader, Map, + typename SmartParameter::Type>(name, map); + } + + /// \brief Add a new undirected edge map reader command for the reader. + /// + /// Add a new edge undirected map reader command for the reader. + template + UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + return _readMap::Type> + (name, map, reader); + } + + template + UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + return _readMap::Type > + (name, map, reader); + } + + private: + + template + UndirEdgeSetReader& _readMap(std::string name, MapParameter map, + const Reader& reader = Reader()) { + if (readers.find(name) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for edge map: " << name; + throw IOParameterError(msg.message()); + } + readers.insert( + make_pair(name, new MapReader(map, reader))); + return *this; + } + + public: + + /// \brief Add a new undirected edge map skipper command for the reader. + /// + /// Add a new undirected edge map skipper command for the reader. + template + UndirEdgeSetReader& skipUndirEdgeMap(std::string name, + const Reader& reader = Reader()) { + if (readers.find(name) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for node map: " << name; + throw IOParameterError(msg.message()); + } + readers.insert(make_pair(name, + new SkipReader(reader))); + return *this; + } + + /// \brief Add a new directed edge map reader command for the reader. + /// + /// Add a new directed edge map reader command for the reader. + template + UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) { + return _readDirMap< + typename Traits::template Reader, Map, + typename SmartParameter::Type>(name, map); + } + + template + UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) { + return _readDirMap< + typename Traits::template Reader, Map, + typename SmartParameter::Type>(name, map); + } + + /// \brief Add a new directed edge map reader command for the reader. + /// + /// Add a new directed edge map reader command for the reader. + template + UndirEdgeSetReader& readEdgeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + return _readDirMap::Type> + (name, map, reader); + } + + template + UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + return _readDirMap::Type> + (name, map, reader); + } + + private: + + template + UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map, + const Reader& reader = Reader()) { + readMap("+" + name, + _reader_bits::writeComposeMap(map, forwardMap(graph)), reader); + readMap("-" + name, + _reader_bits::writeComposeMap(map, backwardMap(graph)), reader); + return *this; + } + + public: + + /// \brief Add a new directed edge map skipper command for the reader. + /// + /// Add a new directed edge map skipper command for the reader. + template + UndirEdgeSetReader& skipEdgeMap(std::string name, + const Reader& reader = Reader()) { + skipMap("+" + name, reader); + skipMap("-" + name, reader); + return *this; + } + + protected: + + /// \brief Gives back true when the SectionReader can process + /// the section with the given header line. + /// + /// It gives back true when the header line starts with \c \@undiredgeset, + /// and the header line's id and the edgeset's id are the same. + virtual bool header(const std::string& line) { + std::istringstream ls(line); + std::string command; + std::string name; + ls >> command >> name; + return command == "@undiredgeset" && name == id; + } + + /// \brief Reader function of the section. + /// + /// It reads the content of the section. + virtual void read(std::istream& is) { + std::vector* > index; + std::string line; + + getline(is, line); + std::istringstream ls(line); + while (ls >> id) { + typename MapReaders::iterator it = readers.find(id); + if (it != readers.end()) { + index.push_back(it->second); + } else { + index.push_back(&skipper); + } + if (id == "id" && inverter.get() == 0) { + inverter.reset(index.back()->getInverter()); + index.back() = inverter.get(); + } + } + while (getline(is, line)) { + std::istringstream ls(line); + Node from = nodeIdReader->read(ls); + Node to = nodeIdReader->read(ls); + UndirEdge edge = graph.addEdge(from, to); + for (int i = 0; i < (int)index.size(); ++i) { + index[i]->read(ls, edge); + } + } + } + + public: + + /// \brief Returns true if the edgeset can give back the edge by its id. + /// + /// Returns true if the edgeset can give back the undirected edge by its + /// id. It is possible only if an "id" named map was read. + bool isIdReader() const { + return inverter.get() != 0; + } + + /// \brief Gives back the undirected edge by its id. + /// + /// It reads an id from the stream and gives back which undirected edge + /// belongs to it. It is possible only if there was read an "id" named map. + UndirEdge readId(std::istream& is, UndirEdge = UndirEdge()) const { + return inverter->read(is); + } + + /// \brief Gives back the directed edge by its id. + /// + /// It reads an id from the stream and gives back which directed edge + /// belongs to it. The directed edge id is the \c '+' or \c '-' character + /// and the undirected edge id. It is possible only if there was read + /// an "id" named map. + Edge readId(std::istream& is, Edge = Edge()) const { + char c; + is >> c; + UndirEdge undirEdge = inverter->read(is); + if (c == '+') { + return graph.edgeWithSource(undirEdge, graph.source(undirEdge)); + } else if (c == '-') { + return graph.edgeWithSource(undirEdge, graph.target(undirEdge)); + } else { + throw DataFormatError("Wrong id format for edge " + "in undirected edgeset"); + } + } + + private: + + typedef std::map*> MapReaders; + MapReaders readers; + + typename SmartReference::Type graph; + std::string id; + SkipReader skipper; + + std::auto_ptr > inverter; + std::auto_ptr > nodeIdReader; + }; + + /// \ingroup io_group + /// \brief SectionReader for reading labeled nodes. + /// + /// The nodes section's header line is \c \@nodes \c nodes_id, but the + /// \c nodes_id may be empty. + /// + /// Each line in the section contains the name of the node + /// and then the node id. + /// + /// \relates LemonReader + template + class NodeReader : public CommonSectionReaderBase { + typedef CommonSectionReaderBase Parent; + typedef _Graph Graph; + typedef typename Graph::Node Node; + public: + + /// \brief Constructor. + /// + /// Constructor for NodeReader. It creates the NodeReader and + /// attach it into the given LemonReader. It will use the given + /// node id reader to give back the nodes. The reader will read the + /// section only if the \c _id and the \c nodes_id are the same. + template + NodeReader(LemonReader& _reader, const _IdReader& _idReader, + const std::string& _id = std::string()) + : Parent(_reader), id(_id), + idReader(new IdReader(_idReader)) {} + + /// \brief Destructor. + /// + /// Destructor for NodeReader. + virtual ~NodeReader() {} + + private: + NodeReader(const NodeReader&); + void operator=(const NodeReader&); + + public: + + /// \brief Add a node reader command for the NodeReader. + /// + /// Add a node reader command for the NodeReader. + void readNode(const std::string& name, Node& item) { + if (readers.find(name) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for node: " << name; + throw IOParameterError(msg.message()); + } + readers.insert(make_pair(name, &item)); + } + + protected: + + /// \brief Gives back true when the SectionReader can process + /// the section with the given header line. + /// + /// It gives back true when the header line start with \c \@nodes, + /// and the header line's id and the reader's id are the same. + virtual bool header(const std::string& line) { + std::istringstream ls(line); + std::string command; + std::string name; + ls >> command >> name; + return command == "@nodes" && name == id; + } + + /// \brief Reader function of the section. + /// + /// It reads the content of the section. + virtual void read(std::istream& is) { + std::string line; + while (getline(is, line)) { + std::istringstream ls(line); + std::string id; + ls >> id; + typename NodeReaders::iterator it = readers.find(id); + if (it != readers.end()) { + *(it->second) = idReader->read(ls); + } + } + } + + private: + + std::string id; + + typedef std::map NodeReaders; + NodeReaders readers; + std::auto_ptr > idReader; + }; + + /// \ingroup io_group + /// \brief SectionReader for reading labeled edges. + /// + /// The edges section's header line is \c \@edges \c edges_id, but the + /// \c edges_id may be empty. + /// + /// Each line in the section contains the name of the edge + /// and then the edge id. + /// + /// \relates LemonReader + template + class EdgeReader : public CommonSectionReaderBase { + typedef CommonSectionReaderBase Parent; + typedef _Graph Graph; + typedef typename Graph::Edge Edge; + public: + + /// \brief Constructor. + /// + /// Constructor for EdgeReader. It creates the EdgeReader and + /// attach it into the given LemonReader. It will use the given + /// edge id reader to give back the edges. The reader will read the + /// section only if the \c _id and the \c edges_id are the same. + template + EdgeReader(LemonReader& _reader, const _IdReader& _idReader, + const std::string& _id = std::string()) + : Parent(_reader), id(_id), + idReader(new IdReader(_idReader)) {} + + /// \brief Destructor. + /// + /// Destructor for EdgeReader. + virtual ~EdgeReader() {} + private: + EdgeReader(const EdgeReader&); + void operator=(const EdgeReader&); + + public: + + /// \brief Add an edge reader command for the EdgeReader. + /// + /// Add an edge reader command for the EdgeReader. + void readEdge(const std::string& name, Edge& item) { + if (readers.find(name) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for edge: " << name; + throw IOParameterError(msg.message()); + } + readers.insert(make_pair(name, &item)); + } + + protected: + + /// \brief Gives back true when the SectionReader can process + /// the section with the given header line. + /// + /// It gives back true when the header line start with \c \@edges, + /// and the header line's id and the reader's id are the same. + virtual bool header(const std::string& line) { + std::istringstream ls(line); + std::string command; + std::string name; + ls >> command >> name; + return command == "@edges" && name == id; + } + + /// \brief Reader function of the section. + /// + /// It reads the content of the section. + virtual void read(std::istream& is) { + std::string line; + while (getline(is, line)) { + std::istringstream ls(line); + std::string id; + ls >> id; + typename EdgeReaders::iterator it = readers.find(id); + if (it != readers.end()) { + *(it->second) = idReader->read(ls); + } + } + } + + private: + + std::string id; + + typedef std::map EdgeReaders; + EdgeReaders readers; + std::auto_ptr > idReader; + }; + + /// \ingroup io_group + /// \brief SectionReader for reading labeled undirected edges. + /// + /// The undirected edges section's header line is \c \@undiredges + /// \c undiredges_id, but the \c undiredges_id may be empty. + /// + /// Each line in the section contains the name of the undirected edge + /// and then the undirected edge id. + /// + /// \relates LemonReader + template + class UndirEdgeReader : public CommonSectionReaderBase { + typedef CommonSectionReaderBase Parent; + typedef _Graph Graph; + typedef typename Graph::Edge Edge; + typedef typename Graph::UndirEdge UndirEdge; + public: + + /// \brief Constructor. + /// + /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and + /// attach it into the given LemonReader. It will use the given + /// undirected edge id reader to give back the edges. The reader will + /// read the section only if the \c _id and the \c undiredges_id are + /// the same. + template + UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, + const std::string& _id = std::string()) + : Parent(_reader), id(_id), + undirEdgeIdReader(new IdReader(_idReader)), + edgeIdReader(new IdReader(_idReader)) + {} + + /// \brief Destructor. + /// + /// Destructor for UndirEdgeReader. + virtual ~UndirEdgeReader() {} + private: + UndirEdgeReader(const UndirEdgeReader&); + void operator=(const UndirEdgeReader&); + + public: + + /// \brief Add an undirected edge reader command for the UndirEdgeReader. + /// + /// Add an undirected edge reader command for the UndirEdgeReader. + void readUndirEdge(const std::string& name, UndirEdge& item) { + if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) { + ErrorMessage msg; + msg << "Multiple read rule for undirected edge: " << name; + throw IOParameterError(msg.message()); + } + undirEdgeReaders.insert(make_pair(name, &item)); + } + + /// \brief Add an edge reader command for the UndirEdgeReader. + /// + /// Add an edge reader command for the UndirEdgeReader. + void readEdge(const std::string& name, Edge& item) { + if (edgeReaders.find(name) != edgeReaders.end()) { + ErrorMessage msg; + msg << "Multiple read rule for edge: " << name; + throw IOParameterError(msg.message()); + } + edgeReaders.insert(make_pair(name, &item)); + } + + protected: + + /// \brief Gives back true when the SectionReader can process + /// the section with the given header line. + /// + /// It gives back true when the header line start with \c \@edges, + /// and the header line's id and the reader's id are the same. + virtual bool header(const std::string& line) { + std::istringstream ls(line); + std::string command; + std::string name; + ls >> command >> name; + return command == "@undiredges" && name == id; + } + + /// \brief Reader function of the section. + /// + /// It reads the content of the section. + virtual void read(std::istream& is) { + std::string line; + while (getline(is, line)) { + std::istringstream ls(line); + std::string id; + ls >> id; + { + typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id); + if (it != undirEdgeReaders.end()) { + *(it->second) = undirEdgeIdReader->read(ls); + break; + } + } { + typename EdgeReaders::iterator it = edgeReaders.find(id); + if (it != edgeReaders.end()) { + *(it->second) = edgeIdReader->read(ls); + break; + } + } + } + } + + private: + + std::string id; + + typedef std::map UndirEdgeReaders; + UndirEdgeReaders undirEdgeReaders; + std::auto_ptr > undirEdgeIdReader; + + typedef std::map EdgeReaders; + EdgeReaders edgeReaders; + std::auto_ptr > edgeIdReader; + }; + + /// \ingroup io_group + /// \brief SectionReader for attributes. + /// + /// The lemon format can store multiple attribute set. Each set has + /// the header line \c \@attributes \c attributeset_id, but the + /// attributeset_id may be empty. + /// + /// The attributeset section contains several lines. Each of them starts + /// with an attribute and then a the value for the id. + /// + /// \relates LemonReader + template + class AttributeReader : public CommonSectionReaderBase { + typedef CommonSectionReaderBase Parent; + typedef _Traits Traits; + public: + /// \brief Constructor. + /// + /// Constructor for AttributeReader. It creates the AttributeReader and + /// attach it into the given LemonReader. The reader process a section + /// only if the \c section_id and the \c _id are the same. + AttributeReader(LemonReader& _reader, + const std::string& _id = std::string()) + : Parent(_reader), id(_id) {} + + /// \brief Destructor. + /// + /// Destructor for AttributeReader. + virtual ~AttributeReader() { + for (typename Readers::iterator it = readers.begin(); + it != readers.end(); ++it) { + delete it->second; + } + } + + private: + AttributeReader(const AttributeReader&); + void operator=(AttributeReader&); + + public: + /// \brief Add an attribute reader command for the reader. + /// + /// Add an attribute reader command for the reader. + template + AttributeReader& readAttribute(const std::string& id, Value& value) { + return readAttribute > + (id, value); + } + + /// \brief Add an attribute reader command for the reader. + /// + /// Add an attribute reader command for the reader. + template + AttributeReader& readAttribute(const std::string& name, Value& value, + const Reader& reader = Reader()) { + if (readers.find(name) != readers.end()) { + ErrorMessage msg; + msg << "Multiple read rule for attribute: " << name; + throw IOParameterError(msg.message()); + } + readers.insert(make_pair(name, new ValueReader + (value, reader))); + return *this; + } + + protected: + + /// \brief Gives back true when the SectionReader can process + /// the section with the given header line. + /// + /// It gives back true when the header line start with \c \@attributes, + /// and the header line's id and the attributeset's id are the same. + bool header(const std::string& line) { + std::istringstream ls(line); + std::string command; + std::string name; + ls >> command >> name; + return command == "@attributes" && name == id; + } + + /// \brief Reader function of the section. + /// + /// It reads the content of the section. + void read(std::istream& is) { + std::string line; + while (getline(is, line)) { + std::istringstream ls(line); + std::string id; + ls >> id; + typename Readers::iterator it = readers.find(id); + if (it != readers.end()) { + it->second->read(ls); + } + } + } + + private: + std::string id; + + typedef std::map Readers; + Readers readers; + }; + + /// \ingroup io_group + /// \brief SectionReader for retrieve what is in the file. + /// + /// SectionReader for retrieve what is in the file. If you want + /// to know which sections, maps and items are in the file + /// use the next code: + /// \code + /// LemonReader reader("input.lgf"); + /// ContentReader content(reader); + /// reader.run(); + /// \endcode + class ContentReader : public LemonReader::SectionReader { + typedef LemonReader::SectionReader Parent; + public: + /// \brief Constructor. + /// + /// Constructor for + ContentReader(LemonReader& _reader) : Parent(_reader) {} + + /// \brief Desctructor. + /// + /// Desctructor. + virtual ~ContentReader() {} + + /// \brief Gives back how many nodesets are in the file. + /// + /// Gives back how many nodesets are in the file. + int nodeSetNum() const { + return nodesets.size(); + } + + /// \brief Gives back the name of nodeset on the indiced position. + /// + /// Gives back the name of nodeset on the indiced position. + std::string nodeSetName(int index) const { + return nodesets[index].name; + } + + /// \brief Gives back the map names of nodeset on the indiced position. + /// + /// Gives back the map names of nodeset on the indiced position. + const std::vector& nodeSetMaps(int index) const { + return nodesets[index].items; + } + + /// \brief Gives back how many edgesets are in the file. + /// + /// Gives back how many edgesets are in the file. + int edgeSetNum() const { + return edgesets.size(); + } + + /// \brief Gives back the name of edgeset on the indiced position. + /// + /// Gives back the name of edgeset on the indiced position. + std::string edgeSetName(int index) const { + return edgesets[index].name; + } + + /// \brief Gives back the map names of edgeset on the indiced position. + /// + /// Gives back the map names of edgeset on the indiced position. + const std::vector& edgeSetMaps(int index) const { + return edgesets[index].items; + } + + /// \brief Gives back how many undirected edgesets are in the file. + /// + /// Gives back how many undirected edgesets are in the file. + int undirEdgeSetNum() const { + return undiredgesets.size(); + } + + /// \brief Gives back the name of undirected edgeset on the indiced + /// position. + /// + /// Gives back the name of undirected edgeset on the indiced position. + std::string undirEdgeSetName(int index) const { + return undiredgesets[index].name; + } + + /// \brief Gives back the map names of undirected edgeset on the indiced + /// position. + /// + /// Gives back the map names of undirected edgeset on the indiced position. + const std::vector& undirEdgeSetMaps(int index) const { + return undiredgesets[index].items; + } + + /// \brief Gives back how many labeled nodes section are in the file. + /// + /// Gives back how many labeled nodes section are in the file. + int nodesNum() const { + return nodes.size(); + } + + /// \brief Gives back the name of labeled nodes section on the indiced + /// position. + /// + /// Gives back the name of labeled nodes section on the indiced position. + std::string nodesName(int index) const { + return nodes[index].name; + } + + /// \brief Gives back the names of the labeled nodes in the indiced + /// section. + /// + /// Gives back the names of the labeled nodes in the indiced section. + const std::vector& nodesItems(int index) const { + return nodes[index].items; + } + + /// \brief Gives back how many labeled edges section are in the file. + /// + /// Gives back how many labeled edges section are in the file. + int edgesNum() const { + return edges.size(); + } + + /// \brief Gives back the name of labeled edges section on the indiced + /// position. + /// + /// Gives back the name of labeled edges section on the indiced position. + std::string edgesName(int index) const { + return edges[index].name; + } + + /// \brief Gives back the names of the labeled edges in the indiced + /// section. + /// + /// Gives back the names of the labeled edges in the indiced section. + const std::vector& edgesItems(int index) const { + return edges[index].items; + } + + /// \brief Gives back how many labeled undirected edges section are + /// in the file. + /// + /// Gives back how many labeled undirected edges section are in the file. + int undirEdgesNum() const { + return undiredges.size(); + } + + /// \brief Gives back the name of labeled undirected edges section + /// on the indiced position. + /// + /// Gives back the name of labeled undirected edges section on the + /// indiced position. + std::string undirEdgesName(int index) const { + return undiredges[index].name; + } + + /// \brief Gives back the names of the labeled undirected edges in + /// the indiced section. + /// + /// Gives back the names of the labeled undirected edges in the + /// indiced section. + const std::vector& undirEdgesItems(int index) const { + return undiredges[index].items; + } + + + /// \brief Gives back how many attributes section are in the file. + /// + /// Gives back how many attributes section are in the file. + int attributesNum() const { + return attributes.size(); + } + + /// \brief Gives back the name of attributes section on the indiced + /// position. + /// + /// Gives back the name of attributes section on the indiced position. + std::string attributesName(int index) const { + return attributes[index].name; + } + + /// \brief Gives back the names of the attributes in the indiced section. + /// + /// Gives back the names of the attributes in the indiced section. + const std::vector& attributesItems(int index) const { + return attributes[index].items; + } + + const std::vector& otherSections() const { + return sections; + } + + protected: + + /// \brief Gives back true when the SectionReader can process + /// the section with the given header line. + /// + /// It gives back true when the section is common section. + bool header(const std::string& line) { + std::istringstream ls(line); + std::string command, name; + ls >> command >> name; + if (command == "@nodeset") { + current = command; + nodesets.push_back(SectionInfo(name)); + } else if (command == "@edgeset") { + current = command; + edgesets.push_back(SectionInfo(name)); + } else if (command == "@undiredgeset") { + current = command; + undiredgesets.push_back(SectionInfo(name)); + } else if (command == "@nodes") { + current = command; + nodes.push_back(SectionInfo(name)); + } else if (command == "@edges") { + current = command; + edges.push_back(SectionInfo(name)); + } else if (command == "@undiredges") { + current = command; + undiredges.push_back(SectionInfo(name)); + } else if (command == "@attributes") { + current = command; + attributes.push_back(SectionInfo(name)); + } else { + sections.push_back(line); + return false; + } + return true; + } + + /// \brief Retrieve the items from various sections. + /// + /// Retrieve the items from various sections. + void read(std::istream& is) { + if (current == "@nodeset") { + readMapNames(is, nodesets.back().items); + } else if (current == "@edgeset") { + readMapNames(is, edgesets.back().items); + } else if (current == "@undiredgeset") { + readMapNames(is, undiredgesets.back().items); + } else if (current == "@nodes") { + readItemNames(is, nodes.back().items); + } else if (current == "@edges") { + readItemNames(is, edges.back().items); + } else if (current == "@undiredges") { + readItemNames(is, undiredges.back().items); + } else if (current == "@attributes") { + readItemNames(is, attributes.back().items); + } + } + + private: + + void readMapNames(std::istream& is, std::vector& maps) { + std::string line, id; + std::getline(is, line); + std::istringstream ls(line); + while (ls >> id) { + maps.push_back(id); + } + while (getline(is, line)); + } + + void readItemNames(std::istream& is, std::vector& maps) { + std::string line, id; + while (std::getline(is, line)) { + std::istringstream ls(line); + ls >> id; + maps.push_back(id); + } + } + + struct SectionInfo { + std::string name; + std::vector items; + + SectionInfo(const std::string& _name) : name(_name) {} + }; + + std::vector nodesets; + std::vector edgesets; + std::vector undiredgesets; + + std::vector nodes; + std::vector edges; + std::vector undiredges; + + std::vector attributes; + + std::vector sections; + + std::string current; + + }; + +} +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lemon_writer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lemon_writer.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,1129 @@ +/* -*- C++ -*- + * lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\ingroup io_group +///\file +///\brief Lemon Format writer. + +#ifndef LEMON_LEMON_WRITER_H +#define LEMON_LEMON_WRITER_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +namespace lemon { + + /// \ingroup io_group + /// \brief Lemon Format writer class. + /// + /// The Lemon Format contains several sections. We do not want to + /// determine what sections are in a lemon file we give only a framework + /// to write a section oriented format. + /// + /// In the Lemon Format each section starts with a line contains a \c \@ + /// character on the first not white space position. This line is the + /// header line of the section. Each next lines belong to this section + /// while it does not starts with \c \@ character. This line can start a + /// new section or if it can close the file with the \c \@end line. + /// The file format ignore the empty lines and it may contain comments + /// started with a \c # character to the end of the line. + /// + /// The framework provides an abstract LemonWriter::SectionWriter class + /// what defines the interface of a SectionWriter. The SectionWriter + /// has the \c header() member function what gives back the header of the + /// section. After that it will be called the \c write() member which + /// should write the content of the section. + /// + /// \relates GraphWriter + /// \relates NodeSetWriter + /// \relates EdgeSetWriter + /// \relates NodesWriter + /// \relates EdgesWriter + /// \relates AttributeWriter + class LemonWriter { + public: + + /// \brief Abstract base class for writing a section. + /// + /// This class has an \c header() member function what gives back + /// the header line of the section. The \c write() member should + /// write the content of the section to the stream. + class SectionWriter { + friend class LemonWriter; + protected: + /// \brief Constructor for SectionWriter. + /// + /// Constructor for SectionWriter. It attach this writer to + /// the given LemonWriter. + SectionWriter(LemonWriter& writer) { + writer.attach(*this); + } + + /// \brief The header of section. + /// + /// It gives back the header of the section. + virtual std::string header() = 0; + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + virtual void write(std::ostream& os) = 0; + }; + + /// \brief Constructor for LemonWriter. + /// + /// Constructor for LemonWriter which writes to the given stream. + LemonWriter(std::ostream& _os) + : os(&_os), own_os(false) {} + + /// \brief Constructor for LemonWriter. + /// + /// Constructor for LemonWriter which writes to the given file. + LemonWriter(const std::string& filename) + : os(0), own_os(true) { + os = new std::ofstream(filename.c_str()); + } + + /// \brief Desctructor for LemonWriter. + /// + /// Desctructor for LemonWriter. + ~LemonWriter() { + if (own_os) { + delete os; + } + } + + private: + LemonWriter(const LemonWriter&); + void operator=(const LemonWriter&); + + void attach(SectionWriter& writer) { + writers.push_back(&writer); + } + + public: + + /// \brief Executes the LemonWriter. + /// + /// It executes the LemonWriter. + void run() { + SectionWriters::iterator it; + for (it = writers.begin(); it != writers.end(); ++it) { + *os << (*it)->header() << std::endl; + (*it)->write(*os); + } + *os << "@end" << std::endl; + } + + + private: + + std::ostream* os; + bool own_os; + + typedef std::vector SectionWriters; + SectionWriters writers; + + }; + + /// \brief Helper class for implementing the common SectionWriters. + /// + /// Helper class for implementing the common SectionWriters. + class CommonSectionWriterBase : public LemonWriter::SectionWriter { + typedef LemonWriter::SectionWriter Parent; + protected: + + /// \brief Constructor for CommonSectionWriterBase. + /// + /// Constructor for CommonSectionWriterBase. It attach this writer to + /// the given LemonWriter. + CommonSectionWriterBase(LemonWriter& _writer) + : Parent(_writer) {} + + template + class WriterBase { + public: + typedef _Item Item; + + virtual ~WriterBase() {} + + virtual void write(std::ostream& os, const Item& item) = 0; + }; + + + template + class MapWriter : public WriterBase<_Item> { + public: + typedef _Map Map; + typedef _Writer Writer; + typedef typename Writer::Value Value; + typedef _Item Item; + + typename SmartConstReference::Type map; + Writer writer; + + MapWriter(const Map& _map, const Writer& _writer) + : map(_map), writer(_writer) {} + + virtual ~MapWriter() {} + + virtual void write(std::ostream& os, const Item& item) { + Value value = map[item]; + writer.write(os, value); + } + + }; + + + class ValueWriterBase { + public: + virtual void write(std::ostream&) = 0; + }; + + template + class ValueWriter : public ValueWriterBase { + public: + typedef _Value Value; + typedef _Writer Writer; + + ValueWriter(const Value& _value, const Writer& _writer) + : value(_value), writer(_writer) {} + + virtual void write(std::ostream& os) { + writer.write(os, value); + } + private: + const Value& value; + Writer writer; + }; + + + template + class IdWriterBase { + public: + typedef _Item Item; + virtual void write(std::ostream&, const Item&) const = 0; + }; + + template + class IdWriter : public IdWriterBase<_Item> { + public: + typedef _Item Item; + typedef _BoxedIdWriter BoxedIdWriter; + + const BoxedIdWriter& idWriter; + + IdWriter(const BoxedIdWriter& _idWriter) + : idWriter(_idWriter) {} + + virtual void write(std::ostream& os, const Item& item) const { + idWriter.writeId(os, item); + } + }; + }; + + /// \ingroup io_group + /// \brief SectionWriter for writing a graph's nodeset. + /// + /// The lemon format can store multiple graph nodesets with several maps. + /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the + /// \c nodeset_id may be empty. + /// + /// The first line of the section contains the names of the maps separated + /// with white spaces. Each next lines describes a node in the nodeset, and + /// contains the mapped values for each map. + /// + /// If the nodeset contains an \c "id" named map then it will be regarded + /// as id map. This map should contain only unique values and when the + /// \c writeId() member will be called with a node it will write it's id. + /// Otherwise if the \c _forceIdMap constructor parameter is true then + /// the id map will be the id in the graph. + /// + /// \relates LemonWriter + template + class NodeSetWriter : public CommonSectionWriterBase { + typedef CommonSectionWriterBase Parent; + public: + + typedef _Graph Graph; + typedef _Traits Traits; + typedef typename Graph::Node Node; + + /// \brief Constructor. + /// + /// Constructor for NodeSetWriter. It creates the NodeSetWriter and + /// attach it into the given LemonWriter. If the \c _forceIdMap + /// parameter is true then the writer will write own id map when + /// the user does not give "id" named map. + NodeSetWriter(LemonWriter& _writer, const Graph& _graph, + const std::string& _id = std::string(), + bool _forceIdMap = true) + : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), + graph(_graph), id(_id) {} + + /// \brief Destructor. + /// + /// Destructor for NodeSetWriter. + virtual ~NodeSetWriter() { + typename MapWriters::iterator it; + for (it = writers.begin(); it != writers.end(); ++it) { + delete it->second; + } + } + + private: + NodeSetWriter(const NodeSetWriter&); + void operator=(const NodeSetWriter&); + + public: + + /// \brief Add a new node map writer command for the writer. + /// + /// Add a new node map writer command for the writer. + template + NodeSetWriter& writeNodeMap(std::string name, const Map& map) { + return writeNodeMap, Map>(name, map); + } + + /// \brief Add a new node map writer command for the writer. + /// + /// Add a new node map writer command for the writer. + template + NodeSetWriter& writeNodeMap(std::string name, const Map& map, + const Writer& writer = Writer()) { + writers.push_back( + make_pair(name, new MapWriter(map, writer))); + return *this; + } + + protected: + + /// \brief The header of the section. + /// + /// It gives back the header of the section. + virtual std::string header() { + return "@nodeset " + id; + } + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + virtual void write(std::ostream& os) { + for (int i = 0; i < (int)writers.size(); ++i) { + if (writers[i].first == "id") { + idMap = writers[i].second; + forceIdMap = false; + break; + } + } + if (forceIdMap) { + os << "id\t"; + } + for (int i = 0; i < (int)writers.size(); ++i) { + os << writers[i].first << '\t'; + } + os << std::endl; + for (typename Graph::NodeIt it(graph); it != INVALID; ++it) { + if (forceIdMap) { + os << graph.id(it) << '\t'; + } + for (int i = 0; i < (int)writers.size(); ++i) { + writers[i].second->write(os, it); + os << '\t'; + } + os << std::endl; + } + } + + public: + + /// \brief Returns true if the nodeset can write the ids of the nodes. + /// + /// Returns true if the nodeset can write the ids of the nodes. + /// It is possible only if an "id" named map was written or the + /// \c _forceIdMap constructor parameter was true. + bool isIdWriter() const { + return idMap != 0 || forceIdMap; + } + + /// \brief Write the id of the given node. + /// + /// It writes the id of the given node. If there was written an "id" + /// named map then it will write the map value belongs to the node. + /// Otherwise if the \c forceId parameter was true it will write + /// its id in the graph. + void writeId(std::ostream& os, const Node& item) const { + if (forceIdMap) { + os << graph.id(item); + } else { + idMap->write(os, item); + } + } + + private: + + typedef std::vector*> > MapWriters; + MapWriters writers; + + WriterBase* idMap; + bool forceIdMap; + + typename SmartConstReference::Type graph; + std::string id; + + }; + + /// \ingroup io_group + /// \brief SectionWriter for writing a graph's edgesets. + /// + /// The lemon format can store multiple graph edgesets with several maps. + /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the + /// \c edgeset_id may be empty. + /// + /// The first line of the section contains the names of the maps separated + /// with white spaces. Each next lines describes a edge in the edgeset. The + /// line contains the source and the target nodes' id and the mapped + /// values for each map. + /// + /// If the edgeset contains an \c "id" named map then it will be regarded + /// as id map. This map should contain only unique values and when the + /// \c writeId() member will be called with an edge it will write it's id. + /// Otherwise if the \c _forceIdMap constructor parameter is true then + /// the id map will be the id in the graph. + /// + /// The edgeset writer needs a node id writer to identify which nodes + /// have to be connected. If a NodeSetWriter can write the nodes' id, + /// it will be able to use with this class. + /// + /// \relates LemonWriter + template + class EdgeSetWriter : public CommonSectionWriterBase { + typedef CommonSectionWriterBase Parent; + public: + + typedef _Graph Graph; + typedef _Traits Traits; + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + + /// \brief Constructor. + /// + /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and + /// attach it into the given LemonWriter. It will write node ids by + /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true + /// then the writer will write own id map if the user does not give + /// "id" named map. + template + EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, + const NodeIdWriter& _nodeIdWriter, + const std::string& _id = std::string(), + bool _forceIdMap = true) + : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), + graph(_graph), id(_id), + nodeIdWriter(new IdWriter(_nodeIdWriter)) {} + + /// \brief Destructor. + /// + /// Destructor for EdgeSetWriter. + virtual ~EdgeSetWriter() { + typename MapWriters::iterator it; + for (it = writers.begin(); it != writers.end(); ++it) { + delete it->second; + } + } + + private: + EdgeSetWriter(const EdgeSetWriter&); + void operator=(const EdgeSetWriter&); + + public: + + /// \brief Add a new edge map writer command for the writer. + /// + /// Add a new edge map writer command for the writer. + template + EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) { + return writeEdgeMap, Map>(name, map); + } + + /// \brief Add a new edge map writer command for the writer. + /// + /// Add a new edge map writer command for the writer. + template + EdgeSetWriter& writeEdgeMap(std::string name, const Map& map, + const Writer& writer = Writer()) { + writers.push_back( + make_pair(name, new MapWriter(map, writer))); + return *this; + } + + protected: + + /// \brief The header of the section. + /// + /// It gives back the header of the section. + virtual std::string header() { + return "@edgeset " + id; + } + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + virtual void write(std::ostream& os) { + for (int i = 0; i < (int)writers.size(); ++i) { + if (writers[i].first == "id") { + idMap = writers[i].second; + forceIdMap = false; + break; + } + } + os << "\t\t"; + if (forceIdMap) { + os << "id\t"; + } + for (int i = 0; i < (int)writers.size(); ++i) { + os << writers[i].first << '\t'; + } + os << std::endl; + for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) { + nodeIdWriter->write(os, graph.source(it)); + os << '\t'; + nodeIdWriter->write(os, graph.target(it)); + os << '\t'; + if (forceIdMap) { + os << graph.id(it) << '\t'; + } + for (int i = 0; i < (int)writers.size(); ++i) { + writers[i].second->write(os, it); + os << '\t'; + } + os << std::endl; + } + } + + public: + + /// \brief Returns true if the edgeset can write the ids of the edges. + /// + /// Returns true if the edgeset can write the ids of the edges. + /// It is possible only if an "id" named map was written or the + /// \c _forceIdMap constructor parameter was true. + bool isIdWriter() const { + return forceIdMap || idMap != 0; + } + + /// \brief Write the id of the given edge. + /// + /// It writes the id of the given edge. If there was written an "id" + /// named map then it will write the map value belongs to the edge. + /// Otherwise if the \c forceId parameter was true it will write + /// its id in the graph. + void writeId(std::ostream& os, const Edge& item) const { + if (forceIdMap) { + os << graph.id(item); + } else { + idMap->write(os, item); + } + } + + private: + + typedef std::vector*> > MapWriters; + MapWriters writers; + + WriterBase* idMap; + bool forceIdMap; + + typename SmartConstReference::Type graph; + std::string id; + + std::auto_ptr > nodeIdWriter; + }; + + /// \ingroup io_group + /// \brief SectionWriter for writing a undirected edgeset. + /// + /// The lemon format can store multiple undirected edgesets with several + /// maps. The undirected edgeset section's header line is \c \@undiredgeset + /// \c undiredgeset_id, but the \c undiredgeset_id may be empty. + /// + /// The first line of the section contains the names of the maps separated + /// with white spaces. Each next lines describes an undirected edge in the + /// edgeset. The line contains the two connected nodes' id and the mapped + /// values for each undirected map. + /// + /// The section can handle the directed as a syntactical sugar. Two + /// undirected edge map describes one directed edge map. This two maps + /// are the forward map and the backward map and the names of this map + /// is near the same just with a prefix \c '+' or \c '-' character + /// difference. + /// + /// If the edgeset contains an \c "id" named map then it will be regarded + /// as id map. This map should contain only unique values and when the + /// \c writeId() member will be called with an undirected edge it will + /// write it's id. Otherwise if the \c _forceIdMap constructor parameter + /// is true then the id map will be the id in the graph. + /// + /// The undirected edgeset writer needs a node id writer to identify + /// which nodes have to be connected. If a NodeSetWriter can write the + /// nodes' id, it will be able to use with this class. + /// + /// \relates LemonWriter + template + class UndirEdgeSetWriter : public CommonSectionWriterBase { + typedef CommonSectionWriterBase Parent; + public: + + typedef _Graph Graph; + typedef _Traits Traits; + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + typedef typename Graph::UndirEdge UndirEdge; + + /// \brief Constructor. + /// + /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter + /// and attach it into the given LemonWriter. It will write node ids by + /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true + /// then the writer will write own id map if the user does not give + /// "id" named map. + template + UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, + const NodeIdWriter& _nodeIdWriter, + const std::string& _id = std::string(), + bool _forceIdMap = true) + : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), + graph(_graph), id(_id), + nodeIdWriter(new IdWriter(_nodeIdWriter)) {} + + /// \brief Destructor. + /// + /// Destructor for UndirEdgeSetWriter. + virtual ~UndirEdgeSetWriter() { + typename MapWriters::iterator it; + for (it = writers.begin(); it != writers.end(); ++it) { + delete it->second; + } + } + + private: + UndirEdgeSetWriter(const UndirEdgeSetWriter&); + void operator=(const UndirEdgeSetWriter&); + + public: + + /// \brief Add a new undirected edge map writer command for the writer. + /// + /// Add a new undirected map writer command for the writer. + template + UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) { + return writeUndirEdgeMap, Map>(name, map); + } + + /// \brief Add a new undirected map writer command for the writer. + /// + /// Add a new undirected map writer command for the writer. + template + UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map, + const Writer& writer = Writer()) { + writers.push_back( + make_pair(name, new MapWriter(map, writer))); + return *this; + } + + /// \brief Add a new directed edge map writer command for the writer. + /// + /// Add a new directed map writer command for the writer. + template + UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) { + writeUndirEdgeMap("+" + name, composeMap(forwardMap(graph), map)); + writeUndirEdgeMap("-" + name, composeMap(backwardMap(graph), map)); + return *this; + } + + /// \brief Add a new directed map writer command for the writer. + /// + /// Add a new directed map writer command for the writer. + template + UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map, + const Writer& writer = Writer()) { + writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer); + writeUndirEdge("-" + name, composeMap(forwardMap(graph), map), writer); + return *this; + } + + protected: + + /// \brief The header of the section. + /// + /// It gives back the header of the section. + virtual std::string header() { + return "@undiredgeset " + id; + } + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + virtual void write(std::ostream& os) { + for (int i = 0; i < (int)writers.size(); ++i) { + if (writers[i].first == "id") { + idMap = writers[i].second; + forceIdMap = false; + break; + } + } + os << "\t\t"; + if (forceIdMap) { + os << "id\t"; + } + for (int i = 0; i < (int)writers.size(); ++i) { + os << writers[i].first << '\t'; + } + os << std::endl; + for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) { + nodeIdWriter->write(os, graph.source(it)); + os << '\t'; + nodeIdWriter->write(os, graph.target(it)); + os << '\t'; + if (forceIdMap) { + os << graph.id(it) << '\t'; + } + for (int i = 0; i < (int)writers.size(); ++i) { + writers[i].second->write(os, it); + os << '\t'; + } + os << std::endl; + } + } + + public: + + /// \brief Returns true if the undirected edgeset can write the ids of + /// the edges. + /// + /// Returns true if the undirected edgeset can write the ids of the + /// undirected edges. It is possible only if an "id" named map was + /// written or the \c _forceIdMap constructor parameter was true. + bool isIdWriter() const { + return forceIdMap || idMap != 0; + } + + /// \brief Write the id of the given undirected edge. + /// + /// It writes the id of the given undirected edge. If there was written + /// an "id" named map then it will write the map value belongs to the + /// undirected edge. Otherwise if the \c forceId parameter was true it + /// will write its id in the graph. + void writeId(std::ostream& os, const UndirEdge& item) const { + if (forceIdMap) { + os << graph.id(item); + } else { + idMap->write(os, item); + } + } + + /// \brief Write the id of the given edge. + /// + /// It writes the id of the given edge. If there was written + /// an "id" named map then it will write the map value belongs to the + /// edge. Otherwise if the \c forceId parameter was true it + /// will write its id in the graph. If the edge is forward map + /// then its prefix character is \c '+' elsewhere \c '-'. + void writeId(std::ostream& os, const Edge& item) const { + if (graph.forward(item)) { + os << "+ "; + } else { + os << "- "; + } + if (forceIdMap) { + os << graph.id(item); + } else { + idMap->write(os, item); + } + } + + private: + + typedef std::vector*> > MapWriters; + MapWriters writers; + + WriterBase* idMap; + bool forceIdMap; + + typename SmartConstReference::Type graph; + std::string id; + + std::auto_ptr > nodeIdWriter; + }; + + /// \ingroup io_group + /// \brief SectionWriter for writing labeled nodes. + /// + /// The nodes section's header line is \c \@nodes \c nodes_id, but the + /// \c nodes_id may be empty. + /// + /// Each line in the section contains the label of the node and + /// then the node id. + /// + /// \relates LemonWriter + template + class NodeWriter : public CommonSectionWriterBase { + typedef CommonSectionWriterBase Parent; + typedef _Graph Graph; + typedef typename Graph::Node Node; + public: + + /// \brief Constructor. + /// + /// Constructor for NodeWriter. It creates the NodeWriter and + /// attach it into the given LemonWriter. The given \c _IdWriter + /// will write the nodes' id what can be a nodeset writer. + template + NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, + const std::string& _id = std::string()) + : Parent(_writer), id(_id), + idWriter(new IdWriter(_idWriter)) {} + + /// \brief Destructor. + /// + /// Destructor for NodeWriter. + virtual ~NodeWriter() {} + + private: + NodeWriter(const NodeWriter&); + void operator=(const NodeWriter&); + + public: + + /// \brief Add a node writer command for the NodeWriter. + /// + /// Add a node writer command for the NodeWriter. + void writeNode(const std::string& name, const Node& item) { + writers.push_back(make_pair(name, &item)); + } + + protected: + + /// \brief Header checking function. + /// + /// It gives back true when the header line start with \c \@nodes, + /// and the header line's id and the writer's id are the same. + virtual std::string header() { + return "@nodes " + id; + } + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + virtual void write(std::ostream& os) { + for (int i = 0; i < (int)writers.size(); ++i) { + os << writers[i].first << ' '; + idWriter->write(os, *(writers[i].second)); + os << std::endl; + } + } + + private: + + std::string id; + + typedef std::vector > NodeWriters; + NodeWriters writers; + std::auto_ptr > idWriter; + }; + + /// \ingroup io_group + /// \brief SectionWriter for writing labeled edges. + /// + /// The edges section's header line is \c \@edges \c edges_id, but the + /// \c edges_id may be empty. + /// + /// Each line in the section contains the label of the edge and + /// then the edge id. + /// + /// \relates LemonWriter + template + class EdgeWriter : public CommonSectionWriterBase { + typedef CommonSectionWriterBase Parent; + typedef _Graph Graph; + typedef typename Graph::Edge Edge; + public: + + /// \brief Constructor. + /// + /// Constructor for EdgeWriter. It creates the EdgeWriter and + /// attach it into the given LemonWriter. The given \c _IdWriter + /// will write the edges' id what can be a edgeset writer. + template + EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, + const std::string& _id = std::string()) + : Parent(_writer), id(_id), + idWriter(new IdWriter(_idWriter)) {} + + /// \brief Destructor. + /// + /// Destructor for EdgeWriter. + virtual ~EdgeWriter() {} + private: + EdgeWriter(const EdgeWriter&); + void operator=(const EdgeWriter&); + + public: + + /// \brief Add an edge writer command for the EdgeWriter. + /// + /// Add an edge writer command for the EdgeWriter. + void writeEdge(const std::string& name, const Edge& item) { + writers.push_back(make_pair(name, &item)); + } + + protected: + + /// \brief Header checking function. + /// + /// It gives back true when the header line start with \c \@edges, + /// and the header line's id and the writer's id are the same. + virtual std::string header() { + return "@edges " + id; + } + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + virtual void write(std::ostream& os) { + for (int i = 0; i < (int)writers.size(); ++i) { + os << writers[i].first << ' '; + idWriter->write(os, *(writers[i].second)); + os << std::endl; + } + } + + private: + + std::string id; + + typedef std::vector > EdgeWriters; + EdgeWriters writers; + + std::auto_ptr > idWriter; + }; + + /// \ingroup io_group + /// \brief SectionWriter for writing labeled undirected edges. + /// + /// The undirected edges section's header line is \c \@undiredges + /// \c undiredges_id, but the \c undiredges_id may be empty. + /// + /// Each line in the section contains the label of the undirected edge and + /// then the undirected edge id. + /// + /// \relates LemonWriter + template + class UndirEdgeWriter : public CommonSectionWriterBase { + typedef CommonSectionWriterBase Parent; + typedef _Graph Graph; + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + typedef typename Graph::UndirEdge UndirEdge; + public: + + /// \brief Constructor. + /// + /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and + /// attach it into the given LemonWriter. The given \c _IdWriter + /// will write the undirected edges' id what can be an undirected + /// edgeset writer. + template + UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, + const std::string& _id = std::string()) + : Parent(_writer), id(_id), + undirEdgeIdWriter(new IdWriter(_idWriter)), + edgeIdWriter(new IdWriter(_idWriter)) {} + + /// \brief Destructor. + /// + /// Destructor for UndirEdgeWriter. + virtual ~UndirEdgeWriter() {} + private: + UndirEdgeWriter(const UndirEdgeWriter&); + void operator=(const UndirEdgeWriter&); + + public: + + /// \brief Add an edge writer command for the UndirEdgeWriter. + /// + /// Add an edge writer command for the UndirEdgeWriter. + void writeEdge(const std::string& name, const Edge& item) { + edgeWriters.push_back(make_pair(name, &item)); + } + + /// \brief Add an undirected edge writer command for the UndirEdgeWriter. + /// + /// Add an undirected edge writer command for the UndirEdgeWriter. + void writeUndirEdge(const std::string& name, const UndirEdge& item) { + undirEdgeWriters.push_back(make_pair(name, &item)); + } + + protected: + + /// \brief Header checking function. + /// + /// It gives back true when the header line start with \c \@undiredges, + /// and the header line's id and the writer's id are the same. + virtual std::string header() { + return "@undiredges " + id; + } + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + virtual void write(std::ostream& os) { + for (int i = 0; i < (int)undirEdgeWriters.size(); ++i) { + os << undirEdgeWriters[i].first << ' '; + undirEdgeIdWriter->write(os, *(undirEdgeWriters[i].second)); + os << std::endl; + } + for (int i = 0; i < (int)edgeWriters.size(); ++i) { + os << edgeWriters[i].first << ' '; + edgeIdWriter->write(os, *(edgeWriters[i].second)); + os << std::endl; + } + } + + private: + + std::string id; + + typedef std::vector > UndirEdgeWriters; + UndirEdgeWriters undirEdgeWriters; + std::auto_ptr > undirEdgeIdWriter; + + typedef std::vector > EdgeWriters; + EdgeWriters edgeWriters; + std::auto_ptr > edgeIdWriter; + + }; + + /// \ingroup io_group + /// \brief SectionWriter for attributes. + /// + /// The lemon format can store multiple attribute set. Each set has + /// the header line \c \@attributes \c attributeset_id, but the + /// attributeset_id may be empty. + /// + /// The attributeset section contains several lines. Each of them starts + /// with the name of attribute and then the value. + /// + /// \relates LemonWriter + template + class AttributeWriter : public CommonSectionWriterBase { + typedef CommonSectionWriterBase Parent; + typedef _Traits Traits; + public: + /// \brief Constructor. + /// + /// Constructor for AttributeWriter. It creates the AttributeWriter and + /// attach it into the given LemonWriter. + AttributeWriter(LemonWriter& _writer, + const std::string& _id = std::string()) + : Parent(_writer), id(_id) {} + + /// \brief Destructor. + /// + /// Destructor for AttributeWriter. + virtual ~AttributeWriter() { + typename Writers::iterator it; + for (it = writers.begin(); it != writers.end(); ++it) { + delete it->second; + } + } + + private: + AttributeWriter(const AttributeWriter&); + void operator=(AttributeWriter&); + + public: + /// \brief Add an attribute writer command for the writer. + /// + /// Add an attribute writer command for the writer. + template + AttributeWriter& writeAttribute(const std::string& id, + const Value& value) { + return + writeAttribute >(id, value); + } + + /// \brief Add an attribute writer command for the writer. + /// + /// Add an attribute writer command for the writer. + template + AttributeWriter& writeAttribute(const std::string& name, + const Value& value, + const Writer& writer = Writer()) { + writers.push_back(make_pair(name, new ValueWriter + (value, writer))); + return *this; + } + + protected: + + /// \brief The header of section. + /// + /// It gives back the header of the section. + std::string header() { + return "@attributes " + id; + } + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + void write(std::ostream& os) { + typename Writers::iterator it; + for (it = writers.begin(); it != writers.end(); ++it) { + os << it->first << ' '; + it->second->write(os); + os << std::endl; + } + } + + private: + std::string id; + + typedef std::vector > Writers; + Writers writers; + }; + + +} +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/list_graph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/list_graph.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,565 @@ +/* -*- C++ -*- + * lemon/list_graph.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_LIST_GRAPH_H +#define LEMON_LIST_GRAPH_H + +///\ingroup graphs +///\file +///\brief ListGraph, SymListGraph classes. + +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace lemon { + + class ListGraphBase { + + protected: + struct NodeT { + int first_in,first_out; + int prev, next; + }; + + struct EdgeT { + int target, source; + int prev_in, prev_out; + int next_in, next_out; + }; + + std::vector nodes; + + int first_node; + + int first_free_node; + + std::vector edges; + + int first_free_edge; + + public: + + typedef ListGraphBase Graph; + + class Node { + friend class ListGraphBase; + protected: + + int id; + Node(int pid) { id = pid;} + + public: + Node() {} + Node (Invalid) { id = -1; } + bool operator==(const Node& node) const {return id == node.id;} + bool operator!=(const Node& node) const {return id != node.id;} + bool operator<(const Node& node) const {return id < node.id;} + }; + + class Edge { + friend class ListGraphBase; + protected: + + int id; + Edge(int pid) { id = pid;} + + public: + Edge() {} + Edge (Invalid) { id = -1; } + bool operator==(const Edge& edge) const {return id == edge.id;} + bool operator!=(const Edge& edge) const {return id != edge.id;} + bool operator<(const Edge& edge) const {return id < edge.id;} + }; + + + + ListGraphBase() + : nodes(), first_node(-1), + first_free_node(-1), edges(), first_free_edge(-1) {} + + + /// Maximum node ID. + + /// Maximum node ID. + ///\sa id(Node) + int maxId(Node = INVALID) const { return nodes.size()-1; } + + /// Maximum edge ID. + + /// Maximum edge ID. + ///\sa id(Edge) + int maxId(Edge = INVALID) const { return edges.size()-1; } + + Node source(Edge e) const { return edges[e.id].source; } + Node target(Edge e) const { return edges[e.id].target; } + + + void first(Node& node) const { + node.id = first_node; + } + + void next(Node& node) const { + node.id = nodes[node.id].next; + } + + + void first(Edge& e) const { + int n; + for(n = first_node; + n!=-1 && nodes[n].first_in == -1; + n = nodes[n].next); + e.id = (n == -1) ? -1 : nodes[n].first_in; + } + + void next(Edge& edge) const { + if (edges[edge.id].next_in != -1) { + edge.id = edges[edge.id].next_in; + } else { + int n; + for(n = nodes[edges[edge.id].target].next; + n!=-1 && nodes[n].first_in == -1; + n = nodes[n].next); + edge.id = (n == -1) ? -1 : nodes[n].first_in; + } + } + + void firstOut(Edge &e, const Node& v) const { + e.id = nodes[v.id].first_out; + } + void nextOut(Edge &e) const { + e.id=edges[e.id].next_out; + } + + void firstIn(Edge &e, const Node& v) const { + e.id = nodes[v.id].first_in; + } + void nextIn(Edge &e) const { + e.id=edges[e.id].next_in; + } + + + static int id(Node v) { return v.id; } + static int id(Edge e) { return e.id; } + + static Node fromId(int id, Node) { return Node(id);} + static Edge fromId(int id, Edge) { return Edge(id);} + + /// Adds a new node to the graph. + + /// \warning It adds the new node to the front of the list. + /// (i.e. the lastly added node becomes the first.) + Node addNode() { + int n; + + if(first_free_node==-1) { + n = nodes.size(); + nodes.push_back(NodeT()); + } else { + n = first_free_node; + first_free_node = nodes[n].next; + } + + nodes[n].next = first_node; + if(first_node != -1) nodes[first_node].prev = n; + first_node = n; + nodes[n].prev = -1; + + nodes[n].first_in = nodes[n].first_out = -1; + + return Node(n); + } + + Edge addEdge(Node u, Node v) { + int n; + + if (first_free_edge == -1) { + n = edges.size(); + edges.push_back(EdgeT()); + } else { + n = first_free_edge; + first_free_edge = edges[n].next_in; + } + + edges[n].source = u.id; + edges[n].target = v.id; + + edges[n].next_out = nodes[u.id].first_out; + if(nodes[u.id].first_out != -1) { + edges[nodes[u.id].first_out].prev_out = n; + } + + edges[n].next_in = nodes[v.id].first_in; + if(nodes[v.id].first_in != -1) { + edges[nodes[v.id].first_in].prev_in = n; + } + + edges[n].prev_in = edges[n].prev_out = -1; + + nodes[u.id].first_out = nodes[v.id].first_in = n; + + return Edge(n); + } + + void erase(const Node& node) { + int n = node.id; + + if(nodes[n].next != -1) { + nodes[nodes[n].next].prev = nodes[n].prev; + } + + if(nodes[n].prev != -1) { + nodes[nodes[n].prev].next = nodes[n].next; + } else { + first_node = nodes[n].next; + } + + nodes[n].next = first_free_node; + first_free_node = n; + + } + + void erase(const Edge& edge) { + int n = edge.id; + + if(edges[n].next_in!=-1) { + edges[edges[n].next_in].prev_in = edges[n].prev_in; + } + + if(edges[n].prev_in!=-1) { + edges[edges[n].prev_in].next_in = edges[n].next_in; + } else { + nodes[edges[n].target].first_in = edges[n].next_in; + } + + + if(edges[n].next_out!=-1) { + edges[edges[n].next_out].prev_out = edges[n].prev_out; + } + + if(edges[n].prev_out!=-1) { + edges[edges[n].prev_out].next_out = edges[n].next_out; + } else { + nodes[edges[n].source].first_out = edges[n].next_out; + } + + edges[n].next_in = first_free_edge; + first_free_edge = n; + + } + + void clear() { + edges.clear(); + nodes.clear(); + first_node = first_free_node = first_free_edge = -1; + } + + protected: + void _moveTarget(Edge e, Node n) + { + if(edges[e.id].next_in != -1) + edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in; + if(edges[e.id].prev_in != -1) + edges[edges[e.id].prev_in].next_in = edges[e.id].next_in; + else nodes[edges[e.id].target].first_in = edges[e.id].next_in; + edges[e.id].target = n.id; + edges[e.id].prev_in = -1; + edges[e.id].next_in = nodes[n.id].first_in; + nodes[n.id].first_in = e.id; + } + void _moveSource(Edge e, Node n) + { + if(edges[e.id].next_out != -1) + edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out; + if(edges[e.id].prev_out != -1) + edges[edges[e.id].prev_out].next_out = edges[e.id].next_out; + else nodes[edges[e.id].source].first_out = edges[e.id].next_out; + edges[e.id].source = n.id; + edges[e.id].prev_out = -1; + edges[e.id].next_out = nodes[n.id].first_out; + nodes[n.id].first_out = e.id; + } + + }; + + typedef AlterableGraphExtender AlterableListGraphBase; + typedef IterableGraphExtender IterableListGraphBase; + typedef DefaultMappableGraphExtender MappableListGraphBase; + typedef ExtendableGraphExtender ExtendableListGraphBase; + typedef ClearableGraphExtender ClearableListGraphBase; + typedef ErasableGraphExtender ErasableListGraphBase; + +/// \addtogroup graphs +/// @{ + + ///A list graph class. + + ///This is a simple and fast erasable graph implementation. + /// + ///It addition that it conforms to the + ///\ref concept::ErasableGraph "ErasableGraph" concept, + ///it also provides several additional useful extra functionalities. + ///\sa concept::ErasableGraph. + + class ListGraph : public ErasableListGraphBase + { + public: + /// Moves the target of \c e to \c n + + /// Moves the target of \c e to \c n + /// + ///\note The Edge's and OutEdge's + ///referencing the moved edge remain + ///valid. However InEdge's are invalidated. + void moveTarget(Edge e, Node n) { _moveTarget(e,n); } + /// Moves the source of \c e to \c n + + /// Moves the source of \c e to \c n + /// + ///\note The Edge's and InEdge's + ///referencing the moved edge remain + ///valid. However OutEdge's are invalidated. + void moveSource(Edge e, Node n) { _moveSource(e,n); } + + /// Invert the direction of an edge. + + ///\note The Edge's + ///referencing the moved edge remain + ///valid. However OutEdge's and InEdge's are invalidated. + void reverseEdge(Edge e) { + Node t=target(e); + _moveTarget(e,source(e)); + _moveSource(e,t); + } + + ///Using this it possible to avoid the superfluous memory allocation. + + ///Using this it possible to avoid the superfluous memory allocation. + ///\todo more docs... + void reserveEdge(int n) { edges.reserve(n); }; + + ///Contract two nodes. + + ///This function contracts two nodes. + /// + ///Node \p b will be removed but instead of deleting + ///its neighboring edges, they will be joined to \p a. + ///The last parameter \p r controls whether to remove loops. \c true + ///means that loops will be removed. + /// + ///\note The Edges + ///referencing a moved edge remain + ///valid. However InEdge's and OutEdge's + ///may be invalidated. + void contract(Node a,Node b,bool r=true) + { + for(OutEdgeIt e(*this,b);e!=INVALID;) { + OutEdgeIt f=e; + ++f; + if(r && target(e)==a) erase(e); + else moveSource(e,a); + e=f; + } + for(InEdgeIt e(*this,b);e!=INVALID;) { + InEdgeIt f=e; + ++f; + if(r && source(e)==a) erase(e); + else moveTarget(e,a); + e=f; + } + erase(b); + } + + ///Split a node. + + ///This function splits a node. First a new node is added to the graph, + ///then the source of each outgoing edge of \c n is moved to this new node. + ///If \c connect is \c true (this is the default value), then a new edge + ///from \c n to the newly created node is also added. + ///\return The newly created node. + /// + ///\note The Edges + ///referencing a moved edge remain + ///valid. However InEdge's and OutEdge's + ///may be invalidated. + ///\warning This functionality cannot be used together with the SnapShot + ///feature. + ///\todo It could be implemented in a bit faster way. + Node split(Node n, bool connect = true) + { + Node b = addNode(); + for(OutEdgeIt e(*this,n);e!=INVALID;) { + OutEdgeIt f=e; + ++f; + moveSource(e,b); + e=f; + } + if(connect) addEdge(n,b); + return b; + } + + ///Class to make a snapshot of the graph and to restrore to it later. + + ///Class to make a snapshot of the graph and to restrore to it later. + /// + ///The newly added nodes and edges can be removed using the + ///restore() function. + /// + ///\warning Edge and node deletions cannot be restored. + ///\warning SnapShots cannot be nested. + ///\todo \c SnapShot or \c Snapshot? + class SnapShot : protected AlterationNotifier::ObserverBase, + protected AlterationNotifier::ObserverBase + { + protected: + + ListGraph *g; + std::list added_nodes; + std::list added_edges; + + bool active; + virtual void add(const Node& n) { + added_nodes.push_back(n); + }; + ///\bug Exception... + /// + virtual void erase(const Node&) + { + exit(1); + } + virtual void add(const Edge& n) { + added_edges.push_back(n); + }; + ///\bug Exception... + /// + virtual void erase(const Edge&) + { + exit(1); + } + + void regist(ListGraph &_g) { + g=&_g; + AlterationNotifier::ObserverBase:: + attach(g->getNotifier(Node())); + AlterationNotifier::ObserverBase:: + attach(g->getNotifier(Edge())); + } + + void deregist() { + AlterationNotifier::ObserverBase:: + detach(); + AlterationNotifier::ObserverBase:: + detach(); + g=0; + } + + public: + ///Default constructur. + + ///Default constructur. + ///To actually make a snapshot you must call save(). + /// + SnapShot() : g(0) {} + ///Constructor that immediately makes a snapshot. + + ///This constructor immediately makes a snapshot of the graph. + ///\param _g The graph we make a snapshot of. + SnapShot(ListGraph &_g) { + regist(_g); + } + ///\bug Is it necessary? + /// + ~SnapShot() + { + if(g) deregist(); + } + + ///Make a snapshot. + + ///Make a snapshot of the graph. + /// + ///This function can be called more than once. In case of a repeated + ///call, the previous snapshot gets lost. + ///\param _g The graph we make the snapshot of. + void save(ListGraph &_g) + { + if(g!=&_g) { + if(g) deregist(); + regist(_g); + } + added_nodes.clear(); + added_edges.clear(); + } + + ///Undo the changes until the last snapshot. + + ///Undo the changes until last snapshot created by save(). + /// + ///\todo This function might be called undo(). + void restore() { + deregist(); + while(!added_edges.empty()) { + g->erase(added_edges.front()); + added_edges.pop_front(); + } + while(!added_nodes.empty()) { + g->erase(added_nodes.front()); + added_nodes.pop_front(); + } + } + }; + + }; + + + /**************** Undirected List Graph ****************/ + + typedef ErasableUndirGraphExtender< + ClearableUndirGraphExtender< + ExtendableUndirGraphExtender< + MappableUndirGraphExtender< + IterableUndirGraphExtender< + AlterableUndirGraphExtender< + UndirGraphExtender > > > > > > ErasableUndirListGraphBase; + + ///An undirected list graph class. + + ///This is a simple and fast erasable undirected graph implementation. + /// + ///It conforms to the + ///\ref concept::UndirGraph "UndirGraph" concept. + /// + ///\sa concept::UndirGraph. + /// + ///\todo SnapShot, reverseEdge(), moveTarget(), moveSource(), contract() + ///haven't been implemented yet. + /// + class UndirListGraph : public ErasableUndirListGraphBase { + }; + + + /// @} +} //namespace lemon + + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lp_base.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lp_base.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,33 @@ +/* -*- C++ -*- + * lemon/lp_base.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\file +///\brief The implementation of the LP solver interface. + +#include +namespace lemon { + + const LpSolverBase::Value + LpSolverBase::INF = std::numeric_limits::infinity(); + const LpSolverBase::Value + LpSolverBase::NaN = std::numeric_limits::quiet_NaN(); + +// const LpSolverBase::Constr::Value +// LpSolverBase::Constr::INF = std::numeric_limits::infinity(); +// const LpSolverBase::Constr::Value +// LpSolverBase::Constr::NaN = std::numeric_limits::quiet_NaN(); + +} //namespace lemon diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lp_base.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lp_base.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,907 @@ +/* -*- C++ -*- + * lemon/lp_base.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_LP_BASE_H +#define LEMON_LP_BASE_H + +#include +#include +#include +#include + +#include +#include +#include + +//#include"lin_expr.h" + +///\file +///\brief The interface of the LP solver interface. +///\ingroup gen_opt_group +namespace lemon { + + ///Internal data structure to convert floating id's to fix one's + + ///\todo This might be implemented to be also usable in other places. + class _FixId + { + std::vector index; + std::vector cross; + int first_free; + public: + _FixId() : first_free(-1) {}; + ///Convert a floating id to a fix one + + ///\param n is a floating id + ///\return the corresponding fix id + int fixId(int n) {return cross[n];} + ///Convert a fix id to a floating one + + ///\param n is a fix id + ///\return the corresponding floating id + int floatingId(int n) { return index[n];} + ///Add a new floating id. + + ///\param n is a floating id + ///\return the fix id of the new value + ///\todo Multiple additions should also be handled. + int insert(int n) + { + if(n>=int(cross.size())) { + cross.resize(n+1); + if(first_free==-1) { + cross[n]=index.size(); + index.push_back(n); + } + else { + cross[n]=first_free; + int next=index[first_free]; + index[first_free]=n; + first_free=next; + } + return cross[n]; + } + ///\todo Create an own exception type. + else throw LogicError(); //floatingId-s must form a continuous range; + } + ///Remove a fix id. + + ///\param n is a fix id + /// + void erase(int n) + { + int fl=index[n]; + index[n]=first_free; + first_free=n; + for(int i=fl+1;i, so for expamle + ///if \c e is an Expr and \c v and \c w are of type \ref Col, then you can + ///read and modify the coefficients like + ///these. + ///\code + ///e[v]=5; + ///e[v]+=12; + ///e.erase(v); + ///\endcode + ///or you can also iterate through its elements. + ///\code + ///double s=0; + ///for(LpSolverBase::Expr::iterator i=e.begin();i!=e.end();++i) + /// s+=i->second; + ///\endcode + ///(This code computes the sum of all coefficients). + ///- Numbers (double's) + ///and variables (\ref Col "Col"s) directly convert to an + ///\ref Expr and the usual linear operations are defined so + ///\code + ///v+w + ///2*v-3.12*(v-w/2)+2 + ///v*2.1+(3*v+(v*12+w+6)*3)/2 + ///\endcode + ///are valid \ref Expr "Expr"essions. + ///The usual assignment operations are also defined. + ///\code + ///e=v+w; + ///e+=2*v-3.12*(v-w/2)+2; + ///e*=3.4; + ///e/=5; + ///\endcode + ///- The constant member can be set and read by \ref constComp() + ///\code + ///e.constComp()=12; + ///double c=e.constComp(); + ///\endcode + /// + ///\note \ref clear() not only sets all coefficients to 0 but also + ///clears the constant components. + /// + ///\sa Constr + /// + class Expr : public std::map + { + public: + typedef LpSolverBase::Col Key; + typedef LpSolverBase::Value Value; + + protected: + typedef std::map Base; + + Value const_comp; + public: + typedef True IsLinExpression; + ///\e + Expr() : Base(), const_comp(0) { } + ///\e + Expr(const Key &v) : const_comp(0) { + Base::insert(std::make_pair(v, 1)); + } + ///\e + Expr(const Value &v) : const_comp(v) {} + ///\e + void set(const Key &v,const Value &c) { + Base::insert(std::make_pair(v, c)); + } + ///\e + Value &constComp() { return const_comp; } + ///\e + const Value &constComp() const { return const_comp; } + + ///Removes the components with zero coefficient. + void simplify() { + for (Base::iterator i=Base::begin(); i!=Base::end();) { + Base::iterator j=i; + ++j; + if ((*i).second==0) Base::erase(i); + j=i; + } + } + + ///Sets all coefficients and the constant component to 0. + void clear() { + Base::clear(); + const_comp=0; + } + + ///\e + Expr &operator+=(const Expr &e) { + for (Base::const_iterator j=e.begin(); j!=e.end(); ++j) + (*this)[j->first]+=j->second; + ///\todo it might be speeded up using "hints" + const_comp+=e.const_comp; + return *this; + } + ///\e + Expr &operator-=(const Expr &e) { + for (Base::const_iterator j=e.begin(); j!=e.end(); ++j) + (*this)[j->first]-=j->second; + const_comp-=e.const_comp; + return *this; + } + ///\e + Expr &operator*=(const Value &c) { + for (Base::iterator j=Base::begin(); j!=Base::end(); ++j) + j->second*=c; + const_comp*=c; + return *this; + } + ///\e + Expr &operator/=(const Value &c) { + for (Base::iterator j=Base::begin(); j!=Base::end(); ++j) + j->second/=c; + const_comp/=c; + return *this; + } + }; + + ///Linear constraint + + ///This data stucture represents a linear constraint in the LP. + ///Basically it is a linear expression with a lower or an upper bound + ///(or both). These parts of the constraint can be obtained by the member + ///functions \ref expr(), \ref lowerBound() and \ref upperBound(), + ///respectively. + ///There are two ways to construct a constraint. + ///- You can set the linear expression and the bounds directly + /// by the functions above. + ///- The operators \<=, == and \>= + /// are defined between expressions, or even between constraints whenever + /// it makes sense. Therefore if \c e and \c f are linear expressions and + /// \c s and \c t are numbers, then the followings are valid expressions + /// and thus they can be used directly e.g. in \ref addRow() whenever + /// it makes sense. + /// \code + /// e<=s + /// e<=f + /// s<=e<=t + /// e>=t + /// \endcode + ///\warning The validity of a constraint is checked only at run time, so + ///e.g. \ref addRow(x[1]\<=x[2]<=5) will compile, but will throw a + ///\ref LogicError exception. + class Constr + { + public: + typedef LpSolverBase::Expr Expr; + typedef Expr::Key Key; + typedef Expr::Value Value; + +// static const Value INF; +// static const Value NaN; + + protected: + Expr _expr; + Value _lb,_ub; + public: + ///\e + Constr() : _expr(), _lb(NaN), _ub(NaN) {} + ///\e + Constr(Value lb,const Expr &e,Value ub) : + _expr(e), _lb(lb), _ub(ub) {} + ///\e + Constr(const Expr &e,Value ub) : + _expr(e), _lb(NaN), _ub(ub) {} + ///\e + Constr(Value lb,const Expr &e) : + _expr(e), _lb(lb), _ub(NaN) {} + ///\e + Constr(const Expr &e) : + _expr(e), _lb(NaN), _ub(NaN) {} + ///\e + void clear() + { + _expr.clear(); + _lb=_ub=NaN; + } + + ///Reference to the linear expression + Expr &expr() { return _expr; } + ///Cont reference to the linear expression + const Expr &expr() const { return _expr; } + ///Reference to the lower bound. + + ///\return + ///- -\ref INF: the constraint is lower unbounded. + ///- -\ref NaN: lower bound has not been set. + ///- finite number: the lower bound + Value &lowerBound() { return _lb; } + ///The const version of \ref lowerBound() + const Value &lowerBound() const { return _lb; } + ///Reference to the upper bound. + + ///\return + ///- -\ref INF: the constraint is upper unbounded. + ///- -\ref NaN: upper bound has not been set. + ///- finite number: the upper bound + Value &upperBound() { return _ub; } + ///The const version of \ref upperBound() + const Value &upperBound() const { return _ub; } + ///Is the constraint lower bounded? + bool lowerBounded() const { + using namespace std; + return finite(_lb); + } + ///Is the constraint upper bounded? + bool upperBounded() const { + using namespace std; + return finite(_ub); + } + }; + + + protected: + _FixId rows; + _FixId cols; + + //Abstract virtual functions + virtual LpSolverBase &_newLp() = 0; + virtual LpSolverBase &_copyLp() = 0; + + virtual int _addCol() = 0; + virtual int _addRow() = 0; + virtual void _setRowCoeffs(int i, + int length, + int const * indices, + Value const * values ) = 0; + virtual void _setColCoeffs(int i, + int length, + int const * indices, + Value const * values ) = 0; + virtual void _setCoeff(int row, int col, Value value) = 0; + virtual void _setColLowerBound(int i, Value value) = 0; + virtual void _setColUpperBound(int i, Value value) = 0; +// virtual void _setRowLowerBound(int i, Value value) = 0; +// virtual void _setRowUpperBound(int i, Value value) = 0; + virtual void _setRowBounds(int i, Value lower, Value upper) = 0; + virtual void _setObjCoeff(int i, Value obj_coef) = 0; + virtual void _clearObj()=0; +// virtual void _setObj(int length, +// int const * indices, +// Value const * values ) = 0; + virtual SolveExitStatus _solve() = 0; + virtual Value _getPrimal(int i) = 0; + virtual Value _getPrimalValue() = 0; + virtual SolutionStatus _getPrimalStatus() = 0; + virtual void _setMax() = 0; + virtual void _setMin() = 0; + + //Own protected stuff + + //Constant component of the objective function + Value obj_const_comp; + + + + + public: + + ///\e + LpSolverBase() : obj_const_comp(0) {} + + ///\e + virtual ~LpSolverBase() {} + + ///Creates a new LP problem + LpSolverBase &newLp() {return _newLp();} + ///Makes a copy of the LP problem + LpSolverBase ©Lp() {return _copyLp();} + + ///\name Build up and modify of the LP + + ///@{ + + ///Add a new empty column (i.e a new variable) to the LP + Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;} + + ///\brief Adds several new columns + ///(i.e a variables) at once + /// + ///This magic function takes a container as its argument + ///and fills its elements + ///with new columns (i.e. variables) + ///\param t can be + ///- a standard STL compatible iterable container with + ///\ref Col as its \c values_type + ///like + ///\code + ///std::vector + ///std::list + ///\endcode + ///- a standard STL compatible iterable container with + ///\ref Col as its \c mapped_type + ///like + ///\code + ///std::map + ///\endcode + ///- an iterable lemon \ref concept::WriteMap "write map" like + ///\code + ///ListGraph::NodeMap + ///ListGraph::EdgeMap + ///\endcode + ///\return The number of the created column. +#ifdef DOXYGEN + template + int addColSet(T &t) { return 0;} +#else + template + typename enable_if::type + addColSet(T &t,dummy<0> = 0) { + int s=0; + for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;} + return s; + } + template + typename enable_if::type + addColSet(T &t,dummy<1> = 1) { + int s=0; + for(typename T::iterator i=t.begin();i!=t.end();++i) { + i->second=addCol(); + s++; + } + return s; + } + template + typename enable_if::type + addColSet(T &t,dummy<2> = 2) { + ///\bug return addColSet(t.valueSet()); should also work. + int s=0; + for(typename T::ValueSet::iterator i=t.valueSet().begin(); + i!=t.valueSet().end(); + ++i) + { + *i=addCol(); + s++; + } + return s; + } +#endif + + ///Add a new empty row (i.e a new constaint) to the LP + + ///This function adds a new empty row (i.e a new constaint) to the LP. + ///\return The created row + Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;} + + ///Set a row (i.e a constaint) of the LP + + ///\param r is the row to be modified + ///\param l is lower bound (-\ref INF means no bound) + ///\param e is a linear expression (see \ref Expr) + ///\param u is the upper bound (\ref INF means no bound) + ///\bug This is a temportary function. The interface will change to + ///a better one. + ///\todo Option to control whether a constraint with a single variable is + ///added or not. + void setRow(Row r, Value l,const Expr &e, Value u) { + std::vector indices; + std::vector values; + indices.push_back(0); + values.push_back(0); + for(Expr::const_iterator i=e.begin(); i!=e.end(); ++i) + if((*i).second!=0) { ///\bug EPSILON would be necessary here!!! + indices.push_back(cols.floatingId((*i).first.id)); + values.push_back((*i).second); + } + _setRowCoeffs(rows.floatingId(r.id),indices.size()-1, + &indices[0],&values[0]); +// _setRowLowerBound(rows.floatingId(r.id),l-e.constComp()); +// _setRowUpperBound(rows.floatingId(r.id),u-e.constComp()); + _setRowBounds(rows.floatingId(r.id),l-e.constComp(),u-e.constComp()); + } + + ///Set a row (i.e a constaint) of the LP + + ///\param r is the row to be modified + ///\param c is a linear expression (see \ref Constr) + void setRow(Row r, const Constr &c) { + setRow(r, + c.lowerBounded()?c.lowerBound():-INF, + c.expr(), + c.upperBounded()?c.upperBound():INF); + } + + ///Add a new row (i.e a new constaint) to the LP + + ///\param l is the lower bound (-\ref INF means no bound) + ///\param e is a linear expression (see \ref Expr) + ///\param u is the upper bound (\ref INF means no bound) + ///\return The created row. + ///\bug This is a temportary function. The interface will change to + ///a better one. + Row addRow(Value l,const Expr &e, Value u) { + Row r=addRow(); + setRow(r,l,e,u); + return r; + } + + ///Add a new row (i.e a new constaint) to the LP + + ///\param c is a linear expression (see \ref Constr) + ///\return The created row. + Row addRow(const Constr &c) { + Row r=addRow(); + setRow(r,c); + return r; + } + + /// Set the lower bound of a column (i.e a variable) + + /// The upper bound of a variable (column) has to be given by an + /// extended number of type Value, i.e. a finite number of type + /// Value or -\ref INF. + void colLowerBound(Col c, Value value) { + _setColLowerBound(cols.floatingId(c.id),value); + } + /// Set the upper bound of a column (i.e a variable) + + /// The upper bound of a variable (column) has to be given by an + /// extended number of type Value, i.e. a finite number of type + /// Value or \ref INF. + void colUpperBound(Col c, Value value) { + _setColUpperBound(cols.floatingId(c.id),value); + }; + /// Set the lower and the upper bounds of a column (i.e a variable) + + /// The lower and the upper bounds of + /// a variable (column) have to be given by an + /// extended number of type Value, i.e. a finite number of type + /// Value, -\ref INF or \ref INF. + void colBounds(Col c, Value lower, Value upper) { + _setColLowerBound(cols.floatingId(c.id),lower); + _setColUpperBound(cols.floatingId(c.id),upper); + } + +// /// Set the lower bound of a row (i.e a constraint) + +// /// The lower bound of a linear expression (row) has to be given by an +// /// extended number of type Value, i.e. a finite number of type +// /// Value or -\ref INF. +// void rowLowerBound(Row r, Value value) { +// _setRowLowerBound(rows.floatingId(r.id),value); +// }; +// /// Set the upper bound of a row (i.e a constraint) + +// /// The upper bound of a linear expression (row) has to be given by an +// /// extended number of type Value, i.e. a finite number of type +// /// Value or \ref INF. +// void rowUpperBound(Row r, Value value) { +// _setRowUpperBound(rows.floatingId(r.id),value); +// }; + + /// Set the lower and the upper bounds of a row (i.e a constraint) + + /// The lower and the upper bounds of + /// a constraint (row) have to be given by an + /// extended number of type Value, i.e. a finite number of type + /// Value, -\ref INF or \ref INF. + void rowBounds(Row c, Value lower, Value upper) { + _setRowBounds(rows.floatingId(c.id),lower, upper); + // _setRowUpperBound(rows.floatingId(c.id),upper); + } + + ///Set an element of the objective function + void objCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); }; + ///Set the objective function + + ///\param e is a linear expression of type \ref Expr. + ///\bug The previous objective function is not cleared! + void setObj(Expr e) { + _clearObj(); + for (Expr::iterator i=e.begin(); i!=e.end(); ++i) + objCoeff((*i).first,(*i).second); + obj_const_comp=e.constComp(); + } + + ///Maximize + void max() { _setMax(); } + ///Minimize + void min() { _setMin(); } + + + ///@} + + + ///\name Solve the LP + + ///@{ + + ///\e + SolveExitStatus solve() { return _solve(); } + + ///@} + + ///\name Obtain the solution + + ///@{ + + ///\e + SolutionStatus primalStatus() { + return _getPrimalStatus(); + } + + ///\e + Value primal(Col c) { return _getPrimal(cols.floatingId(c.id)); } + + ///\e + + ///\return + ///- \ref INF or -\ref INF means either infeasibility or unboundedness + /// of the primal problem, depending on whether we minimize or maximize. + ///- \ref NaN if no primal solution is found. + ///- The (finite) objective value if an optimal solution is found. + Value primalValue() { return _getPrimalValue()+obj_const_comp;} + ///@} + + }; + + ///\e + + ///\relates LpSolverBase::Expr + /// + inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a, + const LpSolverBase::Expr &b) + { + LpSolverBase::Expr tmp(a); + tmp+=b; ///\todo Doesn't STL have some special 'merge' algorithm? + return tmp; + } + ///\e + + ///\relates LpSolverBase::Expr + /// + inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a, + const LpSolverBase::Expr &b) + { + LpSolverBase::Expr tmp(a); + tmp-=b; ///\todo Doesn't STL have some special 'merge' algorithm? + return tmp; + } + ///\e + + ///\relates LpSolverBase::Expr + /// + inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a, + const LpSolverBase::Value &b) + { + LpSolverBase::Expr tmp(a); + tmp*=b; ///\todo Doesn't STL have some special 'merge' algorithm? + return tmp; + } + + ///\e + + ///\relates LpSolverBase::Expr + /// + inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a, + const LpSolverBase::Expr &b) + { + LpSolverBase::Expr tmp(b); + tmp*=a; ///\todo Doesn't STL have some special 'merge' algorithm? + return tmp; + } + ///\e + + ///\relates LpSolverBase::Expr + /// + inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a, + const LpSolverBase::Value &b) + { + LpSolverBase::Expr tmp(a); + tmp/=b; ///\todo Doesn't STL have some special 'merge' algorithm? + return tmp; + } + + ///\e + + ///\relates LpSolverBase::Constr + /// + inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e, + const LpSolverBase::Expr &f) + { + return LpSolverBase::Constr(-LpSolverBase::INF,e-f,0); + } + + ///\e + + ///\relates LpSolverBase::Constr + /// + inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &e, + const LpSolverBase::Expr &f) + { + return LpSolverBase::Constr(e,f); + } + + ///\e + + ///\relates LpSolverBase::Constr + /// + inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e, + const LpSolverBase::Value &f) + { + return LpSolverBase::Constr(e,f); + } + + ///\e + + ///\relates LpSolverBase::Constr + /// + inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e, + const LpSolverBase::Expr &f) + { + return LpSolverBase::Constr(-LpSolverBase::INF,f-e,0); + } + + + ///\e + + ///\relates LpSolverBase::Constr + /// + inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &e, + const LpSolverBase::Expr &f) + { + return LpSolverBase::Constr(f,e); + } + + + ///\e + + ///\relates LpSolverBase::Constr + /// + inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e, + const LpSolverBase::Value &f) + { + return LpSolverBase::Constr(f,e); + } + + ///\e + + ///\relates LpSolverBase::Constr + /// + inline LpSolverBase::Constr operator==(const LpSolverBase::Expr &e, + const LpSolverBase::Expr &f) + { + return LpSolverBase::Constr(0,e-f,0); + } + + ///\e + + ///\relates LpSolverBase::Constr + /// + inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &n, + const LpSolverBase::Constr&c) + { + LpSolverBase::Constr tmp(c); + ///\todo Create an own exception type. + if(!isnan(tmp.lowerBound())) throw LogicError(); + else tmp.lowerBound()=n; + return tmp; + } + ///\e + + ///\relates LpSolverBase::Constr + /// + inline LpSolverBase::Constr operator<=(const LpSolverBase::Constr& c, + const LpSolverBase::Value &n) + { + LpSolverBase::Constr tmp(c); + ///\todo Create an own exception type. + if(!isnan(tmp.upperBound())) throw LogicError(); + else tmp.upperBound()=n; + return tmp; + } + + ///\e + + ///\relates LpSolverBase::Constr + /// + inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &n, + const LpSolverBase::Constr&c) + { + LpSolverBase::Constr tmp(c); + ///\todo Create an own exception type. + if(!isnan(tmp.upperBound())) throw LogicError(); + else tmp.upperBound()=n; + return tmp; + } + ///\e + + ///\relates LpSolverBase::Constr + /// + inline LpSolverBase::Constr operator>=(const LpSolverBase::Constr& c, + const LpSolverBase::Value &n) + { + LpSolverBase::Constr tmp(c); + ///\todo Create an own exception type. + if(!isnan(tmp.lowerBound())) throw LogicError(); + else tmp.lowerBound()=n; + return tmp; + } + + +} //namespace lemon + +#endif //LEMON_LP_BASE_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lp_cplex.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lp_cplex.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,407 @@ +/* -*- C++ -*- + * lemon/lp_cplex.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ +#include +#include + +///\file +///\brief Implementation of the LEMON-CPLEX lp solver interface. +namespace lemon { + + LpCplex::LpCplex() : LpSolverBase() { + env = NULL; + lp = NULL; + env = CPXopenCPLEXdevelop(&status); +// if (Env == NULL) +// { +// fprintf(stderr,"A CPLEX környezet megnyitása sikertelen.\n"); +// CPXgeterrorstring(Env, Status, ErrorMsg); +// fprintf(stderr,"%s",ErrorMsg); +// goto Terminate; +// } + + // *** A problema létrehozása *** + lp = CPXcreateprob(env, &status, "LP problem"); + + // if (Problem == NULL) +// { +// fprintf(stderr,"Az LP létrehozása sikertelen"); +// goto Terminate; +// } + + } + + LpCplex::~LpCplex() { + status = CPXfreeprob(env,&lp); + // if (Status != 0) + // { +// fprintf(stderr,"A CPLEX feladat törlése sikertelen.\n"); +// CPXgeterrorstring(Env, Status, ErrorMsg); +// fprintf(stderr,"%s",ErrorMsg); +// goto Terminate; +// } + + status = CPXcloseCPLEX(&env); + // if (Status != 0) + // { + // fprintf(stderr,"A CPLEX környezet bezárása sikertelen.\n"); +// CPXgeterrorstring(Env, Status, ErrorMsg); +// fprintf(stderr,"%s",ErrorMsg); +// goto Terminate; +// } + + } + + LpSolverBase &LpCplex::_newLp() + { + return *(LpSolverBase*)0; + } + LpSolverBase &LpCplex::_copyLp() { + return *(LpSolverBase*)0; + //Ez lesz majd CPXcloneprob (env, lp, &status); + } + + int LpCplex::_addCol() + { + int i = CPXgetnumcols (env, lp); + Value lb[1],ub[1]; + lb[0]=-INF;//-CPX_INFBOUND; + ub[0]=INF;//CPX_INFBOUND; + status = CPXnewcols (env, lp, 1, NULL, lb, ub, NULL, NULL); + return i; + } + + int LpCplex::_addRow() + { + //We want a row that is not constrained + char sense[1]; + sense[0]='L';//<= constraint + Value rhs[1]; + rhs[0]=INF; + int i = CPXgetnumrows (env, lp); + status = CPXnewrows (env, lp, 1, rhs, sense, NULL, NULL); + return i; + } + + + void LpCplex::_eraseCol(int i) { + ///\todo Not implemented yet + } + + void LpCplex::_eraseRow(int i) { + ///\todo Not implemented yet + } + + + ///\warning Data at index 0 is ignored in the arrays. + void LpCplex::_setRowCoeffs(int i, + int length, + int const * indices, + Value const * values ) + { + int rowlist[length+1]; + int* p=rowlist; + for (int k=1;k<=length;++k){ + rowlist[k]=i; + } + status = CPXchgcoeflist(env, lp, + length, + p+1, + const_cast(indices+1), + const_cast(values+1)); + } + + void LpCplex::_setColCoeffs(int i, + int length, + int const * indices, + Value const * values) + { + int collist[length+1]; + int* p=collist; + for (int k=1;k<=length;++k){ + collist[k]=i; + } + status = CPXchgcoeflist(env, lp, + length, + const_cast(indices+1), + p+1, + const_cast(values+1)); + } + + void LpCplex::_setCoeff(int row, int col, Value value) + { + CPXchgcoef (env, lp, row, col, value); + } + + void LpCplex::_setColLowerBound(int i, Value value) + { + int indices[1]; + indices[0]=i; + char lu[1]; + lu[0]='L'; + Value bd[1]; + bd[0]=value; + status = CPXchgbds (env, lp, 1, indices, lu, bd); + + } + + void LpCplex::_setColUpperBound(int i, Value value) + { + int indices[1]; + indices[0]=i; + char lu[1]; + lu[0]='U'; + Value bd[1]; + bd[0]=value; + status = CPXchgbds (env, lp, 1, indices, lu, bd); + } + + //This will be easier to implement + void LpCplex::_setRowBounds(int i, Value lb, Value ub) + { + //Bad parameter + if (lb==INF || ub==-INF) { + //FIXME error + } + + int cnt=1; + int indices[1]; + indices[0]=i; + char sense[1]; + + if (lb==-INF){ + sense[0]='L'; + CPXchgsense (env, lp, cnt, indices, sense); + CPXchgcoef (env, lp, i, -1, ub); + + } + else{ + if (ub==INF){ + sense[0]='G'; + CPXchgsense (env, lp, cnt, indices, sense); + CPXchgcoef (env, lp, i, -1, lb); + } + else{ + if (lb == ub){ + sense[0]='E'; + CPXchgsense (env, lp, cnt, indices, sense); + CPXchgcoef (env, lp, i, -1, lb); + } + else{ + sense[0]='R'; + CPXchgsense (env, lp, cnt, indices, sense); + CPXchgcoef (env, lp, i, -1, lb); + CPXchgcoef (env, lp, i, -2, ub-lb); + } + } + } + } + +// void LpCplex::_setRowLowerBound(int i, Value value) +// { +// //Not implemented, obsolete +// } + +// void LpCplex::_setRowUpperBound(int i, Value value) +// { +// //Not implemented, obsolete +// // //TODO Ezt kell meg megirni +// // //type of the problem +// // char sense[1]; +// // status = CPXgetsense (env, lp, sense, i, i); +// // Value rhs[1]; +// // status = CPXgetrhs (env, lp, rhs, i, i); + +// // switch (sense[0]) { +// // case 'L'://<= constraint +// // break; +// // case 'E'://= constraint +// // break; +// // case 'G'://>= constraint +// // break; +// // case 'R'://ranged constraint +// // break; +// // default: ; +// // //FIXME error +// // } + +// // status = CPXchgcoef (env, lp, i, -2, value_rng); +// } + + void LpCplex::_setObjCoeff(int i, Value obj_coef) + { + CPXchgcoef (env, lp, -1, i, obj_coef); + } + + void LpCplex::_clearObj() + { + for (int i=0;i< CPXgetnumcols (env, lp);++i){ + CPXchgcoef (env, lp, -1, i, 0); + } + + } + + LpCplex::SolveExitStatus LpCplex::_solve() + { + + status = CPXlpopt (env, lp); + if (status == 0){ + return SOLVED; + } + else{ + return UNSOLVED; + } +// int i= lpx_simplex(lp); +// switch (i) { +// case LPX_E_OK: +// return SOLVED; +// break; +// default: +// return UNSOLVED; +// } + } + + LpCplex::SolutionStatus LpCplex::_getPrimalStatus() + { +//7.5-os cplex statusai +// #define CPX_OPTIMAL 1 +// #define CPX_INFEASIBLE 2 +// #define CPX_UNBOUNDED 3 +// #define CPX_OBJ_LIM 4 +// #define CPX_IT_LIM_FEAS 5 +// #define CPX_IT_LIM_INFEAS 6 +// #define CPX_TIME_LIM_FEAS 7 +// #define CPX_TIME_LIM_INFEAS 8 +// #define CPX_NUM_BEST_FEAS 9 +// #define CPX_NUM_BEST_INFEAS 10 +// #define CPX_OPTIMAL_INFEAS 11 +// #define CPX_ABORT_FEAS 12 +// #define CPX_ABORT_INFEAS 13 +// #define CPX_ABORT_DUAL_INFEAS 14 +// #define CPX_ABORT_PRIM_INFEAS 15 +// #define CPX_ABORT_PRIM_DUAL_INFEAS 16 +// #define CPX_ABORT_PRIM_DUAL_FEAS 17 +// #define CPX_ABORT_CROSSOVER 18 +// #define CPX_INForUNBD 19 +// #define CPX_PIVOT 20 + +// Ezeket hova tegyem: +// ??case CPX_ABORT_DUAL_INFEAS +// ??case CPX_ABORT_CROSSOVER +// ??case CPX_INForUNBD +// ??case CPX_PIVOT + + int stat = CPXgetstat (env, lp); + switch (stat) { + case 0: + return UNDEFINED; //Undefined + break; + case CPX_OPTIMAL://Optimal + return OPTIMAL; + break; + case CPX_UNBOUNDED://Unbounded + return INFINITE; + break; + case CPX_INFEASIBLE://Infeasible + case CPX_IT_LIM_INFEAS: + case CPX_TIME_LIM_INFEAS: + case CPX_NUM_BEST_INFEAS: + case CPX_OPTIMAL_INFEAS: + case CPX_ABORT_INFEAS: + case CPX_ABORT_PRIM_INFEAS: + case CPX_ABORT_PRIM_DUAL_INFEAS: + return INFEASIBLE; + break; + case CPX_OBJ_LIM: + case CPX_IT_LIM_FEAS: + case CPX_TIME_LIM_FEAS: + case CPX_NUM_BEST_FEAS: + case CPX_ABORT_FEAS: + case CPX_ABORT_PRIM_DUAL_FEAS: + return FEASIBLE; + break; + default: + return UNDEFINED; //Everything else comes here + //FIXME error + } + + + //Nem tudom, hanyas cplex verzio statusai +// CPX_STAT_ABORT_DUAL_OBJ_LIM +// CPX_STAT_ABORT_IT_LIM +// CPX_STAT_ABORT_OBJ_LIM +// CPX_STAT_ABORT_PRIM_OBJ_LIM +// CPX_STAT_ABORT_TIME_LIM +// CPX_STAT_ABORT_USER +// CPX_STAT_FEASIBLE_RELAXED +// CPX_STAT_INFEASIBLE +// CPX_STAT_INForUNBD +// CPX_STAT_NUM_BEST +// CPX_STAT_OPTIMAL +// CPX_STAT_OPTIMAL_FACE_UNBOUNDED +// CPX_STAT_OPTIMAL_INFEAS +// CPX_STAT_OPTIMAL_RELAXED +// CPX_STAT_UNBOUNDED + +// int stat = CPXgetstat (env, lp); +// switch (stat) { +// case CPX_STAT_OPTIMAL://Optimal +// return OPTIMAL; +// break; +// case CPX_STAT_INFEASIBLE://Infeasible +// return INFEASIBLE; +// break; +// case CPX_STAT_UNBOUNDED://Unbounded +// return INFINITE; +// break; +// case CPX_STAT_NUM_BEST://Feasible +// return FEASIBLE; +// break; +// default: +// return UNDEFINED; //Everything else comes here +// //FIXME error +// } + + } + + LpCplex::Value LpCplex::_getPrimal(int i) + { + Value x; + CPXgetx (env, lp, &x, i, i); + return x; + } + + LpCplex::Value LpCplex::_getPrimalValue() + { + Value objval; + //method = CPXgetmethod (env, lp); + status = CPXgetobjval (env, lp, &objval); + return objval; + } + + + + + void LpCplex::_setMax() + { + CPXchgobjsen (env, lp, CPX_MAX); + } + void LpCplex::_setMin() + { + CPXchgobjsen (env, lp, CPX_MIN); + } + +} //namespace lemon + diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lp_cplex.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lp_cplex.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,112 @@ +/* -*- C++ -*- + * lemon/lp_cplex.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_LP_CPLEX_H +#define LEMON_LP_CPLEX_H + +///\file +///\brief Header of the LEMON-CPLEX lp solver interface. + +#include + +extern "C" { +#include +} + +namespace lemon { + + + /// \brief Interface for the CPLEX solver + /// + /// This class implements an interface for the CPLEX LP solver. + class LpCplex : public LpSolverBase { + + public: + + typedef LpSolverBase Parent; + + /// \e + int status; + CPXENVptr env; + CPXLPptr lp; + + + /// \e + LpCplex(); + /// \e + ~LpCplex(); + + protected: + virtual LpSolverBase &_newLp(); + virtual LpSolverBase &_copyLp(); + + virtual int _addCol(); + virtual int _addRow(); + virtual void _eraseCol(int i); + virtual void _eraseRow(int i); + virtual void _setRowCoeffs(int i, + int length, + const int * indices, + const Value * values ); + virtual void _setColCoeffs(int i, + int length, + const int * indices, + const Value * values); + virtual void _setCoeff(int row, int col, Value value); + virtual void _setColLowerBound(int i, Value value); + virtual void _setColUpperBound(int i, Value value); +// virtual void _setRowLowerBound(int i, Value value); +// virtual void _setRowUpperBound(int i, Value value); + virtual void _setRowBounds(int i, Value lower, Value upper); + virtual void _setObjCoeff(int i, Value obj_coef); + virtual void _clearObj(); + ///\e + + ///\bug Unimplemented + /// + virtual SolveExitStatus _solve(); + ///\e + + ///\bug Unimplemented + /// + virtual Value _getPrimal(int i); + ///\e + + ///\bug Unimplemented + /// + virtual Value _getPrimalValue(); + ///\e + + ///\bug Unimplemented + /// + virtual SolutionStatus _getPrimalStatus(); + + ///\e + + ///\bug Unimplemented + /// + virtual void _setMax(); + ///\e + + ///\bug Unimplemented + /// + virtual void _setMin(); + + }; +} //END OF NAMESPACE LEMON + +#endif //LEMON_LP_CPLEX_H + diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lp_glpk.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lp_glpk.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,447 @@ +/* -*- C++ -*- + * lemon/lp_glpk.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_LP_GLPK_CC +#define LEMON_LP_GLPK_CC + +///\file +///\brief Implementation of the LEMON-GLPK lp solver interface. + +#include + +namespace lemon { + + ///\e + + ///\bug Unimplemented! + /// + LpSolverBase &LpGlpk::_newLp() + { + LpSolverBase *tmp=0; + return *tmp; + } + + ///\e + + ///\bug Unimplemented! + /// + LpSolverBase &LpGlpk::_copyLp() + { + LpSolverBase *tmp=0; + return *tmp; + } + + LpGlpk::LpGlpk() : Parent(), + lp(lpx_create_prob()) { + ///\todo constrol function for this: + lpx_set_int_parm(lp, LPX_K_DUAL, 1); + messageLevel(0); + } + + LpGlpk::~LpGlpk() { + lpx_delete_prob(lp); + } + + int LpGlpk::_addCol() { + int i=lpx_add_cols(lp, 1); + _setColLowerBound(i, -INF); + _setColUpperBound(i, INF); + return i; + } + + int LpGlpk::_addRow() { + int i=lpx_add_rows(lp, 1); + return i; + } + + + void LpGlpk::_eraseCol(int i) { + int cols[2]; + cols[1]=i; + lpx_del_cols(lp, 1, cols); + } + + void LpGlpk::_eraseRow(int i) { + int rows[2]; + rows[1]=i; + lpx_del_rows(lp, 1, rows); + } + + void LpGlpk::_setRowCoeffs(int i, + int length, + const int * indices, + const Value * values ) + { + lpx_set_mat_row(lp, i, length, + const_cast(indices) , + const_cast(values)); + } + + void LpGlpk::_setColCoeffs(int i, + int length, + const int * indices, + const Value * values) + { + lpx_set_mat_col(lp, i, length, + const_cast(indices), + const_cast(values)); + } + + + void LpGlpk::_setCoeff(int row, int col, Value value) + { + ///FIXME Of course this is not efficient at all, but GLPK knows not more. + // First approach: get one row, apply changes and set it again + //(one idea to improve this: maybe it is better to do this with 1 coloumn) + + int mem_length=2+lpx_get_num_cols(lp); + int* indices = new int[mem_length]; + Value* values = new Value[mem_length]; + + + int length=lpx_get_mat_row(lp, row, indices, values); + + //The following code does not suppose that the elements of the array indices are sorted + int i=1; + bool found=false; + while (i <= length && !found){ + if (indices[i]==col){ + found = true; + values[i]=value; + } + ++i; + } + if (!found){ + ++length; + indices[length]=col; + values[length]=value; + } + + lpx_set_mat_row(lp, row, length, indices, values); + delete [] indices; + delete [] values; + + } + + void LpGlpk::_setColLowerBound(int i, Value lo) + { + if (lo==INF) { + //FIXME error + } + int b=lpx_get_col_type(lp, i); + double up=lpx_get_col_ub(lp, i); + if (lo==-INF) { + switch (b) { + case LPX_FR: + case LPX_LO: + lpx_set_col_bnds(lp, i, LPX_FR, lo, up); + break; + case LPX_UP: + break; + case LPX_DB: + case LPX_FX: + lpx_set_col_bnds(lp, i, LPX_UP, lo, up); + break; + default: ; + //FIXME error + } + } else { + switch (b) { + case LPX_FR: + case LPX_LO: + lpx_set_col_bnds(lp, i, LPX_LO, lo, up); + break; + case LPX_UP: + case LPX_DB: + case LPX_FX: + if (lo==up) + lpx_set_col_bnds(lp, i, LPX_FX, lo, up); + else + lpx_set_col_bnds(lp, i, LPX_DB, lo, up); + break; + default: ; + //FIXME error + } + } + + } + + void LpGlpk::_setColUpperBound(int i, Value up) + { + if (up==-INF) { + //FIXME error + } + int b=lpx_get_col_type(lp, i); + double lo=lpx_get_col_lb(lp, i); + if (up==INF) { + switch (b) { + case LPX_FR: + case LPX_LO: + break; + case LPX_UP: + lpx_set_col_bnds(lp, i, LPX_FR, lo, up); + break; + case LPX_DB: + case LPX_FX: + lpx_set_col_bnds(lp, i, LPX_LO, lo, up); + break; + default: ; + //FIXME error + } + } else { + switch (b) { + case LPX_FR: + lpx_set_col_bnds(lp, i, LPX_UP, lo, up); + break; + case LPX_UP: + lpx_set_col_bnds(lp, i, LPX_UP, lo, up); + break; + case LPX_LO: + case LPX_DB: + case LPX_FX: + if (lo==up) + lpx_set_col_bnds(lp, i, LPX_FX, lo, up); + else + lpx_set_col_bnds(lp, i, LPX_DB, lo, up); + break; + default: ; + //FIXME error + } + } + } + +// void LpGlpk::_setRowLowerBound(int i, Value lo) +// { +// if (lo==INF) { +// //FIXME error +// } +// int b=lpx_get_row_type(lp, i); +// double up=lpx_get_row_ub(lp, i); +// if (lo==-INF) { +// switch (b) { +// case LPX_FR: +// case LPX_LO: +// lpx_set_row_bnds(lp, i, LPX_FR, lo, up); +// break; +// case LPX_UP: +// break; +// case LPX_DB: +// case LPX_FX: +// lpx_set_row_bnds(lp, i, LPX_UP, lo, up); +// break; +// default: ; +// //FIXME error +// } +// } else { +// switch (b) { +// case LPX_FR: +// case LPX_LO: +// lpx_set_row_bnds(lp, i, LPX_LO, lo, up); +// break; +// case LPX_UP: +// case LPX_DB: +// case LPX_FX: +// if (lo==up) +// lpx_set_row_bnds(lp, i, LPX_FX, lo, up); +// else +// lpx_set_row_bnds(lp, i, LPX_DB, lo, up); +// break; +// default: ; +// //FIXME error +// } +// } +// } + +// void LpGlpk::_setRowUpperBound(int i, Value up) +// { +// if (up==-INF) { +// //FIXME error +// } +// int b=lpx_get_row_type(lp, i); +// double lo=lpx_get_row_lb(lp, i); +// if (up==INF) { +// switch (b) { +// case LPX_FR: +// case LPX_LO: +// break; +// case LPX_UP: +// lpx_set_row_bnds(lp, i, LPX_FR, lo, up); +// break; +// case LPX_DB: +// case LPX_FX: +// lpx_set_row_bnds(lp, i, LPX_LO, lo, up); +// break; +// default: ; +// //FIXME error +// } +// } else { +// switch (b) { +// case LPX_FR: +// lpx_set_row_bnds(lp, i, LPX_UP, lo, up); +// break; +// case LPX_UP: +// lpx_set_row_bnds(lp, i, LPX_UP, lo, up); +// break; +// case LPX_LO: +// case LPX_DB: +// case LPX_FX: +// if (lo==up) +// lpx_set_row_bnds(lp, i, LPX_FX, lo, up); +// else +// lpx_set_row_bnds(lp, i, LPX_DB, lo, up); +// break; +// default: ; +// //FIXME error +// } +// } +// } + + void LpGlpk::_setRowBounds(int i, Value lb, Value ub) + { + //Bad parameter + if (lb==INF || ub==-INF) { + //FIXME error + } + + if (lb == -INF){ + if (ub == INF){ + lpx_set_row_bnds(lp, i, LPX_FR, lb, ub); + } + else{ + lpx_set_row_bnds(lp, i, LPX_UP, lb, ub); + } + } + else{ + if (ub==INF){ + lpx_set_row_bnds(lp, i, LPX_LO, lb, ub); + + } + else{ + if (lb == ub){ + lpx_set_row_bnds(lp, i, LPX_FX, lb, ub); + } + else{ + lpx_set_row_bnds(lp, i, LPX_DB, lb, ub); + } + } + } + + } + + void LpGlpk::_setObjCoeff(int i, Value obj_coef) + { + //i=0 means the constant term (shift) + lpx_set_obj_coef(lp, i, obj_coef); + } + + void LpGlpk::_clearObj() + { + for (int i=0;i<=lpx_get_num_cols(lp);++i){ + lpx_set_obj_coef(lp, i, 0); + } + } +// void LpGlpk::_setObj(int length, +// int const * indices, +// Value const * values ) +// { +// Value new_values[1+lpx_num_cols()]; +// for (i=0;i<=lpx_num_cols();++i){ +// new_values[i]=0; +// } +// for (i=1;i<=length;++i){ +// new_values[indices[i]]=values[i]; +// } + +// for (i=0;i<=lpx_num_cols();++i){ +// lpx_set_obj_coef(lp, i, new_values[i]); +// } +// } + + LpGlpk::SolveExitStatus LpGlpk::_solve() + { + int i= lpx_simplex(lp); + switch (i) { + case LPX_E_OK: + return SOLVED; + break; + default: + return UNSOLVED; + } + } + + LpGlpk::Value LpGlpk::_getPrimal(int i) + { + return lpx_get_col_prim(lp,i); + } + + LpGlpk::Value LpGlpk::_getPrimalValue() + { + return lpx_get_obj_val(lp); + } + + + LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() + { + int stat= lpx_get_status(lp); + switch (stat) { + case LPX_UNDEF://Undefined (no solve has been run yet) + return UNDEFINED; + break; + case LPX_NOFEAS://There is no feasible solution (primal, I guess) + case LPX_INFEAS://Infeasible + return INFEASIBLE; + break; + case LPX_UNBND://Unbounded + return INFINITE; + break; + case LPX_FEAS://Feasible + return FEASIBLE; + break; + case LPX_OPT://Feasible + return OPTIMAL; + break; + default: + return UNDEFINED; //to avoid gcc warning + //FIXME error + } + } + + + void LpGlpk::_setMax() + { + lpx_set_obj_dir(lp, LPX_MAX); + } + + void LpGlpk::_setMin() + { + lpx_set_obj_dir(lp, LPX_MIN); + } + + + void LpGlpk::messageLevel(int m) + { + lpx_set_int_parm(lp, LPX_K_MSGLEV, m); + } + + void LpGlpk::presolver(bool b) + { + lpx_set_int_parm(lp, LPX_K_PRESOL, b); + } + + +} //END OF NAMESPACE LEMON + +#endif //LEMON_LP_GLPK_CC diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lp_glpk.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lp_glpk.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,114 @@ +/* -*- C++ -*- + * lemon/lp_glpk.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_LP_GLPK_H +#define LEMON_LP_GLPK_H + +///\file +///\brief Header of the LEMON-GLPK lp solver interface. +///\ingroup gen_opt_group + +#include +extern "C" { +#include +} + +namespace lemon { + + + /// \brief Interface for the GLPK LP solver + /// + /// This class implements an interface for the GLPK LP solver. + ///\ingroup gen_opt_group + class LpGlpk : public LpSolverBase { + protected: + LPX* lp; + + public: + + typedef LpSolverBase Parent; + + LpGlpk(); + ~LpGlpk(); + + protected: + virtual LpSolverBase &_newLp(); + virtual LpSolverBase &_copyLp(); + + virtual int _addCol(); + virtual int _addRow(); + virtual void _eraseCol(int i); + virtual void _eraseRow(int i); + + virtual void _setRowCoeffs(int i, + int length, + const int * indices, + const Value * values ); + virtual void _setColCoeffs(int i, + int length, + const int * indices, + const Value * values); + virtual void _setCoeff(int row, int col, Value value); + virtual void _setColLowerBound(int i, Value value); + virtual void _setColUpperBound(int i, Value value); +// virtual void _setRowLowerBound(int i, Value value); +// virtual void _setRowUpperBound(int i, Value value); + virtual void _setRowBounds(int i, Value lower, Value upper); + virtual void _setObjCoeff(int i, Value obj_coef); + virtual void _clearObj(); +// virtual void _setObj(int length, +// int const * indices, +// Value const * values ) = 0; + + ///\e + + ///\todo It should be clarified + /// + virtual SolveExitStatus _solve(); + virtual Value _getPrimal(int i); + virtual Value _getPrimalValue(); + ///\e + + ///\todo It should be clarified + /// + virtual SolutionStatus _getPrimalStatus(); + virtual void _setMax(); + virtual void _setMin(); + + public: + ///Set the verbosity of the messages + + ///Set the verbosity of the messages + /// + ///\param m is the level of the messages output by the solver routines. + ///The possible values are: + ///- 0 --- no output (default value) + ///- 1 --- error messages only + ///- 2 --- normal output + ///- 3 --- full output (includes informational messages) + void messageLevel(int m); + ///Turns on or off the presolver + + ///Turns on (\c b is \c true) or off (\c b is \c false) the presolver + /// + ///The presolver is off by default. + void presolver(bool b); + + }; +} //END OF NAMESPACE LEMON + +#endif //LEMON_LP_GLPK_H + diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lp_skeleton.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lp_skeleton.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,127 @@ +/* -*- C++ -*- + * lemon/lp_skeleton.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include + +///\file +///\brief A skeleton file to implement LP solver interfaces +namespace lemon { + + LpSolverBase &LpSkeleton::_newLp() + { + LpSolverBase *tmp=0; + return *tmp; + } + + LpSolverBase &LpSkeleton::_copyLp() + { + LpSolverBase *tmp=0; + return *tmp; + } + + int LpSkeleton::_addCol() + { + return ++col_num; + } + + int LpSkeleton::_addRow() + { + return ++row_num; + } + + void LpSkeleton::_eraseCol(int ) { + } + + void LpSkeleton::_eraseRow(int) { + } + + void LpSkeleton::_setRowCoeffs(int, + int, + int const *, + Value const *) + { + } + + void LpSkeleton::_setColCoeffs(int, + int, + int const *, + Value const *) + { + } + + void LpSkeleton::_setCoeff(int, int, Value ) + { + } + + + void LpSkeleton::_setColLowerBound(int, Value) + { + } + + void LpSkeleton::_setColUpperBound(int, Value) + { + } + +// void LpSkeleton::_setRowLowerBound(int, Value) +// { +// } + +// void LpSkeleton::_setRowUpperBound(int, Value) +// { +// } + + void LpSkeleton::_setRowBounds(int, Value, Value) + { + } + + void LpSkeleton::_setObjCoeff(int, Value) + { + } + + void LpSkeleton::_setMax() + { + } + + void LpSkeleton::_setMin() + { + } + + void LpSkeleton::_clearObj() + { + } + + LpSkeleton::SolveExitStatus LpSkeleton::_solve() + { + return SOLVED; + } + + LpSkeleton::Value LpSkeleton::_getPrimal(int) + { + return 0; + } + + LpSkeleton::Value LpSkeleton::_getPrimalValue() + { + return 0; + } + + LpSkeleton::SolutionStatus LpSkeleton::_getPrimalStatus() + { + return OPTIMAL; + } + +} //namespace lemon + diff -r d8475431bbbb -r 8e85e6bbefdf lemon/lp_skeleton.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/lp_skeleton.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,133 @@ +/* -*- C++ -*- + * lemon/lp_skeleton.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_LP_SKELETON +#define LEMON_LP_SKELETON + +#include + +///\file +///\brief A skeleton file to implement LP solver interfaces +namespace lemon { + + ///A skeleton class to implement LP solver interfaces + class LpSkeleton :public LpSolverBase { + int col_num,row_num; + + protected: + ///\e + virtual LpSolverBase &_newLp(); + ///\e + virtual LpSolverBase &_copyLp(); + /// \e + virtual int _addCol(); + /// \e + virtual int _addRow(); + /// \e + virtual void _eraseCol(int i); + /// \e + virtual void _eraseRow(int i); + /// \e + + /// \warning Arrays are indexed from 1 (datum at index 0 is ignored) + /// + virtual void _setRowCoeffs(int i, + int length, + int const * indices, + Value const * values ); + /// \e + + /// \warning Arrays are indexed from 1 (datum at index 0 is ignored) + /// + virtual void _setColCoeffs(int i, + int length, + int const * indices, + Value const * values ); + + /// Set one element of the coefficient matrix + virtual void _setCoeff(int row, int col, Value value); + + /// The lower bound of a variable (column) have to be given by an + /// extended number of type Value, i.e. a finite number of type + /// Value or -\ref INF. + virtual void _setColLowerBound(int i, Value value); + /// \e + + /// The upper bound of a variable (column) have to be given by an + /// extended number of type Value, i.e. a finite number of type + /// Value or \ref INF. + virtual void _setColUpperBound(int i, Value value); + /// \e + +// /// The lower bound of a linear expression (row) have to be given by an +// /// extended number of type Value, i.e. a finite number of type +// /// Value or -\ref INF. +// virtual void _setRowLowerBound(int i, Value value); +// /// \e + +// /// The upper bound of a linear expression (row) have to be given by an +// /// extended number of type Value, i.e. a finite number of type +// /// Value or \ref INF. +// virtual void _setRowUpperBound(int i, Value value); + + /// The lower and upper bound of a linear expression (row) have to be + /// given by an + /// extended number of type Value, i.e. a finite number of type + /// Value or +/-\ref INF. + virtual void _setRowBounds(int i, Value lb, Value ub); + /// \e + + + /// \e + virtual void _clearObj(); + /// \e + virtual void _setObjCoeff(int i, Value obj_coef); + + ///\e + + ///\bug Wrong interface + /// + virtual SolveExitStatus _solve(); + + ///\e + + ///\bug Wrong interface + /// + virtual Value _getPrimal(int i); + ///\e + + ///\bug Wrong interface + /// + virtual Value _getPrimalValue(); + ///\e + + ///\bug Wrong interface + /// + virtual SolutionStatus _getPrimalStatus(); + + ///\e + virtual void _setMax(); + ///\e + virtual void _setMin(); + + + public: + LpSkeleton() : LpSolverBase(), col_num(0), row_num(0) {} + }; + +} //namespace lemon + +#endif // LEMON_LP_SKELETON diff -r d8475431bbbb -r 8e85e6bbefdf lemon/maps.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/maps.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,841 @@ +/* -*- C++ -*- + * lemon/maps.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_MAPS_H +#define LEMON_MAPS_H + +#include +#include + + +///\file +///\ingroup maps +///\brief Miscellaneous property maps +/// +///\todo This file has the same name as the concept file in concept/, +/// and this is not easily detectable in docs... + +#include + +namespace lemon { + + /// \addtogroup maps + /// @{ + + /// Base class of maps. + + /// Base class of maps. + /// It provides the necessary typedefs required by the map concept. + template + class MapBase + { + public: + ///\e + typedef K Key; + ///\e + typedef T Value; + }; + + /// Null map. (a.k.a. DoNothingMap) + + /// If you have to provide a map only for its type definitions, + /// or if you have to provide a writable map, but + /// data written to it will sent to /dev/null... + template + class NullMap : public MapBase + { + public: + + typedef True NeedCopy; + + /// Gives back a default constructed element. + T operator[](const K&) const { return T(); } + /// Absorbs the value. + void set(const K&, const T&) {} + }; + + template + NullMap nullMap() { + return NullMap(); + } + + + /// Constant map. + + /// This is a readable map which assigns a specified value to each key. + /// In other aspects it is equivalent to the \ref NullMap. + /// \todo set could be used to set the value. + template + class ConstMap : public MapBase + { + T v; + public: + + typedef True NeedCopy; + + /// Default constructor + + /// The value of the map will be uninitialized. + /// (More exactly it will be default constructed.) + ConstMap() {} + ///\e + + /// \param _v The initial value of the map. + /// + ConstMap(const T &_v) : v(_v) {} + + T operator[](const K&) const { return v; } + void set(const K&, const T&) {} + + template + struct rebind { + typedef ConstMap other; + }; + + template + ConstMap(const ConstMap &, const T &_v) : v(_v) {} + }; + + ///Returns a \ref ConstMap class + + ///This function just returns a \ref ConstMap class. + ///\relates ConstMap + template + inline ConstMap constMap(const K &k) + { + return ConstMap(k); + } + + + //to document later + template + struct Const { }; + //to document later + template + class ConstMap > : public MapBase + { + public: + ConstMap() { } + V operator[](const K&) const { return v; } + void set(const K&, const V&) { } + }; + + /// \c std::map wrapper + + /// This is essentially a wrapper for \c std::map. With addition that + /// you can specify a default value different from \c Value() . + /// + /// \todo Provide allocator parameter... + template > + class StdMap : public std::map { + typedef std::map parent; + T v; + typedef typename parent::value_type PairType; + + public: + typedef K Key; + typedef T Value; + typedef T& Reference; + typedef const T& ConstReference; + + + StdMap() : v() {} + /// Constructor with specified default value + StdMap(const T& _v) : v(_v) {} + + /// \brief Constructs the map from an appropriate std::map. + /// + /// \warning Inefficient: copies the content of \c m ! + StdMap(const parent &m) : parent(m) {} + /// \brief Constructs the map from an appropriate std::map, and explicitly + /// specifies a default value. + /// + /// \warning Inefficient: copies the content of \c m ! + StdMap(const parent &m, const T& _v) : parent(m), v(_v) {} + + template + StdMap(const StdMap &m, const T &_v) { + //FIXME; + } + + Reference operator[](const Key &k) { + return insert(PairType(k,v)).first -> second; + } + ConstReference operator[](const Key &k) const { + typename parent::iterator i = lower_bound(k); + if (i == parent::end() || parent::key_comp()(k, (*i).first)) + return v; + return (*i).second; + } + void set(const Key &k, const T &t) { + parent::operator[](k) = t; + } + + /// Changes the default value of the map. + /// \return Returns the previous default value. + /// + /// \warning The value of some keys (which has already been queried, but + /// the value has been unchanged from the default) may change! + T setDefault(const T &_v) { T old=v; v=_v; return old; } + + template + struct rebind { + typedef StdMap other; + }; + }; + + /// @} + + /// \addtogroup map_adaptors + /// @{ + + + ///Convert the \c Value of a maps to another type. + + ///This \ref concept::ReadMap "read only map" + ///converts the \c Value of a maps to type \c T. + ///Its \c Value is inherited from \c M. + /// + ///Actually, + ///\code + /// ConvertMap sh(x,v); + ///\endcode + ///it is equivalent with + ///\code + /// ConstMap c_tmp(v); + /// AddMap > sh(x,v); + ///\endcode + ///\bug wrong documentation + template + class ConvertMap { + typename SmartConstReference::Type m; + public: + + typedef True NeedCopy; + + typedef typename M::Key Key; + typedef T Value; + + ///Constructor + + ///Constructor + ///\param _m is the undelying map + ///\param _v is the convert value + ConvertMap(const M &_m) : m(_m) {}; + + /// \brief The subscript operator. + /// + /// The subscript operator. + /// \param edge The edge + /// \return The target of the edge + Value operator[](Key k) const {return m[k];} + }; + + ///Returns an \ref ConvertMap class + + ///This function just returns an \ref ConvertMap class. + ///\relates ConvertMap + ///\todo The order of the template parameters are changed. + template + inline ConvertMap convertMap(const M &m) + { + return ConvertMap(m); + } + + ///Sum of two maps + + ///This \ref concept::ReadMap "read only map" returns the sum of the two + ///given maps. Its \c Key and \c Value will be inherited from \c M1. + ///The \c Key and \c Value of M2 must be convertible to those of \c M1. + + template + class AddMap + { + typename SmartConstReference::Type m1; + typename SmartConstReference::Type m2; + + public: + + typedef True NeedCopy; + + typedef typename M1::Key Key; + typedef typename M1::Value Value; + + ///Constructor + + ///\e + /// + AddMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; + Value operator[](Key k) const {return m1[k]+m2[k];} + }; + + ///Returns an \ref AddMap class + + ///This function just returns an \ref AddMap class. + ///\todo How to call these type of functions? + /// + ///\relates AddMap + ///\todo Wrong scope in Doxygen when \c \\relates is used + template + inline AddMap addMap(const M1 &m1,const M2 &m2) + { + return AddMap(m1,m2); + } + + ///Shift a maps with a constant. + + ///This \ref concept::ReadMap "read only map" returns the sum of the + ///given map and a constant value. + ///Its \c Key and \c Value is inherited from \c M. + /// + ///Actually, + ///\code + /// ShiftMap sh(x,v); + ///\endcode + ///it is equivalent with + ///\code + /// ConstMap c_tmp(v); + /// AddMap > sh(x,v); + ///\endcode + template + class ShiftMap + { + typename SmartConstReference::Type m; + typename M::Value v; + public: + + typedef True NeedCopy; + typedef typename M::Key Key; + typedef typename M::Value Value; + + ///Constructor + + ///Constructor + ///\param _m is the undelying map + ///\param _v is the shift value + ShiftMap(const M &_m,const Value &_v ) : m(_m), v(_v) {}; + Value operator[](Key k) const {return m[k]+v;} + }; + + ///Returns an \ref ShiftMap class + + ///This function just returns an \ref ShiftMap class. + ///\relates ShiftMap + ///\todo A better name is required. + template + inline ShiftMap shiftMap(const M &m,const typename M::Value &v) + { + return ShiftMap(m,v); + } + + ///Difference of two maps + + ///This \ref concept::ReadMap "read only map" returns the difference + ///of the values returned by the two + ///given maps. Its \c Key and \c Value will be inherited from \c M1. + ///The \c Key and \c Value of \c M2 must be convertible to those of \c M1. + + template + class SubMap + { + typename SmartConstReference::Type m1; + typename SmartConstReference::Type m2; + public: + + typedef True NeedCopy; + typedef typename M1::Key Key; + typedef typename M1::Value Value; + + ///Constructor + + ///\e + /// + SubMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; + Value operator[](Key k) const {return m1[k]-m2[k];} + }; + + ///Returns a \ref SubMap class + + ///This function just returns a \ref SubMap class. + /// + ///\relates SubMap + template + inline SubMap subMap(const M1 &m1,const M2 &m2) + { + return SubMap(m1,m2); + } + + ///Product of two maps + + ///This \ref concept::ReadMap "read only map" returns the product of the + ///values returned by the two + ///given + ///maps. Its \c Key and \c Value will be inherited from \c M1. + ///The \c Key and \c Value of \c M2 must be convertible to those of \c M1. + + template + class MulMap + { + typename SmartConstReference::Type m1; + typename SmartConstReference::Type m2; + public: + + typedef True NeedCopy; + typedef typename M1::Key Key; + typedef typename M1::Value Value; + + ///Constructor + + ///\e + /// + MulMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; + Value operator[](Key k) const {return m1[k]*m2[k];} + }; + + ///Returns a \ref MulMap class + + ///This function just returns a \ref MulMap class. + ///\relates MulMap + template + inline MulMap mulMap(const M1 &m1,const M2 &m2) + { + return MulMap(m1,m2); + } + + ///Scale a maps with a constant. + + ///This \ref concept::ReadMap "read only map" returns the value of the + ///given map multipied with a constant value. + ///Its \c Key and \c Value is inherited from \c M. + /// + ///Actually, + ///\code + /// ScaleMap sc(x,v); + ///\endcode + ///it is equivalent with + ///\code + /// ConstMap c_tmp(v); + /// MulMap > sc(x,v); + ///\endcode + template + class ScaleMap + { + typename SmartConstReference::Type m; + typename M::Value v; + public: + + typedef True NeedCopy; + typedef typename M::Key Key; + typedef typename M::Value Value; + + ///Constructor + + ///Constructor + ///\param _m is the undelying map + ///\param _v is the scaling value + ScaleMap(const M &_m,const Value &_v ) : m(_m), v(_v) {}; + Value operator[](Key k) const {return m[k]*v;} + }; + + ///Returns an \ref ScaleMap class + + ///This function just returns an \ref ScaleMap class. + ///\relates ScaleMap + ///\todo A better name is required. + template + inline ScaleMap scaleMap(const M &m,const typename M::Value &v) + { + return ScaleMap(m,v); + } + + ///Quotient of two maps + + ///This \ref concept::ReadMap "read only map" returns the quotient of the + ///values returned by the two + ///given maps. Its \c Key and \c Value will be inherited from \c M1. + ///The \c Key and \c Value of \c M2 must be convertible to those of \c M1. + + template + class DivMap + { + typename SmartConstReference::Type m1; + typename SmartConstReference::Type m2; + public: + + typedef True NeedCopy; + typedef typename M1::Key Key; + typedef typename M1::Value Value; + + ///Constructor + + ///\e + /// + DivMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; + Value operator[](Key k) const {return m1[k]/m2[k];} + }; + + ///Returns a \ref DivMap class + + ///This function just returns a \ref DivMap class. + ///\relates DivMap + template + inline DivMap divMap(const M1 &m1,const M2 &m2) + { + return DivMap(m1,m2); + } + + ///Composition of two maps + + ///This \ref concept::ReadMap "read only map" returns the composition of + ///two + ///given maps. That is to say, if \c m1 is of type \c M1 and \c m2 is + ///of \c M2, + ///then for + ///\code + /// ComposeMap cm(m1,m2); + ///\endcode + /// cm[x] will be equal to m1[m2[x]] + /// + ///Its \c Key is inherited from \c M2 and its \c Value is from + ///\c M1. + ///The \c M2::Value must be convertible to \c M1::Key. + ///\todo Check the requirements. + + template + class ComposeMap + { + typename SmartConstReference::Type m1; + typename SmartConstReference::Type m2; + public: + + typedef True NeedCopy; + typedef typename M2::Key Key; + typedef typename M1::Value Value; + + typedef True NeedCopy; + + ///Constructor + + ///\e + /// + ComposeMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; + Value operator[](Key k) const {return m1[m2[k]];} + }; + ///Returns a \ref ComposeMap class + + ///This function just returns a \ref ComposeMap class. + /// + ///\relates ComposeMap + template + inline ComposeMap composeMap(const M1 &m1,const M2 &m2) + { + return ComposeMap(m1,m2); + } + + ///Combine of two maps using an STL (binary) functor. + + ///Combine of two maps using an STL (binary) functor. + /// + /// + ///This \ref concept::ReadMap "read only map" takes to maps and a + ///binary functor and returns the composition of + ///two + ///given maps unsing the functor. + ///That is to say, if \c m1 and \c m2 is of type \c M1 and \c M2 + ///and \c f is of \c F, + ///then for + ///\code + /// CombineMap cm(m1,m2,f); + ///\endcode + /// cm[x] will be equal to f(m1[x],m2[x]) + /// + ///Its \c Key is inherited from \c M1 and its \c Value is \c V. + ///The \c M2::Value and \c M1::Value must be convertible to the corresponding + ///input parameter of \c F and the return type of \c F must be convertible + ///to \c V. + ///\todo Check the requirements. + + template + class CombineMap + { + typename SmartConstReference::Type m1; + typename SmartConstReference::Type m2; + F f; + public: + + typedef True NeedCopy; + typedef typename M1::Key Key; + typedef V Value; + + ///Constructor + + ///\e + /// + CombineMap(const M1 &_m1,const M2 &_m2,const F &_f) + : m1(_m1), m2(_m2), f(_f) {}; + Value operator[](Key k) const {return f(m1[k],m2[k]);} + }; + + ///Returns a \ref CombineMap class + + ///This function just returns a \ref CombineMap class. + /// + ///Only the first template parameter (the value type) must be given. + /// + ///For example if \c m1 and \c m2 are both \c double valued maps, then + ///\code + ///combineMap(m1,m2,std::plus) + ///\endcode + ///is equivalent with + ///\code + ///addMap(m1,m2) + ///\endcode + /// + ///\relates CombineMap + template + inline CombineMap combineMap(const M1 &m1,const M2 &m2,const F &f) + { + return CombineMap(m1,m2,f); + } + + ///Negative value of a map + + ///This \ref concept::ReadMap "read only map" returns the negative + ///value of the + ///value returned by the + ///given map. Its \c Key and \c Value will be inherited from \c M. + ///The unary \c - operator must be defined for \c Value, of course. + + template + class NegMap + { + typename SmartConstReference::Type m; + public: + + typedef True NeedCopy; + typedef typename M::Key Key; + typedef typename M::Value Value; + + ///Constructor + + ///\e + /// + NegMap(const M &_m) : m(_m) {}; + Value operator[](Key k) const {return -m[k];} + }; + + ///Returns a \ref NegMap class + + ///This function just returns a \ref NegMap class. + ///\relates NegMap + template + inline NegMap negMap(const M &m) + { + return NegMap(m); + } + + + ///Absolute value of a map + + ///This \ref concept::ReadMap "read only map" returns the absolute value + ///of the + ///value returned by the + ///given map. Its \c Key and \c Value will be inherited + ///from M. Value + ///must be comparable to 0 and the unary - + ///operator must be defined for it, of course. + /// + ///\bug We need a unified way to handle the situation below: + ///\code + /// struct _UnConvertible {}; + /// template inline A t_abs(A a) {return _UnConvertible();} + /// template<> inline int t_abs<>(int n) {return abs(n);} + /// template<> inline long int t_abs<>(long int n) {return labs(n);} + /// template<> inline long long int t_abs<>(long long int n) {return ::llabs(n);} + /// template<> inline float t_abs<>(float n) {return fabsf(n);} + /// template<> inline double t_abs<>(double n) {return fabs(n);} + /// template<> inline long double t_abs<>(long double n) {return fabsl(n);} + ///\endcode + + + template + class AbsMap + { + typename SmartConstReference::Type m; + public: + + typedef True NeedCopy; + typedef typename M::Key Key; + typedef typename M::Value Value; + + ///Constructor + + ///\e + /// + AbsMap(const M &_m) : m(_m) {}; + Value operator[](Key k) const {Value tmp=m[k]; return tmp>=0?tmp:-tmp;} + }; + + ///Returns a \ref AbsMap class + + ///This function just returns a \ref AbsMap class. + ///\relates AbsMap + template + inline AbsMap absMap(const M &m) + { + return AbsMap(m); + } + + ///Converts an STL style functor to a map + + ///This \ref concept::ReadMap "read only map" returns the value + ///of a + ///given map. + /// + ///Template parameters \c K and \c V will become its + ///\c Key and \c Value. They must be given explicitely + ///because a functor does not provide such typedefs. + /// + ///Parameter \c F is the type of the used functor. + + + template + class FunctorMap + { + const F &f; + public: + + typedef True NeedCopy; + typedef K Key; + typedef V Value; + + ///Constructor + + ///\e + /// + FunctorMap(const F &_f) : f(_f) {}; + Value operator[](Key k) const {return f(k);} + }; + + ///Returns a \ref FunctorMap class + + ///This function just returns a \ref FunctorMap class. + /// + ///The third template parameter isn't necessary to be given. + ///\relates FunctorMap + template + inline FunctorMap functorMap(const F &f) + { + return FunctorMap(f); + } + + ///Converts a map to an STL style (unary) functor + + ///This class Converts a map to an STL style (unary) functor. + ///that is it provides an operator() to read its values. + /// + ///For the sake of convenience it also works as + ///a ususal \ref concept::ReadMap "readable map", i.e + ///operator[] and the \c Key and \c Value typedefs also exist. + + template + class MapFunctor + { + typename SmartConstReference::Type m; + public: + + typedef True NeedCopy; + typedef typename M::Key argument_type; + typedef typename M::Value result_type; + typedef typename M::Key Key; + typedef typename M::Value Value; + + ///Constructor + + ///\e + /// + MapFunctor(const M &_m) : m(_m) {}; + ///Returns a value of the map + + ///\e + /// + Value operator()(Key k) const {return m[k];} + ///\e + /// + Value operator[](Key k) const {return m[k];} + }; + + ///Returns a \ref MapFunctor class + + ///This function just returns a \ref MapFunctor class. + ///\relates MapFunctor + template + inline MapFunctor mapFunctor(const M &m) + { + return MapFunctor(m); + } + + + ///Apply all map setting operations to two maps + + ///This map has two \ref concept::WriteMap "writable map" + ///parameters and each write request will be passed to both of them. + ///If \c M1 is also \ref concept::ReadMap "readable", + ///then the read operations will return the + ///corresponding values of \c M1. + /// + ///The \c Key and \c Value will be inherited from \c M1. + ///The \c Key and \c Value of M2 must be convertible from those of \c M1. + + template + class ForkMap + { + typename SmartConstReference::Type m1; + typename SmartConstReference::Type m2; + public: + + typedef True NeedCopy; + typedef typename M1::Key Key; + typedef typename M1::Value Value; + + ///Constructor + + ///\e + /// + ForkMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; + Value operator[](Key k) const {return m1[k];} + void set(Key k,const Value &v) {m1.set(k,v); m2.set(k,v);} + }; + + ///Returns an \ref ForkMap class + + ///This function just returns an \ref ForkMap class. + ///\todo How to call these type of functions? + /// + ///\relates ForkMap + ///\todo Wrong scope in Doxygen when \c \\relates is used + template + inline ForkMap forkMap(const M1 &m1,const M2 &m2) + { + return ForkMap(m1,m2); + } + + /// @} + +} + + +#endif // LEMON_MAPS_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/max_matching.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/max_matching.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,583 @@ +/* -*- C++ -*- + * lemon/max_matching.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_MAX_MATCHING_H +#define LEMON_MAX_MATCHING_H + +#include +#include +#include +#include + +///\ingroup galgs +///\file +///\brief Maximum matching algorithm. + +namespace lemon { + + /// \addtogroup galgs + /// @{ + + ///Edmonds' alternating forest maximum matching algorithm. + + ///This class provides Edmonds' alternating forest matching + ///algorithm. The starting matching (if any) can be passed to the + ///algorithm using read-in functions \ref readNMapNode, \ref + ///readNMapEdge or \ref readEMapBool depending on the container. The + ///resulting maximum matching can be attained by write-out functions + ///\ref writeNMapNode, \ref writeNMapEdge or \ref writeEMapBool + ///depending on the preferred container. + /// + ///The dual side of a matching is a map of the nodes to + ///MaxMatching::pos_enum, having values D, A and C showing the + ///Gallai-Edmonds decomposition of the graph. The nodes in D induce + ///a graph with factor-critical components, the nodes in A form the + ///barrier, and the nodes in C induce a graph having a perfect + ///matching. This decomposition can be attained by calling \ref + ///writePos after running the algorithm. + /// + ///\param Graph The undirected graph type the algorithm runs on. + /// + ///\author Jacint Szabo + template + class MaxMatching { + + protected: + + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + typedef typename Graph::UndirEdge UndirEdge; + typedef typename Graph::UndirEdgeIt UndirEdgeIt; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::IncEdgeIt IncEdgeIt; + + typedef UnionFindEnum UFE; + + public: + + ///Indicates the Gallai-Edmonds decomposition of the graph. + + ///Indicates the Gallai-Edmonds decomposition of the graph, which + ///shows an upper bound on the size of a maximum matching. The + ///nodes with pos_enum \c D induce a graph with factor-critical + ///components, the nodes in \c A form the canonical barrier, and the + ///nodes in \c C induce a graph having a perfect matching. + enum pos_enum { + D=0, + A=1, + C=2 + }; + + protected: + + static const int HEUR_density=2; + const Graph& g; + typename Graph::template NodeMap _mate; + typename Graph::template NodeMap position; + + public: + + MaxMatching(const Graph& _g) : g(_g), _mate(_g,INVALID), position(_g) {} + + ///Runs Edmonds' algorithm. + + ///Runs Edmonds' algorithm for sparse graphs (number of edges < + ///2*number of nodes), and a heuristical Edmonds' algorithm with a + ///heuristic of postponing shrinks for dense graphs. + inline void run(); + + ///Runs Edmonds' algorithm. + + ///If heur=0 it runs Edmonds' algorithm. If heur=1 it runs + ///Edmonds' algorithm with a heuristic of postponing shrinks, + ///giving a faster algorithm for dense graphs. + void runEdmonds( int heur ); + + ///Finds a greedy matching starting from the actual matching. + + ///Starting form the actual matching stored, it finds a maximal + ///greedy matching. + void greedyMatching(); + + ///Returns the size of the actual matching stored. + + ///Returns the size of the actual matching stored. After \ref + ///run() it returns the size of a maximum matching in the graph. + int size() const; + + ///Resets the actual matching to the empty matching. + + ///Resets the actual matching to the empty matching. + /// + void resetMatching(); + + ///Returns the mate of a node in the actual matching. + + ///Returns the mate of a \c node in the actual matching. + ///Returns INVALID if the \c node is not covered by the actual matching. + Node mate(Node& node) const { + return _mate[node]; + } + + ///Reads a matching from a \c Node valued \c Node map. + + ///Reads a matching from a \c Node valued \c Node map. This map + ///must be \e symmetric, i.e. if \c map[u]==v then \c map[v]==u + ///must hold, and \c uv will be an edge of the matching. + template + void readNMapNode(NMapN& map) { + for(NodeIt v(g); v!=INVALID; ++v) { + _mate.set(v,map[v]); + } + } + + ///Writes the stored matching to a \c Node valued \c Node map. + + ///Writes the stored matching to a \c Node valued \c Node map. The + ///resulting map will be \e symmetric, i.e. if \c map[u]==v then \c + ///map[v]==u will hold, and now \c uv is an edge of the matching. + template + void writeNMapNode (NMapN& map) const { + for(NodeIt v(g); v!=INVALID; ++v) { + map.set(v,_mate[v]); + } + } + + ///Reads a matching from an \c UndirEdge valued \c Node map. + + ///Reads a matching from an \c UndirEdge valued \c Node map. \c + ///map[v] must be an \c UndirEdge incident to \c v. This map must + ///have the property that if \c g.oppositeNode(u,map[u])==v then + ///\c \c g.oppositeNode(v,map[v])==u holds, and now some edge + ///joining \c u to \c v will be an edge of the matching. + template + void readNMapEdge(NMapE& map) { + for(NodeIt v(g); v!=INVALID; ++v) { + UndirEdge e=map[v]; + if ( e!=INVALID ) + _mate.set(v,g.oppositeNode(v,e)); + } + } + + ///Writes the matching stored to an \c UndirEdge valued \c Node map. + + ///Writes the stored matching to an \c UndirEdge valued \c Node + ///map. \c map[v] will be an \c UndirEdge incident to \c v. This + ///map will have the property that if \c g.oppositeNode(u,map[u]) + ///== v then \c map[u]==map[v] holds, and now this edge is an edge + ///of the matching. + template + void writeNMapEdge (NMapE& map) const { + typename Graph::template NodeMap todo(g,true); + for(NodeIt v(g); v!=INVALID; ++v) { + if ( todo[v] && _mate[v]!=INVALID ) { + Node u=_mate[v]; + for(IncEdgeIt e(g,v); e!=INVALID; ++e) { + if ( g.runningNode(e) == u ) { + map.set(u,e); + map.set(v,e); + todo.set(u,false); + todo.set(v,false); + break; + } + } + } + } + } + + + ///Reads a matching from a \c bool valued \c Edge map. + + ///Reads a matching from a \c bool valued \c Edge map. This map + ///must have the property that there are no two incident edges \c + ///e, \c f with \c map[e]==map[f]==true. The edges \c e with \c + ///map[e]==true form the matching. + template + void readEMapBool(EMapB& map) { + for(UndirEdgeIt e(g); e!=INVALID; ++e) { + if ( map[e] ) { + Node u=g.source(e); + Node v=g.target(e); + _mate.set(u,v); + _mate.set(v,u); + } + } + } + + + ///Writes the matching stored to a \c bool valued \c Edge map. + + ///Writes the matching stored to a \c bool valued \c Edge + ///map. This map will have the property that there are no two + ///incident edges \c e, \c f with \c map[e]==map[f]==true. The + ///edges \c e with \c map[e]==true form the matching. + template + void writeEMapBool (EMapB& map) const { + for(UndirEdgeIt e(g); e!=INVALID; ++e) map.set(e,false); + + typename Graph::template NodeMap todo(g,true); + for(NodeIt v(g); v!=INVALID; ++v) { + if ( todo[v] && _mate[v]!=INVALID ) { + Node u=_mate[v]; + for(IncEdgeIt e(g,v); e!=INVALID; ++e) { + if ( g.runningNode(e) == u ) { + map.set(e,true); + todo.set(u,false); + todo.set(v,false); + break; + } + } + } + } + } + + + ///Writes the canonical decomposition of the graph after running + ///the algorithm. + + ///After calling any run methods of the class, it writes the + ///Gallai-Edmonds canonical decomposition of the graph. \c map + ///must be a node map of \ref pos_enum 's. + template + void writePos (NMapEnum& map) const { + for(NodeIt v(g); v!=INVALID; ++v) map.set(v,position[v]); + } + + private: + + + void lateShrink(Node v, typename Graph::template NodeMap& ear, + UFE& blossom, UFE& tree); + + void normShrink(Node v, typename Graph::template NodeMap& ear, + UFE& blossom, UFE& tree); + + bool noShrinkStep(Node x, typename Graph::template NodeMap& ear, + UFE& blossom, UFE& tree, std::queue& Q); + + void shrinkStep(Node& top, Node& middle, Node& bottom, + typename Graph::template NodeMap& ear, + UFE& blossom, UFE& tree, std::queue& Q); + + void augment(Node x, typename Graph::template NodeMap& ear, + UFE& blossom, UFE& tree); + + }; + + + // ********************************************************************** + // IMPLEMENTATIONS + // ********************************************************************** + + + template + void MaxMatching::run() { + if ( countUndirEdges(g) < HEUR_density*countNodes(g) ) { + greedyMatching(); + runEdmonds(0); + } else runEdmonds(1); + } + + + template + void MaxMatching::runEdmonds( int heur=1 ) { + + for(NodeIt v(g); v!=INVALID; ++v) + position.set(v,C); + + typename Graph::template NodeMap ear(g,INVALID); + //undefined for the base nodes of the blossoms (i.e. for the + //representative elements of UFE blossom) and for the nodes in C + + typename UFE::MapType blossom_base(g); + UFE blossom(blossom_base); + typename UFE::MapType tree_base(g); + UFE tree(tree_base); + //If these UFE's would be members of the class then also + //blossom_base and tree_base should be a member. + + for(NodeIt v(g); v!=INVALID; ++v) { + if ( position[v]==C && _mate[v]==INVALID ) { + blossom.insert(v); + tree.insert(v); + position.set(v,D); + if ( heur == 1 ) lateShrink( v, ear, blossom, tree ); + else normShrink( v, ear, blossom, tree ); + } + } + } + + + template + void MaxMatching::lateShrink(Node v, typename Graph::template NodeMap& ear, + UFE& blossom, UFE& tree) { + + std::queue Q; //queue of the totally unscanned nodes + Q.push(v); + std::queue R; + //queue of the nodes which must be scanned for a possible shrink + + while ( !Q.empty() ) { + Node x=Q.front(); + Q.pop(); + if ( noShrinkStep( x, ear, blossom, tree, Q ) ) return; + else R.push(x); + } + + while ( !R.empty() ) { + Node x=R.front(); + R.pop(); + + for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) { + Node y=g.runningNode(e); + + if ( position[y] == D && blossom.find(x) != blossom.find(y) ) { + //x and y must be in the same tree + + typename Graph::template NodeMap path(g,false); + + Node b=blossom.find(x); + path.set(b,true); + b=_mate[b]; + while ( b!=INVALID ) { + b=blossom.find(ear[b]); + path.set(b,true); + b=_mate[b]; + } //going till the root + + Node top=y; + Node middle=blossom.find(top); + Node bottom=x; + while ( !path[middle] ) + shrinkStep(top, middle, bottom, ear, blossom, tree, Q); + + Node base=middle; + top=x; + middle=blossom.find(top); + bottom=y; + Node blossom_base=blossom.find(base); + while ( middle!=blossom_base ) + shrinkStep(top, middle, bottom, ear, blossom, tree, Q); + + blossom.makeRep(base); + } // if shrink is needed + + while ( !Q.empty() ) { + Node x=Q.front(); + Q.pop(); + if ( noShrinkStep(x, ear, blossom, tree, Q) ) return; + else R.push(x); + } + } //for e + } // while ( !R.empty() ) + } + + + template + void MaxMatching::normShrink(Node v, + typename Graph::template + NodeMap& ear, + UFE& blossom, UFE& tree) { + std::queue Q; //queue of the unscanned nodes + Q.push(v); + while ( !Q.empty() ) { + + Node x=Q.front(); + Q.pop(); + + for( IncEdgeIt e(g,x); e!=INVALID; ++e ) { + Node y=g.runningNode(e); + + switch ( position[y] ) { + case D: //x and y must be in the same tree + + if ( blossom.find(x) != blossom.find(y) ) { //shrink + typename Graph::template NodeMap path(g,false); + + Node b=blossom.find(x); + path.set(b,true); + b=_mate[b]; + while ( b!=INVALID ) { + b=blossom.find(ear[b]); + path.set(b,true); + b=_mate[b]; + } //going till the root + + Node top=y; + Node middle=blossom.find(top); + Node bottom=x; + while ( !path[middle] ) + shrinkStep(top, middle, bottom, ear, blossom, tree, Q); + + Node base=middle; + top=x; + middle=blossom.find(top); + bottom=y; + Node blossom_base=blossom.find(base); + while ( middle!=blossom_base ) + shrinkStep(top, middle, bottom, ear, blossom, tree, Q); + + blossom.makeRep(base); + } + break; + case C: + if ( _mate[y]!=INVALID ) { //grow + + ear.set(y,x); + Node w=_mate[y]; + blossom.insert(w); + position.set(y,A); + position.set(w,D); + tree.insert(y); + tree.insert(w); + tree.join(y,blossom.find(x)); + tree.join(w,y); + Q.push(w); + } else { //augment + augment(x, ear, blossom, tree); + _mate.set(x,y); + _mate.set(y,x); + return; + } //if + break; + default: break; + } + } + } + } + + template + void MaxMatching::greedyMatching() { + for(NodeIt v(g); v!=INVALID; ++v) + if ( _mate[v]==INVALID ) { + for( IncEdgeIt e(g,v); e!=INVALID ; ++e ) { + Node y=g.runningNode(e); + if ( _mate[y]==INVALID && y!=v ) { + _mate.set(v,y); + _mate.set(y,v); + break; + } + } + } + } + + template + int MaxMatching::size() const { + int s=0; + for(NodeIt v(g); v!=INVALID; ++v) { + if ( _mate[v]!=INVALID ) { + ++s; + } + } + return s/2; + } + + template + void MaxMatching::resetMatching() { + for(NodeIt v(g); v!=INVALID; ++v) + _mate.set(v,INVALID); + } + + template + bool MaxMatching::noShrinkStep(Node x, + typename Graph::template + NodeMap& ear, + UFE& blossom, UFE& tree, + std::queue& Q) { + for( IncEdgeIt e(g,x); e!= INVALID; ++e ) { + Node y=g.runningNode(e); + + if ( position[y]==C ) { + if ( _mate[y]!=INVALID ) { //grow + ear.set(y,x); + Node w=_mate[y]; + blossom.insert(w); + position.set(y,A); + position.set(w,D); + tree.insert(y); + tree.insert(w); + tree.join(y,blossom.find(x)); + tree.join(w,y); + Q.push(w); + } else { //augment + augment(x, ear, blossom, tree); + _mate.set(x,y); + _mate.set(y,x); + return true; + } + } + } + return false; + } + + template + void MaxMatching::shrinkStep(Node& top, Node& middle, Node& bottom, + typename Graph::template + NodeMap& ear, + UFE& blossom, UFE& tree, + std::queue& Q) { + ear.set(top,bottom); + Node t=top; + while ( t!=middle ) { + Node u=_mate[t]; + t=ear[u]; + ear.set(t,u); + } + bottom=_mate[middle]; + position.set(bottom,D); + Q.push(bottom); + top=ear[bottom]; + Node oldmiddle=middle; + middle=blossom.find(top); + tree.erase(bottom); + tree.erase(oldmiddle); + blossom.insert(bottom); + blossom.join(bottom, oldmiddle); + blossom.join(top, oldmiddle); + } + + template + void MaxMatching::augment(Node x, + typename Graph::template NodeMap& ear, + UFE& blossom, UFE& tree) { + Node v=_mate[x]; + while ( v!=INVALID ) { + + Node u=ear[v]; + _mate.set(v,u); + Node tmp=v; + v=_mate[u]; + _mate.set(u,tmp); + } + typename UFE::ItemIt it; + for (tree.first(it,blossom.find(x)); tree.valid(it); tree.next(it)) { + if ( position[it] == D ) { + typename UFE::ItemIt b_it; + for (blossom.first(b_it,it); blossom.valid(b_it); blossom.next(b_it)) { + position.set( b_it ,C); + } + blossom.eraseClass(it); + } else position.set( it ,C); + } + tree.eraseClass(x); + + } + + /// @} + +} //END OF NAMESPACE LEMON + +#endif //LEMON_MAX_MATCHING_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/min_cost_flow.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/min_cost_flow.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,260 @@ +/* -*- C++ -*- + * lemon/min_cost_flow.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_MIN_COST_FLOW_H +#define LEMON_MIN_COST_FLOW_H + +///\ingroup flowalgs +///\file +///\brief An algorithm for finding a flow of value \c k (for small values of \c k) having minimal total cost + + +#include +#include +#include +#include + +namespace lemon { + +/// \addtogroup flowalgs +/// @{ + + ///\brief Implementation of an algorithm for finding a flow of value \c k + ///(for small values of \c k) having minimal total cost between 2 nodes + /// + /// + /// The class \ref lemon::MinCostFlow "MinCostFlow" implements an + /// algorithm for finding a flow of value \c k having minimal total + /// cost from a given source node to a given target node in an + /// edge-weighted directed graph. To this end, the edge-capacities + /// and edge-weights have to be nonnegative. The edge-capacities + /// should be integers, but the edge-weights can be integers, reals + /// or of other comparable numeric type. This algorithm is intended + /// to be used only for small values of \c k, since it is only + /// polynomial in k, not in the length of k (which is log k): in + /// order to find the minimum cost flow of value \c k it finds the + /// minimum cost flow of value \c i for every \c i between 0 and \c + /// k. + /// + ///\param Graph The directed graph type the algorithm runs on. + ///\param LengthMap The type of the length map. + ///\param CapacityMap The capacity map type. + /// + ///\author Attila Bernath + template + class MinCostFlow { + + typedef typename LengthMap::Value Length; + + //Warning: this should be integer type + typedef typename CapacityMap::Value Capacity; + + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::Edge Edge; + typedef typename Graph::OutEdgeIt OutEdgeIt; + typedef typename Graph::template EdgeMap EdgeIntMap; + + typedef ResGraphAdaptor ResGW; + typedef typename ResGW::Edge ResGraphEdge; + + protected: + + const Graph& g; + const LengthMap& length; + const CapacityMap& capacity; + + EdgeIntMap flow; + typedef typename Graph::template NodeMap PotentialMap; + PotentialMap potential; + + Node s; + Node t; + + Length total_length; + + class ModLengthMap { + typedef typename Graph::template NodeMap NodeMap; + const ResGW& g; + const LengthMap &length; + const NodeMap &pot; + public : + typedef typename LengthMap::Key Key; + typedef typename LengthMap::Value Value; + + ModLengthMap(const ResGW& _g, + const LengthMap &_length, const NodeMap &_pot) : + g(_g), /*rev(_rev),*/ length(_length), pot(_pot) { } + + Value operator[](typename ResGW::Edge e) const { + if (g.forward(e)) + return length[e]-(pot[g.target(e)]-pot[g.source(e)]); + else + return -length[e]-(pot[g.target(e)]-pot[g.source(e)]); + } + + }; //ModLengthMap + + ResGW res_graph; + ModLengthMap mod_length; + Dijkstra dijkstra; + + public : + + /*! \brief The constructor of the class. + + \param _g The directed graph the algorithm runs on. + \param _length The length (weight or cost) of the edges. + \param _cap The capacity of the edges. + \param _s Source node. + \param _t Target node. + */ + MinCostFlow(Graph& _g, LengthMap& _length, CapacityMap& _cap, + Node _s, Node _t) : + g(_g), length(_length), capacity(_cap), flow(_g), potential(_g), + s(_s), t(_t), + res_graph(g, capacity, flow), + mod_length(res_graph, length, potential), + dijkstra(res_graph, mod_length) { + reset(); + } + + /*! Tries to augment the flow between s and t by 1. + The return value shows if the augmentation is successful. + */ + bool augment() { + dijkstra.run(s); + if (!dijkstra.reached(t)) { + + //Unsuccessful augmentation. + return false; + } else { + + //We have to change the potential + for(typename ResGW::NodeIt n(res_graph); n!=INVALID; ++n) + potential.set(n, potential[n]+dijkstra.distMap()[n]); + + //Augmenting on the shortest path + Node n=t; + ResGraphEdge e; + while (n!=s){ + e = dijkstra.pred(n); + n = dijkstra.predNode(n); + res_graph.augment(e,1); + //Let's update the total length + if (res_graph.forward(e)) + total_length += length[e]; + else + total_length -= length[e]; + } + + return true; + } + } + + /*! \brief Runs the algorithm. + + Runs the algorithm. + Returns k if there is a flow of value at least k from s to t. + Otherwise it returns the maximum value of a flow from s to t. + + \param k The value of the flow we are looking for. + + \todo May be it does make sense to be able to start with a nonzero + feasible primal-dual solution pair as well. + + \todo If the actual flow value is bigger than k, then everything is + cleared and the algorithm starts from zero flow. Is it a good approach? + */ + int run(int k) { + if (flowValue()>k) reset(); + while (flowValue() 0 && fl_e != 0) + return false; + if (mod_pot < 0 && fl_e != capacity[e]) + return false; + } + } + return true; + } + + }; //class MinCostFlow + + ///@} + +} //namespace lemon + +#endif //LEMON_MIN_COST_FLOW_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/path.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/path.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,703 @@ +/* -*- C++ -*- + * lemon/path.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +/** +@defgroup paths Path Structures +@ingroup datas +\brief Path structures implemented in LEMON. + +LEMON provides flexible data structures +to work with paths. + +All of them have the same interface, especially they can be built or extended +using a standard Builder subclass. This make is easy to have e.g. the Dijkstra +algorithm to store its result in any kind of path structure. + +\sa lemon::concept::Path + +*/ + +///\ingroup paths +///\file +///\brief Classes for representing paths in graphs. +/// +///\todo Iterators have obsolete style + +#ifndef LEMON_PATH_H +#define LEMON_PATH_H + +#include +#include +#include + +#include + +namespace lemon { + + /// \addtogroup paths + /// @{ + + + //! \brief A structure for representing directed paths in a graph. + //! + //! A structure for representing directed path in a graph. + //! \param Graph The graph type in which the path is. + //! \param DM DebugMode, defaults to DefaultDebugMode. + //! + //! In a sense, the path can be treated as a graph, for is has \c NodeIt + //! and \c EdgeIt with the same usage. These types converts to the \c Node + //! and \c Edge of the original graph. + //! + //! \todo Thoroughfully check all the range and consistency tests. + template + class DirPath { + public: + /// Edge type of the underlying graph. + typedef typename Graph::Edge GraphEdge; + /// Node type of the underlying graph. + typedef typename Graph::Node GraphNode; + class NodeIt; + class EdgeIt; + + protected: + const Graph *gr; + typedef std::vector Container; + Container edges; + + public: + + /// \param _G The graph in which the path is. + /// + DirPath(const Graph &_G) : gr(&_G) {} + + /// \brief Subpath constructor. + /// + /// Subpath defined by two nodes. + /// \warning It is an error if the two edges are not in order! + DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b) { + gr = P.gr; + edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); + } + + /// \brief Subpath constructor. + /// + /// Subpath defined by two edges. Contains edges in [a,b) + /// \warning It is an error if the two edges are not in order! + DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b) { + gr = P.gr; + edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); + } + + /// Length of the path. + int length() const { return edges.size(); } + /// Returns whether the path is empty. + bool empty() const { return edges.empty(); } + + /// Resets the path to an empty path. + void clear() { edges.clear(); } + + /// \brief Starting point of the path. + /// + /// Starting point of the path. + /// Returns INVALID if the path is empty. + GraphNode source() const { + return empty() ? INVALID : gr->source(edges[0]); + } + /// \brief End point of the path. + /// + /// End point of the path. + /// Returns INVALID if the path is empty. + GraphNode target() const { + return empty() ? INVALID : gr->target(edges[length()-1]); + } + + /// \brief Initializes node or edge iterator to point to the first + /// node or edge. + /// + /// \sa nth + template + It& first(It &i) const { return i=It(*this); } + + /// \brief Initializes node iterator to point to the node of a given index. + NodeIt& nth(NodeIt &i, int n) const { + return i=NodeIt(*this, n); + } + + /// \brief Initializes edge iterator to point to the edge of a given index. + EdgeIt& nth(EdgeIt &i, int n) const { + return i=EdgeIt(*this, n); + } + + /// \brief Returns node iterator pointing to the target node of the + /// given edge iterator. + NodeIt target(const EdgeIt& e) const { + return NodeIt(*this, e.idx+1); + } + + /// \brief Returns node iterator pointing to the source node of the + /// given edge iterator. + NodeIt source(const EdgeIt& e) const { + return NodeIt(*this, e.idx); + } + + + /* Iterator classes */ + + /** + * \brief Iterator class to iterate on the edges of the paths + * + * This class is used to iterate on the edges of the paths + * + * Of course it converts to Graph::Edge + * + */ + class EdgeIt { + friend class DirPath; + + int idx; + const DirPath *p; + public: + /// Default constructor + EdgeIt() {} + /// Invalid constructor + EdgeIt(Invalid) : idx(-1), p(0) {} + /// Constructor with starting point + EdgeIt(const DirPath &_p, int _idx = 0) : + idx(_idx), p(&_p) { validate(); } + + ///Validity check + bool valid() const { return idx!=-1; } + + ///Conversion to Graph::Edge + operator GraphEdge () const { + return valid() ? p->edges[idx] : INVALID; + } + + /// Next edge + EdgeIt& operator++() { ++idx; validate(); return *this; } + + /// Comparison operator + bool operator==(const EdgeIt& e) const { return idx==e.idx; } + /// Comparison operator + bool operator!=(const EdgeIt& e) const { return idx!=e.idx; } + /// Comparison operator + bool operator<(const EdgeIt& e) const { return idx= p->length() ) idx=-1; } + }; + + /** + * \brief Iterator class to iterate on the nodes of the paths + * + * This class is used to iterate on the nodes of the paths + * + * Of course it converts to Graph::Node + * + */ + class NodeIt { + friend class DirPath; + + int idx; + const DirPath *p; + public: + /// Default constructor + NodeIt() {} + /// Invalid constructor + NodeIt(Invalid) : idx(-1), p(0) {} + /// Constructor with starting point + NodeIt(const DirPath &_p, int _idx = 0) : + idx(_idx), p(&_p) { validate(); } + + ///Validity check + bool valid() const { return idx!=-1; } + + ///Conversion to Graph::Node + operator const GraphNode& () const { + if(idx >= p->length()) + return p->target(); + else if(idx >= 0) + return p->gr->source(p->edges[idx]); + else + return INVALID; + } + /// Next node + NodeIt& operator++() { ++idx; validate(); return *this; } + + /// Comparison operator + bool operator==(const NodeIt& e) const { return idx==e.idx; } + /// Comparison operator + bool operator!=(const NodeIt& e) const { return idx!=e.idx; } + /// Comparison operator + bool operator<(const NodeIt& e) const { return idx p->length() ) idx=-1; } + }; + + friend class Builder; + + /** + * \brief Class to build paths + * + * This class is used to fill a path with edges. + * + * You can push new edges to the front and to the back of the path in + * arbitrary order then you should commit these changes to the graph. + * + * Fundamentally, for most "Paths" (classes fulfilling the + * PathConcept) while the builder is active (after the first modifying + * operation and until the commit()) the original Path is in a + * "transitional" state (operations on it have undefined result). But + * in the case of DirPath the original path remains unchanged until the + * commit. However we don't recomend that you use this feature. + */ + class Builder { + DirPath &P; + Container front, back; + + public: + ///\param _p the path you want to fill in. + /// + Builder(DirPath &_p) : P(_p) {} + + /// Sets the starting node of the path. + + /// Sets the starting node of the path. Edge added to the path + /// afterwards have to be incident to this node. + /// It should be called if and only if + /// the path is empty and before any call to + /// \ref pushFront() or \ref pushBack() + void setStartNode(const GraphNode &) {} + + ///Push a new edge to the front of the path + + ///Push a new edge to the front of the path. + ///\sa setStartNode + void pushFront(const GraphEdge& e) { + front.push_back(e); + } + + ///Push a new edge to the back of the path + + ///Push a new edge to the back of the path. + ///\sa setStartNode + void pushBack(const GraphEdge& e) { + back.push_back(e); + } + + ///Commit the changes to the path. + void commit() { + if( !front.empty() || !back.empty() ) { + Container tmp; + tmp.reserve(front.size()+back.size()+P.length()); + tmp.insert(tmp.end(), front.rbegin(), front.rend()); + tmp.insert(tmp.end(), P.edges.begin(), P.edges.end()); + tmp.insert(tmp.end(), back.begin(), back.end()); + P.edges.swap(tmp); + front.clear(); + back.clear(); + } + } + + ///Reserve storage for the builder in advance. + + ///If you know a reasonable upper bound of the number of the edges + ///to add to the front, using this function you can speed up the building. + + void reserveFront(size_t r) {front.reserve(r);} + + ///Reserve storage for the builder in advance. + + ///If you know a reasonable upper bound of the number of the edges + ///to add to the back, using this function you can speed up the building. + + void reserveBack(size_t r) {back.reserve(r);} + + private: + bool empty() { + return front.empty() && back.empty() && P.empty(); + } + + GraphNode source() const { + if( ! front.empty() ) + return P.gr->source(front[front.size()-1]); + else if( ! P.empty() ) + return P.gr->source(P.edges[0]); + else if( ! back.empty() ) + return P.gr->source(back[0]); + else + return INVALID; + } + GraphNode target() const { + if( ! back.empty() ) + return P.gr->target(back[back.size()-1]); + else if( ! P.empty() ) + return P.gr->target(P.edges[P.length()-1]); + else if( ! front.empty() ) + return P.gr->target(front[0]); + else + return INVALID; + } + + }; + + }; + + + + + + + + + + + /**********************************************************************/ + + + //! \brief A structure for representing undirected path in a graph. + //! + //! A structure for representing undirected path in a graph. Ie. this is + //! a path in a \e directed graph but the edges should not be directed + //! forward. + //! + //! \param Graph The graph type in which the path is. + //! \param DM DebugMode, defaults to DefaultDebugMode. + //! + //! In a sense, the path can be treated as a graph, for is has \c NodeIt + //! and \c EdgeIt with the same usage. These types converts to the \c Node + //! and \c Edge of the original graph. + //! + //! \todo Thoroughfully check all the range and consistency tests. + template + class UndirPath { + public: + /// Edge type of the underlying graph. + typedef typename Graph::Edge GraphEdge; + /// Node type of the underlying graph. + typedef typename Graph::Node GraphNode; + class NodeIt; + class EdgeIt; + + protected: + const Graph *gr; + typedef std::vector Container; + Container edges; + + public: + + /// \param _G The graph in which the path is. + /// + UndirPath(const Graph &_G) : gr(&_G) {} + + /// \brief Subpath constructor. + /// + /// Subpath defined by two nodes. + /// \warning It is an error if the two edges are not in order! + UndirPath(const UndirPath &P, const NodeIt &a, const NodeIt &b) { + gr = P.gr; + edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); + } + + /// \brief Subpath constructor. + /// + /// Subpath defined by two edges. Contains edges in [a,b) + /// \warning It is an error if the two edges are not in order! + UndirPath(const UndirPath &P, const EdgeIt &a, const EdgeIt &b) { + gr = P.gr; + edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); + } + + /// Length of the path. + size_t length() const { return edges.size(); } + /// Returns whether the path is empty. + bool empty() const { return edges.empty(); } + + /// Resets the path to an empty path. + void clear() { edges.clear(); } + + /// \brief Starting point of the path. + /// + /// Starting point of the path. + /// Returns INVALID if the path is empty. + GraphNode source() const { + return empty() ? INVALID : gr->source(edges[0]); + } + /// \brief End point of the path. + /// + /// End point of the path. + /// Returns INVALID if the path is empty. + GraphNode target() const { + return empty() ? INVALID : gr->target(edges[length()-1]); + } + + /// \brief Initializes node or edge iterator to point to the first + /// node or edge. + /// + /// \sa nth + template + It& first(It &i) const { return i=It(*this); } + + /// \brief Initializes node iterator to point to the node of a given index. + NodeIt& nth(NodeIt &i, int n) const { + return i=NodeIt(*this, n); + } + + /// \brief Initializes edge iterator to point to the edge of a given index. + EdgeIt& nth(EdgeIt &i, int n) const { + return i=EdgeIt(*this, n); + } + + /// Checks validity of a node or edge iterator. + template + static + bool valid(const It &i) { return i.valid(); } + + /// Steps the given node or edge iterator. + template + static + It& next(It &e) { + return ++e; + } + + /// \brief Returns node iterator pointing to the target node of the + /// given edge iterator. + NodeIt target(const EdgeIt& e) const { + return NodeIt(*this, e.idx+1); + } + + /// \brief Returns node iterator pointing to the source node of the + /// given edge iterator. + NodeIt source(const EdgeIt& e) const { + return NodeIt(*this, e.idx); + } + + + + /** + * \brief Iterator class to iterate on the edges of the paths + * + * This class is used to iterate on the edges of the paths + * + * Of course it converts to Graph::Edge + * + * \todo Its interface differs from the standard edge iterator. + * Yes, it shouldn't. + */ + class EdgeIt { + friend class UndirPath; + + int idx; + const UndirPath *p; + public: + /// Default constructor + EdgeIt() {} + /// Invalid constructor + EdgeIt(Invalid) : idx(-1), p(0) {} + /// Constructor with starting point + EdgeIt(const UndirPath &_p, int _idx = 0) : + idx(_idx), p(&_p) { validate(); } + + ///Validity check + bool valid() const { return idx!=-1; } + + ///Conversion to Graph::Edge + operator GraphEdge () const { + return valid() ? p->edges[idx] : INVALID; + } + /// Next edge + EdgeIt& operator++() { ++idx; validate(); return *this; } + + /// Comparison operator + bool operator==(const EdgeIt& e) const { return idx==e.idx; } + /// Comparison operator + bool operator!=(const EdgeIt& e) const { return idx!=e.idx; } + /// Comparison operator + bool operator<(const EdgeIt& e) const { return idx= p->length() ) idx=-1; } + }; + + /** + * \brief Iterator class to iterate on the nodes of the paths + * + * This class is used to iterate on the nodes of the paths + * + * Of course it converts to Graph::Node + * + * \todo Its interface differs from the standard node iterator. + * Yes, it shouldn't. + */ + class NodeIt { + friend class UndirPath; + + int idx; + const UndirPath *p; + public: + /// Default constructor + NodeIt() {} + /// Invalid constructor + NodeIt(Invalid) : idx(-1), p(0) {} + /// Constructor with starting point + NodeIt(const UndirPath &_p, int _idx = 0) : + idx(_idx), p(&_p) { validate(); } + + ///Validity check + bool valid() const { return idx!=-1; } + + ///Conversion to Graph::Node + operator const GraphNode& () const { + if(idx >= p->length()) + return p->target(); + else if(idx >= 0) + return p->gr->source(p->edges[idx]); + else + return INVALID; + } + /// Next node + NodeIt& operator++() { ++idx; validate(); return *this; } + + /// Comparison operator + bool operator==(const NodeIt& e) const { return idx==e.idx; } + /// Comparison operator + bool operator!=(const NodeIt& e) const { return idx!=e.idx; } + /// Comparison operator + bool operator<(const NodeIt& e) const { return idx p->length() ) idx=-1; } + }; + + friend class Builder; + + /** + * \brief Class to build paths + * + * This class is used to fill a path with edges. + * + * You can push new edges to the front and to the back of the path in + * arbitrary order then you should commit these changes to the graph. + * + * Fundamentally, for most "Paths" (classes fulfilling the + * PathConcept) while the builder is active (after the first modifying + * operation and until the commit()) the original Path is in a + * "transitional" state (operations ot it have undefined result). But + * in the case of UndirPath the original path is unchanged until the + * commit. However we don't recomend that you use this feature. + */ + class Builder { + UndirPath &P; + Container front, back; + + public: + ///\param _p the path you want to fill in. + /// + Builder(UndirPath &_p) : P(_p) {} + + /// Sets the starting node of the path. + + /// Sets the starting node of the path. Edge added to the path + /// afterwards have to be incident to this node. + /// It should be called if and only if + /// the path is empty and before any call to + /// \ref pushFront() or \ref pushBack() + void setStartNode(const GraphNode &) {} + + ///Push a new edge to the front of the path + + ///Push a new edge to the front of the path. + ///\sa setStartNode + void pushFront(const GraphEdge& e) { + front.push_back(e); + } + + ///Push a new edge to the back of the path + + ///Push a new edge to the back of the path. + ///\sa setStartNode + void pushBack(const GraphEdge& e) { + back.push_back(e); + } + + ///Commit the changes to the path. + void commit() { + if( !(front.empty() && back.empty()) ) { + Container tmp; + tmp.reserve(front.size()+back.size()+P.length()); + tmp.insert(tmp.end(), front.rbegin(), front.rend()); + tmp.insert(tmp.end(), P.edges.begin(), P.edges.end()); + tmp.insert(tmp.end(), back.begin(), back.end()); + P.edges.swap(tmp); + front.clear(); + back.clear(); + } + } + + + ///Reserve storage for the builder in advance. + + ///If you know a reasonable upper bound of the number of the edges + ///to add to the front, using this function you can speed up the building. + + void reserveFront(size_t r) {front.reserve(r);} + + ///Reserve storage for the builder in advance. + + ///If you know a reasonable upper bound of the number of the edges + ///to add to the back, using this function you can speed up the building. + + void reserveBack(size_t r) {back.reserve(r);} + + private: + bool empty() { + return front.empty() && back.empty() && P.empty(); + } + + GraphNode source() const { + if( ! front.empty() ) + return P.gr->source(front[front.size()-1]); + else if( ! P.empty() ) + return P.gr->source(P.edges[0]); + else if( ! back.empty() ) + return P.gr->source(back[0]); + else + return INVALID; + } + GraphNode target() const { + if( ! back.empty() ) + return P.gr->target(back[back.size()-1]); + else if( ! P.empty() ) + return P.gr->target(P.edges[P.length()-1]); + else if( ! front.empty() ) + return P.gr->target(front[0]); + else + return INVALID; + } + + }; + + }; + + + ///@} + +} // namespace lemon + +#endif // LEMON_PATH_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/preflow.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/preflow.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,868 @@ +/* -*- C++ -*- + * lemon/preflow.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_PREFLOW_H +#define LEMON_PREFLOW_H + +#include +#include + +#include +#include +#include + +/// \file +/// \ingroup flowalgs +/// Implementation of the preflow algorithm. + +namespace lemon { + + /// \addtogroup flowalgs + /// @{ + + ///%Preflow algorithms class. + + ///This class provides an implementation of the \e preflow \e + ///algorithm producing a flow of maximum value in a directed + ///graph. The preflow algorithms are the fastest known max flow algorithms + ///up to now. The \e source node, the \e target node, the \e + ///capacity of the edges and the \e starting \e flow value of the + ///edges should be passed to the algorithm through the + ///constructor. It is possible to change these quantities using the + ///functions \ref source, \ref target, \ref capacityMap and \ref + ///flowMap. + /// + ///After running \ref lemon::Preflow::phase1() "phase1()" + ///or \ref lemon::Preflow::run() "run()", the maximal flow + ///value can be obtained by calling \ref flowValue(). The minimum + ///value cut can be written into a bool node map by + ///calling \ref minCut(). (\ref minMinCut() and \ref maxMinCut() writes + ///the inclusionwise minimum and maximum of the minimum value cuts, + ///resp.) + /// + ///\param Graph The directed graph type the algorithm runs on. + ///\param Num The number type of the capacities and the flow values. + ///\param CapacityMap The capacity map type. + ///\param FlowMap The flow map type. + /// + ///\author Jacint Szabo + ///\todo Second template parameter is superfluous + template , + typename FlowMap=typename Graph::template EdgeMap > + class Preflow { + protected: + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::OutEdgeIt OutEdgeIt; + typedef typename Graph::InEdgeIt InEdgeIt; + + typedef typename Graph::template NodeMap NNMap; + typedef typename std::vector VecNode; + + const Graph* _g; + Node _source; + Node _target; + const CapacityMap* _capacity; + FlowMap* _flow; + int _node_num; //the number of nodes of G + + typename Graph::template NodeMap level; + typename Graph::template NodeMap excess; + + // constants used for heuristics + static const int H0=20; + static const int H1=1; + + public: + + ///Indicates the property of the starting flow map. + + ///Indicates the property of the starting flow map. + ///The meanings are as follows: + ///- \c ZERO_FLOW: constant zero flow + ///- \c GEN_FLOW: any flow, i.e. the sum of the in-flows equals to + ///the sum of the out-flows in every node except the \e source and + ///the \e target. + ///- \c PRE_FLOW: any preflow, i.e. the sum of the in-flows is at + ///least the sum of the out-flows in every node except the \e source. + ///- \c NO_FLOW: indicates an unspecified edge map. \c flow will be + ///set to the constant zero flow in the beginning of + ///the algorithm in this case. + /// + enum FlowEnum{ + NO_FLOW, + ZERO_FLOW, + GEN_FLOW, + PRE_FLOW + }; + + ///Indicates the state of the preflow algorithm. + + ///Indicates the state of the preflow algorithm. + ///The meanings are as follows: + ///- \c AFTER_NOTHING: before running the algorithm or + /// at an unspecified state. + ///- \c AFTER_PREFLOW_PHASE_1: right after running \c phase1 + ///- \c AFTER_PREFLOW_PHASE_2: after running \ref phase2() + /// + enum StatusEnum { + AFTER_NOTHING, + AFTER_PREFLOW_PHASE_1, + AFTER_PREFLOW_PHASE_2 + }; + + protected: + FlowEnum flow_prop; + StatusEnum status; // Do not needle this flag only if necessary. + + public: + ///The constructor of the class. + + ///The constructor of the class. + ///\param _gr The directed graph the algorithm runs on. + ///\param _s The source node. + ///\param _t The target node. + ///\param _cap The capacity of the edges. + ///\param _f The flow of the edges. + ///Except the graph, all of these parameters can be reset by + ///calling \ref source, \ref target, \ref capacityMap and \ref + ///flowMap, resp. + Preflow(const Graph& _gr, Node _s, Node _t, + const CapacityMap& _cap, FlowMap& _f) : + _g(&_gr), _source(_s), _target(_t), _capacity(&_cap), + _flow(&_f), _node_num(countNodes(_gr)), level(_gr), excess(_gr,0), + flow_prop(NO_FLOW), status(AFTER_NOTHING) { } + + + + ///Runs the preflow algorithm. + + ///Runs the preflow algorithm. + /// + void run() { + phase1(flow_prop); + phase2(); + } + + ///Runs the preflow algorithm. + + ///Runs the preflow algorithm. + ///\pre The starting flow map must be + /// - a constant zero flow if \c fp is \c ZERO_FLOW, + /// - an arbitrary flow if \c fp is \c GEN_FLOW, + /// - an arbitrary preflow if \c fp is \c PRE_FLOW, + /// - any map if \c fp is NO_FLOW. + ///If the starting flow map is a flow or a preflow then + ///the algorithm terminates faster. + void run(FlowEnum fp) { + flow_prop=fp; + run(); + } + + ///Runs the first phase of the preflow algorithm. + + ///The preflow algorithm consists of two phases, this method runs + ///the first phase. After the first phase the maximum flow value + ///and a minimum value cut can already be computed, although a + ///maximum flow is not yet obtained. So after calling this method + ///\ref flowValue returns the value of a maximum flow and \ref + ///minCut returns a minimum cut. + ///\warning \ref minMinCut and \ref maxMinCut do not give minimum + ///value cuts unless calling \ref phase2. + ///\pre The starting flow must be + ///- a constant zero flow if \c fp is \c ZERO_FLOW, + ///- an arbitary flow if \c fp is \c GEN_FLOW, + ///- an arbitary preflow if \c fp is \c PRE_FLOW, + ///- any map if \c fp is NO_FLOW. + void phase1(FlowEnum fp) + { + flow_prop=fp; + phase1(); + } + + + ///Runs the first phase of the preflow algorithm. + + ///The preflow algorithm consists of two phases, this method runs + ///the first phase. After the first phase the maximum flow value + ///and a minimum value cut can already be computed, although a + ///maximum flow is not yet obtained. So after calling this method + ///\ref flowValue returns the value of a maximum flow and \ref + ///minCut returns a minimum cut. + ///\warning \ref minCut(), \ref minMinCut() and \ref maxMinCut() do not + ///give minimum value cuts unless calling \ref phase2(). + void phase1() + { + int heur0=(int)(H0*_node_num); //time while running 'bound decrease' + int heur1=(int)(H1*_node_num); //time while running 'highest label' + int heur=heur1; //starting time interval (#of relabels) + int numrelabel=0; + + bool what_heur=1; + //It is 0 in case 'bound decrease' and 1 in case 'highest label' + + bool end=false; + //Needed for 'bound decrease', true means no active + //nodes are above bound b. + + int k=_node_num-2; //bound on the highest level under n containing a node + int b=k; //bound on the highest level under n of an active node + + VecNode first(_node_num, INVALID); + NNMap next(*_g, INVALID); + + NNMap left(*_g, INVALID); + NNMap right(*_g, INVALID); + VecNode level_list(_node_num,INVALID); + //List of the nodes in level i 0 ) { + b=k; + end=true; + } else break; + } + + if ( first[b]==INVALID ) --b; + else { + end=false; + Node w=first[b]; + first[b]=next[w]; + int newlevel=push(w, next, first); + if ( excess[w] > 0 ) relabel(w, newlevel, first, next, level_list, + left, right, b, k, what_heur); + + ++numrelabel; + if ( numrelabel >= heur ) { + numrelabel=0; + if ( what_heur ) { + what_heur=0; + heur=heur0; + end=false; + } else { + what_heur=1; + heur=heur1; + b=k; + } + } + } + } + flow_prop=PRE_FLOW; + status=AFTER_PREFLOW_PHASE_1; + } + // Heuristics: + // 2 phase + // gap + // list 'level_list' on the nodes on level i implemented by hand + // stack 'active' on the active nodes on level i + // runs heuristic 'highest label' for H1*n relabels + // runs heuristic 'bound decrease' for H0*n relabels, + // starts with 'highest label' + // Parameters H0 and H1 are initialized to 20 and 1. + + + ///Runs the second phase of the preflow algorithm. + + ///The preflow algorithm consists of two phases, this method runs + ///the second phase. After calling \ref phase1 and then \ref + ///phase2, \ref flow contains a maximum flow, \ref flowValue + ///returns the value of a maximum flow, \ref minCut returns a + ///minimum cut, while the methods \ref minMinCut and \ref + ///maxMinCut return the inclusionwise minimum and maximum cuts of + ///minimum value, resp. \pre \ref phase1 must be called before. + void phase2() + { + + int k=_node_num-2; //bound on the highest level under n containing a node + int b=k; //bound on the highest level under n of an active node + + + VecNode first(_node_num, INVALID); + NNMap next(*_g, INVALID); + level.set(_source,0); + std::queue bfs_queue; + bfs_queue.push(_source); + + while ( !bfs_queue.empty() ) { + + Node v=bfs_queue.front(); + bfs_queue.pop(); + int l=level[v]+1; + + for(InEdgeIt e(*_g,v); e!=INVALID; ++e) { + if ( (*_capacity)[e] <= (*_flow)[e] ) continue; + Node u=_g->source(e); + if ( level[u] >= _node_num ) { + bfs_queue.push(u); + level.set(u, l); + if ( excess[u] > 0 ) { + next.set(u,first[l]); + first[l]=u; + } + } + } + + for(OutEdgeIt e(*_g,v); e!=INVALID; ++e) { + if ( 0 >= (*_flow)[e] ) continue; + Node u=_g->target(e); + if ( level[u] >= _node_num ) { + bfs_queue.push(u); + level.set(u, l); + if ( excess[u] > 0 ) { + next.set(u,first[l]); + first[l]=u; + } + } + } + } + b=_node_num-2; + + while ( true ) { + + if ( b == 0 ) break; + if ( first[b]==INVALID ) --b; + else { + Node w=first[b]; + first[b]=next[w]; + int newlevel=push(w,next, first); + + //relabel + if ( excess[w] > 0 ) { + level.set(w,++newlevel); + next.set(w,first[newlevel]); + first[newlevel]=w; + b=newlevel; + } + } + } // while(true) + flow_prop=GEN_FLOW; + status=AFTER_PREFLOW_PHASE_2; + } + + /// Returns the value of the maximum flow. + + /// Returns the value of the maximum flow by returning the excess + /// of the target node \c t. This value equals to the value of + /// the maximum flow already after running \ref phase1. + Num flowValue() const { + return excess[_target]; + } + + + ///Returns a minimum value cut. + + ///Sets \c M to the characteristic vector of a minimum value + ///cut. This method can be called both after running \ref + ///phase1 and \ref phase2. It is much faster after + ///\ref phase1. \pre M should be a bool-valued node-map. \pre + ///If \ref minCut() is called after \ref phase2() then M should + ///be initialized to false. + template + void minCut(_CutMap& M) const { + switch ( status ) { + case AFTER_PREFLOW_PHASE_1: + for(NodeIt v(*_g); v!=INVALID; ++v) { + if (level[v] < _node_num) { + M.set(v, false); + } else { + M.set(v, true); + } + } + break; + case AFTER_PREFLOW_PHASE_2: + minMinCut(M); + break; + case AFTER_NOTHING: + break; + } + } + + ///Returns the inclusionwise minimum of the minimum value cuts. + + ///Sets \c M to the characteristic vector of the minimum value cut + ///which is inclusionwise minimum. It is computed by processing a + ///bfs from the source node \c s in the residual graph. \pre M + ///should be a node map of bools initialized to false. \pre \ref + ///phase2 should already be run. + template + void minMinCut(_CutMap& M) const { + + std::queue queue; + M.set(_source,true); + queue.push(_source); + + while (!queue.empty()) { + Node w=queue.front(); + queue.pop(); + + for(OutEdgeIt e(*_g,w) ; e!=INVALID; ++e) { + Node v=_g->target(e); + if (!M[v] && (*_flow)[e] < (*_capacity)[e] ) { + queue.push(v); + M.set(v, true); + } + } + + for(InEdgeIt e(*_g,w) ; e!=INVALID; ++e) { + Node v=_g->source(e); + if (!M[v] && (*_flow)[e] > 0 ) { + queue.push(v); + M.set(v, true); + } + } + } + } + + ///Returns the inclusionwise maximum of the minimum value cuts. + + ///Sets \c M to the characteristic vector of the minimum value cut + ///which is inclusionwise maximum. It is computed by processing a + ///backward bfs from the target node \c t in the residual graph. + ///\pre \ref phase2() or run() should already be run. + template + void maxMinCut(_CutMap& M) const { + + for(NodeIt v(*_g) ; v!=INVALID; ++v) M.set(v, true); + + std::queue queue; + + M.set(_target,false); + queue.push(_target); + + while (!queue.empty()) { + Node w=queue.front(); + queue.pop(); + + for(InEdgeIt e(*_g,w) ; e!=INVALID; ++e) { + Node v=_g->source(e); + if (M[v] && (*_flow)[e] < (*_capacity)[e] ) { + queue.push(v); + M.set(v, false); + } + } + + for(OutEdgeIt e(*_g,w) ; e!=INVALID; ++e) { + Node v=_g->target(e); + if (M[v] && (*_flow)[e] > 0 ) { + queue.push(v); + M.set(v, false); + } + } + } + } + + ///Sets the source node to \c _s. + + ///Sets the source node to \c _s. + /// + void source(Node _s) { + _source=_s; + if ( flow_prop != ZERO_FLOW ) flow_prop=NO_FLOW; + status=AFTER_NOTHING; + } + + ///Returns the source node. + + ///Returns the source node. + /// + Node source() const { + return _source; + } + + ///Sets the target node to \c _t. + + ///Sets the target node to \c _t. + /// + void target(Node _t) { + _target=_t; + if ( flow_prop == GEN_FLOW ) flow_prop=PRE_FLOW; + status=AFTER_NOTHING; + } + + ///Returns the target node. + + ///Returns the target node. + /// + Node target() const { + return _target; + } + + /// Sets the edge map of the capacities to _cap. + + /// Sets the edge map of the capacities to _cap. + /// + void capacityMap(const CapacityMap& _cap) { + _capacity=&_cap; + status=AFTER_NOTHING; + } + /// Returns a reference to capacity map. + + /// Returns a reference to capacity map. + /// + const CapacityMap &capacityMap() const { + return *_capacity; + } + + /// Sets the edge map of the flows to _flow. + + /// Sets the edge map of the flows to _flow. + /// + void flowMap(FlowMap& _f) { + _flow=&_f; + flow_prop=NO_FLOW; + status=AFTER_NOTHING; + } + + /// Returns a reference to flow map. + + /// Returns a reference to flow map. + /// + const FlowMap &flowMap() const { + return *_flow; + } + + private: + + int push(Node w, NNMap& next, VecNode& first) { + + int lev=level[w]; + Num exc=excess[w]; + int newlevel=_node_num; //bound on the next level of w + + for(OutEdgeIt e(*_g,w) ; e!=INVALID; ++e) { + if ( (*_flow)[e] >= (*_capacity)[e] ) continue; + Node v=_g->target(e); + + if( lev > level[v] ) { //Push is allowed now + + if ( excess[v]<=0 && v!=_target && v!=_source ) { + next.set(v,first[level[v]]); + first[level[v]]=v; + } + + Num cap=(*_capacity)[e]; + Num flo=(*_flow)[e]; + Num remcap=cap-flo; + + if ( remcap >= exc ) { //A nonsaturating push. + + _flow->set(e, flo+exc); + excess.set(v, excess[v]+exc); + exc=0; + break; + + } else { //A saturating push. + _flow->set(e, cap); + excess.set(v, excess[v]+remcap); + exc-=remcap; + } + } else if ( newlevel > level[v] ) newlevel = level[v]; + } //for out edges wv + + if ( exc > 0 ) { + for(InEdgeIt e(*_g,w) ; e!=INVALID; ++e) { + + if( (*_flow)[e] <= 0 ) continue; + Node v=_g->source(e); + + if( lev > level[v] ) { //Push is allowed now + + if ( excess[v]<=0 && v!=_target && v!=_source ) { + next.set(v,first[level[v]]); + first[level[v]]=v; + } + + Num flo=(*_flow)[e]; + + if ( flo >= exc ) { //A nonsaturating push. + + _flow->set(e, flo-exc); + excess.set(v, excess[v]+exc); + exc=0; + break; + } else { //A saturating push. + + excess.set(v, excess[v]+flo); + exc-=flo; + _flow->set(e,0); + } + } else if ( newlevel > level[v] ) newlevel = level[v]; + } //for in edges vw + + } // if w still has excess after the out edge for cycle + + excess.set(w, exc); + + return newlevel; + } + + + + void preflowPreproc(VecNode& first, NNMap& next, + VecNode& level_list, NNMap& left, NNMap& right) + { + for(NodeIt v(*_g); v!=INVALID; ++v) level.set(v,_node_num); + std::queue bfs_queue; + + if ( flow_prop == GEN_FLOW || flow_prop == PRE_FLOW ) { + //Reverse_bfs from t in the residual graph, + //to find the starting level. + level.set(_target,0); + bfs_queue.push(_target); + + while ( !bfs_queue.empty() ) { + + Node v=bfs_queue.front(); + bfs_queue.pop(); + int l=level[v]+1; + + for(InEdgeIt e(*_g,v) ; e!=INVALID; ++e) { + if ( (*_capacity)[e] <= (*_flow)[e] ) continue; + Node w=_g->source(e); + if ( level[w] == _node_num && w != _source ) { + bfs_queue.push(w); + Node z=level_list[l]; + if ( z!=INVALID ) left.set(z,w); + right.set(w,z); + level_list[l]=w; + level.set(w, l); + } + } + + for(OutEdgeIt e(*_g,v) ; e!=INVALID; ++e) { + if ( 0 >= (*_flow)[e] ) continue; + Node w=_g->target(e); + if ( level[w] == _node_num && w != _source ) { + bfs_queue.push(w); + Node z=level_list[l]; + if ( z!=INVALID ) left.set(z,w); + right.set(w,z); + level_list[l]=w; + level.set(w, l); + } + } + } //while + } //if + + + switch (flow_prop) { + case NO_FLOW: + for(EdgeIt e(*_g); e!=INVALID; ++e) _flow->set(e,0); + case ZERO_FLOW: + for(NodeIt v(*_g); v!=INVALID; ++v) excess.set(v,0); + + //Reverse_bfs from t, to find the starting level. + level.set(_target,0); + bfs_queue.push(_target); + + while ( !bfs_queue.empty() ) { + + Node v=bfs_queue.front(); + bfs_queue.pop(); + int l=level[v]+1; + + for(InEdgeIt e(*_g,v) ; e!=INVALID; ++e) { + Node w=_g->source(e); + if ( level[w] == _node_num && w != _source ) { + bfs_queue.push(w); + Node z=level_list[l]; + if ( z!=INVALID ) left.set(z,w); + right.set(w,z); + level_list[l]=w; + level.set(w, l); + } + } + } + + //the starting flow + for(OutEdgeIt e(*_g,_source) ; e!=INVALID; ++e) { + Num c=(*_capacity)[e]; + if ( c <= 0 ) continue; + Node w=_g->target(e); + if ( level[w] < _node_num ) { + if ( excess[w] <= 0 && w!=_target ) { //putting into the stack + next.set(w,first[level[w]]); + first[level[w]]=w; + } + _flow->set(e, c); + excess.set(w, excess[w]+c); + } + } + break; + + case GEN_FLOW: + for(NodeIt v(*_g); v!=INVALID; ++v) excess.set(v,0); + { + Num exc=0; + for(InEdgeIt e(*_g,_target) ; e!=INVALID; ++e) exc+=(*_flow)[e]; + for(OutEdgeIt e(*_g,_target) ; e!=INVALID; ++e) exc-=(*_flow)[e]; + excess.set(_target,exc); + } + + //the starting flow + for(OutEdgeIt e(*_g,_source); e!=INVALID; ++e) { + Num rem=(*_capacity)[e]-(*_flow)[e]; + if ( rem <= 0 ) continue; + Node w=_g->target(e); + if ( level[w] < _node_num ) { + if ( excess[w] <= 0 && w!=_target ) { //putting into the stack + next.set(w,first[level[w]]); + first[level[w]]=w; + } + _flow->set(e, (*_capacity)[e]); + excess.set(w, excess[w]+rem); + } + } + + for(InEdgeIt e(*_g,_source); e!=INVALID; ++e) { + if ( (*_flow)[e] <= 0 ) continue; + Node w=_g->source(e); + if ( level[w] < _node_num ) { + if ( excess[w] <= 0 && w!=_target ) { + next.set(w,first[level[w]]); + first[level[w]]=w; + } + excess.set(w, excess[w]+(*_flow)[e]); + _flow->set(e, 0); + } + } + break; + + case PRE_FLOW: + //the starting flow + for(OutEdgeIt e(*_g,_source) ; e!=INVALID; ++e) { + Num rem=(*_capacity)[e]-(*_flow)[e]; + if ( rem <= 0 ) continue; + Node w=_g->target(e); + if ( level[w] < _node_num ) _flow->set(e, (*_capacity)[e]); + } + + for(InEdgeIt e(*_g,_source) ; e!=INVALID; ++e) { + if ( (*_flow)[e] <= 0 ) continue; + Node w=_g->source(e); + if ( level[w] < _node_num ) _flow->set(e, 0); + } + + //computing the excess + for(NodeIt w(*_g); w!=INVALID; ++w) { + Num exc=0; + for(InEdgeIt e(*_g,w); e!=INVALID; ++e) exc+=(*_flow)[e]; + for(OutEdgeIt e(*_g,w); e!=INVALID; ++e) exc-=(*_flow)[e]; + excess.set(w,exc); + + //putting the active nodes into the stack + int lev=level[w]; + if ( exc > 0 && lev < _node_num && Node(w) != _target ) { + next.set(w,first[lev]); + first[lev]=w; + } + } + break; + } //switch + } //preflowPreproc + + + void relabel(Node w, int newlevel, VecNode& first, NNMap& next, + VecNode& level_list, NNMap& left, + NNMap& right, int& b, int& k, bool what_heur ) + { + + int lev=level[w]; + + Node right_n=right[w]; + Node left_n=left[w]; + + //unlacing starts + if ( right_n!=INVALID ) { + if ( left_n!=INVALID ) { + right.set(left_n, right_n); + left.set(right_n, left_n); + } else { + level_list[lev]=right_n; + left.set(right_n, INVALID); + } + } else { + if ( left_n!=INVALID ) { + right.set(left_n, INVALID); + } else { + level_list[lev]=INVALID; + } + } + //unlacing ends + + if ( level_list[lev]==INVALID ) { + + //gapping starts + for (int i=lev; i!=k ; ) { + Node v=level_list[++i]; + while ( v!=INVALID ) { + level.set(v,_node_num); + v=right[v]; + } + level_list[i]=INVALID; + if ( !what_heur ) first[i]=INVALID; + } + + level.set(w,_node_num); + b=lev-1; + k=b; + //gapping ends + + } else { + + if ( newlevel == _node_num ) level.set(w,_node_num); + else { + level.set(w,++newlevel); + next.set(w,first[newlevel]); + first[newlevel]=w; + if ( what_heur ) b=newlevel; + if ( k < newlevel ) ++k; //now k=newlevel + Node z=level_list[newlevel]; + if ( z!=INVALID ) left.set(z,w); + right.set(w,z); + left.set(w,INVALID); + level_list[newlevel]=w; + } + } + } //relabel + + }; + + ///Function type interface for Preflow algorithm. + + /// \ingroup flowalgs + ///Function type interface for Preflow algorithm. + ///\sa Preflow + template + Preflow preflow(const GR &g, + typename GR::Node source, + typename GR::Node target, + const CM &cap, + FM &flow + ) + { + return Preflow(g,source,target,cap,flow); + } + +} //namespace lemon + +#endif //LEMON_PREFLOW_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/radix_heap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/radix_heap.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,412 @@ +/* -*- C++ -*- + * lemon/radix_heap.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_RADIX_HEAP_H +#define LEMON_RADIX_HEAP_H + +///\ingroup auxdat +///\file +///\brief Radix Heap implementation. + +#include +#include + +namespace lemon { + + /// \addtogroup auxdat + /// @{ + + /// \brief Exception thrown by RadixHeap. + /// + /// This Exception is thrown when a smaller priority + /// is inserted into the \e RadixHeap then the last time erased. + /// \see RadixHeap + /// \author Balazs Dezso + + class UnderFlowPriorityError : public RuntimeError { + public: + virtual const char* exceptionName() const { + return "lemon::UnderFlowPriorityError"; + } + }; + + /// \brief A Radix Heap implementation. + /// + /// This class implements the \e radix \e heap data structure. A \e heap + /// is a data structure for storing items with specified values called \e + /// priorities in such a way that finding the item with minimum priority is + /// efficient. This heap type can store only items with \e int priority. + /// In a heap one can change the priority of an item, add or erase an + /// item, but the priority cannot be decreased under the last removed + /// item's priority. + /// + /// \param _Item Type of the items to be stored. + /// \param _ItemIntMap A read and writable Item int map, used internally + /// to handle the cross references. + /// + /// \see BinHeap + /// \see Dijkstra + /// \author Balazs Dezso + + template + class RadixHeap { + + public: + typedef _Item Item; + typedef int Prio; + typedef _ItemIntMap ItemIntMap; + + /// \brief Type to represent the items states. + /// + /// Each Item element have a state associated to it. It may be "in heap", + /// "pre heap" or "post heap". The latter two are indifferent from the + /// heap's point of view, but may be useful to the user. + /// + /// The ItemIntMap \e should be initialized in such way that it maps + /// PRE_HEAP (-1) to any element to be put in the heap... + enum state_enum { + IN_HEAP = 0, + PRE_HEAP = -1, + POST_HEAP = -2 + }; + + private: + + struct RadixItem { + int prev, next, box; + Item item; + int prio; + RadixItem(Item _item, int _prio) : item(_item), prio(_prio) {} + }; + + struct RadixBox { + int first; + int min, size; + RadixBox(int _min, int _size) : first(-1), min(_min), size(_size) {} + }; + + std::vector data; + std::vector boxes; + + ItemIntMap &iim; + + + public: + /// \brief The constructor. + /// + /// The constructor. + /// \param _iim should be given to the constructor, since it is used + /// internally to handle the cross references. The value of the map + /// should be PRE_HEAP (-1) for each element. + explicit RadixHeap(ItemIntMap &_iim) : iim(_iim) { + boxes.push_back(RadixBox(0, 1)); + boxes.push_back(RadixBox(1, 1)); + } + + /// \brief The constructor. + /// + /// The constructor. + /// + /// \param _iim It should be given to the constructor, since it is used + /// internally to handle the cross references. The value of the map + /// should be PRE_HEAP (-1) for each element. + /// + /// \param capacity It determines the initial capacity of the heap. + RadixHeap(ItemIntMap &_iim, int capacity) : iim(_iim) { + boxes.push_back(RadixBox(0, 1)); + boxes.push_back(RadixBox(1, 1)); + while (upper(boxes.back(), capacity)) { + extend(); + } + } + + /// The number of items stored in the heap. + /// + /// \brief Returns the number of items stored in the heap. + int size() const { return data.size(); } + /// \brief Checks if the heap stores no items. + /// + /// Returns \c true if and only if the heap stores no items. + bool empty() const { return data.empty(); } + + private: + + bool upper(int box, Prio prio) { + return prio < boxes[box].min; + } + + bool lower(int box, Prio prio) { + return prio >= boxes[box].min + boxes[box].size; + } + + /// \brief Remove item from the box list. + void remove(int index) { + if (data[index].prev >= 0) { + data[data[index].prev].next = data[index].next; + } else { + boxes[data[index].box].first = data[index].next; + } + if (data[index].next >= 0) { + data[data[index].next].prev = data[index].prev; + } + } + + /// \brief Insert item into the box list. + void insert(int box, int index) { + if (boxes[box].first == -1) { + boxes[box].first = index; + data[index].next = data[index].prev = -1; + } else { + data[index].next = boxes[box].first; + data[boxes[box].first].prev = index; + data[index].prev = -1; + boxes[box].first = index; + } + data[index].box = box; + } + + /// \brief Add a new box to the box list. + void extend() { + int min = boxes.back().min + boxes.back().size; + int size = 2 * boxes.back().size; + boxes.push_back(RadixBox(min, size)); + } + + /// \brief Move an item up into the proper box. + void bubble_up(int index) { + if (!lower(data[index].box, data[index].prio)) return; + remove(index); + int box = findUp(data[index].box, data[index].prio); + insert(box, index); + } + + /// \brief Find up the proper box for the item with the given prio. + int findUp(int start, int prio) { + while (lower(start, prio)) { + if (++start == (int)boxes.size()) { + extend(); + } + } + return start; + } + + /// \brief Move an item down into the proper box. + void bubble_down(int index) { + if (!upper(data[index].box, data[index].prio)) return; + remove(index); + int box = findDown(data[index].box, data[index].prio); + insert(box, index); + } + + /// \brief Find up the proper box for the item with the given prio. + int findDown(int start, int prio) { + while (upper(start, prio)) { + if (--start < 0) throw UnderFlowPriorityError(); + } + return start; + } + + /// \brief Find the first not empty box. + int findFirst() { + int first = 0; + while (boxes[first].first == -1) ++first; + return first; + } + + /// \brief Gives back the minimal prio of the box. + int minValue(int box) { + int min = data[boxes[box].first].prio; + for (int k = boxes[box].first; k != -1; k = data[k].next) { + if (data[k].prio < min) min = data[k].prio; + } + return min; + } + + /// \brief Rearrange the items of the heap and makes the + /// first box not empty. + void moveDown() { + int box = findFirst(); + if (box == 0) return; + int min = minValue(box); + for (int i = 0; i <= box; ++i) { + boxes[i].min = min; + min += boxes[i].size; + } + int curr = boxes[box].first, next; + while (curr != -1) { + next = data[curr].next; + bubble_down(curr); + curr = next; + } + } + + void relocate_last(int index) { + if (index != (int)data.size() - 1) { + data[index] = data.back(); + if (data[index].prev != -1) { + data[data[index].prev].next = index; + } else { + boxes[data[index].box].first = index; + } + if (data[index].next != -1) { + data[data[index].next].prev = index; + } + iim[data[index].item] = index; + } + data.pop_back(); + } + + public: + + /// \brief Insert an item into the heap with the given heap. + /// + /// Adds \c i to the heap with priority \c p. + /// \param i The item to insert. + /// \param p The priority of the item. + void push(const Item &i, const Prio &p) { + int n = data.size(); + iim.set(i, n); + data.push_back(RadixItem(i, p)); + while (lower(boxes.size() - 1, p)) { + extend(); + } + int box = findDown(boxes.size() - 1, p); + insert(box, n); + } + + /// \brief Returns the item with minimum priority. + /// + /// This method returns the item with minimum priority. + /// \pre The heap must be nonempty. + Item top() const { + const_cast*>(this)->moveDown(); + return data[boxes[0].first].item; + } + + /// \brief Returns the minimum priority. + /// + /// It returns the minimum priority. + /// \pre The heap must be nonempty. + Prio prio() const { + const_cast*>(this)->moveDown(); + return data[boxes[0].first].prio; + } + + /// \brief Deletes the item with minimum priority. + /// + /// This method deletes the item with minimum priority. + /// \pre The heap must be non-empty. + void pop() { + moveDown(); + int index = boxes[0].first; + iim[data[index].item] = POST_HEAP; + remove(index); + relocate_last(index); + } + + /// \brief Deletes \c i from the heap. + /// + /// This method deletes item \c i from the heap, if \c i was + /// already stored in the heap. + /// \param i The item to erase. + void erase(const Item &i) { + int index = iim[i]; + iim[i] = POST_HEAP; + remove(index); + relocate_last(index); + } + + /// \brief Returns the priority of \c i. + /// + /// This function returns the priority of item \c i. + /// \pre \c i must be in the heap. + /// \param i The item. + Prio operator[](const Item &i) const { + int idx = iim[i]; + return data[idx].prio; + } + + /// \brief \c i gets to the heap with priority \c p independently + /// if \c i was already there. + /// + /// This method calls \ref push(\c i, \c p) if \c i is not stored + /// in the heap and sets the priority of \c i to \c p otherwise. + /// It may throw an \e UnderFlowPriorityException. + /// \param i The item. + /// \param p The priority. + void set(const Item &i, const Prio &p) { + int idx = iim[i]; + if( idx < 0 ) { + push(i, p); + } + else if( p >= data[idx].prio ) { + data[idx].prio = p; + bubble_up(idx); + } else { + data[idx].prio = p; + bubble_down(idx); + } + } + + + /// \brief Decreases the priority of \c i to \c p. + /// + /// This method decreases the priority of item \c i to \c p. + /// \pre \c i must be stored in the heap with priority at least \c p, and + /// \c should be greater then the last removed item's priority. + /// \param i The item. + /// \param p The priority. + void decrease(const Item &i, const Prio &p) { + int idx = iim[i]; + data[idx].prio = p; + bubble_down(idx); + } + + /// \brief Increases the priority of \c i to \c p. + /// + /// This method sets the priority of item \c i to \c p. + /// \pre \c i must be stored in the heap with priority at most \c + /// p relative to \c Compare. + /// \param i The item. + /// \param p The priority. + void increase(const Item &i, const Prio &p) { + int idx = iim[i]; + data[idx].prio = p; + bubble_up(idx); + } + + /// \brief Returns if \c item is in, has already been in, or has + /// never been in the heap. + /// + /// This method returns PRE_HEAP if \c item has never been in the + /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP + /// otherwise. In the latter case it is possible that \c item will + /// get back to the heap again. + /// \param i The item. + state_enum state(const Item &i) const { + int s = iim[i]; + if( s >= 0 ) s = 0; + return state_enum(s); + } + + }; // class RadixHeap + + + ///@} + +} // namespace lemon + +#endif // LEMON_RADIX_HEAP_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/smart_graph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/smart_graph.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,414 @@ +/* -*- C++ -*- + * lemon/smart_graph.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_SMART_GRAPH_H +#define LEMON_SMART_GRAPH_H + +///\ingroup graphs +///\file +///\brief SmartGraph and SymSmartGraph classes. + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +namespace lemon { + + class SmartGraph; + ///Base of SmartGraph + + ///Base of SmartGraph + /// + class SmartGraphBase { + + friend class SmatGraph; + + protected: + struct NodeT + { + int first_in,first_out; + NodeT() : first_in(-1), first_out(-1) {} + }; + struct EdgeT + { + int target, source, next_in, next_out; + //FIXME: is this necessary? + EdgeT() : next_in(-1), next_out(-1) {} + }; + + std::vector nodes; + + std::vector edges; + + + public: + + typedef SmartGraphBase Graph; + + class Node; + class Edge; + + + public: + + SmartGraphBase() : nodes(), edges() { } + SmartGraphBase(const SmartGraphBase &_g) : nodes(_g.nodes), edges(_g.edges) { } + + typedef True NodeNumTag; + typedef True EdgeNumTag; + + ///Number of nodes. + int nodeNum() const { return nodes.size(); } + ///Number of edges. + int edgeNum() const { return edges.size(); } + + /// Maximum node ID. + + /// Maximum node ID. + ///\sa id(Node) + int maxId(Node = INVALID) const { return nodes.size()-1; } + /// Maximum edge ID. + + /// Maximum edge ID. + ///\sa id(Edge) + int maxId(Edge = INVALID) const { return edges.size()-1; } + + Node source(Edge e) const { return edges[e.n].source; } + Node target(Edge e) const { return edges[e.n].target; } + + /// Node ID. + + /// The ID of a valid Node is a nonnegative integer not greater than + /// \ref maxNodeId(). The range of the ID's is not surely continuous + /// and the greatest node ID can be actually less then \ref maxNodeId(). + /// + /// The ID of the \ref INVALID node is -1. + ///\return The ID of the node \c v. + static int id(Node v) { return v.n; } + /// Edge ID. + + /// The ID of a valid Edge is a nonnegative integer not greater than + /// \ref maxEdgeId(). The range of the ID's is not surely continuous + /// and the greatest edge ID can be actually less then \ref maxEdgeId(). + /// + /// The ID of the \ref INVALID edge is -1. + ///\return The ID of the edge \c e. + static int id(Edge e) { return e.n; } + + static Node fromId(int id, Node) { return Node(id);} + + static Edge fromId(int id, Edge) { return Edge(id);} + + Node addNode() { + Node n; n.n=nodes.size(); + nodes.push_back(NodeT()); //FIXME: Hmmm... + return n; + } + + Edge addEdge(Node u, Node v) { + Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm... + edges[e.n].source=u.n; edges[e.n].target=v.n; + edges[e.n].next_out=nodes[u.n].first_out; + edges[e.n].next_in=nodes[v.n].first_in; + nodes[u.n].first_out=nodes[v.n].first_in=e.n; + + return e; + } + + void clear() { + edges.clear(); + nodes.clear(); + } + + + class Node { + friend class SmartGraphBase; + friend class SmartGraph; + + protected: + int n; + ///\todo It should be removed (or at least define a setToId() instead). + /// + Node(int nn) {n=nn;} + public: + Node() {} + Node (Invalid) { n=-1; } + bool operator==(const Node i) const {return n==i.n;} + bool operator!=(const Node i) const {return n!=i.n;} + bool operator<(const Node i) const {return n AlterableSmartGraphBase; + typedef IterableGraphExtender IterableSmartGraphBase; + typedef DefaultMappableGraphExtender MappableSmartGraphBase; + typedef ExtendableGraphExtender ExtendableSmartGraphBase; + typedef ClearableGraphExtender ClearableSmartGraphBase; + + /// \addtogroup graphs + /// @{ + + ///A smart graph class. + + ///This is a simple and fast graph implementation. + ///It is also quite memory efficient, but at the price + ///that it does support only limited (only stack-like) + ///node and edge deletions. + ///It conforms to + ///the \ref concept::ExtendableGraph "ExtendableGraph" concept. + ///\sa concept::ExtendableGraph. + /// + ///\author Alpar Juttner + class SmartGraph : public ClearableSmartGraphBase { + public: + /// Finds an edge between two nodes. + + /// Finds an edge from node \c u to node \c v. + /// + /// If \c prev is \ref INVALID (this is the default value), then + /// it finds the first edge from \c u to \c v. Otherwise it looks for + /// the next edge from \c u to \c v after \c prev. + /// \return The found edge or \ref INVALID if there is no such an edge. + /// + /// Thus you can iterate through each edge from \c u to \c v as it follows. + /// \code + /// for(Edge e=G.findEdge(u,v);e!=INVALID;e=G.findEdge(u,v,e)) { + /// ... + /// } + /// \endcode + /// \todo Possibly it should be a global function. + Edge findEdge(Node u,Node v, Edge prev = INVALID) + { + return _findEdge(u,v,prev); + } + + class SnapShot; + friend class SnapShot; + + protected: + void restoreSnapShot(const SnapShot &s) + { + while(s.edge_num>edges.size()) { + Parent::getNotifier(Edge()).erase(Edge(edges.size()-1)); + nodes[edges.back().target].first_in=edges.back().next_in; + nodes[edges.back().source].first_out=edges.back().next_out; + edges.pop_back(); + } + //nodes.resize(s.nodes_num); + while(s.node_num>nodes.size()) { + Parent::getNotifier(Node()).erase(Node(nodes.size()-1)); + nodes.pop_back(); + } + } + + public: + + ///Split a node. + + ///This function splits a node. First a new node is added to the graph, + ///then the source of each outgoing edge of \c n is moved to this new node. + ///If \c connect is \c true (this is the default value), then a new edge + ///from \c n to the newly created node is also added. + ///\return The newly created node. + /// + ///\note The Edges + ///referencing a moved edge remain + ///valid. However InEdge's and OutEdge's + ///may be invalidated. + ///\warning This functionality cannot be used together with the SnapShot + ///feature. + ///\todo It could be implemented in a bit faster way. + Node split(Node n, bool connect = true) + { + return _split(n,connect); + } + + + ///Class to make a snapshot of the graph and to restrore to it later. + + ///Class to make a snapshot of the graph and to restrore to it later. + /// + ///The newly added nodes and edges can be removed using the + ///restore() function. + ///\note After you restore a state, you cannot restore + ///a later state, in other word you cannot add again the edges deleted + ///by restore() using another SnapShot instance. + /// + class SnapShot + { + SmartGraph *g; + protected: + friend class SmartGraph; + unsigned int node_num; + unsigned int edge_num; + public: + ///Default constructor. + + ///Default constructor. + ///To actually make a snapshot you must call save(). + /// + SnapShot() : g(0) {} + ///Constructor that immediately makes a snapshot + + ///This constructor immediately makes a snapshot of the graph. + ///\param _g The graph we make a snapshot of. + SnapShot(SmartGraph &_g) :g(&_g) { + node_num=g->nodes.size(); + edge_num=g->edges.size(); + } + + ///Make a snapshot. + + ///Make a snapshot of the graph. + /// + ///This function can be called more than once. In case of a repeated + ///call, the previous snapshot gets lost. + ///\param _g The graph we make the snapshot of. + void save(SmartGraph &_g) + { + g=&_g; + node_num=g->nodes.size(); + edge_num=g->edges.size(); + } + + ///Undo the changes until a snapshot. + + ///Undo the changes until a snapshot created by save(). + /// + ///\param s an internal stucture given back by save() + ///\note After you restored a state, you cannot restore + ///a later state, in other word you cannot add again the edges deleted + ///by restore(). + /// + ///\todo This function might be called undo(). + + void restore() + { + g->restoreSnapShot(*this); + } + }; + }; + + + /**************** Undirected List Graph ****************/ + + typedef ClearableUndirGraphExtender< + ExtendableUndirGraphExtender< + MappableUndirGraphExtender< + IterableUndirGraphExtender< + AlterableUndirGraphExtender< + UndirGraphExtender > > > > > UndirSmartGraphBase; + + ///A smart undirected graph class. + + ///This is a simple and fast undirected graph implementation. + ///It is also quite memory efficient, but at the price + ///that it does support only limited (only stack-like) + ///node and edge deletions. + ///Except from this it conforms to + ///the \ref concept::UndirGraph "UndirGraph" concept. + ///\sa concept::UndirGraph. + /// + ///\todo SnapShot hasn't been implemented yet. + /// + class UndirSmartGraph : public UndirSmartGraphBase { + }; + + + /// @} +} //namespace lemon + + +#endif //LEMON_SMART_GRAPH_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/suurballe.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/suurballe.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,209 @@ +/* -*- C++ -*- + * lemon/suurballe.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_SUURBALLE_H +#define LEMON_SUURBALLE_H + +///\ingroup flowalgs +///\file +///\brief An algorithm for finding k paths of minimal total length. + + +#include +#include +#include + +namespace lemon { + +/// \addtogroup flowalgs +/// @{ + + ///\brief Implementation of an algorithm for finding k edge-disjoint paths between 2 nodes + /// of minimal total length + /// + /// The class \ref lemon::Suurballe implements + /// an algorithm for finding k edge-disjoint paths + /// from a given source node to a given target node in an + /// edge-weighted directed graph having minimal total weight (length). + /// + ///\warning Length values should be nonnegative. + /// + ///\param Graph The directed graph type the algorithm runs on. + ///\param LengthMap The type of the length map (values should be nonnegative). + /// + ///\note It it questionable whether it is correct to call this method after + ///%Suurballe for it is just a special case of Edmonds' and Karp's algorithm + ///for finding minimum cost flows. In fact, this implementation just + ///wraps the MinCostFlow algorithms. The paper of both %Suurballe and + ///Edmonds-Karp published in 1972, therefore it is possibly right to + ///state that they are + ///independent results. Most frequently this special case is referred as + ///%Suurballe method in the literature, especially in communication + ///network context. + ///\author Attila Bernath + template + class Suurballe{ + + + typedef typename LengthMap::Value Length; + + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::Edge Edge; + typedef typename Graph::OutEdgeIt OutEdgeIt; + typedef typename Graph::template EdgeMap EdgeIntMap; + + typedef ConstMap ConstMap; + + const Graph& G; + + Node s; + Node t; + + //Auxiliary variables + //This is the capacity map for the mincostflow problem + ConstMap const1map; + //This MinCostFlow instance will actually solve the problem + MinCostFlow min_cost_flow; + + //Container to store found paths + std::vector< std::vector > paths; + + public : + + + /*! \brief The constructor of the class. + + \param _G The directed graph the algorithm runs on. + \param _length The length (weight or cost) of the edges. + \param _s Source node. + \param _t Target node. + */ + Suurballe(Graph& _G, LengthMap& _length, Node _s, Node _t) : + G(_G), s(_s), t(_t), const1map(1), + min_cost_flow(_G, _length, const1map, _s, _t) { } + + ///Runs the algorithm. + + ///Runs the algorithm. + ///Returns k if there are at least k edge-disjoint paths from s to t. + ///Otherwise it returns the number of edge-disjoint paths found + ///from s to t. + /// + ///\param k How many paths are we looking for? + /// + int run(int k) { + int i = min_cost_flow.run(k); + + //Let's find the paths + //We put the paths into stl vectors (as an inner representation). + //In the meantime we lose the information stored in 'reversed'. + //We suppose the lengths to be positive now. + + //We don't want to change the flow of min_cost_flow, so we make a copy + //The name here suggests that the flow has only 0/1 values. + EdgeIntMap reversed(G); + + for(typename Graph::EdgeIt e(G); e!=INVALID; ++e) + reversed[e] = min_cost_flow.getFlow()[e]; + + paths.clear(); + //total_length=0; + paths.resize(k); + for (int j=0; j + void getPath(Path& p, size_t j){ + + p.clear(); + if (j>paths.size()-1){ + return; + } + typename Path::Builder B(p); + for(typename std::vector::iterator i=paths[j].begin(); + i!=paths[j].end(); ++i ){ + B.pushBack(*i); + } + + B.commit(); + } + + }; //class Suurballe + + ///@} + +} //namespace lemon + +#endif //LEMON_SUURBALLE_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/time_measure.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/time_measure.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,255 @@ +/* -*- C++ -*- + * lemon/time_measure.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_TIME_MEASURE_H +#define LEMON_TIME_MEASURE_H + +///\ingroup misc +///\file +///\brief Tools for measuring cpu usage + +#include +#include +#include +#include +#include + +namespace lemon { + + /// \addtogroup misc + /// @{ + + /// A class to store (cpu)time instances. + + /// This class stores five time values. + /// - a real time + /// - a user cpu time + /// - a system cpu time + /// - a user cpu time of children + /// - a system cpu time of children + /// + /// TimeStamp's can be added to or substracted from each other and + /// they can be pushed to a stream. + /// + /// In most cases, perhaps \ref Timer class is what you want to use instead. + /// + ///\author Alpar Juttner + + class TimeStamp + { + tms ts; + double real_time; + + public: + + tms &getTms() {return ts;} + const tms &getTms() const {return ts;} + ///Read the current time values of the process + void stamp() + { + timeval tv; + times(&ts); + gettimeofday(&tv, 0);real_time=tv.tv_sec+double(tv.tv_usec)/1e6; + } + + /// Constructor initializing with zero + TimeStamp() + { ts.tms_utime=ts.tms_stime=ts.tms_cutime=ts.tms_cstime=0; real_time=0;} + ///Constructor initializing with the current time values of the process + TimeStamp(void *) { stamp();} + + ///\e + TimeStamp &operator+=(const TimeStamp &b) + { + ts.tms_utime+=b.ts.tms_utime; + ts.tms_stime+=b.ts.tms_stime; + ts.tms_cutime+=b.ts.tms_cutime; + ts.tms_cstime+=b.ts.tms_cstime; + real_time+=b.real_time; + return *this; + } + ///\e + TimeStamp operator+(const TimeStamp &b) const + { + TimeStamp t(*this); + return t+=b; + } + ///\e + TimeStamp &operator-=(const TimeStamp &b) + { + ts.tms_utime-=b.ts.tms_utime; + ts.tms_stime-=b.ts.tms_stime; + ts.tms_cutime-=b.ts.tms_cutime; + ts.tms_cstime-=b.ts.tms_cstime; + real_time-=b.real_time; + return *this; + } + ///\e + TimeStamp operator-(const TimeStamp &b) const + { + TimeStamp t(*this); + return t-=b; + } + ///The time ellapsed since the last call of stamp() + TimeStamp ellapsed() const + { + TimeStamp t(NULL); + return t-*this; + } + + friend std::ostream& operator<<(std::ostream& os,const TimeStamp &t); + + ///Gives back the user time of the process + double getUserTime() const + { + return double(ts.tms_utime)/sysconf(_SC_CLK_TCK); + } + ///Gives back the system time of the process + double getSystemTime() const + { + return double(ts.tms_stime)/sysconf(_SC_CLK_TCK); + } + ///Gives back the user time of the process' children + double getCUserTime() const + { + return double(ts.tms_cutime)/sysconf(_SC_CLK_TCK); + } + ///Gives back the user time of the process' children + double getCSystemTime() const + { + return double(ts.tms_cstime)/sysconf(_SC_CLK_TCK); + } + ///Gives back the real time of the process + double getRealTime() const {return real_time;} + }; + + ///Class measuring the cpu time and real time usage of the process + + ///Class measuring the cpu time and real time usage of the process. + ///It is quite easy-to-use, here is a short example. + ///\code + ///#include + ///#include + /// + ///int main() + ///{ + /// + /// ... + /// + /// Timer T; + /// doSomething(); + /// std::cout << T << '\n'; + /// T.reset(); + /// doSomethingElse(); + /// std::cout << T << '\n'; + /// + /// ... + /// + ///} + ///\endcode + /// + ///\todo This shouldn't be Unix (Linux) specific. + /// + ///\author Alpar Juttner + class Timer + { + TimeStamp start_time; + + void _reset() {start_time.stamp();} + + public: + ///Constructor. It starts with zero time counters + Timer() {_reset();} + + ///Computes the ellapsed time + + ///This conversion computes the ellapsed time + ///since the construction of \c t or since + ///the last \c t.reset(). + operator TimeStamp () const + { + TimeStamp t; + t.stamp(); + return t-start_time; + } + + ///Resets the time counters + + ///Resets the time counters + /// + void reset() + { + _reset(); + } + + + ///Gives back the ellapsed user time of the process + double getUserTime() const + { + return operator TimeStamp().getUserTime(); + } + ///Gives back the ellapsed system time of the process + double getSystemTime() const + { + return operator TimeStamp().getSystemTime(); + } + ///Gives back the ellapsed user time of the process' children + double getCUserTime() const + { + return operator TimeStamp().getCUserTime(); + } + ///Gives back the ellapsed user time of the process' children + double getCSystemTime() const + { + return operator TimeStamp().getCSystemTime(); + } + ///Gives back the ellapsed real time of the process + double getRealTime() const + { + return operator TimeStamp().getRealTime(); + } + + }; + + ///Prints the time counters + + ///Prints the time counters in the following form: + /// + /// u: XX.XXs s: XX.XXs cu: XX.XXs cs: XX.XXs real: XX.XXs + /// + /// where the values are the + /// \li \c u: user cpu time, + /// \li \c s: system cpu time, + /// \li \c cu: user cpu time of children, + /// \li \c cs: system cpu time of children, + /// \li \c real: real time. + /// \relates TimeStamp + inline std::ostream& operator<<(std::ostream& os,const TimeStamp &t) + { + long cls = sysconf(_SC_CLK_TCK); + os << "u: " << double(t.getTms().tms_utime)/cls << + "s, s: " << double(t.getTms().tms_stime)/cls << + "s, cu: " << double(t.getTms().tms_cutime)/cls << + "s, cs: " << double(t.getTms().tms_cstime)/cls << + "s, real: " << t.getRealTime() << "s"; + return os; + } + + /// @} + +} //namespace lemon + +#endif //LEMON_TIME_MEASURE_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/unionfind.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/unionfind.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,724 @@ +/* -*- C++ -*- + * lemon/unionfind.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_UNION_FIND_H +#define LEMON_UNION_FIND_H + +//!\ingroup auxdat +//!\file +//!\brief Union-Find data structures. +//! +//!\bug unionfind_test.cc doesn't work with Intel compiler. It compiles but +//!fails to run (Segmentation fault). + + +#include +#include +#include +#include + +#include + +namespace lemon { + + //! \addtogroup auxdat + //! @{ + + /** + * \brief A \e Union-Find data structure implementation + * + * The class implements the \e Union-Find data structure. + * The union operation uses rank heuristic, while + * the find operation uses path compression. + * This is a very simple but efficient implementation, providing + * only four methods: join (union), find, insert and size. + * For more features see the \ref UnionFindEnum class. + * + * It is primarily used in Kruskal algorithm for finding minimal + * cost spanning tree in a graph. + * \sa kruskal() + * + * \pre The elements are automatically added only if the map + * given to the constructor was filled with -1's. Otherwise you + * need to add all the elements by the \ref insert() method. + * \bug It is not clear what the constructor parameter is used for. + */ + + template + class UnionFind { + + public: + typedef T ElementType; + typedef std::pair PairType; + + private: + std::vector data; + TIntMap& map; + + public: + UnionFind(TIntMap& m) : map(m) {} + + /** + * \brief Returns the index of the element's component. + * + * The method returns the index of the element's component. + * This is an integer between zero and the number of inserted elements. + */ + + int find(T a) + { + int comp0 = map[a]; + if (comp0 < 0) { + return insert(a); + } + int comp = comp0; + int next; + while ( (next = data[comp].first) != comp) { + comp = next; + } + while ( (next = data[comp0].first) != comp) { + data[comp0].first = comp; + comp0 = next; + } + + return comp; + } + + /** + * \brief Inserts a new element into the structure. + * + * This method inserts a new element into the data structure. + * + * It is not required to use this method: + * if the map given to the constructor was filled + * with -1's then it is called automatically + * on the first \ref find or \ref join. + * + * The method returns the index of the new component. + */ + + int insert(T a) + { + int n = data.size(); + data.push_back(std::make_pair(n, 1)); + map.set(a,n); + return n; + } + + /** + * \brief Joining the components of element \e a and element \e b. + * + * This is the \e union operation of the Union-Find structure. + * Joins the component of element \e a and component of + * element \e b. If \e a and \e b are in the same component then + * it returns false otherwise it returns true. + */ + + bool join(T a, T b) + { + int ca = find(a); + int cb = find(b); + + if ( ca == cb ) + return false; + + if ( data[ca].second > data[cb].second ) { + data[cb].first = ca; + data[ca].second += data[cb].second; + } + else { + data[ca].first = cb; + data[cb].second += data[ca].second; + } + return true; + } + + /** + * \brief Returns the size of the component of element \e a. + * + * Returns the size of the component of element \e a. + */ + + int size(T a) + { + int ca = find(a); + return data[ca].second; + } + + }; + + + + + /*******************************************************/ + + +#ifdef DEVELOPMENT_DOCS + + /** + * \brief The auxiliary class for the \ref UnionFindEnum class. + * + * In the \ref UnionFindEnum class all components are represented as + * a std::list. + * Items of these lists are UnionFindEnumItem structures. + * + * The class has four fields: + * - T me - the actual element + * - IIter parent - the parent of the element in the union-find structure + * - int size - the size of the component of the element. + * Only valid if the element + * is the leader of the component. + * - CIter my_class - pointer into the list of components + * pointing to the component of the element. + * Only valid if the element is the leader of the component. + */ + +#endif + + template + struct UnionFindEnumItem { + + typedef std::list ItemList; + typedef std::list ClassList; + typedef typename ItemList::iterator IIter; + typedef typename ClassList::iterator CIter; + + T me; + IIter parent; + int size; + CIter my_class; + + UnionFindEnumItem() {} + UnionFindEnumItem(const T &_me, CIter _my_class): + me(_me), size(1), my_class(_my_class) {} + }; + + + /** + * \brief A \e Union-Find data structure implementation which + * is able to enumerate the components. + * + * The class implements a \e Union-Find data structure + * which is able to enumerate the components and the items in + * a component. If you don't need this feature then perhaps it's + * better to use the \ref UnionFind class which is more efficient. + * + * The union operation uses rank heuristic, while + * the find operation uses path compression. + * + * \pre You + * need to add all the elements by the \ref insert() method. + */ + + + template class Map> + class UnionFindEnum { + + typedef std::list > ItemList; + typedef std::list ClassList; + typedef typename ItemList::iterator IIter; + typedef typename ItemList::const_iterator IcIter; + typedef typename ClassList::iterator CIter; + typedef typename ClassList::const_iterator CcIter; + + public: + typedef T ElementType; + typedef UnionFindEnumItem ItemType; + typedef Map< IIter > MapType; + + private: + MapType& m; + ClassList classes; + + IIter _find(IIter a) const { + IIter comp = a; + IIter next; + while( (next = comp->parent) != comp ) { + comp = next; + } + + IIter comp1 = a; + while( (next = comp1->parent) != comp ) { + comp1->parent = comp->parent; + comp1 = next; + } + return comp; + } + + public: + UnionFindEnum(MapType& _m) : m(_m) {} + + + /** + * \brief Inserts the given element into a new component. + * + * This method creates a new component consisting only of the + * given element. + */ + + void insert(const T &a) + { + + + classes.push_back(ItemList()); + CIter aclass = classes.end(); + --aclass; + + ItemList &alist = *aclass; + alist.push_back(ItemType(a, aclass)); + IIter ai = alist.begin(); + + ai->parent = ai; + m.set(a, ai); + + } + + /** + * \brief Inserts the given element into the component of the others. + * + * This methods inserts the element \e a into the component of the + * element \e comp. + */ + + void insert(const T &a, const T &comp) { + + IIter clit = _find(m[comp]); + ItemList &c = *clit->my_class; + c.push_back(ItemType(a,0)); + IIter ai = c.end(); + --ai; + ai->parent = clit; + m.set(a, ai); + ++clit->size; + } + + + /** + * \brief Finds the leader of the component of the given element. + * + * The method returns the leader of the component of the given element. + */ + + T find(const T &a) const { + return _find(m[a])->me; + } + + + /** + * \brief Joining the component of element \e a and element \e b. + * + * This is the \e union operation of the Union-Find structure. + * Joins the component of element \e a and component of + * element \e b. If \e a and \e b are in the same component then + * returns false else returns true. + */ + + bool join(T a, T b) { + + IIter ca = _find(m[a]); + IIter cb = _find(m[b]); + + if ( ca == cb ) { + return false; + } + + if ( ca->size > cb->size ) { + + cb->parent = ca->parent; + ca->size += cb->size; + + ItemList &alist = *ca->my_class; + alist.splice(alist.end(),*cb->my_class); + + classes.erase(cb->my_class); + cb->my_class = 0; + } + else { + + ca->parent = cb->parent; + cb->size += ca->size; + + ItemList &blist = *cb->my_class; + blist.splice(blist.end(),*ca->my_class); + + classes.erase(ca->my_class); + ca->my_class = 0; + } + + return true; + } + + + /** + * \brief Returns the size of the component of element \e a. + * + * Returns the size of the component of element \e a. + */ + + int size(const T &a) const { + return _find(m[a])->size; + } + + + /** + * \brief Splits up the component of the element. + * + * Splitting the component of the element into sigleton + * components (component of size one). + */ + + void split(const T &a) { + + IIter ca = _find(m[a]); + + if ( ca->size == 1 ) + return; + + CIter aclass = ca->my_class; + + for(IIter curr = ca; ++curr != aclass->end(); curr=ca) { + classes.push_back(ItemList()); + CIter nl = --classes.end(); + nl->splice(nl->end(), *aclass, curr); + + curr->size=1; + curr->parent=curr; + curr->my_class = nl; + } + + ca->size=1; + return; + } + + + /** + * \brief Sets the given element to the leader element of its component. + * + * Sets the given element to the leader element of its component. + */ + + void makeRep(const T &a) { + + IIter ia = m[a]; + IIter la = _find(ia); + if (la == ia) return; + + ia->my_class = la->my_class; + la->my_class = 0; + + ia->size = la->size; + + CIter l = ia->my_class; + l->splice(l->begin(),*l,ia); + + ia->parent = ia; + la->parent = ia; + } + + /** + * \brief Moves the given element to an other component. + * + * This method moves the element \e a from its component + * to the component of \e comp. + * If \e a and \e comp are in the same component then + * it returns false otherwise it returns true. + */ + + bool move(const T &a, const T &comp) { + + IIter ai = m[a]; + IIter lai = _find(ai); + IIter clit = _find(m[comp]); + + if (lai == clit) + return false; + + ItemList &cl = *clit->my_class, + &al = *lai->my_class; + + bool is_leader = (lai == ai); + bool singleton = false; + + if (is_leader) { + ++lai; + } + + cl.splice(cl.end(), al, ai); + + if (is_leader) { + if (ai->size == 1) { + classes.erase(ai->my_class); + singleton = true; + } + else { + lai->size = ai->size; + lai->my_class = ai->my_class; + } + } + if (!singleton) { + for (IIter i = lai; i != al.end(); ++i) + i->parent = lai; + --lai->size; + } + + ai->parent = clit; + ai->my_class = 0; + ++clit->size; + + return true; + } + + + /** + * \brief Removes the given element from the structure. + * + * Removes the given element from the structure. + * + * Removes the element from its component and if the component becomes + * empty then removes that component from the component list. + */ + void erase(const T &a) { + + IIter ma = m[a]; + if (ma == 0) return; + + IIter la = _find(ma); + if (la == ma) { + if (ma -> size == 1){ + classes.erase(ma->my_class); + m.set(a,0); + return; + } + ++la; + la->size = ma->size; + la->my_class = ma->my_class; + } + + for (IIter i = la; i != la->my_class->end(); ++i) { + i->parent = la; + } + + la->size--; + la->my_class->erase(ma); + m.set(a,0); + } + + /** + * \brief Removes the component of the given element from the structure. + * + * Removes the component of the given element from the structure. + */ + + void eraseClass(const T &a) { + IIter ma = m[a]; + if (ma == 0) return; +# ifdef DEBUG + CIter c = _find(ma)->my_class; + for (IIter i=c->begin(); i!=c->end(); ++i) + m.set(i->me, 0); +# endif + classes.erase(_find(ma)->my_class); + } + + + class ClassIt { + friend class UnionFindEnum; + + CcIter i; + public: + ClassIt(Invalid): i(0) {} + ClassIt() {} + + operator const T& () const { + ItemList const &ll = *i; + return (ll.begin())->me; } + bool operator == (ClassIt it) const { + return (i == it.i); + } + bool operator != (ClassIt it) const { + return (i != it.i); + } + bool operator < (ClassIt it) const { + return (i < it.i); + } + + bool valid() const { return i != 0; } + private: + void first(const ClassList &l) { i = l.begin(); validate(l); } + void next(const ClassList &l) { + ++i; + validate(l); + } + void validate(const ClassList &l) { + if ( i == l.end() ) + i = 0; + } + }; + + /** + * \brief Sets the iterator to point to the first component. + * + * Sets the iterator to point to the first component. + * + * With the \ref first, \ref valid and \ref next methods you can + * iterate through the components. For example: + * \code + * UnionFindEnum::MapType map(G); + * UnionFindEnum U(map); + * UnionFindEnum::ClassIt iter; + * for (U.first(iter); U.valid(iter); U.next(iter)) { + * // iter is convertible to Graph::Node + * cout << iter << endl; + * } + * \endcode + */ + + ClassIt& first(ClassIt& it) const { + it.first(classes); + return it; + } + + /** + * \brief Returns whether the iterator is valid. + * + * Returns whether the iterator is valid. + * + * With the \ref first, \ref valid and \ref next methods you can + * iterate through the components. See the example here: \ref first. + */ + + bool valid(ClassIt const &it) const { + return it.valid(); + } + + /** + * \brief Steps the iterator to the next component. + * + * Steps the iterator to the next component. + * + * With the \ref first, \ref valid and \ref next methods you can + * iterate through the components. See the example here: \ref first. + */ + + ClassIt& next(ClassIt& it) const { + it.next(classes); + return it; + } + + + class ItemIt { + friend class UnionFindEnum; + + IcIter i; + const ItemList *l; + public: + ItemIt(Invalid): i(0) {} + ItemIt() {} + + operator const T& () const { return i->me; } + bool operator == (ItemIt it) const { + return (i == it.i); + } + bool operator != (ItemIt it) const { + return (i != it.i); + } + bool operator < (ItemIt it) const { + return (i < it.i); + } + + bool valid() const { return i != 0; } + private: + void first(const ItemList &il) { l=&il; i = l->begin(); validate(); } + void next() { + ++i; + validate(); + } + void validate() { + if ( i == l->end() ) + i = 0; + } + }; + + + + /** + * \brief Sets the iterator to point to the first element of the component. + * + * \anchor first2 + * Sets the iterator to point to the first element of the component. + * + * With the \ref first2 "first", \ref valid2 "valid" + * and \ref next2 "next" methods you can + * iterate through the elements of a component. For example + * (iterating through the component of the node \e node): + * \code + * Graph::Node node = ...; + * UnionFindEnum::MapType map(G); + * UnionFindEnum U(map); + * UnionFindEnum::ItemIt iiter; + * for (U.first(iiter, node); U.valid(iiter); U.next(iiter)) { + * // iiter is convertible to Graph::Node + * cout << iiter << endl; + * } + * \endcode + */ + + ItemIt& first(ItemIt& it, const T& a) const { + it.first( * _find(m[a])->my_class ); + return it; + } + + /** + * \brief Returns whether the iterator is valid. + * + * \anchor valid2 + * Returns whether the iterator is valid. + * + * With the \ref first2 "first", \ref valid2 "valid" + * and \ref next2 "next" methods you can + * iterate through the elements of a component. + * See the example here: \ref first2 "first". + */ + + bool valid(ItemIt const &it) const { + return it.valid(); + } + + /** + * \brief Steps the iterator to the next component. + * + * \anchor next2 + * Steps the iterator to the next component. + * + * With the \ref first2 "first", \ref valid2 "valid" + * and \ref next2 "next" methods you can + * iterate through the elements of a component. + * See the example here: \ref first2 "first". + */ + + ItemIt& next(ItemIt& it) const { + it.next(); + return it; + } + + }; + + + //! @} + +} //namespace lemon + +#endif //LEMON_UNION_FIND_H diff -r d8475431bbbb -r 8e85e6bbefdf lemon/utility.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/utility.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,152 @@ +/* -*- C++ -*- + * lemon/utility.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi + * Kutatocsoport (Egervary Research Group on Combinatorial Optimization, + * EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + * This file contains a modified version of the enable_if library from BOOST. + * See the appropriate copyright notice below. + */ + +// Boost enable_if library + +// Copyright 2003 Š The Trustees of Indiana University. + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Jaakko Järvi (jajarvi at osl.iu.edu) +// Jeremiah Willcock (jewillco at osl.iu.edu) +// Andrew Lumsdaine (lums at osl.iu.edu) + + +#ifndef LEMON_UTILITY_H +#define LEMON_UTILITY_H + +namespace lemon +{ + + /// Basic type for defining "tags". A "YES" condition for enable_if. + + /// \todo This should go to a separate "basic_types.h" (or something) + /// file. + struct True { + static const bool value = true; + }; + + /// Basic type for defining "tags". A "NO" condition for enable_if. + struct False { + static const bool value = false; + }; + + template + struct Wrap { + const T &value; + Wrap(const T &t) : value(t) {} + }; + + /**************** dummy class to avoid ambiguity ****************/ + + template struct dummy { dummy(int) {} }; + + /**************** enable_if from BOOST ****************/ + + template + struct enable_if_c { + typedef T type; + }; + + template + struct enable_if_c {}; + + template + struct enable_if : public enable_if_c {}; + + template + struct lazy_enable_if_c { + typedef typename T::type type; + }; + + template + struct lazy_enable_if_c {}; + + template + struct lazy_enable_if : public lazy_enable_if_c {}; + + + template + struct disable_if_c { + typedef T type; + }; + + template + struct disable_if_c {}; + + template + struct disable_if : public disable_if_c {}; + + template + struct lazy_disable_if_c { + typedef typename T::type type; + }; + + template + struct lazy_disable_if_c {}; + + template + struct lazy_disable_if : public lazy_disable_if_c {}; + + // smart referencing + + template + struct SmartReference { + typedef _Type& Type; + }; + + template + struct SmartReference< + _Type, + typename enable_if::type + > { + typedef _Type Type; + }; + + template + struct SmartConstReference { + typedef const _Type& Type; + }; + + template + struct SmartConstReference< + _Type, + typename enable_if::type + > { + typedef const _Type Type; + }; + + template + struct SmartParameter { + typedef _Type& Type; + }; + + template + struct SmartParameter< + _Type, + typename enable_if::type + > { + typedef const _Type& Type; + }; + +} // namespace lemon + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf lemon/xy.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/xy.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,518 @@ +/* -*- C++ -*- + * lemon/xy.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_XY_H +#define LEMON_XY_H + +#include +#include + +///\ingroup misc +///\file +///\brief A simple two dimensional vector and a bounding box implementation +/// +/// The class \ref lemon::xy "xy" implements +///a two dimensional vector with the usual +/// operations. +/// +/// The class \ref lemon::BoundingBox "BoundingBox" can be used to determine +/// the rectangular bounding box of a set of \ref lemon::xy "xy"'s. +/// +///\author Attila Bernath + + +namespace lemon { + + /// \addtogroup misc + /// @{ + + /// A simple two dimensional vector (plainvector) implementation + + /// A simple two dimensional vector (plainvector) implementation + ///with the usual vector + /// operators. + /// + ///\author Attila Bernath + template + class xy { + + public: + + typedef T Value; + + T x,y; + + ///Default constructor + xy() {} + + ///Constructing the instance from coordinates + xy(T a, T b) : x(a), y(b) { } + + + ///Conversion constructor + template xy(const xy &p) : x(p.x), y(p.y) {} + + ///Gives back the square of the norm of the vector + T normSquare() const { + return x*x+y*y; + } + + ///Increments the left hand side by u + xy& operator +=(const xy& u) { + x += u.x; + y += u.y; + return *this; + } + + ///Decrements the left hand side by u + xy& operator -=(const xy& u) { + x -= u.x; + y -= u.y; + return *this; + } + + ///Multiplying the left hand side with a scalar + xy& operator *=(const T &u) { + x *= u; + y *= u; + return *this; + } + + ///Dividing the left hand side by a scalar + xy& operator /=(const T &u) { + x /= u; + y /= u; + return *this; + } + + ///Returns the scalar product of two vectors + T operator *(const xy& u) const { + return x*u.x+y*u.y; + } + + ///Returns the sum of two vectors + xy operator+(const xy &u) const { + xy b=*this; + return b+=u; + } + + ///Returns the neg of the vectors + xy operator-() const { + xy b=*this; + b.x=-b.x; b.y=-b.y; + return b; + } + + ///Returns the difference of two vectors + xy operator-(const xy &u) const { + xy b=*this; + return b-=u; + } + + ///Returns a vector multiplied by a scalar + xy operator*(const T &u) const { + xy b=*this; + return b*=u; + } + + ///Returns a vector divided by a scalar + xy operator/(const T &u) const { + xy b=*this; + return b/=u; + } + + ///Testing equality + bool operator==(const xy &u) const { + return (x==u.x) && (y==u.y); + } + + ///Testing inequality + bool operator!=(xy u) const { + return (x!=u.x) || (y!=u.y); + } + + }; + + ///Returns a vector multiplied by a scalar + + ///Returns a vector multiplied by a scalar + ///\relates xy + template xy operator*(const T &u,const xy &x) { + return x*u; + } + + ///Read a plainvector from a stream + + ///Read a plainvector from a stream + ///\relates xy + /// + template + inline std::istream& operator>>(std::istream &is, xy &z) { + char c; + if (is >> c) { + if (c != '(') is.putback(c); + } else { + is.clear(); + } + if (!(is >> z.x)) return is; + if (is >> c) { + if (c != ',') is.putback(c); + } else { + is.clear(); + } + if (!(is >> z.y)) return is; + if (is >> c) { + if (c != ')') is.putback(c); + } else { + is.clear(); + } + return is; + } + + ///Write a plainvector to a stream + + ///Write a plainvector to a stream + ///\relates xy + /// + template + inline std::ostream& operator<<(std::ostream &os, const xy& z) + { + os << "(" << z.x << ", " << z.y << ")"; + return os; + } + + ///Rotate by 90 degrees + + ///Returns its parameter rotated by 90 degrees in positive direction. + ///\relates xy + /// + template + inline xy rot90(const xy &z) + { + return xy(-z.y,z.x); + } + + ///Rotate by 270 degrees + + ///Returns its parameter rotated by 90 degrees in negative direction. + ///\relates xy + /// + template + inline xy rot270(const xy &z) + { + return xy(z.y,-z.x); + } + + + + /// A class to calculate or store the bounding box of plainvectors. + + /// A class to calculate or store the bounding box of plainvectors. + /// + ///\author Attila Bernath + template + class BoundingBox { + xy bottom_left, top_right; + bool _empty; + public: + + ///Default constructor: creates an empty bounding box + BoundingBox() { _empty = true; } + + ///Constructing the instance from one point + BoundingBox(xy a) { bottom_left=top_right=a; _empty = false; } + + ///Were any points added? + bool empty() const { + return _empty; + } + + ///Makes the BoundingBox empty + void clear() { + _empty=1; + } + + ///Gives back the bottom left corner (if the bounding box is empty, then the return value is not defined) + xy bottomLeft() const { + return bottom_left; + } + + ///Gives back the top right corner (if the bounding box is empty, then the return value is not defined) + xy topRight() const { + return top_right; + } + + ///Gives back the bottom right corner (if the bounding box is empty, then the return value is not defined) + xy bottomRight() const { + return xy(top_right.x,bottom_left.y); + } + + ///Gives back the top left corner (if the bounding box is empty, then the return value is not defined) + xy topLeft() const { + return xy(bottom_left.x,top_right.y); + } + + ///Gives back the bottom of the box (if the bounding box is empty, then the return value is not defined) + T bottom() const { + return bottom_left.y; + } + + ///Gives back the top of the box (if the bounding box is empty, then the return value is not defined) + T top() const { + return top_right.y; + } + + ///Gives back the left side of the box (if the bounding box is empty, then the return value is not defined) + T left() const { + return bottom_left.x; + } + + ///Gives back the right side of the box (if the bounding box is empty, then the return value is not defined) + T right() const { + return top_right.x; + } + + ///Gives back the height of the box (if the bounding box is empty, then the return value is not defined) + T height() const { + return top_right.y-bottom_left.y; + } + + ///Gives back the width of the box (if the bounding box is empty, then the return value is not defined) + T width() const { + return top_right.x-bottom_left.x; + } + + ///Checks whether a point is inside a bounding box + bool inside(const xy& u){ + if (_empty) + return false; + else{ + return ((u.x-bottom_left.x)*(top_right.x-u.x) >= 0 && + (u.y-bottom_left.y)*(top_right.y-u.y) >= 0 ); + } + } + + ///Increments a bounding box with a point + BoundingBox& operator +=(const xy& u){ + if (_empty){ + bottom_left=top_right=u; + _empty = false; + } + else{ + if (bottom_left.x > u.x) bottom_left.x = u.x; + if (bottom_left.y > u.y) bottom_left.y = u.y; + if (top_right.x < u.x) top_right.x = u.x; + if (top_right.y < u.y) top_right.y = u.y; + } + return *this; + } + + ///Sums a bounding box and a point + BoundingBox operator +(const xy& u){ + BoundingBox b = *this; + return b += u; + } + + ///Increments a bounding box with an other bounding box + BoundingBox& operator +=(const BoundingBox &u){ + if ( !u.empty() ){ + *this += u.bottomLeft(); + *this += u.topRight(); + } + return *this; + } + + ///Sums two bounding boxes + BoundingBox operator +(const BoundingBox& u){ + BoundingBox b = *this; + return b += u; + } + + };//class Boundingbox + + + ///Map of x-coordinates of an xy<>-map + + ///\ingroup maps + /// + template + class XMap + { + typename SmartReference::Type _map; + public: + typedef True NeedCopy; + + typedef typename M::Value::Value Value; + typedef typename M::Key Key; + ///\e + XMap(typename SmartParameter::Type map) : _map(map) {} + Value operator[](Key k) const {return _map[k].x;} + void set(Key k,Value v) {_map.set(k,typename M::Value(v,_map[k].y));} + }; + + ///Returns an \ref XMap class + + ///This function just returns an \ref XMap class. + /// + ///\ingroup maps + ///\relates XMap + template + inline XMap xMap(M &m) + { + return XMap(m); + } + + template + inline XMap xMap(const M &m) + { + return XMap(m); + } + + ///Constant (read only) version of \ref XMap + + ///\ingroup maps + /// + template + class ConstXMap + { + typename SmartConstReference::Type _map; + public: + typedef True NeedCopy; + + typedef typename M::Value::Value Value; + typedef typename M::Key Key; + ///\e + ConstXMap(const M &map) : _map(map) {} + Value operator[](Key k) const {return _map[k].x;} + }; + + ///Returns a \ref ConstXMap class + + ///This function just returns an \ref ConstXMap class. + /// + ///\ingroup maps + ///\relates ConstXMap + template + inline ConstXMap xMap(const M &m) + { + return ConstXMap(m); + } + + ///Map of y-coordinates of an xy<>-map + + ///\ingroup maps + /// + template + class YMap + { + typename SmartReference::Type _map; + public: + typedef True NeedCopy; + + typedef typename M::Value::Value Value; + typedef typename M::Key Key; + ///\e + YMap(typename SmartParameter::Type map) : _map(map) {} + Value operator[](Key k) const {return _map[k].y;} + void set(Key k,Value v) {_map.set(k,typename M::Value(_map[k].x,v));} + }; + + ///Returns an \ref YMap class + + ///This function just returns an \ref YMap class. + /// + ///\ingroup maps + ///\relates YMap + template + inline YMap yMap(M &m) + { + return YMap(m); + } + + template + inline YMap yMap(const M &m) + { + return YMap(m); + } + + ///Constant (read only) version of \ref YMap + + ///\ingroup maps + /// + template + class ConstYMap + { + typename SmartConstReference::Type _map; + public: + typedef True NeedCopy; + + typedef typename M::Value::Value Value; + typedef typename M::Key Key; + ///\e + ConstYMap(const M &map) : _map(map) {} + Value operator[](Key k) const {return _map[k].y;} + }; + + ///Returns a \ref ConstYMap class + + ///This function just returns an \ref ConstYMap class. + /// + ///\ingroup maps + ///\relates ConstYMap + template + inline ConstYMap yMap(const M &m) + { + return ConstYMap(m); + } + + + ///Map of the \ref xy::normSquare() "normSquare()" of an \ref xy "xy"-map + + ///Map of the \ref xy::normSquare() "normSquare()" of an \ref xy "xy"-map + ///\ingroup maps + /// + template + class NormSquareMap + { + typename SmartConstReference::Type _map; + public: + typedef True NeedCopy; + + typedef typename M::Value::Value Value; + typedef typename M::Key Key; + ///\e + NormSquareMap(const M &map) : _map(map) {} + Value operator[](Key k) const {return _map[k].normSquare();} + }; + + ///Returns a \ref NormSquareMap class + + ///This function just returns an \ref NormSquareMap class. + /// + ///\ingroup maps + ///\relates NormSquareMap + template + inline NormSquareMap normSquareMap(const M &m) + { + return NormSquareMap(m); + } + + /// @} + + +} //namespace lemon + +#endif //LEMON_XY_H diff -r d8475431bbbb -r 8e85e6bbefdf src/Makefile.am --- a/src/Makefile.am Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -if WANT_GUI - MAYBE_GUI = gui -endif -SUBDIRS = lemon benchmark demo test $(MAYBE_GUI) diff -r d8475431bbbb -r 8e85e6bbefdf src/benchmark/Makefile.am --- a/src/benchmark/Makefile.am Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src - -noinst_HEADERS = bench_tools.h - -noinst_PROGRAMS = graph-bench hcube bfs-bench - -graph_bench_SOURCES = graph-bench.cc - -hcube_SOURCES = hcube.cc - -bfs_bench_SOURCES = bfs-bench.cc diff -r d8475431bbbb -r 8e85e6bbefdf src/benchmark/bench_tools.h --- a/src/benchmark/bench_tools.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -// -*- mode:C++ -*- -#ifndef LEMON_BENCH_TEST_H -#define LEMON_BENCH_TEST_H - -#include -#include - -#include - -///An experimental typedef factory -#define GRAPH_TYPEDEF_FACTORY(Graph) \ - typedef typename Graph:: Node Node;\ - typedef typename Graph:: NodeIt NodeIt;\ - typedef typename Graph:: Edge Edge;\ - typedef typename Graph:: EdgeIt EdgeIt;\ - typedef typename Graph:: InEdgeIt InEdgeIt;\ - typedef typename Graph::OutEdgeIt OutEdgeIt; - -#define GRAPH_TYPEDEF_FACTORY_NOTYPENAME(Graph) \ - typedef Graph:: Node Node;\ - typedef Graph:: NodeIt NodeIt;\ - typedef Graph:: Edge Edge;\ - typedef Graph:: EdgeIt EdgeIt;\ - typedef Graph:: InEdgeIt InEdgeIt;\ - typedef Graph::OutEdgeIt OutEdgeIt; - - -///A primitive primtest - -///\bug 2 is not a prime according to this function! -/// -///\bug This function should go out of header file. I'm making it -/// inline for now. -inline bool isPrim(int n) -{ - if(n%2) { - for(int k=3;n/k>=k;k+=2) - if(!(n%k)) return false; - return true; - } - return false; -} - -///Finds the smallest prime not less then \c n. - -///\bug This function should go out of header file. I'm making it -/// inline for now. -inline int nextPrim(int n) -{ - for(n+=!(n%2);!isPrim(n);n+=2) ; - return n; -} - - -/// Class to generate consecutive primes -class Primes -{ - std::vector primes; - int n; - - bool isPrime(int m) - { - for(int i=0;m -void addHiperCube(Graph &G,int dim,std::vector &nodes) -{ - GRAPH_TYPEDEF_FACTORY(Graph); - - std::vector bits(dim+1); - bits[0]=1; - for(int i=1;i<=dim;i++) bits[i]=2*bits[i-1]; - - for(int i=0;i -void addBiDirHiperCube(Graph &G,int dim,std::vector&nodes) -{ - GRAPH_TYPEDEF_FACTORY(Graph); - - std::vector bits(dim+1); - bits[0]=1; - for(int i=1;i<=dim;i++) bits[i]=2*bits[i-1]; - - for(int i=0;i&2 - $2 $3 $4 $5 $6 $7 $8 $9 >/dev/null; - for ((i=1;i<=3;i++)) - do - $2 $3 $4 $5 $6 $7 $8 $9; - done | - awk '{print "'$1'",$0}' -} - -function runalltest() #postfix, CXX, CXXFLAGS -{ - echo $1 1>&2 - make clean >/dev/null - make CXX="$2" CXXFLAGS="$3" >/dev/null - { - runtest HCUBE19 hcube 19 - runtest BFS13-5000 hcube 13 5000 - runtest BFS10-50000 hcube 10 50000 - runtest GRBENCH graph-bench - } | awk "{print \$0, \"$1\"}" -} - -runalltest "gcc-3.3 -O2" g++ "-O2" -runalltest "gcc-3.3 -O2-march=pentium-m" g++ "-O2 -march=pentium-m" -runalltest "gcc-3.3 -O3" g++ "-O3" -runalltest "gcc-3.3 -O3-march=pentium-m" g++ "-O3 -march=pentium-m" - -runalltest "gcc-3.4 -O2" g++-3.4 "-O2" -runalltest "gcc-3.4 -O2-march=pentium-m" g++-3.4 "-O2 -march=pentium-m" -runalltest "gcc-3.4 -O3" g++-3.4 "-O3" -runalltest "gcc-3.4 -O3-march=pentium-m" g++-3.4 "-O3 -march=pentium-m" - -runalltest "icc -O2" icc "-O2" -runalltest "icc -O2-march=pentium-m" icc "-O2 -march=pentium-m" -runalltest "icc -O3" icc "-O3" -runalltest "icc -O3-march=pentium-m" icc "-O3 -march=pentium-m" - diff -r d8475431bbbb -r 8e85e6bbefdf src/benchmark/bfs-bench.cc --- a/src/benchmark/bfs-bench.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -// -*- mode:C++ -*- - -#include -#include -#include -#include"bench_tools.h" - -using namespace std; -using namespace lemon; - -inline int numOfOnes(int n,int dim) -{ - int s=0; - for(int i=0;i>=1; - } - return s; -} - -inline int numOfZeros(int n,int dim) -{ - int s=dim; - for(int i=0;i>=1; - } - return s; -} - -template -void bfsStlQueue(Graph &G,typename Graph::Node source) -{ - GRAPH_TYPEDEF_FACTORY(Graph); - - using namespace std; - - typename Graph::template NodeMap visited(G,false); - - queue Q; - - Q.push(source); - visited[source]=true; - do { - Node n(Q.front()); - Node m; - Q.pop(); - for(OutEdgeIt e(G,n);e!=INVALID;++e) - if(!visited[m=G.target(e)]) { - Q.push(m); - visited.set(m,true); - } - } while(!Q.empty()); -} - -template -void bfsOwnQueue(Graph &G,typename Graph::Node source) -{ - GRAPH_TYPEDEF_FACTORY(Graph); - - using namespace std; - - typename Graph::template NodeMap visited(G,false); - - int N=G.nodeNum(); - vector Q(N); - int Qh=0; - int Qt=0; - - - Q[Qh++]=source; - visited.set(source,true); - do { - Node m; - Node n=Q[Qt++]; - for(OutEdgeIt e(G,n);e!=INVALID;++e) - if(!visited[m=G.target(e)]) { - Q[Qh++]=m; - visited.set(m,true); - } - } while(Qt!=Qh); -} - -template -void iteratorBench(Graph &G) -{ - GRAPH_TYPEDEF_FACTORY(Graph); - - int i=0; - - for(NodeIt n(G);n!=INVALID;++n) - for(OutEdgeIt e(G,n);e!=INVALID;++e) - i++; -} - -int main(int argc, char *argv[]) -{ - typedef SmartGraph Graph; - - ///\bug GRAPH_TYPEDEF_FACTORY(Graph); - GRAPH_TYPEDEF_FACTORY_NOTYPENAME(Graph); - - Graph G; - - Timer T; - - if(argc!=3) { - cout << "Usage: " << argv[0] << " dim mul\n"; - return 1; - } - - int dim=atoi(argv[1]); - int mul=atoi(argv[2]); - -// cout << "Creating Hipercube ("<< (1< nodes; - addBiDirHiperCube(G,dim,nodes); - - PrintTime("GENGRAPH",T); - - T.reset(); - { - for(int i=0;i - -#include"bench_tools.h" - -using namespace lemon; - -///Makes a full graph by adding and deleting a lot of edges; - -///\param n Number of nodes. -///\param rat The funcion will make \f$rat\timesn^2\f$ edge addition and -///\f$(rat-1)\timesn^2\f$ deletion. -///\param p Tuning parameters. -///\warning \c rat, \c p, and \c n must be pairwise relative primes. -template -void makeFullGraph(int n, int rat, int p) -{ - GRAPH_TYPEDEF_FACTORY(Graph); - - Graph G; - - // Node nodes[n]; - std::vector nodes(n); - for(int i=0;i equ(rat); - - long long int count; - - for(count=0;count(nextPrim(1000),nextPrim(300),nextPrim(100)); - - PrintTime("BIG",T); - T.reset(); - makeFullGraph(nextPrim(100),nextPrim(30000),nextPrim(150)); - - PrintTime("SMALL",T); -} diff -r d8475431bbbb -r 8e85e6bbefdf src/benchmark/hcube.cc --- a/src/benchmark/hcube.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -// -*- mode:C++ -*- - -#include -#include -#include -#include -#include - -#include"bench_tools.h" - -using namespace std; -using namespace lemon; - -inline int numOfOnes(int n,int dim) -{ - int s=0; - for(int i=0;i>=1; - } - return s; -} - -inline int numOfZeros(int n,int dim) -{ - int s=dim; - for(int i=0;i>=1; - } - return s; -} - -int main(int argc, char *argv[]) -{ - // typedef ListGraph Graph; - typedef SmartGraph Graph; - - ///\bug GRAPH_TYPEDEF_FACTORY(Graph); - GRAPH_TYPEDEF_FACTORY_NOTYPENAME(Graph); - - Graph G; - - Timer T; - - if(argc!=2) { - cout << "Usage: " << argv[0] << " dim\n"; - return 1; - } - - int dim=atoi(argv[1]); - -// cout << "Creating Hipercube ("<< (1< nodes; - addBiDirHiperCube(G,dim,nodes); - - PrintTime("GENGRAPH",T); - - T.reset(); - Graph::EdgeMap map(G); - for(int i=0;i<5;i++) { - Primes P; - for(int i=0;i Dij(G,map); - for(int i=0;i<10;i++) - Dij.run(nodes[0]); - } - PrintTime("DIJKSTRA",T); - - T.reset(); - { - Graph::EdgeMap flow(G); - - Preflow MF(G,nodes[0],nodes[1< - -#include -#include -#include -#include - -using namespace std; -using namespace lemon; - -int main() { - typedef UndirSmartGraph Graph; - typedef Graph::Node Node; - typedef Graph::NodeIt NodeIt; - typedef Graph::UndirEdge UndirEdge; - typedef Graph::IncEdgeIt IncEdgeIt; - - Graph graph; - - UndirGraphReader reader(std::cin, graph); - Graph::NodeMap > coords(graph); - reader.readNodeMap("coords", coords); - - reader.run(); - - Graph::NodeMap color(graph, -2); - - Graph::NodeMap heapMap(graph, -1); - BinHeap > heap(heapMap); - - for (NodeIt it(graph); it != INVALID; ++it) { - heap.push(it, countOutEdges(graph, it)); - } - - vector order; - - while (!heap.empty()) { - Node node = heap.top(); - heap.pop(); - color[node] = -1; - order.push_back(node); - for (IncEdgeIt it(graph, node); it != INVALID; ++it) { - Node target = graph.runningNode(it); - if (color[target] == -2) { - heap.decrease(target, heap[target] - 1); - } - } - } - - for (int i = order.size() - 1; i >= 0; --i) { - set forbidden; - for (IncEdgeIt it(graph, order[i]); it != INVALID; ++it) { - Node target = graph.runningNode(it); - if (color[target] != -1) { - forbidden.insert(color[target]); - } - } - int current = 0; - while (forbidden.find(current) != forbidden.end()) ++current; - color[order[i]] = current; - } - - ColorSet colorSet; - - graphToEps(graph, "six_coloring.eps"). - title("Six Colored Graph").copyright("(C) 2005 LEMON Project"). - coords(coords).nodeColors(composeMap(colorSet, color)). - scaleToA4().run(); - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/demo/dijkstra_demo.cc --- a/src/demo/dijkstra_demo.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -#include - -#include -#include - -using namespace lemon; - - -int main (int, char*[]) -{ - - typedef ListGraph Graph; - typedef Graph::Node Node; - typedef Graph::Edge Edge; - typedef Graph::EdgeMap LengthMap; - - Graph g; - - //An example from Ahuja's book - - Node s=g.addNode(); - Node v2=g.addNode(); - Node v3=g.addNode(); - Node v4=g.addNode(); - Node v5=g.addNode(); - Node t=g.addNode(); - - Edge s_v2=g.addEdge(s, v2); - Edge s_v3=g.addEdge(s, v3); - Edge v2_v4=g.addEdge(v2, v4); - Edge v2_v5=g.addEdge(v2, v5); - Edge v3_v5=g.addEdge(v3, v5); - Edge v4_t=g.addEdge(v4, t); - Edge v5_t=g.addEdge(v5, t); - - LengthMap len(g); - - len.set(s_v2, 10); - len.set(s_v3, 10); - len.set(v2_v4, 5); - len.set(v2_v5, 8); - len.set(v3_v5, 5); - len.set(v4_t, 8); - len.set(v5_t, 8); - - std::cout << "The id of s is " << g.id(s)<< ", the id of t is " << g.id(t)<<"."< dijkstra_test(g,len); - - dijkstra_test.run(s); - - - std::cout << "The distance of node t from node s: " << dijkstra_test.dist(t)< dot_output_file -// This program makes a dot file from a dimacs max flow file. -// This program can be an aid in making up to date visualized documantation -// of demo programs. - -#include -#include - -#include -#include - -using namespace lemon; - -using std::cout; -using std::endl; - -int main() -{ - typedef SmartGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef Graph::EdgeMap LengthMap; - - Graph g; - Node s, t; - LengthMap length(g); - - readDimacs(std::cin, g, length, s, t); - - cout << "digraph lemon_dot_example {" << endl; - cout << " node [ shape=ellipse, fontname=Helvetica, fontsize=10 ];" << endl; - for(NodeIt n(g); n!=INVALID; ++n) { - if (n==s) { - cout << " n" << g.id(n) - << " [ label=\"" << g.id(n) << " (s)\" ]; " << endl; - } else { - if (n==t) { - cout << " n" << g.id(n) - << " [ label=\"" << g.id(n) << " (t)\" ]; " << endl; - } else { - cout << " n" << g.id(n) - << " [ label=\"" << g.id(n) << "\" ]; " << endl; - } - } - } - cout << " edge [ shape=ellipse, fontname=Helvetica, fontsize=10 ];" << endl; - for(EdgeIt e(g); e!=INVALID; ++e) { - cout << " n" << g.id(g.source(e)) << " -> " << " n" << g.id(g.target(e)) - << " [ label=\"" << g.id(e) - << ", length:" << length[e] << "\" ]; " << endl; - } - cout << "}" << endl; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/demo/dim_to_lgf.cc --- a/src/demo/dim_to_lgf.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -using namespace std; -using namespace lemon; - -const char* versionString = -"dim_to_lgf - part of lemon library\n"; - -const char* helpString = -"Dimacs to LGF converter\n" -"Usage: dim_to_lgf [OPTIONS]\n" -"\n" -"Examples:\n" -" dim_to_lgf --type shortestpath --input graph.dim --output graph.lgf\n" -"\n" -"Options:\n" -" -i FILE, --input FILE use FILE as input instead of standard input\n" -" -o FILE, --output FILE use FILE as output instead of standard output\n" -" -t TYPE, --type TYPE set up the type of the graph\n" -" Possible types:\n" -" mincostflow\n" -" maxflow (default)\n" -" shortestpath\n" -" capacitated\n" -" plain\n" -" -v, --version shows the version of the converter\n" -" -h, --help shows the help of the converter\n"; - - -int main(int argc, const char *argv[]) { - typedef SmartGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef Graph::EdgeMap StringMap; - - std::string inputName; - std::string outputName; - std::string typeName; - - bool help = false; - bool version = false; - - for (int arg = 1; arg < argc; ++arg) { - if (strcmp(argv[arg], "--type") == 0 || - strcmp(argv[arg], "-t") == 0) { - if (!typeName.empty()) { - cerr << "Multiple type description" << endl; - return -1; - } - if (arg + 1 == argc) { - cerr << "Parameter without value" << endl; - return -1; - } - typeName = argv[++arg]; - } - else if (strcmp(argv[arg], "--input") == 0 || - strcmp(argv[arg], "-i") == 0) { - if (!inputName.empty()) { - cerr << "Multiple input description" << endl; - return -1; - } - if (arg + 1 == argc) { - cerr << "Parameter without value" << endl; - return -1; - } - inputName = argv[++arg]; - } - else if (strcmp(argv[arg], "--output") == 0 || - strcmp(argv[arg], "-o") == 0) { - if (!outputName.empty()) { - cerr << "Multiple input description" << endl; - return -1; - } - if (arg + 1 == argc) { - cerr << "Parameter without value" << endl; - return -1; - } - outputName = argv[++arg]; - } else if (strcmp(argv[arg], "--help") == 0 || - strcmp(argv[arg], "-h") == 0) { - help = true; - } else if (strcmp(argv[arg], "--version") == 0 || - strcmp(argv[arg], "-v") == 0) { - version = true; - } else { - cerr << "Invalid option: " << argv[arg] << endl; - return -1; - } - } - - if (version) { - cout << versionString; - } - if (help) { - cout << helpString; - } - if (help || version) { - return 0; - } - - ifstream input; - if (!inputName.empty()) { - input.open(inputName.c_str()); - if (!input) { - cerr << "File open error" << endl; - return -1; - } - } - istream& is = (inputName.empty() ? cin : input); - - ofstream output; - if (!outputName.empty()) { - output.open(outputName.c_str()); - if (!output) { - cerr << "File open error" << endl; - return -1; - } - } - ostream& os = (outputName.empty() ? cout : output); - - if (typeName.empty()) { - typeName = "maxflow"; - } - - if (typeName == "mincostflow") { - Graph graph; - Node s, t; - StringMap cost(graph), capacity(graph); - readDimacs(is, graph, capacity, s, t, cost); - writeGraph(os, graph, capacity, s, t, cost); - } else if (typeName == "maxflow") { - Graph graph; - Node s, t; - StringMap capacity(graph); - readDimacs(is, graph, capacity, s, t); - writeGraph(os, graph, capacity, s, t); - } else if (typeName == "shortestpath") { - Graph graph; - Node s; - StringMap capacity(graph); - readDimacs(is, graph, capacity, s); - writeGraph(os, graph, capacity, s); - } else if (typeName == "capacitated") { - Graph graph; - StringMap capacity(graph); - readDimacs(is, graph, capacity); - writeGraph(os, graph, capacity); - } else if (typeName == "plain") { - Graph graph; - readDimacs(is, graph); - writeGraph(os, graph); - } else { - cerr << "Invalid type error" << endl; - return -1; - } - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/demo/graph_to_eps_demo.cc --- a/src/demo/graph_to_eps_demo.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -/* -*- C++ -*- - * src/lemon/demo/graph_to_eps.cc - - * Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include -#include -#include -#include - -#include - - -using namespace std; -using namespace lemon; - -int main() -{ - ColorSet colorSet; - - ListGraph g; - typedef ListGraph::Node Node; - typedef ListGraph::NodeIt NodeIt; - typedef ListGraph::Edge Edge; - typedef xy Xy; - - Node n1=g.addNode(); - Node n2=g.addNode(); - Node n3=g.addNode(); - Node n4=g.addNode(); - Node n5=g.addNode(); - - ListGraph::NodeMap coords(g); - ListGraph::NodeMap sizes(g); - ListGraph::NodeMap colors(g); - ListGraph::NodeMap shapes(g); - ListGraph::EdgeMap ecolors(g); - ListGraph::EdgeMap widths(g); - - coords[n1]=Xy(50,50); sizes[n1]=1; colors[n1]=1; shapes[n1]=0; - coords[n2]=Xy(50,70); sizes[n2]=2; colors[n2]=2; shapes[n2]=2; - coords[n3]=Xy(70,70); sizes[n3]=1; colors[n3]=3; shapes[n3]=0; - coords[n4]=Xy(70,50); sizes[n4]=2; colors[n4]=4; shapes[n4]=1; - coords[n5]=Xy(85,60); sizes[n5]=3; colors[n5]=5; shapes[n5]=2; - - Edge e; - - e=g.addEdge(n1,n2); ecolors[e]=0; widths[e]=1; - e=g.addEdge(n2,n3); ecolors[e]=0; widths[e]=1; - e=g.addEdge(n3,n5); ecolors[e]=0; widths[e]=3; - e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1; - e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1; - e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2; - e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1; - - IdMap id(g); - - graphToEps(g,"graph_to_eps_demo_out.eps").scale(10).coords(coords). - title("Sample .eps figure"). - copyright("(C) 2005 LEMON Project"). - nodeScale(2).nodeSizes(sizes). - nodeShapes(shapes). - nodeColors(composeMap(colorSet,colors)). - edgeColors(composeMap(colorSet,ecolors)). - edgeWidthScale(.4).edgeWidths(widths). - nodeTexts(id).nodeTextSize(3). - run(); - - graphToEps(g,"graph_to_eps_demo_out_arr.eps").scale(10). - title("Sample .eps figure (with arrowheads)"). - copyright("(C) 2005 LEMON Project"). - nodeColors(composeMap(colorSet,colors)). - coords(coords). - nodeScale(2).nodeSizes(sizes). - nodeShapes(shapes). - edgeColors(composeMap(colorSet,ecolors)). - edgeWidthScale(.4).edgeWidths(widths). - nodeTexts(id).nodeTextSize(3). - drawArrows().arrowWidth(1).arrowLength(1). - run(); - - e=g.addEdge(n1,n4); ecolors[e]=2; widths[e]=1; - e=g.addEdge(n4,n1); ecolors[e]=1; widths[e]=2; - - e=g.addEdge(n1,n2); ecolors[e]=1; widths[e]=1; - e=g.addEdge(n1,n2); ecolors[e]=2; widths[e]=1; - e=g.addEdge(n1,n2); ecolors[e]=3; widths[e]=1; - e=g.addEdge(n1,n2); ecolors[e]=4; widths[e]=1; - e=g.addEdge(n1,n2); ecolors[e]=5; widths[e]=1; - e=g.addEdge(n1,n2); ecolors[e]=6; widths[e]=1; - e=g.addEdge(n1,n2); ecolors[e]=7; widths[e]=1; - - graphToEps(g,"graph_to_eps_demo_out_par.eps").scale(10). - title("Sample .eps figure (parallel edges)"). - copyright("(C) 2005 LEMON Project"). - nodeShapes(shapes). - coords(coords). - nodeScale(2).nodeSizes(sizes). - nodeColors(composeMap(colorSet,colors)). - edgeColors(composeMap(colorSet,ecolors)). - edgeWidthScale(.4).edgeWidths(widths). - nodeTexts(id).nodeTextSize(3). - enableParallel().parEdgeDist(1.5). - run(); - - graphToEps(g,"graph_to_eps_demo_out_par_arr.eps").scale(10). - title("Sample .eps figure (parallel edges and arrowheads)"). - copyright("(C) 2005 LEMON Project"). - nodeScale(2).nodeSizes(sizes). - coords(coords). - nodeShapes(shapes). - nodeColors(composeMap(colorSet,colors)). - edgeColors(composeMap(colorSet,ecolors)). - edgeWidthScale(.3).edgeWidths(widths). - nodeTexts(id).nodeTextSize(3). - enableParallel().parEdgeDist(1). - drawArrows().arrowWidth(1).arrowLength(1). - run(); - - graphToEps(g,"graph_to_eps_demo_out_a4.eps").scaleToA4(). - title("Sample .eps figure (fits to A4)"). - copyright("(C) 2005 LEMON Project"). - nodeScale(2).nodeSizes(sizes). - coords(coords). - nodeShapes(shapes). - nodeColors(composeMap(colorSet,colors)). - edgeColors(composeMap(colorSet,ecolors)). - edgeWidthScale(.3).edgeWidths(widths). - nodeTexts(id).nodeTextSize(3). - enableParallel().parEdgeDist(1). - drawArrows().arrowWidth(1).arrowLength(1). - run(); - - ListGraph h; - ListGraph::NodeMap hcolors(h); - ListGraph::NodeMap hcoords(h); - - int cols=int(sqrt(double(colorSet.size()))); - for(int i=0;i -#include - -using namespace lemon; - -int main() -{ - typedef ListGraph Graph; - typedef Graph::Edge Edge; - typedef Graph::InEdgeIt InEdgeIt; - typedef Graph::OutEdgeIt OutEdgeIt; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::Node Node; - typedef Graph::NodeIt NodeIt; - - Graph g; - - for (int i = 0; i < 3; i++) - g.addNode(); - - for (NodeIt i(g); i!=INVALID; ++i) - for (NodeIt j(g); j!=INVALID; ++j) - if (i != j) g.addEdge(i, j); - - std::cout << "Nodes:"; - for (NodeIt i(g); i!=INVALID; ++i) - std::cout << " " << g.id(i); - std::cout << std::endl; - - std::cout << "Edges:"; - for (EdgeIt i(g); i!=INVALID; ++i) - std::cout << " (" << g.id(g.source(i)) << "," << g.id(g.target(i)) << ")"; - std::cout << std::endl; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/demo/kruskal_demo.cc --- a/src/demo/kruskal_demo.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -#include -#include - -#include -#include -#include - - -using namespace std; -using namespace lemon; - - -int main() { - - typedef ListGraph::Node Node; - typedef ListGraph::Edge Edge; - typedef ListGraph::NodeIt NodeIt; - typedef ListGraph::EdgeIt EdgeIt; - - ListGraph G; - - Node s=G.addNode(); - Node v1=G.addNode(); - Node v2=G.addNode(); - Node v3=G.addNode(); - Node v4=G.addNode(); - Node t=G.addNode(); - - Edge e1 = G.addEdge(s, v1); - Edge e2 = G.addEdge(s, v2); - Edge e3 = G.addEdge(v1, v2); - Edge e4 = G.addEdge(v2, v1); - Edge e5 = G.addEdge(v1, v3); - Edge e6 = G.addEdge(v3, v2); - Edge e7 = G.addEdge(v2, v4); - Edge e8 = G.addEdge(v4, v3); - Edge e9 = G.addEdge(v3, t); - Edge e10 = G.addEdge(v4, t); - - typedef ListGraph::EdgeMap ECostMap; - typedef ListGraph::EdgeMap EBoolMap; - - ECostMap edge_cost_map(G, 2); - EBoolMap tree_map(G); - - - //Test with const map. - std::cout << "The weight of the minimum spanning tree is " << kruskalEdgeMap(G, ConstMap(2), tree_map)< tree_edge_vec; - - //Test with a edge map and inserter. - check(kruskalEdgeMap_IteratorOut(G, edge_cost_map, - back_inserter(tree_edge_vec)) - ==-31, - "Total cost should be -31."); - - tree_edge_vec.clear(); - - //The above test could also be coded like this: - check(kruskal(G, - makeKruskalMapInput(G, edge_cost_map), - makeKruskalSequenceOutput(back_inserter(tree_edge_vec))) - ==-31, - "Total cost should be -31."); - - check(tree_edge_vec.size()==5,"The tree should have 5 edges."); - - check(tree_edge_vec[0]==e1 && - tree_edge_vec[1]==e2 && - tree_edge_vec[2]==e5 && - tree_edge_vec[3]==e7 && - tree_edge_vec[4]==e9, - "Wrong tree."); -*/ - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/demo/lp_demo.cc --- a/src/demo/lp_demo.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - - -#ifdef HAVE_GLPK -#include -#elif HAVE_CPLEX -#include -#endif - -using namespace lemon; - -#ifdef HAVE_GLPK -typedef LpGlpk LpDefault; -#elif HAVE_CPLEX -typedef LpCplex LpDefault; -#endif - -int main() -{ - //The following example is taken from the documentation of the GLPK library. - //See it in the GLPK reference manual and among the GLPK sample files (sample.c) - LpDefault lp; - typedef LpDefault::Row Row; - typedef LpDefault::Col Col; - - lp.max(); - - Col x1 = lp.addCol(); - Col x2 = lp.addCol(); - Col x3 = lp.addCol(); - - //One solution - // Row p = lp.addRow(); - // Row q = lp.addRow(); - // Row r = lp.addRow(); - // lp.setRow(p,x1+x2+x3 <=100); - // lp.setRow(q,10*x1+4*x2+5*x3<=600); - // lp.setRow(r,2*x1+2*x2+6*x3<=300); - - //A more elegant one - //Constraints - lp.addRow(x1+x2+x3 <=100); - lp.addRow(10*x1+4*x2+5*x3<=600); - lp.addRow(2*x1+2*x2+6*x3<=300); - //Nonnegativity of the variables - lp.colLowerBound(x1, 0); - lp.colLowerBound(x2, 0); - lp.colLowerBound(x3, 0); - //Objective function - lp.setObj(10*x1+6*x2+4*x3); - - lp.solve(); - - if (lp.primalStatus()==LpSolverBase::OPTIMAL){ - printf("Z = %g; x1 = %g; x2 = %g; x3 = %g\n", - lp.primalValue(), - lp.primal(x1), lp.primal(x2), lp.primal(x3)); - } - else{ - std::cout<<"Optimal solution not found!"< -#endif - -#include -#include - - -#ifdef HAVE_GLPK -#include -#elif HAVE_CPLEX -#include -#endif - -using namespace lemon; - -#ifdef HAVE_GLPK -typedef LpGlpk LpDefault; -#elif HAVE_CPLEX -typedef LpCplex LpDefault; -#endif - - -template -double maxFlow(const G &g,const C &cap,typename G::Node s,typename G::Node t) -{ - LpDefault lp; - - typedef G Graph; - typedef typename G::Node Node; - typedef typename G::NodeIt NodeIt; - typedef typename G::Edge Edge; - typedef typename G::EdgeIt EdgeIt; - typedef typename G::OutEdgeIt OutEdgeIt; - typedef typename G::InEdgeIt InEdgeIt; - - typename G::template EdgeMap x(g); - lp.addColSet(x); - - for(EdgeIt e(g);e!=INVALID;++e) { - lp.colUpperBound(x[e],cap[e]); - lp.colLowerBound(x[e],0); - } - - for(NodeIt n(g);n!=INVALID;++n) if(n!=s&&n!=t) { - LpDefault::Expr ex; - for(InEdgeIt e(g,n);e!=INVALID;++e) ex+=x[e]; - for(OutEdgeIt e(g,n);e!=INVALID;++e) ex-=x[e]; - lp.addRow(ex==0); - } - { - LpDefault::Expr ex; - for(InEdgeIt e(g,t);e!=INVALID;++e) ex+=x[e]; - for(OutEdgeIt e(g,t);e!=INVALID;++e) ex-=x[e]; - lp.setObj(ex); - } - lp.max(); - -#ifdef HAVE_GLPK - lp.presolver(true); - lp.messageLevel(3); -#endif - - lp.solve(); - - return lp.primalValue(); -} - -int main() -{ - ListGraph g; - ListGraph::Node s; - ListGraph::Node t; - - ListGraph::EdgeMap cap(g); - - GraphReader reader(std::cin,g); - reader.readNode("source",s).readNode("target",t) - .readEdgeMap("capacity",cap).run(); - - // std::ifstream file("../test/preflow_"); -// readDimacs(file, g, cap, s, t); - - std::cout << "Max flow value = " << maxFlow(g,cap,s,t) << std::endl; - -} diff -r d8475431bbbb -r 8e85e6bbefdf src/demo/min_route.cc --- a/src/demo/min_route.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - - -using namespace lemon; - -template -class PotentialMap { -public: - typedef double Value; - typedef typename CoordMap::Key Key; - - PotentialMap(const CoordMap& _coord, const xy& _target) - : coord(_coord), target(_target) {} - - double operator[](const Key& node) const { - return std::sqrt((coord[node].x - target.x) * (coord[node].x - target.x) + - (coord[node].y - target.y) * (coord[node].y - target.y)); - } -private: - const CoordMap& coord; - xy target; -}; - -template -class ReducedLengthMap { -public: - typedef double Value; - typedef typename LengthMap::Key Key; - - ReducedLengthMap(const Graph& _graph, const LengthMap& _length, - const PotentialMap& _pot) - : graph(_graph), length(_length), pot(_pot) {} - - Value operator[](const Key& edge) const { - return length[edge] - (pot[graph.source(edge)] - pot[graph.target(edge)]); - } - -private: - const Graph& graph; - const LengthMap& length; - const PotentialMap& pot; -}; - -int main() { - typedef SmartGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef Graph::EdgeMap LengthMap; - typedef Graph::NodeMap > CoordMap; - - SmartGraph graph; - - std::ifstream is("route.lgf"); - GraphReader reader(is, graph); - - CoordMap coord(graph); - XMap xcoord = xMap(coord); - reader.readNodeMap("coordinates_x", xcoord); - YMap ycoord = yMap(coord); - reader.readNodeMap("coordinates_y", ycoord); - - LengthMap length(graph); - reader.readEdgeMap("length", length); - - Node source, target; - reader.readNode("source", source); - reader.readNode("target", target); - - reader.run(); - - { - Timer timer; - Dijkstra dijkstra(graph, length); - dijkstra.init(); - dijkstra.addSource(source); - dijkstra.start(target); - - std::cout << dijkstra.dist(target) << std::endl; - std::cout << timer << std::endl; - } - { - Timer timer; - typedef PotentialMap Potential; - Potential potential(coord, coord[target]); - - typedef ReducedLengthMap ReducedLength; - ReducedLength reduced(graph, length, potential); - - Dijkstra dijkstra(graph, reduced); - - dijkstra.init(); - dijkstra.addSource(source); - dijkstra.start(target); - - std::cout << dijkstra.dist(target) + potential[source] << std::endl; - std::cout << timer << std::endl; - } - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/demo/route.lgf --- a/src/demo/route.lgf Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -@nodeset -id coordinates_x coordinates_y -9 447.907 578.328 -8 79.2573 909.464 -7 878.677 960.04 -6 11.5504 938.413 -5 327.398 815.035 -4 427.002 954.002 -3 148.549 753.748 -2 903.889 326.476 -1 408.248 577.327 -0 189.239 92.5316 -@edgeset - length -2 3 901.074 -8 5 270.85 -6 9 601.553 -5 9 285.022 -9 4 408.091 -3 0 719.712 -7 5 612.836 -0 4 933.353 -5 0 778.871 -5 5 0 -7 1 664.049 -5 5 0 -0 9 560.464 -4 8 352.36 -4 9 399.625 -4 1 402.171 -1 2 591.688 -3 8 182.376 -4 5 180.254 -3 1 345.283 -5 4 184.511 -6 2 1112.45 -0 1 556.624 -@nodes -source 1 -target 8 -@end diff -r d8475431bbbb -r 8e85e6bbefdf src/demo/sub_graph_adaptor_demo.cc --- a/src/demo/sub_graph_adaptor_demo.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -// -*- c++ -*- - -// Use a DIMACS max flow file as stdin. -// sub_graph_adaptor_demo < dimacs_max_flow_file -// This program computes a maximum number of edge-disjoint shortest paths -// between s and t. - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace lemon; - -using std::cout; -using std::endl; - -int main() -{ - typedef SmartGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef Graph::EdgeMap LengthMap; - - Graph g; - Node s, t; - LengthMap length(g); - - readDimacs(std::cin, g, length, s, t); - - cout << "edges with lengths (of form id, source--length->target): " << endl; - for(EdgeIt e(g); e!=INVALID; ++e) - cout << " " << g.id(e) << ", " << g.id(g.source(e)) << "--" - << length[e] << "->" << g.id(g.target(e)) << endl; - - cout << "s: " << g.id(s) << " t: " << g.id(t) << endl; - - typedef Dijkstra Dijkstra; - Dijkstra dijkstra(g, length); - dijkstra.run(s); - - // This map returns true exactly for those edges which are - // tight w.r.t the length funcion and the potential - // given by the dijkstra algorithm. - typedef TightEdgeFilterMap - TightEdgeFilter; - TightEdgeFilter tight_edge_filter(g, dijkstra.distMap(), length); - -// ConstMap const_true_map(true); - // This graph contains exaclty the tight edges. -// typedef SubGraphAdaptor, TightEdgeFilter> SubGW; - typedef EdgeSubGraphAdaptor SubGW; - SubGW gw(g, tight_edge_filter); - - ConstMap const_1_map(1); - Graph::EdgeMap flow(g, 0); - // Max flow between s and t in the graph of tight edges. - Preflow, Graph::EdgeMap > - preflow(gw, s, t, const_1_map, flow); - preflow.run(); - - cout << "maximum number of edge-disjoint shortest path: " - << preflow.flowValue() << endl; - cout << "edges of the maximum number of edge-disjoint shortest s-t paths: " - << endl; - for(EdgeIt e(g); e!=INVALID; ++e) - if (flow[e]) - cout << " " << g.id(e) << ", " - << g.id(g.source(e)) << "--" - << length[e] << "->" << g.id(g.target(e)) << endl; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/demo/sub_graph_adaptor_demo.dim --- a/src/demo/sub_graph_adaptor_demo.dim Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -c LEMON max flow problem -p max 7 9 -n 1 s -n 7 t -a 1 2 3 -a 1 3 2 -a 1 4 1 -a 2 5 3 -a 3 5 2 -a 3 7 5 -a 3 6 3 -a 4 6 1 -a 5 7 2 -a 6 7 4 diff -r d8475431bbbb -r 8e85e6bbefdf src/demo/tight_edge_filter_map.h --- a/src/demo/tight_edge_filter_map.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* -*- C++ -*- - * src/lemon/tight_edge_filter_map.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_TIGHT_EDGE_FILTER_MAP_H -#define LEMON_TIGHT_EDGE_FILTER_MAP_H - -#include - -// /// \file -// /// \brief Maximum flow algorithms. -// /// \ingroup galgs - -namespace lemon { - - /*! - \brief A map for filtering the edge-set to those edges - which are tight w.r.t. a node-potential and - edge-distance. - - Let \f$G=(V,A)\f$ be a directed graph (graph for short) and - let \f$\mathbb{F}\f$ be a number type. - Given a distance function - \f$d:E\to\mathbb{F}\f$, - \f$\pi:V\to\mathbb{F}\f$ is said to be a potetial - w.r.t. \f$d\f$ - if and only if - \f$\pi(v)\le d(uv)+\pi(u)\f$ holds for each edge \f$uv\in E\f$ - (or the reverse inequality holds for each edge). - An edge is said to be tight if this inequality holds with equality, - and the map returns \c true exactly for those edges. - To avoid rounding errors, it is recommended to use this class with exact - number types, e.g. with \c int. - */ - template - class TightEdgeFilterMap : public MapBase { - protected: - const Graph* g; - NodePotentialMap* node_potential; - EdgeDistanceMap* edge_distance; - public: - TightEdgeFilterMap(Graph& _g, NodePotentialMap& _node_potential, - EdgeDistanceMap& _edge_distance) : - g(&_g), node_potential(&_node_potential), - edge_distance(&_edge_distance) { } - bool operator[](const typename Graph::Edge& e) const { - return ((*node_potential)[g->target(e)] == - (*edge_distance)[e]+(*node_potential)[g->source(e)]); - } - }; - -} //namespace lemon - -#endif //LEMON_TIGHT_EDGE_FILTER_MAP_H diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/Makefile.am --- a/src/gui/Makefile.am Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src -LDADD = $(top_builddir)/src/lemon/libemon.la - -bin_PROGRAMS = gd - -gd_SOURCES = \ - all_include.h \ - graph_displayer_canvas.cc \ - graph_displayer_canvas.h \ - graph-displayer.cc \ - main_win.cc \ - main_win.h \ - mapstorage.cc \ - mapstorage.h \ - map_win.cc \ - map_win.h - -gd_CXXFLAGS = $(GTK_CFLAGS) -gd_LDFLAGS = $(GTK_LIBS) diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/all_include.h --- a/src/gui/all_include.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -// -*- C++ -*- // - -#ifndef ALL_INCLUDE_H -#define ALL_INCLUDE_H - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -enum {WIDTH, COLOR, TEXT, PROPERTY_NUM};// properties; -#define RANGE 3 -#define WIN_WIDTH 900 -#define WIN_HEIGHT 600 - - -#ifndef MAIN_PART -extern std::string * property_strings; -extern double * property_defaults; -#endif //MAIN_PART - -using namespace lemon; - -typedef xy Coordinates; -typedef ListGraph Graph; -typedef Graph::NodeMap CoordinatesMap; -typedef Graph::Node Node; -typedef Graph::EdgeIt EdgeIt; -typedef Graph::NodeIt NodeIt; - -#endif // ALL_INCLUDE_H diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/graph-displayer.cc --- a/src/gui/graph-displayer.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -#include -#include -#include -#include -#include - -#define MAIN_PART - -std::string * property_strings; -double * property_defaults; - - -int main(int argc, char *argv[]) -{ - property_strings=new std::string[PROPERTY_NUM]; - property_strings[WIDTH]="Width"; - property_strings[COLOR]="Color"; - property_strings[TEXT]="Text"; - - property_defaults=new double[PROPERTY_NUM]; - property_defaults[WIDTH]=10.0; - property_defaults[COLOR]=100; - property_defaults[TEXT]=0; - - if(argc<2) - { - std::cerr << "USAGE: gd " << std::endl; - return 0; - } - - Coordinates coosvector; - - Graph g; - - CoordinatesMap cm(g); - Graph::EdgeMap cap(g), map1(g), map2(g), map3(g), map4(g); - - //we create one object to read x coordinates - //and one to read y coordinate of nodes and write them to cm NodeMap. - - XMap xreader (cm); - YMap yreader (cm); - Graph::NodeMap nodedata (g); - - std::ifstream is(argv[1]); - - GraphReader reader(is, g); - reader.readNodeMap("coordinates_x", xreader); - reader.readNodeMap("coordinates_y", yreader); - reader.readNodeMap("data", nodedata); - reader.readEdgeMap("cap", cap); - reader.readEdgeMap("map1", map1); - reader.readEdgeMap("map2", map2); - reader.readEdgeMap("map3", map3); - reader.readEdgeMap("map4", map4); - reader.run(); - - MapStorage ms(g); - ms.addNodeMap("data",&nodedata); - ms.addEdgeMap("cap",&cap); - ms.addEdgeMap("map1",&map1); - ms.addEdgeMap("map2",&map2); - ms.addEdgeMap("map3",&map3); - ms.addEdgeMap("map4",&map4); - - Gnome::Canvas::init(); - Gtk::Main app(argc, argv); - - MainWin mainwin("Displayed Graph", g, cm, ms); - app.run(mainwin); - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/graph_displayer_canvas.cc --- a/src/gui/graph_displayer_canvas.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,259 +0,0 @@ -#include - -GraphDisplayerCanvas::GraphDisplayerCanvas(Graph & gr, CoordinatesMap & cm, MapStorage & ms):g(gr),nodesmap(g),edgesmap(g),edgetextmap(g),displayed_graph(*(root()), 0, 0),mapstorage(ms),isbutton(false),active_item(NULL) -{ - - for (EdgeIt i(g); i!=INVALID; ++i) - { - Gnome::Canvas::Points coos; - coos.push_back(Gnome::Art::Point(cm[g.source(i)].x,cm[g.source(i)].y)); - coos.push_back(Gnome::Art::Point(cm[g.target(i)].x,cm[g.target(i)].y)); - - edgesmap[i]=new Gnome::Canvas::Line(displayed_graph, coos); - *(edgesmap[i]) << Gnome::Canvas::Properties::fill_color("green"); - edgesmap[i]->property_width_pixels().set_value(10); - - - double x1, x2, y1, y2; - edgesmap[i]->get_bounds(x1, y1, x2, y2); - - edgetextmap[i]=new Gnome::Canvas::Text(displayed_graph,(x1+x2)/2, (y1+y2)/2, ""); - edgetextmap[i]->property_fill_color().set_value("black"); - } - - NodeIt i(g); - int maxx=0, maxy=0, minx=(int)cm[i].x, miny=(int)cm[i].y; - - for (; i!=INVALID; ++i) - { - if(cm[i].x>maxx)maxx=(int)cm[i].x; - if(cm[i].y>maxy)maxy=(int)cm[i].y; - if(cm[i].xsignal_event().connect(sigc::bind(sigc::mem_fun(*this, &GraphDisplayerCanvas::event_handler),i)); - } - - double biggest_x=(abs(maxx)>abs(minx))?(abs(maxx)+80):(abs(minx)+80); - double biggest_y=(abs(maxy)>abs(miny))?(abs(maxy)+80):(abs(miny)+80); - - set_pixels_per_unit((biggest_x>biggest_y)?(WIN_WIDTH/biggest_x/2):(WIN_HEIGHT/biggest_y/2)); - std::cout< id(g); - Graph::NodeMap xc(g); - Graph::NodeMap yc(g); - - int j=1; - - for (NodeIt i(g); i!=INVALID; ++i) - { - double x1,y1,x2,y2; - nodesmap[i]->get_bounds(x1, y1, x2, y2); - - id[i]=j++; - xc[i]=(x1+x2)/2; - yc[i]=(y1+y2)/2; - } - - GraphWriter writer(std::cout,g); - - writer.writeNodeMap("id", id); - writer.writeNodeMap("coordinates_x", xc); - writer.writeNodeMap("coordinates_y", yc); - writer.run(); -} - -int GraphDisplayerCanvas::changeLineWidth (std::string mapname) -{ - for (EdgeIt i(g); i!=INVALID; ++i) - { - int w=(int)(*(mapstorage.edgemap_storage)[mapname])[i]; - edgesmap[i]->property_width_pixels().set_value(w); - } - return 0; -}; - -int GraphDisplayerCanvas::changeColor (std::string mapname) -{ - for (EdgeIt i(g); i!=INVALID; ++i) - { - double w=(*(mapstorage.edgemap_storage)[mapname])[i]; - double max=mapstorage.maxOfEdgeMap(mapname); - double min=mapstorage.minOfEdgeMap(mapname); - - //std::cout<property_fill_color_gdk().set_value(color); - } - return 0; -}; - -int GraphDisplayerCanvas::changeText (std::string mapname) -{ - for (EdgeIt i(g); i!=INVALID; ++i) - { - if(mapname!="Text") - { - double number=(*(mapstorage.edgemap_storage)[mapname])[i]; - int length=(int)(floor(log(number)/log(10)))+1; - int maxpos=(int)(pow(10,length-1)); - int strl=length+1+RANGE; - char * str=new char[strl]; - str[length]='.'; - str[strl]='\0'; - - for(int j=0;jproperty_text().set_value(str); - } - else - { - edgetextmap[i]->property_text().set_value(""); - } - } - return 0; -}; - - -int GraphDisplayerCanvas::rezoom () -{ - double x1, x2, y1, y2; - int x,y; - - NodeIt i(g); - nodesmap[i]->get_bounds(x1, y1, x2, y2); - - x=(int)((x1+x2)/2); - y=(int)((y1+y2)/2); - - int maxx=0, maxy=0, minx=(int)x, miny=(int)y; - - for (; i!=INVALID; ++i) - { - nodesmap[i]->get_bounds(x1, y1, x2, y2); - - x=(int)((x1+x2)/2); - y=(int)((y1+y2)/2); - - if(x>maxx)maxx=x; - if(y>maxy)maxy=y; - if(xabs(minx))?(abs(maxx)+80):(abs(minx)+80); - double biggest_y=(abs(maxy)>abs(miny))?(abs(maxy)+80):(abs(miny)+80); - - set_pixels_per_unit((biggest_x-WIN_WIDTH>biggest_y-WIN_HEIGHT)?(WIN_WIDTH/biggest_x/2):(WIN_HEIGHT/biggest_y/2)); - return 0; -}; - - -///This function moves only one node of displayed_graph, -///but recalculate the location of weight point, -///and also redraw the sides of the planefigure. -bool GraphDisplayerCanvas::event_handler(GdkEvent* e, Node n) -{ - switch(e->type) - { - case GDK_BUTTON_PRESS: - clicked_x=e->button.x; - clicked_y=e->button.y; - active_item=(get_item_at(e->button.x, e->button.y)); - isbutton=true; - break; - case GDK_BUTTON_RELEASE: - isbutton=false; - active_item=NULL; - break; - case GDK_MOTION_NOTIFY: - if(isbutton) - { - double dx=e->motion.x-clicked_x; - double dy=e->motion.y-clicked_y; - active_item->move(dx, dy); - clicked_x=e->motion.x; - clicked_y=e->motion.y; - - EdgeIt e; - - g.firstOut(e,n); - for(;e!=INVALID;g.nextOut(e)) - { - Gnome::Canvas::Points coos; - double x1, x2, y1, y2; - - nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2); - coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); - - nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2); - coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); - - edgesmap[e]->property_points().set_value(coos); - - edgesmap[e]->get_bounds(x1, y1, x2, y2); - - edgetextmap[e]->property_x().set_value((x1+x2)/2); - edgetextmap[e]->property_y().set_value((y1+y2)/2); - } - - g.firstIn(e,n); - for(;e!=INVALID;g.nextIn(e)) - { - Gnome::Canvas::Points coos; - double x1, x2, y1, y2; - - nodesmap[g.source(e)]->get_bounds(x1, y1, x2, y2); - coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); - - nodesmap[g.target(e)]->get_bounds(x1, y1, x2, y2); - coos.push_back(Gnome::Art::Point((x1+x2)/2,(y1+y2)/2)); - - edgesmap[e]->property_points().set_value(coos); - - edgesmap[e]->get_bounds(x1, y1, x2, y2); - - edgetextmap[e]->property_x().set_value((x1+x2)/2); - edgetextmap[e]->property_y().set_value((y1+y2)/2); - } - } - default: break; - } - return true; -} - -bool GraphDisplayerCanvas::on_expose_event(GdkEventExpose *event) -{ - Gnome::Canvas::CanvasAA::on_expose_event(event); - //usleep(10000); - //rezoom(); - return true; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/graph_displayer_canvas.h --- a/src/gui/graph_displayer_canvas.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -// -*- C++ -*- // - -#ifndef GRAPH_DISPLAYER_CANVAS_H -#define GRAPH_DISPLAYER_CANVAS_H - -#include -#include -#include -#include - -class GraphDisplayerCanvas : public Gnome::Canvas::CanvasAA -{ - typedef Gnome::Canvas::CanvasAA Parent; - -public: - GraphDisplayerCanvas(Graph &, CoordinatesMap &, MapStorage &); - virtual ~GraphDisplayerCanvas(); - - int changeLineWidth (std::string mapname); - int changeColor (std::string mapname); - int changeText (std::string mapname); - int rezoom(); - -protected: - - virtual bool on_expose_event(GdkEventExpose *); - -private: - - ///Event handler function that handles dragging nodes of displayed_graph - bool event_handler(GdkEvent* e, Node n); - - ///The graph, on which we work - Graph g; - ///Map of nodes of planefigure - Graph::NodeMap nodesmap; - ///Map of edges of planefigure - Graph::EdgeMap edgesmap; - - ///Map of texts to write on edges - Graph::EdgeMap edgetextmap; - - ///Group of graphical elements of displayed_graph - Gnome::Canvas::Group displayed_graph; - - ///Here we store the maps that can be displayed through properties. - MapStorage mapstorage; - - ///Indicates whether the button of mouse is pressed or not - bool isbutton; - - ///At this location was the mousebutton pressed. - ///It helps to calculate the distance of dragging. - double clicked_x, clicked_y; - - ///Remembers which Gnome::Canvas::Item was pressed. - ///this variable is needed, because - ///1. we cannot query the item at he cursor as fast as it could not cause a Segmentation Fault - ///2. we would like to handle only ony item per movement, therefore quering it is not a working solution - Gnome::Canvas::Item * active_item; - - -}; - -#endif //GRAPH_DISPLAYER_CANVAS_H diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/graphocska.lgf --- a/src/gui/graphocska.lgf Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -@nodeset -id coordinates_x coordinates_y data -1 230 -80 1 -2 230 100 3 -3 120 -80 5 -4 120 100 7 -5 20 100 9 -6 20 -80 11 -7 -40 10 13 -8 -100 100 15 -9 -100 10 17 -10 -100 -80 19 -11 -200 -80 21 -12 -200 10 23 -13 -200 100 25 -14 -300 100 27 -15 -300 -80 29 - -@edgeset - cap map1 map2 map3 map4 -15 14 1 21 111 231 3 -14 13 2 22 112 232 6 -13 12 3 23 113 233 9 -13 8 4 24 114 234 12 -12 11 5 25 115 235 15 -12 9 6 26 116 236 18 -11 10 7 27 117 237 21 -10 9 8 28 118 238 24 -10 7 9 29 119 239 27 -9 8 10 30 120 230 30 -7 6 11 31 121 241 33 -6 5 12 32 122 242 36 -6 3 13 33 123 243 39 -5 4 14 34 124 244 42 -4 3 15 35 125 245 45 -3 2 16 36 126 246 48 -2 1 17 37 127 247 51 - -@end \ No newline at end of file diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/main_win.cc --- a/src/gui/main_win.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -#include - -MainWin::MainWin(const std::string& title, Graph & graph, CoordinatesMap & cm, MapStorage & ms):mapwin("Map Setup", ms, gd_canvas),gd_canvas(graph, cm, ms) -{ - set_title (title); - set_default_size(WIN_WIDTH,WIN_HEIGHT); - add(vbox); - - ag=Gtk::ActionGroup::create(); - ag->add( Gtk::Action::create("ShowMenu", "_Show") ); - ag->add( Gtk::Action::create("ShowMaps", "_Maps"), sigc::mem_fun(*this, &MainWin::showMaps)); - ag->add( Gtk::Action::create("FileMenu", "_File") ); - ag->add( Gtk::Action::create("FileQuit", "_Quit"), sigc::mem_fun(*this, &MainWin::quit)); - ag->add( Gtk::Action::create("ZoomMenu", "_Zoom") ); - ag->add( Gtk::Action::create("ZoomRezoom", "_Rezoom"), sigc::mem_fun(*this, &MainWin::rezoom)); //!!!!!! - - uim=Gtk::UIManager::create(); - uim->insert_action_group(ag); - add_accel_group(uim->get_accel_group()); - - try - { - - Glib::ustring ui_info = - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; - - uim->add_ui_from_string(ui_info); - - } - catch(const Glib::Error& ex) - { - std::cerr << "building menus failed: " << ex.what(); - } - - Gtk::Widget* menubar = uim->get_widget("/MenuBar"); - if(menubar)vbox.pack_start(*menubar, Gtk::PACK_SHRINK); - - vbox.pack_start(gd_canvas); - - show_all_children(); -} - -void MainWin::showMaps() -{ - mapwin.show(); -} - -void MainWin::quit() -{ - hide(); -} - -void MainWin::rezoom() -{ - gd_canvas.rezoom(); -} - diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/main_win.h --- a/src/gui/main_win.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -// -*- C++ -*- // - -#ifndef MAIN_WIN_H -#define MAIN_WIN_H - -#include -#include -#include -#include -#include - -class MainWin : public Gtk::Window -{ -public: - MainWin(const std::string& title, Graph &, CoordinatesMap &, MapStorage &); - -protected: - //Window of map-showing setup - MapWin mapwin; - - //Member widgets: - GraphDisplayerCanvas gd_canvas; - - //ActionGroup for menu - Glib::RefPtr ag; - - //UIManager for menu - Glib::RefPtr uim; - - //Container - Gtk::VBox vbox; - - //Pops up map-setup window - virtual void showMaps(); - - //Exit - virtual void quit(); - - //Refit screen - virtual void rezoom(); - -}; - -#endif //MAIN_WIN_H diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/map_win.cc --- a/src/gui/map_win.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -#include -#include - -MapWin::MapWin(const std::string& title, MapStorage & mapst, GraphDisplayerCanvas & grdispc):gdc(grdispc),ms(mapst) -{ - set_title(title); - set_default_size(400, 200); - - rb_array=new Gtk::RadioButton * [PROPERTY_NUM]; - vbox_r1=new Gtk::VBox[PROPERTY_NUM]; - vbox_r2=new Gtk::VBox[PROPERTY_NUM]; - radios=new Gtk::HBox[PROPERTY_NUM]; - for(int i=0;i * >::iterator emsi=ms.beginOfEdgeMaps(); - std::set props; - - int actprop; - for(int j=0;jsecond==&(ms.default_edgemaps[i])) - { - actprop=j; - } - for(int k=0;ksecond==&(ms.default_edgemaps[k])) - { - props.insert(j); - } - } - emsi++; - } - - rb_array[i][0].set_group(group); - rb_array[i][0].set_label("Default"); - rb_array[i][0].signal_clicked().connect( sigc::bind( sigc::bind( sigc::mem_fun(*this, &MapWin::radio_click), 0), i) ); - vbox_r1[i].pack_start(rb_array[i][0]); - - - emsi=ms.beginOfEdgeMaps(); - int actpos=1; - for(int j=0;jfirst); - rb_array[i][actpos].signal_clicked().connect - ( - sigc::bind( - sigc::bind( - sigc::mem_fun(*this, &MapWin::radio_click), - actpos - ), - i - ) - ); - - if(actpos<(ms.numOfEdgeMaps()-PROPERTY_NUM+1)/2) - { - vbox_r1[i].pack_start(rb_array[i][actpos]); - } - else - { - vbox_r2[i].pack_start(rb_array[i][actpos]); - } - actpos++; - } - emsi++; - } - radios[i].pack_start(vbox_r1[i]); - radios[i].pack_start(vbox_r2[i]); - notebook.append_page(radios[i], property_strings[i]); - } - - add(vbox_b); - vbox_b.pack_start(notebook); - - show_all_children(); - -} - -void MapWin::radio_click(int prop, int actpos) -{ - if(rb_array[prop][actpos].get_active()) - { - - std::string mapname=rb_array[prop][actpos].get_label(); - - if(mapname=="Default") - { - mapname=property_strings[prop]; - } - - switch(prop) - { - case WIDTH: - gdc.changeLineWidth(mapname); - break; - case COLOR: - gdc.changeColor(mapname); - break; - case TEXT: - gdc.changeText(mapname); - break; - default: - std::cout<<"Error\n"; - } - } -}; diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/map_win.h --- a/src/gui/map_win.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -// -*- C++ -*- // - -#ifndef MAP_WIN_H -#define MAP_WIN_H - -#include -#include -#include -#include -#include - -class MapWin : public Gtk::Window -{ -protected: - GraphDisplayerCanvas & gdc; - MapStorage & ms; - - Gtk::HBox * radios; - Gtk::RadioButton ** rb_array; - - Gtk::VBox vbox_b, * vbox_r1, * vbox_r2; - Gtk::Notebook notebook; - Gtk::Label * labels; - -public: - MapWin(const std::string& title, MapStorage &, GraphDisplayerCanvas &); - virtual void radio_click(int, int); -}; - -#endif //MAP_WIN_H diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/mapstorage.cc --- a/src/gui/mapstorage.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -#include - -MapStorage::MapStorage(Graph & graph):g(graph) -{ - for(int i=0;i emd(g); - default_edgemaps.push_back(emd); - Graph::NodeMap nmd(g); - default_nodemaps.push_back(nmd); - } - - //std::string defaultstr="Default "; - for(int i=0;i *nodemap) -{ - nodemap_storage[name]=nodemap; - return 0; -} -int MapStorage::addEdgeMap(const std::string & name, Graph::EdgeMap *edgemap) -{ - edgemap_storage[name]=edgemap; - return 0; -} - -double MapStorage::maxOfNodeMap(const std::string & name) -{ - double max=0; - for (NodeIt j(g); j!=INVALID; ++j) - { - if( (*nodemap_storage[name])[j]>max ) - { - max=(*nodemap_storage[name])[j]; - } - } - return max; -} - -double MapStorage::maxOfEdgeMap(const std::string & name) -{ - double max=0; - for (EdgeIt j(g); j!=INVALID; ++j) - { - if( (*edgemap_storage[name])[j]>max ) - { - max=(*edgemap_storage[name])[j]; - } - } - return max; -} - -double MapStorage::minOfNodeMap(const std::string & name) -{ - NodeIt j(g); - double min=(*nodemap_storage[name])[j]; - for (; j!=INVALID; ++j) - { - if( (*nodemap_storage[name])[j] - -class MapStorage -{ - -public: ///!!!!!!!! - Graph g; - std::map< std::string,Graph::NodeMap * > nodemap_storage; - std::map< std::string,Graph::EdgeMap * > edgemap_storage; - - std::vector > default_nodemaps; - std::vector > default_edgemaps; - -public: - MapStorage(Graph &); - int addNodeMap(const std::string &,Graph::NodeMap *); - int addEdgeMap(const std::string &,Graph::EdgeMap *); - - int numOfNodeMaps() {return nodemap_storage.size();}; - int numOfEdgeMaps() {return edgemap_storage.size();}; - - double maxOfNodeMap(const std::string &); - double maxOfEdgeMap(const std::string &); - - double minOfNodeMap(const std::string &); - double minOfEdgeMap(const std::string &); - - std::map< std::string,Graph::NodeMap * >::iterator beginOfNodeMaps(){return nodemap_storage.begin();}; - std::map< std::string,Graph::EdgeMap * >::iterator beginOfEdgeMaps(){return edgemap_storage.begin();}; -}; - -#endif //MAPSTORAGE_H diff -r d8475431bbbb -r 8e85e6bbefdf src/gui/xml.h --- a/src/gui/xml.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,442 +0,0 @@ -/* -*- C++ -*- */ - -#include -#include -#include -#include -#include -#include - -class XmlWriter -{ - std::ostream& os; - int level; - -protected: - void indent(int level) { - os << std::endl; - for(int i=0;i'; - } - void etag(const std::string &_tag) { - os << "'; - } - void itag(const std::string &_tag) { indent();tag(_tag); } - void ietag(const std::string &_tag) { indent();etag(_tag); } - - void beginTag(const std::string &_tag) { - itag(_tag); - level++; - } - void endTag(const std::string &_tag) { - level--; - ietag(_tag); - } - -public: - - void indent() - { - if(level>=0) indent(level); - else level=0; - } - - ///\e - - ///\e - /// - class ContTag - { - XmlWriter &ix; - const std::string _tag; - public: - ///\e - - ///\e - /// - ContTag(XmlWriter &_ix,const std::string &_t) : - ix(_ix), _tag(_t) - { - ix.tag(_tag); - } - ~ContTag() { ix.etag(_tag);} - }; - - class LineTag - { - XmlWriter &ix; - const std::string _tag; - public: - ///\e - - ///\e - /// - LineTag(XmlWriter &_ix,const std::string &_t) : - ix(_ix), _tag(_t) - { - ix.itag(_tag); - } - ~LineTag() { ix.etag(_tag);} - }; - - ///\e - - ///\e - /// - class Tag - { - XmlWriter &ix; - const std::string _tag; - public: - ///\e - - ///\e - /// - Tag(XmlWriter &_ix,const std::string &_t) : - ix(_ix), _tag(_t) - { - ix.beginTag(_tag); - } - ~Tag() { - ix.endTag(_tag); - } - }; - - ///\e - - ///\e - /// - XmlWriter(std::ostream& _os) : os(_os),level(-1) {} - ~XmlWriter() { os<< std::endl; } - - XmlWriter &operator()(int v) - { - if(!(os << v)) throw (std::ios::failure ("data format error")); - return *this; - } - XmlWriter &operator()(const std::string &_tag,int v) - { - LineTag t(*this,_tag); - if(!(os << v)) throw (std::ios::failure ("data format error")); - return *this; - } - XmlWriter &operator()(const std::string &_tag,double v) - { - LineTag t(*this,_tag); - if(os << v) throw (std::ios::failure ("data format error")); - return *this; - } - XmlWriter &operator()(double v) - { - os << v; - return *this; - } - XmlWriter &operator()(const std::string &v) - { - for(std::string::const_iterator i=v.begin();i!=v.end();++i) - switch(*i) { - case '\\': - os << "\\\\"; - break; - case '<': - os << "\\<"; - break; - case '&': - os << "\\&"; - break; - case '\n': - os << "\\n"; - break; - default: - os<<*i; - break; - } - return *this; - } - XmlWriter &operator()(const std::string &_tag,const std::string &v) - { - LineTag t(*this,_tag); - (*this)(v); - return *this; - } - ///\e - - ///\e - /// - template - XmlWriter &operator()(const std::string &_tag,const V &v) - { - Tag t(*this,_tag); - out(*this,v); - return *this; - } - ///\e - - ///\e - /// - template - XmlWriter &operator()(const V &v) - { - out(*this,v); - return *this; - } -}; - -////////////////////////////////////////////////////////////////////// - -class XmlReader -{ - std::istream& is; - - std::string next_tag; - void skipWhiteSpaces() - { - char c; - while (is.get(c) && std::isspace(c,is.getloc())); - is.unget(); - } -protected: - ///\e - - ///\e - /// - void useTag() {next_tag.clear();} - - void useTag(const std::string &_tag) { - if(nextTag()==_tag) useTag(); - else throw (std::ios::failure ("data format error")); - } -public: - ///\e - - ///\e - /// - const std::string &nextTag() - { - if(next_tag.empty()) { - char c; - skipWhiteSpaces(); - if(!is.get(c) || c!='<') - throw (std::ios::failure ("data format error")); - next_tag.clear(); - while (is.get(c) && c!='>') next_tag.push_back(c); - if(c!='>') - throw (std::ios::failure ("data format error")); - } - return next_tag; - } - - ///\e - - ///\e - /// - class Tag - { - XmlReader &ix; - const std::string tag; - public: - ///\e - - ///\e - /// - Tag(XmlReader &_ix,const std::string &_tag) : - ix(_ix), tag(_tag) - { - ix.useTag(_tag); - } - ~Tag() { - if(!std::uncaught_exception()) - ix.useTag('/'+tag); - } - }; - - ///\e - - ///\e - /// - XmlReader(std::istream& _is) : is(_is) {} - - int operator()(const std::string &tag,int &v) - { - Tag t(*this,tag); - if(!(is >> v)) throw (std::ios::failure ("data format error")); - return v; - } - double operator()(const std::string &tag,double &v) - { - Tag t(*this,tag); - if(!(is >> v)) throw (std::ios::failure ("data format error")); - return v; - } - std::string &operator()(const std::string &tag,std::string &v) - { - Tag t(*this,tag); - v.clear(); - char c; - while (is.get(c) && c!='<') - if(c=='\\') - if(!is.get(c)) throw (std::ios::failure ("data format error")); - else switch(c) { - case 'n': - v.push_back('\n'); - break; - default: - v.push_back(c); - break; - } - else v.push_back(c); - if(c!='<') - throw (std::ios::failure ("data format error")); - is.unget(); - return v; - } - ///\e - - ///\e - /// - template - V &operator()(const std::string &tag,V &v) - { - Tag t(*this,tag); - in(*this,v); - return v; - } - ///\e - - ///\e - /// - template - V &operator()(V &v) - { - in(*this,v); - return v; - } - ///\e - - ///\e - /// - template - V load(const std::string &tag) - { - Tag t(*this,tag); - V v; - (*this)(tag,v); - return v; - } -}; - -////////////////////////////////////////////////////////////////////// - -template -void out(XmlWriter &i,const std::pair &v) -{ - i("first",v.first); - i("second",v.second); -} - -template -void in(XmlReader &i,std::pair &v) -{ - i("first",v.first); - i("second",v.second); -} - -////////////////////////////// - -template -void out(XmlWriter &i,const std::list &v) -{ - for(typename std::list::const_iterator it=v.begin(); - it!=v.end();++it) i("item",*it); -} - -template -void in(XmlReader &i,std::list &v) -{ - while(i.nextTag()=="item") - { - v.push_back(T()); - i("item",v.back()); - } -} - -////////////////////////////// - -template -void out(XmlWriter &i,const std::vector &v) -{ - for(typename std::vector::const_iterator it=v.begin(); - it!=v.end();++it) i("item",*it); -} - -template -void in(XmlReader &i,std::vector &v) -{ - while(i.nextTag()=="item") - { - v.push_back(T()); - i("item",v.back()); - } -} - -////////////////////////////// - -template -void out(XmlWriter &i,const std::map &v) -{ - for(typename std::map::const_iterator it=v.begin(); - it!=v.end();++it) i("item",*it); -} - -template -void in(XmlReader &i,std::map &v) -{ - while(i.nextTag()=="item") - { - typename std::map::value_type it; - i("item",it); - v.insert(it); - } -} - -////////////////////////////// - -template -void out(XmlWriter &i,const lemon::xy &v) -{ -// i("x",v.x); -// i("y",v.y); - { XmlWriter::LineTag t(i,"x"); i(v.x); } - { XmlWriter::ContTag t(i,"y"); i(v.y); } -} - -template -void in(XmlReader &i,lemon::xy &v) -{ - i("x",v.x); - i("y",v.y); -} - -////////////////////////////// - -template -void out(XmlWriter &i,const lemon::BoundingBox &v) -{ - if(!v.empty()) { - i("point",v.bottomLeft()); - if(v.bottomLeft()!=v.topRight()) i("point",v.topRight()); - } -} - -template -void in(XmlReader &i,lemon::BoundingBox &v) -{ - v.clear(); - while(i.nextTag()=="point") { - lemon::xy co; - i("point",co); - v+=co; - } -} diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/Makefile.am --- a/src/lemon/Makefile.am Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = lemon.pc - -lib_LTLIBRARIES = libemon.la - -libemon_la_SOURCES = \ - lp_base.cc \ - lp_skeleton.cc -libemon_la_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) -libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) - -if HAVE_GLPK -libemon_la_SOURCES += lp_glpk.cc -endif - -if HAVE_CPLEX -libemon_la_SOURCES += lp_cplex.cc -endif - -nobase_pkginclude_HEADERS = \ - bezier.h \ - bfs.h \ - dfs.h \ - bin_heap.h \ - config.h \ - dijkstra.h \ - dimacs.h \ - error.h \ - fib_heap.h \ - full_graph.h \ - graph_adaptor.h \ - graph_utils.h \ - graph_to_eps.h \ - invalid.h \ - kruskal.h \ - list_graph.h \ - lp_base.h \ - lp_cplex.h \ - lp_glpk.h \ - lp_skeleton.h \ - maps.h \ - max_matching.h \ - min_cost_flow.h \ - suurballe.h \ - preflow.h \ - path.h \ - radix_heap.h \ - smart_graph.h \ - time_measure.h \ - unionfind.h \ - xy.h \ - concept_check.h \ - utility.h \ - lemon_reader.h \ - lemon_writer.h \ - graph_reader.h \ - graph_writer.h \ - bits/alteration_notifier.h \ - bits/map_iterator.h \ - bits/array_map.h \ - bits/default_map.h \ - bits/extended_pair.h \ - bits/vector_map.h \ - bits/iterable_graph_extender.h \ - bits/extendable_graph_extender.h \ - bits/clearable_graph_extender.h \ - bits/erasable_graph_extender.h \ - bits/undir_graph_extender.h \ - bits/item_reader.h \ - bits/item_writer.h - -noinst_HEADERS = \ - concept/graph.h \ - concept/graph_component.h \ - concept/undir_graph.h \ - concept/sym_graph.h \ - concept/maps.h \ - concept/heap.h \ - concept/path.h diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/attic/debug.h --- a/src/lemon/attic/debug.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* -*- C++ -*- - * src/lemon/debug.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_DEBUG_H -#define LEMON_DEBUG_H - -//! \file -//! \brief Basic definitions for debug control. - -namespace lemon { - - //! Debug mode for testing/debugging - - //! Use this debug mode if you want exhaustive range and consistency checks. - //! It also produces verbose debug messages. - struct DebugOn { - //! Example: check whether the edges added to a path are adjacent - static const bool consistensy_check = true; - - static const bool range_check = true; - - //! Examples: initialize maps with some value; - //! after deleting an item from UnionFindEnum set its value in the - //! corresponding map to NULL... - static const bool ensure_safe_state = true; - - static const int verbose = 5; - }; - - //! Debug mode for turning off debug aids. - - //! This debud mode switches off all range and consistency checks, - //! as well as the debug messages. - //! - struct DebugOff { - static const bool consistensy_check = false; - static const bool range_check = false; - static const bool ensure_safe_state = false; - static const int verbose = 0; - }; - -#ifdef DEBUG - //! The default debug mode. - - //! The default debug mode. - //! - typedef DebugOn DefaultDebugMode; -#else - //! The default debug mode. - - //! The default debug mode. - //! - typedef DebugOff DefaultDebugMode; -#endif - -} -#endif // LEMON_DEBUG_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bezier.h --- a/src/lemon/bezier.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -/* -*- C++ -*- - * src/lemon/bezier.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_BEZIER_H -#define LEMON_BEZIER_H - -///\ingroup misc -///\file -///\brief Classes to compute with Bezier curves. -/// -///Up to now this file is used internally by \ref graph_to_eps.h -/// -///\author Alpar Juttner - -#include - -namespace lemon { - -class BezierBase { -public: - typedef xy xy; -protected: - static xy conv(xy x,xy y,double t) {return (1-t)*x+t*y;} -}; - -class Bezier1 : public BezierBase -{ -public: - xy p1,p2; - - Bezier1() {} - Bezier1(xy _p1, xy _p2) :p1(_p1), p2(_p2) {} - - xy operator()(double t) const - { - // return conv(conv(p1,p2,t),conv(p2,p3,t),t); - return conv(p1,p2,t); - } - Bezier1 before(double t) const - { - return Bezier1(p1,conv(p1,p2,t)); - } - - Bezier1 after(double t) const - { - return Bezier1(conv(p1,p2,t),p2); - } - Bezier1 revert() { return Bezier1(p2,p1);} - Bezier1 operator()(double a,double b) { return before(b).after(a/b); } - xy grad() { return p2-p1; } - xy grad(double t) { return grad(); } - -}; - -class Bezier2 : public BezierBase -{ -public: - xy p1,p2,p3; - - Bezier2() {} - Bezier2(xy _p1, xy _p2, xy _p3) :p1(_p1), p2(_p2), p3(_p3) {} - Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {} - xy operator()(double t) const - { - // return conv(conv(p1,p2,t),conv(p2,p3,t),t); - return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3; - } - Bezier2 before(double t) const - { - xy q(conv(p1,p2,t)); - xy r(conv(p2,p3,t)); - return Bezier2(p1,q,conv(q,r,t)); - } - - Bezier2 after(double t) const - { - xy q(conv(p1,p2,t)); - xy r(conv(p2,p3,t)); - return Bezier2(conv(q,r,t),r,p3); - } - Bezier2 revert() { return Bezier2(p3,p2,p1);} - Bezier2 operator()(double a,double b) { return before(b).after(a/b); } - Bezier1 grad() { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); } - xy grad(double t) { return grad()(t); } -}; - -class Bezier3 : public BezierBase -{ -public: - xy p1,p2,p3,p4; - - Bezier3() {} - Bezier3(xy _p1, xy _p2, xy _p3, xy _p4) :p1(_p1), p2(_p2), p3(_p3), p4(_p4) {} - Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)), - p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {} - Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)), - p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {} - - xy operator()(double t) const - { - // return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t); - return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+ - (3*t*t*(1-t))*p3+(t*t*t)*p4; - } - Bezier3 before(double t) const - { - xy p(conv(p1,p2,t)); - xy q(conv(p2,p3,t)); - xy r(conv(p3,p4,t)); - xy a(conv(p,q,t)); - xy b(conv(q,r,t)); - xy c(conv(a,b,t)); - return Bezier3(p1,p,a,c); - } - - Bezier3 after(double t) const - { - xy p(conv(p1,p2,t)); - xy q(conv(p2,p3,t)); - xy r(conv(p3,p4,t)); - xy a(conv(p,q,t)); - xy b(conv(q,r,t)); - xy c(conv(a,b,t)); - return Bezier3(c,b,r,p4); - } - Bezier3 revert() { return Bezier3(p4,p3,p2,p1);} - Bezier3 operator()(double a,double b) { return before(b).after(a/b); } - Bezier2 grad() { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); } - xy grad(double t) { return grad()(t); } -}; - -} //END OF NAMESPACE LEMON - -#endif // LEMON_BEZIER_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bfs.h --- a/src/lemon/bfs.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1130 +0,0 @@ -/* -*- C++ -*- - * src/lemon/bfs.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_BFS_H -#define LEMON_BFS_H - -///\ingroup flowalgs -///\file -///\brief Bfs algorithm. - -#include -#include -#include -#include -#include - -namespace lemon { - - - - ///Default traits class of Bfs class. - - ///Default traits class of Bfs class. - ///\param GR Graph type. - template - struct BfsDefaultTraits - { - ///The graph type the algorithm runs on. - typedef GR Graph; - ///\brief The type of the map that stores the last - ///edges of the shortest paths. - /// - ///The type of the map that stores the last - ///edges of the shortest paths. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef typename Graph::template NodeMap PredMap; - ///Instantiates a PredMap. - - ///This function instantiates a \ref PredMap. - ///\param G is the graph, to which we would like to define the PredMap. - ///\todo The graph alone may be insufficient to initialize - static PredMap *createPredMap(const GR &G) - { - return new PredMap(G); - } -// ///\brief The type of the map that stores the last but one -// ///nodes of the shortest paths. -// /// -// ///The type of the map that stores the last but one -// ///nodes of the shortest paths. -// ///It must meet the \ref concept::WriteMap "WriteMap" concept. -// /// -// typedef NullMap PredNodeMap; -// ///Instantiates a PredNodeMap. - -// ///This function instantiates a \ref PredNodeMap. -// ///\param G is the graph, to which -// ///we would like to define the \ref PredNodeMap -// static PredNodeMap *createPredNodeMap(const GR &G) -// { -// return new PredNodeMap(); -// } - - ///The type of the map that indicates which nodes are processed. - - ///The type of the map that indicates which nodes are processed. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - ///\todo named parameter to set this type, function to read and write. - typedef NullMap ProcessedMap; - ///Instantiates a ProcessedMap. - - ///This function instantiates a \ref ProcessedMap. - ///\param G is the graph, to which - ///we would like to define the \ref ProcessedMap - static ProcessedMap *createProcessedMap(const GR &) - { - return new ProcessedMap(); - } - ///The type of the map that indicates which nodes are reached. - - ///The type of the map that indicates which nodes are reached. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - ///\todo named parameter to set this type, function to read and write. - typedef typename Graph::template NodeMap ReachedMap; - ///Instantiates a ReachedMap. - - ///This function instantiates a \ref ReachedMap. - ///\param G is the graph, to which - ///we would like to define the \ref ReachedMap. - static ReachedMap *createReachedMap(const GR &G) - { - return new ReachedMap(G); - } - ///The type of the map that stores the dists of the nodes. - - ///The type of the map that stores the dists of the nodes. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef typename Graph::template NodeMap DistMap; - ///Instantiates a DistMap. - - ///This function instantiates a \ref DistMap. - ///\param G is the graph, to which we would like to define the \ref DistMap - static DistMap *createDistMap(const GR &G) - { - return new DistMap(G); - } - }; - - ///%BFS algorithm class. - - ///\ingroup flowalgs - ///This class provides an efficient implementation of the %BFS algorithm. - /// - ///\param GR The graph type the algorithm runs on. The default value is - ///\ref ListGraph. The value of GR is not used directly by Bfs, it - ///is only passed to \ref BfsDefaultTraits. - ///\param TR Traits class to set various data types used by the algorithm. - ///The default traits class is - ///\ref BfsDefaultTraits "BfsDefaultTraits". - ///See \ref BfsDefaultTraits for the documentation of - ///a Bfs traits class. - /// - ///\author Alpar Juttner - ///\todo A compare object would be nice. - -#ifdef DOXYGEN - template -#else - template > -#endif - class Bfs { - public: - /** - * \brief \ref Exception for uninitialized parameters. - * - * This error represents problems in the initialization - * of the parameters of the algorithms. - */ - class UninitializedParameter : public lemon::UninitializedParameter { - public: - virtual const char* exceptionName() const { - return "lemon::Bfs::UninitializedParameter"; - } - }; - - typedef TR Traits; - ///The type of the underlying graph. - typedef typename TR::Graph Graph; - ///\e - typedef typename Graph::Node Node; - ///\e - typedef typename Graph::NodeIt NodeIt; - ///\e - typedef typename Graph::Edge Edge; - ///\e - typedef typename Graph::OutEdgeIt OutEdgeIt; - - ///\brief The type of the map that stores the last - ///edges of the shortest paths. - typedef typename TR::PredMap PredMap; -// ///\brief The type of the map that stores the last but one -// ///nodes of the shortest paths. -// typedef typename TR::PredNodeMap PredNodeMap; - ///The type of the map indicating which nodes are reached. - typedef typename TR::ReachedMap ReachedMap; - ///The type of the map indicating which nodes are processed. - typedef typename TR::ProcessedMap ProcessedMap; - ///The type of the map that stores the dists of the nodes. - typedef typename TR::DistMap DistMap; - private: - /// Pointer to the underlying graph. - const Graph *G; - ///Pointer to the map of predecessors edges. - PredMap *_pred; - ///Indicates if \ref _pred is locally allocated (\c true) or not. - bool local_pred; -// ///Pointer to the map of predecessors nodes. -// PredNodeMap *_predNode; -// ///Indicates if \ref _predNode is locally allocated (\c true) or not. -// bool local_predNode; - ///Pointer to the map of distances. - DistMap *_dist; - ///Indicates if \ref _dist is locally allocated (\c true) or not. - bool local_dist; - ///Pointer to the map of reached status of the nodes. - ReachedMap *_reached; - ///Indicates if \ref _reached is locally allocated (\c true) or not. - bool local_reached; - ///Pointer to the map of processed status of the nodes. - ProcessedMap *_processed; - ///Indicates if \ref _processed is locally allocated (\c true) or not. - bool local_processed; - - std::vector _queue; - int _queue_head,_queue_tail,_queue_next_dist; - int _curr_dist; -// ///The source node of the last execution. -// Node source; - - ///Creates the maps if necessary. - - ///\todo Error if \c G are \c NULL. - ///\todo Better memory allocation (instead of new). - void create_maps() - { - if(!_pred) { - local_pred = true; - _pred = Traits::createPredMap(*G); - } -// if(!_predNode) { -// local_predNode = true; -// _predNode = Traits::createPredNodeMap(*G); -// } - if(!_dist) { - local_dist = true; - _dist = Traits::createDistMap(*G); - } - if(!_reached) { - local_reached = true; - _reached = Traits::createReachedMap(*G); - } - if(!_processed) { - local_processed = true; - _processed = Traits::createProcessedMap(*G); - } - } - - public : - - ///\name Named template parameters - - ///@{ - - template - struct DefPredMapTraits : public Traits { - typedef T PredMap; - static PredMap *createPredMap(const Graph &G) - { - throw UninitializedParameter(); - } - }; - ///\ref named-templ-param "Named parameter" for setting PredMap type - - ///\ref named-templ-param "Named parameter" for setting PredMap type - /// - template - class DefPredMap : public Bfs< Graph, - DefPredMapTraits > { }; - -// template -// struct DefPredNodeMapTraits : public Traits { -// typedef T PredNodeMap; -// static PredNodeMap *createPredNodeMap(const Graph &G) -// { -// throw UninitializedParameter(); -// } -// }; -// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type - -// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type -// /// -// template -// class DefPredNodeMap : public Bfs< Graph, -// LengthMap, -// DefPredNodeMapTraits > { }; - - template - struct DefDistMapTraits : public Traits { - typedef T DistMap; - static DistMap *createDistMap(const Graph &G) - { - throw UninitializedParameter(); - } - }; - ///\ref named-templ-param "Named parameter" for setting DistMap type - - ///\ref named-templ-param "Named parameter" for setting DistMap type - /// - template - class DefDistMap : public Bfs< Graph, - DefDistMapTraits > { }; - - template - struct DefReachedMapTraits : public Traits { - typedef T ReachedMap; - static ReachedMap *createReachedMap(const Graph &G) - { - throw UninitializedParameter(); - } - }; - ///\ref named-templ-param "Named parameter" for setting ReachedMap type - - ///\ref named-templ-param "Named parameter" for setting ReachedMap type - /// - template - class DefReachedMap : public Bfs< Graph, - DefReachedMapTraits > { }; - - struct DefGraphReachedMapTraits : public Traits { - typedef typename Graph::template NodeMap ReachedMap; - static ReachedMap *createReachedMap(const Graph &G) - { - return new ReachedMap(G); - } - }; - template - struct DefProcessedMapTraits : public Traits { - typedef T ProcessedMap; - static ProcessedMap *createProcessedMap(const Graph &G) - { - throw UninitializedParameter(); - } - }; - ///\ref named-templ-param "Named parameter" for setting ProcessedMap type - - ///\ref named-templ-param "Named parameter" for setting ProcessedMap type - /// - template - class DefProcessedMap : public Bfs< Graph, - DefProcessedMapTraits > { }; - - struct DefGraphProcessedMapTraits : public Traits { - typedef typename Graph::template NodeMap ProcessedMap; - static ProcessedMap *createProcessedMap(const Graph &G) - { - return new ProcessedMap(G); - } - }; - ///\brief \ref named-templ-param "Named parameter" - ///for setting the ProcessedMap type to be Graph::NodeMap. - /// - ///\ref named-templ-param "Named parameter" - ///for setting the ProcessedMap type to be Graph::NodeMap. - ///If you don't set it explicitly, it will be automatically allocated. - template - class DefProcessedMapToBeDefaultMap : - public Bfs< Graph, - DefGraphProcessedMapTraits> { }; - - ///@} - - public: - - ///Constructor. - - ///\param _G the graph the algorithm will run on. - /// - Bfs(const Graph& _G) : - G(&_G), - _pred(NULL), local_pred(false), -// _predNode(NULL), local_predNode(false), - _dist(NULL), local_dist(false), - _reached(NULL), local_reached(false), - _processed(NULL), local_processed(false) - { } - - ///Destructor. - ~Bfs() - { - if(local_pred) delete _pred; -// if(local_predNode) delete _predNode; - if(local_dist) delete _dist; - if(local_reached) delete _reached; - if(local_processed) delete _processed; - } - - ///Sets the map storing the predecessor edges. - - ///Sets the map storing the predecessor edges. - ///If you don't use this function before calling \ref run(), - ///it will allocate one. The destructor deallocates this - ///automatically allocated map, of course. - ///\return (*this) - Bfs &predMap(PredMap &m) - { - if(local_pred) { - delete _pred; - local_pred=false; - } - _pred = &m; - return *this; - } - - ///Sets the map indicating the reached nodes. - - ///Sets the map indicating the reached nodes. - ///If you don't use this function before calling \ref run(), - ///it will allocate one. The destructor deallocates this - ///automatically allocated map, of course. - ///\return (*this) - Bfs &reachedMap(ReachedMap &m) - { - if(local_reached) { - delete _reached; - local_reached=false; - } - _reached = &m; - return *this; - } - - ///Sets the map indicating the processed nodes. - - ///Sets the map indicating the processed nodes. - ///If you don't use this function before calling \ref run(), - ///it will allocate one. The destructor deallocates this - ///automatically allocated map, of course. - ///\return (*this) - Bfs &processedMap(ProcessedMap &m) - { - if(local_processed) { - delete _processed; - local_processed=false; - } - _processed = &m; - return *this; - } - -// ///Sets the map storing the predecessor nodes. - -// ///Sets the map storing the predecessor nodes. -// ///If you don't use this function before calling \ref run(), -// ///it will allocate one. The destructor deallocates this -// ///automatically allocated map, of course. -// ///\return (*this) -// Bfs &predNodeMap(PredNodeMap &m) -// { -// if(local_predNode) { -// delete _predNode; -// local_predNode=false; -// } -// _predNode = &m; -// return *this; -// } - - ///Sets the map storing the distances calculated by the algorithm. - - ///Sets the map storing the distances calculated by the algorithm. - ///If you don't use this function before calling \ref run(), - ///it will allocate one. The destructor deallocates this - ///automatically allocated map, of course. - ///\return (*this) - Bfs &distMap(DistMap &m) - { - if(local_dist) { - delete _dist; - local_dist=false; - } - _dist = &m; - return *this; - } - - public: - ///\name Execution control - ///The simplest way to execute the algorithm is to use - ///one of the member functions called \c run(...). - ///\n - ///If you need more control on the execution, - ///first you must call \ref init(), then you can add several source nodes - ///with \ref addSource(). - ///Finally \ref start() will perform the actual path - ///computation. - - ///@{ - - ///Initializes the internal data structures. - - ///Initializes the internal data structures. - /// - void init() - { - create_maps(); - _queue.resize(countNodes(*G)); - _queue_head=_queue_tail=0; - _curr_dist=1; - for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { - _pred->set(u,INVALID); -// _predNode->set(u,INVALID); - _reached->set(u,false); - _processed->set(u,false); - } - } - - ///Adds a new source node. - - ///Adds a new source node to the set of nodes to be processed. - /// - void addSource(Node s) - { - if(!(*_reached)[s]) - { - _reached->set(s,true); - _pred->set(s,INVALID); - _dist->set(s,0); - _queue[_queue_head++]=s; - _queue_next_dist=_queue_head; - } - } - - ///Processes the next node. - - ///Processes the next node. - /// - ///\warning The queue must not be empty! - void processNextNode() - { - if(_queue_tail==_queue_next_dist) { - _curr_dist++; - _queue_next_dist=_queue_head; - } - Node n=_queue[_queue_tail++]; - _processed->set(n,true); - Node m; - for(OutEdgeIt e(*G,n);e!=INVALID;++e) - if(!(*_reached)[m=G->target(e)]) { - _queue[_queue_head++]=m; - _reached->set(m,true); - _pred->set(m,e); -// _pred_node->set(m,n); - _dist->set(m,_curr_dist); - } - } - - ///\brief Returns \c false if there are nodes - ///to be processed in the queue - /// - ///Returns \c false if there are nodes - ///to be processed in the queue - bool emptyQueue() { return _queue_tail==_queue_head; } - ///Returns the number of the nodes to be processed. - - ///Returns the number of the nodes to be processed in the queue. - /// - int queueSize() { return _queue_head-_queue_tail; } - - ///Executes the algorithm. - - ///Executes the algorithm. - /// - ///\pre init() must be called and at least one node should be added - ///with addSource() before using this function. - /// - ///This method runs the %BFS algorithm from the root node(s) - ///in order to - ///compute the - ///shortest path to each node. The algorithm computes - ///- The shortest path tree. - ///- The distance of each node from the root(s). - /// - void start() - { - while ( !emptyQueue() ) processNextNode(); - } - - ///Executes the algorithm until \c dest is reached. - - ///Executes the algorithm until \c dest is reached. - /// - ///\pre init() must be called and at least one node should be added - ///with addSource() before using this function. - /// - ///This method runs the %BFS algorithm from the root node(s) - ///in order to - ///compute the - ///shortest path to \c dest. The algorithm computes - ///- The shortest path to \c dest. - ///- The distance of \c dest from the root(s). - /// - void start(Node dest) - { - while ( !emptyQueue() && _queue[_queue_tail]!=dest ) processNextNode(); - } - - ///Executes the algorithm until a condition is met. - - ///Executes the algorithm until a condition is met. - /// - ///\pre init() must be called and at least one node should be added - ///with addSource() before using this function. - /// - ///\param nm must be a bool (or convertible) node map. The algorithm - ///will stop when it reaches a node \c v with nm[v]==true. - template - void start(const NM &nm) - { - while ( !emptyQueue() && !nm[_queue[_queue_tail]] ) processNextNode(); - } - - ///Runs %BFS algorithm from node \c s. - - ///This method runs the %BFS algorithm from a root node \c s - ///in order to - ///compute the - ///shortest path to each node. The algorithm computes - ///- The shortest path tree. - ///- The distance of each node from the root. - /// - ///\note d.run(s) is just a shortcut of the following code. - ///\code - /// d.init(); - /// d.addSource(s); - /// d.start(); - ///\endcode - void run(Node s) { - init(); - addSource(s); - start(); - } - - ///Finds the shortest path between \c s and \c t. - - ///Finds the shortest path between \c s and \c t. - /// - ///\return The length of the shortest s---t path if there exists one, - ///0 otherwise. - ///\note Apart from the return value, d.run(s) is - ///just a shortcut of the following code. - ///\code - /// d.init(); - /// d.addSource(s); - /// d.start(t); - ///\endcode - int run(Node s,Node t) { - init(); - addSource(s); - start(t); - return reached(t)?_curr_dist-1+(_queue_tail==_queue_next_dist):0; - } - - ///@} - - ///\name Query Functions - ///The result of the %BFS algorithm can be obtained using these - ///functions.\n - ///Before the use of these functions, - ///either run() or start() must be called. - - ///@{ - - ///Copies the shortest path to \c t into \c p - - ///This function copies the shortest path to \c t into \c p. - ///If it \c \t is a source itself or unreachable, then it does not - ///alter \c p. - ///\todo Is it the right way to handle unreachable nodes? - ///\return Returns \c true if a path to \c t was actually copied to \c p, - ///\c false otherwise. - ///\sa DirPath - template - bool getPath(P &p,Node t) - { - if(reached(t)) { - p.clear(); - typename P::Builder b(p); - for(b.setStartNode(t);pred(t)!=INVALID;t=predNode(t)) - b.pushFront(pred(t)); - b.commit(); - return true; - } - return false; - } - - ///The distance of a node from the root(s). - - ///Returns the distance of a node from the root(s). - ///\pre \ref run() must be called before using this function. - ///\warning If node \c v in unreachable from the root(s) the return value - ///of this function is undefined. - int dist(Node v) const { return (*_dist)[v]; } - - ///Returns the 'previous edge' of the shortest path tree. - - ///For a node \c v it returns the 'previous edge' - ///of the shortest path tree, - ///i.e. it returns the last edge of a shortest path from the root(s) to \c - ///v. It is \ref INVALID - ///if \c v is unreachable from the root(s) or \c v is a root. The - ///shortest path tree used here is equal to the shortest path tree used in - ///\ref predNode(Node v). - ///\pre Either \ref run() or \ref start() must be called before using - ///this function. - ///\todo predEdge could be a better name. - Edge pred(Node v) const { return (*_pred)[v];} - - ///Returns the 'previous node' of the shortest path tree. - - ///For a node \c v it returns the 'previous node' - ///of the shortest path tree, - ///i.e. it returns the last but one node from a shortest path from the - ///root(a) to \c /v. - ///It is INVALID if \c v is unreachable from the root(s) or - ///if \c v itself a root. - ///The shortest path tree used here is equal to the shortest path - ///tree used in \ref pred(Node v). - ///\pre Either \ref run() or \ref start() must be called before - ///using this function. - Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID: - G->source((*_pred)[v]); } - - ///Returns a reference to the NodeMap of distances. - - ///Returns a reference to the NodeMap of distances. - ///\pre Either \ref run() or \ref init() must - ///be called before using this function. - const DistMap &distMap() const { return *_dist;} - - ///Returns a reference to the shortest path tree map. - - ///Returns a reference to the NodeMap of the edges of the - ///shortest path tree. - ///\pre Either \ref run() or \ref init() - ///must be called before using this function. - const PredMap &predMap() const { return *_pred;} - -// ///Returns a reference to the map of nodes of shortest paths. - -// ///Returns a reference to the NodeMap of the last but one nodes of the -// ///shortest path tree. -// ///\pre \ref run() must be called before using this function. -// const PredNodeMap &predNodeMap() const { return *_predNode;} - - ///Checks if a node is reachable from the root. - - ///Returns \c true if \c v is reachable from the root. - ///\warning The source nodes are indicated as unreached. - ///\pre Either \ref run() or \ref start() - ///must be called before using this function. - /// - bool reached(Node v) { return (*_reached)[v]; } - - ///@} - }; - - ///Default traits class of Bfs function. - - ///Default traits class of Bfs function. - ///\param GR Graph type. - template - struct BfsWizardDefaultTraits - { - ///The graph type the algorithm runs on. - typedef GR Graph; - ///\brief The type of the map that stores the last - ///edges of the shortest paths. - /// - ///The type of the map that stores the last - ///edges of the shortest paths. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef NullMap PredMap; - ///Instantiates a PredMap. - - ///This function instantiates a \ref PredMap. - ///\param G is the graph, to which we would like to define the PredMap. - ///\todo The graph alone may be insufficient to initialize - static PredMap *createPredMap(const GR &) - { - return new PredMap(); - } -// ///\brief The type of the map that stores the last but one -// ///nodes of the shortest paths. -// /// -// ///The type of the map that stores the last but one -// ///nodes of the shortest paths. -// ///It must meet the \ref concept::WriteMap "WriteMap" concept. -// /// -// typedef NullMap PredNodeMap; -// ///Instantiates a PredNodeMap. - -// ///This function instantiates a \ref PredNodeMap. -// ///\param G is the graph, to which -// ///we would like to define the \ref PredNodeMap -// static PredNodeMap *createPredNodeMap(const GR &G) -// { -// return new PredNodeMap(); -// } - - ///The type of the map that indicates which nodes are processed. - - ///The type of the map that indicates which nodes are processed. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - ///\todo named parameter to set this type, function to read and write. - typedef NullMap ProcessedMap; - ///Instantiates a ProcessedMap. - - ///This function instantiates a \ref ProcessedMap. - ///\param G is the graph, to which - ///we would like to define the \ref ProcessedMap - static ProcessedMap *createProcessedMap(const GR &) - { - return new ProcessedMap(); - } - ///The type of the map that indicates which nodes are reached. - - ///The type of the map that indicates which nodes are reached. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - ///\todo named parameter to set this type, function to read and write. - typedef typename Graph::template NodeMap ReachedMap; - ///Instantiates a ReachedMap. - - ///This function instantiates a \ref ReachedMap. - ///\param G is the graph, to which - ///we would like to define the \ref ReachedMap. - static ReachedMap *createReachedMap(const GR &G) - { - return new ReachedMap(G); - } - ///The type of the map that stores the dists of the nodes. - - ///The type of the map that stores the dists of the nodes. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef NullMap DistMap; - ///Instantiates a DistMap. - - ///This function instantiates a \ref DistMap. - ///\param G is the graph, to which we would like to define the \ref DistMap - static DistMap *createDistMap(const GR &) - { - return new DistMap(); - } - }; - - /// Default traits used by \ref BfsWizard - - /// To make it easier to use Bfs algorithm - ///we have created a wizard class. - /// This \ref BfsWizard class needs default traits, - ///as well as the \ref Bfs class. - /// The \ref BfsWizardBase is a class to be the default traits of the - /// \ref BfsWizard class. - template - class BfsWizardBase : public BfsWizardDefaultTraits - { - - typedef BfsWizardDefaultTraits Base; - protected: - /// Type of the nodes in the graph. - typedef typename Base::Graph::Node Node; - - /// Pointer to the underlying graph. - void *_g; - ///Pointer to the map of reached nodes. - void *_reached; - ///Pointer to the map of processed nodes. - void *_processed; - ///Pointer to the map of predecessors edges. - void *_pred; -// ///Pointer to the map of predecessors nodes. -// void *_predNode; - ///Pointer to the map of distances. - void *_dist; - ///Pointer to the source node. - Node _source; - - public: - /// Constructor. - - /// This constructor does not require parameters, therefore it initiates - /// all of the attributes to default values (0, INVALID). - BfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), -// _predNode(0), - _dist(0), _source(INVALID) {} - - /// Constructor. - - /// This constructor requires some parameters, - /// listed in the parameters list. - /// Others are initiated to 0. - /// \param g is the initial value of \ref _g - /// \param s is the initial value of \ref _source - BfsWizardBase(const GR &g, Node s=INVALID) : - _g((void *)&g), _reached(0), _processed(0), _pred(0), -// _predNode(0), - _dist(0), _source(s) {} - - }; - - /// A class to make the usage of Bfs algorithm easier - - /// This class is created to make it easier to use Bfs algorithm. - /// It uses the functions and features of the plain \ref Bfs, - /// but it is much simpler to use it. - /// - /// Simplicity means that the way to change the types defined - /// in the traits class is based on functions that returns the new class - /// and not on templatable built-in classes. - /// When using the plain \ref Bfs - /// the new class with the modified type comes from - /// the original class by using the :: - /// operator. In the case of \ref BfsWizard only - /// a function have to be called and it will - /// return the needed class. - /// - /// It does not have own \ref run method. When its \ref run method is called - /// it initiates a plain \ref Bfs class, and calls the \ref Bfs::run - /// method of it. - template - class BfsWizard : public TR - { - typedef TR Base; - - ///The type of the underlying graph. - typedef typename TR::Graph Graph; - //\e - typedef typename Graph::Node Node; - //\e - typedef typename Graph::NodeIt NodeIt; - //\e - typedef typename Graph::Edge Edge; - //\e - typedef typename Graph::OutEdgeIt OutEdgeIt; - - ///\brief The type of the map that stores - ///the reached nodes - typedef typename TR::ReachedMap ReachedMap; - ///\brief The type of the map that stores - ///the processed nodes - typedef typename TR::ProcessedMap ProcessedMap; - ///\brief The type of the map that stores the last - ///edges of the shortest paths. - typedef typename TR::PredMap PredMap; -// ///\brief The type of the map that stores the last but one -// ///nodes of the shortest paths. -// typedef typename TR::PredNodeMap PredNodeMap; - ///The type of the map that stores the dists of the nodes. - typedef typename TR::DistMap DistMap; - -public: - /// Constructor. - BfsWizard() : TR() {} - - /// Constructor that requires parameters. - - /// Constructor that requires parameters. - /// These parameters will be the default values for the traits class. - BfsWizard(const Graph &g, Node s=INVALID) : - TR(g,s) {} - - ///Copy constructor - BfsWizard(const TR &b) : TR(b) {} - - ~BfsWizard() {} - - ///Runs Bfs algorithm from a given node. - - ///Runs Bfs algorithm from a given node. - ///The node can be given by the \ref source function. - void run() - { - if(Base::_source==INVALID) throw UninitializedParameter(); - Bfs alg(*(Graph*)Base::_g); - if(Base::_reached) - alg.reachedMap(*(ReachedMap*)Base::_reached); - if(Base::_processed) alg.processedMap(*(ProcessedMap*)Base::_processed); - if(Base::_pred) alg.predMap(*(PredMap*)Base::_pred); -// if(Base::_predNode) alg.predNodeMap(*(PredNodeMap*)Base::_predNode); - if(Base::_dist) alg.distMap(*(DistMap*)Base::_dist); - alg.run(Base::_source); - } - - ///Runs Bfs algorithm from the given node. - - ///Runs Bfs algorithm from the given node. - ///\param s is the given source. - void run(Node s) - { - Base::_source=s; - run(); - } - - template - struct DefPredMapBase : public Base { - typedef T PredMap; - static PredMap *createPredMap(const Graph &) { return 0; }; - DefPredMapBase(const TR &b) : TR(b) {} - }; - - ///\brief \ref named-templ-param "Named parameter" - ///function for setting PredMap - /// - /// \ref named-templ-param "Named parameter" - ///function for setting PredMap - /// - template - BfsWizard > predMap(const T &t) - { - Base::_pred=(void *)&t; - return BfsWizard >(*this); - } - - - template - struct DefReachedMapBase : public Base { - typedef T ReachedMap; - static ReachedMap *createReachedMap(const Graph &) { return 0; }; - DefReachedMapBase(const TR &b) : TR(b) {} - }; - - ///\brief \ref named-templ-param "Named parameter" - ///function for setting ReachedMap - /// - /// \ref named-templ-param "Named parameter" - ///function for setting ReachedMap - /// - template - BfsWizard > reachedMap(const T &t) - { - Base::_pred=(void *)&t; - return BfsWizard >(*this); - } - - - template - struct DefProcessedMapBase : public Base { - typedef T ProcessedMap; - static ProcessedMap *createProcessedMap(const Graph &) { return 0; }; - DefProcessedMapBase(const TR &b) : TR(b) {} - }; - - ///\brief \ref named-templ-param "Named parameter" - ///function for setting ProcessedMap - /// - /// \ref named-templ-param "Named parameter" - ///function for setting ProcessedMap - /// - template - BfsWizard > processedMap(const T &t) - { - Base::_pred=(void *)&t; - return BfsWizard >(*this); - } - - -// template -// struct DefPredNodeMapBase : public Base { -// typedef T PredNodeMap; -// static PredNodeMap *createPredNodeMap(const Graph &G) { return 0; }; -// DefPredNodeMapBase(const TR &b) : TR(b) {} -// }; - -// ///\brief \ref named-templ-param "Named parameter" -// ///function for setting PredNodeMap type -// /// -// /// \ref named-templ-param "Named parameter" -// ///function for setting PredNodeMap type -// /// -// template -// BfsWizard > predNodeMap(const T &t) -// { -// Base::_predNode=(void *)&t; -// return BfsWizard >(*this); -// } - - template - struct DefDistMapBase : public Base { - typedef T DistMap; - static DistMap *createDistMap(const Graph &) { return 0; }; - DefDistMapBase(const TR &b) : TR(b) {} - }; - - ///\brief \ref named-templ-param "Named parameter" - ///function for setting DistMap type - /// - /// \ref named-templ-param "Named parameter" - ///function for setting DistMap type - /// - template - BfsWizard > distMap(const T &t) - { - Base::_dist=(void *)&t; - return BfsWizard >(*this); - } - - /// Sets the source node, from which the Bfs algorithm runs. - - /// Sets the source node, from which the Bfs algorithm runs. - /// \param s is the source node. - BfsWizard &source(Node s) - { - Base::_source=s; - return *this; - } - - }; - - ///Function type interface for Bfs algorithm. - - /// \ingroup flowalgs - ///Function type interface for Bfs algorithm. - /// - ///This function also has several - ///\ref named-templ-func-param "named parameters", - ///they are declared as the members of class \ref BfsWizard. - ///The following - ///example shows how to use these parameters. - ///\code - /// bfs(g,source).predMap(preds).run(); - ///\endcode - ///\warning Don't forget to put the \ref BfsWizard::run() "run()" - ///to the end of the parameter list. - ///\sa BfsWizard - ///\sa Bfs - template - BfsWizard > - bfs(const GR &g,typename GR::Node s=INVALID) - { - return BfsWizard >(g,s); - } - -} //END OF NAMESPACE LEMON - -#endif - diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bin_heap.h --- a/src/lemon/bin_heap.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,303 +0,0 @@ -/* -*- C++ -*- - * src/lemon/bin_heap.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_BIN_HEAP_H -#define LEMON_BIN_HEAP_H - -///\ingroup auxdat -///\file -///\brief Binary Heap implementation. - -#include -#include -#include - -namespace lemon { - - /// \addtogroup auxdat - /// @{ - - /// A Binary Heap implementation. - - ///This class implements the \e binary \e heap data structure. A \e heap - ///is a data structure for storing items with specified values called \e - ///priorities in such a way that finding the item with minimum priority is - ///efficient. \c Compare specifies the ordering of the priorities. In a heap - ///one can change the priority of an item, add or erase an item, etc. - /// - ///\param Item Type of the items to be stored. - ///\param Prio Type of the priority of the items. - ///\param ItemIntMap A read and writable Item int map, used internally - ///to handle the cross references. - ///\param Compare A class for the ordering of the priorities. The - ///default is \c std::less. - /// - ///\sa FibHeap - ///\sa Dijkstra - template > - class BinHeap { - - public: - typedef Item ItemType; - // FIXME: stl-ben nem ezt hivjak value_type -nak, hanem a kovetkezot... - typedef Prio PrioType; - typedef std::pair PairType; - typedef ItemIntMap ItemIntMapType; - typedef Compare PrioCompare; - - /// \brief Type to represent the items states. - /// - /// Each Item element have a state associated to it. It may be "in heap", - /// "pre heap" or "post heap". The latter two are indifferent from the - /// heap's point of view, but may be useful to the user. - /// - /// The ItemIntMap \e should be initialized in such way that it maps - /// PRE_HEAP (-1) to any element to be put in the heap... - enum state_enum { - IN_HEAP = 0, - PRE_HEAP = -1, - POST_HEAP = -2 - }; - - private: - std::vector data; - Compare comp; - ItemIntMap &iim; - - public: - /// \brief The constructor. - /// - /// The constructor. - /// \param _iim should be given to the constructor, since it is used - /// internally to handle the cross references. The value of the map - /// should be PRE_HEAP (-1) for each element. - explicit BinHeap(ItemIntMap &_iim) : iim(_iim) {} - - /// \brief The constructor. - /// - /// The constructor. - /// \param _iim should be given to the constructor, since it is used - /// internally to handle the cross references. The value of the map - /// should be PRE_HEAP (-1) for each element. - /// - /// \param _comp The comparator function object. - BinHeap(ItemIntMap &_iim, const Compare &_comp) - : iim(_iim), comp(_comp) {} - - - /// The number of items stored in the heap. - /// - /// \brief Returns the number of items stored in the heap. - int size() const { return data.size(); } - - /// \brief Checks if the heap stores no items. - /// - /// Returns \c true if and only if the heap stores no items. - bool empty() const { return data.empty(); } - - private: - static int parent(int i) { return (i-1)/2; } - static int second_child(int i) { return 2*i+2; } - bool less(const PairType &p1, const PairType &p2) const { - return comp(p1.second, p2.second); - } - - int bubble_up(int hole, PairType p); - int bubble_down(int hole, PairType p, int length); - - void move(const PairType &p, int i) { - data[i] = p; - iim.set(p.first, i); - } - - void rmidx(int h) { - int n = data.size()-1; - if( h>=0 && h<=n ) { - iim.set(data[h].first, POST_HEAP); - if ( h=0 ) - s=0; - return state_enum(s); - } - - }; // class BinHeap - - - template - int BinHeap::bubble_up(int hole, PairType p) { - int par = parent(hole); - while( hole>0 && less(p,data[par]) ) { - move(data[par],hole); - hole = par; - par = parent(hole); - } - move(p, hole); - return hole; - } - - template - int BinHeap::bubble_down(int hole, PairType p, int length) { - int child = second_child(hole); - while(child < length) { - if( less(data[child-1], data[child]) ) { - --child; - } - if( !less(data[child], p) ) - goto ok; - move(data[child], hole); - hole = child; - child = second_child(hole); - } - child--; - if( child -#include - -///\ingroup graphmaps -///\file -///\brief Observer registry for graph alteration observers. - -namespace lemon { - - /// \addtogroup graphmaps - /// @{ - - /// \brief Registry class to register objects observes alterations in - /// the graph. - /// - /// This class is a registry for the objects which observe the - /// alterations in a container. The alteration observers can be attached - /// to and detached from the registry. The observers have to inherit - /// from the \ref AlterationNotifier::ObserverBase and override - /// the virtual functions in that. - /// - /// The most important application of the alteration observing is the - /// dynamic map implementation. - /// - /// \param _Item The item type what the observers are observing, usually - /// edge or node. - /// - /// \author Balazs Dezso - - template - class AlterationNotifier { - public: - typedef _Item Item; - - /// ObserverBase is the base class for the observers. - - /// ObserverBase is the abstract base class for the observers. - /// It will be notified about an item was inserted into or - /// erased from the graph. - /// - /// The observer interface contains some pure virtual functions - /// to override. The add() and erase() functions are - /// to notify the oberver when one item is added or - /// erased. - /// - /// The build() and clear() members are to notify the observer - /// about the container is built from an empty container or - /// is cleared to an empty container. - /// - /// \author Balazs Dezso - - class ObserverBase { - protected: - typedef AlterationNotifier Registry; - - friend class AlterationNotifier; - - /// \brief Default constructor. - /// - /// Default constructor for ObserverBase. - /// - ObserverBase() : registry(0) {} - - virtual ~ObserverBase() {} - - /// \brief Attaches the observer into an AlterationNotifier. - /// - /// This member attaches the observer into an AlterationNotifier. - /// - void attach(AlterationNotifier& r) { - registry = &r; - registry->attach(*this); - } - - /// \brief Detaches the observer into an AlterationNotifier. - /// - /// This member detaches the observer from an AlterationNotifier. - /// - void detach() { - if (registry) { - registry->detach(*this); - } - } - - - /// Gives back a pointer to the registry what the map attached into. - - /// This function gives back a pointer to the registry what the map - /// attached into. - /// - Registry* getRegistry() const { return const_cast(registry); } - - /// Gives back true when the observer is attached into a registry. - bool attached() const { return registry != 0; } - - private: - - ObserverBase(const ObserverBase& copy); - ObserverBase& operator=(const ObserverBase& copy); - - protected: - - Registry* registry; - int registry_index; - - public: - - /// \brief The member function to notificate the observer about an - /// item is added to the container. - /// - /// The add() member function notificates the observer about an item - /// is added to the container. It have to be overrided in the - /// subclasses. - - virtual void add(const Item&) = 0; - - /// \brief The member function to notificate the observer about - /// simulitem is added to the container. - /// - /// The add() member function notificates the observer about an item - /// is added to the container. It have to be overrided in the - /// subclasses. - - virtual void add(const std::vector& items) { - for (int i = 0; i < (int)items.size(); ++i) { - add(items[i]); - } - } - - /// \brief The member function to notificate the observer about an - /// item is erased from the container. - /// - /// The erase() member function notificates the observer about an - /// item is erased from the container. It have to be overrided in - /// the subclasses. - - virtual void erase(const Item&) = 0; - - virtual void erase(const std::vector& items) { - for (int i = 0; i < (int)items.size(); ++i) { - add(items[i]); - } - } - - /// \brief The member function to notificate the observer about the - /// container is built. - /// - /// The build() member function notificates the observer about the - /// container is built from an empty container. It have to be - /// overrided in the subclasses. - - virtual void build() = 0; - - /// \brief The member function to notificate the observer about all - /// items are erased from the container. - /// - /// The clear() member function notificates the observer about all - /// items are erased from the container. It have to be overrided in - /// the subclasses. - - virtual void clear() = 0; - - }; - - protected: - - - typedef std::vector Container; - - Container container; - - - public: - - /// Default constructor. - - /// - /// The default constructor of the AlterationNotifier. - /// It creates an empty registry. - AlterationNotifier() {} - - /// Copy Constructor of the AlterationNotifier. - - /// Copy constructor of the AlterationNotifier. - /// It creates only an empty registry because the copiable - /// registry's observers have to be registered still into that registry. - AlterationNotifier(const AlterationNotifier&) {} - - /// Assign operator. - - /// Assign operator for the AlterationNotifier. - /// It makes the notifier only empty because the copiable - /// notifier's observers have to be registered still into that registry. - AlterationNotifier& operator=(const AlterationNotifier&) { - typename Container::iterator it; - for (it = container.begin(); it != container.end(); ++it) { - (*it)->registry = 0; - } - } - - /// Destructor. - - /// Destructor of the AlterationNotifier. - /// - ~AlterationNotifier() { - typename Container::iterator it; - for (it = container.begin(); it != container.end(); ++it) { - (*it)->registry = 0; - } - } - - - protected: - - void attach(ObserverBase& observer) { - container.push_back(&observer); - observer.registry = this; - observer.registry_index = container.size()-1; - } - - void detach(ObserverBase& base) { - container.back()->registry_index = base.registry_index; - container[base.registry_index] = container.back(); - container.pop_back(); - base.registry = 0; - } - - public: - - /// \brief Notifies all the registered observers about an Item added to - /// the container. - /// - /// It notifies all the registered observers about an Item added to - /// the container. - /// - void add(const Item& item) { - typename Container::iterator it; - for (it = container.begin(); it != container.end(); ++it) { - (*it)->add(item); - } - } - - /// \brief Notifies all the registered observers about more Item added to - /// the container. - /// - /// It notifies all the registered observers about more Item added to - /// the container. - /// - void add(const std::vector& items) { - typename Container::iterator it; - for (it = container.begin(); it != container.end(); ++it) { - (*it)->add(items); - } - } - - /// \brief Notifies all the registered observers about an Item erased from - /// the container. - /// - /// It notifies all the registered observers about an Item erased from - /// the container. - /// - void erase(const Item& key) { - typename Container::iterator it; - for (it = container.begin(); it != container.end(); ++it) { - (*it)->erase(key); - } - } - - /// \brief Notifies all the registered observers about more Item erased - /// from the container. - /// - /// It notifies all the registered observers about more Item erased from - /// the container. - /// - void erase(const std::vector& items) { - typename Container::iterator it; - for (it = container.begin(); it != container.end(); ++it) { - (*it)->erase(items); - } - } - - - /// \brief Notifies all the registered observers about the container is - /// built. - /// - /// Notifies all the registered observers about the container is built - /// from an empty container. - void build() { - typename Container::iterator it; - for (it = container.begin(); it != container.end(); ++it) { - (*it)->build(); - } - } - - - /// \brief Notifies all the registered observers about all Items are - /// erased. - /// - /// Notifies all the registered observers about all Items are erased - /// from the container. - void clear() { - typename Container::iterator it; - for (it = container.begin(); it != container.end(); ++it) { - (*it)->clear(); - } - } - }; - - - /// \brief Class to extend a graph with the functionality of alteration - /// observing. - /// - /// AlterableGraphExtender extends the _Base graphs functionality with - /// the possibility of alteration observing. It defines two observer - /// registrys for the nodes and mapes. - /// - /// \todo Document what "alteration observing" is. And probably find a - /// better (shorter) name. - /// - /// \param _Base is the base class to extend. - /// - /// \pre _Base is conform to the BaseGraphComponent concept. - /// - /// \post AlterableGraphExtender<_Base> is conform to the - /// AlterableGraphComponent concept. - /// - /// \author Balazs Dezso - - template - class AlterableGraphExtender : public _Base { - public: - - typedef AlterableGraphExtender Graph; - typedef _Base Parent; - - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - - /// The edge observer registry. - typedef AlterationNotifier EdgeNotifier; - /// The node observer registry. - typedef AlterationNotifier NodeNotifier; - - - protected: - - mutable EdgeNotifier edge_notifier; - - mutable NodeNotifier node_notifier; - - public: - - /// \brief Gives back the edge alteration notifier. - /// - /// Gives back the edge alteration notifier. - EdgeNotifier& getNotifier(Edge) const { - return edge_notifier; - } - - /// \brief Gives back the node alteration notifier. - /// - /// Gives back the node alteration notifier. - NodeNotifier& getNotifier(Node) const { - return node_notifier; - } - - ~AlterableGraphExtender() { - node_notifier.clear(); - edge_notifier.clear(); - } - - }; - - /// \brief Class to extend an undirected graph with the functionality of - /// alteration observing. - /// - /// \todo Document. - /// - /// \sa AlterableGraphExtender - /// - /// \bug This should be done some other way. Possibilities: template - /// specialization (not very easy, if at all possible); some kind of - /// enable_if boost technique? - - template - class AlterableUndirGraphExtender - : public AlterableGraphExtender<_Base> { - public: - - typedef AlterableUndirGraphExtender Graph; - typedef AlterableGraphExtender<_Base> Parent; - - typedef typename Parent::UndirEdge UndirEdge; - - /// The edge observer registry. - typedef AlterationNotifier UndirEdgeNotifier; - - protected: - - mutable UndirEdgeNotifier undir_edge_notifier; - - public: - - using Parent::getNotifier; - UndirEdgeNotifier& getNotifier(UndirEdge) const { - return undir_edge_notifier; - } - - ~AlterableUndirGraphExtender() { - undir_edge_notifier.clear(); - } - }; - -/// @} - - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/array_map.h --- a/src/lemon/bits/array_map.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,369 +0,0 @@ -/* -*- C++ -*- - * src/lemon/bits/array_map.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_ARRAY_MAP_H -#define LEMON_ARRAY_MAP_H - -#include -#include - -///\ingroup graphmaps -///\file -///\brief Graph maps that construates and destruates -///their elements dynamically. - -namespace lemon { - - - /// \addtogroup graphmaps - /// @{ - - /// The ArrayMap template class is graph map structure what - /// automatically updates the map when a key is added to or erased from - /// the map. This map factory uses the allocators to implement - /// the container functionality. - /// - /// The template parameter is the AlterationNotifier that the maps - /// will belong to and the Value. - - - template - class ArrayMap : public AlterationNotifier<_Item>::ObserverBase { - - typedef _Item Item; - public: - - /// The graph type of the maps. - typedef _Graph Graph; - /// The key type of the maps. - typedef _Item Key; - - typedef AlterationNotifier<_Item> Registry; - - /// The MapBase of the Map which imlements the core regisitry function. - typedef typename Registry::ObserverBase Parent; - - /// The value type of the map. - typedef _Value Value; - - - private: - typedef std::allocator Allocator; - - - public: - - /// Graph and Registry initialized map constructor. - - ArrayMap(const Graph& _g) : graph(&_g) { - Item it; - attach(_g.getNotifier(Item())); - allocate_memory(); - for (graph->first(it); it != INVALID; graph->next(it)) { - int id = graph->id(it);; - allocator.construct(&(values[id]), Value()); - } - } - - /// Constructor to use default value to initialize the map. - - /// It constrates a map and initialize all of the the map. - - ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) { - Item it; - attach(_g.getNotifier(_Item())); - allocate_memory(); - for (graph->first(it); it != INVALID; graph->next(it)) { - int id = graph->id(it);; - allocator.construct(&(values[id]), _v); - } - } - - /// Constructor to copy a map of the same map type. - - ArrayMap(const ArrayMap& copy) : Parent() { - if (copy.attached()) { - attach(*copy.getRegistry()); - } - capacity = copy.capacity; - if (capacity == 0) return; - values = allocator.allocate(capacity); - Item it; - for (graph->first(it); it != INVALID; graph->next(it)) { - int id = graph->id(it);; - allocator.construct(&(values[id]), copy.values[id]); - } - } - - using Parent::attach; - using Parent::detach; - using Parent::attached; - - /// Assign operator to copy a map of the same map type. - - ArrayMap& operator=(const ArrayMap& copy) { - if (© == this) return *this; - - if (graph != copy.graph) { - if (attached()) { - clear(); - detach(); - } - if (copy.attached()) { - attach(*copy.getRegistry()); - } - capacity = copy.capacity; - if (capacity == 0) return *this; - values = allocator.allocate(capacity); - } - - Item it; - for (graph->first(it); it != INVALID; graph->next(it)) { - int id = graph->id(it);; - allocator.construct(&(values[id]), copy.values[id]); - } - - return *this; - } - - /// The destructor of the map. - - virtual ~ArrayMap() { - if (attached()) { - clear(); - detach(); - } - } - - - ///The subscript operator. The map can be subscripted by the - ///actual keys of the graph. - - Value& operator[](const Key& key) { - int id = graph->id(key); - return values[id]; - } - - - ///The const subscript operator. The map can be subscripted by the - ///actual keys of the graph. - - const Value& operator[](const Key& key) const { - int id = graph->id(key); - return values[id]; - } - - /// Setter function of the map. Equivalent with map[key] = val. - /// This is a compatibility feature with the not dereferable maps. - - void set(const Key& key, const Value& val) { - (*this)[key] = val; - } - - /// Add a new key to the map. It called by the map registry. - - void add(const Key& key) { - int id = graph->id(key); - if (id >= capacity) { - int new_capacity = (capacity == 0 ? 1 : capacity); - while (new_capacity <= id) { - new_capacity <<= 1; - } - Value* new_values = allocator.allocate(new_capacity); - Item it; - for (graph->first(it); it != INVALID; graph->next(it)) { - int jd = graph->id(it);; - if (id != jd) { - allocator.construct(&(new_values[jd]), values[jd]); - allocator.destroy(&(values[jd])); - } - } - if (capacity != 0) allocator.deallocate(values, capacity); - values = new_values; - capacity = new_capacity; - } - allocator.construct(&(values[id]), Value()); - } - - void add(const std::vector& keys) { - int max_id = -1; - for (int i = 0; i < (int)keys.size(); ++i) { - int id = graph->id(keys[i]); - if (id > max_id) { - max_id = id; - } - } - if (max_id >= capacity) { - int new_capacity = (capacity == 0 ? 1 : capacity); - while (new_capacity <= max_id) { - new_capacity <<= 1; - } - Value* new_values = allocator.allocate(new_capacity); - Item it; - for (graph->first(it); it != INVALID; graph->next(it)) { - int id = graph->id(it); - bool found = false; - for (int i = 0; i < (int)keys.size(); ++i) { - int jd = graph->id(keys[i]); - if (id == jd) { - found = true; - break; - } - } - if (found) continue; - allocator.construct(&(new_values[id]), values[id]); - allocator.destroy(&(values[id])); - } - if (capacity != 0) allocator.deallocate(values, capacity); - values = new_values; - capacity = new_capacity; - } - for (int i = 0; i < (int)keys.size(); ++i) { - int id = graph->id(keys[i]); - allocator.construct(&(values[id]), Value()); - } - } - - /// Erase a key from the map. It called by the map registry. - - void erase(const Key& key) { - int id = graph->id(key); - allocator.destroy(&(values[id])); - } - - void erase(const std::vector& keys) { - for (int i = 0; i < (int)keys.size(); ++i) { - int id = graph->id(keys[i]); - allocator.destroy(&(values[id])); - } - } - - void build() { - allocate_memory(); - Item it; - for (graph->first(it); it != INVALID; graph->next(it)) { - int id = graph->id(it);; - allocator.construct(&(values[id]), Value()); - } - } - - void clear() { - if (capacity != 0) { - Item it; - for (graph->first(it); it != INVALID; graph->next(it)) { - int id = graph->id(it); - allocator.destroy(&(values[id])); - } - allocator.deallocate(values, capacity); - capacity = 0; - } - } - - const Graph* getGraph() { - return graph; - } - - private: - - void allocate_memory() { - int max_id = graph->maxId(_Item()); - if (max_id == -1) { - capacity = 0; - values = 0; - return; - } - capacity = 1; - while (capacity <= max_id) { - capacity <<= 1; - } - values = allocator.allocate(capacity); - } - - const Graph* graph; - int capacity; - Value* values; - Allocator allocator; - - }; - - template - class ArrayMappableGraphExtender : public _Base { - public: - - typedef ArrayMappableGraphExtender<_Base> Graph; - typedef _Base Parent; - - typedef typename Parent::Node Node; - typedef typename Parent::NodeIt NodeIt; - typedef typename Parent::NodeNotifier NodeObserverRegistry; - - typedef typename Parent::Edge Edge; - typedef typename Parent::EdgeIt EdgeIt; - typedef typename Parent::EdgeNotifier EdgeObserverRegistry; - - - - template - class NodeMap - : public IterableMapExtender > { - public: - typedef ArrayMappableGraphExtender<_Base> Graph; - - typedef typename Graph::Node Node; - typedef typename Graph::NodeIt NodeIt; - - typedef IterableMapExtender > Parent; - - //typedef typename Parent::Graph Graph; - typedef typename Parent::Value Value; - - NodeMap(const Graph& g) - : Parent(g) {} - NodeMap(const Graph& g, const Value& v) - : Parent(g, v) {} - - }; - - template - class EdgeMap - : public IterableMapExtender > { - public: - typedef ArrayMappableGraphExtender<_Base> Graph; - - typedef typename Graph::Edge Edge; - typedef typename Graph::EdgeIt EdgeIt; - - typedef IterableMapExtender > Parent; - - //typedef typename Parent::Graph Graph; - typedef typename Parent::Value Value; - - EdgeMap(const Graph& g) - : Parent(g) {} - EdgeMap(const Graph& g, const Value& v) - : Parent(g, v) {} - - }; - - }; - -/// @} - -} - -#endif //LEMON_ARRAY_MAP_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/clearable_graph_extender.h --- a/src/lemon/bits/clearable_graph_extender.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -// -*- c++ -*- - -#ifndef LEMON_CLEARABLE_GRAPH_EXTENDER_H -#define LEMON_CLEARABLE_GRAPH_EXTENDER_H - -#include - - -namespace lemon { - - template - class ClearableGraphExtender : public _Base { - public: - - typedef ClearableGraphExtender Graph; - typedef _Base Parent; - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - - void clear() { - Parent::getNotifier(Node()).clear(); - Parent::getNotifier(Edge()).clear(); - Parent::clear(); - } - - }; - - template - class ClearableUndirGraphExtender : public _Base { - public: - - typedef ClearableUndirGraphExtender Graph; - typedef _Base Parent; - typedef typename Parent::Node Node; - typedef typename Parent::UndirEdge UndirEdge; - typedef typename Parent::Edge Edge; - - void clear() { - Parent::getNotifier(Node()).clear(); - Parent::getNotifier(UndirEdge()).clear(); - Parent::getNotifier(Edge()).clear(); - Parent::clear(); - } - - }; - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/default_map.h --- a/src/lemon/bits/default_map.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,230 +0,0 @@ -/* -*- C++ -*- - * src/lemon/default_map.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_DEFAULT_MAP_H -#define LEMON_DEFAULT_MAP_H - - -#include -#include - -///\ingroup graphmaps -///\file -///\brief Graph maps that construct and destruct -///their elements dynamically. - -namespace lemon { - -/// \addtogroup graphmaps -/// @{ - - /** The ArrayMap template class is graph map structure what - * automatically updates the map when a key is added to or erased from - * the map. This map uses the VectorMap if the Value is a primitive - * type and the ArrayMap for the other cases. - * - * The template parameter is the MapRegistry that the maps - * will belong to and the Value. - */ - - - - template - struct DefaultMapSelector { - typedef ArrayMap<_Graph, _Item, _Value> Map; - }; - - // bool - template - struct DefaultMapSelector<_Graph, _Item, bool> { - typedef VectorMap<_Graph, _Item, bool> Map; - }; - - // char - template - struct DefaultMapSelector<_Graph, _Item, char> { - typedef VectorMap<_Graph, _Item, char> Map; - }; - - template - struct DefaultMapSelector<_Graph, _Item, signed char> { - typedef VectorMap<_Graph, _Item, signed char> Map; - }; - - template - struct DefaultMapSelector<_Graph, _Item, unsigned char> { - typedef VectorMap<_Graph, _Item, unsigned char> Map; - }; - - - // int - template - struct DefaultMapSelector<_Graph, _Item, signed int> { - typedef VectorMap<_Graph, _Item, signed int> Map; - }; - - template - struct DefaultMapSelector<_Graph, _Item, unsigned int> { - typedef VectorMap<_Graph, _Item, unsigned int> Map; - }; - - - // short - template - struct DefaultMapSelector<_Graph, _Item, signed short> { - typedef VectorMap<_Graph, _Item, signed short> Map; - }; - - template - struct DefaultMapSelector<_Graph, _Item, unsigned short> { - typedef VectorMap<_Graph, _Item, unsigned short> Map; - }; - - - // long - template - struct DefaultMapSelector<_Graph, _Item, signed long> { - typedef VectorMap<_Graph, _Item, signed long> Map; - }; - - template - struct DefaultMapSelector<_Graph, _Item, unsigned long> { - typedef VectorMap<_Graph, _Item, unsigned long> Map; - }; - - // \todo handling long long type - - - // float - template - struct DefaultMapSelector<_Graph, _Item, float> { - typedef VectorMap<_Graph, _Item, float> Map; - }; - - - // double - template - struct DefaultMapSelector<_Graph, _Item, double> { - typedef VectorMap<_Graph, _Item, double> Map; - }; - - - // long double - template - struct DefaultMapSelector<_Graph, _Item, long double> { - typedef VectorMap<_Graph, _Item, long double> Map; - }; - - - // pointer - template - struct DefaultMapSelector<_Graph, _Item, _Ptr*> { - typedef VectorMap<_Graph, _Item, _Ptr*> Map; - }; - - - - template < - typename _Graph, - typename _Item, - typename _Value> - class DefaultMap - : public DefaultMapSelector<_Graph, _Item, _Value>::Map { - public: - typedef typename DefaultMapSelector<_Graph, _Item, _Value>::Map Parent; - typedef DefaultMap<_Graph, _Item, _Value> Map; - - typedef typename Parent::Graph Graph; - typedef typename Parent::Value Value; - - DefaultMap(const Graph& _g) : Parent(_g) {} - DefaultMap(const Graph& _g, const Value& _v) : Parent(_g, _v) {} - }; - - - - template - class DefaultMappableGraphExtender : public _Base { - public: - - typedef DefaultMappableGraphExtender<_Base> Graph; - typedef _Base Parent; - - typedef typename Parent::Node Node; - typedef typename Parent::NodeIt NodeIt; - - typedef typename Parent::Edge Edge; - typedef typename Parent::EdgeIt EdgeIt; - - - template - class NodeMap - : public IterableMapExtender > { - public: - typedef DefaultMappableGraphExtender Graph; - typedef IterableMapExtender > Parent; - - NodeMap(const Graph& _g) - : Parent(_g) {} - NodeMap(const Graph& _g, const _Value& _v) - : Parent(_g, _v) {} - }; - - template - class EdgeMap - : public IterableMapExtender > { - public: - typedef DefaultMappableGraphExtender Graph; - typedef IterableMapExtender > Parent; - - EdgeMap(const Graph& _g) - : Parent(_g) {} - EdgeMap(const Graph& _g, const _Value& _v) - : Parent(_g, _v) {} - }; - - }; - - template - class MappableUndirGraphExtender : - public DefaultMappableGraphExtender<_Base> { - public: - - typedef MappableUndirGraphExtender Graph; - typedef DefaultMappableGraphExtender<_Base> Parent; - - typedef typename Parent::UndirEdge UndirEdge; - - template - class UndirEdgeMap - : public IterableMapExtender > { - public: - typedef MappableUndirGraphExtender Graph; - typedef IterableMapExtender< - DefaultMap > Parent; - - UndirEdgeMap(const Graph& _g) - : Parent(_g) {} - UndirEdgeMap(const Graph& _g, const _Value& _v) - : Parent(_g, _v) {} - }; - - - }; - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/erasable_graph_extender.h --- a/src/lemon/bits/erasable_graph_extender.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -// -*- c++ -*- - -#ifndef LEMON_ERASABLE_GRAPH_EXTENDER_H -#define LEMON_ERASABLE_GRAPH_EXTENDER_H - -#include - -#include - - -namespace lemon { - - template - class ErasableGraphExtender : public _Base { - public: - - typedef ErasableGraphExtender Graph; - typedef _Base Parent; - - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - - void erase(const Node& node) { - Edge edge; - Parent::firstOut(edge, node); - while (edge != INVALID ) { - erase(edge); - Parent::firstOut(edge, node); - } - - Parent::firstIn(edge, node); - while (edge != INVALID ) { - erase(edge); - Parent::firstIn(edge, node); - } - - Parent::getNotifier(Node()).erase(node); - Parent::erase(node); - } - - void erase(const Edge& edge) { - Parent::getNotifier(Edge()).erase(edge); - Parent::erase(edge); - } - - }; - - template - class ErasableUndirGraphExtender : public _Base { - public: - - typedef ErasableUndirGraphExtender Graph; - typedef _Base Parent; - - typedef typename Parent::Node Node; - typedef typename Parent::UndirEdge UndirEdge; - typedef typename Parent::Edge Edge; - - void erase(const Node& node) { - Edge edge; - Parent::firstOut(edge, node); - while (edge != INVALID ) { - erase(edge); - Parent::firstOut(edge, node); - } - - Parent::getNotifier(Node()).erase(node); - Parent::erase(node); - } - - void erase(const UndirEdge& uedge) { - std::vector edges; - edges.push_back(Edge(uedge,true)); - edges.push_back(Edge(uedge,false)); - Parent::getNotifier(Edge()).erase(edges); - Parent::getNotifier(UndirEdge()).erase(uedge); - Parent::erase(uedge); - } - - }; - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/extendable_graph_extender.h --- a/src/lemon/bits/extendable_graph_extender.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -// -*- c++ -*- - -#ifndef LEMON_EXTENDABLE_GRAPH_EXTENDER_H -#define LEMON_EXTENDABLE_GRAPH_EXTENDER_H - -namespace lemon { - - template - class ExtendableGraphExtender : public _Base { - public: - - typedef ExtendableGraphExtender Graph; - typedef _Base Parent; - - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - - Node addNode() { - Node node = Parent::addNode(); - Parent::getNotifier(Node()).add(node); - return node; - } - - Edge addEdge(const Node& from, const Node& to) { - Edge edge = Parent::addEdge(from, to); - Parent::getNotifier(Edge()).add(edge); - return edge; - } - - }; - - template - class ExtendableUndirGraphExtender : public _Base { - public: - - typedef ExtendableUndirGraphExtender Graph; - typedef _Base Parent; - - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - typedef typename Parent::UndirEdge UndirEdge; - - Node addNode() { - Node node = Parent::addNode(); - Parent::getNotifier(Node()).add(node); - return node; - } - - UndirEdge addEdge(const Node& from, const Node& to) { - UndirEdge uedge = Parent::addEdge(from, to); - Parent::getNotifier(UndirEdge()).add(uedge); - - std::vector edges; - edges.push_back(Edge(uedge, true)); - edges.push_back(Edge(uedge, false)); - Parent::getNotifier(Edge()).add(edges); - - return uedge; - } - - }; - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/extended_pair.h --- a/src/lemon/bits/extended_pair.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* -*- C++ -*- - * src/lemon/bits/extended_pair.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_EXTENDED_PAIR_H -#define LEMON_EXTENDED_PAIR_H - -///\ingroup misc -///\file -///\brief A more customizable pair type than std::pair. - -namespace lemon { - - /// \brief A more customizable pair type than std::pair. - /// - /// This type is a customizable pair type. The main goal - /// is that the constructor's parameter type does not depend - /// on the stored data type. This way it is possible to store - /// references in the extended_pair. - /// \code - /// int a; char b; - /// typedef extended_pair ICPair; - /// ICPair p(a, b); - /// // like a real reference to an std::pair - /// // but the pair does not exist - /// p.first = 42; - /// p.second = '@'; - /// \endcode - /// \param T1 The type of first. - /// \param A1 The parameter type for first. - /// \param T2 The type of second. - /// \param A2 The parameter type for second. - template - struct extended_pair { - /// \brief The type of first. - /// - /// The type of first. - typedef T1 first_type; - /// \brief The type of second. - /// - /// The type of second. - typedef T2 second_type; - - /// \brief Default constructor. - /// - /// Default constructor. It calls the default constructor of - /// first and second. - extended_pair() : first(), second() {} - - /// \brief Constructor. - /// - /// Constructor. - extended_pair(A1 f, A2 s) : first(f), second(s) {} - - /// \brief Template constructor. - /// - /// Template constructor. It copies everything which has - /// \c first and \c second member. - template - extended_pair(const Pair& pair) : first(pair.first), second(pair.second) {} - - /// \brief The first value - /// - /// The first value - T1 first; - /// \brief The second value - /// - /// The second value - T2 second; - }; - - /// \brief Equality operator - /// - /// Equality operator - template - bool operator==(const extended_pair& left, - const extended_pair& right) { - return left.first == right.first && left.second == right.second; - } - - /// \brief Inequality operator. - /// - /// Inequality operator. - template - bool operator!=(const extended_pair& left, - const extended_pair& right) { - return !(left == right); - } - - /// \brief Less operator. - /// - /// Less operator. - template - bool operator<(const extended_pair& left, - const extended_pair& right) { - return left.first < right.first || - (!(right.first - bool operator>(const extended_pair& left, - const extended_pair& right) { - return right < left; - } - - /// \brief Less or equal operator. - /// - /// Less or equal operator. - template - bool operator<=(const extended_pair& left, - const extended_pair& right) { - return !(right > left); - } - - /// \brief Greater or equal operator. - /// - /// Greater or equal operator. - template - bool operator>=(const extended_pair& left, - const extended_pair& right) { - return !(right < left); - } - -} -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/item_reader.h --- a/src/lemon/bits/item_reader.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,414 +0,0 @@ -/* -*- C++ -*- - * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -/// @defgroup item_io Item Readers and Writers -/// @ingroup io_group -/// \brief Item Readers and Writers -/// -/// The Input-Output classes can handle more data type by example -/// as map or attribute value. Each of these should be written and -/// read some way. The module make possible to do this. - -/// \ingroup item_io -/// \file -/// \brief Item reader bits for lemon input. - -#ifndef LEMON_BITS_ITEM_READER_H -#define LEMON_BITS_ITEM_READER_H - -#include -#include - -#include -#include -#include -#include - -namespace lemon { - - template - class DefaultReader; - - /// \ingroup item_io - /// - /// \brief Reader class for quoted strings. - /// - /// Reader class for quoted strings. It can process the escape - /// sequences in the string. - /// - /// \author Balazs Dezso - class QuotedStringReader { - public: - /// \brief The value type of reader. - /// - /// The value type of reader. - typedef std::string Value; - - /// \brief Constructor for the reader. - /// - /// Constructor for the reader. If the given parameter is true - /// the reader processes the escape sequences. - QuotedStringReader(bool _escaped = true) - : escaped(_escaped) {} - - /// \brief Reads a quoted string from the given stream. - /// - /// Reads a quoted string from the given stream. - void read(std::istream& is, std::string& value) const { - char c; - value.clear(); - is >> std::ws; - if (!is.get(c) || c != '\"') - throw DataFormatError("Quoted string format error"); - while (is.get(c) && c != '\"') { - if (escaped && c == '\\') { - value += readEscape(is); - } else { - value += c; - } - } - if (!is) throw DataFormatError("Quoted string format error"); - } - - private: - - static char readEscape(std::istream& is) { - char c; - switch (is.get(c), c) { - case '\\': - return '\\'; - case '\"': - return '\"'; - case '\'': - return '\''; - case '\?': - return '\?'; - case 'a': - return '\a'; - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - case 'v': - return '\v'; - case 'x': - { - int code; - if (!is.get(c) || !isHex(c)) - throw DataFormatError("Escape format error"); - else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c); - else code = code * 16 + valueHex(c); - return code; - } - default: - { - int code; - if (!isOct(c)) - throw DataFormatError("Escape format error"); - else if (code = valueOct(c), !is.get(c) || !isOct(c)) - is.putback(c); - else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) - is.putback(c); - else code = code * 8 + valueOct(c); - return code; - } - } - } - - static bool isOct(char c) { - return '0' <= c && c <='7'; - } - - static int valueOct(char c) { - return c - '0'; - } - - static bool isHex(char c) { - return ('0' <= c && c <= '9') || - ('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z'); - } - - static int valueHex(char c) { - if ('0' <= c && c <= '9') return c - '0'; - if ('a' <= c && c <= 'z') return c - 'a' + 10; - return c - 'A' + 10; - } - - bool escaped; - }; - - /// \ingroup item_io - /// \brief Reader for standard containers. - /// - /// Reader for back insertable standard containers. The representation - /// of the container is the values enumerated between an open and a - /// close parse. - /// - /// \author Balazs Dezso - template < - typename _Container, - typename _ItemReader = DefaultReader - > - class PushBackReader { - public: - typedef _Container Value; - typedef _ItemReader ItemReader; - - private: - - ItemReader item_reader; - - public: - - /// \brief Reads the values into the container from the given stream. - /// - /// Reads the values into the container from the given stream. - void read(std::istream& is, Value& value) const { - char c; - if (!(is >> c) || c != '(') - throw DataFormatError("PushBackReader format error"); - while (is >> c && c != ')') { - is.putback(c); - typename ItemReader::Value item; - item_reader.read(is, item); - value.push_back(item); - } - if (!is) throw DataFormatError("PushBackReader format error"); - is.putback(c); - } - - }; - - /// \ingroup item_io - /// - /// \brief Reader for standard containers. - /// - /// Reader for insertable standard containers. The representation - /// of the container is the values enumerated between an open and a - /// close parse. - /// - /// \author Balazs Dezso - template < - typename _Container, - typename _ItemReader = DefaultReader - > - class InsertReader { - public: - typedef _Container Value; - typedef _ItemReader ItemReader; - - private: - - ItemReader item_reader; - - public: - - /// \brief Reads the values into the container from the given stream. - /// - /// Reads the values into the container from the given stream. - void read(std::istream& is, Value& value) const { - char c; - if (!(is >> c) || c != '(') - throw DataFormatError("InsertReader format error"); - while (is >> c && c != ')') { - is.putback(c); - typename ItemReader::Value item; - item_reader.read(is, item); - value.insert(item); - } - if (!is) throw DataFormatError("PushBackReader format error"); - is.putback(c); - } - - }; - - /// \ingroup item_io - /// \brief Reader for parsed string. - /// - /// Reader for parsed strings. You can give the open and close - /// parse characters. - /// - /// \author Balazs Dezso - class ParsedStringReader { - public: - typedef std::string Value; - - /// \brief Constructor. - /// - /// Constructor for ParsedStringReader. You can give as parameter - /// the open and close parse characters. - ParsedStringReader(char _open = '(', char _close = ')') - : open(_open), close(_close) {} - - - /// \brief Reads the parsed string from the given stream. - /// - /// Reads the parsed string from the given stream. - void read(std::istream& is, Value& value) const { - char c; - if (!(is >> c) || c != open) { - throw DataFormatError("ParsedStringReader format error"); - } - value += c; - int counter = 1; - while (counter > 0 && is >> c) { - if (c == close) { - --counter; - } else if (c == open) { - ++counter; - } - value += c; - } - if (!is) { - throw DataFormatError("ParsedStrinReader format error"); - } - } - - private: - char open, close; - - }; - - /// \ingroup item_io - /// \brief Reader for read the whole line. - /// - /// Reader for read the whole line. - /// - /// \author Balazs Dezso - class LineReader { - public: - typedef std::string Value; - - /// \brief Constructor. - /// - /// Constructor for the LineReader. If the given parameter is - /// true then the spaces before the first not space character are - /// skipped. - LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {} - - /// \brief Reads the line from the given stream. - /// - /// Reads the line from the given stream. - void read(std::istream& is, Value& value) { - if (skipSpaces) is >> std::ws; - if (!getline(is, value)) { - throw DataFormatError("LineReader forma error"); - } - } - private: - bool skipSpaces; - }; - - /// \ingroup item_io - /// - /// \brief The default item reader template class. - /// - /// The default item reader template class. If some section reader - /// needs to read a value from a stream it will give the default way for it. - /// - /// \author Balazs Dezso - template - class DefaultReader { - public: - /// The value type. - typedef _Value Value; - /// \brief Reads a value from the given stream. - /// - /// Reads a value from the given stream. - void read(std::istream& is, Value& value) const { - if (!(is >> value)) - throw DataFormatError("DefaultReader format error"); - } - }; - - template <> - class DefaultReader { - public: - typedef std::string Value; - - void read(std::istream& is, Value& value) const { - char c; - if (!(is >> std::ws >> c)) return; - is.putback(c); - switch (c) { - case '\"': - QuotedStringReader().read(is, value); - break; - case '(': - ParsedStringReader().read(is, value); - break; - default: - is >> value; - break; - } - } - - }; - - template - class DefaultReader > - : public PushBackReader > {}; - - template - class DefaultReader > - : public PushBackReader > {}; - - template - class DefaultReader > - : public PushBackReader > {}; - - template - class DefaultReader > - : public InsertReader > {}; - - template - class DefaultReader > - : public InsertReader > {}; - - /// \ingroup item_io - /// - /// \brief The default item reader for skipping a value in the stream. - /// - /// The default item reader for skipping a value in the stream. - /// - /// \author Balazs Dezso - class DefaultSkipper : public DefaultReader {}; - - /// \ingroup item_io - /// \brief Standard ReaderTraits for the GraphReader class. - /// - /// Standard ReaderTraits for the GraphReader class. - /// It defines standard reading method for all type of value. - /// \author Balazs Dezso - struct DefaultReaderTraits { - - template - struct Reader : DefaultReader<_Value> {}; - - typedef DefaultSkipper Skipper; - - }; - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/item_writer.h --- a/src/lemon/bits/item_writer.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,219 +0,0 @@ -/* -*- C++ -*- - * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -/// \ingroup item_io -/// \file -/// \brief Item writer bits for lemon output. - -#ifndef LEMON_BITS_ITEM_WRITER_H -#define LEMON_BITS_ITEM_WRITER_H - -#include -#include - -#include -#include -#include -#include - -namespace lemon { - - template - class DefaultWriter; - - /// \ingroup item_io - /// \brief Writer class for quoted strings. - /// - /// Writer class for quoted strings. It can process the escape - /// sequences in the string. - /// \author Balazs Dezso - class QuotedStringWriter { - public: - typedef std::string Value; - - /// \brief Constructor for the writer. - /// - /// Constructor for the writer. If the given parameter is true - /// the writer creates escape sequences from special characters. - QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {} - - /// \brief Writes a quoted string to the given stream. - /// - /// Writes a quoted string to the given stream. - void write(std::ostream& os, const std::string& value) { - os << "\""; - if (escaped) { - std::ostringstream ls; - for (int i = 0; i < (int)value.size(); ++i) { - writeEscape(ls, value[i]); - } - os << ls.str(); - } else { - os << value; - } - os << "\""; - } - - private: - - static void writeEscape(std::ostream& os, char c) { - switch (c) { - case '\\': - os << "\\\\"; - return; - case '\"': - os << "\\\""; - return; - case '\'': - os << "\\\'"; - return; - case '\?': - os << "\\\?"; - return; - case '\a': - os << "\\a"; - return; - case '\b': - os << "\\b"; - return; - case '\f': - os << "\\f"; - return; - case '\r': - os << "\\r"; - return; - case '\n': - os << "\\n"; - return; - case '\t': - os << "\\t"; - return; - case '\v': - os << "\\v"; - return; - default: - if (c < 0x20) { - os << '\\' << std::oct << (int)c; - } else { - os << c; - } - return; - } - } - private: - bool escaped; - }; - - /// \ingroup item_io - /// - /// \brief Writer for standard containers. - /// - /// Writer for each iterable standard containers. The representation - /// of the container is the values enumerated between an open and a - /// close parse. - /// - /// \author Balazs Dezso - template < - typename _Container, - typename _ItemWriter = DefaultWriter - > - class IterableWriter { - public: - typedef _Container Value; - typedef _ItemWriter ItemWriter; - - private: - - ItemWriter item_writer; - - public: - - /// \brief Writes the values of the container to the given stream. - /// - /// Writes the values of the container to the given stream. - void write(std::ostream& os, const Value& value) const { - typename Value::const_iterator it; - os << '('; - for (it = value.begin(); it != value.end(); ++it) { - item_writer.write(os, *it); - os << ' '; - } - os << ')'; - } - - }; - - /// \ingroup item_io - /// - /// \brief The default item writer template class. - /// - /// The default item writer template class. If some section writer - /// needs to write a value to the stream it will give the default way for it. - /// - /// \author Balazs Dezso - template - class DefaultWriter { - public: - /// The value type. - typedef _Value Value; - /// \brief Writes the value to the given stream. - /// - /// Writes the value to the given stream. - void write(std::ostream& os, const Value& value) const { - os << value; - } - }; - - template <> - class DefaultWriter - : public QuotedStringWriter {}; - - template - class DefaultWriter > - : public IterableWriter > {}; - - template - class DefaultWriter > - : public IterableWriter > {}; - - template - class DefaultWriter > - : public IterableWriter > {}; - - template - class DefaultWriter > - : public IterableWriter > {}; - - template - class DefaultWriter > - : public IterableWriter > {}; - - /// \ingroup item_io - /// \brief Standard WriterTraits for the section writers. - /// - /// Standard WriterTraits for the section writers. - /// It defines standard writing method for all type of value. - /// \author Balazs Dezso - struct DefaultWriterTraits { - - template - struct Writer : DefaultWriter<_Value> {}; - - }; - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/iterable_graph_extender.h --- a/src/lemon/bits/iterable_graph_extender.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,250 +0,0 @@ -// -*- c++ -*- -#ifndef LEMON_ITERABLE_GRAPH_EXTENDER_H -#define LEMON_ITERABLE_GRAPH_EXTENDER_H - -#include - -namespace lemon { - - template - class IterableGraphExtender : public _Base { - public: - - typedef _Base Parent; - typedef IterableGraphExtender<_Base> Graph; - - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - - - class NodeIt : public Node { - const Graph* graph; - public: - - NodeIt() {} - - NodeIt(Invalid i) : Node(i) { } - - explicit NodeIt(const Graph& _graph) : graph(&_graph) { - _graph.first(*static_cast(this)); - } - - NodeIt(const Graph& _graph, const Node& node) - : Node(node), graph(&_graph) {} - - NodeIt& operator++() { - graph->next(*this); - return *this; - } - - }; - - - class EdgeIt : public Edge { - const Graph* graph; - public: - - EdgeIt() { } - - EdgeIt(Invalid i) : Edge(i) { } - - explicit EdgeIt(const Graph& _graph) : graph(&_graph) { - _graph.first(*static_cast(this)); - } - - EdgeIt(const Graph& _graph, const Edge& e) : - Edge(e), graph(&_graph) { } - - EdgeIt& operator++() { - graph->next(*this); - return *this; - } - - }; - - - class OutEdgeIt : public Edge { - const Graph* graph; - public: - - OutEdgeIt() { } - - OutEdgeIt(Invalid i) : Edge(i) { } - - OutEdgeIt(const Graph& _graph, const Node& node) - : graph(&_graph) { - _graph.firstOut(*this, node); - } - - OutEdgeIt(const Graph& _graph, const Edge& edge) - : Edge(edge), graph(&_graph) {} - - OutEdgeIt& operator++() { - graph->nextOut(*this); - return *this; - } - - }; - - - class InEdgeIt : public Edge { - const Graph* graph; - public: - - InEdgeIt() { } - - InEdgeIt(Invalid i) : Edge(i) { } - - InEdgeIt(const Graph& _graph, const Node& node) - : graph(&_graph) { - _graph.firstIn(*this, node); - } - - InEdgeIt(const Graph& _graph, const Edge& edge) : - Edge(edge), graph(&_graph) {} - - InEdgeIt& operator++() { - graph->nextIn(*this); - return *this; - } - - }; - - /// Base node of the iterator - /// - /// Returns the base node (ie. the source in this case) of the iterator - /// - /// \todo Document in the concept! - Node baseNode(const OutEdgeIt &e) const { - return source(e); - } - /// Running node of the iterator - /// - /// Returns the running node (ie. the target in this case) of the - /// iterator - /// - /// \todo Document in the concept! - Node runningNode(const OutEdgeIt &e) const { - return target(e); - } - - /// Base node of the iterator - /// - /// Returns the base node (ie. the target in this case) of the iterator - /// - /// \todo Document in the concept! - Node baseNode(const InEdgeIt &e) const { - return target(e); - } - /// Running node of the iterator - /// - /// Returns the running node (ie. the source in this case) of the - /// iterator - /// - /// \todo Document in the concept! - Node runningNode(const InEdgeIt &e) const { - return source(e); - } - - using Parent::first; - - private: - - // /// \todo When (and if) we change the iterators concept to use operator*, - // /// then the following shadowed methods will become superfluous. - // /// But for now these are important safety measures. - - // void first(NodeIt &) const; - // void first(EdgeIt &) const; - // void first(OutEdgeIt &) const; - // void first(InEdgeIt &) const; - - }; - - - - - - - template - class IterableUndirGraphExtender : public IterableGraphExtender<_Base> { - public: - - typedef IterableGraphExtender<_Base> Parent; - typedef IterableUndirGraphExtender<_Base> Graph; - typedef typename Parent::Node Node; - - typedef typename Parent::UndirEdge UndirEdge; - - class UndirEdgeIt : public Parent::UndirEdge { - const Graph* graph; - public: - - UndirEdgeIt() { } - - UndirEdgeIt(Invalid i) : UndirEdge(i) { } - - explicit UndirEdgeIt(const Graph& _graph) : graph(&_graph) { - _graph.first(*static_cast(this)); - } - - UndirEdgeIt(const Graph& _graph, const UndirEdge& e) : - UndirEdge(e), graph(&_graph) { } - - UndirEdgeIt& operator++() { - graph->next(*this); - return *this; - } - - }; - - class IncEdgeIt : public Parent::UndirEdge { - const Graph* graph; - bool forward; - friend class IterableUndirGraphExtender; - template - friend class UndirGraphExtender; - public: - - IncEdgeIt() { } - - IncEdgeIt(Invalid i) : UndirEdge(i), forward(false) { } - - IncEdgeIt(const Graph& _graph, const Node &n) - : graph(&_graph) - { - _graph._dirFirstOut(*this, n); - } - - IncEdgeIt(const Graph& _graph, const UndirEdge &ue, const Node &n) - : graph(&_graph), UndirEdge(ue) - { - forward = (_graph.source(ue) == n); - } - - IncEdgeIt& operator++() { - graph->_dirNextOut(*this); - return *this; - } - }; - - using Parent::baseNode; - using Parent::runningNode; - - /// Base node of the iterator - /// - /// Returns the base node of the iterator - Node baseNode(const IncEdgeIt &e) const { - return _dirSource(e); - } - /// Running node of the iterator - /// - /// Returns the running node of the iterator - Node runningNode(const IncEdgeIt &e) const { - return _dirTarget(e); - } - - }; -} - -#endif // LEMON_GRAPH_EXTENDER_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/map_iterator.h --- a/src/lemon/bits/map_iterator.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,855 +0,0 @@ -/* -*- C++ -*- - * src/lemon/map_iterator.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_MAP_ITERATOR_H -#define LEMON_MAP_ITERATOR_H - -#include - -#include -#include - -///\ingroup graphmaps -///\file -///\brief Iterators on the maps. - -namespace lemon { - - /// \addtogroup graphmaps - /// @{ - - /** The base class all of the map iterators. - * The class defines the typedefs of the iterators, - * simple step functions and equality operators. - */ - - template < - typename _Graph, - typename _Item> - class MapIteratorBase { - - protected: - - /// The key type of the iterator. - typedef typename ItemSetTraits<_Graph, _Item>::ItemIt ItemIt; - - ItemIt it; - - /// Default constructor. - MapIteratorBase() {} - - /// ItemIt initialized MapIteratorBase constructor. - MapIteratorBase(const ItemIt _it) : it(_it) {} - - public: - - /// Stepping forward in the map. - void increment() { - ++it; - } - - /// The equality operator of the map. - bool operator==(const MapIteratorBase& _it) const { - return _it.it == it; - } - - /// The not-equality operator of the map. - bool operator!=(const MapIteratorBase& _it) const { - return !(*this == _it); - } - }; - - - template < - typename _Graph, - typename _Item, - typename _Map> - class MapConstIterator; - - /** Compatible iterator with the stl maps' iterators. - * It iterates on pairs of a key and a value. - */ - template < - typename _Graph, - typename _Item, - typename _Map> - class MapIterator : public MapIteratorBase<_Graph, _Item> { - - friend class MapConstIterator<_Graph, _Item, _Map>; - - - public: - - /// The iterator base class. - typedef MapIteratorBase<_Graph, _Item> Parent; - - typedef _Item Item; - typedef _Map Map; - typedef _Graph Graph; - - protected: - - typedef typename Parent::ItemIt ItemIt; - - typedef typename ReferenceMapTraits<_Map>::Value MapValue; - typedef typename ReferenceMapTraits<_Map>::Reference MapReference; - - public: - - /// The value type of the iterator. - typedef extended_pair Value; - - /// The reference type of the iterator. - typedef extended_pair Reference; - - /// Default constructor. - MapIterator() {} - - /// Constructor to initalize the iterators returned - /// by the begin() and end(). - MapIterator(Map& _map, const ItemIt& _it) - : Parent(_it), map(&_map) {} - - /// Dereference operator for the iterator. - Reference operator*() { - return Reference(Parent::it, (*map)[Parent::it]); - } - - /// The pointer type of the iterator. - class Pointer { - friend class MapIterator; - protected: - Reference data; - Pointer(const Item& item, MapReference val) - : data(item, val) {} - public: - Reference* operator->() {return &data;} - }; - - /// Arrow operator for the iterator. - Pointer operator->() { - return Pointer(Parent::it, (*map)[Parent::it]); - } - - /// The pre increment operator of the iterator. - MapIterator& operator++() { - Parent::increment(); - return *this; - } - - /// The post increment operator of the iterator. - MapIterator operator++(int) { - MapIterator tmp(*this); - Parent::increment(); - return tmp; - } - - protected: - - Map* map; - - public: - // STL compatibility typedefs. - typedef std::forward_iterator_tag iterator_category; - typedef int difference_type; - typedef Value value_type; - typedef Reference reference; - typedef Pointer pointer; - }; - - /** Compatible iterator with the stl maps' iterators. - * It iterates on pairs of a key and a value. - */ - template < - typename _Graph, - typename _Item, - typename _Map> - class MapConstIterator : public MapIteratorBase<_Graph, _Item> { - - public: - - /// The iterator base class. - typedef MapIteratorBase<_Graph, _Item> Parent; - - typedef _Graph Graph; - typedef _Item Item; - typedef _Map Map; - - protected: - - typedef typename Parent::ItemIt ItemIt; - - typedef typename ReferenceMapTraits<_Map>::Value MapValue; - typedef typename ReferenceMapTraits<_Map>::ConstReference - MapReference; - - public: - - /// The value type of the iterator. - typedef extended_pair Value; - - /// The reference type of the iterator. - typedef extended_pair Reference; - - /// Default constructor. - MapConstIterator() {} - - /// Constructor to initalize the iterators returned - /// by the begin() and end(). - MapConstIterator(const Map& _map, const ItemIt& _it) - : Parent(_it), map(&_map) {} - - /// Dereference operator for the iterator. - Reference operator*() { - return Reference(Parent::it, (*map)[Parent::it]); - } - - /// The pointer type of the iterator. - class Pointer { - friend class MapConstIterator; - protected: - Reference data; - Pointer(const Item& item, MapReference val) - : data(item, val) {} - public: - Reference* operator->() {return &data;} - }; - - /// Arrow operator for the iterator. - Pointer operator->() { - return Pointer(Parent::it, ((*map)[Parent::it])); - } - - /// The pre increment operator of the iterator. - MapConstIterator& operator++() { - Parent::increment(); - return *this; - } - - /// The post increment operator of the iterator. - MapConstIterator operator++(int) { - MapConstIterator tmp(*this); - Parent::increment(); - return tmp; - } - - protected: - const Map* map; - - public: - // STL compatibility typedefs. - typedef std::forward_iterator_tag iterator_category; - typedef int difference_type; - typedef Value value_type; - typedef Reference reference; - typedef Pointer pointer; - }; - - /** The class makes the ItemIt to an stl compatible iterator - * with dereferencing operator. - */ - template < - typename _Graph, - typename _Item> - class MapConstKeyIterator : public MapIteratorBase<_Graph, _Item> { - - public: - - /// The iterator base class. - typedef MapIteratorBase<_Graph, _Item> Parent; - - typedef _Graph Graph; - typedef _Item Item; - - protected: - /// The iterator to iterate on the keys. - typedef typename Parent::ItemIt ItemIt; - - public: - - typedef Item Value; - typedef const Item& Reference; - typedef const Item* Pointer; - - /// Default constructor. - MapConstKeyIterator() {} - - /// ItemIt initialized iterator. - MapConstKeyIterator(const ItemIt& pit) : Parent(pit) {} - - /// The pre increment operator of the iterator. - MapConstKeyIterator& operator++() { - Parent::increment(); - return *this; - } - - /// The post increment operator of the iterator. - MapConstKeyIterator operator++(int) { - MapConstKeyIterator tmp(*this); - Parent::increment(); - return tmp; - } - - /// The dereferencing operator of the iterator. - Item operator*() const { - return static_cast(Parent::it); - } - - public: - // STL compatibility typedefs. - typedef std::input_iterator_tag iterator_category; - typedef int difference_type; - typedef Value value_type; - typedef Reference reference; - typedef Pointer pointer; - }; - - template < - typename _Graph, - typename _Item, - typename _Map> - class MapConstValueIterator; - - /** MapValueIterator creates an stl compatible iterator - * for the values. - */ - template < - typename _Graph, - typename _Item, - typename _Map> - class MapValueIterator : public MapIteratorBase<_Graph, _Item> { - - friend class MapConstValueIterator<_Graph, _Item, _Map>; - - public: - - /// The iterator base class. - typedef MapIteratorBase<_Graph, _Item> Parent; - - typedef _Graph Graph; - typedef _Item Item; - typedef _Map Map; - - protected: - - /// The iterator to iterate on the keys. - typedef typename Parent::ItemIt ItemIt; - - /// The value type of the iterator. - typedef typename ReferenceMapTraits::Value MapValue; - /// The reference type of the iterator. - typedef typename ReferenceMapTraits::Reference MapReference; - /// The pointer type of the iterator. - typedef typename ReferenceMapTraits::Pointer MapPointer; - - public: - - typedef MapValue Value; - typedef MapReference Reference; - typedef MapPointer Pointer; - - /// Default constructor. - MapValueIterator() {} - - /// Map and ItemIt initialized iterator. - MapValueIterator(Map& _map, const ItemIt& _it) - : Parent(_it), map(&_map) {} - - - /// The pre increment operator of the iterator. - MapValueIterator& operator++() { - Parent::increment(); - return *this; - } - - /// The post increment operator of the iterator. - MapValueIterator operator++(int) { - MapValueIterator tmp(*this); - Parent::increment(); - return tmp; - } - - /// The dereferencing operator of the iterator. - Reference operator*() const { - return (*map)[Parent::it]; - } - - /// The arrow operator of the iterator. - Pointer operator->() const { - return &(operator*()); - } - - protected: - - Map* map; - - public: - // STL compatibility typedefs. - typedef std::forward_iterator_tag iterator_category; - typedef int difference_type; - typedef Value value_type; - typedef Reference reference; - typedef Pointer pointer; - }; - - /** MapValueIterator creates an stl compatible iterator - * for the values. - */ - template < - typename _Graph, - typename _Item, - typename _Map> - class MapConstValueIterator : public MapIteratorBase<_Graph, _Item> { - - public: - - /// The iterator base class. - typedef MapIteratorBase<_Graph, _Item> Parent; - - typedef _Graph Graph; - typedef _Item Item; - typedef _Map Map; - - protected: - - /// The iterator to iterate on the keys. - typedef typename Parent::ItemIt ItemIt; - - /// The value type of the iterator. - typedef typename ReferenceMapTraits::Value MapValue; - /// The reference type of the iterator. - typedef typename ReferenceMapTraits::ConstReference MapReference; - /// The pointer type of the iterator. - typedef typename ReferenceMapTraits::ConstPointer MapPointer; - - public: - - typedef MapValue Value; - typedef MapReference Reference; - typedef MapPointer Pointer; - - /// Default constructor. - MapConstValueIterator() {} - - /// Map and ItemIt initialized iterator. - MapConstValueIterator(const Map& _map, const ItemIt& _it) - : Parent(_it), map(&_map) {} - - - /// The pre increment operator of the iterator. - MapConstValueIterator& operator++() { - Parent::increment(); - return *this; - } - - /// The post increment operator of the iterator. - MapConstValueIterator operator++(int) { - MapConstValueIterator tmp(*this); - Parent::increment(); - return tmp; - } - - /// The dereferencing operator of the iterator. - Reference operator*() const { - return (*map)[Parent::it]; - } - - /// The arrow operator of the iterator. - Pointer operator->() const { - return &(operator*()); - } - - protected: - - const Map* map; - - public: - // STL compatibility typedefs. - typedef std::forward_iterator_tag iterator_category; - typedef int difference_type; - typedef Value value_type; - typedef Reference reference; - typedef Pointer pointer; - }; - - - /** This class makes from a map an iteratable set - * which contains all the keys of the map. - */ - template - class MapConstKeySet { - - public: - - typedef _Graph Graph; - /// The key type of the iterator. - typedef _Item Item; - /// The iterator to iterate on the keys. - - protected: - - typedef typename ItemSetTraits<_Graph, _Item>::ItemIt ItemIt; - - public: - - /// The map initialized const key set. - MapConstKeySet(const Graph& _graph) : graph(&_graph) {} - - /// The const iterator of the set. - typedef MapConstKeyIterator<_Graph, _Item> ConstIterator; - - typedef typename ConstIterator::Value Value; - /// The reference type of the iterator. - typedef typename ConstIterator::Reference ConstReference; - /// The pointer type of the iterator. - typedef typename ConstIterator::Pointer ConstPointer; - - /// It gives back the const iterator pointed to the first element. - ConstIterator begin() const { - return ConstIterator(ItemIt(*graph)); - } - - /// It gives back the const iterator pointed to the first ivalid element. - ConstIterator end() const { - return ConstIterator(ItemIt(INVALID)); - } - - protected: - - const Graph* graph; - - public: - // STL compatibility typedefs. - typedef Value value_type; - typedef ConstIterator const_iterator; - typedef ConstReference const_reference; - typedef ConstPointer const_pointer; - typedef int difference_type; - }; - - /** This class makes from a map an iteratable set - * which contains all the values of the map. - * The values cannot be modified. - */ - template - class MapConstValueSet { - - public: - - typedef _Graph Graph; - typedef _Item Item; - typedef _Map Map; - - protected: - - /// The iterator to iterate on the keys. - typedef typename ItemSetTraits::ItemIt ItemIt; - - public: - - /// The map initialized const value set. - MapConstValueSet(const Graph& _graph, const Map& _map) - : graph(&_graph), map(&_map) {} - - /// The const iterator of the set. - typedef MapConstValueIterator<_Graph, _Item, _Map> ConstIterator; - - typedef typename ConstIterator::Value Value; - typedef typename ConstIterator::Reference ConstReference; - typedef typename ConstIterator::Pointer ConstPointer; - - /// It gives back the const iterator pointed to the first element. - ConstIterator begin() const { - return ConstIterator(*map, ItemIt(*graph)); - } - - /// It gives back the const iterator pointed to the first invalid element. - ConstIterator end() const { - return ConstIterator(*map, ItemIt(INVALID)); - } - - protected: - - const Map* map; - const Graph * graph; - - public: - // STL compatibility typedefs. - typedef Value value_type; - typedef ConstIterator const_iterator; - typedef ConstReference const_reference; - typedef ConstPointer const_pointer; - typedef int difference_type; - }; - - - /** This class makes from a map an iteratable set - * which contains all the values of the map. - * The values can be modified. - */ - template - class MapValueSet { - - public: - - typedef _Graph Graph; - typedef _Item Item; - typedef _Map Map; - - protected: - - /// The iterator to iterate on the keys. - typedef typename ItemSetTraits::ItemIt ItemIt; - - public: - - /// The map initialized const value set. - MapValueSet(const Graph& _graph, Map& _map) - : map(&_map), graph(&_graph) {} - - /// The const iterator of the set. - typedef MapValueIterator<_Graph, _Item, _Map> Iterator; - /// The const iterator of the set. - typedef MapConstValueIterator<_Graph, _Item, _Map> ConstIterator; - - typedef typename ConstIterator::Value Value; - typedef typename Iterator::Reference Reference; - typedef typename Iterator::Pointer Pointer; - typedef typename ConstIterator::Reference ConstReference; - typedef typename ConstIterator::Pointer ConstPointer; - - /// It gives back the const iterator pointed to the first element. - ConstIterator begin() const { - return ConstIterator(*map, ItemIt(*graph)); - } - - /// It gives back the const iterator pointed to the first invalid element. - ConstIterator end() const { - return ConstIterator(*map, ItemIt(INVALID)); - } - - /// It gives back the iterator pointed to the first element. - Iterator begin() { - return Iterator(*map, ItemIt(*graph)); - } - - /// It gives back the iterator pointed to the first invalid element. - Iterator end() { - return Iterator(*map, ItemIt(INVALID)); - } - - protected: - - Map* map; - const Graph * graph; - - public: - // STL compatibility typedefs. - typedef Value value_type; - typedef Iterator iterator; - typedef ConstIterator const_iterator; - typedef Reference reference; - typedef ConstReference const_reference; - typedef Pointer pointer; - typedef ConstPointer const_pointer; - typedef int difference_type; - - }; - - /** This class makes from a map an iteratable set - * which contains all the values of the map. - * The values can be modified. - */ - template < - typename _Graph, - typename _Item, - typename _Map - > - class MapSet { - public: - - typedef _Graph Graph; - typedef _Item Item; - typedef _Map Map; - - protected: - - typedef typename ItemSetTraits<_Graph, _Item>::ItemIt ItemIt; - - public: - - /// The map initialized value set. - MapSet(const Graph& _graph, Map& _map) : graph(&_graph), map(&_map) {} - - /// The const iterator of the set. - typedef MapIterator<_Graph, _Item, _Map> Iterator; - typedef MapConstIterator<_Graph, _Item, _Map> ConstIterator; - - typedef typename ConstIterator::Value Value; - typedef typename Iterator::Reference Reference; - typedef typename Iterator::Pointer Pointer; - typedef typename ConstIterator::Reference ConstReference; - typedef typename ConstIterator::Pointer ConstPointer; - - - /// It gives back the const iterator pointed to the first element. - ConstIterator begin() const { - return ConstIterator(*map, ItemIt(*graph)); - } - - /// It gives back the const iterator pointed to the first invalid element. - ConstIterator end() const { - return ConstIterator(*map, ItemIt(INVALID)); - } - - /// The iterator of the set. - - /// It gives back the iterator pointed to the first element. - Iterator begin() { - return Iterator(*map, ItemIt(*graph)); - } - - /// It gives back the iterator pointed to the first invalid element. - Iterator end() { - return Iterator(*map, ItemIt(INVALID)); - } - - protected: - - const Graph* graph; - Map* map; - - public: - // STL compatibility typedefs. - typedef Value value_type; - typedef Iterator iterator; - typedef ConstIterator const_iterator; - typedef Reference reference; - typedef ConstReference const_reference; - typedef Pointer pointer; - typedef ConstPointer const_pointer; - typedef int difference_type; - - }; - - template < - typename _Graph, - typename _Item, - typename _Map - > - class ConstMapSet { - - typedef _Graph Graph; - typedef _Map Map; - - const Graph* graph; - const Map* map; - - public: - - typedef typename ItemSetTraits<_Graph, _Item>::ItemIt ItemIt; - - - /// The map initialized value set. - ConstMapSet(const Graph& _graph, const Map& _map) - : graph(&_graph), map(&_map) {} - - /// The const iterator of the set. - typedef MapConstIterator<_Graph, _Item, _Map> ConstIterator; - - typedef typename ConstIterator::Value Value; - typedef typename ConstIterator::Reference ConstReference; - typedef typename ConstIterator::Pointer ConstPointer; - - - /// It gives back the const iterator pointed to the first element. - ConstIterator begin() const { - return ConstIterator(*map, ItemIt(*graph)); - } - - /// It gives back the const iterator pointed to the first invalid element. - ConstIterator end() const { - return ConstIterator(*map, ItemIt(INVALID)); - } - - public: - // STL compatibility typedefs. - typedef Value value_type; - typedef ConstIterator const_iterator; - typedef ConstReference const_reference; - typedef ConstPointer const_pointer; - typedef int difference_type; - - }; - - template - class IterableMapExtender : public _Map { - public: - - typedef _Map Parent; - typedef Parent Map; - typedef typename Map::Graph Graph; - typedef typename Map::Key Item; - typedef typename Map::Value Value; - - typedef MapSet MapSet; - - IterableMapExtender() : Parent() {} - - IterableMapExtender(const Graph& graph) : Parent(graph) {} - - IterableMapExtender(const Graph& graph, const Value& value) - : Parent(graph, value) {} - - MapSet mapSet() { - return MapSet(*Parent::getGraph(), *this); - } - - typedef ConstMapSet ConstMapSet; - - ConstMapSet mapSet() const { - return ConstMapSet(*Parent::getGraph(), *this); - } - - typedef MapConstKeySet ConstKeySet; - - ConstKeySet keySet() const { - return ConstKeySet(*Parent::getGraph()); - } - - typedef MapValueSet ValueSet; - - ValueSet valueSet() { - return ValueSet(*Parent::getGraph(), *this); - } - - typedef MapConstValueSet ConstValueSet; - - ConstValueSet valueSet() const { - return ConstValueSet(*Parent::getGraph(), *this); - } - - }; - - /// @} - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/undir_graph_extender.h --- a/src/lemon/bits/undir_graph_extender.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,278 +0,0 @@ -/* -*- C++ -*- - * - * src/lemon/undir_graph_extender.h - Part of LEMON, a generic C++ - * optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi - * Kutatocsoport (Egervary Research Group on Combinatorial Optimization, - * EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_UNDIR_GRAPH_EXTENDER_H -#define LEMON_UNDIR_GRAPH_EXTENDER_H - -#include - -namespace lemon { - - template - class UndirGraphExtender : public _Base { - typedef _Base Parent; - typedef UndirGraphExtender Graph; - - public: - - typedef typename Parent::Edge UndirEdge; - typedef typename Parent::Node Node; - - class Edge : public UndirEdge { - friend class UndirGraphExtender; - - protected: - // FIXME: Marci use opposite logic in his graph adaptors. It would - // be reasonable to syncronize... - bool forward; - - public: - Edge() {} - - /// \brief Directed edge from undirected edge and a direction. - /// - /// This constructor is not a part of the concept interface of - /// undirected graph, so please avoid using it if possible! - Edge(const UndirEdge &ue, bool _forward) : - UndirEdge(ue), forward(_forward) {} - - /// \brief Directed edge from undirected edge and a source node. - /// - /// Constructs a directed edge from undirected edge and a source node. - /// - /// \note You have to specify the graph for this constructor. - Edge(const Graph &g, const UndirEdge &ue, const Node &n) : - UndirEdge(ue) { forward = (g.source(ue) == n); } - - /// Invalid edge constructor - Edge(Invalid i) : UndirEdge(i), forward(true) {} - - bool operator==(const Edge &that) const { - return forward==that.forward && UndirEdge(*this)==UndirEdge(that); - } - bool operator!=(const Edge &that) const { - return forward!=that.forward || UndirEdge(*this)!=UndirEdge(that); - } - bool operator<(const Edge &that) const { - return forward - Node _dirSource(const E &e) const { - return e.forward ? Parent::source(e) : Parent::target(e); - } - - template - Node _dirTarget(const E &e) const { - return e.forward ? Parent::target(e) : Parent::source(e); - } - - public: - /// \todo Shouldn't the "source" of an undirected edge be called "aNode" - /// or something??? - using Parent::source; - - /// Source of the given Edge. - Node source(const Edge &e) const { - return _dirSource(e); - } - - /// \todo Shouldn't the "target" of an undirected edge be called "bNode" - /// or something??? - using Parent::target; - - /// Target of the given Edge. - Node target(const Edge &e) const { - return _dirTarget(e); - } - - /// Returns whether the given directed edge is same orientation as the - /// corresponding undirected edge. - /// - /// \todo reference to the corresponding point of the undirected graph - /// concept. "What does the direction of an undirected edge mean?" - bool forward(const Edge &e) const { return e.forward; } - - Node oppositeNode(const Node &n, const UndirEdge &e) const { - if( n == Parent::source(e)) - return Parent::target(e); - else if( n == Parent::target(e)) - return Parent::source(e); - else - return INVALID; - } - - /// Directed edge from an undirected edge and a source node. - /// - /// Returns a (directed) Edge corresponding to the specified UndirEdge - /// and source Node. - /// - ///\todo Do we need this? - /// - ///\todo Better name... - Edge edgeWithSource(const UndirEdge &ue, const Node &s) const { - return Edge(*this, ue, s); - } - - using Parent::first; - void first(Edge &e) const { - Parent::first(e); - e.forward=true; - } - - using Parent::next; - void next(Edge &e) const { - if( e.forward ) { - e.forward = false; - } - else { - Parent::next(e); - e.forward = true; - } - } - - - protected: - - template - void _dirFirstOut(E &e, const Node &n) const { - Parent::firstIn(e,n); - if( UndirEdge(e) != INVALID ) { - e.forward = false; - } - else { - Parent::firstOut(e,n); - e.forward = true; - } - } - template - void _dirFirstIn(E &e, const Node &n) const { - Parent::firstOut(e,n); - if( UndirEdge(e) != INVALID ) { - e.forward = false; - } - else { - Parent::firstIn(e,n); - e.forward = true; - } - } - - template - void _dirNextOut(E &e) const { - if( ! e.forward ) { - Node n = Parent::target(e); - Parent::nextIn(e); - if( UndirEdge(e) == INVALID ) { - Parent::firstOut(e, n); - e.forward = true; - } - } - else { - Parent::nextOut(e); - } - } - template - void _dirNextIn(E &e) const { - if( ! e.forward ) { - Node n = Parent::source(e); - Parent::nextOut(e); - if( UndirEdge(e) == INVALID ) { - Parent::firstIn(e, n); - e.forward = true; - } - } - else { - Parent::nextIn(e); - } - } - - public: - - void firstOut(Edge &e, const Node &n) const { - _dirFirstOut(e, n); - } - void firstIn(Edge &e, const Node &n) const { - _dirFirstIn(e, n); - } - - void nextOut(Edge &e) const { - _dirNextOut(e); - } - void nextIn(Edge &e) const { - _dirNextIn(e); - } - - // Miscellaneous stuff: - - /// \todo these methods (id, maxEdgeId) should be moved into separate - /// Extender - - // using Parent::id; - // Using "using" is not a good idea, cause it could be that there is - // no "id" in Parent... - - int id(const Node &n) const { - return Parent::id(n); - } - - int id(const UndirEdge &e) const { - return Parent::id(e); - } - - int id(const Edge &e) const { - return 2 * Parent::id(e) + int(e.forward); - } - - - int maxId(Node) const { - return Parent::maxId(Node()); - } - - int maxId(Edge) const { - return 2 * Parent::maxId(typename Parent::Edge()) + 1; - } - int maxId(UndirEdge) const { - return Parent::maxId(typename Parent::Edge()); - } - - - int edgeNum() const { - return 2 * Parent::edgeNum(); - } - int undirEdgeNum() const { - return Parent::edgeNum(); - } - - }; - -} - -#endif // LEMON_UNDIR_GRAPH_EXTENDER_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/bits/vector_map.h --- a/src/lemon/bits/vector_map.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,288 +0,0 @@ -/* -*- C++ -*- - * src/lemon/vector_map.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_VECTOR_MAP_H -#define LEMON_VECTOR_MAP_H - -#include -#include - -#include -#include -#include - -///\ingroup graphmaps -///\file -///\brief Vector based graph maps. - -namespace lemon { - - /// \addtogroup graphmaps - /// @{ - - /// The VectorMap template class is graph map structure what - /// automatically updates the map when a key is added to or erased from - /// the map. This map factory uses the allocators to implement - /// the container functionality. This map factory - /// uses the std::vector to implement the container function. - /// - /// \param Registry The AlterationNotifier that will notify this map. - /// \param IdMap The IdMap type of the graph items. - /// \param Value The value type of the map. - /// - /// \author Balazs Dezso - - - template < - typename _Graph, - typename _Item, - typename _Value - > - class VectorMap : public AlterationNotifier<_Item>::ObserverBase { - public: - - /// The graph type of the map. - typedef _Graph Graph; - /// The key type of the map. - typedef _Item Key; - /// The id map type of the map. - typedef AlterationNotifier<_Item> Registry; - /// The value type of the map. - typedef _Value Value; - - /// The map type. - typedef VectorMap Map; - /// The base class of the map. - typedef typename Registry::ObserverBase Parent; - - private: - - /// The container type of the map. - typedef std::vector Container; - - public: - - /// The reference type of the map; - typedef typename Container::reference Reference; - /// The pointer type of the map; - typedef typename Container::pointer Pointer; - - /// The const value type of the map. - typedef const Value ConstValue; - /// The const reference type of the map; - typedef typename Container::const_reference ConstReference; - /// The pointer type of the map; - typedef typename Container::const_pointer ConstPointer; - - typedef True FullTypeTag; - - /// Constructor to attach the new map into the registry. - - /// It construates a map and attachs it into the registry. - /// It adds all the items of the graph to the map. - - VectorMap(const Graph& _g) : graph(&_g) { - attach(_g.getNotifier(_Item())); - build(); - } - - /// Constructor uses given value to initialize the map. - - /// It construates a map uses a given value to initialize the map. - /// It adds all the items of the graph to the map. - - VectorMap(const Graph& _g, const Value& _v) : graph(&_g) { - attach(_g.getNotifier(_Item())); - container.resize(graph->maxId(_Item()) + 1, _v); - } - - VectorMap(const VectorMap& _copy) - : Parent(), graph(_copy.getGraph()) { - if (_copy.attached()) { - attach(*_copy.getRegistry()); - container = _copy.container; - } - } - - using Parent::attach; - using Parent::detach; - using Parent::attached; - - /** Assign operator to copy a map of the same map type. - */ - VectorMap& operator=(const VectorMap& copy) { - if (© == this) return *this; - - if (graph != copy.graph) { - if (attached()) { - detach(); - } - if (copy.attached()) { - attach(*copy.getRegistry()); - } - } - container = copy.container; - - return *this; - } - - - virtual ~VectorMap() { - if (attached()) { - detach(); - } - } - - const Graph* getGraph() const { - return graph; - } - - /// The subcript operator. - - /// The subscript operator. The map can be subscripted by the - /// actual items of the graph. - - Reference operator[](const Key& key) { - return container[graph->id(key)]; - } - - /// The const subcript operator. - - /// The const subscript operator. The map can be subscripted by the - /// actual items of the graph. - - ConstReference operator[](const Key& key) const { - return container[graph->id(key)]; - } - - - /// The setter function of the map. - - /// It the same as operator[](key) = value expression. - /// - - void set(const Key& key, const Value& value) { - (*this)[key] = value; - } - - /// Adds a new key to the map. - - /// It adds a new key to the map. It called by the observer registry - /// and it overrides the add() member function of the observer base. - - void add(const Key& key) { - int id = graph->id(key); - if (id >= (int)container.size()) { - container.resize(id + 1); - } - } - - /// Erases a key from the map. - - /// Erase a key from the map. It called by the observer registry - /// and it overrides the erase() member function of the observer base. - void erase(const Key&) {} - - /// Buildes the map. - - /// It buildes the map. It called by the observer registry - /// and it overrides the build() member function of the observer base. - - void build() { - container.resize(graph->maxId(_Item()) + 1); - } - - /// Clear the map. - - /// It erase all items from the map. It called by the observer registry - /// and it overrides the clear() member function of the observer base. - void clear() { - container.clear(); - } - - private: - - Container container; - const Graph *graph; - - }; - - - template - class VectorMappableGraphExtender : public _Base { - public: - - typedef VectorMappableGraphExtender<_Base> Graph; - typedef _Base Parent; - - typedef typename Parent::Node Node; - typedef typename Parent::NodeIt NodeIt; - typedef typename Parent::NodeIdMap NodeIdMap; - typedef typename Parent::NodeNotifier NodeObserverRegistry; - - typedef typename Parent::Edge Edge; - typedef typename Parent::EdgeIt EdgeIt; - typedef typename Parent::EdgeIdMap EdgeIdMap; - typedef typename Parent::EdgeNotifier EdgeObserverRegistry; - - - template - class NodeMap : - public IterableMapExtender > { - public: - typedef VectorMappableGraphExtender<_Base> Graph; - - typedef typename Graph::Node Node; - - typedef IterableMapExtender > Parent; - - //typedef typename Parent::Graph Graph; - typedef typename Parent::Value Value; - - NodeMap(const Graph& g) - : Parent(g) {} - NodeMap(const Graph& g, const Value& v) - : Parent(g, v) {} - - }; - - template - class EdgeMap - : public IterableMapExtender > { - public: - typedef VectorMappableGraphExtender<_Base> Graph; - - typedef typename Graph::Edge Edge; - - typedef IterableMapExtender > Parent; - - //typedef typename Parent::Graph Graph; - typedef typename Parent::Value Value; - - EdgeMap(const Graph& g) - : Parent(g) {} - EdgeMap(const Graph& g, const Value& v) - : Parent(g, v) {} - - }; - - }; - - /// @} - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/concept/graph.h --- a/src/lemon/concept/graph.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,578 +0,0 @@ -/* -*- C++ -*- - * src/lemon/concept/graph.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_CONCEPT_GRAPH_H -#define LEMON_CONCEPT_GRAPH_H - -///\ingroup graph_concepts -///\file -///\brief Declaration of Graph. - -#include -#include -#include -#include - -namespace lemon { - namespace concept { - - - /// \addtogroup graph_concepts - /// @{ - - /**************** The full-featured graph concepts ****************/ - - - /// \brief Modular static graph class. - /// - /// It should be the same as the \c StaticGraph class. - class _StaticGraph - : virtual public BaseGraphComponent, - public IterableGraphComponent, public MappableGraphComponent { - public: - typedef BaseGraphComponent::Node Node; - typedef BaseGraphComponent::Edge Edge; - - template - struct Constraints { - void constraints() { - checkConcept(); - checkConcept(); - } - }; - }; - - /// \brief Modular extendable graph class. - /// - /// It should be the same as the \c ExtendableGraph class. - class _ExtendableGraph - : virtual public BaseGraphComponent, public _StaticGraph, - public ExtendableGraphComponent, public ClearableGraphComponent { - public: - typedef BaseGraphComponent::Node Node; - typedef BaseGraphComponent::Edge Edge; - - template - struct Constraints { - void constraints() { - checkConcept<_StaticGraph, _Graph >(); - checkConcept(); - checkConcept(); - } - }; - }; - - /// \brief Modular erasable graph class. - /// - /// It should be the same as the \c ErasableGraph class. - class _ErasableGraph - : virtual public BaseGraphComponent, public _ExtendableGraph, - public ErasableGraphComponent { - public: - typedef BaseGraphComponent::Node Node; - typedef BaseGraphComponent::Edge Edge; - - template - struct Constraints { - void constraints() { - checkConcept<_ExtendableGraph, _Graph >(); - checkConcept(); - } - }; - }; - - /// An empty static graph class. - - /// This class provides all the common features of a graph structure, - /// however completely without implementations and real data structures - /// behind the interface. - /// All graph algorithms should compile with this class, but it will not - /// run properly, of course. - /// - /// It can be used for checking the interface compatibility, - /// or it can serve as a skeleton of a new graph structure. - /// - /// Also, you will find here the full documentation of a certain graph - /// feature, the documentation of a real graph imlementation - /// like @ref ListGraph or - /// @ref SmartGraph will just refer to this structure. - /// - /// \todo A pages describing the concept of concept description would - /// be nice. - class StaticGraph - { - public: - /// Defalult constructor. - - /// Defalult constructor. - /// - StaticGraph() { } - ///Copy consructor. - -// ///\todo It is not clear, what we expect from a copy constructor. -// ///E.g. How to assign the nodes/edges to each other? What about maps? -// StaticGraph(const StaticGraph& g) { } - - /// The base type of node iterators, - /// or in other words, the trivial node iterator. - - /// This is the base type of each node iterator, - /// thus each kind of node iterator converts to this. - /// More precisely each kind of node iterator should be inherited - /// from the trivial node iterator. - class Node { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - Node() { } - /// Copy constructor. - - /// Copy constructor. - /// - Node(const Node&) { } - - /// Invalid constructor \& conversion. - - /// This constructor initializes the iterator to be invalid. - /// \sa Invalid for more details. - Node(Invalid) { } - /// Equality operator - - /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. - bool operator==(Node) const { return true; } - - /// Inequality operator - - /// \sa operator==(Node n) - /// - bool operator!=(Node) const { return true; } - - }; - - /// This iterator goes through each node. - - /// This iterator goes through each node. - /// Its usage is quite simple, for example you can count the number - /// of nodes in graph \c g of type \c Graph like this: - /// \code - /// int count=0; - /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count; - /// \endcode - class NodeIt : public Node { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - NodeIt() { } - /// Copy constructor. - - /// Copy constructor. - /// - NodeIt(const NodeIt& n) : Node(n) { } - /// Invalid constructor \& conversion. - - /// Initialize the iterator to be invalid. - /// \sa Invalid for more details. - NodeIt(Invalid) { } - /// Sets the iterator to the first node. - - /// Sets the iterator to the first node of \c g. - /// - NodeIt(const StaticGraph&) { } - /// Node -> NodeIt conversion. - - /// Sets the iterator to the node of \c g pointed by the trivial - /// iterator n. - /// This feature necessitates that each time we - /// iterate the edge-set, the iteration order is the same. - NodeIt(const StaticGraph& g, const Node& n) { } - /// Next node. - - /// Assign the iterator to the next node. - /// - NodeIt& operator++() { return *this; } - }; - - - /// The base type of the edge iterators. - - /// The base type of the edge iterators. - /// - class Edge { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - Edge() { } - /// Copy constructor. - - /// Copy constructor. - /// - Edge(const Edge&) { } - /// Initialize the iterator to be invalid. - - /// Initialize the iterator to be invalid. - /// - Edge(Invalid) { } - /// Equality operator - - /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. - bool operator==(Edge) const { return true; } - /// Inequality operator - - /// \sa operator==(Node n) - /// - bool operator!=(Edge) const { return true; } - }; - - /// This iterator goes trough the outgoing edges of a node. - - /// This iterator goes trough the \e outgoing edges of a certain node - /// of a graph. - /// Its usage is quite simple, for example you can count the number - /// of outgoing edges of a node \c n - /// in graph \c g of type \c Graph as follows. - /// \code - /// int count=0; - /// for (Graph::OutEdgeIt e(g, n); e!=INVALID; ++e) ++count; - /// \endcode - - class OutEdgeIt : public Edge { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - OutEdgeIt() { } - /// Copy constructor. - - /// Copy constructor. - /// - OutEdgeIt(const OutEdgeIt& e) : Edge(e) { } - /// Initialize the iterator to be invalid. - - /// Initialize the iterator to be invalid. - /// - OutEdgeIt(Invalid) { } - /// This constructor sets the iterator to the first outgoing edge. - - /// This constructor sets the iterator to the first outgoing edge of - /// the node. - ///@param n the node - ///@param g the graph - OutEdgeIt(const StaticGraph&, const Node&) { } - /// Edge -> OutEdgeIt conversion - - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the edge-set, the iteration order is the same. - OutEdgeIt(const StaticGraph& g, const Edge& e) { } - ///Next outgoing edge - - /// Assign the iterator to the next - /// outgoing edge of the corresponding node. - OutEdgeIt& operator++() { return *this; } - }; - - /// This iterator goes trough the incoming edges of a node. - - /// This iterator goes trough the \e incoming edges of a certain node - /// of a graph. - /// Its usage is quite simple, for example you can count the number - /// of outgoing edges of a node \c n - /// in graph \c g of type \c Graph as follows. - /// \code - /// int count=0; - /// for(Graph::InEdgeIt e(g, n); e!=INVALID; ++e) ++count; - /// \endcode - - class InEdgeIt : public Edge { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - InEdgeIt() { } - /// Copy constructor. - - /// Copy constructor. - /// - InEdgeIt(const InEdgeIt& e) : Edge(e) { } - /// Initialize the iterator to be invalid. - - /// Initialize the iterator to be invalid. - /// - InEdgeIt(Invalid) { } - /// This constructor sets the iterator to first incoming edge. - - /// This constructor set the iterator to the first incoming edge of - /// the node. - ///@param n the node - ///@param g the graph - InEdgeIt(const StaticGraph&, const Node&) { } - /// Edge -> InEdgeIt conversion - - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the edge-set, the iteration order is the same. - InEdgeIt(const StaticGraph&, const Edge&) { } - /// Next incoming edge - - /// Assign the iterator to the next inedge of the corresponding node. - /// - InEdgeIt& operator++() { return *this; } - }; - /// This iterator goes through each edge. - - /// This iterator goes through each edge of a graph. - /// Its usage is quite simple, for example you can count the number - /// of edges in a graph \c g of type \c Graph as follows: - /// \code - /// int count=0; - /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count; - /// \endcode - class EdgeIt : public Edge { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - EdgeIt() { } - /// Copy constructor. - - /// Copy constructor. - /// - EdgeIt(const EdgeIt& e) : Edge(e) { } - /// Initialize the iterator to be invalid. - - /// Initialize the iterator to be invalid. - /// - EdgeIt(Invalid) { } - /// This constructor sets the iterator to the first edge. - - /// This constructor sets the iterator to the first edge of \c g. - ///@param g the graph - EdgeIt(const StaticGraph&) { } - /// Edge -> EdgeIt conversion - - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the edge-set, the iteration order is the same. - EdgeIt(const StaticGraph&, const Edge&) { } - ///Next edge - - /// Assign the iterator to the next edge. - EdgeIt& operator++() { return *this; } - }; - ///Gives back the target node of an edge. - - ///Gives back the target node of an edge. - /// - Node target(Edge) const { return INVALID; } - ///Gives back the source node of an edge. - - ///Gives back the source node of an edge. - /// - Node source(Edge) const { return INVALID; } - /// Read write map of the nodes to type \c T. - - /// \ingroup concept - /// ReadWrite map of the nodes to type \c T. - /// \sa Reference - /// \warning Making maps that can handle bool type (NodeMap) - /// needs some extra attention! - template - class NodeMap : public ReadWriteMap< Node, T > - { - public: - - ///\e - NodeMap(const StaticGraph&) { } - ///\e - NodeMap(const StaticGraph&, T) { } - - ///Copy constructor - NodeMap(const NodeMap& nm) : ReadWriteMap< Node, T >(nm) { } - ///Assignment operator - NodeMap& operator=(const NodeMap&) { return *this; } - // \todo fix this concept - }; - - /// Read write map of the edges to type \c T. - - /// \ingroup concept - ///Reference map of the edges to type \c T. - /// \sa Reference - /// \warning Making maps that can handle bool type (EdgeMap) - /// needs some extra attention! - template - class EdgeMap : public ReadWriteMap - { - public: - - ///\e - EdgeMap(const StaticGraph&) { } - ///\e - EdgeMap(const StaticGraph&, T) { } - ///Copy constructor - EdgeMap(const EdgeMap& em) : ReadWriteMap(em) { } - ///Assignment operator - EdgeMap& operator=(const EdgeMap&) { return *this; } - // \todo fix this concept - }; - - template - struct Constraints : public _StaticGraph::Constraints<_Graph> {}; - - }; - - /// An empty non-static graph class. - - /// This class provides everything that \ref StaticGraph does. - /// Additionally it enables building graphs from scratch. - class ExtendableGraph : public StaticGraph - { - public: - /// Defalult constructor. - - /// Defalult constructor. - /// - ExtendableGraph() { } - ///Add a new node to the graph. - - /// \return the new node. - /// - Node addNode() { return INVALID; } - ///Add a new edge to the graph. - - ///Add a new edge to the graph with source node \c s - ///and target node \c t. - ///\return the new edge. - Edge addEdge(Node, Node) { return INVALID; } - - /// Resets the graph. - - /// This function deletes all edges and nodes of the graph. - /// It also frees the memory allocated to store them. - /// \todo It might belong to \ref ErasableGraph. - void clear() { } - - template - struct Constraints : public _ExtendableGraph::Constraints<_Graph> {}; - - }; - - /// An empty erasable graph class. - - /// This class is an extension of \ref ExtendableGraph. It makes it - /// possible to erase edges or nodes. - class ErasableGraph : public ExtendableGraph - { - public: - /// Defalult constructor. - - /// Defalult constructor. - /// - ErasableGraph() { } - /// Deletes a node. - - /// Deletes node \c n node. - /// - void erase(Node) { } - /// Deletes an edge. - - /// Deletes edge \c e edge. - /// - void erase(Edge) { } - - template - struct Constraints : public _ErasableGraph::Constraints<_Graph> {}; - - }; - - - /************* New GraphBase stuff **************/ - - -// /// A minimal GraphBase concept - -// /// This class describes a minimal concept which can be extended to a -// /// full-featured graph with \ref GraphFactory. -// class GraphBase { -// public: - -// GraphBase() {} - -// /// \bug Should we demand that Node and Edge be subclasses of the -// /// Graph class??? - -// typedef GraphItem<'n'> Node; -// typedef GraphItem<'e'> Edge; - -// // class Node : public BaseGraphItem<'n'> {}; -// // class Edge : public BaseGraphItem<'e'> {}; - -// // Graph operation -// void firstNode(Node &n) const { } -// void firstEdge(Edge &e) const { } - -// void firstOutEdge(Edge &e, Node) const { } -// void firstInEdge(Edge &e, Node) const { } - -// void nextNode(Node &n) const { } -// void nextEdge(Edge &e) const { } - - -// // Question: isn't it reasonable if this methods have a Node -// // parameter? Like this: -// // Edge& nextOut(Edge &e, Node) const { return e; } -// void nextOutEdge(Edge &e) const { } -// void nextInEdge(Edge &e) const { } - -// Node target(Edge) const { return Node(); } -// Node source(Edge) const { return Node(); } - - -// // Do we need id, nodeNum, edgeNum and co. in this basic graphbase -// // concept? - - -// // Maps. -// // -// // We need a special slimer concept which does not provide maps (it -// // wouldn't be strictly slimer, cause for map-factory id() & friends -// // a required...) - -// template -// class NodeMap : public GraphMap {}; - -// template -// class EdgeMap : public GraphMap {}; -// }; - - // @} - } //namespace concept -} //namespace lemon - - - -#endif // LEMON_CONCEPT_GRAPH_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/concept/graph_component.h --- a/src/lemon/concept/graph_component.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,982 +0,0 @@ -/* -*- C++ -*- - * src/lemon/concept/graph_component.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -///\ingroup graph_concepts -///\file -///\brief The graph components. - - -#ifndef LEMON_CONCEPT_GRAPH_COMPONENT_H -#define LEMON_CONCEPT_GRAPH_COMPONENT_H - -#include -#include - -#include - -namespace lemon { - namespace concept { - - /// \addtogroup graph_concepts - /// @{ - - /**************** Graph iterator concepts ****************/ - - /// Skeleton class for graph Node and Edge types - - /// This class describes the interface of Node and Edge (and UndirEdge - /// in undirected graphs) subtypes of graph types. - /// - /// \note This class is a template class so that we can use it to - /// create graph skeleton classes. The reason for this is than Node - /// and Edge types should \em not derive from the same base class. - /// For Node you should instantiate it with character 'n' and for Edge - /// with 'e'. - -#ifndef DOXYGEN - template -#endif - class GraphItem { - public: - /// Default constructor. - - /// \warning The default constructor is not required to set - /// the item to some well-defined value. So you should consider it - /// as uninitialized. - GraphItem() {} - /// Copy constructor. - - /// Copy constructor. - /// - GraphItem(GraphItem const&) {} - /// Invalid constructor \& conversion. - - /// This constructor initializes the item to be invalid. - /// \sa Invalid for more details. - GraphItem(Invalid) {} - /// Assign operator for nodes. - - /// The nodes are assignable. - /// - GraphItem& operator=(GraphItem const&) { return *this; } - /// Equality operator. - - /// Two iterators are equal if and only if they represents the - /// same node in the graph or both are invalid. - bool operator==(GraphItem) const { return false; } - /// Inequality operator. - - /// \sa operator==(const Node& n) - /// - bool operator!=(GraphItem) const { return false; } - - /// Artificial ordering operator. - - /// To allow the use of graph descriptors as key type in std::map or - /// similar associative container we require this. - /// - /// \note This operator only have to define some strict ordering of - /// the items; this order has nothing to do with the iteration - /// ordering of the items. - /// - /// \bug This is a technical requirement. Do we really need this? - bool operator<(GraphItem) const { return false; } - - template - struct Constraints { - void constraints() { - _GraphItem i1; - _GraphItem i2 = i1; - _GraphItem i3 = INVALID; - - i1 = i2 = i3; - - bool b; - // b = (ia == ib) && (ia != ib) && (ia < ib); - b = (ia == ib) && (ia != ib); - b = (ia == INVALID) && (ib != INVALID); - // b = (ia < ib); - } - - const _GraphItem &ia; - const _GraphItem &ib; - }; - }; - - /// A type describing the concept of graph node - - /// This is an instantiation of \ref GraphItem which can be used as a - /// Node subtype in graph skeleton definitions - typedef GraphItem<'n'> GraphNode; - - /// A type describing the concept of graph edge - - /// This is an instantiation of \ref GraphItem which can be used as a - /// Edge subtype in graph skeleton definitions - typedef GraphItem<'e'> GraphEdge; - - - /**************** Basic features of graphs ****************/ - - /// An empty base graph class. - - /// This class provides the minimal set of features needed for a graph - /// structure. All graph concepts have to be conform to this base - /// graph. - /// - /// \bug This is not true. The minimal graph concept is the - /// BaseIterableGraphComponent. - - class BaseGraphComponent { - public: - - typedef BaseGraphComponent Graph; - - /// Node class of the graph. - - /// This class represents the Nodes of the graph. - /// - typedef GraphItem<'n'> Node; - - /// Edge class of the graph. - - /// This class represents the Edges of the graph. - /// - typedef GraphItem<'e'> Edge; - - ///Gives back the target node of an edge. - - ///Gives back the target node of an edge. - /// - Node target(const Edge&) const { return INVALID;} - - ///Gives back the source node of an edge. - - ///Gives back the source node of an edge. - /// - Node source(const Edge&) const { return INVALID;} - - - template - struct Constraints { - typedef typename _Graph::Node Node; - typedef typename _Graph::Edge Edge; - - void constraints() { - checkConcept, Node>(); - checkConcept, Edge>(); - { - Node n; - Edge e; - n = graph.source(e); - n = graph.target(e); - } - } - - const _Graph& graph; - }; - }; - - /// An empty iterable base graph class. - - /// This class provides beside the core graph features - /// core iterable interface for the graph structure. - /// Most of the base graphs should be conform to this concept. - - class BaseIterableGraphComponent : virtual public BaseGraphComponent { - public: - - typedef BaseGraphComponent::Node Node; - typedef BaseGraphComponent::Edge Edge; - - /// Gives back the first Node in the iterating order. - - /// Gives back the first Node in the iterating order. - /// - void first(Node&) const {} - - /// Gives back the next Node in the iterating order. - - /// Gives back the next Node in the iterating order. - /// - void next(Node&) const {} - - /// Gives back the first Edge in the iterating order. - - /// Gives back the first Edge in the iterating order. - /// - void first(Edge&) const {} - /// Gives back the next Edge in the iterating order. - - /// Gives back the next Edge in the iterating order. - /// - void next(Edge&) const {} - - - /// Gives back the first of the Edges point to the given Node. - - /// Gives back the first of the Edges point to the given Node. - /// - void firstIn(Edge&, const Node&) const {} - - /// Gives back the next of the Edges points to the given Node. - - - /// Gives back the next of the Edges points to the given Node. - /// - void nextIn(Edge&) const {} - - /// Gives back the first of the Edges start from the given Node. - - /// Gives back the first of the Edges start from the given Node. - /// - void firstOut(Edge&, const Node&) const {} - - /// Gives back the next of the Edges start from the given Node. - - /// Gives back the next of the Edges start from the given Node. - /// - void nextOut(Edge&) const {} - - - template - struct Constraints { - - void constraints() { - checkConcept< BaseGraphComponent, _Graph >(); - typename _Graph::Node node; - typename _Graph::Edge edge; - { - graph.first(node); - graph.next(node); - } - { - graph.first(edge); - graph.next(edge); - } - { - graph.firstIn(edge, node); - graph.nextIn(edge); - } - { - graph.firstOut(edge, node); - graph.nextOut(edge); - } - } - - const _Graph& graph; - }; - }; - - /// An empty idable base graph class. - - /// This class provides beside the core graph features - /// core id functions for the graph structure. - /// The most of the base graphs should be conform to this concept. - /// The id's are unique and immutable. - class IDableGraphComponent : virtual public BaseGraphComponent { - public: - - typedef BaseGraphComponent::Node Node; - typedef BaseGraphComponent::Edge Edge; - - /// Gives back an unique integer id for the Node. - - /// Gives back an unique integer id for the Node. - /// - int id(const Node&) const { return -1;} - - /// \brief Gives back the node by the unique id. - /// - /// Gives back the node by the unique id. - /// If the graph does not contain node with the given id - /// then the result of the function is undetermined. - Node fromId(int , Node) const { return INVALID;} - - /// \brief Gives back an unique integer id for the Edge. - /// - /// Gives back an unique integer id for the Edge. - /// - int id(const Edge&) const { return -1;} - - /// \brief Gives back the edge by the unique id. - /// - /// Gives back the edge by the unique id. - /// If the graph does not contain edge with the given id - /// then the result of the function is undetermined. - Edge fromId(int, Edge) const { return INVALID;} - - template - struct Constraints { - - void constraints() { - checkConcept< BaseGraphComponent, _Graph >(); - typename _Graph::Node node; - int nid = graph.id(node); - nid = graph.id(node); - node = graph.fromId(nid, Node()); - typename _Graph::Edge edge; - int eid = graph.id(edge); - eid = graph.id(edge); - edge = graph.fromId(eid, Edge()); - } - - const _Graph& graph; - }; - }; - - - /// An empty max-idable base graph class. - - /// This class provides beside the core graph features - /// core max id functions for the graph structure. - /// The most of the base graphs should be conform to this concept. - /// The id's are unique and immutable. - class MaxIDableGraphComponent : virtual public BaseGraphComponent { - public: - - /// Gives back an integer greater or equal to the maximum Node id. - - /// Gives back an integer greater or equal to the maximum Node id. - /// - int maxId(Node = INVALID) const { return -1;} - - /// Gives back an integer greater or equal to the maximum Edge id. - - /// Gives back an integer greater or equal to the maximum Edge id. - /// - int maxId(Edge = INVALID) const { return -1;} - - template - struct Constraints { - - void constraints() { - checkConcept(); - int nid = graph.maxId(typename _Graph::Node()); - ignore_unused_variable_warning(nid); - int eid = graph.maxId(typename _Graph::Edge()); - ignore_unused_variable_warning(eid); - } - - const _Graph& graph; - }; - }; - - /// An empty extendable base graph class. - - /// This class provides beside the core graph features - /// core graph extend interface for the graph structure. - /// The most of the base graphs should be conform to this concept. - class BaseExtendableGraphComponent : virtual public BaseGraphComponent { - public: - - typedef BaseGraphComponent::Node Node; - typedef BaseGraphComponent::Edge Edge; - - /// Adds a new Node to the graph. - - /// Adds a new Node to the graph. - /// - Node addNode() { - return INVALID; - } - - /// Adds a new Edge connects the two Nodes to the graph. - - /// Adds a new Edge connects the two Nodes to the graph. - /// - Edge addEdge(const Node&, const Node&) { - return INVALID; - } - - template - struct Constraints { - void constraints() { - checkConcept(); - typename _Graph::Node node_a, node_b; - node_a = graph.addNode(); - typename _Graph::Edge edge; - edge = graph.addEdge(node_a, node_b); - } - - _Graph& graph; - }; - }; - - /// An empty erasable base graph class. - - /// This class provides beside the core graph features - /// core erase functions for the graph structure. - /// The most of the base graphs should be conform to this concept. - class BaseErasableGraphComponent : virtual public BaseGraphComponent { - public: - - typedef BaseGraphComponent::Node Node; - typedef BaseGraphComponent::Edge Edge; - - /// Erase a Node from the graph. - - /// Erase a Node from the graph. This function should not - /// erase edges connecting to the Node. - void erase(const Node&) {} - - /// Erase an Edge from the graph. - - /// Erase an Edge from the graph. - /// - void erase(const Edge&) {} - - template - struct Constraints { - void constraints() { - checkConcept(); - typename _Graph::Node node; - graph.erase(node); - typename _Graph::Edge edge; - graph.erase(edge); - } - - _Graph& graph; - }; - }; - - /// An empty clearable base graph class. - - /// This class provides beside the core graph features - /// core clear functions for the graph structure. - /// The most of the base graphs should be conform to this concept. - class ClearableGraphComponent : virtual public BaseGraphComponent { - public: - - /// Erase all the Nodes and Edges from the graph. - - /// Erase all the Nodes and Edges from the graph. - /// - void clear() {} - - template - struct Constraints { - void constraints() { - checkConcept(); - graph.clear(); - } - - _Graph graph; - }; - }; - - - /// Skeleton class for graph NodeIt and EdgeIt - - /// Skeleton class for graph NodeIt and EdgeIt. - /// - template - class GraphIterator : public _Item { - public: - /// \todo Don't we need the Item type as typedef? - - /// Default constructor. - - /// @warning The default constructor sets the iterator - /// to an undefined value. - GraphIterator() {} - /// Copy constructor. - - /// Copy constructor. - /// - GraphIterator(GraphIterator const&) {} - /// Sets the iterator to the first item. - - /// Sets the iterator to the first item of \c the graph. - /// - explicit GraphIterator(const _Graph&) {} - /// Invalid constructor \& conversion. - - /// This constructor initializes the item to be invalid. - /// \sa Invalid for more details. - GraphIterator(Invalid) {} - /// Assign operator for items. - - /// The items are assignable. - /// - GraphIterator& operator=(GraphIterator const&) { return *this; } - /// Next item. - - /// Assign the iterator to the next item. - /// - GraphIterator& operator++() { return *this; } - // Node operator*() const { return INVALID; } - /// Equality operator - - /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. - bool operator==(const GraphIterator&) const { return true;} - /// Inequality operator - - /// \sa operator==(Node n) - /// - bool operator!=(const GraphIterator&) const { return true;} - - template - struct Constraints { - void constraints() { - // checkConcept< Item, _GraphIterator >(); - _GraphIterator it1(g); - - /// \todo Do we need NodeIt(Node) kind of constructor? - // _GraphIterator it2(bj); - _GraphIterator it2; - - it2 = ++it1; - ++it2 = it1; - ++(++it1); - /// \bug This should be: is_base_and_derived - _Item bi = it1; - bi = it2; - } - _Graph& g; - }; - }; - - /// Skeleton class for graph InEdgeIt and OutEdgeIt - - /// \note Because InEdgeIt and OutEdgeIt may not inherit from the same - /// base class, the _selector is a additional template parameter. For - /// InEdgeIt you should instantiate it with character 'i' and for - /// OutEdgeIt with 'o'. - /// \todo Is this a good name for this concept? - template - class GraphIncIterator : public Edge { - public: - /// Default constructor. - - /// @warning The default constructor sets the iterator - /// to an undefined value. - GraphIncIterator() {} - /// Copy constructor. - - /// Copy constructor. - /// - GraphIncIterator(GraphIncIterator const& gi) :Edge(gi) {} - /// Sets the iterator to the first edge incoming into or outgoing - /// from the node. - - /// Sets the iterator to the first edge incoming into or outgoing - /// from the node. - /// - explicit GraphIncIterator(const Graph&, const typename Graph::Node&) {} - /// Invalid constructor \& conversion. - - /// This constructor initializes the item to be invalid. - /// \sa Invalid for more details. - GraphIncIterator(Invalid) {} - /// Assign operator for nodes. - - /// The nodes are assignable. - /// - GraphIncIterator& operator=(GraphIncIterator const&) { return *this; } - /// Next edge. - - /// Assign the iterator to the next node. - /// - GraphIncIterator& operator++() { return *this; } - - // Node operator*() const { return INVALID; } - - /// Equality operator - - /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. - bool operator==(const GraphIncIterator&) const { return true;} - - /// Inequality operator - - /// \sa operator==(Node n) - /// - bool operator!=(const GraphIncIterator&) const { return true;} - - template - struct Constraints { - typedef typename Graph::Node Node; - void constraints() { - checkConcept, _GraphIncIterator>(); - _GraphIncIterator it1(graph, node); - /// \todo Do we need OutEdgeIt(Edge) kind of constructor? - // _GraphIncIterator it2(edge); - _GraphIncIterator it2; - - it2 = ++it1; - ++it2 = it1; - ++(++it1); - Edge e = it1; - e = it2; - - const_constraits(); - } - - void const_constraits() { - Node n = graph.baseNode(it); - n = graph.runningNode(it); - } - - Edge edge; - Node node; - Graph graph; - _GraphIncIterator it; - }; - }; - - - /// An empty iterable base graph class. - - /// This class provides beside the core graph features - /// iterator based iterable interface for the graph structure. - /// This concept is part of the StaticGraphConcept. - class IterableGraphComponent : virtual public BaseGraphComponent { - - public: - - typedef IterableGraphComponent Graph; - - typedef BaseGraphComponent::Node Node; - typedef BaseGraphComponent::Edge Edge; - - /// This iterator goes through each node. - - /// This iterator goes through each node. - /// - typedef GraphIterator NodeIt; - /// This iterator goes through each node. - - /// This iterator goes through each node. - /// - typedef GraphIterator EdgeIt; - /// This iterator goes trough the incoming edges of a node. - - /// This iterator goes trough the \e inccoming edges of a certain node - /// of a graph. - typedef GraphIncIterator InEdgeIt; - /// This iterator goes trough the outgoing edges of a node. - - /// This iterator goes trough the \e outgoing edges of a certain node - /// of a graph. - typedef GraphIncIterator OutEdgeIt; - }; - - template - struct Constraints { - void constraints() { - checkConcept< BaseGraphComponent, _Graph>(); - - checkConcept, - typename _Graph::EdgeIt >(); - checkConcept, - typename _Graph::NodeIt >(); - checkConcept, typename _Graph::InEdgeIt >(); - checkConcept, typename _Graph::OutEdgeIt >(); - } - }; - - /// An empty alteration notifier base graph class. - - /// This class provides beside the core graph features - /// alteration notifier interface for the graph structure. - /// This is an observer-notifier pattern. More Obsevers can - /// be registered into the notifier and whenever an alteration - /// occured in the graph all the observers will notified about it. - class AlterableGraphComponent : virtual public BaseGraphComponent { - public: - - /// The edge observer registry. - typedef AlterationNotifier EdgeNotifier; - /// The node observer registry. - typedef AlterationNotifier NodeNotifier; - - /// \brief Gives back the edge alteration notifier. - /// - /// Gives back the edge alteration notifier. - EdgeNotifier getNotifier(Edge) const { - return EdgeNotifier(); - } - - /// \brief Gives back the node alteration notifier. - /// - /// Gives back the node alteration notifier. - NodeNotifier getNotifier(Node) const { - return NodeNotifier(); - } - - }; - - - /// Class describing the concept of graph maps - - /// This class describes the common interface of the graph maps - /// (NodeMap, EdgeMap), that is \ref maps-pages "maps" which can be used to - /// associate data to graph descriptors (nodes or edges). - template - class GraphMap : public ReadWriteMap { - protected: - GraphMap() {} - public: - /// \brief Construct a new map. - /// - /// Construct a new map for the graph. - explicit GraphMap(const Graph&) {} - /// \brief Construct a new map with default value. - /// - /// Construct a new map for the graph and initalise the values. - GraphMap(const Graph&, const _Value&) {} - /// \brief Copy constructor. - /// - /// Copy Constructor. - GraphMap(const GraphMap& gm) :ReadWriteMap(gm) {} - - /// \brief Assign operator. - /// - /// Assign operator. - GraphMap& operator=(const GraphMap&) { return *this;} - - template - struct Constraints { - void constraints() { - checkConcept, _Map >(); - // Construction with a graph parameter - _Map a(g); - // Constructor with a graph and a default value parameter - _Map a2(g,t); - // Copy constructor. Do we need it? - _Map b=c; - // Copy operator. Do we need it? - a=b; - - ignore_unused_variable_warning(a2); - } - - const _Map &c; - const Graph &g; - const typename GraphMap::Value &t; - }; - - }; - - /// An empty mappable base graph class. - - /// This class provides beside the core graph features - /// map interface for the graph structure. - /// This concept is part of the StaticGraphConcept. - class MappableGraphComponent : virtual public BaseGraphComponent { - public: - - typedef MappableGraphComponent Graph; - - typedef BaseGraphComponent::Node Node; - typedef BaseGraphComponent::Edge Edge; - - /// ReadWrite map of the nodes. - - /// ReadWrite map of the nodes. - /// - template - class NodeMap : public GraphMap { - private: - NodeMap(); - public: - /// \brief Construct a new map. - /// - /// Construct a new map for the graph. - /// \todo call the right parent class constructor - explicit NodeMap(const Graph&) {} - /// \brief Construct a new map with default value. - /// - /// Construct a new map for the graph and initalise the values. - NodeMap(const Graph&, const _Value&) {} - /// \brief Copy constructor. - /// - /// Copy Constructor. - NodeMap(const NodeMap& nm) : GraphMap(nm) {} - - /// \brief Assign operator. - /// - /// Assign operator. - NodeMap& operator=(const NodeMap&) { return *this;} - - }; - - /// ReadWrite map of the edges. - - /// ReadWrite map of the edges. - /// - template - class EdgeMap : public GraphMap { - private: - EdgeMap(); - public: - /// \brief Construct a new map. - /// - /// Construct a new map for the graph. - /// \todo call the right parent class constructor - explicit EdgeMap(const Graph&) {} - /// \brief Construct a new map with default value. - /// - /// Construct a new map for the graph and initalise the values. - EdgeMap(const Graph&, const _Value&) {} - /// \brief Copy constructor. - /// - /// Copy Constructor. - EdgeMap(const EdgeMap& em) :GraphMap(em) {} - - /// \brief Assign operator. - /// - /// Assign operator. - EdgeMap& operator=(const EdgeMap&) { return *this;} - - }; - - template - struct Constraints { - - struct Type { - int value; - Type() : value(0) {} - Type(int _v) : value(_v) {} - }; - - void constraints() { - checkConcept(); - { // int map test - typedef typename _Graph::template NodeMap IntNodeMap; - checkConcept, - IntNodeMap >(); - } { // bool map test - typedef typename _Graph::template NodeMap BoolNodeMap; - checkConcept, - BoolNodeMap >(); - } { // Type map test - typedef typename _Graph::template NodeMap TypeNodeMap; - checkConcept, - TypeNodeMap >(); - } - - { // int map test - typedef typename _Graph::template EdgeMap IntEdgeMap; - checkConcept, - IntEdgeMap >(); - } { // bool map test - typedef typename _Graph::template EdgeMap BoolEdgeMap; - checkConcept, - BoolEdgeMap >(); - } { // Type map test - typedef typename _Graph::template EdgeMap TypeEdgeMap; - checkConcept, - TypeEdgeMap >(); - } - } - - _Graph& graph; - }; - }; - - /// \brief An empty extendable extended graph class. - /// - /// This class provides beside the core graph features - /// item addition interface for the graph structure. - /// The difference between this class and the - /// \c BaseExtendableGraphComponent is that it should - /// notify the item alteration observers. - class ExtendableGraphComponent : virtual public BaseGraphComponent { - public: - - typedef ExtendableGraphComponent Graph; - - typedef BaseGraphComponent::Node Node; - typedef BaseGraphComponent::Edge Edge; - - /// \brief Add a node to the graph. - /// - /// Add a node to the graph and notify the observers. - Node addNode() { - return INVALID; - } - - /// \brief Add an edge to the graph. - /// - /// Add an edge to the graph and notify the observers. - Edge addEdge(const Node&, const Node&) { - return INVALID; - } - - template - struct Constraints { - void constraints() { - checkConcept(); - typename _Graph::Node node_a, node_b; - node_a = graph.addNode(); - typename _Graph::Edge edge; - edge = graph.addEdge(node_a, node_b); - } - _Graph& graph; - }; - }; - - /// \brief An empty erasable extended graph class. - /// - /// This class provides beside the core graph features - /// item erase interface for the graph structure. - /// The difference between this class and the - /// \c BaseErasableGraphComponent is that it should - /// notify the item alteration observers. - class ErasableGraphComponent : virtual public BaseGraphComponent { - public: - - typedef ErasableGraphComponent Graph; - - typedef BaseGraphComponent::Node Node; - typedef BaseGraphComponent::Edge Edge; - - /// \brief Erase the Node and notify the node alteration observers. - /// - /// Erase the Node and notify the node alteration observers. - void erase(const Node&) {} - - /// \brief Erase the Edge and notify the edge alteration observers. - /// - /// Erase the Edge and notify the edge alteration observers. - void erase(const Edge&) {} - - template - struct Constraints { - void constraints() { - checkConcept(); - typename _Graph::Node node; - graph.erase(node); - typename _Graph::Edge edge; - graph.erase(edge); - } - - _Graph& graph; - }; - }; - - /// @} - - } - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/concept/heap.h --- a/src/lemon/concept/heap.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,201 +0,0 @@ -/* -*- C++ -*- - * src/lemon/concept/heap.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -///\ingroup concept -///\file -///\brief Classes for representing heaps. -/// - -#ifndef LEMON_CONCEPT_HEAP_H -#define LEMON_CONCEPT_HEAP_H - -#include - -namespace lemon { - namespace concept { - /// \addtogroup concept - /// @{ - - - /// \brief A concept structure describes the main interface of heaps. - /// - /// A concept structure describes the main interface of heaps. - /// - template - class Heap { - public: - - - /// \brief Type to represent the items states. - /// - /// Each Item element have a state associated to it. It may be "in heap", - /// "pre heap" or "post heap". The later two are indifferent from the - /// heap's point of view, but may be useful to the user. - /// - /// The ItemIntMap _should_ be initialized in such way, that it maps - /// PRE_HEAP (-1) to any element to be put in the heap... - enum state_enum { - IN_HEAP = 0, - PRE_HEAP = -1, - POST_HEAP = -2 - }; - - /// \brief The constructor. - /// - /// The constructor. - /// \param _iim should be given to the constructor, since it is used - /// internally to handle the cross references. The value of the map - /// should be PRE_HEAP (-1) for each element. - explicit Heap(ItemIntMap &_iim) {} - - /// The number of items stored in the heap. - /// - /// \brief Returns the number of items stored in the heap. - int size() const { return 0; } - /// \brief Checks if the heap stores no items. - /// - /// Returns \c true if and only if the heap stores no items. - bool empty() const { return false; } - - /// \brief Insert an item into the heap with the given heap. - /// - /// Adds \c i to the heap with priority \c p. - /// \param i The item to insert. - /// \param p The priority of the item. - void push(const Item &i, const Prio &p) {} - - /// \brief Returns the item with minimum priority. - /// - /// This method returns the item with minimum priority. - /// \pre The heap must be nonempty. - Item top() const {} - - /// \brief Returns the minimum priority. - /// - /// It returns the minimum priority. - /// \pre The heap must be nonempty. - Prio prio() const {} - - /// \brief Deletes the item with minimum priority. - /// - /// This method deletes the item with minimum priority. - /// \pre The heap must be non-empty. - void pop() {} - - /// \brief Deletes \c i from the heap. - /// - /// This method deletes item \c i from the heap, if \c i was - /// already stored in the heap. - /// \param i The item to erase. - void erase(const Item &i) {} - - /// \brief Returns the priority of \c i. - /// - /// This function returns the priority of item \c i. - /// \pre \c i must be in the heap. - /// \param i The item. - Prio operator[](const Item &i) const {} - - /// \brief \c i gets to the heap with priority \c p independently - /// if \c i was already there. - /// - /// This method calls \ref push(\c i, \c p) if \c i is not stored - /// in the heap and sets the priority of \c i to \c p otherwise. - /// It may throw an \e UnderFlowPriorityException. - /// \param i The item. - /// \param p The priority. - void set(const Item &i, const Prio &p) {} - - /// \brief Decreases the priority of \c i to \c p. - /// - /// This method decreases the priority of item \c i to \c p. - /// \pre \c i must be stored in the heap with priority at least \c p. - /// \param i The item. - /// \param p The priority. - void decrease(const Item &i, const Prio &p) {} - - /// \brief Increases the priority of \c i to \c p. - /// - /// This method sets the priority of item \c i to \c p. - /// \pre \c i must be stored in the heap with priority at most \c - /// p relative to \c Compare. - /// \param i The item. - /// \param p The priority. - void increase(const Item &i, const Prio &p) {} - - /// \brief Returns if \c item is in, has already been in, or has - /// never been in the heap. - /// - /// This method returns PRE_HEAP if \c item has never been in the - /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP - /// otherwise. In the latter case it is possible that \c item will - /// get back to the heap again. - /// \param i The item. - state_enum state(const Item &i) const {} - - - template - struct Constraints { - public: - - void constraints() { - Item item; - Prio prio; - - ignore_unused_variable_warning(item); - ignore_unused_variable_warning(prio); - - typedef typename _Heap::state_enum state_enum; - state_enum state; - - ignore_unused_variable_warning(state); - - _Heap heap1 = _Heap(map); - - ignore_unused_variable_warning(heap1); - - heap.push(item, prio); - - prio = heap.prio(); - item = heap.top(); - - heap.pop(); - - heap.set(item, prio); - heap.decrease(item, prio); - heap.increase(item, prio); - prio = heap[item]; - - heap.erase(item); - - state = heap.state(item); - - state = _Heap::PRE_HEAP; - state = _Heap::IN_HEAP; - state = _Heap::POST_HEAP; - } - - _Heap& heap; - ItemIntMap& map; - - Constraints() : heap(0), map(0) {} - }; - }; - - /// @} - } // namespace lemon -} -#endif // LEMON_CONCEPT_PATH_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/concept/maps.h --- a/src/lemon/concept/maps.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,187 +0,0 @@ -/* -*- C++ -*- - * src/lemon/concept/maps.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_CONCEPT_MAPS_H -#define LEMON_CONCEPT_MAPS_H - -#include - -///\ingroup concept -///\file -///\brief Map concepts checking classes for testing and documenting. - -namespace lemon { - - namespace concept { - - /// \addtogroup concept - /// @{ - - /// Readable map concept - template - class ReadMap - { - public: - /// Map's key type. - typedef K Key; - /// Map's value type. (The type of objects associated with the keys). - typedef T Value; - - // \bug Value don't need to be default constructible. - /// Returns the value associated with a key. - Value operator[](const Key &) const {return Value();} - - template - struct Constraints { - - void constraints() { - Value val = m[key]; - val = m[key]; - typename _ReadMap::Value own_val = m[own_key]; - own_val = m[own_key]; - - ignore_unused_variable_warning(val); - ignore_unused_variable_warning(own_val); - ignore_unused_variable_warning(key); - } - Key& key; - typename _ReadMap::Key& own_key; - _ReadMap& m; - }; - - }; - - - /// Writable map concept - template - class WriteMap - { - public: - /// Map's key type. - typedef K Key; - /// Map's value type. (The type of objects associated with the keys). - typedef T Value; - - /// Sets the value associated with a key. - void set(const Key &,const Value &) {} - - ///Default constructor - WriteMap() {} - - template - struct Constraints { - void constraints() { - // No constraints for constructor. - m.set(key, val); - m.set(own_key, own_val); - ignore_unused_variable_warning(key); - ignore_unused_variable_warning(val); - ignore_unused_variable_warning(own_key); - ignore_unused_variable_warning(own_val); - } - - Value& val; - typename _WriteMap::Value own_val; - Key& key; - typename _WriteMap::Key& own_key; - WriteMap& m; - - }; - }; - - ///Read/Writable map concept - template - class ReadWriteMap : public ReadMap, - public WriteMap - { - public: - /// Map's key type. - typedef K Key; - /// Map's value type. (The type of objects associated with the keys). - typedef T Value; - - /// Returns the value associated with a key. - Value operator[](const Key &) const {return Value();} - /// Sets the value associated with a key. - void set(const Key & ,const Value &) {} - - template - struct Constraints { - void constraints() { - checkConcept, _ReadWriteMap >(); - checkConcept, _ReadWriteMap >(); - } - }; - }; - - - ///Dereferable map concept - template - class ReferenceMap : public ReadWriteMap - { - public: - /// Map's key type. - typedef K Key; - /// Map's value type. (The type of objects associated with the keys). - typedef T Value; - /// Map's reference type. - typedef R Reference; - /// Map's const reference type. - typedef CR ConstReference; - - protected: - Value tmp; - public: - - ///Returns a reference to the value associated to a key. - Reference operator[](const Key &) { return tmp; } - ///Returns a const reference to the value associated to a key. - ConstReference operator[](const Key &) const - { return tmp; } - /// Sets the value associated with a key. - void set(const Key &k,const Value &t) { operator[](k)=t; } - - // \todo rethink this concept - template - struct ReferenceMapConcept { - - void constraints() { - checkConcept(); - m[key] = val; - val = m[key]; - m[key] = ref; - ref = m[key]; - m[own_key] = own_val; - own_val = m[own_key]; - m[own_key] = own_ref; - own_ref = m[own_key]; - } - - typename _ReferenceMap::Key& own_key; - typename _ReferenceMap::Value& own_val; - typename _ReferenceMap::Reference& own_ref; - Key& key; - Value& val; - Reference& ref; - ReferenceMap& m; - }; - }; - - // @} - - } //namespace concept -} //namespace lemon -#endif // LEMON_CONCEPT_MAPS_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/concept/path.h --- a/src/lemon/concept/path.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,236 +0,0 @@ -/* -*- C++ -*- - * src/lemon/concept/path.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -///\ingroup concept -///\file -///\brief Classes for representing paths in graphs. -/// -///\todo Iterators have obsolete style - -#ifndef LEMON_CONCEPT_PATH_H -#define LEMON_CONCEPT_PATH_H - -#include - -namespace lemon { - namespace concept { - /// \addtogroup concept - /// @{ - - - //! \brief A skeleton structure for representing directed paths in a graph. - //! - //! A skeleton structure for representing directed paths in a graph. - //! \param GR The graph type in which the path is. - //! - //! In a sense, the path can be treated as a graph, for it has \c NodeIt - //! and \c EdgeIt with the same usage. These types converts to the \c Node - //! and \c Edge of the original graph. - template - class Path { - public: - - /// Type of the underlying graph. - typedef /*typename*/ GR Graph; - /// Edge type of the underlying graph. - typedef typename Graph::Edge GraphEdge; - /// Node type of the underlying graph. - typedef typename Graph::Node GraphNode; - class NodeIt; - class EdgeIt; - - /// \param _G The graph in which the path is. - /// - Path(const Graph &) {} - - /// Length of the path. - int length() const {return 0;} - /// Returns whether the path is empty. - bool empty() const { return true;} - - /// Resets the path to an empty path. - void clear() {} - - /// \brief Starting point of the path. - /// - /// Starting point of the path. - /// Returns INVALID if the path is empty. - GraphNode/*It*/ target() const {return INVALID;} - /// \brief End point of the path. - /// - /// End point of the path. - /// Returns INVALID if the path is empty. - GraphNode/*It*/ source() const {return INVALID;} - - /// \brief First NodeIt/EdgeIt. - /// - /// Initializes node or edge iterator to point to the first - /// node or edge. - template - It& first(It &i) const { return i=It(*this); } - - /// \brief The target of an edge. - /// - /// Returns node iterator pointing to the target node of the - /// given edge iterator. - NodeIt target(const EdgeIt&) const {return INVALID;} - - /// \brief The source of an edge. - /// - /// Returns node iterator pointing to the source node of the - /// given edge iterator. - NodeIt source(const EdgeIt&) const {return INVALID;} - - - /* Iterator classes */ - - /** - * \brief Iterator class to iterate on the edges of the paths - * - * This class is used to iterate on the edges of the paths - * - * Of course it converts to Graph::Edge - * - */ - class EdgeIt { - public: - /// Default constructor - EdgeIt() {} - /// Invalid constructor - EdgeIt(Invalid) {} - /// Constructor with starting point - EdgeIt(const Path &) {} - - operator GraphEdge () const {} - - /// Next edge - EdgeIt& operator++() {return *this;} - - /// Comparison operator - bool operator==(const EdgeIt&) const {return true;} - /// Comparison operator - bool operator!=(const EdgeIt&) const {return true;} -// /// Comparison operator -// /// \todo It is not clear what is the "natural" ordering. -// bool operator<(const EdgeIt& e) const {} - - }; - - /** - * \brief Iterator class to iterate on the nodes of the paths - * - * This class is used to iterate on the nodes of the paths - * - * Of course it converts to Graph::Node. - * - */ - class NodeIt { - public: - /// Default constructor - NodeIt() {} - /// Invalid constructor - NodeIt(Invalid) {} - /// Constructor with starting point - NodeIt(const Path &) {} - - ///Conversion to Graph::Node - operator const GraphNode& () const {} - /// Next node - NodeIt& operator++() {return *this;} - - /// Comparison operator - bool operator==(const NodeIt&) const {return true;} - /// Comparison operator - bool operator!=(const NodeIt&) const {return true;} -// /// Comparison operator -// /// \todo It is not clear what is the "natural" ordering. -// bool operator<(const NodeIt& e) const {} - - }; - - friend class Builder; - - /** - * \brief Class to build paths - * - * This class is used to fill a path with edges. - * - * You can push new edges to the front and to the back of the path in - * arbitrary order then you should commit these changes to the graph. - * - * While the builder is active (after the first modifying - * operation and until the call of \ref commit()) the - * underlining Path is in a "transitional" state (operations on - * it have undefined result). - */ - class Builder { - public: - - Path &P; - - ///\param _P the path you want to fill in. - /// - - Builder(Path &_p) : P(_p) {} - - /// Sets the starting node of the path. - - /// Sets the starting node of the path. Edge added to the path - /// afterwards have to be incident to this node. - /// You \em must start building an empty path with these functions. - /// (And you \em must \em not use it later). - /// \sa pushFront() - /// \sa pushBack() - void setStartNode(const GraphNode &) {} - - ///Push a new edge to the front of the path - - ///Push a new edge to the front of the path. - ///If the path is empty, you \em must call \ref setStartNode() before - ///the first use of \ref pushFront(). - void pushFront(const GraphEdge&) {} - - ///Push a new edge to the back of the path - - ///Push a new edge to the back of the path. - ///If the path is empty, you \em must call \ref setStartNode() before - ///the first use of \ref pushBack(). - void pushBack(const GraphEdge&) {} - - ///Commit the changes to the path. - void commit() {} - - ///Reserve (front) storage for the builder in advance. - - ///If you know a reasonable upper bound on the number of the edges - ///to add to the front of the path, - ///using this function you may speed up the building. - void reserveFront(size_t) {} - ///Reserve (back) storage for the builder in advance. - - ///If you know a reasonable upper bound on the number of the edges - ///to add to the back of the path, - ///using this function you may speed up the building. - void reserveBack(size_t) {} - }; - }; - - ///@} - } - -} // namespace lemon - -#endif // LEMON_CONCEPT_PATH_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/concept/sym_graph.h --- a/src/lemon/concept/sym_graph.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,653 +0,0 @@ -/* -*- C++ -*- - * src/lemon/concept/graph.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_CONCEPT_SYM_GRAPH_H -#define LEMON_CONCEPT_SYM_GRAPH_H - -///\ingroup concept -///\file -///\brief Declaration of SymGraph. - -#include -#include -#include - -namespace lemon { - namespace concept { - - /// \addtogroup concept - /// @{ - - /// An empty static graph class. - - /// This class provides all the common features of a symmetric - /// graph structure, however completely without implementations and - /// real data structures behind the interface. - /// All graph algorithms should compile with this class, but it will not - /// run properly, of course. - /// - /// It can be used for checking the interface compatibility, - /// or it can serve as a skeleton of a new symmetric graph structure. - /// - /// Also, you will find here the full documentation of a certain graph - /// feature, the documentation of a real symmetric graph imlementation - /// like @ref SymListGraph or - /// @ref lemon::SymSmartGraph will just refer to this structure. - class StaticSymGraph - { - public: - /// Defalult constructor. - - /// Defalult constructor. - /// - StaticSymGraph() { } - ///Copy consructor. - -// ///\todo It is not clear, what we expect from a copy constructor. -// ///E.g. How to assign the nodes/edges to each other? What about maps? -// StaticGraph(const StaticGraph& g) { } - - /// The base type of node iterators, - /// or in other words, the trivial node iterator. - - /// This is the base type of each node iterator, - /// thus each kind of node iterator converts to this. - /// More precisely each kind of node iterator should be inherited - /// from the trivial node iterator. - class Node { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - Node() { } - /// Copy constructor. - - /// Copy constructor. - /// - Node(const Node&) { } - - /// Invalid constructor \& conversion. - - /// This constructor initializes the iterator to be invalid. - /// \sa Invalid for more details. - Node(Invalid) { } - /// Equality operator - - /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. - bool operator==(Node) const { return true; } - - /// Inequality operator - - /// \sa operator==(Node n) - /// - bool operator!=(Node) const { return true; } - - ///Comparison operator. - - ///This is a strict ordering between the nodes. - /// - ///This ordering can be different from the order in which NodeIt - ///goes through the nodes. - ///\todo Possibly we don't need it. - bool operator<(Node) const { return true; } - }; - - /// This iterator goes through each node. - - /// This iterator goes through each node. - /// Its usage is quite simple, for example you can count the number - /// of nodes in graph \c g of type \c Graph like this: - /// \code - /// int count=0; - /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count; - /// \endcode - class NodeIt : public Node { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - NodeIt() { } - /// Copy constructor. - - /// Copy constructor. - /// - NodeIt(const NodeIt&) { } - /// Invalid constructor \& conversion. - - /// Initialize the iterator to be invalid. - /// \sa Invalid for more details. - NodeIt(Invalid) { } - /// Sets the iterator to the first node. - - /// Sets the iterator to the first node of \c g. - /// - NodeIt(const StaticSymGraph& g) { } - /// Node -> NodeIt conversion. - - /// Sets the iterator to the node of \c g pointed by the trivial - /// iterator n. - /// This feature necessitates that each time we - /// iterate the edge-set, the iteration order is the same. - NodeIt(const StaticSymGraph& g, const Node& n) { } - /// Next node. - - /// Assign the iterator to the next node. - /// - NodeIt& operator++() { return *this; } - }; - - - /// The base type of the symmetric edge iterators. - - /// The base type of the symmetric edge iterators. - /// - class SymEdge { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - SymEdge() { } - /// Copy constructor. - - /// Copy constructor. - /// - SymEdge(const SymEdge&) { } - /// Initialize the iterator to be invalid. - - /// Initialize the iterator to be invalid. - /// - SymEdge(Invalid) { } - /// Equality operator - - /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. - bool operator==(SymEdge) const { return true; } - /// Inequality operator - - /// \sa operator==(Node n) - /// - bool operator!=(SymEdge) const { return true; } - ///Comparison operator. - - ///This is a strict ordering between the nodes. - /// - ///This ordering can be different from the order in which NodeIt - ///goes through the nodes. - ///\todo Possibly we don't need it. - bool operator<(SymEdge) const { return true; } - }; - - - /// The base type of the edge iterators. - - /// The base type of the edge iterators. - /// - class Edge : public SymEdge { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - Edge() { } - /// Copy constructor. - - /// Copy constructor. - /// - Edge(const Edge&) { } - /// Initialize the iterator to be invalid. - - /// Initialize the iterator to be invalid. - /// - Edge(Invalid) { } - /// Equality operator - - /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. - bool operator==(Edge) const { return true; } - /// Inequality operator - - /// \sa operator==(Node n) - /// - bool operator!=(Edge) const { return true; } - ///Comparison operator. - - ///This is a strict ordering between the nodes. - /// - ///This ordering can be different from the order in which NodeIt - ///goes through the nodes. - ///\todo Possibly we don't need it. - bool operator<(Edge) const { return true; } - }; - - /// This iterator goes trough the outgoing edges of a node. - - /// This iterator goes trough the \e outgoing edges of a certain node - /// of a graph. - /// Its usage is quite simple, for example you can count the number - /// of outgoing edges of a node \c n - /// in graph \c g of type \c Graph as follows. - /// \code - /// int count=0; - /// for (Graph::OutEdgeIt e(g, n); e!=INVALID; ++e) ++count; - /// \endcode - - class OutEdgeIt : public Edge { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - OutEdgeIt() { } - /// Copy constructor. - - /// Copy constructor. - /// - OutEdgeIt(const OutEdgeIt&) { } - /// Initialize the iterator to be invalid. - - /// Initialize the iterator to be invalid. - /// - OutEdgeIt(Invalid) { } - /// This constructor sets the iterator to first outgoing edge. - - /// This constructor set the iterator to the first outgoing edge of - /// node - ///@param n the node - ///@param g the graph - OutEdgeIt(const StaticSymGraph& g, const Node& n) { } - /// Edge -> OutEdgeIt conversion - - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the edge-set, the iteration order is the same. - OutEdgeIt(const StaticSymGraph& g, const Edge& e) { } - ///Next outgoing edge - - /// Assign the iterator to the next - /// outgoing edge of the corresponding node. - OutEdgeIt& operator++() { return *this; } - }; - - /// This iterator goes trough the incoming edges of a node. - - /// This iterator goes trough the \e incoming edges of a certain node - /// of a graph. - /// Its usage is quite simple, for example you can count the number - /// of outgoing edges of a node \c n - /// in graph \c g of type \c Graph as follows. - /// \code - /// int count=0; - /// for(Graph::InEdgeIt e(g, n); e!=INVALID; ++e) ++count; - /// \endcode - - class InEdgeIt : public Edge { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - InEdgeIt() { } - /// Copy constructor. - - /// Copy constructor. - /// - InEdgeIt(const InEdgeIt&) { } - /// Initialize the iterator to be invalid. - - /// Initialize the iterator to be invalid. - /// - InEdgeIt(Invalid) { } - /// This constructor sets the iterator to first incoming edge. - - /// This constructor set the iterator to the first incoming edge of - /// node - ///@param n the node - ///@param g the graph - InEdgeIt(const StaticSymGraph& g, const Node& n) { } - /// Edge -> InEdgeIt conversion - - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the edge-set, the iteration order is the same. - InEdgeIt(const StaticSymGraph& g, const Edge& n) { } - /// Next incoming edge - - /// Assign the iterator to the next inedge of the corresponding node. - /// - InEdgeIt& operator++() { return *this; } - }; - /// This iterator goes through each symmetric edge. - - /// This iterator goes through each symmetric edge of a graph. - /// Its usage is quite simple, for example you can count the number - /// of symmetric edges in a graph \c g of type \c Graph as follows: - /// \code - /// int count=0; - /// for(Graph::SymEdgeIt e(g); e!=INVALID; ++e) ++count; - /// \endcode - class SymEdgeIt : public SymEdge { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - SymEdgeIt() { } - /// Copy constructor. - - /// Copy constructor. - /// - SymEdgeIt(const SymEdgeIt&) { } - /// Initialize the iterator to be invalid. - - /// Initialize the iterator to be invalid. - /// - SymEdgeIt(Invalid) { } - /// This constructor sets the iterator to first edge. - - /// This constructor set the iterator to the first edge of - /// node - ///@param g the graph - SymEdgeIt(const StaticSymGraph& g) { } - /// Edge -> EdgeIt conversion - - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the edge-set, the iteration order is the same. - SymEdgeIt(const StaticSymGraph&, const SymEdge&) { } - ///Next edge - - /// Assign the iterator to the next - /// edge of the corresponding node. - SymEdgeIt& operator++() { return *this; } - }; - /// This iterator goes through each edge. - - /// This iterator goes through each edge of a graph. - /// Its usage is quite simple, for example you can count the number - /// of edges in a graph \c g of type \c Graph as follows: - /// \code - /// int count=0; - /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count; - /// \endcode - class EdgeIt : public Edge { - public: - /// Default constructor - - /// @warning The default constructor sets the iterator - /// to an undefined value. - EdgeIt() { } - /// Copy constructor. - - /// Copy constructor. - /// - EdgeIt(const EdgeIt&) { } - /// Initialize the iterator to be invalid. - - /// Initialize the iterator to be invalid. - /// - EdgeIt(Invalid) { } - /// This constructor sets the iterator to first edge. - - /// This constructor set the iterator to the first edge of - /// node - ///@param g the graph - EdgeIt(const StaticSymGraph& g) { } - /// Edge -> EdgeIt conversion - - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the edge-set, the iteration order is the same. - EdgeIt(const StaticSymGraph&, const Edge&) { } - ///Next edge - - /// Assign the iterator to the next - /// edge of the corresponding node. - EdgeIt& operator++() { return *this; } - }; - - /// First node of the graph. - - /// \retval i the first node. - /// \return the first node. - /// - NodeIt& first(NodeIt& i) const { return i; } - - /// The first incoming edge. - - /// The first incoming edge. - /// - InEdgeIt& first(InEdgeIt &i, Node) const { return i; } - /// The first outgoing edge. - - /// The first outgoing edge. - /// - OutEdgeIt& first(OutEdgeIt& i, Node) const { return i; } - /// The first edge of the Graph. - - /// The first edge of the Graph. - /// - EdgeIt& first(EdgeIt& i) const { return i; } - /// The first symmetric edge of the Graph. - - /// The first symmetric edge of the Graph. - /// - SymEdgeIt& first(SymEdgeIt& i) const { return i; } - - ///Gives back the target node of an edge. - - ///Gives back the target node of an edge. - /// - Node target(Edge) const { return INVALID; } - ///Gives back the source node of an edge. - - ///Gives back the source node of an edge. - /// - Node source(Edge) const { return INVALID; } - - ///Gives back the first node of an symmetric edge. - - ///Gives back the first node of an symmetric edge. - /// - Node target(SymEdge) const { return INVALID; } - ///Gives back the second node of an symmetric edge. - - ///Gives back the second node of an symmetric edge. - /// - Node source(SymEdge) const { return INVALID; } - ///Gives back the \e id of a node. - - ///\warning Not all graph structures provide this feature. - /// - ///\todo Should each graph provide \c id? - int id(const Node&) const { return 0; } - ///Gives back the \e id of an edge. - - ///\warning Not all graph structures provide this feature. - /// - ///\todo Should each graph provide \c id? - int id(const Edge&) const { return 0; } - - ///\warning Not all graph structures provide this feature. - /// - ///\todo Should each graph provide \c id? - int id(const SymEdge&) const { return 0; } - - ///\e - - ///\todo Should it be in the concept? - /// - int nodeNum() const { return 0; } - ///\e - - ///\todo Should it be in the concept? - /// - int edgeNum() const { return 0; } - - ///\todo Should it be in the concept? - /// - int symEdgeNum() const { return 0; } - - - /// Gives back the forward directed edge of the symmetric edge. - Edge forward(SymEdge) const {return INVALID;} - - /// Gives back the backward directed edge of the symmetric edge. - Edge backward(SymEdge) const {return INVALID;}; - - /// Gives back the opposite of the edge. - Edge opposite(Edge) const {return INVALID;} - - ///Reference map of the nodes to type \c T. - /// \ingroup concept - ///Reference map of the nodes to type \c T. - /// \sa Reference - /// \warning Making maps that can handle bool type (NodeMap) - /// needs some extra attention! - template class NodeMap : public ReferenceMap< Node, T > - { - public: - - ///\e - NodeMap(const StaticSymGraph&) { } - ///\e - NodeMap(const StaticSymGraph&, T) { } - - ///Copy constructor - template NodeMap(const NodeMap&) { } - ///Assignment operator - template NodeMap& operator=(const NodeMap&) - { return *this; } - }; - - ///Reference map of the edges to type \c T. - - /// \ingroup concept - ///Reference map of the edges to type \c T. - /// \sa Reference - /// \warning Making maps that can handle bool type (EdgeMap) - /// needs some extra attention! - template class EdgeMap - : public ReferenceMap - { - public: - - ///\e - EdgeMap(const StaticSymGraph&) { } - ///\e - EdgeMap(const StaticSymGraph&, T) { } - - ///Copy constructor - template EdgeMap(const EdgeMap&) { } - ///Assignment operator - template EdgeMap &operator=(const EdgeMap&) - { return *this; } - }; - - ///Reference map of the edges to type \c T. - - /// \ingroup concept - ///Reference map of the symmetric edges to type \c T. - /// \sa Reference - /// \warning Making maps that can handle bool type (EdgeMap) - /// needs some extra attention! - template class SymEdgeMap - : public ReferenceMap - { - public: - - ///\e - SymEdgeMap(const StaticSymGraph&) { } - ///\e - SymEdgeMap(const StaticSymGraph&, T) { } - - ///Copy constructor - template SymEdgeMap(const SymEdgeMap&) { } - ///Assignment operator - template SymEdgeMap &operator=(const SymEdgeMap&) - { return *this; } - }; - }; - - - - /// An empty non-static graph class. - - /// This class provides everything that \ref StaticGraph - /// with additional functionality which enables to build a - /// graph from scratch. - class ExtendableSymGraph : public StaticSymGraph - { - public: - /// Defalult constructor. - - /// Defalult constructor. - /// - ExtendableSymGraph() { } - ///Add a new node to the graph. - - /// \return the new node. - /// - Node addNode() { return INVALID; } - ///Add a new edge to the graph. - - ///Add a new symmetric edge to the graph with source node \c t - ///and target node \c h. - ///\return the new edge. - SymEdge addEdge(Node h, Node t) { return INVALID; } - - /// Resets the graph. - - /// This function deletes all edges and nodes of the graph. - /// It also frees the memory allocated to store them. - /// \todo It might belong to \ref ErasableGraph. - void clear() { } - }; - - /// An empty erasable graph class. - - /// This class is an extension of \ref ExtendableGraph. It also makes it - /// possible to erase edges or nodes. - class ErasableSymGraph : public ExtendableSymGraph - { - public: - /// Defalult constructor. - - /// Defalult constructor. - /// - ErasableSymGraph() { } - /// Deletes a node. - - /// Deletes node \c n node. - /// - void erase(Node n) { } - /// Deletes an edge. - - /// Deletes edge \c e edge. - /// - void erase(SymEdge e) { } - }; - - // @} - } //namespace concept -} //namespace lemon - - - -#endif // LEMON_CONCEPT_GRAPH_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/concept/undir_graph.h --- a/src/lemon/concept/undir_graph.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,531 +0,0 @@ -/* -*- C++ -*- - * - * src/lemon/concept/undir_graph_component.h - Part of LEMON, a generic - * C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi - * Kutatocsoport (Egervary Research Group on Combinatorial Optimization, - * EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -///\ingroup graph_concepts -///\file -///\brief Undirected graphs and components of. - - -#ifndef LEMON_CONCEPT_UNDIR_GRAPH_H -#define LEMON_CONCEPT_UNDIR_GRAPH_H - -#include - -namespace lemon { - namespace concept { - - /// \addtogroup graph_concepts - /// @{ - - - /// Skeleton class which describes an edge with direction in \ref - /// UndirGraph "undirected graph". - template - class UndirGraphEdge : public UndirGraph::UndirEdge { - typedef typename UndirGraph::UndirEdge UndirEdge; - typedef typename UndirGraph::Node Node; - public: - - /// \e - UndirGraphEdge() {} - - /// \e - UndirGraphEdge(const UndirGraphEdge& e) : UndirGraph::UndirEdge(e) {} - - /// \e - UndirGraphEdge(Invalid) {} - - /// \brief Directed edge from undirected edge and a source node. - /// - /// Constructs a directed edge from undirected edge and a source node. - /// - /// \note You have to specify the graph for this constructor. - UndirGraphEdge(const UndirGraph &g, - UndirEdge undir_edge, Node n) { - ignore_unused_variable_warning(undir_edge); - ignore_unused_variable_warning(g); - ignore_unused_variable_warning(n); - } - - /// \e - UndirGraphEdge& operator=(UndirGraphEdge) { return *this; } - - /// \e - bool operator==(UndirGraphEdge) const { return true; } - /// \e - bool operator!=(UndirGraphEdge) const { return false; } - - /// \e - bool operator<(UndirGraphEdge) const { return false; } - - template - struct Constraints { - void constraints() { - const_constraints(); - } - void const_constraints() const { - /// \bug This should be is_base_and_derived ... - UndirEdge ue = e; - ue = e; - - Edge e_with_source(graph,ue,n); - ignore_unused_variable_warning(e_with_source); - } - Edge e; - UndirEdge ue; - UndirGraph graph; - Node n; - }; - }; - - - struct BaseIterableUndirGraphConcept { - - template - struct Constraints { - - typedef typename Graph::UndirEdge UndirEdge; - typedef typename Graph::Edge Edge; - typedef typename Graph::Node Node; - - void constraints() { - checkConcept(); - checkConcept, UndirEdge>(); - checkConcept, Edge>(); - - graph.first(ue); - graph.next(ue); - - const_constraints(); - } - void const_constraints() { - Node n; - n = graph.target(ue); - n = graph.source(ue); - n = graph.oppositeNode(n0, ue); - - bool b; - b = graph.forward(e); - ignore_unused_variable_warning(b); - } - - Graph graph; - Edge e; - Node n0; - UndirEdge ue; - }; - - }; - - - struct IterableUndirGraphConcept { - - template - struct Constraints { - void constraints() { - /// \todo we don't need the iterable component to be base iterable - /// Don't we really??? - //checkConcept< BaseIterableUndirGraphConcept, Graph > (); - - checkConcept (); - - typedef typename Graph::UndirEdge UndirEdge; - typedef typename Graph::UndirEdgeIt UndirEdgeIt; - typedef typename Graph::IncEdgeIt IncEdgeIt; - - checkConcept, UndirEdgeIt>(); - checkConcept, IncEdgeIt>(); - } - }; - - }; - - struct MappableUndirGraphConcept { - - template - struct Constraints { - - struct Dummy { - int value; - Dummy() : value(0) {} - Dummy(int _v) : value(_v) {} - }; - - void constraints() { - checkConcept(); - - typedef typename Graph::template UndirEdgeMap IntMap; - checkConcept, - IntMap >(); - - typedef typename Graph::template UndirEdgeMap BoolMap; - checkConcept, - BoolMap >(); - - typedef typename Graph::template UndirEdgeMap DummyMap; - checkConcept, - DummyMap >(); - } - }; - - }; - - struct ExtendableUndirGraphConcept { - - template - struct Constraints { - void constraints() { - node_a = graph.addNode(); - uedge = graph.addEdge(node_a, node_b); - } - typename Graph::Node node_a, node_b; - typename Graph::UndirEdge uedge; - Graph graph; - }; - - }; - - struct ErasableUndirGraphConcept { - - template - struct Constraints { - void constraints() { - graph.erase(n); - graph.erase(e); - } - Graph graph; - typename Graph::Node n; - typename Graph::UndirEdge e; - }; - - }; - - /// Class describing the concept of Undirected Graphs. - - /// This class describes the common interface of all Undirected - /// Graphs. - /// - /// As all concept describing classes it provides only interface - /// without any sensible implementation. So any algorithm for - /// undirected graph should compile with this class, but it will not - /// run properly, of couse. - /// - /// In LEMON undirected graphs also fulfill the concept of directed - /// graphs (\ref lemon::concept::Graph "Graph Concept"). For - /// explanation of this and more see also the page \ref undir_graphs, - /// a tutorial about undirected graphs. - - class UndirGraph { - public: - - /// Type describing a node in the graph - typedef GraphNode Node; - - /// Type describing an undirected edge - typedef GraphItem<'u'> UndirEdge; - - /// Type describing an UndirEdge with direction -#ifndef DOXYGEN - typedef UndirGraphEdge Edge; -#else - typedef UndirGraphEdge Edge; -#endif - - /// Iterator type which iterates over all nodes -#ifndef DOXYGEN - typedef GraphIterator NodeIt; -#else - typedef GraphIterator NodeIt; -#endif - - /// Iterator type which iterates over all undirected edges -#ifndef DOXYGEN - typedef GraphIterator UndirEdgeIt; -#else - typedef GraphIterator UndirEdgeIt; -#endif - - /// Iterator type which iterates over all directed edges. - - /// Iterator type which iterates over all edges (each undirected - /// edge occurs twice with both directions. -#ifndef DOXYGEN - typedef GraphIterator EdgeIt; -#else - typedef GraphIterator EdgeIt; -#endif - - - /// Iterator of undirected edges incident to a node -#ifndef DOXYGEN - typedef GraphIncIterator IncEdgeIt; -#else - typedef GraphIncIterator IncEdgeIt; -#endif - - /// Iterator of edges incoming to a node -#ifndef DOXYGEN - typedef GraphIncIterator InEdgeIt; -#else - typedef GraphIncIterator InEdgeIt; -#endif - - /// Iterator of edges outgoing from a node -#ifndef DOXYGEN - typedef GraphIncIterator OutEdgeIt; -#else - typedef GraphIncIterator OutEdgeIt; -#endif - - /// NodeMap template -#ifdef DOXYGEN - typedef GraphMap NodeMap; -#endif - - /// UndirEdgeMap template -#ifdef DOXYGEN - typedef GraphMap UndirEdgeMap; -#endif - - /// EdgeMap template -#ifdef DOXYGEN - typedef GraphMap EdgeMap; -#endif - - template - class NodeMap : public GraphMap { - typedef GraphMap Parent; - public: - - explicit NodeMap(const UndirGraph &g) : Parent(g) {} - NodeMap(const UndirGraph &g, T t) : Parent(g, t) {} - }; - - template - class UndirEdgeMap : public GraphMap { - typedef GraphMap Parent; - public: - - explicit UndirEdgeMap(const UndirGraph &g) : Parent(g) {} - UndirEdgeMap(const UndirGraph &g, T t) : Parent(g, t) {} - }; - - template - class EdgeMap : public GraphMap { - typedef GraphMap Parent; - public: - - explicit EdgeMap(const UndirGraph &g) : Parent(g) {} - EdgeMap(const UndirGraph &g, T t) : Parent(g, t) {} - }; - - /// Is the Edge oriented "forward"? - - /// Returns whether the given directed edge is same orientation as - /// the corresponding undirected edge. - /// - /// \todo "What does the direction of an undirected edge mean?" - bool forward(Edge) const { return true; } - - /// Opposite node on an edge - - /// \return the opposite of the given Node on the given Edge - /// - /// \todo What should we do if given Node and Edge are not incident? - Node oppositeNode(Node, UndirEdge) const { return INVALID; } - - /// First node of the undirected edge. - - /// \return the first node of the given UndirEdge. - /// - /// Naturally undirectected edges don't have direction and thus - /// don't have source and target node. But we use these two methods - /// to query the two endnodes of the edge. The direction of the edge - /// which arises this way is called the inherent direction of the - /// undirected edge, and is used to define the "forward" direction - /// of the directed versions of the edges. - /// \sa forward - Node source(UndirEdge) const { return INVALID; } - - /// Second node of the undirected edge. - Node target(UndirEdge) const { return INVALID; } - - /// Source node of the directed edge. - Node source(Edge) const { return INVALID; } - - /// Target node of the directed edge. - Node target(Edge) const { return INVALID; } - - /// First node of the graph - - /// \note This method is part of so called \ref - /// developpers_interface "Developpers' interface", so it shouldn't - /// be used in an end-user program. - void first(Node&) const {} - /// Next node of the graph - - /// \note This method is part of so called \ref - /// developpers_interface "Developpers' interface", so it shouldn't - /// be used in an end-user program. - void next(Node&) const {} - - /// First undirected edge of the graph - - /// \note This method is part of so called \ref - /// developpers_interface "Developpers' interface", so it shouldn't - /// be used in an end-user program. - void first(UndirEdge&) const {} - /// Next undirected edge of the graph - - /// \note This method is part of so called \ref - /// developpers_interface "Developpers' interface", so it shouldn't - /// be used in an end-user program. - void next(UndirEdge&) const {} - - /// First directed edge of the graph - - /// \note This method is part of so called \ref - /// developpers_interface "Developpers' interface", so it shouldn't - /// be used in an end-user program. - void first(Edge&) const {} - /// Next directed edge of the graph - - /// \note This method is part of so called \ref - /// developpers_interface "Developpers' interface", so it shouldn't - /// be used in an end-user program. - void next(Edge&) const {} - - /// First outgoing edge from a given node - - /// \note This method is part of so called \ref - /// developpers_interface "Developpers' interface", so it shouldn't - /// be used in an end-user program. - void firstOut(Edge&, Node) const {} - /// Next outgoing edge to a node - - /// \note This method is part of so called \ref - /// developpers_interface "Developpers' interface", so it shouldn't - /// be used in an end-user program. - void nextOut(Edge&) const {} - - /// First incoming edge to a given node - - /// \note This method is part of so called \ref - /// developpers_interface "Developpers' interface", so it shouldn't - /// be used in an end-user program. - void firstIn(Edge&, Node) const {} - /// Next incoming edge to a node - - /// \note This method is part of so called \ref - /// developpers_interface "Developpers' interface", so it shouldn't - /// be used in an end-user program. - void nextIn(Edge&) const {} - - - /// Base node of the iterator - /// - /// Returns the base node (the source in this case) of the iterator - Node baseNode(OutEdgeIt e) const { - return source(e); - } - /// Running node of the iterator - /// - /// Returns the running node (the target in this case) of the - /// iterator - Node runningNode(OutEdgeIt e) const { - return target(e); - } - - /// Base node of the iterator - /// - /// Returns the base node (the target in this case) of the iterator - Node baseNode(InEdgeIt e) const { - return target(e); - } - /// Running node of the iterator - /// - /// Returns the running node (the source in this case) of the - /// iterator - Node runningNode(InEdgeIt e) const { - return source(e); - } - - /// Base node of the iterator - /// - /// Returns the base node of the iterator - Node baseNode(IncEdgeIt) const { - return INVALID; - } - /// Running node of the iterator - /// - /// Returns the running node of the iterator - Node runningNode(IncEdgeIt) const { - return INVALID; - } - - - template - struct Constraints { - void constraints() { - checkConcept(); - checkConcept(); - checkConcept(); - } - }; - - }; - - class ExtendableUndirGraph : public UndirGraph { - public: - - template - struct Constraints { - void constraints() { - checkConcept(); - checkConcept(); - checkConcept(); - - checkConcept(); - checkConcept(); - checkConcept(); - } - }; - - }; - - class ErasableUndirGraph : public ExtendableUndirGraph { - public: - - template - struct Constraints { - void constraints() { - checkConcept(); - checkConcept(); - } - }; - - }; - - /// @} - - } - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/concept_check.h --- a/src/lemon/concept_check.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -// -*- C++ -*- -// Modified for use in LEMON. -// We should really consider using Boost... - - -// -// (C) Copyright Jeremy Siek 2000. -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Revision History: -// 05 May 2001: Workarounds for HP aCC from Thomas Matelich. (Jeremy Siek) -// 02 April 2001: Removed limits header altogether. (Jeremy Siek) -// 01 April 2001: Modified to use new header. (JMaddock) -// - -// See http://www.boost.org/libs/concept_check for documentation. - -#ifndef LEMON_BOOST_CONCEPT_CHECKS_HPP -#define LEMON_BOOST_CONCEPT_CHECKS_HPP - -namespace lemon { - - /* - "inline" is used for ignore_unused_variable_warning() - and function_requires() to make sure there is no - overtarget with g++. - */ - - template inline void ignore_unused_variable_warning(const T&) { } - - template - inline void function_requires() - { -#if !defined(NDEBUG) - void (Concept::*x)() = & Concept::constraints; - ignore_unused_variable_warning(x); -#endif - } - - template - inline void checkConcept() { -#if !defined(NDEBUG) - typedef typename Concept::template Constraints ConceptCheck; - void (ConceptCheck::*x)() = & ConceptCheck::constraints; - ignore_unused_variable_warning(x); -#endif - } - -#define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ - typedef void (ns::concept ::* func##type_var##concept)(); \ - template \ - struct concept_checking_##type_var##concept { }; \ - typedef concept_checking_##type_var##concept< \ - BOOST_FPTR ns::concept::constraints> \ - concept_checking_typedef_##type_var##concept - -#define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \ - typedef void (ns::concept ::* \ - func##type_var1##type_var2##concept)(); \ - template \ - struct concept_checking_##type_var1##type_var2##concept { }; \ - typedef concept_checking_##type_var1##type_var2##concept< \ - BOOST_FPTR ns::concept::constraints> \ - concept_checking_typedef_##type_var1##type_var2##concept - -#define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \ - typedef void (ns::concept ::* \ - func##tv1##tv2##tv3##concept)(); \ - template \ - struct concept_checking_##tv1##tv2##tv3##concept { }; \ - typedef concept_checking_##tv1##tv2##tv3##concept< \ - BOOST_FPTR ns::concept::constraints> \ - concept_checking_typedef_##tv1##tv2##tv3##concept - -#define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \ - typedef void (ns::concept ::* \ - func##tv1##tv2##tv3##tv4##concept)(); \ - template \ - struct concept_checking_##tv1##tv2##tv3##tv4##concept { }; \ - typedef concept_checking_##tv1##tv2##tv3##tv4##concept< \ - BOOST_FPTR ns::concept::constraints> \ - concept_checking_typedef_##tv1##tv2##tv3##tv4##concept - - -} // namespace lemon - -#endif // LEMON_BOOST_CONCEPT_CHECKS_HPP diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/config.h.in --- a/src/lemon/config.h.in Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -/* Define to 1 if you have CPLEX. */ -#undef HAVE_CPLEX - -/* Define to 1 if you have GLPK. */ -#undef HAVE_GLPK diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/dfs.h --- a/src/lemon/dfs.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1136 +0,0 @@ -/* -*- C++ -*- - * src/lemon/dfs.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_DFS_H -#define LEMON_DFS_H - -///\ingroup flowalgs -///\file -///\brief Dfs algorithm. - -#include -#include -#include -#include -#include - -namespace lemon { - - - - ///Default traits class of Dfs class. - - ///Default traits class of Dfs class. - ///\param GR Graph type. - template - struct DfsDefaultTraits - { - ///The graph type the algorithm runs on. - typedef GR Graph; - ///\brief The type of the map that stores the last - ///edges of the %DFS paths. - /// - ///The type of the map that stores the last - ///edges of the %DFS paths. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef typename Graph::template NodeMap PredMap; - ///Instantiates a PredMap. - - ///This function instantiates a \ref PredMap. - ///\param G is the graph, to which we would like to define the PredMap. - ///\todo The graph alone may be insufficient to initialize - static PredMap *createPredMap(const GR &G) - { - return new PredMap(G); - } -// ///\brief The type of the map that stores the last but one -// ///nodes of the %DFS paths. -// /// -// ///The type of the map that stores the last but one -// ///nodes of the %DFS paths. -// ///It must meet the \ref concept::WriteMap "WriteMap" concept. -// /// -// typedef NullMap PredNodeMap; -// ///Instantiates a PredNodeMap. - -// ///This function instantiates a \ref PredNodeMap. -// ///\param G is the graph, to which -// ///we would like to define the \ref PredNodeMap -// static PredNodeMap *createPredNodeMap(const GR &G) -// { -// return new PredNodeMap(); -// } - - ///The type of the map that indicates which nodes are processed. - - ///The type of the map that indicates which nodes are processed. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - ///\todo named parameter to set this type, function to read and write. - typedef NullMap ProcessedMap; - ///Instantiates a ProcessedMap. - - ///This function instantiates a \ref ProcessedMap. - ///\param G is the graph, to which - ///we would like to define the \ref ProcessedMap - static ProcessedMap *createProcessedMap(const GR &) - { - return new ProcessedMap(); - } - ///The type of the map that indicates which nodes are reached. - - ///The type of the map that indicates which nodes are reached. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - ///\todo named parameter to set this type, function to read and write. - typedef typename Graph::template NodeMap ReachedMap; - ///Instantiates a ReachedMap. - - ///This function instantiates a \ref ReachedMap. - ///\param G is the graph, to which - ///we would like to define the \ref ReachedMap. - static ReachedMap *createReachedMap(const GR &G) - { - return new ReachedMap(G); - } - ///The type of the map that stores the dists of the nodes. - - ///The type of the map that stores the dists of the nodes. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef typename Graph::template NodeMap DistMap; - ///Instantiates a DistMap. - - ///This function instantiates a \ref DistMap. - ///\param G is the graph, to which we would like to define the \ref DistMap - static DistMap *createDistMap(const GR &G) - { - return new DistMap(G); - } - }; - - ///%DFS algorithm class. - - ///\ingroup flowalgs - ///This class provides an efficient implementation of the %DFS algorithm. - /// - ///\param GR The graph type the algorithm runs on. The default value is - ///\ref ListGraph. The value of GR is not used directly by Dfs, it - ///is only passed to \ref DfsDefaultTraits. - ///\param TR Traits class to set various data types used by the algorithm. - ///The default traits class is - ///\ref DfsDefaultTraits "DfsDefaultTraits". - ///See \ref DfsDefaultTraits for the documentation of - ///a Dfs traits class. - /// - ///\author Jacint Szabo and Alpar Juttner - ///\todo A compare object would be nice. - -#ifdef DOXYGEN - template -#else - template > -#endif - class Dfs { - public: - /** - * \brief \ref Exception for uninitialized parameters. - * - * This error represents problems in the initialization - * of the parameters of the algorithms. - */ - class UninitializedParameter : public lemon::UninitializedParameter { - public: - virtual const char* exceptionName() const { - return "lemon::Dfs::UninitializedParameter"; - } - }; - - typedef TR Traits; - ///The type of the underlying graph. - typedef typename TR::Graph Graph; - ///\e - typedef typename Graph::Node Node; - ///\e - typedef typename Graph::NodeIt NodeIt; - ///\e - typedef typename Graph::Edge Edge; - ///\e - typedef typename Graph::OutEdgeIt OutEdgeIt; - - ///\brief The type of the map that stores the last - ///edges of the %DFS paths. - typedef typename TR::PredMap PredMap; -// ///\brief The type of the map that stores the last but one -// ///nodes of the %DFS paths. -// typedef typename TR::PredNodeMap PredNodeMap; - ///The type of the map indicating which nodes are reached. - typedef typename TR::ReachedMap ReachedMap; - ///The type of the map indicating which nodes are processed. - typedef typename TR::ProcessedMap ProcessedMap; - ///The type of the map that stores the dists of the nodes. - typedef typename TR::DistMap DistMap; - private: - /// Pointer to the underlying graph. - const Graph *G; - ///Pointer to the map of predecessors edges. - PredMap *_pred; - ///Indicates if \ref _pred is locally allocated (\c true) or not. - bool local_pred; -// ///Pointer to the map of predecessors nodes. -// PredNodeMap *_predNode; -// ///Indicates if \ref _predNode is locally allocated (\c true) or not. -// bool local_predNode; - ///Pointer to the map of distances. - DistMap *_dist; - ///Indicates if \ref _dist is locally allocated (\c true) or not. - bool local_dist; - ///Pointer to the map of reached status of the nodes. - ReachedMap *_reached; - ///Indicates if \ref _reached is locally allocated (\c true) or not. - bool local_reached; - ///Pointer to the map of processed status of the nodes. - ProcessedMap *_processed; - ///Indicates if \ref _processed is locally allocated (\c true) or not. - bool local_processed; - - std::vector _stack; - int _stack_head; -// ///The source node of the last execution. -// Node source; - - ///Creates the maps if necessary. - - ///\todo Error if \c G are \c NULL. - ///\todo Better memory allocation (instead of new). - void create_maps() - { - if(!_pred) { - local_pred = true; - _pred = Traits::createPredMap(*G); - } -// if(!_predNode) { -// local_predNode = true; -// _predNode = Traits::createPredNodeMap(*G); -// } - if(!_dist) { - local_dist = true; - _dist = Traits::createDistMap(*G); - } - if(!_reached) { - local_reached = true; - _reached = Traits::createReachedMap(*G); - } - if(!_processed) { - local_processed = true; - _processed = Traits::createProcessedMap(*G); - } - } - - public : - - ///\name Named template parameters - - ///@{ - - template - struct DefPredMapTraits : public Traits { - typedef T PredMap; - static PredMap *createPredMap(const Graph &G) - { - throw UninitializedParameter(); - } - }; - ///\ref named-templ-param "Named parameter" for setting PredMap type - - ///\ref named-templ-param "Named parameter" for setting PredMap type - /// - template - class DefPredMap : public Dfs< Graph, - DefPredMapTraits > { }; - -// template -// struct DefPredNodeMapTraits : public Traits { -// typedef T PredNodeMap; -// static PredNodeMap *createPredNodeMap(const Graph &G) -// { -// throw UninitializedParameter(); -// } -// }; -// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type - -// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type -// /// -// template -// class DefPredNodeMap : public Dfs< Graph, -// LengthMap, -// DefPredNodeMapTraits > { }; - - template - struct DefDistMapTraits : public Traits { - typedef T DistMap; - static DistMap *createDistMap(const Graph &G) - { - throw UninitializedParameter(); - } - }; - ///\ref named-templ-param "Named parameter" for setting DistMap type - - ///\ref named-templ-param "Named parameter" for setting DistMap type - /// - template - class DefDistMap : public Dfs< Graph, - DefDistMapTraits > { }; - - template - struct DefReachedMapTraits : public Traits { - typedef T ReachedMap; - static ReachedMap *createReachedMap(const Graph &G) - { - throw UninitializedParameter(); - } - }; - ///\ref named-templ-param "Named parameter" for setting ReachedMap type - - ///\ref named-templ-param "Named parameter" for setting ReachedMap type - /// - template - class DefReachedMap : public Dfs< Graph, - DefReachedMapTraits > { }; - - struct DefGraphReachedMapTraits : public Traits { - typedef typename Graph::template NodeMap ReachedMap; - static ReachedMap *createReachedMap(const Graph &G) - { - return new ReachedMap(G); - } - }; - template - struct DefProcessedMapTraits : public Traits { - typedef T ProcessedMap; - static ProcessedMap *createProcessedMap(const Graph &G) - { - throw UninitializedParameter(); - } - }; - ///\ref named-templ-param "Named parameter" for setting ProcessedMap type - - ///\ref named-templ-param "Named parameter" for setting ProcessedMap type - /// - template - class DefProcessedMap : public Dfs< Graph, - DefProcessedMapTraits > { }; - - struct DefGraphProcessedMapTraits : public Traits { - typedef typename Graph::template NodeMap ProcessedMap; - static ProcessedMap *createProcessedMap(const Graph &G) - { - return new ProcessedMap(G); - } - }; - ///\brief \ref named-templ-param "Named parameter" - ///for setting the ProcessedMap type to be Graph::NodeMap. - /// - ///\ref named-templ-param "Named parameter" - ///for setting the ProcessedMap type to be Graph::NodeMap. - ///If you don't set it explicitely, it will be automatically allocated. - template - class DefProcessedMapToBeDefaultMap : - public Dfs< Graph, - DefGraphProcessedMapTraits> { }; - - ///@} - - public: - - ///Constructor. - - ///\param _G the graph the algorithm will run on. - /// - Dfs(const Graph& _G) : - G(&_G), - _pred(NULL), local_pred(false), -// _predNode(NULL), local_predNode(false), - _dist(NULL), local_dist(false), - _reached(NULL), local_reached(false), - _processed(NULL), local_processed(false) - { } - - ///Destructor. - ~Dfs() - { - if(local_pred) delete _pred; -// if(local_predNode) delete _predNode; - if(local_dist) delete _dist; - if(local_reached) delete _reached; - if(local_processed) delete _processed; - } - - ///Sets the map storing the predecessor edges. - - ///Sets the map storing the predecessor edges. - ///If you don't use this function before calling \ref run(), - ///it will allocate one. The destuctor deallocates this - ///automatically allocated map, of course. - ///\return (*this) - Dfs &predMap(PredMap &m) - { - if(local_pred) { - delete _pred; - local_pred=false; - } - _pred = &m; - return *this; - } - -// ///Sets the map storing the predecessor nodes. - -// ///Sets the map storing the predecessor nodes. -// ///If you don't use this function before calling \ref run(), -// ///it will allocate one. The destuctor deallocates this -// ///automatically allocated map, of course. -// ///\return (*this) -// Dfs &predNodeMap(PredNodeMap &m) -// { -// if(local_predNode) { -// delete _predNode; -// local_predNode=false; -// } -// _predNode = &m; -// return *this; -// } - - ///Sets the map storing the distances calculated by the algorithm. - - ///Sets the map storing the distances calculated by the algorithm. - ///If you don't use this function before calling \ref run(), - ///it will allocate one. The destuctor deallocates this - ///automatically allocated map, of course. - ///\return (*this) - Dfs &distMap(DistMap &m) - { - if(local_dist) { - delete _dist; - local_dist=false; - } - _dist = &m; - return *this; - } - - ///Sets the map indicating if a node is reached. - - ///Sets the map indicating if a node is reached. - ///If you don't use this function before calling \ref run(), - ///it will allocate one. The destuctor deallocates this - ///automatically allocated map, of course. - ///\return (*this) - Dfs &reachedMap(ReachedMap &m) - { - if(local_reached) { - delete _reached; - local_reached=false; - } - _reached = &m; - return *this; - } - - ///Sets the map indicating if a node is processed. - - ///Sets the map indicating if a node is processed. - ///If you don't use this function before calling \ref run(), - ///it will allocate one. The destuctor deallocates this - ///automatically allocated map, of course. - ///\return (*this) - Dfs &processedMap(ProcessedMap &m) - { - if(local_processed) { - delete _processed; - local_processed=false; - } - _processed = &m; - return *this; - } - - public: - ///\name Execution control - ///The simplest way to execute the algorithm is to use - ///one of the member functions called \c run(...). - ///\n - ///If you need more control on the execution, - ///first you must call \ref init(), then you can add several source nodes - ///with \ref addSource(). - ///Finally \ref start() will perform the actual path - ///computation. - - ///@{ - - ///Initializes the internal data structures. - - ///Initializes the internal data structures. - /// - void init() - { - create_maps(); - _stack.resize(countNodes(*G)); - _stack_head=-1; - for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { - _pred->set(u,INVALID); - // _predNode->set(u,INVALID); - _reached->set(u,false); - _processed->set(u,false); - } - } - - ///Adds a new source node. - - ///Adds a new source node to the set of nodes to be processed. - /// - ///\bug dist's are wrong (or at least strange) in case of multiple sources. - void addSource(Node s) - { - if(!(*_reached)[s]) - { - _reached->set(s,true); - _pred->set(s,INVALID); - // _predNode->set(u,INVALID); - _stack[++_stack_head]=OutEdgeIt(*G,s); - _dist->set(s,_stack_head); - } - } - - ///Processes the next node. - - ///Processes the next node. - /// - ///\warning The stack must not be empty! - void processNextEdge() - { - Node m; - Edge e=_stack[_stack_head]; - if(!(*_reached)[m=G->target(e)]) { - _pred->set(m,e); - _reached->set(m,true); - // _pred_node->set(m,G->source(e)); - ++_stack_head; - _stack[_stack_head] = OutEdgeIt(*G, m); - _dist->set(m,_stack_head); - } - else { - Node n; - while(_stack_head>=0 && - (n=G->source(_stack[_stack_head]), - ++_stack[_stack_head]==INVALID)) - { - _processed->set(n,true); - --_stack_head; - } - } - } - - ///\brief Returns \c false if there are nodes - ///to be processed in the queue - /// - ///Returns \c false if there are nodes - ///to be processed in the queue - bool emptyQueue() { return _stack_head<0; } - ///Returns the number of the nodes to be processed. - - ///Returns the number of the nodes to be processed in the queue. - /// - int queueSize() { return _stack_head+1; } - - ///Executes the algorithm. - - ///Executes the algorithm. - /// - ///\pre init() must be called and at least one node should be added - ///with addSource() before using this function. - /// - ///This method runs the %DFS algorithm from the root node(s) - ///in order to - ///compute the - ///%DFS path to each node. The algorithm computes - ///- The %DFS tree. - ///- The distance of each node from the root(s). - /// - void start() - { - while ( !emptyQueue() ) processNextEdge(); - } - - ///Executes the algorithm until \c dest is reached. - - ///Executes the algorithm until \c dest is reached. - /// - ///\pre init() must be called and at least one node should be added - ///with addSource() before using this function. - /// - ///This method runs the %DFS algorithm from the root node(s) - ///in order to - ///compute the - ///%DFS path to \c dest. The algorithm computes - ///- The %DFS path to \c dest. - ///- The distance of \c dest from the root(s). - /// - void start(Node dest) - { - while ( !emptyQueue() && G->target(_stack[_stack_head])!=dest ) - processNextEdge(); - } - - ///Executes the algorithm until a condition is met. - - ///Executes the algorithm until a condition is met. - /// - ///\pre init() must be called and at least one node should be added - ///with addSource() before using this function. - /// - ///\param nm must be a bool (or convertible) edge map. The algorithm - ///will stop when it reaches a edge \c v with nm[v]==true. - ///\warning Contrary to \ref Dfs and \ref Dijkstra, \c mn is an edge map, - ///not a node map. - template - void start(const NM &nm) - { - while ( !emptyQueue() && !nm[_stack[_stack_head]] ) processNextEdge(); - } - - ///Runs %DFS algorithm from node \c s. - - ///This method runs the %DFS algorithm from a root node \c s - ///in order to - ///compute the - ///%DFS path to each node. The algorithm computes - ///- The %DFS tree. - ///- The distance of each node from the root. - /// - ///\note d.run(s) is just a shortcut of the following code. - ///\code - /// d.init(); - /// d.addSource(s); - /// d.start(); - ///\endcode - void run(Node s) { - init(); - addSource(s); - start(); - } - - ///Finds the %DFS path between \c s and \c t. - - ///Finds the %DFS path between \c s and \c t. - /// - ///\return The length of the %DFS s---t path if there exists one, - ///0 otherwise. - ///\note Apart from the return value, d.run(s) is - ///just a shortcut of the following code. - ///\code - /// d.init(); - /// d.addSource(s); - /// d.start(t); - ///\endcode - int run(Node s,Node t) { - init(); - addSource(s); - start(t); - return reached(t)?_stack_head+1:0; - } - - ///@} - - ///\name Query Functions - ///The result of the %DFS algorithm can be obtained using these - ///functions.\n - ///Before the use of these functions, - ///either run() or start() must be called. - - ///@{ - - ///Copies the path to \c t on the DFS tree into \c p - - ///This function copies the path on the DFS tree to \c t into \c p. - ///If it \c \t is a source itself or unreachable, then it does not - ///alter \c p. - ///\todo Is it the right way to handle unreachable nodes? - ///\return Returns \c true if a path to \c t was actually copied to \c p, - ///\c false otherwise. - ///\sa DirPath - template - bool getPath(P &p,Node t) - { - if(reached(t)) { - p.clear(); - typename P::Builder b(p); - for(b.setStartNode(t);pred(t)!=INVALID;t=predNode(t)) - b.pushFront(pred(t)); - b.commit(); - return true; - } - return false; - } - - ///The distance of a node from the root(s). - - ///Returns the distance of a node from the root(s). - ///\pre \ref run() must be called before using this function. - ///\warning If node \c v in unreachable from the root(s) the return value - ///of this funcion is undefined. - int dist(Node v) const { return (*_dist)[v]; } - - ///Returns the 'previous edge' of the %DFS tree. - - ///For a node \c v it returns the 'previous edge' - ///of the %DFS path, - ///i.e. it returns the last edge of a %DFS path from the root(s) to \c - ///v. It is \ref INVALID - ///if \c v is unreachable from the root(s) or \c v is a root. The - ///%DFS tree used here is equal to the %DFS tree used in - ///\ref predNode(Node v). - ///\pre Either \ref run() or \ref start() must be called before using - ///this function. - ///\todo predEdge could be a better name. - Edge pred(Node v) const { return (*_pred)[v];} - - ///Returns the 'previous node' of the %DFS tree. - - ///For a node \c v it returns the 'previous node' - ///of the %DFS tree, - ///i.e. it returns the last but one node from a %DFS path from the - ///root(a) to \c /v. - ///It is INVALID if \c v is unreachable from the root(s) or - ///if \c v itself a root. - ///The %DFS tree used here is equal to the %DFS - ///tree used in \ref pred(Node v). - ///\pre Either \ref run() or \ref start() must be called before - ///using this function. - Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID: - G->source((*_pred)[v]); } - - ///Returns a reference to the NodeMap of distances. - - ///Returns a reference to the NodeMap of distances. - ///\pre Either \ref run() or \ref init() must - ///be called before using this function. - const DistMap &distMap() const { return *_dist;} - - ///Returns a reference to the %DFS edge-tree map. - - ///Returns a reference to the NodeMap of the edges of the - ///%DFS tree. - ///\pre Either \ref run() or \ref init() - ///must be called before using this function. - const PredMap &predMap() const { return *_pred;} - -// ///Returns a reference to the map of nodes of %DFS paths. - -// ///Returns a reference to the NodeMap of the last but one nodes of the -// ///%DFS tree. -// ///\pre \ref run() must be called before using this function. -// const PredNodeMap &predNodeMap() const { return *_predNode;} - - ///Checks if a node is reachable from the root. - - ///Returns \c true if \c v is reachable from the root. - ///\warning The source nodes are inditated as unreached. - ///\pre Either \ref run() or \ref start() - ///must be called before using this function. - /// - bool reached(Node v) { return (*_reached)[v]; } - - ///@} - }; - - ///Default traits class of Dfs function. - - ///Default traits class of Dfs function. - ///\param GR Graph type. - template - struct DfsWizardDefaultTraits - { - ///The graph type the algorithm runs on. - typedef GR Graph; - ///\brief The type of the map that stores the last - ///edges of the %DFS paths. - /// - ///The type of the map that stores the last - ///edges of the %DFS paths. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef NullMap PredMap; - ///Instantiates a PredMap. - - ///This function instantiates a \ref PredMap. - ///\param G is the graph, to which we would like to define the PredMap. - ///\todo The graph alone may be insufficient to initialize - static PredMap *createPredMap(const GR &) - { - return new PredMap(); - } -// ///\brief The type of the map that stores the last but one -// ///nodes of the %DFS paths. -// /// -// ///The type of the map that stores the last but one -// ///nodes of the %DFS paths. -// ///It must meet the \ref concept::WriteMap "WriteMap" concept. -// /// -// typedef NullMap PredNodeMap; -// ///Instantiates a PredNodeMap. - -// ///This function instantiates a \ref PredNodeMap. -// ///\param G is the graph, to which -// ///we would like to define the \ref PredNodeMap -// static PredNodeMap *createPredNodeMap(const GR &G) -// { -// return new PredNodeMap(); -// } - - ///The type of the map that indicates which nodes are processed. - - ///The type of the map that indicates which nodes are processed. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - ///\todo named parameter to set this type, function to read and write. - typedef NullMap ProcessedMap; - ///Instantiates a ProcessedMap. - - ///This function instantiates a \ref ProcessedMap. - ///\param G is the graph, to which - ///we would like to define the \ref ProcessedMap - static ProcessedMap *createProcessedMap(const GR &) - { - return new ProcessedMap(); - } - ///The type of the map that indicates which nodes are reached. - - ///The type of the map that indicates which nodes are reached. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - ///\todo named parameter to set this type, function to read and write. - typedef typename Graph::template NodeMap ReachedMap; - ///Instantiates a ReachedMap. - - ///This function instantiates a \ref ReachedMap. - ///\param G is the graph, to which - ///we would like to define the \ref ReachedMap. - static ReachedMap *createReachedMap(const GR &G) - { - return new ReachedMap(G); - } - ///The type of the map that stores the dists of the nodes. - - ///The type of the map that stores the dists of the nodes. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef NullMap DistMap; - ///Instantiates a DistMap. - - ///This function instantiates a \ref DistMap. - ///\param G is the graph, to which we would like to define the \ref DistMap - static DistMap *createDistMap(const GR &) - { - return new DistMap(); - } - }; - - /// Default traits used by \ref DfsWizard - - /// To make it easier to use Dfs algorithm - ///we have created a wizard class. - /// This \ref DfsWizard class needs default traits, - ///as well as the \ref Dfs class. - /// The \ref DfsWizardBase is a class to be the default traits of the - /// \ref DfsWizard class. - template - class DfsWizardBase : public DfsWizardDefaultTraits - { - - typedef DfsWizardDefaultTraits Base; - protected: - /// Type of the nodes in the graph. - typedef typename Base::Graph::Node Node; - - /// Pointer to the underlying graph. - void *_g; - ///Pointer to the map of reached nodes. - void *_reached; - ///Pointer to the map of processed nodes. - void *_processed; - ///Pointer to the map of predecessors edges. - void *_pred; -// ///Pointer to the map of predecessors nodes. -// void *_predNode; - ///Pointer to the map of distances. - void *_dist; - ///Pointer to the source node. - Node _source; - - public: - /// Constructor. - - /// This constructor does not require parameters, therefore it initiates - /// all of the attributes to default values (0, INVALID). - DfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), -// _predNode(0), - _dist(0), _source(INVALID) {} - - /// Constructor. - - /// This constructor requires some parameters, - /// listed in the parameters list. - /// Others are initiated to 0. - /// \param g is the initial value of \ref _g - /// \param s is the initial value of \ref _source - DfsWizardBase(const GR &g, Node s=INVALID) : - _g((void *)&g), _reached(0), _processed(0), _pred(0), -// _predNode(0), - _dist(0), _source(s) {} - - }; - - /// A class to make the usage of Dfs algorithm easier - - /// This class is created to make it easier to use Dfs algorithm. - /// It uses the functions and features of the plain \ref Dfs, - /// but it is much simpler to use it. - /// - /// Simplicity means that the way to change the types defined - /// in the traits class is based on functions that returns the new class - /// and not on templatable built-in classes. - /// When using the plain \ref Dfs - /// the new class with the modified type comes from - /// the original class by using the :: - /// operator. In the case of \ref DfsWizard only - /// a function have to be called and it will - /// return the needed class. - /// - /// It does not have own \ref run method. When its \ref run method is called - /// it initiates a plain \ref Dfs class, and calls the \ref Dfs::run - /// method of it. - template - class DfsWizard : public TR - { - typedef TR Base; - - ///The type of the underlying graph. - typedef typename TR::Graph Graph; - //\e - typedef typename Graph::Node Node; - //\e - typedef typename Graph::NodeIt NodeIt; - //\e - typedef typename Graph::Edge Edge; - //\e - typedef typename Graph::OutEdgeIt OutEdgeIt; - - ///\brief The type of the map that stores - ///the reached nodes - typedef typename TR::ReachedMap ReachedMap; - ///\brief The type of the map that stores - ///the processed nodes - typedef typename TR::ProcessedMap ProcessedMap; - ///\brief The type of the map that stores the last - ///edges of the %DFS paths. - typedef typename TR::PredMap PredMap; -// ///\brief The type of the map that stores the last but one -// ///nodes of the %DFS paths. -// typedef typename TR::PredNodeMap PredNodeMap; - ///The type of the map that stores the dists of the nodes. - typedef typename TR::DistMap DistMap; - -public: - /// Constructor. - DfsWizard() : TR() {} - - /// Constructor that requires parameters. - - /// Constructor that requires parameters. - /// These parameters will be the default values for the traits class. - DfsWizard(const Graph &g, Node s=INVALID) : - TR(g,s) {} - - ///Copy constructor - DfsWizard(const TR &b) : TR(b) {} - - ~DfsWizard() {} - - ///Runs Dfs algorithm from a given node. - - ///Runs Dfs algorithm from a given node. - ///The node can be given by the \ref source function. - void run() - { - if(Base::_source==INVALID) throw UninitializedParameter(); - Dfs alg(*(Graph*)Base::_g); - if(Base::_reached) alg.reachedMap(*(ReachedMap*)Base::_reached); - if(Base::_processed) alg.processedMap(*(ProcessedMap*)Base::_processed); - if(Base::_pred) alg.predMap(*(PredMap*)Base::_pred); -// if(Base::_predNode) alg.predNodeMap(*(PredNodeMap*)Base::_predNode); - if(Base::_dist) alg.distMap(*(DistMap*)Base::_dist); - alg.run(Base::_source); - } - - ///Runs Dfs algorithm from the given node. - - ///Runs Dfs algorithm from the given node. - ///\param s is the given source. - void run(Node s) - { - Base::_source=s; - run(); - } - - template - struct DefPredMapBase : public Base { - typedef T PredMap; - static PredMap *createPredMap(const Graph &) { return 0; }; - DefPredMapBase(const TR &b) : TR(b) {} - }; - - ///\brief \ref named-templ-param "Named parameter" - ///function for setting PredMap type - /// - /// \ref named-templ-param "Named parameter" - ///function for setting PredMap type - /// - template - DfsWizard > predMap(const T &t) - { - Base::_pred=(void *)&t; - return DfsWizard >(*this); - } - - - template - struct DefReachedMapBase : public Base { - typedef T ReachedMap; - static ReachedMap *createReachedMap(const Graph &) { return 0; }; - DefReachedMapBase(const TR &b) : TR(b) {} - }; - - ///\brief \ref named-templ-param "Named parameter" - ///function for setting ReachedMap - /// - /// \ref named-templ-param "Named parameter" - ///function for setting ReachedMap - /// - template - DfsWizard > reachedMap(const T &t) - { - Base::_pred=(void *)&t; - return DfsWizard >(*this); - } - - - template - struct DefProcessedMapBase : public Base { - typedef T ProcessedMap; - static ProcessedMap *createProcessedMap(const Graph &) { return 0; }; - DefProcessedMapBase(const TR &b) : TR(b) {} - }; - - ///\brief \ref named-templ-param "Named parameter" - ///function for setting ProcessedMap - /// - /// \ref named-templ-param "Named parameter" - ///function for setting ProcessedMap - /// - template - DfsWizard > processedMap(const T &t) - { - Base::_pred=(void *)&t; - return DfsWizard >(*this); - } - - -// template -// struct DefPredNodeMapBase : public Base { -// typedef T PredNodeMap; -// static PredNodeMap *createPredNodeMap(const Graph &G) { return 0; }; -// DefPredNodeMapBase(const TR &b) : TR(b) {} -// }; - -// ///\brief \ref named-templ-param "Named parameter" -// ///function for setting PredNodeMap type -// /// -// /// \ref named-templ-param "Named parameter" -// ///function for setting PredNodeMap type -// /// -// template -// DfsWizard > predNodeMap(const T &t) -// { -// Base::_predNode=(void *)&t; -// return DfsWizard >(*this); -// } - - template - struct DefDistMapBase : public Base { - typedef T DistMap; - static DistMap *createDistMap(const Graph &) { return 0; }; - DefDistMapBase(const TR &b) : TR(b) {} - }; - - ///\brief \ref named-templ-param "Named parameter" - ///function for setting DistMap type - /// - /// \ref named-templ-param "Named parameter" - ///function for setting DistMap type - /// - template - DfsWizard > distMap(const T &t) - { - Base::_dist=(void *)&t; - return DfsWizard >(*this); - } - - /// Sets the source node, from which the Dfs algorithm runs. - - /// Sets the source node, from which the Dfs algorithm runs. - /// \param s is the source node. - DfsWizard &source(Node s) - { - Base::_source=s; - return *this; - } - - }; - - ///Function type interface for Dfs algorithm. - - /// \ingroup flowalgs - ///Function type interface for Dfs algorithm. - /// - ///This function also has several - ///\ref named-templ-func-param "named parameters", - ///they are declared as the members of class \ref DfsWizard. - ///The following - ///example shows how to use these parameters. - ///\code - /// dfs(g,source).predMap(preds).run(); - ///\endcode - ///\warning Don't forget to put the \ref DfsWizard::run() "run()" - ///to the end of the parameter list. - ///\sa DfsWizard - ///\sa Dfs - template - DfsWizard > - dfs(const GR &g,typename GR::Node s=INVALID) - { - return DfsWizard >(g,s); - } - -} //END OF NAMESPACE LEMON - -#endif - diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/dijkstra.h --- a/src/lemon/dijkstra.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1074 +0,0 @@ -/* -*- C++ -*- - * src/lemon/dijkstra.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_DIJKSTRA_H -#define LEMON_DIJKSTRA_H - -///\ingroup flowalgs -///\file -///\brief Dijkstra algorithm. -/// -///\todo getPath() should be implemented! (also for BFS and DFS) - -#include -#include -#include -#include -#include - -namespace lemon { - - - - ///Default traits class of Dijkstra class. - - ///Default traits class of Dijkstra class. - ///\param GR Graph type. - ///\param LM Type of length map. - template - struct DijkstraDefaultTraits - { - ///The graph type the algorithm runs on. - typedef GR Graph; - ///The type of the map that stores the edge lengths. - - ///The type of the map that stores the edge lengths. - ///It must meet the \ref concept::ReadMap "ReadMap" concept. - typedef LM LengthMap; - //The type of the length of the edges. - typedef typename LM::Value Value; - ///The heap type used by Dijkstra algorithm. - - ///The heap type used by Dijkstra algorithm. - /// - ///\sa BinHeap - ///\sa Dijkstra - typedef BinHeap, - std::less > Heap; - - ///\brief The type of the map that stores the last - ///edges of the shortest paths. - /// - ///The type of the map that stores the last - ///edges of the shortest paths. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef typename Graph::template NodeMap PredMap; - ///Instantiates a PredMap. - - ///This function instantiates a \ref PredMap. - ///\param G is the graph, to which we would like to define the PredMap. - ///\todo The graph alone may be insufficient for the initialization - static PredMap *createPredMap(const GR &G) - { - return new PredMap(G); - } -// ///\brief The type of the map that stores the last but one -// ///nodes of the shortest paths. -// /// -// ///The type of the map that stores the last but one -// ///nodes of the shortest paths. -// ///It must meet the \ref concept::WriteMap "WriteMap" concept. -// /// -// typedef NullMap PredNodeMap; -// ///Instantiates a PredNodeMap. - -// ///This function instantiates a \ref PredNodeMap. -// ///\param G is the graph, to which -// ///we would like to define the \ref PredNodeMap -// static PredNodeMap *createPredNodeMap(const GR &G) -// { -// return new PredNodeMap(); -// } - - ///The type of the map that stores whether a nodes is processed. - - ///The type of the map that stores whether a nodes is processed. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - ///By default it is a NullMap. - ///\todo If it is set to a real map, - ///Dijkstra::processed() should read this. - ///\todo named parameter to set this type, function to read and write. - typedef NullMap ProcessedMap; - ///Instantiates a ProcessedMap. - - ///This function instantiates a \ref ProcessedMap. - ///\param G is the graph, to which - ///we would like to define the \ref ProcessedMap - static ProcessedMap *createProcessedMap(const GR &) - { - return new ProcessedMap(); - } - ///The type of the map that stores the dists of the nodes. - - ///The type of the map that stores the dists of the nodes. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef typename Graph::template NodeMap DistMap; - ///Instantiates a DistMap. - - ///This function instantiates a \ref DistMap. - ///\param G is the graph, to which we would like to define the \ref DistMap - static DistMap *createDistMap(const GR &G) - { - return new DistMap(G); - } - }; - - ///%Dijkstra algorithm class. - - /// \ingroup flowalgs - ///This class provides an efficient implementation of %Dijkstra algorithm. - ///The edge lengths are passed to the algorithm using a - ///\ref concept::ReadMap "ReadMap", - ///so it is easy to change it to any kind of length. - /// - ///The type of the length is determined by the - ///\ref concept::ReadMap::Value "Value" of the length map. - /// - ///It is also possible to change the underlying priority heap. - /// - ///\param GR The graph type the algorithm runs on. The default value - ///is \ref ListGraph. The value of GR is not used directly by - ///Dijkstra, it is only passed to \ref DijkstraDefaultTraits. - ///\param LM This read-only EdgeMap determines the lengths of the - ///edges. It is read once for each edge, so the map may involve in - ///relatively time consuming process to compute the edge length if - ///it is necessary. The default map type is \ref - ///concept::StaticGraph::EdgeMap "Graph::EdgeMap". The value - ///of LM is not used directly by Dijkstra, it is only passed to \ref - ///DijkstraDefaultTraits. \param TR Traits class to set - ///various data types used by the algorithm. The default traits - ///class is \ref DijkstraDefaultTraits - ///"DijkstraDefaultTraits". See \ref - ///DijkstraDefaultTraits for the documentation of a Dijkstra traits - ///class. - /// - ///\author Jacint Szabo and Alpar Juttner - ///\todo A compare object would be nice. - -#ifdef DOXYGEN - template -#else - template , - typename TR=DijkstraDefaultTraits > -#endif - class Dijkstra { - public: - /** - * \brief \ref Exception for uninitialized parameters. - * - * This error represents problems in the initialization - * of the parameters of the algorithms. - */ - class UninitializedParameter : public lemon::UninitializedParameter { - public: - virtual const char* exceptionName() const { - return "lemon::Dijkstra::UninitializedParameter"; - } - }; - - typedef TR Traits; - ///The type of the underlying graph. - typedef typename TR::Graph Graph; - ///\e - typedef typename Graph::Node Node; - ///\e - typedef typename Graph::NodeIt NodeIt; - ///\e - typedef typename Graph::Edge Edge; - ///\e - typedef typename Graph::OutEdgeIt OutEdgeIt; - - ///The type of the length of the edges. - typedef typename TR::LengthMap::Value Value; - ///The type of the map that stores the edge lengths. - typedef typename TR::LengthMap LengthMap; - ///\brief The type of the map that stores the last - ///edges of the shortest paths. - typedef typename TR::PredMap PredMap; -// ///\brief The type of the map that stores the last but one -// ///nodes of the shortest paths. -// typedef typename TR::PredNodeMap PredNodeMap; - ///The type of the map indicating if a node is processed. - typedef typename TR::ProcessedMap ProcessedMap; - ///The type of the map that stores the dists of the nodes. - typedef typename TR::DistMap DistMap; - ///The heap type used by the dijkstra algorithm. - typedef typename TR::Heap Heap; - private: - /// Pointer to the underlying graph. - const Graph *G; - /// Pointer to the length map - const LengthMap *length; - ///Pointer to the map of predecessors edges. - PredMap *_pred; - ///Indicates if \ref _pred is locally allocated (\c true) or not. - bool local_pred; -// ///Pointer to the map of predecessors nodes. -// PredNodeMap *_predNode; -// ///Indicates if \ref _predNode is locally allocated (\c true) or not. -// bool local_predNode; - ///Pointer to the map of distances. - DistMap *_dist; - ///Indicates if \ref _dist is locally allocated (\c true) or not. - bool local_dist; - ///Pointer to the map of processed status of the nodes. - ProcessedMap *_processed; - ///Indicates if \ref _processed is locally allocated (\c true) or not. - bool local_processed; - -// ///The source node of the last execution. -// Node source; - - ///Creates the maps if necessary. - - ///\todo Error if \c G or are \c NULL. What about \c length? - ///\todo Better memory allocation (instead of new). - void create_maps() - { - if(!_pred) { - local_pred = true; - _pred = Traits::createPredMap(*G); - } -// if(!_predNode) { -// local_predNode = true; -// _predNode = Traits::createPredNodeMap(*G); -// } - if(!_dist) { - local_dist = true; - _dist = Traits::createDistMap(*G); - } - if(!_processed) { - local_processed = true; - _processed = Traits::createProcessedMap(*G); - } - } - - public : - - ///\name Named template parameters - - ///@{ - - template - struct DefPredMapTraits : public Traits { - typedef T PredMap; - static PredMap *createPredMap(const Graph &G) - { - throw UninitializedParameter(); - } - }; - ///\ref named-templ-param "Named parameter" for setting PredMap type - - ///\ref named-templ-param "Named parameter" for setting PredMap type - /// - template - class DefPredMap : public Dijkstra< Graph, - LengthMap, - DefPredMapTraits > { }; - -// template -// struct DefPredNodeMapTraits : public Traits { -// typedef T PredNodeMap; -// static PredNodeMap *createPredNodeMap(const Graph &G) -// { -// throw UninitializedParameter(); -// } -// }; -// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type - -// ///\ref named-templ-param "Named parameter" for setting PredNodeMap type -// /// -// template -// class DefPredNodeMap : public Dijkstra< Graph, -// LengthMap, -// DefPredNodeMapTraits > { }; - - template - struct DefDistMapTraits : public Traits { - typedef T DistMap; - static DistMap *createDistMap(const Graph &G) - { - throw UninitializedParameter(); - } - }; - ///\ref named-templ-param "Named parameter" for setting DistMap type - - ///\ref named-templ-param "Named parameter" for setting DistMap type - /// - template - class DefDistMap : public Dijkstra< Graph, - LengthMap, - DefDistMapTraits > { }; - - template - struct DefProcessedMapTraits : public Traits { - typedef T ProcessedMap; - static ProcessedMap *createProcessedMap(const Graph &G) - { - throw UninitializedParameter(); - } - }; - ///\ref named-templ-param "Named parameter" for setting ProcessedMap type - - ///\ref named-templ-param "Named parameter" for setting ProcessedMap type - /// - template - class DefProcessedMap : public Dijkstra< Graph, - LengthMap, - DefProcessedMapTraits > { }; - - struct DefGraphProcessedMapTraits : public Traits { - typedef typename Graph::template NodeMap ProcessedMap; - static ProcessedMap *createProcessedMap(const Graph &G) - { - return new ProcessedMap(G); - } - }; - ///\brief \ref named-templ-param "Named parameter" - ///for setting the ProcessedMap type to be Graph::NodeMap. - /// - ///\ref named-templ-param "Named parameter" - ///for setting the ProcessedMap type to be Graph::NodeMap. - ///If you don't set it explicitely, it will be automatically allocated. - template - class DefProcessedMapToBeDefaultMap : - public Dijkstra< Graph, - LengthMap, - DefGraphProcessedMapTraits> { }; - - ///@} - - - private: - typename Graph::template NodeMap _heap_map; - Heap _heap; - public: - - ///Constructor. - - ///\param _G the graph the algorithm will run on. - ///\param _length the length map used by the algorithm. - Dijkstra(const Graph& _G, const LengthMap& _length) : - G(&_G), length(&_length), - _pred(NULL), local_pred(false), -// _predNode(NULL), local_predNode(false), - _dist(NULL), local_dist(false), - _processed(NULL), local_processed(false), - _heap_map(*G,-1),_heap(_heap_map) - { } - - ///Destructor. - ~Dijkstra() - { - if(local_pred) delete _pred; -// if(local_predNode) delete _predNode; - if(local_dist) delete _dist; - if(local_processed) delete _processed; - } - - ///Sets the length map. - - ///Sets the length map. - ///\return (*this) - Dijkstra &lengthMap(const LengthMap &m) - { - length = &m; - return *this; - } - - ///Sets the map storing the predecessor edges. - - ///Sets the map storing the predecessor edges. - ///If you don't use this function before calling \ref run(), - ///it will allocate one. The destuctor deallocates this - ///automatically allocated map, of course. - ///\return (*this) - Dijkstra &predMap(PredMap &m) - { - if(local_pred) { - delete _pred; - local_pred=false; - } - _pred = &m; - return *this; - } - -// ///Sets the map storing the predecessor nodes. - -// ///Sets the map storing the predecessor nodes. -// ///If you don't use this function before calling \ref run(), -// ///it will allocate one. The destuctor deallocates this -// ///automatically allocated map, of course. -// ///\return (*this) -// Dijkstra &predNodeMap(PredNodeMap &m) -// { -// if(local_predNode) { -// delete _predNode; -// local_predNode=false; -// } -// _predNode = &m; -// return *this; -// } - - ///Sets the map storing the distances calculated by the algorithm. - - ///Sets the map storing the distances calculated by the algorithm. - ///If you don't use this function before calling \ref run(), - ///it will allocate one. The destuctor deallocates this - ///automatically allocated map, of course. - ///\return (*this) - Dijkstra &distMap(DistMap &m) - { - if(local_dist) { - delete _dist; - local_dist=false; - } - _dist = &m; - return *this; - } - - private: - void finalizeNodeData(Node v,Value dst) - { - _processed->set(v,true); - _dist->set(v, dst); -// if((*_pred)[v]!=INVALID) -// _predNode->set(v,G->source((*_pred)[v])); ///\todo What to do? - } - - public: - ///\name Execution control - ///The simplest way to execute the algorithm is to use - ///one of the member functions called \c run(...). - ///\n - ///If you need more control on the execution, - ///first you must call \ref init(), then you can add several source nodes - ///with \ref addSource(). - ///Finally \ref start() will perform the actual path - ///computation. - - ///@{ - - ///Initializes the internal data structures. - - ///Initializes the internal data structures. - /// - ///\todo _heap_map's type could also be in the traits class. - ///\todo The heaps should be able to make themselves empty directly. - void init() - { - create_maps(); - while(!_heap.empty()) _heap.pop(); - for ( NodeIt u(*G) ; u!=INVALID ; ++u ) { - _pred->set(u,INVALID); -// _predNode->set(u,INVALID); - _processed->set(u,false); - _heap_map.set(u,Heap::PRE_HEAP); - } - } - - ///Adds a new source node. - - ///Adds a new source node to the priority heap. - /// - ///The optional second parameter is the initial distance of the node. - /// - ///It checks if the node has already been added to the heap and - ///It is pushed to the heap only if either it was not in the heap - ///or the shortest path found till then is longer then \c dst. - void addSource(Node s,Value dst=0) - { -// source = s; - if(_heap.state(s) != Heap::IN_HEAP) _heap.push(s,dst); - else if(_heap[s]set(s,INVALID); - } - } - - ///Processes the next node in the priority heap - - ///Processes the next node in the priority heap. - /// - ///\warning The priority heap must not be empty! - void processNextNode() - { - Node v=_heap.top(); - Value oldvalue=_heap[v]; - _heap.pop(); - finalizeNodeData(v,oldvalue); - - for(OutEdgeIt e(*G,v); e!=INVALID; ++e) { - Node w=G->target(e); - switch(_heap.state(w)) { - case Heap::PRE_HEAP: - _heap.push(w,oldvalue+(*length)[e]); - _pred->set(w,e); -// _predNode->set(w,v); - break; - case Heap::IN_HEAP: - if ( oldvalue+(*length)[e] < _heap[w] ) { - _heap.decrease(w, oldvalue+(*length)[e]); - _pred->set(w,e); -// _predNode->set(w,v); - } - break; - case Heap::POST_HEAP: - break; - } - } - } - - ///\brief Returns \c false if there are nodes - ///to be processed in the priority heap - /// - ///Returns \c false if there are nodes - ///to be processed in the priority heap - bool emptyQueue() { return _heap.empty(); } - ///Returns the number of the nodes to be processed in the priority heap - - ///Returns the number of the nodes to be processed in the priority heap - /// - int queueSize() { return _heap.size(); } - - ///Executes the algorithm. - - ///Executes the algorithm. - /// - ///\pre init() must be called and at least one node should be added - ///with addSource() before using this function. - /// - ///This method runs the %Dijkstra algorithm from the root node(s) - ///in order to - ///compute the - ///shortest path to each node. The algorithm computes - ///- The shortest path tree. - ///- The distance of each node from the root(s). - /// - void start() - { - while ( !_heap.empty() ) processNextNode(); - } - - ///Executes the algorithm until \c dest is reached. - - ///Executes the algorithm until \c dest is reached. - /// - ///\pre init() must be called and at least one node should be added - ///with addSource() before using this function. - /// - ///This method runs the %Dijkstra algorithm from the root node(s) - ///in order to - ///compute the - ///shortest path to \c dest. The algorithm computes - ///- The shortest path to \c dest. - ///- The distance of \c dest from the root(s). - /// - void start(Node dest) - { - while ( !_heap.empty() && _heap.top()!=dest ) processNextNode(); - if ( !_heap.empty() ) finalizeNodeData(_heap.top(),_heap.prio()); - } - - ///Executes the algorithm until a condition is met. - - ///Executes the algorithm until a condition is met. - /// - ///\pre init() must be called and at least one node should be added - ///with addSource() before using this function. - /// - ///\param nm must be a bool (or convertible) node map. The algorithm - ///will stop when it reaches a node \c v with nm[v]==true. - template - void start(const NodeBoolMap &nm) - { - while ( !_heap.empty() && !nm[_heap.top()] ) processNextNode(); - if ( !_heap.empty() ) finalizeNodeData(_heap.top(),_heap.prio()); - } - - ///Runs %Dijkstra algorithm from node \c s. - - ///This method runs the %Dijkstra algorithm from a root node \c s - ///in order to - ///compute the - ///shortest path to each node. The algorithm computes - ///- The shortest path tree. - ///- The distance of each node from the root. - /// - ///\note d.run(s) is just a shortcut of the following code. - ///\code - /// d.init(); - /// d.addSource(s); - /// d.start(); - ///\endcode - void run(Node s) { - init(); - addSource(s); - start(); - } - - ///Finds the shortest path between \c s and \c t. - - ///Finds the shortest path between \c s and \c t. - /// - ///\return The length of the shortest s---t path if there exists one, - ///0 otherwise. - ///\note Apart from the return value, d.run(s) is - ///just a shortcut of the following code. - ///\code - /// d.init(); - /// d.addSource(s); - /// d.start(t); - ///\endcode - Value run(Node s,Node t) { - init(); - addSource(s); - start(t); - return (*_pred)[t]==INVALID?0:(*_dist)[t]; - } - - ///@} - - ///\name Query Functions - ///The result of the %Dijkstra algorithm can be obtained using these - ///functions.\n - ///Before the use of these functions, - ///either run() or start() must be called. - - ///@{ - - ///Copies the shortest path to \c t into \c p - - ///This function copies the shortest path to \c t into \c p. - ///If it \c \t is a source itself or unreachable, then it does not - ///alter \c p. - ///\todo Is it the right way to handle unreachable nodes? - ///\return Returns \c true if a path to \c t was actually copied to \c p, - ///\c false otherwise. - ///\sa DirPath - template - bool getPath(P &p,Node t) - { - if(reached(t)) { - p.clear(); - typename P::Builder b(p); - for(b.setStartNode(t);pred(t)!=INVALID;t=predNode(t)) - b.pushFront(pred(t)); - b.commit(); - return true; - } - return false; - } - - ///The distance of a node from the root. - - ///Returns the distance of a node from the root. - ///\pre \ref run() must be called before using this function. - ///\warning If node \c v in unreachable from the root the return value - ///of this funcion is undefined. - Value dist(Node v) const { return (*_dist)[v]; } - - ///Returns the 'previous edge' of the shortest path tree. - - ///For a node \c v it returns the 'previous edge' of the shortest path tree, - ///i.e. it returns the last edge of a shortest path from the root to \c - ///v. It is \ref INVALID - ///if \c v is unreachable from the root or if \c v=s. The - ///shortest path tree used here is equal to the shortest path tree used in - ///\ref predNode(Node v). \pre \ref run() must be called before using - ///this function. - ///\todo predEdge could be a better name. - Edge pred(Node v) const { return (*_pred)[v]; } - - ///Returns the 'previous node' of the shortest path tree. - - ///For a node \c v it returns the 'previous node' of the shortest path tree, - ///i.e. it returns the last but one node from a shortest path from the - ///root to \c /v. It is INVALID if \c v is unreachable from the root or if - ///\c v=s. The shortest path tree used here is equal to the shortest path - ///tree used in \ref pred(Node v). \pre \ref run() must be called before - ///using this function. - Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID: - G->source((*_pred)[v]); } - - ///Returns a reference to the NodeMap of distances. - - ///Returns a reference to the NodeMap of distances. \pre \ref run() must - ///be called before using this function. - const DistMap &distMap() const { return *_dist;} - - ///Returns a reference to the shortest path tree map. - - ///Returns a reference to the NodeMap of the edges of the - ///shortest path tree. - ///\pre \ref run() must be called before using this function. - const PredMap &predMap() const { return *_pred;} - -// ///Returns a reference to the map of nodes of shortest paths. - -// ///Returns a reference to the NodeMap of the last but one nodes of the -// ///shortest path tree. -// ///\pre \ref run() must be called before using this function. -// const PredNodeMap &predNodeMap() const { return *_predNode;} - - ///Checks if a node is reachable from the root. - - ///Returns \c true if \c v is reachable from the root. - ///\warning The source nodes are inditated as unreached. - ///\pre \ref run() must be called before using this function. - /// - bool reached(Node v) { return _heap_map[v]!=Heap::PRE_HEAP; } - - ///@} - }; - - - - - - ///Default traits class of Dijkstra function. - - ///Default traits class of Dijkstra function. - ///\param GR Graph type. - ///\param LM Type of length map. - template - struct DijkstraWizardDefaultTraits - { - ///The graph type the algorithm runs on. - typedef GR Graph; - ///The type of the map that stores the edge lengths. - - ///The type of the map that stores the edge lengths. - ///It must meet the \ref concept::ReadMap "ReadMap" concept. - typedef LM LengthMap; - //The type of the length of the edges. - typedef typename LM::Value Value; - ///The heap type used by Dijkstra algorithm. - - ///The heap type used by Dijkstra algorithm. - /// - ///\sa BinHeap - ///\sa Dijkstra - typedef BinHeap, - std::less > Heap; - - ///\brief The type of the map that stores the last - ///edges of the shortest paths. - /// - ///The type of the map that stores the last - ///edges of the shortest paths. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef NullMap PredMap; - ///Instantiates a PredMap. - - ///This function instantiates a \ref PredMap. - ///\param G is the graph, to which we would like to define the PredMap. - ///\todo The graph alone may be insufficient for the initialization - static PredMap *createPredMap(const GR &) - { - return new PredMap(); - } - ///The type of the map that stores whether a nodes is processed. - - ///The type of the map that stores whether a nodes is processed. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - ///By default it is a NullMap. - ///\todo If it is set to a real map, - ///Dijkstra::processed() should read this. - ///\todo named parameter to set this type, function to read and write. - typedef NullMap ProcessedMap; - ///Instantiates a ProcessedMap. - - ///This function instantiates a \ref ProcessedMap. - ///\param G is the graph, to which - ///we would like to define the \ref ProcessedMap - static ProcessedMap *createProcessedMap(const GR &) - { - return new ProcessedMap(); - } - ///The type of the map that stores the dists of the nodes. - - ///The type of the map that stores the dists of the nodes. - ///It must meet the \ref concept::WriteMap "WriteMap" concept. - /// - typedef NullMap DistMap; - ///Instantiates a DistMap. - - ///This function instantiates a \ref DistMap. - ///\param G is the graph, to which we would like to define the \ref DistMap - static DistMap *createDistMap(const GR &) - { - return new DistMap(); - } - }; - - /// Default traits used by \ref DijkstraWizard - - /// To make it easier to use Dijkstra algorithm - ///we have created a wizard class. - /// This \ref DijkstraWizard class needs default traits, - ///as well as the \ref Dijkstra class. - /// The \ref DijkstraWizardBase is a class to be the default traits of the - /// \ref DijkstraWizard class. - /// \todo More named parameters are required... - template - class DijkstraWizardBase : public DijkstraWizardDefaultTraits - { - - typedef DijkstraWizardDefaultTraits Base; - protected: - /// Type of the nodes in the graph. - typedef typename Base::Graph::Node Node; - - /// Pointer to the underlying graph. - void *_g; - /// Pointer to the length map - void *_length; - ///Pointer to the map of predecessors edges. - void *_pred; -// ///Pointer to the map of predecessors nodes. -// void *_predNode; - ///Pointer to the map of distances. - void *_dist; - ///Pointer to the source node. - Node _source; - - public: - /// Constructor. - - /// This constructor does not require parameters, therefore it initiates - /// all of the attributes to default values (0, INVALID). - DijkstraWizardBase() : _g(0), _length(0), _pred(0), -// _predNode(0), - _dist(0), _source(INVALID) {} - - /// Constructor. - - /// This constructor requires some parameters, - /// listed in the parameters list. - /// Others are initiated to 0. - /// \param g is the initial value of \ref _g - /// \param l is the initial value of \ref _length - /// \param s is the initial value of \ref _source - DijkstraWizardBase(const GR &g,const LM &l, Node s=INVALID) : - _g((void *)&g), _length((void *)&l), _pred(0), -// _predNode(0), - _dist(0), _source(s) {} - - }; - - /// A class to make the usage of Dijkstra algorithm easier - - /// This class is created to make it easier to use Dijkstra algorithm. - /// It uses the functions and features of the plain \ref Dijkstra, - /// but it is much simpler to use it. - /// - /// Simplicity means that the way to change the types defined - /// in the traits class is based on functions that returns the new class - /// and not on templatable built-in classes. - /// When using the plain \ref Dijkstra - /// the new class with the modified type comes from - /// the original class by using the :: - /// operator. In the case of \ref DijkstraWizard only - /// a function have to be called and it will - /// return the needed class. - /// - /// It does not have own \ref run method. When its \ref run method is called - /// it initiates a plain \ref Dijkstra class, and calls the \ref Dijkstra::run - /// method of it. - template - class DijkstraWizard : public TR - { - typedef TR Base; - - ///The type of the underlying graph. - typedef typename TR::Graph Graph; - //\e - typedef typename Graph::Node Node; - //\e - typedef typename Graph::NodeIt NodeIt; - //\e - typedef typename Graph::Edge Edge; - //\e - typedef typename Graph::OutEdgeIt OutEdgeIt; - - ///The type of the map that stores the edge lengths. - typedef typename TR::LengthMap LengthMap; - ///The type of the length of the edges. - typedef typename LengthMap::Value Value; - ///\brief The type of the map that stores the last - ///edges of the shortest paths. - typedef typename TR::PredMap PredMap; -// ///\brief The type of the map that stores the last but one -// ///nodes of the shortest paths. -// typedef typename TR::PredNodeMap PredNodeMap; - ///The type of the map that stores the dists of the nodes. - typedef typename TR::DistMap DistMap; - - ///The heap type used by the dijkstra algorithm. - typedef typename TR::Heap Heap; -public: - /// Constructor. - DijkstraWizard() : TR() {} - - /// Constructor that requires parameters. - - /// Constructor that requires parameters. - /// These parameters will be the default values for the traits class. - DijkstraWizard(const Graph &g,const LengthMap &l, Node s=INVALID) : - TR(g,l,s) {} - - ///Copy constructor - DijkstraWizard(const TR &b) : TR(b) {} - - ~DijkstraWizard() {} - - ///Runs Dijkstra algorithm from a given node. - - ///Runs Dijkstra algorithm from a given node. - ///The node can be given by the \ref source function. - void run() - { - if(Base::_source==INVALID) throw UninitializedParameter(); - Dijkstra - dij(*(Graph*)Base::_g,*(LengthMap*)Base::_length); - if(Base::_pred) dij.predMap(*(PredMap*)Base::_pred); -// if(Base::_predNode) Dij.predNodeMap(*(PredNodeMap*)Base::_predNode); - if(Base::_dist) dij.distMap(*(DistMap*)Base::_dist); - dij.run(Base::_source); - } - - ///Runs Dijkstra algorithm from the given node. - - ///Runs Dijkstra algorithm from the given node. - ///\param s is the given source. - void run(Node s) - { - Base::_source=s; - run(); - } - - template - struct DefPredMapBase : public Base { - typedef T PredMap; - static PredMap *createPredMap(const Graph &) { return 0; }; - DefPredMapBase(const TR &b) : TR(b) {} - }; - - ///\brief \ref named-templ-param "Named parameter" - ///function for setting PredMap type - /// - /// \ref named-templ-param "Named parameter" - ///function for setting PredMap type - /// - template - DijkstraWizard > predMap(const T &t) - { - Base::_pred=(void *)&t; - return DijkstraWizard >(*this); - } - - -// template -// struct DefPredNodeMapBase : public Base { -// typedef T PredNodeMap; -// static PredNodeMap *createPredNodeMap(const Graph &G) { return 0; }; -// DefPredNodeMapBase(const TR &b) : TR(b) {} -// }; - -// ///\brief \ref named-templ-param "Named parameter" -// ///function for setting PredNodeMap type -// /// -// /// \ref named-templ-param "Named parameter" -// ///function for setting PredNodeMap type -// /// -// template -// DijkstraWizard > predNodeMap(const T &t) -// { -// Base::_predNode=(void *)&t; -// return DijkstraWizard >(*this); -// } - - template - struct DefDistMapBase : public Base { - typedef T DistMap; - static DistMap *createDistMap(const Graph &) { return 0; }; - DefDistMapBase(const TR &b) : TR(b) {} - }; - - ///\brief \ref named-templ-param "Named parameter" - ///function for setting DistMap type - /// - /// \ref named-templ-param "Named parameter" - ///function for setting DistMap type - /// - template - DijkstraWizard > distMap(const T &t) - { - Base::_dist=(void *)&t; - return DijkstraWizard >(*this); - } - - /// Sets the source node, from which the Dijkstra algorithm runs. - - /// Sets the source node, from which the Dijkstra algorithm runs. - /// \param s is the source node. - DijkstraWizard &source(Node s) - { - Base::_source=s; - return *this; - } - - }; - - ///Function type interface for Dijkstra algorithm. - - /// \ingroup flowalgs - ///Function type interface for Dijkstra algorithm. - /// - ///This function also has several - ///\ref named-templ-func-param "named parameters", - ///they are declared as the members of class \ref DijkstraWizard. - ///The following - ///example shows how to use these parameters. - ///\code - /// dijkstra(g,length,source).predMap(preds).run(); - ///\endcode - ///\warning Don't forget to put the \ref DijkstraWizard::run() "run()" - ///to the end of the parameter list. - ///\sa DijkstraWizard - ///\sa Dijkstra - template - DijkstraWizard > - dijkstra(const GR &g,const LM &l,typename GR::Node s=INVALID) - { - return DijkstraWizard >(g,l,s); - } - -} //END OF NAMESPACE LEMON - -#endif - diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/dimacs.h --- a/src/lemon/dimacs.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ -/* -*- C++ -*- - * src/lemon/dimacs.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_DIMACS_H -#define LEMON_DIMACS_H - -#include -#include -#include -#include -#include - -/// \ingroup dimacs_group -/// \file -/// \brief Dimacs file format reader. - -namespace lemon { - - /// - ///@defgroup dimacs_group DIMACS format - ///\brief Read and write files in DIMACS format - /// - ///Tools to read a graph from or write it to a file in DIMACS format - ///data - ///\ingroup io_group - - /// \addtogroup dimacs_group - /// @{ - - /// Dimacs min cost flow reader function. - - /// This function reads a min cost flow instance from dimacs format, - /// i.e. from dimacs files having a line starting with - /// \code - /// p "min" - /// \endcode - /// At the beginning \c g is cleared by \c g.clear(). The edge - /// capacities are written to \c capacity, \c s and \c t are set to - /// the source and the target nodes resp. and the cost of the edges - /// are written to \c cost. - /// - /// \author Marton Makai - template - void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity, - typename Graph::Node &s, typename Graph::Node &t, - CostMap& cost) { - g.clear(); - typename CapacityMap::Value _cap; - typename CostMap::Value _cost; - char d; - std::string problem; - char c; - int i, j; - std::string str; - int n, m; - typename Graph::Edge e; - std::vector nodes; - while (is>>c) { - switch (c) { - case 'c': //comment - getline(is, str); - break; - case 'p': //problem definition - is >> problem >> n >> m; - getline(is, str); - nodes.resize(n+1); - for (int k=1; k<=n; ++k) nodes[k]=g.addNode(); - break; - case 'n': //node definition - if (problem=="sp") { //shortest path problem - is >> i; - getline(is, str); - s=nodes[i]; - } - if (problem=="max" || problem=="min") { //((max) or (min cost)) flow problem - is >> i >> d; - getline(is, str); - if (d=='s') s=nodes[i]; - if (d=='t') t=nodes[i]; - } - break; - case 'a': - if ( problem == "max" || problem == "sp") { - is >> i >> j >> _cap; - getline(is, str); - e=g.addEdge(nodes[i], nodes[j]); - //capacity.update(); - capacity.set(e, _cap); - } else { - if ( problem == "min" ) { - is >> i >> j >> _cap >> _cost; - getline(is, str); - e=g.addEdge(nodes[i], nodes[j]); - //capacity.update(); - capacity.set(e, _cap); - //cost.update(); - cost.set(e, _cost); - } else { - is >> i >> j; - getline(is, str); - g.addEdge(nodes[i], nodes[j]); - } - } - break; - } - } - } - - - /// Dimacs max flow reader function. - - /// This function reads a max flow instance from dimacs format, - /// i.e. from dimacs files having a line starting with - /// \code - /// p "max" - /// \endcode - ///At the beginning \c g is cleared by \c g.clear(). The - /// edge capacities are written to \c capacity and \c s and \c t are - /// set to the source and the target nodes. - /// - /// \author Marton Makai - template - void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity, - typename Graph::Node &s, typename Graph::Node &t) { - NullMap n; - readDimacs(is, g, capacity, s, t, n); - } - - - /// Dimacs shortest path reader function. - - /// This function reads a shortest path instance from dimacs format, - /// i.e. from dimacs files having a line starting with - /// \code - /// p "sp" - /// \endcode - /// At the beginning \c g is cleared by \c g.clear(). The edge - /// capacities are written to \c capacity and \c s is set to the - /// source node. - /// - /// \author Marton Makai - template - void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity, - typename Graph::Node &s) { - NullMap n; - readDimacs(is, g, capacity, s, s, n); - } - - - /// Dimacs capacitated graph reader function. - - /// This function reads an edge capacitated graph instance from - /// dimacs format. At the beginning \c g is cleared by \c g.clear() - /// and the edge capacities are written to \c capacity. - /// - /// \author Marton Makai - template - void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity) { - typename Graph::Node u; - NullMap n; - readDimacs(is, g, capacity, u, u, n); - } - - - /// Dimacs plain graph reader function. - - /// This function reads a graph without any designated nodes and - /// maps from dimacs format, i.e. from dimacs files having a line - /// starting with - /// \code - /// p "mat" - /// \endcode - /// At the beginning \c g is cleared - /// by \c g.clear(). - /// - /// \author Marton Makai - template - void readDimacs(std::istream& is, Graph &g) { - typename Graph::Node u; - NullMap n; - readDimacs(is, g, n, u, u, n); - } - - - - - /// write matching problem - template - void writeDimacs(std::ostream& os, const Graph &g) { - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::EdgeIt EdgeIt; - - typename Graph::template NodeMap nodes(g); - - os << "c matching problem" << std::endl; - - int i=1; - for(NodeIt v(g); v!=INVALID; ++v) { - nodes.set(v, i); - ++i; - } - - os << "p mat " << g.nodeNum() << " " << g.edgeNum() << std::endl; - - for(EdgeIt e(g); e!=INVALID; ++e) { - os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)] << std::endl; - } - - } - - /// @} - -} //namespace lemon - -#endif //LEMON_DIMACS_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/error.h --- a/src/lemon/error.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,540 +0,0 @@ -/* -*- C++ -*- - * - * src/lemon/error.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi - * Kutatocsoport (Egervary Research Group on Combinatorial Optimization, - * EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_ERROR_H -#define LEMON_ERROR_H - -//! \ingroup exceptions -//! \file -//! \brief Basic exception classes and error handling. - -#include -#include -#include -#include -#include -#include - -namespace lemon { - - /// \addtogroup exceptions - /// @{ - - /// \brief Exception safe wrapper class. - /// - /// Exception safe wrapper class to implement the members of exceptions. - template - class ExceptionMember { - public: - typedef _Type Type; - - ExceptionMember() throw () { - try { - ptr.reset(new Type()); - } catch (...) {} - } - - ExceptionMember(const Type& type) throw () { - try { - ptr.reset(new Type()); - if (ptr.get() == 0) return; - *ptr = type; - } catch (...) {} - } - - ExceptionMember(const ExceptionMember& copy) throw() { - try { - if (!copy.valid()) return; - ptr.reset(new Type()); - if (ptr.get() == 0) return; - *ptr = copy.get(); - } catch (...) {} - } - - ExceptionMember& operator=(const ExceptionMember& copy) { - if (ptr.get() == 0) return; - try { - if (!copy.valid()) return; - *ptr = copy.get(); - } catch (...) {} - } - - void set(const Type& type) { - if (ptr.get() == 0) return; - try { - *ptr = type; - } catch (...) {} - } - - const Type& get() const { - return *ptr; - } - - bool valid() const { - return ptr.get() != 0; - } - - private: - std::auto_ptr<_Type> ptr; - }; - - /// Exception-safe convenient "error message" class. - - /// Helper class which provides a convenient ostream-like (operator << - /// based) interface to create a string message. Mostly useful in - /// exception classes (therefore the name). - class ErrorMessage { - protected: - ///\e - ///\todo The good solution is boost:shared_ptr... - mutable - std::auto_ptr buf; - - ///\e - bool init() throw() { - try { - buf.reset(new std::ostringstream); - } - catch(...) { - buf.reset(); - } - return buf.get(); - } - - public: - - ///\e - ErrorMessage() throw() { init(); } - - ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { } - - ///\e - ErrorMessage(const char *message) throw() { - init(); - *this << message; - } - - ///\e - ErrorMessage(const std::string &message) throw() { - init(); - *this << message; - } - - ///\e - template - ErrorMessage& operator<<(const T &t) throw() { - if( ! buf.get() ) return *this; - - try { - *buf << t; - } - catch(...) { - buf.reset(); - } - return *this; - } - - ///\e - const char* message() throw() { - if( ! buf.get() ) return 0; - - const char* mes = 0; - try { - mes = buf->str().c_str(); - } - catch(...) {} - return mes; - } - - }; - - /** - * \brief Generic exception class. - * - * Base class for exceptions used in LEMON. - */ - class Exception : public std::exception { - public: - ///\e - Exception() {} - ///\e - virtual ~Exception() throw() {} - - ///\e - virtual const char* exceptionName() const { - return "lemon::Exception"; - } - - ///\e - virtual const char* what() const throw() { - return exceptionName(); - } - }; - - /** - * \brief One of the two main subclasses of \ref Exception. - * - * Logic errors represent problems in the internal logic of a program; - * in theory, these are preventable, and even detectable before the - * program runs (e.g., violations of class invariants). - * - * A typical example for this is \ref UninitializedParameter. - */ - class LogicError : public Exception { - public: - virtual const char* exceptionName() const { - return "lemon::LogicError"; - } - }; - - /** - * \brief \ref Exception for uninitialized parameters. - * - * This error represents problems in the initialization - * of the parameters of the algorithms. - */ - class UninitializedParameter : public LogicError { - public: - virtual const char* exceptionName() const { - return "lemon::UninitializedParameter"; - } - }; - - - /** - * \brief One of the two main subclasses of \ref Exception. - * - * Runtime errors represent problems outside the scope of a program; - * they cannot be easily predicted and can generally only be caught as - * the program executes. - */ - class RuntimeError : public Exception { - public: - virtual const char* exceptionName() const { - return "lemon::RuntimeError"; - } - }; - - ///\e - class RangeError : public RuntimeError { - public: - virtual const char* exceptionName() const { - return "lemon::RangeError"; - } - }; - - ///\e - class IOError : public RuntimeError { - public: - virtual const char* exceptionName() const { - return "lemon::IOError"; - } - }; - - ///\e - class DataFormatError : public IOError { - protected: - ExceptionMember _message; - ExceptionMember _file; - int _line; - - mutable ExceptionMember _message_holder; - public: - - DataFormatError(const DataFormatError &dfe) : - IOError(dfe), _message(dfe._message), _file(dfe._file), - _line(dfe._line) {} - - ///\e - explicit DataFormatError(const char *the_message) - : _message(the_message), _line(0) {} - - ///\e - DataFormatError(const std::string &file_name, int line_num, - const char *the_message) - : _message(the_message), _line(line_num) { file(file_name); } - - ///\e - void line(int line) { _line = line; } - ///\e - void message(const std::string& message) { _message.set(message); } - ///\e - void file(const std::string &file) { _file.set(file); } - - ///\e - int line() const { return _line; } - ///\e - const char* message() const { - if (_message.valid() && !_message.get().empty()) { - return _message.get().c_str(); - } else { - return 0; - } - } - - /// \brief Returns the filename. - /// - /// Returns \e null if the filename was not specified. - const char* file() const { - if (_file.valid() && !_file.get().empty()) { - return _file.get().c_str(); - } else { - return 0; - } - } - - ///\e - virtual const char* what() const throw() { - try { - std::ostringstream ostr; - ostr << exceptionName() << ": "; - if (message()) ostr << message(); - if( file() || line() != 0 ) { - ostr << " ("; - if( file() ) ostr << "in file '" << file() << "'"; - if( file() && line() != 0 ) ostr << " "; - if( line() != 0 ) ostr << "at line " << line(); - ostr << ")"; - } - _message_holder.set(ostr.str()); - } - catch (...) {} - if( _message_holder.valid()) return _message_holder.get().c_str(); - return exceptionName(); - } - - virtual const char* exceptionName() const { - return "lemon::DataFormatError"; - } - - virtual ~DataFormatError() throw() {} - }; - - class IOParameterError : public LogicError { - protected: - ExceptionMember _message; - ExceptionMember _file; - - mutable ExceptionMember _message_holder; - public: - - IOParameterError(const IOParameterError &ile) : - LogicError(ile), _message(ile._message), _file(ile._file) {} - - ///\e - explicit IOParameterError(const char *the_message) - : _message(the_message) {} - - ///\e - IOParameterError(const char *file_name, const char *the_message) - : _message(the_message), _file(file_name) {} - - ///\e - void message(const std::string& message) { _message.set(message); } - ///\e - void file(const std::string &file) { _file.set(file); } - - ///\e - const char* message() const { - if (_message.valid()) { - return _message.get().c_str(); - } else { - return 0; - } - } - - /// \brief Returns the filename. - /// - /// Returns \e null if the filename was not specified. - const char* file() const { - if (_file.valid()) { - return _file.get().c_str(); - } else { - return 0; - } - } - - ///\e - virtual const char* what() const throw() { - try { - std::ostringstream ostr; - if (message()) ostr << message(); - if (file()) ostr << "(when reading file '" << file() << "')"; - _message_holder.set(ostr.str()); - } - catch (...) {} - if( _message_holder.valid() ) return _message_holder.get().c_str(); - return exceptionName(); - } - - virtual const char* exceptionName() const { - return "lemon::IOParameterError"; - } - - virtual ~IOParameterError() throw() {} - }; - - - ///\e - class AssertionFailedError : public LogicError { - protected: - const char *assertion; - const char *file; - int line; - const char *function; - const char *message; - - mutable ExceptionMember _message_holder; - public: - ///\e - AssertionFailedError(const char *_file, int _line, const char *func, - const char *msg, const char *_assertion = 0) : - assertion(_assertion), file(_file), line(_line), function(func), - message(msg) {} - - ///\e - const char* get_assertion() const { return assertion; } - ///\e - const char* get_message() const { return message; } - ///\e - const char* get_file() const { return file; } - ///\e - const char* get_function() const { return function; } - ///\e - int get_line() const { return line; } - - - virtual const char* what() const throw() { - try { - std::ostringstream ostr; - ostr << file << ":" << line << ": "; - if( function ) - ostr << function << ": "; - ostr << message; - if( assertion ) - ostr << " (assertion '" << assertion << "' failed)"; - _message_holder.set(ostr.str()); - return ostr.str().c_str(); - } - catch(...) {} - if( _message_holder.valid() ) return _message_holder.get().c_str(); - return exceptionName(); - } - - virtual const char* exceptionName() const { - return "lemon::AssertionFailedError"; - } - - virtual ~AssertionFailedError() throw() {} - }; - - - /**************** Macros ****************/ - - - inline - void assert_fail(const char *file, int line, const char *func, - const char *message, const char *assertion = 0, - bool do_abort=true) - { - using namespace std; - cerr << file << ":" << line << ": "; - if( func ) - cerr << func << ": "; - cerr << message; - if( assertion ) - cerr << " (assertion '" << assertion << "' failed)"; - cerr << endl; - if(do_abort) - abort(); - } - - inline - void assert_fail_throw(const char *file, int line, const char *func, - const char *message, const char *assertion = 0, - bool = true) - { - throw AssertionFailedError(file, line, func, message, assertion); - } - -/// @} - -} -#endif // LEMON_ERROR_H - -#undef LEMON_ASSERT -#undef LEMON_FIXME - -#ifndef LEMON_ASSERT_ABORT -# define LEMON_ASSERT_ABORT 1 -#endif - -#ifndef LEMON_ASSERT_HANDLER -# ifdef LEMON_ASSERT_EXCEPTION -# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw -# else -# define LEMON_ASSERT_HANDLER ::lemon::assert_fail -# endif -#endif - -#if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS) - -# define LEMON_ASSERT(exp, msg) (static_cast (0)) - -#else - -/** - * \brief Macro for assertions with customizable message - * - * Macro for assertions with customizable message. - * - * The behaviour can be customized with LEMON_ASSERT_HANDLER, - * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be - * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros. - * - * \todo We should provide some way to reset to the default behaviour, - * shouldn't we? - * - * \todo This whole 'assert' business should be placed in a separate - * include file. - * - * \todo __PRETTY_FUNCTION__ should be replaced by something - * compiler-independent, like BOOST_CURRENT_FUNCTION - */ - -# define LEMON_ASSERT(exp, msg) \ - (static_cast (!!(exp) ? 0 : ( \ - LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ - __PRETTY_FUNCTION__, \ - (msg), #exp, LEMON_ASSERT_ABORT), 0))) - -#endif // NDEBUG || LEMON_DISABLE_ASSERTS - -/** - * \brief Macro for mark not yet implemented features. - * - * \todo Is this the right place for this? It should be used only in - * modules under development. - * - * \todo __PRETTY_FUNCTION__ should be replaced by something - * compiler-independent, like BOOST_CURRENT_FUNCTION - */ - -# define LEMON_FIXME(msg) \ - (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \ - "FIXME: " msg)) diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/fib_heap.h --- a/src/lemon/fib_heap.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,531 +0,0 @@ -/* -*- C++ -*- - * src/lemon/fib_heap.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_FIB_HEAP_H -#define LEMON_FIB_HEAP_H - -///\file -///\ingroup auxdat -///\brief Fibonacci Heap implementation. - -#include -#include -#include - -namespace lemon { - - /// \addtogroup auxdat - /// @{ - - /// Fibonacci Heap. - - ///This class implements the \e Fibonacci \e heap data structure. A \e heap - ///is a data structure for storing items with specified values called \e - ///priorities in such a way that finding the item with minimum priority is - ///efficient. \c Compare specifies the ordering of the priorities. In a heap - ///one can change the priority of an item, add or erase an item, etc. - /// - ///The methods \ref increase and \ref erase are not efficient in a Fibonacci - ///heap. In case of many calls to these operations, it is better to use a - ///\e binary \e heap. - /// - ///\param Item Type of the items to be stored. - ///\param Prio Type of the priority of the items. - ///\param ItemIntMap A read and writable Item int map, used internally - ///to handle the cross references. - ///\param Compare A class for the ordering of the priorities. The - ///default is \c std::less. - /// - ///\sa BinHeap - ///\sa Dijkstra - ///\author Jacint Szabo - -#ifdef DOXYGEN - template -#else - template > -#endif - class FibHeap { - public: - typedef Prio PrioType; - - private: - class store; - - std::vector container; - int minimum; - ItemIntMap &iimap; - Compare comp; - int num_items; - - public: - ///Status of the nodes - enum state_enum { - ///The node is in the heap - IN_HEAP = 0, - ///The node has never been in the heap - PRE_HEAP = -1, - ///The node was in the heap but it got out of it - POST_HEAP = -2 - }; - - ///The constructor - - /** - \c _iimap should be given to the constructor, since it is - used internally to handle the cross references. - */ - explicit FibHeap(ItemIntMap &_iimap) - : minimum(0), iimap(_iimap), num_items() {} - - ///The constructor - - /** - \c _iimap should be given to the constructor, since it is used - internally to handle the cross references. \c _comp is an - object for ordering of the priorities. - */ - FibHeap(ItemIntMap &_iimap, const Compare &_comp) : minimum(0), - iimap(_iimap), comp(_comp), num_items() {} - - ///The number of items stored in the heap. - - /** - Returns the number of items stored in the heap. - */ - int size() const { return num_items; } - - ///Checks if the heap stores no items. - - /** - Returns \c true if and only if the heap stores no items. - */ - bool empty() const { return num_items==0; } - - ///\c item gets to the heap with priority \c value independently if \c item was already there. - - /** - This method calls \ref push(\c item, \c value) if \c item is not - stored in the heap and it calls \ref decrease(\c item, \c value) or - \ref increase(\c item, \c value) otherwise. - */ - void set (Item const item, PrioType const value); - - ///Adds \c item to the heap with priority \c value. - - /** - Adds \c item to the heap with priority \c value. - \pre \c item must not be stored in the heap. - */ - void push (Item const item, PrioType const value); - - ///Returns the item with minimum priority relative to \c Compare. - - /** - This method returns the item with minimum priority relative to \c - Compare. - \pre The heap must be nonempty. - */ - Item top() const { return container[minimum].name; } - - ///Returns the minimum priority relative to \c Compare. - - /** - It returns the minimum priority relative to \c Compare. - \pre The heap must be nonempty. - */ - PrioType prio() const { return container[minimum].prio; } - - ///Returns the priority of \c item. - - /** - This function returns the priority of \c item. - \pre \c item must be in the heap. - */ - PrioType& operator[](const Item& item) { - return container[iimap[item]].prio; - } - - ///Returns the priority of \c item. - - /** - It returns the priority of \c item. - \pre \c item must be in the heap. - */ - const PrioType& operator[](const Item& item) const { - return container[iimap[item]].prio; - } - - - ///Deletes the item with minimum priority relative to \c Compare. - - /** - This method deletes the item with minimum priority relative to \c - Compare from the heap. - \pre The heap must be non-empty. - */ - void pop(); - - ///Deletes \c item from the heap. - - /** - This method deletes \c item from the heap, if \c item was already - stored in the heap. It is quite inefficient in Fibonacci heaps. - */ - void erase (const Item& item); - - ///Decreases the priority of \c item to \c value. - - /** - This method decreases the priority of \c item to \c value. - \pre \c item must be stored in the heap with priority at least \c - value relative to \c Compare. - */ - void decrease (Item item, PrioType const value); - - ///Increases the priority of \c item to \c value. - - /** - This method sets the priority of \c item to \c value. Though - there is no precondition on the priority of \c item, this - method should be used only if it is indeed necessary to increase - (relative to \c Compare) the priority of \c item, because this - method is inefficient. - */ - void increase (Item item, PrioType const value) { - erase(item); - push(item, value); - } - - - ///Returns if \c item is in, has already been in, or has never been in the heap. - - /** - This method returns PRE_HEAP if \c item has never been in the - heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP - otherwise. In the latter case it is possible that \c item will - get back to the heap again. - */ - state_enum state(const Item &item) const { - int i=iimap[item]; - if( i>=0 ) { - if ( container[i].in ) i=0; - else i=-2; - } - return state_enum(i); - } - - private: - - void balance(); - void makeroot(int c); - void cut(int a, int b); - void cascade(int a); - void fuse(int a, int b); - void unlace(int a); - - - class store { - friend class FibHeap; - - Item name; - int parent; - int left_neighbor; - int right_neighbor; - int child; - int degree; - bool marked; - bool in; - PrioType prio; - - store() : parent(-1), child(-1), degree(), marked(false), in(true) {} - }; - }; - - - - // ********************************************************************** - // IMPLEMENTATIONS - // ********************************************************************** - - template - void FibHeap::set - (Item const item, PrioType const value) - { - int i=iimap[item]; - if ( i >= 0 && container[i].in ) { - if ( comp(value, container[i].prio) ) decrease(item, value); - if ( comp(container[i].prio, value) ) increase(item, value); - } else push(item, value); - } - - template - void FibHeap::push - (Item const item, PrioType const value) { - int i=iimap[item]; - if ( i < 0 ) { - int s=container.size(); - iimap.set( item, s ); - store st; - st.name=item; - container.push_back(st); - i=s; - } else { - container[i].parent=container[i].child=-1; - container[i].degree=0; - container[i].in=true; - container[i].marked=false; - } - - if ( num_items ) { - container[container[minimum].right_neighbor].left_neighbor=i; - container[i].right_neighbor=container[minimum].right_neighbor; - container[minimum].right_neighbor=i; - container[i].left_neighbor=minimum; - if ( comp( value, container[minimum].prio) ) minimum=i; - } else { - container[i].right_neighbor=container[i].left_neighbor=i; - minimum=i; - } - container[i].prio=value; - ++num_items; - } - - template - void FibHeap::pop() { - /*The first case is that there are only one root.*/ - if ( container[minimum].left_neighbor==minimum ) { - container[minimum].in=false; - if ( container[minimum].degree!=0 ) { - makeroot(container[minimum].child); - minimum=container[minimum].child; - balance(); - } - } else { - int right=container[minimum].right_neighbor; - unlace(minimum); - container[minimum].in=false; - if ( container[minimum].degree > 0 ) { - int left=container[minimum].left_neighbor; - int child=container[minimum].child; - int last_child=container[child].left_neighbor; - - makeroot(child); - - container[left].right_neighbor=child; - container[child].left_neighbor=left; - container[right].left_neighbor=last_child; - container[last_child].right_neighbor=right; - } - minimum=right; - balance(); - } // the case where there are more roots - --num_items; - } - - - template - void FibHeap::erase - (const Item& item) { - int i=iimap[item]; - - if ( i >= 0 && container[i].in ) { - if ( container[i].parent!=-1 ) { - int p=container[i].parent; - cut(i,p); - cascade(p); - } - minimum=i; //As if its prio would be -infinity - pop(); - } - } - - template - void FibHeap::decrease - (Item item, PrioType const value) { - int i=iimap[item]; - container[i].prio=value; - int p=container[i].parent; - - if ( p!=-1 && comp(value, container[p].prio) ) { - cut(i,p); - cascade(p); - } - if ( comp(value, container[minimum].prio) ) minimum=i; - } - - - template - void FibHeap::balance() { - - int maxdeg=int( std::floor( 2.08*log(double(container.size()))))+1; - - std::vector A(maxdeg,-1); - - /* - *Recall that now minimum does not point to the minimum prio element. - *We set minimum to this during balance(). - */ - int anchor=container[minimum].left_neighbor; - int next=minimum; - bool end=false; - - do { - int active=next; - if ( anchor==active ) end=true; - int d=container[active].degree; - next=container[active].right_neighbor; - - while (A[d]!=-1) { - if( comp(container[active].prio, container[A[d]].prio) ) { - fuse(active,A[d]); - } else { - fuse(A[d],active); - active=A[d]; - } - A[d]=-1; - ++d; - } - A[d]=active; - } while ( !end ); - - - while ( container[minimum].parent >=0 ) minimum=container[minimum].parent; - int s=minimum; - int m=minimum; - do { - if ( comp(container[s].prio, container[minimum].prio) ) minimum=s; - s=container[s].right_neighbor; - } while ( s != m ); - } - - template - void FibHeap::makeroot - (int c) { - int s=c; - do { - container[s].parent=-1; - s=container[s].right_neighbor; - } while ( s != c ); - } - - - template - void FibHeap::cut - (int a, int b) { - /* - *Replacing a from the children of b. - */ - --container[b].degree; - - if ( container[b].degree !=0 ) { - int child=container[b].child; - if ( child==a ) - container[b].child=container[child].right_neighbor; - unlace(a); - } - - - /*Lacing a to the roots.*/ - int right=container[minimum].right_neighbor; - container[minimum].right_neighbor=a; - container[a].left_neighbor=minimum; - container[a].right_neighbor=right; - container[right].left_neighbor=a; - - container[a].parent=-1; - container[a].marked=false; - } - - - template - void FibHeap::cascade - (int a) - { - if ( container[a].parent!=-1 ) { - int p=container[a].parent; - - if ( container[a].marked==false ) container[a].marked=true; - else { - cut(a,p); - cascade(p); - } - } - } - - - template - void FibHeap::fuse - (int a, int b) { - unlace(b); - - /*Lacing b under a.*/ - container[b].parent=a; - - if (container[a].degree==0) { - container[b].left_neighbor=b; - container[b].right_neighbor=b; - container[a].child=b; - } else { - int child=container[a].child; - int last_child=container[child].left_neighbor; - container[child].left_neighbor=b; - container[b].right_neighbor=child; - container[last_child].right_neighbor=b; - container[b].left_neighbor=last_child; - } - - ++container[a].degree; - - container[b].marked=false; - } - - - /* - *It is invoked only if a has siblings. - */ - template - void FibHeap::unlace - (int a) { - int leftn=container[a].left_neighbor; - int rightn=container[a].right_neighbor; - container[leftn].right_neighbor=rightn; - container[rightn].left_neighbor=leftn; - } - - ///@} - -} //namespace lemon - -#endif //LEMON_FIB_HEAP_H - diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/full_graph.h --- a/src/lemon/full_graph.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,385 +0,0 @@ -/* -*- C++ -*- - * src/lemon/full_graph.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_FULL_GRAPH_H -#define LEMON_FULL_GRAPH_H - -#include - - -#include -#include -#include - -#include -#include - - -///\ingroup graphs -///\file -///\brief FullGraph and SymFullGraph classes. - - -namespace lemon { - -/// \addtogroup graphs -/// @{ - - class FullGraphBase { - int NodeNum; - int EdgeNum; - public: - - typedef FullGraphBase Graph; - - class Node; - class Edge; - - public: - - FullGraphBase() {} - - - ///Creates a full graph with \c n nodes. - void construct(int n) { NodeNum = n; EdgeNum = n * n; } - /// - // FullGraphBase(const FullGraphBase &_g) - // : NodeNum(_g.nodeNum()), EdgeNum(NodeNum*NodeNum) { } - - typedef True NodeNumTag; - typedef True EdgeNumTag; - - ///Number of nodes. - int nodeNum() const { return NodeNum; } - ///Number of edges. - int edgeNum() const { return EdgeNum; } - - /// Maximum node ID. - - /// Maximum node ID. - ///\sa id(Node) - int maxId(Node = INVALID) const { return NodeNum-1; } - /// Maximum edge ID. - - /// Maximum edge ID. - ///\sa id(Edge) - int maxId(Edge = INVALID) const { return EdgeNum-1; } - - Node source(Edge e) const { return e.id % NodeNum; } - Node target(Edge e) const { return e.id / NodeNum; } - - - /// Node ID. - - /// The ID of a valid Node is a nonnegative integer not greater than - /// \ref maxNodeId(). The range of the ID's is not surely continuous - /// and the greatest node ID can be actually less then \ref maxNodeId(). - /// - /// The ID of the \ref INVALID node is -1. - ///\return The ID of the node \c v. - - static int id(Node v) { return v.id; } - /// Edge ID. - - /// The ID of a valid Edge is a nonnegative integer not greater than - /// \ref maxEdgeId(). The range of the ID's is not surely continuous - /// and the greatest edge ID can be actually less then \ref maxEdgeId(). - /// - /// The ID of the \ref INVALID edge is -1. - ///\return The ID of the edge \c e. - static int id(Edge e) { return e.id; } - - static Node fromId(int id, Node) { return Node(id);} - - static Edge fromId(int id, Edge) { return Edge(id);} - - /// Finds an edge between two nodes. - - /// Finds an edge from node \c u to node \c v. - /// - /// If \c prev is \ref INVALID (this is the default value), then - /// It finds the first edge from \c u to \c v. Otherwise it looks for - /// the next edge from \c u to \c v after \c prev. - /// \return The found edge or INVALID if there is no such an edge. - Edge findEdge(Node u,Node v, Edge prev = INVALID) - { - return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID; - } - - - class Node { - friend class FullGraphBase; - - protected: - int id; - Node(int _id) { id = _id;} - public: - Node() {} - Node (Invalid) { id = -1; } - bool operator==(const Node node) const {return id == node.id;} - bool operator!=(const Node node) const {return id != node.id;} - bool operator<(const Node node) const {return id < node.id;} - }; - - - - class Edge { - friend class FullGraphBase; - - protected: - int id; // NodeNum * target + source; - - Edge(int _id) : id(_id) {} - - Edge(const FullGraphBase& _graph, int source, int target) - : id(_graph.NodeNum * target+source) {} - public: - Edge() { } - Edge (Invalid) { id = -1; } - bool operator==(const Edge edge) const {return id == edge.id;} - bool operator!=(const Edge edge) const {return id != edge.id;} - bool operator<(const Edge edge) const {return id < edge.id;} - }; - - void first(Node& node) const { - node.id = NodeNum-1; - } - - static void next(Node& node) { - --node.id; - } - - void first(Edge& edge) const { - edge.id = EdgeNum-1; - } - - static void next(Edge& edge) { - --edge.id; - } - - void firstOut(Edge& edge, const Node& node) const { - edge.id = EdgeNum + node.id - NodeNum; - } - - void nextOut(Edge& edge) const { - edge.id -= NodeNum; - if (edge.id < 0) edge.id = -1; - } - - void firstIn(Edge& edge, const Node& node) const { - edge.id = node.id * NodeNum; - } - - void nextIn(Edge& edge) const { - ++edge.id; - if (edge.id % NodeNum == 0) edge.id = -1; - } - - }; - - - typedef AlterableGraphExtender AlterableFullGraphBase; - typedef IterableGraphExtender IterableFullGraphBase; - typedef DefaultMappableGraphExtender MappableFullGraphBase; - - ///A full graph class. - - ///This is a simple and fast directed full graph implementation. - ///It is completely static, so you can neither add nor delete either - ///edges or nodes. - ///Thus it conforms to - ///the \ref concept::StaticGraph "StaticGraph" concept - ///\sa concept::StaticGraph. - /// - ///\author Alpar Juttner - class FullGraph : public MappableFullGraphBase { - public: - - FullGraph(int n) { construct(n); } - }; - - - // Base graph class for UndirFullGraph. - class UndirFullGraphBase { - int NodeNum; - int EdgeNum; - public: - - typedef UndirFullGraphBase Graph; - - class Node; - class Edge; - - public: - - UndirFullGraphBase() {} - - - ///Creates a full graph with \c n nodes. - void construct(int n) { NodeNum = n; EdgeNum = n * (n - 1) / 2; } - /// - // FullGraphBase(const FullGraphBase &_g) - // : NodeNum(_g.nodeNum()), EdgeNum(NodeNum*NodeNum) { } - - typedef True NodeNumTag; - typedef True EdgeNumTag; - - ///Number of nodes. - int nodeNum() const { return NodeNum; } - ///Number of edges. - int edgeNum() const { return EdgeNum; } - - /// Maximum node ID. - - /// Maximum node ID. - ///\sa id(Node) - int maxId(Node = INVALID) const { return NodeNum-1; } - /// Maximum edge ID. - - /// Maximum edge ID. - ///\sa id(Edge) - int maxId(Edge = INVALID) const { return EdgeNum-1; } - - Node source(Edge e) const { - /// \todo we may do it faster - return ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2; - } - - Node target(Edge e) const { - int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;; - return e.id - (source) * (source - 1) / 2; - } - - - /// Node ID. - - /// The ID of a valid Node is a nonnegative integer not greater than - /// \ref maxNodeId(). The range of the ID's is not surely continuous - /// and the greatest node ID can be actually less then \ref maxNodeId(). - /// - /// The ID of the \ref INVALID node is -1. - ///\return The ID of the node \c v. - - static int id(Node v) { return v.id; } - /// Edge ID. - - /// The ID of a valid Edge is a nonnegative integer not greater than - /// \ref maxEdgeId(). The range of the ID's is not surely continuous - /// and the greatest edge ID can be actually less then \ref maxEdgeId(). - /// - /// The ID of the \ref INVALID edge is -1. - ///\return The ID of the edge \c e. - static int id(Edge e) { return e.id; } - - /// Finds an edge between two nodes. - - /// Finds an edge from node \c u to node \c v. - /// - /// If \c prev is \ref INVALID (this is the default value), then - /// It finds the first edge from \c u to \c v. Otherwise it looks for - /// the next edge from \c u to \c v after \c prev. - /// \return The found edge or INVALID if there is no such an edge. - Edge findEdge(Node u,Node v, Edge prev = INVALID) - { - return prev.id == -1 ? Edge(*this, u.id, v.id) : INVALID; - } - - - class Node { - friend class UndirFullGraphBase; - - protected: - int id; - Node(int _id) { id = _id;} - public: - Node() {} - Node (Invalid) { id = -1; } - bool operator==(const Node node) const {return id == node.id;} - bool operator!=(const Node node) const {return id != node.id;} - bool operator<(const Node node) const {return id < node.id;} - }; - - - - class Edge { - friend class UndirFullGraphBase; - - protected: - int id; // NodeNum * target + source; - - Edge(int _id) : id(_id) {} - - Edge(const UndirFullGraphBase& _graph, int source, int target) - : id(_graph.NodeNum * target+source) {} - public: - Edge() { } - Edge (Invalid) { id = -1; } - bool operator==(const Edge edge) const {return id == edge.id;} - bool operator!=(const Edge edge) const {return id != edge.id;} - bool operator<(const Edge edge) const {return id < edge.id;} - }; - - void first(Node& node) const { - node.id = NodeNum-1; - } - - static void next(Node& node) { - --node.id; - } - - void first(Edge& edge) const { - edge.id = EdgeNum-1; - } - - static void next(Edge& edge) { - --edge.id; - } - - void firstOut(Edge& edge, const Node& node) const { - edge.id = node.id != 0 ? node.id * (node.id - 1) / 2 : -1; - } - - /// \todo with specialized iterators we can make faster iterating - void nextOut(Edge& e) const { - int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;; - int target = e.id - (source) * (source - 1) / 2; - ++target; - e.id = target < source ? source * (source - 1) / 2 + target : -1; - } - - void firstIn(Edge& edge, const Node& node) const { - edge.id = node.id * (node.id + 1) / 2 - 1; - } - - void nextIn(Edge& e) const { - int source = ((int)sqrt((double)(1 + 8 * e.id)) + 1) / 2;; - int target = e.id - (source) * (source - 1) / 2; ++target; - ++source; - e.id = source < NodeNum ? source * (source - 1) / 2 + target : -1; - } - - }; - - /// \todo UndirFullGraph from the UndirFullGraphBase - - - - /// @} - -} //namespace lemon - - -#endif //LEMON_FULL_GRAPH_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/graph_adaptor.h --- a/src/lemon/graph_adaptor.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1218 +0,0 @@ -/* -*- C++ -*- - * src/lemon/graph_adaptor.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_GRAPH_ADAPTOR_H -#define LEMON_GRAPH_ADAPTOR_H - -///\ingroup graph_adaptors -///\file -///\brief Several graph adaptors. -/// -///This file contains several useful graph adaptor functions. -/// -///\author Marton Makai - -#include -#include -#include -#include -#include - -namespace lemon { - - // Graph adaptors - - /*! - \addtogroup graph_adaptors - @{ - */ - - /*! - Base type for the Graph Adaptors - - \warning Graph adaptors are in even more experimental state than the other - parts of the lib. Use them at you own risk. - - This is the base type for most of LEMON graph adaptors. - This class implements a trivial graph adaptor i.e. it only wraps the - functions and types of the graph. The purpose of this class is to - make easier implementing graph adaptors. E.g. if an adaptor is - considered which differs from the wrapped graph only in some of its - functions or types, then it can be derived from GraphAdaptor, and only the - differences should be implemented. - - \author Marton Makai - */ - template - class GraphAdaptorBase { - public: - typedef _Graph Graph; - /// \todo Is it needed? - typedef Graph BaseGraph; - typedef Graph ParentGraph; - - protected: - Graph* graph; - GraphAdaptorBase() : graph(0) { } - void setGraph(Graph& _graph) { graph=&_graph; } - - public: - GraphAdaptorBase(Graph& _graph) : graph(&_graph) { } - - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - - void first(Node& i) const { graph->first(i); } - void first(Edge& i) const { graph->first(i); } - void firstIn(Edge& i, const Node& n) const { graph->firstIn(i, n); } - void firstOut(Edge& i, const Node& n ) const { graph->firstOut(i, n); } - - void next(Node& i) const { graph->next(i); } - void next(Edge& i) const { graph->next(i); } - void nextIn(Edge& i) const { graph->nextIn(i); } - void nextOut(Edge& i) const { graph->nextOut(i); } - - Node source(const Edge& e) const { return graph->source(e); } - Node target(const Edge& e) const { return graph->target(e); } - - int nodeNum() const { return graph->nodeNum(); } - int edgeNum() const { return graph->edgeNum(); } - - Node addNode() const { return Node(graph->addNode()); } - Edge addEdge(const Node& source, const Node& target) const { - return Edge(graph->addEdge(source, target)); } - - void erase(const Node& i) const { graph->erase(i); } - void erase(const Edge& i) const { graph->erase(i); } - - void clear() const { graph->clear(); } - - bool forward(const Edge& e) const { return graph->forward(e); } - bool backward(const Edge& e) const { return graph->backward(e); } - - int id(const Node& v) const { return graph->id(v); } - int id(const Edge& e) const { return graph->id(e); } - - Edge opposite(const Edge& e) const { return Edge(graph->opposite(e)); } - - template - class NodeMap : public _Graph::template NodeMap<_Value> { - public: - typedef typename _Graph::template NodeMap<_Value> Parent; - NodeMap(const GraphAdaptorBase<_Graph>& gw) : Parent(*gw.graph) { } - NodeMap(const GraphAdaptorBase<_Graph>& gw, const _Value& value) - : Parent(*gw.graph, value) { } - }; - - template - class EdgeMap : public _Graph::template EdgeMap<_Value> { - public: - typedef typename _Graph::template EdgeMap<_Value> Parent; - EdgeMap(const GraphAdaptorBase<_Graph>& gw) : Parent(*gw.graph) { } - EdgeMap(const GraphAdaptorBase<_Graph>& gw, const _Value& value) - : Parent(*gw.graph, value) { } - }; - - }; - - template - class GraphAdaptor : - public IterableGraphExtender > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender > Parent; - protected: - GraphAdaptor() : Parent() { } - - public: - GraphAdaptor(Graph& _graph) { setGraph(_graph); } - }; - - template - class RevGraphAdaptorBase : public GraphAdaptorBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphAdaptorBase<_Graph> Parent; - protected: - RevGraphAdaptorBase() : Parent() { } - public: - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - - // using Parent::first; - void firstIn(Edge& i, const Node& n) const { Parent::firstOut(i, n); } - void firstOut(Edge& i, const Node& n ) const { Parent::firstIn(i, n); } - - // using Parent::next; - void nextIn(Edge& i) const { Parent::nextOut(i); } - void nextOut(Edge& i) const { Parent::nextIn(i); } - - Node source(const Edge& e) const { return Parent::target(e); } - Node target(const Edge& e) const { return Parent::source(e); } - }; - - - /// A graph adaptor which reverses the orientation of the edges. - - ///\warning Graph adaptors are in even more experimental state than the other - ///parts of the lib. Use them at you own risk. - /// - /// Let \f$G=(V, A)\f$ be a directed graph and - /// suppose that a graph instange \c g of type - /// \c ListGraph implements \f$G\f$. - /// \code - /// ListGraph g; - /// \endcode - /// For each directed edge - /// \f$e\in A\f$, let \f$\bar e\f$ denote the edge obtained by - /// reversing its orientation. - /// Then RevGraphAdaptor implements the graph structure with node-set - /// \f$V\f$ and edge-set - /// \f$\{\bar e : e\in A \}\f$, i.e. the graph obtained from \f$G\f$ be - /// reversing the orientation of its edges. The following code shows how - /// such an instance can be constructed. - /// \code - /// RevGraphAdaptor gw(g); - /// \endcode - ///\author Marton Makai - template - class RevGraphAdaptor : - public IterableGraphExtender > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - RevGraphAdaptorBase<_Graph> > Parent; - protected: - RevGraphAdaptor() { } - public: - RevGraphAdaptor(_Graph& _graph) { setGraph(_graph); } - }; - - - template - class SubGraphAdaptorBase : public GraphAdaptorBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphAdaptorBase<_Graph> Parent; - protected: - NodeFilterMap* node_filter_map; - EdgeFilterMap* edge_filter_map; - SubGraphAdaptorBase() : Parent(), - node_filter_map(0), edge_filter_map(0) { } - - void setNodeFilterMap(NodeFilterMap& _node_filter_map) { - node_filter_map=&_node_filter_map; - } - void setEdgeFilterMap(EdgeFilterMap& _edge_filter_map) { - edge_filter_map=&_edge_filter_map; - } - - public: -// SubGraphAdaptorBase(Graph& _graph, -// NodeFilterMap& _node_filter_map, -// EdgeFilterMap& _edge_filter_map) : -// Parent(&_graph), -// node_filter_map(&node_filter_map), -// edge_filter_map(&edge_filter_map) { } - - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - - void first(Node& i) const { - Parent::first(i); - while (i!=INVALID && !(*node_filter_map)[i]) Parent::next(i); - } - void first(Edge& i) const { - Parent::first(i); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::next(i); - } - void firstIn(Edge& i, const Node& n) const { - Parent::firstIn(i, n); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextIn(i); - } - void firstOut(Edge& i, const Node& n) const { - Parent::firstOut(i, n); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextOut(i); - } - - void next(Node& i) const { - Parent::next(i); - while (i!=INVALID && !(*node_filter_map)[i]) Parent::next(i); - } - void next(Edge& i) const { - Parent::next(i); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::next(i); - } - void nextIn(Edge& i) const { - Parent::nextIn(i); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextIn(i); - } - void nextOut(Edge& i) const { - Parent::nextOut(i); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextOut(i); - } - - /// This function hides \c n in the graph, i.e. the iteration - /// jumps over it. This is done by simply setting the value of \c n - /// to be false in the corresponding node-map. - void hide(const Node& n) const { node_filter_map->set(n, false); } - - /// This function hides \c e in the graph, i.e. the iteration - /// jumps over it. This is done by simply setting the value of \c e - /// to be false in the corresponding edge-map. - void hide(const Edge& e) const { edge_filter_map->set(e, false); } - - /// The value of \c n is set to be true in the node-map which stores - /// hide information. If \c n was hidden previuosly, then it is shown - /// again - void unHide(const Node& n) const { node_filter_map->set(n, true); } - - /// The value of \c e is set to be true in the edge-map which stores - /// hide information. If \c e was hidden previuosly, then it is shown - /// again - void unHide(const Edge& e) const { edge_filter_map->set(e, true); } - - /// Returns true if \c n is hidden. - bool hidden(const Node& n) const { return !(*node_filter_map)[n]; } - - /// Returns true if \c n is hidden. - bool hidden(const Edge& e) const { return !(*edge_filter_map)[e]; } - - /// \warning This is a linear time operation and works only if s - /// \c Graph::NodeIt is defined. - /// \todo assign tags. - int nodeNum() const { - int i=0; - Node n; - for (first(n); n!=INVALID; next(n)) ++i; - return i; - } - - /// \warning This is a linear time operation and works only if - /// \c Graph::EdgeIt is defined. - /// \todo assign tags. - int edgeNum() const { - int i=0; - Edge e; - for (first(e); e!=INVALID; next(e)) ++i; - return i; - } - - - }; - - /*! \brief A graph adaptor for hiding nodes and edges from a graph. - - \warning Graph adaptors are in even more experimental state than the other - parts of the lib. Use them at you own risk. - - SubGraphAdaptor shows the graph with filtered node-set and - edge-set. - Let \f$G=(V, A)\f$ be a directed graph - and suppose that the graph instance \c g of type ListGraph implements - \f$G\f$. - Let moreover \f$b_V\f$ and - \f$b_A\f$ be bool-valued functions resp. on the node-set and edge-set. - SubGraphAdaptor<...>::NodeIt iterates - on the node-set \f$\{v\in V : b_V(v)=true\}\f$ and - SubGraphAdaptor<...>::EdgeIt iterates - on the edge-set \f$\{e\in A : b_A(e)=true\}\f$. Similarly, - SubGraphAdaptor<...>::OutEdgeIt and SubGraphAdaptor<...>::InEdgeIt iterates - only on edges leaving and entering a specific node which have true value. - - We have to note that this does not mean that an - induced subgraph is obtained, the node-iterator cares only the filter - on the node-set, and the edge-iterators care only the filter on the - edge-set. - \code - typedef ListGraph Graph; - Graph g; - typedef Graph::Node Node; - typedef Graph::Edge Edge; - Node u=g.addNode(); //node of id 0 - Node v=g.addNode(); //node of id 1 - Node e=g.addEdge(u, v); //edge of id 0 - Node f=g.addEdge(v, u); //edge of id 1 - Graph::NodeMap nm(g, true); - nm.set(u, false); - Graph::EdgeMap em(g, true); - em.set(e, false); - typedef SubGraphAdaptor, Graph::EdgeMap > SubGW; - SubGW gw(g, nm, em); - for (SubGW::NodeIt n(gw); n!=INVALID; ++n) std::cout << g.id(n) << std::endl; - std::cout << ":-)" << std::endl; - for (SubGW::EdgeIt e(gw); e!=INVALID; ++e) std::cout << g.id(e) << std::endl; - \endcode - The output of the above code is the following. - \code - 1 - :-) - 1 - \endcode - Note that \c n is of type \c SubGW::NodeIt, but it can be converted to - \c Graph::Node that is why \c g.id(n) can be applied. - - For other examples see also the documentation of NodeSubGraphAdaptor and - EdgeSubGraphAdaptor. - - \author Marton Makai - */ - template - class SubGraphAdaptor : - public IterableGraphExtender< - SubGraphAdaptorBase<_Graph, NodeFilterMap, EdgeFilterMap> > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - SubGraphAdaptorBase<_Graph, NodeFilterMap, EdgeFilterMap> > Parent; - protected: - SubGraphAdaptor() { } - public: - SubGraphAdaptor(_Graph& _graph, NodeFilterMap& _node_filter_map, - EdgeFilterMap& _edge_filter_map) { - setGraph(_graph); - setNodeFilterMap(_node_filter_map); - setEdgeFilterMap(_edge_filter_map); - } - }; - - - - /*! \brief An adaptor for hiding nodes from a graph. - - \warning Graph adaptors are in even more experimental state than the other - parts of the lib. Use them at you own risk. - - An adaptor for hiding nodes from a graph. - This adaptor specializes SubGraphAdaptor in the way that only the node-set - can be filtered. Note that this does not mean of considering induced - subgraph, the edge-iterators consider the original edge-set. - \author Marton Makai - */ - template - class NodeSubGraphAdaptor : - public SubGraphAdaptor > { - public: - typedef SubGraphAdaptor > Parent; - protected: - ConstMap const_true_map; - public: - NodeSubGraphAdaptor(Graph& _graph, NodeFilterMap& _node_filter_map) : - Parent(), const_true_map(true) { - Parent::setGraph(_graph); - Parent::setNodeFilterMap(_node_filter_map); - Parent::setEdgeFilterMap(const_true_map); - } - }; - - - /*! \brief An adaptor for hiding edges from a graph. - - \warning Graph adaptors are in even more experimental state than the other - parts of the lib. Use them at you own risk. - - An adaptor for hiding edges from a graph. - This adaptor specializes SubGraphAdaptor in the way that only the edge-set - can be filtered. The usefulness of this adaptor is demonstrated in the - problem of searching a maximum number of edge-disjoint shortest paths - between - two nodes \c s and \c t. Shortest here means being shortest w.r.t. - non-negative edge-lengths. Note that - the comprehension of the presented solution - need's some elementary knowledge from combinatorial optimization. - - If a single shortest path is to be - searched between \c s and \c t, then this can be done easily by - applying the Dijkstra algorithm. What happens, if a maximum number of - edge-disjoint shortest paths is to be computed. It can be proved that an - edge can be in a shortest path if and only if it is tight with respect to - the potential function computed by Dijkstra. Moreover, any path containing - only such edges is a shortest one. Thus we have to compute a maximum number - of edge-disjoint paths between \c s and \c t in the graph which has edge-set - all the tight edges. The computation will be demonstrated on the following - graph, which is read from the dimacs file \ref sub_graph_adaptor_demo.dim. - The full source code is available in \ref sub_graph_adaptor_demo.cc. - If you are interested in more demo programs, you can use - \ref dim_to_dot.cc to generate .dot files from dimacs files. - The .dot file of the following figure of was generated generated by - the demo program \ref dim_to_dot.cc. - - \dot - digraph lemon_dot_example { - node [ shape=ellipse, fontname=Helvetica, fontsize=10 ]; - n0 [ label="0 (s)" ]; - n1 [ label="1" ]; - n2 [ label="2" ]; - n3 [ label="3" ]; - n4 [ label="4" ]; - n5 [ label="5" ]; - n6 [ label="6 (t)" ]; - edge [ shape=ellipse, fontname=Helvetica, fontsize=10 ]; - n5 -> n6 [ label="9, length:4" ]; - n4 -> n6 [ label="8, length:2" ]; - n3 -> n5 [ label="7, length:1" ]; - n2 -> n5 [ label="6, length:3" ]; - n2 -> n6 [ label="5, length:5" ]; - n2 -> n4 [ label="4, length:2" ]; - n1 -> n4 [ label="3, length:3" ]; - n0 -> n3 [ label="2, length:1" ]; - n0 -> n2 [ label="1, length:2" ]; - n0 -> n1 [ label="0, length:3" ]; - } - \enddot - - \code - Graph g; - Node s, t; - LengthMap length(g); - - readDimacs(std::cin, g, length, s, t); - - cout << "edges with lengths (of form id, source--length->target): " << endl; - for(EdgeIt e(g); e!=INVALID; ++e) - cout << g.id(e) << ", " << g.id(g.source(e)) << "--" - << length[e] << "->" << g.id(g.target(e)) << endl; - - cout << "s: " << g.id(s) << " t: " << g.id(t) << endl; - \endcode - Next, the potential function is computed with Dijkstra. - \code - typedef Dijkstra Dijkstra; - Dijkstra dijkstra(g, length); - dijkstra.run(s); - \endcode - Next, we consrtruct a map which filters the edge-set to the tight edges. - \code - typedef TightEdgeFilterMap - TightEdgeFilter; - TightEdgeFilter tight_edge_filter(g, dijkstra.distMap(), length); - - typedef EdgeSubGraphAdaptor SubGW; - SubGW gw(g, tight_edge_filter); - \endcode - Then, the maximum nimber of edge-disjoint \c s-\c t paths are computed - with a max flow algorithm Preflow. - \code - ConstMap const_1_map(1); - Graph::EdgeMap flow(g, 0); - - Preflow, Graph::EdgeMap > - preflow(gw, s, t, const_1_map, flow); - preflow.run(); - \endcode - Last, the output is: - \code - cout << "maximum number of edge-disjoint shortest path: " - << preflow.flowValue() << endl; - cout << "edges of the maximum number of edge-disjoint shortest s-t paths: " - << endl; - for(EdgeIt e(g); e!=INVALID; ++e) - if (flow[e]) - cout << " " << g.id(g.source(e)) << "--" - << length[e] << "->" << g.id(g.target(e)) << endl; - \endcode - The program has the following (expected :-)) output: - \code - edges with lengths (of form id, source--length->target): - 9, 5--4->6 - 8, 4--2->6 - 7, 3--1->5 - 6, 2--3->5 - 5, 2--5->6 - 4, 2--2->4 - 3, 1--3->4 - 2, 0--1->3 - 1, 0--2->2 - 0, 0--3->1 - s: 0 t: 6 - maximum number of edge-disjoint shortest path: 2 - edges of the maximum number of edge-disjoint shortest s-t paths: - 9, 5--4->6 - 8, 4--2->6 - 7, 3--1->5 - 4, 2--2->4 - 2, 0--1->3 - 1, 0--2->2 - \endcode - - \author Marton Makai - */ - template - class EdgeSubGraphAdaptor : - public SubGraphAdaptor, - EdgeFilterMap> { - public: - typedef SubGraphAdaptor, - EdgeFilterMap> Parent; - protected: - ConstMap const_true_map; - public: - EdgeSubGraphAdaptor(Graph& _graph, EdgeFilterMap& _edge_filter_map) : - Parent(), const_true_map(true) { - Parent::setGraph(_graph); - Parent::setNodeFilterMap(const_true_map); - Parent::setEdgeFilterMap(_edge_filter_map); - } - }; - - template - class UndirGraphAdaptorBase : - public UndirGraphExtender > { - public: - typedef _Graph Graph; - typedef UndirGraphExtender > Parent; - protected: - UndirGraphAdaptorBase() : Parent() { } - public: - typedef typename Parent::UndirEdge UndirEdge; - typedef typename Parent::Edge Edge; - - /// \bug Why cant an edge say that it is forward or not??? - /// By this, a pointer to the graph have to be stored - /// The implementation - template - class EdgeMap { - protected: - const UndirGraphAdaptorBase<_Graph>* g; - template friend class EdgeMap; - typename _Graph::template EdgeMap forward_map, backward_map; - public: - typedef T Value; - typedef Edge Key; - - EdgeMap(const UndirGraphAdaptorBase<_Graph>& _g) : g(&_g), - forward_map(*(g->graph)), backward_map(*(g->graph)) { } - - EdgeMap(const UndirGraphAdaptorBase<_Graph>& _g, T a) : g(&_g), - forward_map(*(g->graph), a), backward_map(*(g->graph), a) { } - - void set(Edge e, T a) { - if (g->forward(e)) - forward_map.set(e, a); - else - backward_map.set(e, a); - } - - T operator[](Edge e) const { - if (g->forward(e)) - return forward_map[e]; - else - return backward_map[e]; - } - }; - - template - class UndirEdgeMap { - template friend class UndirEdgeMap; - typename _Graph::template EdgeMap map; - public: - typedef T Value; - typedef UndirEdge Key; - - UndirEdgeMap(const UndirGraphAdaptorBase<_Graph>& g) : - map(*(g.graph)) { } - - UndirEdgeMap(const UndirGraphAdaptorBase<_Graph>& g, T a) : - map(*(g.graph), a) { } - - void set(UndirEdge e, T a) { - map.set(e, a); - } - - T operator[](UndirEdge e) const { - return map[e]; - } - }; - - }; - - /// \brief An undirected graph is made from a directed graph by an adaptor - /// - /// Undocumented, untested!!! - /// If somebody knows nice demo application, let's polulate it. - /// - /// \author Marton Makai - template - class UndirGraphAdaptor : - public IterableUndirGraphExtender< - UndirGraphAdaptorBase<_Graph> > { - public: - typedef _Graph Graph; - typedef IterableUndirGraphExtender< - UndirGraphAdaptorBase<_Graph> > Parent; - protected: - UndirGraphAdaptor() { } - public: - UndirGraphAdaptor(_Graph& _graph) { - setGraph(_graph); - } - }; - - - template - class SubBidirGraphAdaptorBase : public GraphAdaptorBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphAdaptorBase<_Graph> Parent; - protected: - ForwardFilterMap* forward_filter; - BackwardFilterMap* backward_filter; - SubBidirGraphAdaptorBase() : Parent(), - forward_filter(0), backward_filter(0) { } - - void setForwardFilterMap(ForwardFilterMap& _forward_filter) { - forward_filter=&_forward_filter; - } - void setBackwardFilterMap(BackwardFilterMap& _backward_filter) { - backward_filter=&_backward_filter; - } - - public: -// SubGraphAdaptorBase(Graph& _graph, -// NodeFilterMap& _node_filter_map, -// EdgeFilterMap& _edge_filter_map) : -// Parent(&_graph), -// node_filter_map(&node_filter_map), -// edge_filter_map(&edge_filter_map) { } - - typedef typename Parent::Node Node; - typedef typename _Graph::Edge GraphEdge; - template class EdgeMap; - /// SubBidirGraphAdaptorBase<..., ..., ...>::Edge is inherited from - /// _Graph::Edge. It contains an extra bool flag which is true - /// if and only if the - /// edge is the backward version of the original edge. - class Edge : public _Graph::Edge { - friend class SubBidirGraphAdaptorBase< - Graph, ForwardFilterMap, BackwardFilterMap>; - template friend class EdgeMap; - protected: - bool backward; //true, iff backward - public: - Edge() { } - /// \todo =false is needed, or causes problems? - /// If \c _backward is false, then we get an edge corresponding to the - /// original one, otherwise its oppositely directed pair is obtained. - Edge(const typename _Graph::Edge& e, bool _backward/*=false*/) : - _Graph::Edge(e), backward(_backward) { } - Edge(Invalid i) : _Graph::Edge(i), backward(true) { } - bool operator==(const Edge& v) const { - return (this->backward==v.backward && - static_cast(*this)== - static_cast(v)); - } - bool operator!=(const Edge& v) const { - return (this->backward!=v.backward || - static_cast(*this)!= - static_cast(v)); - } - }; - - void first(Node& i) const { - Parent::first(i); - } - - void first(Edge& i) const { - Parent::first(i); - i.backward=false; - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::next(i); - if (*static_cast(&i)==INVALID) { - Parent::first(i); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::next(i); - } - } - - void firstIn(Edge& i, const Node& n) const { - Parent::firstIn(i, n); - i.backward=false; - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::nextIn(i); - if (*static_cast(&i)==INVALID) { - Parent::firstOut(i, n); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextOut(i); - } - } - - void firstOut(Edge& i, const Node& n) const { - Parent::firstOut(i, n); - i.backward=false; - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::nextOut(i); - if (*static_cast(&i)==INVALID) { - Parent::firstIn(i, n); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextIn(i); - } - } - - void next(Node& i) const { - Parent::next(i); - } - - void next(Edge& i) const { - if (!(i.backward)) { - Parent::next(i); - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::next(i); - if (*static_cast(&i)==INVALID) { - Parent::first(i); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::next(i); - } - } else { - Parent::next(i); - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::next(i); - } - } - - void nextIn(Edge& i) const { - if (!(i.backward)) { - Node n=Parent::target(i); - Parent::nextIn(i); - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::nextIn(i); - if (*static_cast(&i)==INVALID) { - Parent::firstOut(i, n); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextOut(i); - } - } else { - Parent::nextOut(i); - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextOut(i); - } - } - - void nextOut(Edge& i) const { - if (!(i.backward)) { - Node n=Parent::source(i); - Parent::nextOut(i); - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::nextOut(i); - if (*static_cast(&i)==INVALID) { - Parent::firstIn(i, n); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextIn(i); - } - } else { - Parent::nextIn(i); - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextIn(i); - } - } - - Node source(Edge e) const { - return ((!e.backward) ? this->graph->source(e) : this->graph->target(e)); } - Node target(Edge e) const { - return ((!e.backward) ? this->graph->target(e) : this->graph->source(e)); } - - /// Gives back the opposite edge. - Edge opposite(const Edge& e) const { - Edge f=e; - f.backward=!f.backward; - return f; - } - - /// \warning This is a linear time operation and works only if - /// \c Graph::EdgeIt is defined. - /// \todo hmm - int edgeNum() const { - int i=0; - Edge e; - for (first(e); e!=INVALID; next(e)) ++i; - return i; - } - - bool forward(const Edge& e) const { return !e.backward; } - bool backward(const Edge& e) const { return e.backward; } - - template - /// \c SubBidirGraphAdaptorBase<..., ..., ...>::EdgeMap contains two - /// _Graph::EdgeMap one for the forward edges and - /// one for the backward edges. - class EdgeMap { - template friend class EdgeMap; - typename _Graph::template EdgeMap forward_map, backward_map; - public: - typedef T Value; - typedef Edge Key; - - EdgeMap(const SubBidirGraphAdaptorBase<_Graph, - ForwardFilterMap, BackwardFilterMap>& g) : - forward_map(*(g.graph)), backward_map(*(g.graph)) { } - - EdgeMap(const SubBidirGraphAdaptorBase<_Graph, - ForwardFilterMap, BackwardFilterMap>& g, T a) : - forward_map(*(g.graph), a), backward_map(*(g.graph), a) { } - - void set(Edge e, T a) { - if (!e.backward) - forward_map.set(e, a); - else - backward_map.set(e, a); - } - -// typename _Graph::template EdgeMap::ConstReference -// operator[](Edge e) const { -// if (!e.backward) -// return forward_map[e]; -// else -// return backward_map[e]; -// } - -// typename _Graph::template EdgeMap::Reference - T operator[](Edge e) const { - if (!e.backward) - return forward_map[e]; - else - return backward_map[e]; - } - - void update() { - forward_map.update(); - backward_map.update(); - } - }; - - }; - - - ///\brief An adaptor for composing a subgraph of a - /// bidirected graph made from a directed one. - /// - /// An adaptor for composing a subgraph of a - /// bidirected graph made from a directed one. - /// - ///\warning Graph adaptors are in even more experimental state than the other - ///parts of the lib. Use them at you own risk. - /// - /// Let \f$G=(V, A)\f$ be a directed graph and for each directed edge - /// \f$e\in A\f$, let \f$\bar e\f$ denote the edge obtained by - /// reversing its orientation. We are given moreover two bool valued - /// maps on the edge-set, - /// \f$forward\_filter\f$, and \f$backward\_filter\f$. - /// SubBidirGraphAdaptor implements the graph structure with node-set - /// \f$V\f$ and edge-set - /// \f$\{e : e\in A \mbox{ and } forward\_filter(e) \mbox{ is true}\}+\{\bar e : e\in A \mbox{ and } backward\_filter(e) \mbox{ is true}\}\f$. - /// The purpose of writing + instead of union is because parallel - /// edges can arise. (Similarly, antiparallel edges also can arise). - /// In other words, a subgraph of the bidirected graph obtained, which - /// is given by orienting the edges of the original graph in both directions. - /// As the oppositely directed edges are logically different, - /// the maps are able to attach different values for them. - /// - /// An example for such a construction is \c RevGraphAdaptor where the - /// forward_filter is everywhere false and the backward_filter is - /// everywhere true. We note that for sake of efficiency, - /// \c RevGraphAdaptor is implemented in a different way. - /// But BidirGraphAdaptor is obtained from - /// SubBidirGraphAdaptor by considering everywhere true - /// valued maps both for forward_filter and backward_filter. - /// - /// The most important application of SubBidirGraphAdaptor - /// is ResGraphAdaptor, which stands for the residual graph in directed - /// flow and circulation problems. - /// As adaptors usually, the SubBidirGraphAdaptor implements the - /// above mentioned graph structure without its physical storage, - /// that is the whole stuff is stored in constant memory. - template - class SubBidirGraphAdaptor : - public IterableGraphExtender< - SubBidirGraphAdaptorBase<_Graph, ForwardFilterMap, BackwardFilterMap> > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - SubBidirGraphAdaptorBase< - _Graph, ForwardFilterMap, BackwardFilterMap> > Parent; - protected: - SubBidirGraphAdaptor() { } - public: - SubBidirGraphAdaptor(_Graph& _graph, ForwardFilterMap& _forward_filter, - BackwardFilterMap& _backward_filter) { - setGraph(_graph); - setForwardFilterMap(_forward_filter); - setBackwardFilterMap(_backward_filter); - } - }; - - - - ///\brief An adaptor for composing bidirected graph from a directed one. - /// - ///\warning Graph adaptors are in even more experimental state than the other - ///parts of the lib. Use them at you own risk. - /// - /// An adaptor for composing bidirected graph from a directed one. - /// A bidirected graph is composed over the directed one without physical - /// storage. As the oppositely directed edges are logically different ones - /// the maps are able to attach different values for them. - template - class BidirGraphAdaptor : - public SubBidirGraphAdaptor< - Graph, - ConstMap, - ConstMap > { - public: - typedef SubBidirGraphAdaptor< - Graph, - ConstMap, - ConstMap > Parent; - protected: - ConstMap cm; - - BidirGraphAdaptor() : Parent(), cm(true) { - Parent::setForwardFilterMap(cm); - Parent::setBackwardFilterMap(cm); - } - public: - BidirGraphAdaptor(Graph& _graph) : Parent(), cm(true) { - Parent::setGraph(_graph); - Parent::setForwardFilterMap(cm); - Parent::setBackwardFilterMap(cm); - } - - int edgeNum() const { - return 2*this->graph->edgeNum(); - } - // KEEP_MAPS(Parent, BidirGraphAdaptor); - }; - - - template - class ResForwardFilter { - // const Graph* graph; - const CapacityMap* capacity; - const FlowMap* flow; - public: - ResForwardFilter(/*const Graph& _graph, */ - const CapacityMap& _capacity, const FlowMap& _flow) : - /*graph(&_graph),*/ capacity(&_capacity), flow(&_flow) { } - ResForwardFilter() : /*graph(0),*/ capacity(0), flow(0) { } - void setCapacity(const CapacityMap& _capacity) { capacity=&_capacity; } - void setFlow(const FlowMap& _flow) { flow=&_flow; } - bool operator[](const typename Graph::Edge& e) const { - return (Number((*flow)[e]) < Number((*capacity)[e])); - } - }; - - template - class ResBackwardFilter { - const CapacityMap* capacity; - const FlowMap* flow; - public: - ResBackwardFilter(/*const Graph& _graph,*/ - const CapacityMap& _capacity, const FlowMap& _flow) : - /*graph(&_graph),*/ capacity(&_capacity), flow(&_flow) { } - ResBackwardFilter() : /*graph(0),*/ capacity(0), flow(0) { } - void setCapacity(const CapacityMap& _capacity) { capacity=&_capacity; } - void setFlow(const FlowMap& _flow) { flow=&_flow; } - bool operator[](const typename Graph::Edge& e) const { - return (Number(0) < Number((*flow)[e])); - } - }; - - - /*! \brief An adaptor for composing the residual graph for directed flow and circulation problems. - - An adaptor for composing the residual graph for directed flow and circulation problems. - Let \f$G=(V, A)\f$ be a directed graph and let \f$F\f$ be a - number type. Let moreover - \f$f,c:A\to F\f$, be functions on the edge-set. - In the appications of ResGraphAdaptor, \f$f\f$ usually stands for a flow - and \f$c\f$ for a capacity function. - Suppose that a graph instange \c g of type - \c ListGraph implements \f$G\f$. - \code - ListGraph g; - \endcode - Then RevGraphAdaptor implements the graph structure with node-set - \f$V\f$ and edge-set \f$A_{forward}\cup A_{backward}\f$, where - \f$A_{forward}=\{uv : uv\in A, f(uv)0\}\f$, - i.e. the so called residual graph. - When we take the union \f$A_{forward}\cup A_{backward}\f$, - multilicities are counted, i.e. if an edge is in both - \f$A_{forward}\f$ and \f$A_{backward}\f$, then in the adaptor it - appears twice. - The following code shows how - such an instance can be constructed. - \code - typedef ListGraph Graph; - Graph::EdgeMap f(g); - Graph::EdgeMap c(g); - ResGraphAdaptor, Graph::EdgeMap > gw(g); - \endcode - \author Marton Makai - */ - template - class ResGraphAdaptor : - public SubBidirGraphAdaptor< - Graph, - ResForwardFilter, - ResBackwardFilter > { - public: - typedef SubBidirGraphAdaptor< - Graph, - ResForwardFilter, - ResBackwardFilter > Parent; - protected: - const CapacityMap* capacity; - FlowMap* flow; - ResForwardFilter forward_filter; - ResBackwardFilter backward_filter; - ResGraphAdaptor() : Parent(), - capacity(0), flow(0) { } - void setCapacityMap(const CapacityMap& _capacity) { - capacity=&_capacity; - forward_filter.setCapacity(_capacity); - backward_filter.setCapacity(_capacity); - } - void setFlowMap(FlowMap& _flow) { - flow=&_flow; - forward_filter.setFlow(_flow); - backward_filter.setFlow(_flow); - } - public: - ResGraphAdaptor(Graph& _graph, const CapacityMap& _capacity, - FlowMap& _flow) : - Parent(), capacity(&_capacity), flow(&_flow), - forward_filter(/*_graph,*/ _capacity, _flow), - backward_filter(/*_graph,*/ _capacity, _flow) { - Parent::setGraph(_graph); - Parent::setForwardFilterMap(forward_filter); - Parent::setBackwardFilterMap(backward_filter); - } - - typedef typename Parent::Edge Edge; - - void augment(const Edge& e, Number a) const { - if (Parent::forward(e)) - flow->set(e, (*flow)[e]+a); - else - flow->set(e, (*flow)[e]-a); - } - - /// \brief Residual capacity map. - /// - /// In generic residual graphs the residual capacity can be obtained - /// as a map. - class ResCap { - protected: - const ResGraphAdaptor* res_graph; - public: - typedef Number Value; - typedef Edge Key; - ResCap(const ResGraphAdaptor& - _res_graph) : res_graph(&_res_graph) { } - Number operator[](const Edge& e) const { - if (res_graph->forward(e)) - return (*(res_graph->capacity))[e]-(*(res_graph->flow))[e]; - else - return (*(res_graph->flow))[e]; - } - }; - - // KEEP_MAPS(Parent, ResGraphAdaptor); - }; - - - - template - class ErasingFirstGraphAdaptorBase : public GraphAdaptorBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphAdaptorBase<_Graph> Parent; - protected: - FirstOutEdgesMap* first_out_edges; - ErasingFirstGraphAdaptorBase() : Parent(), - first_out_edges(0) { } - - void setFirstOutEdgesMap(FirstOutEdgesMap& _first_out_edges) { - first_out_edges=&_first_out_edges; - } - - public: - - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - - void firstOut(Edge& i, const Node& n) const { - i=(*first_out_edges)[n]; - } - - void erase(const Edge& e) const { - Node n=source(e); - Edge f=e; - Parent::nextOut(f); - first_out_edges->set(n, f); - } - }; - - - /// For blocking flows. - - ///\warning Graph adaptors are in even more experimental state than the other - ///parts of the lib. Use them at you own risk. - /// - /// This graph adaptor is used for on-the-fly - /// Dinits blocking flow computations. - /// For each node, an out-edge is stored which is used when the - /// \code - /// OutEdgeIt& first(OutEdgeIt&, const Node&) - /// \endcode - /// is called. - /// - /// \author Marton Makai - template - class ErasingFirstGraphAdaptor : - public IterableGraphExtender< - ErasingFirstGraphAdaptorBase<_Graph, FirstOutEdgesMap> > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - ErasingFirstGraphAdaptorBase<_Graph, FirstOutEdgesMap> > Parent; - ErasingFirstGraphAdaptor(Graph& _graph, - FirstOutEdgesMap& _first_out_edges) { - setGraph(_graph); - setFirstOutEdgesMap(_first_out_edges); - } - - }; - - ///@} - -} //namespace lemon - -#endif //LEMON_GRAPH_ADAPTOR_H - diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/graph_reader.h --- a/src/lemon/graph_reader.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,808 +0,0 @@ -/* -*- C++ -*- - * src/lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -///\ingroup io_group -///\file -///\brief Lemon Graph Format reader. - -#ifndef LEMON_GRAPH_READER_H -#define LEMON_GRAPH_READER_H - -#include - -#include -#include - -namespace lemon { - - /// \addtogroup io_group - /// @{ - - /// \brief The graph reader class. - /// - /// The given file format may contain several maps and labeled nodes or - /// edges. - /// - /// If you read a graph you need not read all the maps and items just those - /// that you need. The interface of the \c GraphReader is very similar to - /// the GraphWriter but the reading method does not depend on the order the - /// given commands. - /// - /// The reader object suppose that each not readed value does not contain - /// whitespaces, therefore it has some extra possibilities to control how - /// it should skip the values when the string representation contains spaces. - /// - /// \code - /// GraphReader reader(std::cin, graph); - /// \endcode - /// - /// The \c readNodeMap() function reads a map from the \c \@nodeset section. - /// If there is a map that you do not want to read from the file and there is - /// whitespace in the string represenation of the values then you should - /// call the \c skipNodeMap() template member function with proper - /// parameters. - /// - /// \code - /// reader.readNodeMap("coords", coords); - /// - /// reader.readNodeMap("label", labelMap); - /// reader.skipNodeMap("description"); - /// - /// reader.readNodeMap("color", colorMap); - /// \endcode - /// - /// With the \c readEdgeMap() member function you can give an edge map - /// reading command similar to the NodeMaps. - /// - /// \code - /// reader.readEdgeMap("weight", weightMap); - /// reader.readEdgeMap("label", labelMap); - /// \endcode - /// - /// With \c readNode() and \c readEdge() functions you can read - /// labeled Nodes and Edges. - /// - /// \code - /// reader.readNode("source", sourceNode); - /// reader.readNode("target", targetNode); - /// - /// reader.readEdge("observed", edge); - /// \endcode - /// - /// With the \c readAttribute() functions you can read an attribute - /// in a variable. You can specify the reader for the attribute as - /// the nodemaps. - /// - /// After you give all read commands you must call the \c run() member - /// function, which execute all the commands. - /// - /// \code - /// reader.run(); - /// \endcode - /// - /// \see DefaultReaderTraits - /// \see QuotedStringReader - /// \see \ref GraphWriter - /// \see \ref graph-io-page - /// \author Balazs Dezso - template - class GraphReader { - public: - - typedef _Graph Graph; - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - - typedef _ReaderTraits ReaderTraits; - typedef typename ReaderTraits::Skipper DefaultSkipper; - - /// \brief Construct a new GraphReader. - /// - /// Construct a new GraphReader. It reads into the given graph - /// and it use the given reader as the default skipper. - GraphReader(std::istream& _is, - typename SmartParameter::Type _graph, - const DefaultSkipper& _skipper = DefaultSkipper()) - : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper), - nodeset_reader(*reader, _graph, std::string(), skipper), - edgeset_reader(*reader, _graph, nodeset_reader, - std::string(), skipper), - node_reader(*reader, nodeset_reader, std::string()), - edge_reader(*reader, edgeset_reader, std::string()), - attribute_reader(*reader, std::string()) {} - - /// \brief Construct a new GraphReader. - /// - /// Construct a new GraphReader. It reads into the given graph - /// and it use the given reader as the default skipper. - GraphReader(const std::string& _filename, - typename SmartParameter::Type _graph, - const DefaultSkipper& _skipper = DefaultSkipper()) - : reader(new LemonReader(_filename)), own_reader(true), - skipper(_skipper), - nodeset_reader(*reader, _graph, std::string(), skipper), - edgeset_reader(*reader, _graph, nodeset_reader, - std::string(), skipper), - node_reader(*reader, nodeset_reader, std::string()), - edge_reader(*reader, edgeset_reader, std::string()), - attribute_reader(*reader, std::string()) {} - - /// \brief Construct a new GraphReader. - /// - /// Construct a new GraphReader. It reads into the given graph - /// and it use the given reader as the default skipper. - GraphReader(LemonReader& _reader, - typename SmartParameter::Type _graph, - const DefaultSkipper& _skipper = DefaultSkipper()) - : reader(_reader), own_reader(false), skipper(_skipper), - nodeset_reader(*reader, _graph, std::string(), skipper), - edgeset_reader(*reader, _graph, nodeset_reader, - std::string(), skipper), - node_reader(*reader, nodeset_reader, std::string()), - edge_reader(*reader, edgeset_reader, std::string()), - attribute_reader(*reader, std::string()) {} - - /// \brief Destruct the graph reader. - /// - /// Destruct the graph reader. - ~GraphReader() { - if (own_reader) - delete reader; - } - - /// \brief Add a new node map reader command for the reader. - /// - /// Add a new node map reader command for the reader. - template - GraphReader& readNodeMap(std::string name, Map& map) { - nodeset_reader.readNodeMap(name, map); - return *this; - } - - template - GraphReader& readNodeMap(std::string name, const Map& map) { - nodeset_reader.readNodeMap(name, map); - return *this; - } - - /// \brief Add a new node map reader command for the reader. - /// - /// Add a new node map reader command for the reader. - template - GraphReader& readNodeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - nodeset_reader.readNodeMap(name, map, reader); - return *this; - } - - template - GraphReader& readNodeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - nodeset_reader.readNodeMap(name, map, reader); - return *this; - } - - /// \brief Add a new node map skipper command for the reader. - /// - /// Add a new node map skipper command for the reader. - template - GraphReader& skipNodeMap(std::string name, - const Reader& reader = Reader()) { - nodeset_reader.skipNodeMap(name, reader); - return *this; - } - - /// \brief Add a new edge map reader command for the reader. - /// - /// Add a new edge map reader command for the reader. - template - GraphReader& readEdgeMap(std::string name, Map& map) { - edgeset_reader.readEdgeMap(name, map); - return *this; - } - - template - GraphReader& readEdgeMap(std::string name, const Map& map) { - edgeset_reader.readEdgeMap(name, map); - return *this; - } - - - /// \brief Add a new edge map reader command for the reader. - /// - /// Add a new edge map reader command for the reader. - template - GraphReader& readEdgeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - edgeset_reader.readEdgeMap(name, map, reader); - return *this; - } - - template - GraphReader& readEdgeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - edgeset_reader.readEdgeMap(name, map, reader); - return *this; - } - - /// \brief Add a new edge map skipper command for the reader. - /// - /// Add a new edge map skipper command for the reader. - template - GraphReader& skipEdgeMap(std::string name, - const Reader& reader = Reader()) { - edgeset_reader.skipEdgeMap(name, reader); - return *this; - } - - /// \brief Add a new labeled node reader for the reader. - /// - /// Add a new labeled node reader for the reader. - GraphReader& readNode(std::string name, Node& node) { - node_reader.readNode(name, node); - return *this; - } - - /// \brief Add a new labeled edge reader for the reader. - /// - /// Add a new labeled edge reader for the reader. - GraphReader& readEdge(std::string name, Edge& edge) { - edge_reader.readEdge(name, edge); - } - - /// \brief Add a new attribute reader command. - /// - /// Add a new attribute reader command. - template - GraphReader& readAttribute(std::string name, Value& value) { - attribute_reader.readAttribute(name, value); - return *this; - } - - /// \brief Add a new attribute reader command. - /// - /// Add a new attribute reader command. - template - GraphReader& readAttribute(std::string name, Value& value, - const Reader& reader) { - attribute_reader.readAttribute(name, value, reader); - return *this; - } - - /// \brief Conversion operator to LemonReader. - /// - /// Conversion operator to LemonReader. It make possible - /// to access the encapsulated \e LemonReader, this way - /// you can attach to this reader new instances of - /// \e LemonReader::SectionReader. - operator LemonReader&() { - return *reader; - } - - /// \brief Executes the reader commands. - /// - /// Executes the reader commands. - void run() { - reader->run(); - } - - /// \brief Gives back the node by its id. - /// - /// It reads an id from the stream and gives back which node belongs to - /// it. It is possible only if there was read an "id" named node map. - Node readId(std::istream& is, Node) const { - return nodeset_reader.readId(is, Node()); - } - - /// \brief Gives back the edge by its id. - /// - /// It reads an id from the stream and gives back which edge belongs to - /// it. It is possible only if there was read an "id" named edge map. - Edge readId(std::istream& is, Edge) const { - return edgeset_reader.readId(is, Edge()); - } - - private: - - LemonReader* reader; - bool own_reader; - - DefaultSkipper skipper; - - NodeSetReader nodeset_reader; - EdgeSetReader edgeset_reader; - - NodeReader node_reader; - EdgeReader edge_reader; - - AttributeReader attribute_reader; - }; - - /// \brief Read a graph from the input. - /// - /// Read a graph from the input. - /// \param is The input stream. - /// \param g The graph. - /// \param capacity The capacity map. - /// \param s The source node. - /// \param t The target node. - /// \param cost The cost map. - template - void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, - typename Graph::Node &s, typename Graph::Node &t, - CostMap& cost) { - GraphReader reader(is, g); - reader.readEdgeMap("capacity", capacity); - reader.readEdgeMap("cost", cost); - reader.readNode("source", s); - reader.readNode("target", t); - reader.run(); - } - - /// \brief Read a graph from the input. - /// - /// Read a graph from the input. - /// \param is The input stream. - /// \param g The graph. - /// \param capacity The capacity map. - /// \param s The source node. - /// \param t The target node. - template - void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, - typename Graph::Node &s, typename Graph::Node &t) { - GraphReader reader(is, g); - reader.readEdgeMap("capacity", capacity); - reader.readNode("source", s); - reader.readNode("target", t); - reader.run(); - } - - /// \brief Read a graph from the input. - /// - /// Read a graph from the input. - /// \param is The input stream. - /// \param g The graph. - /// \param capacity The capacity map. - /// \param s The source node. - template - void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, - typename Graph::Node &s) { - GraphReader reader(is, g); - reader.readEdgeMap("capacity", capacity); - reader.readNode("source", s); - reader.run(); - } - - /// \brief Read a graph from the input. - /// - /// Read a graph from the input. - /// \param is The input stream. - /// \param g The graph. - /// \param capacity The capacity map. - template - void readGraph(std::istream& is, Graph &g, CapacityMap& capacity) { - GraphReader reader(is, g); - reader.readEdgeMap("capacity", capacity); - reader.run(); - } - - /// \brief Read a graph from the input. - /// - /// Read a graph from the input. - /// \param is The input stream. - /// \param g The graph. - template - void readGraph(std::istream& is, Graph &g) { - GraphReader reader(is, g); - reader.run(); - } - - /// \brief The undir graph reader class. - /// - /// The given file format may contain several maps and labeled nodes or - /// edges. - /// - /// If you read a graph you need not read all the maps and items just those - /// that you need. The interface of the \c GraphReader is very similar to - /// the GraphWriter but the reading method does not depend on the order the - /// given commands. - /// - /// The reader object suppose that each not readed value does not contain - /// whitespaces, therefore it has some extra possibilities to control how - /// it should skip the values when the string representation contains spaces. - /// - /// \code - /// UndirGraphReader reader(std::cin, graph); - /// \endcode - /// - /// The \c readNodeMap() function reads a map from the \c \@nodeset section. - /// If there is a map that you do not want to read from the file and there is - /// whitespace in the string represenation of the values then you should - /// call the \c skipNodeMap() template member function with proper - /// parameters. - /// - /// \code - /// reader.readNodeMap("coords", coords); - /// - /// reader.readNodeMap("label", labelMap); - /// reader.skipNodeMap("description"); - /// - /// reader.readNodeMap("color", colorMap); - /// \endcode - /// - /// With the \c readUndirEdgeMap() member function you can give an - /// undir edge map reading command similar to the NodeMaps. - /// - /// \code - /// reader.readUndirEdgeMap("capacity", capacityMap); - /// \endcode - /// - /// The reading of the directed edge maps is just a syntactical sugar. - /// It reads two undirected edgemaps into a directed edge map. The - /// undirected edge maps' name should be start with the \c '+' and the - /// \c '-' character and the same. - /// - /// \code - /// reader.readEdgeMap("flow", flowMap); - /// \endcode - /// - /// With \c readNode() and \c readUndirEdge() functions you can read - /// labeled Nodes and UndirEdges. - /// - /// \code - /// reader.readNode("source", sourceNode); - /// reader.readNode("target", targetNode); - /// - /// reader.readUndirEdge("observed", undirEdge); - /// \endcode - /// - /// With the \c readAttribute() functions you can read an attribute - /// in a variable. You can specify the reader for the attribute as - /// the nodemaps. - /// - /// After you give all read commands you must call the \c run() member - /// function, which execute all the commands. - /// - /// \code - /// reader.run(); - /// \endcode - /// - /// \see GraphReader - /// \see DefaultReaderTraits - /// \see \ref UndirGraphWriter - /// \see \ref graph-io-page - /// - /// \author Balazs Dezso - template - class UndirGraphReader { - public: - - typedef _Graph Graph; - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - typedef typename Graph::UndirEdge UndirEdge; - - typedef _ReaderTraits ReaderTraits; - typedef typename ReaderTraits::Skipper DefaultSkipper; - - /// \brief Construct a new UndirGraphReader. - /// - /// Construct a new UndirGraphReader. It reads into the given graph - /// and it use the given reader as the default skipper. - UndirGraphReader(std::istream& _is, Graph& _graph, - const DefaultSkipper& _skipper = DefaultSkipper()) - : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper), - nodeset_reader(*reader, _graph, std::string(), skipper), - undir_edgeset_reader(*reader, _graph, nodeset_reader, - std::string(), skipper), - node_reader(*reader, nodeset_reader, std::string()), - undir_edge_reader(*reader, undir_edgeset_reader, std::string()), - attribute_reader(*reader, std::string()) {} - - /// \brief Construct a new UndirGraphReader. - /// - /// Construct a new UndirGraphReader. It reads into the given graph - /// and it use the given reader as the default skipper. - UndirGraphReader(const std::string& _filename, Graph& _graph, - const DefaultSkipper& _skipper = DefaultSkipper()) - : reader(new LemonReader(_filename)), own_reader(true), - skipper(_skipper), - nodeset_reader(*reader, _graph, std::string(), skipper), - undir_edgeset_reader(*reader, _graph, nodeset_reader, - std::string(), skipper), - node_reader(*reader, nodeset_reader, std::string()), - undir_edge_reader(*reader, undir_edgeset_reader, std::string()), - attribute_reader(*reader, std::string()) {} - - /// \brief Construct a new UndirGraphReader. - /// - /// Construct a new UndirGraphReader. It reads into the given graph - /// and it use the given reader as the default skipper. - UndirGraphReader(LemonReader& _reader, Graph& _graph, - const DefaultSkipper& _skipper = DefaultSkipper()) - : reader(_reader), own_reader(false), skipper(_skipper), - nodeset_reader(*reader, _graph, std::string(), skipper), - undir_edgeset_reader(*reader, _graph, nodeset_reader, - std::string(), skipper), - node_reader(*reader, nodeset_reader, std::string()), - undir_edge_reader(*reader, undir_edgeset_reader, std::string()), - attribute_reader(*reader, std::string()) {} - - /// \brief Destruct the graph reader. - /// - /// Destruct the graph reader. - ~UndirGraphReader() { - if (own_reader) - delete reader; - } - - /// \brief Add a new node map reader command for the reader. - /// - /// Add a new node map reader command for the reader. - template - UndirGraphReader& readNodeMap(std::string name, Map& map) { - nodeset_reader.readNodeMap(name, map); - return *this; - } - - template - UndirGraphReader& readNodeMap(std::string name, const Map& map) { - nodeset_reader.readNodeMap(name, map); - return *this; - } - - /// \brief Add a new node map reader command for the reader. - /// - /// Add a new node map reader command for the reader. - template - UndirGraphReader& readNodeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - nodeset_reader.readNodeMap(name, map, reader); - return *this; - } - - template - UndirGraphReader& readNodeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - nodeset_reader.readNodeMap(name, map, reader); - return *this; - } - - /// \brief Add a new node map skipper command for the reader. - /// - /// Add a new node map skipper command for the reader. - template - UndirGraphReader& skipNodeMap(std::string name, - const Reader& reader = Reader()) { - nodeset_reader.skipNodeMap(name, reader); - return *this; - } - - /// \brief Add a new undirected edge map reader command for the reader. - /// - /// Add a new undirected edge map reader command for the reader. - template - UndirGraphReader& readUndirEdgeMap(std::string name, Map& map) { - undir_edgeset_reader.readUndirEdgeMap(name, map); - return *this; - } - - template - UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map) { - undir_edgeset_reader.readUndirEdgeMap(name, map); - return *this; - } - - - /// \brief Add a new undirected edge map reader command for the reader. - /// - /// Add a new undirected edge map reader command for the reader. - template - UndirGraphReader& readUndirEdgeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - undir_edgeset_reader.readUndirEdgeMap(name, map, reader); - return *this; - } - - template - UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - undir_edgeset_reader.readUndirEdgeMap(name, map, reader); - return *this; - } - - /// \brief Add a new undirected edge map skipper command for the reader. - /// - /// Add a new undirected edge map skipper command for the reader. - template - UndirGraphReader& skipUndirEdgeMap(std::string name, - const Reader& reader = Reader()) { - undir_edgeset_reader.skipUndirMap(name, reader); - return *this; - } - - - /// \brief Add a new edge map reader command for the reader. - /// - /// Add a new edge map reader command for the reader. - template - UndirGraphReader& readEdgeMap(std::string name, Map& map) { - undir_edgeset_reader.readEdgeMap(name, map); - return *this; - } - - template - UndirGraphReader& readEdgeMap(std::string name, const Map& map) { - undir_edgeset_reader.readEdgeMap(name, map); - return *this; - } - - - /// \brief Add a new edge map reader command for the reader. - /// - /// Add a new edge map reader command for the reader. - template - UndirGraphReader& readEdgeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - undir_edgeset_reader.readEdgeMap(name, map, reader); - return *this; - } - - template - UndirGraphReader& readEdgeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - undir_edgeset_reader.readEdgeMap(name, map, reader); - return *this; - } - - /// \brief Add a new edge map skipper command for the reader. - /// - /// Add a new edge map skipper command for the reader. - template - UndirGraphReader& skipEdgeMap(std::string name, - const Reader& reader = Reader()) { - undir_edgeset_reader.skipEdgeMap(name, reader); - return *this; - } - - /// \brief Add a new labeled node reader for the reader. - /// - /// Add a new labeled node reader for the reader. - UndirGraphReader& readNode(std::string name, Node& node) { - node_reader.readNode(name, node); - return *this; - } - - /// \brief Add a new labeled edge reader for the reader. - /// - /// Add a new labeled edge reader for the reader. - UndirGraphReader& readEdge(std::string name, Edge& edge) { - undir_edge_reader.readEdge(name, edge); - } - - /// \brief Add a new labeled undirected edge reader for the reader. - /// - /// Add a new labeled undirected edge reader for the reader. - UndirGraphReader& readUndirEdge(std::string name, UndirEdge& edge) { - undir_edge_reader.readUndirEdge(name, edge); - } - - /// \brief Add a new attribute reader command. - /// - /// Add a new attribute reader command. - template - UndirGraphReader& readAttribute(std::string name, Value& value) { - attribute_reader.readAttribute(name, value); - return *this; - } - - /// \brief Add a new attribute reader command. - /// - /// Add a new attribute reader command. - template - UndirGraphReader& readAttribute(std::string name, Value& value, - const Reader& reader) { - attribute_reader.readAttribute(name, value, reader); - return *this; - } - - /// \brief Conversion operator to LemonReader. - /// - /// Conversion operator to LemonReader. It make possible - /// to access the encapsulated \e LemonReader, this way - /// you can attach to this reader new instances of - /// \e LemonReader::SectionReader. - operator LemonReader&() { - return *reader; - } - - /// \brief Executes the reader commands. - /// - /// Executes the reader commands. - void run() { - reader->run(); - } - - /// \brief Gives back the node by its id. - /// - /// It reads an id from the stream and gives back which node belongs to - /// it. It is possible only if there was read an "id" named node map. - Node readId(std::istream& is, Node) const { - return nodeset_reader.readId(is, Node()); - } - - /// \brief Gives back the edge by its id. - /// - /// It reads an id from the stream and gives back which edge belongs to - /// it. It is possible only if there was read an "id" named edge map. - Edge readId(std::istream& is, Edge) const { - return undir_edgeset_reader.readId(is, Edge()); - } - - /// \brief Gives back the undirected edge by its id. - /// - /// It reads an id from the stream and gives back which undirected edge - /// belongs to it. It is possible only if there was read an "id" named - /// edge map. - UndirEdge readId(std::istream& is, UndirEdge) const { - return undir_edgeset_reader.readId(is, UndirEdge()); - } - - - private: - - LemonReader* reader; - bool own_reader; - - DefaultSkipper skipper; - - NodeSetReader nodeset_reader; - UndirEdgeSetReader undir_edgeset_reader; - - NodeReader node_reader; - UndirEdgeReader undir_edge_reader; - - AttributeReader attribute_reader; - }; - - /// \brief Read an undir graph from the input. - /// - /// Read an undir graph from the input. - /// \param is The input stream. - /// \param g The graph. - /// \param capacity The capacity map. - template - void readUndirGraph(std::istream& is, Graph &g, CapacityMap& capacity) { - UndirGraphReader reader(is, g); - reader.readUndirEdgeMap("capacity", capacity); - reader.run(); - } - - /// \brief Read an undir graph from the input. - /// - /// Read an undir graph from the input. - /// \param is The input stream. - /// \param g The graph. - template - void readUndirGraph(std::istream& is, Graph &g) { - UndirGraphReader reader(is, g); - reader.run(); - } - - /// @} -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/graph_to_eps.h --- a/src/lemon/graph_to_eps.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1026 +0,0 @@ -/* -*- C++ -*- - * src/lemon/graph_to_eps.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_GRAPH_TO_EPS_H -#define LEMON_GRAPH_TO_EPS_H - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - - -///\ingroup io_group -///\file -///\brief Simple graph drawer -/// -///\author Alpar Juttner - -namespace lemon { - -///Data structure representing RGB colors. - -///Data structure representing RGB colors. -///\ingroup misc -class Color -{ - double _r,_g,_b; -public: - ///Default constructor - Color() {} - ///Constructor - Color(double r,double g,double b) :_r(r),_g(g),_b(b) {}; - ///Returns the red component - - ///\todo \c red() could be a better name... - double getR() const {return _r;} - ///Returns the green component - double getG() const {return _g;} - ///Returns the blue component - double getB() const {return _b;} - ///Set the color components - void set(double r,double g,double b) { _r=r;_g=g;_b=b; }; -}; - -///Maps ints to different \ref Color "Color"s - -///This map assing one of the predefined \ref Color "Color"s -///to each int. It is possible to change the colors as well as their -///number. The integer range is cyclically mapped to the provided set of colors. -/// -///This is a true \ref concept::ReferenceMap "reference map", so you can also -///change the actual colors. - -class ColorSet : public MapBase -{ - std::vector colors; -public: - ///Constructor - - ///Constructor - ///\param have_white indicates wheter white is - ///amongst the provided color (\c true) or not (\c false). If it is true, - ///white will be assigned to \c 0. - ///\param num the number of the allocated colors. If it is \c 0 - ///the default color configuration is set up (26 color plus the while). - ///If \c num is less then 26/27 then the default color list is cut. Otherwise - ///the color list is filled repeatedly with the default color list. - ColorSet(bool have_white=false,int num=0) - { - do { - if(have_white) colors.push_back(Color(1,1,1)); - - colors.push_back(Color(0,0,0)); - colors.push_back(Color(1,0,0)); - colors.push_back(Color(0,1,0)); - colors.push_back(Color(0,0,1)); - colors.push_back(Color(1,1,0)); - colors.push_back(Color(1,0,1)); - colors.push_back(Color(0,1,1)); - - colors.push_back(Color(.5,0,0)); - colors.push_back(Color(0,.5,0)); - colors.push_back(Color(0,0,.5)); - colors.push_back(Color(.5,.5,0)); - colors.push_back(Color(.5,0,.5)); - colors.push_back(Color(0,.5,.5)); - - colors.push_back(Color(.5,.5,.5)); - colors.push_back(Color(1,.5,.5)); - colors.push_back(Color(.5,1,.5)); - colors.push_back(Color(.5,.5,1)); - colors.push_back(Color(1,1,.5)); - colors.push_back(Color(1,.5,1)); - colors.push_back(Color(.5,1,1)); - - colors.push_back(Color(1,.5,0)); - colors.push_back(Color(.5,1,0)); - colors.push_back(Color(1,0,.5)); - colors.push_back(Color(0,1,.5)); - colors.push_back(Color(0,.5,1)); - colors.push_back(Color(.5,0,1)); - } while(int(colors.size())0) colors.resize(num); - } - ///\e - Color &operator[](int i) - { - return colors[i%colors.size()]; - } - ///\e - const Color &operator[](int i) const - { - return colors[i%colors.size()]; - } - ///\e - void set(int i,const Color &c) - { - colors[i%colors.size()]=c; - } - ///Sets the number of the exiting colors. - void resize(int s) { colors.resize(s);} - ///Returns the munber of the existing colors. - std::size_t size() { return colors.size();} -}; - -///Returns a visible distinct \ref Color - -///Returns a \ref Color which is as different from the given parameter -///as it is possible. -inline Color distantColor(const Color &c) -{ - return Color(c.getR()<.5?1:0,c.getG()<.5?1:0,c.getB()<.5?1:0); -} -///Returns black for light colors and white for the dark ones. - -///Returns black for light colors and white for the dark ones. -///\todo weighted average would be better -inline Color distantBW(const Color &c){ - double v=(.2125*c.getR()+.7154*c.getG()+.0721*c.getB())<.5?1:0; - return Color(v,v,v); -} - -///Default traits class of \ref GraphToEps - -///Default traits class of \ref GraphToEps -/// -///\c G is the type of the underlying graph. -template -struct DefaultGraphToEpsTraits -{ - typedef G Graph; - typedef typename Graph::Node Node; - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::Edge Edge; - typedef typename Graph::EdgeIt EdgeIt; - typedef typename Graph::InEdgeIt InEdgeIt; - typedef typename Graph::OutEdgeIt OutEdgeIt; - - - const Graph &g; - - std::ostream& os; - - ConstMap > _coords; - ConstMap _nodeSizes; - ConstMap _nodeShapes; - - ConstMap _nodeColors; - ConstMap _edgeColors; - - ConstMap _edgeWidths; - - double _edgeWidthScale; - - double _nodeScale; - double _xBorder, _yBorder; - double _scale; - double _nodeBorderQuotient; - - bool _drawArrows; - double _arrowLength, _arrowWidth; - - bool _showNodes, _showEdges; - - bool _enableParallel; - double _parEdgeDist; - - bool _showNodeText; - ConstMap _nodeTexts; - double _nodeTextSize; - - bool _showNodePsText; - ConstMap _nodePsTexts; - char *_nodePsTextsPreamble; - - bool _undir; - bool _pleaseRemoveOsStream; - - bool _scaleToA4; - - std::string _title; - std::string _copyright; - - enum NodeTextColorType - { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType; - ConstMap _nodeTextColors; - - ///Constructor - - ///Constructor - ///\param _g is a reference to the graph to be printed - ///\param _os is a reference to the output stream. - ///\param _os is a reference to the output stream. - ///\param _pros If it is \c true, then the \c ostream referenced by \c _os - ///will be explicitly deallocated by the destructor. - ///By default it is std::cout - DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout, - bool _pros=false) : - g(_g), os(_os), - _coords(xy(1,1)), _nodeSizes(1.0), _nodeShapes(0), - _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)), - _edgeWidths(1), _edgeWidthScale(0.3), - _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0), - _nodeBorderQuotient(.1), - _drawArrows(false), _arrowLength(1), _arrowWidth(0.3), - _showNodes(true), _showEdges(true), - _enableParallel(false), _parEdgeDist(1), - _showNodeText(false), _nodeTexts(false), _nodeTextSize(1), - _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0), - _undir(false), - _pleaseRemoveOsStream(_pros), _scaleToA4(false), - _nodeTextColorType(SAME_COL), _nodeTextColors(Color(0,0,0)) - {} -}; - -///Helper class to implement the named parameters of \ref graphToEps() - -///Helper class to implement the named parameters of \ref graphToEps() -///\todo Is 'helper class' a good name for this? -/// -///\todo Follow PostScript's DSC. -/// Use own dictionary. -///\todo Useful new features. -/// - Linestyles: dotted, dashed etc. -/// - A second color and percent value for the lines. -template class GraphToEps : public T -{ - // Can't believe it is required by the C++ standard - using T::g; - using T::os; - - using T::_coords; - using T::_nodeSizes; - using T::_nodeShapes; - using T::_nodeColors; - using T::_edgeColors; - using T::_edgeWidths; - - using T::_edgeWidthScale; - using T::_nodeScale; - using T::_xBorder; - using T::_yBorder; - using T::_scale; - using T::_nodeBorderQuotient; - - using T::_drawArrows; - using T::_arrowLength; - using T::_arrowWidth; - - using T::_showNodes; - using T::_showEdges; - - using T::_enableParallel; - using T::_parEdgeDist; - - using T::_showNodeText; - using T::_nodeTexts; - using T::_nodeTextSize; - - using T::_showNodePsText; - using T::_nodePsTexts; - using T::_nodePsTextsPreamble; - - using T::_undir; - using T::_pleaseRemoveOsStream; - - using T::_scaleToA4; - - using T::_title; - using T::_copyright; - - using T::NodeTextColorType; - using T::CUST_COL; - using T::DIST_COL; - using T::DIST_BW; - using T::_nodeTextColorType; - using T::_nodeTextColors; - // dradnats ++C eht yb deriuqer si ti eveileb t'naC - - typedef typename T::Graph Graph; - typedef typename Graph::Node Node; - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::Edge Edge; - typedef typename Graph::EdgeIt EdgeIt; - typedef typename Graph::InEdgeIt InEdgeIt; - typedef typename Graph::OutEdgeIt OutEdgeIt; - - static const int INTERPOL_PREC=20; - static const double A4HEIGHT = 841.8897637795276; - static const double A4WIDTH = 595.275590551181; - static const double A4BORDER = 15; - - bool dontPrint; - -public: - ///Node shapes - - ///Node shapes - /// - enum NodeShapes { - /// = 0 - ///\image html nodeshape_0.png - ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm - CIRCLE=0, - /// = 1 - ///\image html nodeshape_1.png - ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm - /// - SQUARE=1, - /// = 2 - ///\image html nodeshape_2.png - ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm - /// - DIAMOND=2 - }; - -private: - class edgeLess { - const Graph &g; - public: - edgeLess(const Graph &_g) : g(_g) {} - bool operator()(Edge a,Edge b) const - { - Node ai=std::min(g.source(a),g.target(a)); - Node aa=std::max(g.source(a),g.target(a)); - Node bi=std::min(g.source(b),g.target(b)); - Node ba=std::max(g.source(b),g.target(b)); - return ai - static std::string psOut(const xy &p) - { - std::ostringstream os; - os << p.x << ' ' << p.y; - return os.str(); - } - static std::string psOut(const Color &c) - { - std::ostringstream os; - os << c.getR() << ' ' << c.getG() << ' ' << c.getB(); - return os.str(); - } - -public: - GraphToEps(const T &t) : T(t), dontPrint(false) {}; - - template struct CoordsTraits : public T { - const X &_coords; - CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {} - }; - ///Sets the map of the node coordinates - - ///Sets the map of the node coordinates. - ///\param x must be a node map with xy or \ref xy "xy" values. - template GraphToEps > coords(const X &x) { - dontPrint=true; - return GraphToEps >(CoordsTraits(*this,x)); - } - template struct NodeSizesTraits : public T { - const X &_nodeSizes; - NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {} - }; - ///Sets the map of the node sizes - - ///Sets the map of the node sizes - ///\param x must be a node map with \c double (or convertible) values. - template GraphToEps > nodeSizes(const X &x) - { - dontPrint=true; - return GraphToEps >(NodeSizesTraits(*this,x)); - } - template struct NodeShapesTraits : public T { - const X &_nodeShapes; - NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {} - }; - ///Sets the map of the node shapes - - ///Sets the map of the node shapes. - ///The availabe shape values - ///can be found in \ref NodeShapes "enum NodeShapes". - ///\param x must be a node map with \c int (or convertible) values. - ///\sa NodeShapes - template GraphToEps > nodeShapes(const X &x) - { - dontPrint=true; - return GraphToEps >(NodeShapesTraits(*this,x)); - } - template struct NodeTextsTraits : public T { - const X &_nodeTexts; - NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {} - }; - ///Sets the text printed on the nodes - - ///Sets the text printed on the nodes - ///\param x must be a node map with type that can be pushed to a standard - ///ostream. - template GraphToEps > nodeTexts(const X &x) - { - dontPrint=true; - _showNodeText=true; - return GraphToEps >(NodeTextsTraits(*this,x)); - } - template struct NodePsTextsTraits : public T { - const X &_nodePsTexts; - NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {} - }; - ///Inserts a PostScript block to the nodes - - ///With this command it is possible to insert a verbatim PostScript - ///block to the nodes. - ///The PS current point will be moved to the centre of the node before - ///the PostScript block inserted. - /// - ///Before and after the block a newline character is inserted to you - ///don't have to bother with the separators. - /// - ///\param x must be a node map with type that can be pushed to a standard - ///ostream. - /// - ///\sa nodePsTextsPreamble() - ///\todo Offer the choise not to move to the centre but pass the coordinates - ///to the Postscript block inserted. - template GraphToEps > nodePsTexts(const X &x) - { - dontPrint=true; - _showNodePsText=true; - return GraphToEps >(NodePsTextsTraits(*this,x)); - } - template struct EdgeWidthsTraits : public T { - const X &_edgeWidths; - EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {} - }; - ///Sets the map of the edge widths - - ///Sets the map of the edge widths - ///\param x must be a edge map with \c double (or convertible) values. - template GraphToEps > edgeWidths(const X &x) - { - dontPrint=true; - return GraphToEps >(EdgeWidthsTraits(*this,x)); - } - - template struct NodeColorsTraits : public T { - const X &_nodeColors; - NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {} - }; - ///Sets the map of the node colors - - ///Sets the map of the node colors - ///\param x must be a node map with \ref Color values. - template GraphToEps > - nodeColors(const X &x) - { - dontPrint=true; - return GraphToEps >(NodeColorsTraits(*this,x)); - } - template struct NodeTextColorsTraits : public T { - const X &_nodeTextColors; - NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {} - }; - ///Sets the map of the node text colors - - ///Sets the map of the node text colors - ///\param x must be a node map with \ref Color values. - template GraphToEps > - nodeTextColors(const X &x) - { - dontPrint=true; - _nodeTextColorType=CUST_COL; - return GraphToEps > - (NodeTextColorsTraits(*this,x)); - } - template struct EdgeColorsTraits : public T { - const X &_edgeColors; - EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {} - }; - ///Sets the map of the edge colors - - ///Sets the map of the edge colors - ///\param x must be a edge map with \ref Color values. - template GraphToEps > - edgeColors(const X &x) - { - dontPrint=true; - return GraphToEps >(EdgeColorsTraits(*this,x)); - } - ///Sets a global scale factor for node sizes - - ///Sets a global scale factor for node sizes - /// - GraphToEps &nodeScale(double d) {_nodeScale=d;return *this;} - ///Sets a global scale factor for edge widths - - ///Sets a global scale factor for edge widths - /// - GraphToEps &edgeWidthScale(double d) {_edgeWidthScale=d;return *this;} - ///Sets a global scale factor for the whole picture - - ///Sets a global scale factor for the whole picture - /// - GraphToEps &scale(double d) {_scale=d;return *this;} - ///Sets the width of the border around the picture - - ///Sets the width of the border around the picture - /// - GraphToEps &border(double b) {_xBorder=_yBorder=b;return *this;} - ///Sets the width of the border around the picture - - ///Sets the width of the border around the picture - /// - GraphToEps &border(double x, double y) { - _xBorder=x;_yBorder=y;return *this; - } - ///Sets whether to draw arrows - - ///Sets whether to draw arrows - /// - GraphToEps &drawArrows(bool b=true) {_drawArrows=b;return *this;} - ///Sets the length of the arrowheads - - ///Sets the length of the arrowheads - /// - GraphToEps &arrowLength(double d) {_arrowLength*=d;return *this;} - ///Sets the width of the arrowheads - - ///Sets the width of the arrowheads - /// - GraphToEps &arrowWidth(double d) {_arrowWidth*=d;return *this;} - - ///Scales the drawing to fit to A4 page - - ///Scales the drawing to fit to A4 page - /// - GraphToEps &scaleToA4() {_scaleToA4=true;return *this;} - - ///Enables parallel edges - - ///Enables parallel edges - ///\todo Partially implemented - GraphToEps &enableParallel(bool b=true) {_enableParallel=b;return *this;} - - ///Sets the distance - - ///Sets the distance - /// - GraphToEps &parEdgeDist(double d) {_parEdgeDist*=d;return *this;} - - ///Hides the edges - - ///Hides the edges - /// - GraphToEps &hideEdges(bool b=true) {_showEdges=!b;return *this;} - ///Hides the nodes - - ///Hides the nodes - /// - GraphToEps &hideNodes(bool b=true) {_showNodes=!b;return *this;} - - ///Sets the size of the node texts - - ///Sets the size of the node texts - /// - GraphToEps &nodeTextSize(double d) {_nodeTextSize=d;return *this;} - - ///Sets the color of the node texts to be different from the node color - - ///Sets the color of the node texts to be as different from the node color - ///as it is possible - /// - GraphToEps &distantColorNodeTexts() - {_nodeTextColorType=DIST_COL;return *this;} - ///Sets the color of the node texts to be black or white and always visible. - - ///Sets the color of the node texts to be black or white according to - ///which is more - ///different from the node color - /// - GraphToEps &distantBWNodeTexts() - {_nodeTextColorType=DIST_BW;return *this;} - - ///Gives a preamble block for node Postscript block. - - ///Gives a preamble block for node Postscript block. - /// - ///\sa nodePsTexts() - GraphToEps & nodePsTextsPreamble(const char *str) { - _nodePsTextsPreamble=str ;return *this; - } - ///Sets whether the the graph is undirected - - ///Sets whether the the graph is undirected - /// - GraphToEps &undir(bool b=true) {_undir=b;return *this;} - ///Sets whether the the graph is directed - - ///Sets whether the the graph is directed. - ///Use it to show the undirected edges as a pair of directed ones. - GraphToEps &bidir(bool b=true) {_undir=!b;return *this;} - - ///Sets the title. - - ///Sets the title of the generated image, - ///namely it inserts a %%Title: DSC field to the header of - ///the EPS file. - GraphToEps &title(const std::string &t) {_title=t;return *this;} - ///Sets the copyright statement. - - ///Sets the copyright statement of the generated image, - ///namely it inserts a %%Copyright: DSC field to the header of - ///the EPS file. - ///\todo Multiline copyright notice could be supported. - GraphToEps ©right(const std::string &t) {_copyright=t;return *this;} - -protected: - bool isInsideNode(xy p, double r,int t) - { - switch(t) { - case CIRCLE: - return p.normSquare()<=r*r; - case SQUARE: - return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r; - case DIAMOND: - return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r; - } - return false; - } - -public: - ~GraphToEps() { } - - ///Draws the graph. - - ///Like other functions using - ///\ref named-templ-func-param "named template parameters", - ///this function calles the algorithm itself, i.e. in this case - ///it draws the graph. - void run() { - if(dontPrint) return; - - os << "%!PS-Adobe-2.0 EPSF-2.0\n"; - if(_title.size()>0) os << "%%Title: " << _title << '\n'; - if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n'; -// << "%%Copyright: XXXX\n" - os << "%%Creator: LEMON GraphToEps function\n"; - - { - char cbuf[50]; - timeval tv; - gettimeofday(&tv, 0); - ctime_r(&tv.tv_sec,cbuf); - os << "%%CreationDate: " << cbuf; - } - ///\todo: Chech whether the graph is empty. - BoundingBox bb; - for(NodeIt n(g);n!=INVALID;++n) { - double ns=_nodeSizes[n]*_nodeScale; - xy p(ns,ns); - bb+=p+_coords[n]; - bb+=-p+_coords[n]; - } - if(_scaleToA4) - os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n"; - else os << "%%BoundingBox: " - << bb.left()* _scale-_xBorder << ' ' - << bb.bottom()*_scale-_yBorder << ' ' - << bb.right()* _scale+_xBorder << ' ' - << bb.top()* _scale+_yBorder << '\n'; - - os << "%%EndComments\n"; - - //x1 y1 x2 y2 x3 y3 cr cg cb w - os << "/lb { setlinewidth setrgbcolor newpath moveto\n" - << " 4 2 roll 1 index 1 index curveto stroke } bind def\n"; - os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n"; - //x y r - os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n"; - //x y r - os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n" - << " 2 index 1 index sub 2 index 2 index add lineto\n" - << " 2 index 1 index sub 2 index 2 index sub lineto\n" - << " 2 index 1 index add 2 index 2 index sub lineto\n" - << " closepath pop pop pop} bind def\n"; - //x y r - os << "/di { newpath 2 index 1 index add 2 index moveto\n" - << " 2 index 2 index 2 index add lineto\n" - << " 2 index 1 index sub 2 index lineto\n" - << " 2 index 2 index 2 index sub lineto\n" - << " closepath pop pop pop} bind def\n"; - // x y r cr cg cb - os << "/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill\n" - << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n" - << " } bind def\n"; - os << "/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill\n" - << " setrgbcolor " << 1+_nodeBorderQuotient << " div sq fill\n" - << " } bind def\n"; - os << "/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill\n" - << " setrgbcolor " << 1+_nodeBorderQuotient << " div di fill\n" - << " } bind def\n"; - os << "/arrl " << _arrowLength << " def\n"; - os << "/arrw " << _arrowWidth << " def\n"; - // l dx_norm dy_norm - os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n"; - //len w dx_norm dy_norm x1 y1 cr cg cb - os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n" - << " /w exch def /len exch def\n" - // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke" - << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n" - << " len w sub arrl sub dx dy lrl\n" - << " arrw dy dx neg lrl\n" - << " dx arrl w add mul dy w 2 div arrw add mul sub\n" - << " dy arrl w add mul dx w 2 div arrw add mul add rlineto\n" - << " dx arrl w add mul neg dy w 2 div arrw add mul sub\n" - << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n" - << " arrw dy dx neg lrl\n" - << " len w sub arrl sub neg dx dy lrl\n" - << " closepath fill } bind def\n"; - os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n" - << " neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n"; - - os << "\ngsave\n"; - if(_scaleToA4) - if(bb.height()>bb.width()) { - double sc= min((A4HEIGHT-2*A4BORDER)/bb.height(), - (A4WIDTH-2*A4BORDER)/bb.width()); - os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' ' - << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER << " translate\n" - << sc << " dup scale\n" - << -bb.left() << ' ' << -bb.bottom() << " translate\n"; - } - else { - //\todo Verify centering - double sc= min((A4HEIGHT-2*A4BORDER)/bb.width(), - (A4WIDTH-2*A4BORDER)/bb.height()); - os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' ' - << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER << " translate\n" - << sc << " dup scale\n90 rotate\n" - << -bb.left() << ' ' << -bb.top() << " translate\n"; - } - else if(_scale!=1.0) os << _scale << " dup scale\n"; - - if(_showEdges) { - os << "%Edges:\ngsave\n"; - if(_enableParallel) { - std::vector el; - for(EdgeIt e(g);e!=INVALID;++e) - if((!_undir||g.source(e)0) - el.push_back(e); - sort(el.begin(),el.end(),edgeLess(g)); - - typename std::vector::iterator j; - for(typename std::vector::iterator i=el.begin();i!=el.end();i=j) { - for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ; - - double sw=0; - for(typename std::vector::iterator e=i;e!=j;++e) - sw+=_edgeWidths[*e]*_edgeWidthScale+_parEdgeDist; - sw-=_parEdgeDist; - sw/=-2.0; - xy dvec(_coords[g.target(*i)]-_coords[g.source(*i)]); - double l=std::sqrt(dvec.normSquare()); - ///\todo better 'epsilon' would be nice here. - xy d(dvec/std::max(l,1e-9)); - xy m; -// m=xy(_coords[g.target(*i)]+_coords[g.source(*i)])/2.0; - -// m=xy(_coords[g.source(*i)])+ -// dvec*(double(_nodeSizes[g.source(*i)])/ -// (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)])); - - m=xy(_coords[g.source(*i)])+ - d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0; - - for(typename std::vector::iterator e=i;e!=j;++e) { - sw+=_edgeWidths[*e]*_edgeWidthScale/2.0; - xy mm=m+rot90(d)*sw/.75; - if(_drawArrows) { - int node_shape; - xy s=_coords[g.source(*e)]; - xy t=_coords[g.target(*e)]; - double rn=_nodeSizes[g.target(*e)]*_nodeScale; - node_shape=_nodeShapes[g.target(*e)]; - Bezier3 bez(s,mm,mm,t); - double t1=0,t2=1; - for(int i=0;i apoint=bez((t1+t2)/2); - rn = _arrowLength+_edgeWidths[*e]*_edgeWidthScale; - rn*=rn; - t2=(t1+t2)/2;t1=0; - for(int i=0;irn) t1=(t1+t2)/2; - else t2=(t1+t2)/2; - xy linend=bez((t1+t2)/2); - bez=bez.before((t1+t2)/2); -// rn=_nodeSizes[g.source(*e)]*_nodeScale; -// node_shape=_nodeShapes[g.source(*e)]; -// t1=0;t2=1; -// for(int i=0;i dd(rot90(linend-apoint)); - dd*=(.5*_edgeWidths[*e]*_edgeWidthScale+_arrowWidth)/ - std::sqrt(dd.normSquare()); - os << "newpath " << psOut(apoint) << " moveto " - << psOut(linend+dd) << " lineto " - << psOut(linend-dd) << " lineto closepath fill\n"; - } - else { - os << _coords[g.source(*e)].x << ' ' - << _coords[g.source(*e)].y << ' ' - << mm.x << ' ' << mm.y << ' ' - << _coords[g.target(*e)].x << ' ' - << _coords[g.target(*e)].y << ' ' - << _edgeColors[*e].getR() << ' ' - << _edgeColors[*e].getG() << ' ' - << _edgeColors[*e].getB() << ' ' - << _edgeWidths[*e]*_edgeWidthScale << " lb\n"; - } - sw+=_edgeWidths[*e]*_edgeWidthScale/2.0+_parEdgeDist; - } - } - } - else for(EdgeIt e(g);e!=INVALID;++e) - if((!_undir||g.source(e)0) - if(_drawArrows) { - xy d(_coords[g.target(e)]-_coords[g.source(e)]); - double rn=_nodeSizes[g.target(e)]*_nodeScale; - int node_shape=_nodeShapes[g.target(e)]; - double t1=0,t2=1; - for(int i=0;istd::cout -/// -///This function also has a lot of -///\ref named-templ-func-param "named parameters", -///they are declared as the members of class \ref GraphToEps. The following -///example shows how to use these parameters. -///\code -/// graphToEps(g,os).scale(10).coords(coords) -/// .nodeScale(2).nodeSizes(sizes) -/// .edgeWidthScale(.4).run(); -///\endcode -///\warning Don't forget to put the \ref GraphToEps::run() "run()" -///to the end of the parameter list. -///\sa GraphToEps -///\sa graphToEps(G &g, char *file_name) -template -GraphToEps > -graphToEps(G &g, std::ostream& os=std::cout) -{ - return - GraphToEps >(DefaultGraphToEpsTraits(g,os)); -} - -///Generates an EPS file from a graph - -///\ingroup misc -///This function does the same as -///\ref graphToEps(G &g,std::ostream& os) -///but it writes its output into the file \c file_name -///instead of a stream. -///\sa graphToEps(G &g, std::ostream& os) -template -GraphToEps > -graphToEps(G &g,const char *file_name) -{ - return GraphToEps > - (DefaultGraphToEpsTraits(g,*new std::ofstream(file_name),true)); -} - -} //END OF NAMESPACE LEMON - -#endif // LEMON_GRAPH_TO_EPS_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/graph_utils.h --- a/src/lemon/graph_utils.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,861 +0,0 @@ -/* -*- C++ -*- - * src/lemon/graph_utils.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_GRAPH_UTILS_H -#define LEMON_GRAPH_UTILS_H - -#include -#include -#include - -#include -#include -#include - -///\ingroup gutils -///\file -///\brief Graph utilities. -/// -///\todo Please -///revise the documentation. -/// - - -namespace lemon { - - /// \addtogroup gutils - /// @{ - - /// \brief Function to count the items in the graph. - /// - /// This function counts the items in the graph. - /// The complexity of the function is O(n) because - /// it iterates on all of the items. - - template - inline int countItems(const Graph& g) { - int num = 0; - for (ItemIt it(g); it != INVALID; ++it) { - ++num; - } - return num; - } - - // Node counting: - - template - inline - typename enable_if::type - _countNodes(const Graph &g) { - return g.nodeNum(); - } - - template - inline int _countNodes(Wrap w) { - return countItems(w.value); - } - - /// \brief Function to count the nodes in the graph. - /// - /// This function counts the nodes in the graph. - /// The complexity of the function is O(n) but for some - /// graph structure it is specialized to run in O(1). - /// - /// \todo refer how to specialize it - - template - inline int countNodes(const Graph& g) { - return _countNodes(g); - } - - // Edge counting: - - template - inline - typename enable_if::type - _countEdges(const Graph &g) { - return g.edgeNum(); - } - - template - inline int _countEdges(Wrap w) { - return countItems(w.value); - } - - /// \brief Function to count the edges in the graph. - /// - /// This function counts the edges in the graph. - /// The complexity of the function is O(e) but for some - /// graph structure it is specialized to run in O(1). - - template - inline int countEdges(const Graph& g) { - return _countEdges(g); - } - - // Undirected edge counting: - - template - inline - typename enable_if::type - _countUndirEdges(const Graph &g) { - return g.undirEdgeNum(); - } - - template - inline int _countUndirEdges(Wrap w) { - return countItems(w.value); - } - - /// \brief Function to count the edges in the graph. - /// - /// This function counts the edges in the graph. - /// The complexity of the function is O(e) but for some - /// graph structure it is specialized to run in O(1). - - template - inline int countUndirEdges(const Graph& g) { - return _countUndirEdges(g); - } - - - - template - inline int countNodeDegree(const Graph& _g, const typename Graph::Node& _n) { - int num = 0; - for (DegIt it(_g, _n); it != INVALID; ++it) { - ++num; - } - return num; - } - - /// Finds an edge between two nodes of a graph. - - /// Finds an edge from node \c u to node \c v in graph \c g. - /// - /// If \c prev is \ref INVALID (this is the default value), then - /// it finds the first edge from \c u to \c v. Otherwise it looks for - /// the next edge from \c u to \c v after \c prev. - /// \return The found edge or \ref INVALID if there is no such an edge. - /// - /// Thus you can iterate through each edge from \c u to \c v as it follows. - /// \code - /// for(Edge e=findEdge(g,u,v);e!=INVALID;e=findEdge(g,u,v,e)) { - /// ... - /// } - /// \endcode - /// \todo We may want to use the \ref concept::GraphBase "GraphBase" - /// interface here... - /// \bug Untested ... - template - typename Graph::Edge findEdge(const Graph &g, - typename Graph::Node u, typename Graph::Node v, - typename Graph::Edge prev = INVALID) - { - typename Graph::OutEdgeIt e(g,prev); - // if(prev==INVALID) g.first(e,u); - if(prev==INVALID) e=typename Graph::OutEdgeIt(g,u); - else ++e; - while(e!=INVALID && g.target(e)!=v) ++e; - return e; - } - - ///\e - - ///\todo Please document. - /// - template - inline int countOutEdges(const Graph& _g, const typename Graph::Node& _n) { - return countNodeDegree(_g, _n); - } - - ///\e - - ///\todo Please document. - /// - template - inline int countInEdges(const Graph& _g, const typename Graph::Node& _n) { - return countNodeDegree(_g, _n); - } - - // graph copy - - template < - typename DestinationGraph, - typename SourceGraph, - typename NodeBijection> - void copyNodes(DestinationGraph& _d, const SourceGraph& _s, - NodeBijection& _nb) { - for (typename SourceGraph::NodeIt it(_s); it != INVALID; ++it) { - _nb[it] = _d.addNode(); - } - } - - template < - typename DestinationGraph, - typename SourceGraph, - typename NodeBijection, - typename EdgeBijection> - void copyEdges(DestinationGraph& _d, const SourceGraph& _s, - const NodeBijection& _nb, EdgeBijection& _eb) { - for (typename SourceGraph::EdgeIt it(_s); it != INVALID; ++it) { - _eb[it] = _d.addEdge(_nb[_s.source(it)], _nb[_s.target(it)]); - } - } - - template < - typename DestinationGraph, - typename SourceGraph, - typename NodeBijection, - typename EdgeBijection> - void copyGraph(DestinationGraph& _d, const SourceGraph& _s, - NodeBijection& _nb, EdgeBijection& _eb) { - nodeCopy(_d, _s, _nb); - edgeCopy(_d, _s, _nb, _eb); - } - - template < - typename _DestinationGraph, - typename _SourceGraph, - typename _NodeBijection - =typename _SourceGraph::template NodeMap, - typename _EdgeBijection - = typename _SourceGraph::template EdgeMap - > - class GraphCopy { - public: - - typedef _DestinationGraph DestinationGraph; - typedef _SourceGraph SourceGraph; - - typedef _NodeBijection NodeBijection; - typedef _EdgeBijection EdgeBijection; - - protected: - - NodeBijection node_bijection; - EdgeBijection edge_bijection; - - public: - - GraphCopy(DestinationGraph& _d, const SourceGraph& _s) { - copyGraph(_d, _s, node_bijection, edge_bijection); - } - - const NodeBijection& getNodeBijection() const { - return node_bijection; - } - - const EdgeBijection& getEdgeBijection() const { - return edge_bijection; - } - - }; - - - template - class ItemSetTraits {}; - - template - class ItemSetTraits<_Graph, typename _Graph::Node> { - public: - - typedef _Graph Graph; - - typedef typename Graph::Node Item; - typedef typename Graph::NodeIt ItemIt; - - template - class Map : public Graph::template NodeMap<_Value> { - public: - typedef typename Graph::template NodeMap<_Value> Parent; - typedef typename Parent::Value Value; - - Map(const Graph& _graph) : Parent(_graph) {} - Map(const Graph& _graph, const Value& _value) - : Parent(_graph, _value) {} - }; - - }; - - template - class ItemSetTraits<_Graph, typename _Graph::Edge> { - public: - - typedef _Graph Graph; - - typedef typename Graph::Edge Item; - typedef typename Graph::EdgeIt ItemIt; - - template - class Map : public Graph::template EdgeMap<_Value> { - public: - typedef typename Graph::template EdgeMap<_Value> Parent; - typedef typename Parent::Value Value; - - Map(const Graph& _graph) : Parent(_graph) {} - Map(const Graph& _graph, const Value& _value) - : Parent(_graph, _value) {} - }; - - }; - - template - class ItemSetTraits<_Graph, typename _Graph::UndirEdge> { - public: - - typedef _Graph Graph; - - typedef typename Graph::UndirEdge Item; - typedef typename Graph::UndirEdgeIt ItemIt; - - template - class Map : public Graph::template UndirEdgeMap<_Value> { - public: - typedef typename Graph::template UndirEdgeMap<_Value> Parent; - typedef typename Parent::Value Value; - - Map(const Graph& _graph) : Parent(_graph) {} - Map(const Graph& _graph, const Value& _value) - : Parent(_graph, _value) {} - }; - - }; - - /// @} - - /// \addtogroup graph_maps - /// @{ - - template - struct ReferenceMapTraits { - typedef typename Map::Value Value; - typedef typename Map::Value& Reference; - typedef const typename Map::Value& ConstReference; - typedef typename Map::Value* Pointer; - typedef const typename Map::Value* ConstPointer; - }; - - template - struct ReferenceMapTraits< - Map, - typename enable_if::type - > { - typedef typename Map::Value Value; - typedef typename Map::Reference Reference; - typedef typename Map::ConstReference ConstReference; - typedef typename Map::Pointer Pointer; - typedef typename Map::ConstPointer ConstPointer; - }; - - /// Provides an immutable and unique id for each item in the graph. - - /// The IdMap class provides an unique and immutable mapping for each item - /// in the graph. - /// - template - class IdMap { - public: - typedef _Graph Graph; - typedef int Value; - typedef _Item Item; - typedef _Item Key; - - typedef True NeedCopy; - - /// \brief Constructor. - /// - /// Constructor for creating id map. - IdMap(const Graph& _graph) : graph(&_graph) {} - - /// \brief Gives back the \e id of the item. - /// - /// Gives back the immutable and unique \e id of the map. - int operator[](const Item& item) const { return graph->id(item);} - - - private: - const Graph* graph; - - public: - - /// \brief The class represents the inverse of the map. - /// - /// The class represents the inverse of the map. - /// \see inverse() - class InverseMap { - public: - - typedef True NeedCopy; - - /// \brief Constructor. - /// - /// Constructor for creating an id-to-item map. - InverseMap(const Graph& _graph) : graph(&_graph) {} - - /// \brief Constructor. - /// - /// Constructor for creating an id-to-item map. - InverseMap(const IdMap& idMap) : graph(idMap.graph) {} - - /// \brief Gives back the given item from its id. - /// - /// Gives back the given item from its id. - /// - Item operator[](int id) const { return graph->fromId(id, Item());} - private: - const Graph* graph; - }; - - /// \brief Gives back the inverse of the map. - /// - /// Gives back the inverse of the map. - InverseMap inverse() const { return InverseMap(*graph);} - - }; - - - /// \brief General inversable graph-map type. - - /// This type provides simple inversable map functions. - /// The InversableMap wraps an arbitrary ReadWriteMap - /// and if a key is setted to a new value then store it - /// in the inverse map. - /// \param _Graph The graph type. - /// \param _Map The map to extend with inversable functionality. - template < - typename _Graph, - typename _Item, - typename _Value, - typename _Map - = typename ItemSetTraits<_Graph, _Item>::template Map<_Value>::Parent - > - class InvertableMap : protected _Map { - - public: - - typedef _Map Map; - typedef _Graph Graph; - - /// The key type of InvertableMap (Node, Edge, UndirEdge). - typedef typename _Map::Key Key; - /// The value type of the InvertableMap. - typedef typename _Map::Value Value; - - /// \brief Constructor. - /// - /// Construct a new InvertableMap for the graph. - /// - InvertableMap(const Graph& graph) : Map(graph) {} - - /// \brief The setter function of the map. - /// - /// Sets the mapped value. - void set(const Key& key, const Value& val) { - Value oldval = Map::operator[](key); - typename Container::iterator it = invMap.find(oldval); - if (it != invMap.end() && it->second == key) { - invMap.erase(it); - } - invMap.insert(make_pair(val, key)); - Map::set(key, val); - } - - /// \brief The getter function of the map. - /// - /// It gives back the value associated with the key. - const Value operator[](const Key& key) const { - return Map::operator[](key); - } - - /// \brief Add a new key to the map. - /// - /// Add a new key to the map. It is called by the - /// \c AlterationNotifier. - virtual void add(const Key& key) { - Map::add(key); - } - - /// \brief Erase the key from the map. - /// - /// Erase the key to the map. It is called by the - /// \c AlterationNotifier. - virtual void erase(const Key& key) { - Value val = Map::operator[](key); - typename Container::iterator it = invMap.find(val); - if (it != invMap.end() && it->second == key) { - invMap.erase(it); - } - Map::erase(key); - } - - /// \brief Clear the keys from the map and inverse map. - /// - /// Clear the keys from the map and inverse map. It is called by the - /// \c AlterationNotifier. - virtual void clear() { - invMap.clear(); - Map::clear(); - } - - private: - - typedef std::map Container; - Container invMap; - - public: - - /// \brief The inverse map type. - /// - /// The inverse of this map. The subscript operator of the map - /// gives back always the item what was last assigned to the value. - class InverseMap { - public: - /// \brief Constructor of the InverseMap. - /// - /// Constructor of the InverseMap. - InverseMap(const InvertableMap& _inverted) : inverted(_inverted) {} - - /// The value type of the InverseMap. - typedef typename InvertableMap::Key Value; - /// The key type of the InverseMap. - typedef typename InvertableMap::Value Key; - - /// \brief Subscript operator. - /// - /// Subscript operator. It gives back always the item - /// what was last assigned to the value. - Value operator[](const Key& key) const { - typename Container::const_iterator it = inverted.invMap.find(key); - return it->second; - } - - private: - const InvertableMap& inverted; - }; - - /// \brief It gives back the just readeable inverse map. - /// - /// It gives back the just readeable inverse map. - InverseMap inverse() const { - return InverseMap(*this); - } - - - - }; - - /// \brief Provides a mutable, continuous and unique descriptor for each - /// item in the graph. - /// - /// The DescriptorMap class provides a mutable, continuous and immutable - /// mapping for each item in the graph. The value for an item may mutated - /// on each operation when the an item erased or added to graph. - /// - /// \param _Graph The graph class the \c DescriptorMap belongs to. - /// \param _Item The Item is the Key of the Map. It may be Node, Edge or - /// UndirEdge. - /// \param _Map A ReadWriteMap mapping from the item type to integer. - template < - typename _Graph, - typename _Item, - typename _Map - = typename ItemSetTraits<_Graph, _Item>::template Map::Parent - > - class DescriptorMap : protected _Map { - - typedef _Item Item; - typedef _Map Map; - - public: - /// The graph class of DescriptorMap. - typedef _Graph Graph; - - /// The key type of DescriptorMap (Node, Edge, UndirEdge). - typedef typename _Map::Key Key; - /// The value type of DescriptorMap. - typedef typename _Map::Value Value; - - /// \brief Constructor. - /// - /// Constructor for descriptor map. - DescriptorMap(const Graph& _graph) : Map(_graph) { - build(); - } - - /// \brief Add a new key to the map. - /// - /// Add a new key to the map. It is called by the - /// \c AlterationNotifier. - virtual void add(const Item& item) { - Map::add(item); - Map::set(item, invMap.size()); - invMap.push_back(item); - } - - /// \brief Erase the key from the map. - /// - /// Erase the key to the map. It is called by the - /// \c AlterationNotifier. - virtual void erase(const Item& item) { - Map::set(invMap.back(), Map::operator[](item)); - invMap[Map::operator[](item)] = invMap.back(); - invMap.pop_back(); - Map::erase(item); - } - - /// \brief Build the unique map. - /// - /// Build the unique map. It is called by the - /// \c AlterationNotifier. - virtual void build() { - Map::build(); - Item it; - const typename Map::Graph* graph = Map::getGraph(); - for (graph->first(it); it != INVALID; graph->next(it)) { - Map::set(it, invMap.size()); - invMap.push_back(it); - } - } - - /// \brief Clear the keys from the map. - /// - /// Clear the keys from the map. It is called by the - /// \c AlterationNotifier. - virtual void clear() { - invMap.clear(); - Map::clear(); - } - - /// \brief Gives back the \e descriptor of the item. - /// - /// Gives back the mutable and unique \e descriptor of the map. - int operator[](const Item& item) const { - return Map::operator[](item); - } - - private: - - typedef std::vector Container; - Container invMap; - - public: - /// \brief The inverse map type. - /// - /// The inverse map type. - class InverseMap { - public: - /// \brief Constructor of the InverseMap. - /// - /// Constructor of the InverseMap. - InverseMap(const DescriptorMap& _inverted) - : inverted(_inverted) {} - - - /// The value type of the InverseMap. - typedef typename DescriptorMap::Key Value; - /// The key type of the InverseMap. - typedef typename DescriptorMap::Value Key; - - /// \brief Subscript operator. - /// - /// Subscript operator. It gives back the item - /// that the descriptor belongs to currently. - Value operator[](const Key& key) const { - return inverted.invMap[key]; - } - - private: - const DescriptorMap& inverted; - }; - - /// \brief Gives back the inverse of the map. - /// - /// Gives back the inverse of the map. - const InverseMap inverse() const { - return InverseMap(*this); - } - }; - - /// \brief Returns the source of the given edge. - /// - /// The SourceMap gives back the source Node of the given edge. - /// \author Balazs Dezso - template - class SourceMap { - public: - - typedef True NeedCopy; - - typedef typename Graph::Node Value; - typedef typename Graph::Edge Key; - - /// \brief Constructor - /// - /// Constructor - /// \param _graph The graph that the map belongs to. - SourceMap(const Graph& _graph) : graph(_graph) {} - - /// \brief The subscript operator. - /// - /// The subscript operator. - /// \param edge The edge - /// \return The source of the edge - Value operator[](const Key& edge) { - return graph.source(edge); - } - - private: - const Graph& graph; - }; - - /// \brief Returns a \ref SourceMap class - /// - /// This function just returns an \ref SourceMap class. - /// \relates SourceMap - template - inline SourceMap sourceMap(const Graph& graph) { - return SourceMap(graph); - } - - /// \brief Returns the target of the given edge. - /// - /// The TargetMap gives back the target Node of the given edge. - /// \author Balazs Dezso - template - class TargetMap { - public: - - typedef True NeedCopy; - - typedef typename Graph::Node Value; - typedef typename Graph::Edge Key; - - /// \brief Constructor - /// - /// Constructor - /// \param _graph The graph that the map belongs to. - TargetMap(const Graph& _graph) : graph(_graph) {} - - /// \brief The subscript operator. - /// - /// The subscript operator. - /// \param edge The edge - /// \return The target of the edge - Value operator[](const Key& key) { - return graph.target(key); - } - - private: - const Graph& graph; - }; - - /// \brief Returns a \ref TargetMap class - - /// This function just returns an \ref TargetMap class. - /// \relates TargetMap - template - inline TargetMap targetMap(const Graph& graph) { - return TargetMap(graph); - } - - /// \brief Returns the "forward" directed edge view of undirected edge. - /// - /// Returns the "forward" directed edge view of undirected edge. - /// \author Balazs Dezso - template - class ForwardMap { - public: - - typedef True NeedCopy; - - typedef typename Graph::Edge Value; - typedef typename Graph::UndirEdge Key; - - /// \brief Constructor - /// - /// Constructor - /// \param _graph The graph that the map belongs to. - ForwardMap(const Graph& _graph) : graph(_graph) {} - - /// \brief The subscript operator. - /// - /// The subscript operator. - /// \param key An undirected edge - /// \return The "forward" directed edge view of undirected edge - Value operator[](const Key& key) const { - return graph.edgeWithSource(key, graph.source(key)); - } - - private: - const Graph& graph; - }; - - /// \brief Returns a \ref ForwardMap class - - /// This function just returns an \ref ForwardMap class. - /// \relates ForwardMap - template - inline ForwardMap forwardMap(const Graph& graph) { - return ForwardMap(graph); - } - - /// \brief Returns the "backward" directed edge view of undirected edge. - /// - /// Returns the "backward" directed edge view of undirected edge. - /// \author Balazs Dezso - template - class BackwardMap { - public: - typedef True NeedCopy; - - typedef typename Graph::Edge Value; - typedef typename Graph::UndirEdge Key; - - /// \brief Constructor - /// - /// Constructor - /// \param _graph The graph that the map belongs to. - BackwardMap(const Graph& _graph) : graph(_graph) {} - - /// \brief The subscript operator. - /// - /// The subscript operator. - /// \param key An undirected edge - /// \return The "backward" directed edge view of undirected edge - Value operator[](const Key& key) const { - return graph.edgeWithSource(key, graph.target(key)); - } - - private: - const Graph& graph; - }; - - /// \brief Returns a \ref BackwardMap class - - /// This function just returns an \ref BackwardMap class. - /// \relates BackwardMap - template - inline BackwardMap backwardMap(const Graph& graph) { - return BackwardMap(graph); - } - - - /// @} - -} //END OF NAMESPACE LEMON - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/graph_writer.h --- a/src/lemon/graph_writer.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,683 +0,0 @@ -/* -*- C++ -*- - * src/lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -///\ingroup io_group -///\file -///\brief Lemon Graph Format writer. - -#ifndef LEMON_GRAPH_WRITER_H -#define LEMON_GRAPH_WRITER_H - -#include - -#include -#include - -namespace lemon { - - /// \addtogroup io_group - /// @{ - - /// \brief The graph writer class. - /// - /// The \c GraphWriter class provides the graph output. To write a graph - /// you should first give writing commands for the writer. You can declare - /// write command as \c NodeMap or \c EdgeMap writing and labeled Node and - /// Edge writing. - /// - /// \code - /// GraphWriter writer(std::cout, graph); - /// \endcode - /// - /// The \c writeNodeMap() function declares a \c NodeMap writing - /// command in the \c GraphWriter. You should give as parameter - /// the name of the map and the map object. The NodeMap writing - /// command with name "id" should write a unique map because it - /// is regarded as ID map. - /// - /// \code - /// IdMap nodeIdMap; - /// writer.writeNodeMap("id", nodeIdMap); - /// - /// writer.writeNodeMap("coords", coords); - /// writer.writeNodeMap("color", colorMap); - /// \endcode - /// - /// With the \c writeEdgeMap() member function you can give an edge map - /// writing command similar to the NodeMaps. - /// - /// \code - /// DescriptorMap > - /// edgeDescMap(graph); - /// writer.writeEdgeMap("descriptor", edgeDescMap); - /// - /// writer.writeEdgeMap("weight", weightMap); - /// writer.writeEdgeMap("label", labelMap); - /// \endcode - /// - /// With \c writeNode() and \c writeEdge() functions you can - /// point out Nodes and Edges in the graph. By example, you can - /// write out the source and target of the graph. - /// - /// \code - /// writer.writeNode("source", sourceNode); - /// writer.writeNode("target", targetNode); - /// - /// writer.writeEdge("observed", edge); - /// \endcode - /// - /// After you give all write commands you must call the \c run() member - /// function, which execute all the writer commands. - /// - /// \code - /// writer.run(); - /// \endcode - /// - /// \see DefaultWriterTraits - /// \see QuotedStringWriter - /// \see IdMap - /// \see DescriptorMap - /// \see \ref GraphReader - /// \see \ref graph-io-page - /// \author Balazs Dezso - template - class GraphWriter { - public: - - typedef _Graph Graph; - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - - typedef _WriterTraits WriterTraits; - - /// \brief Construct a new GraphWriter. - /// - /// Construct a new GraphWriter. It writes the given graph - /// to the given stream. - GraphWriter(std::ostream& _os, const Graph& _graph) - : writer(new LemonWriter(_os)), own_writer(true), - nodeset_writer(*writer, _graph, std::string()), - edgeset_writer(*writer, _graph, nodeset_writer, std::string()), - node_writer(*writer, nodeset_writer, std::string()), - edge_writer(*writer, edgeset_writer, std::string()), - attribute_writer(*writer, std::string()) {} - - /// \brief Construct a new GraphWriter. - /// - /// Construct a new GraphWriter. It writes into the given graph - /// to the given file. - GraphWriter(const std::string& _filename, const Graph& _graph) - : writer(new LemonWriter(_filename)), own_writer(true), - nodeset_writer(*writer, _graph, std::string()), - edgeset_writer(*writer, _graph, nodeset_writer, std::string()), - node_writer(*writer, nodeset_writer, std::string()), - edge_writer(*writer, edgeset_writer, std::string()), - attribute_writer(*writer, std::string()) {} - - /// \brief Construct a new GraphWriter. - /// - /// Construct a new GraphWriter. It writes into the given graph - /// to given LemonReader. - GraphWriter(LemonWriter& _writer, const Graph& _graph) - : writer(_writer), own_writer(false), - nodeset_writer(*writer, _graph, std::string()), - edgeset_writer(*writer, _graph, nodeset_writer, std::string()), - node_writer(*writer, nodeset_writer, std::string()), - edge_writer(*writer, edgeset_writer, std::string()), - attribute_writer(*writer, std::string()) {} - - /// \brief Destruct the graph writer. - /// - /// Destruct the graph writer. - ~GraphWriter() { - if (own_writer) - delete writer; - } - - /// \brief Add a new node map writer command for the writer. - /// - /// Add a new node map writer command for the writer. - template - GraphWriter& writeNodeMap(std::string name, const Map& map) { - nodeset_writer.writeNodeMap(name, map); - return *this; - } - - /// \brief Add a new node map writer command for the writer. - /// - /// Add a new node map writer command for the writer. - template - GraphWriter& writeNodeMap(std::string name, const Map& map, - const Writer& writer = Writer()) { - nodeset_writer.writeNodeMap(name, map, writer); - return *this; - } - - - /// \brief Add a new edge map writer command for the writer. - /// - /// Add a new edge map writer command for the writer. - template - GraphWriter& writeEdgeMap(std::string name, const Map& map) { - edgeset_writer.writeEdgeMap(name, map); - return *this; - } - - - /// \brief Add a new edge map writer command for the writer. - /// - /// Add a new edge map writer command for the writer. - template - GraphWriter& writeEdgeMap(std::string name, const Map& map, - const Writer& writer = Writer()) { - edgeset_writer.writeEdgeMap(name, map, writer); - return *this; - } - - /// \brief Add a new labeled node writer for the writer. - /// - /// Add a new labeled node writer for the writer. - GraphWriter& writeNode(std::string name, const Node& node) { - node_writer.writeNode(name, node); - return *this; - } - - /// \brief Add a new labeled edge writer for the writer. - /// - /// Add a new labeled edge writer for the writer. - GraphWriter& writeEdge(std::string name, const Edge& edge) { - edge_writer.writeEdge(name, edge); - } - - /// \brief Add a new attribute writer command. - /// - /// Add a new attribute writer command. - template - GraphWriter& writeAttribute(std::string name, const Value& value) { - attribute_writer.writeAttribute(name, value); - return *this; - } - - /// \brief Add a new attribute writer command. - /// - /// Add a new attribute writer command. - template - GraphWriter& writeAttribute(std::string name, const Value& value, - const Writer& writer) { - attribute_writer.writeAttribute(name, value, writer); - return *this; - } - - /// \brief Conversion operator to LemonWriter. - /// - /// Conversion operator to LemonWriter. It make possible - /// to access the encapsulated \e LemonWriter, this way - /// you can attach to this writer new instances of - /// \e LemonWriter::SectionWriter. - operator LemonWriter&() { - return *writer; - } - - /// \brief Executes the writer commands. - /// - /// Executes the writer commands. - void run() { - writer->run(); - } - - /// \brief Write the id of the given node. - /// - /// It writes the id of the given node. If there was written an "id" - /// named node map then it will write the map value belongs to the node. - void writeId(std::ostream& os, const Node& item) const { - nodeset_writer.writeId(os, item); - } - - /// \brief Write the id of the given edge. - /// - /// It writes the id of the given edge. If there was written an "id" - /// named edge map then it will write the map value belongs to the edge. - void writeId(std::ostream& os, const Edge& item) const { - edgeset_writer.writeId(os, item); - } - - private: - - LemonWriter* writer; - bool own_writer; - - NodeSetWriter nodeset_writer; - EdgeSetWriter edgeset_writer; - - NodeWriter node_writer; - EdgeWriter edge_writer; - - AttributeWriter attribute_writer; - }; - - - /// \brief Write a graph to the output. - /// - /// Write a graph to the output. - /// \param os The output stream. - /// \param g The graph. - /// \param capacity The capacity map. - /// \param s The source node. - /// \param t The target node. - /// \param cost The cost map. - template - void writeGraph(std::ostream& os, const Graph &g, - const CapacityMap& capacity, const typename Graph::Node &s, - const typename Graph::Node &t, const CostMap& cost) { - GraphWriter writer(os, g); - IdMap nodeIdMap(g); - writer.writeNodeMap("id", nodeIdMap); - IdMap edgeIdMap(g); - writer.writeEdgeMap("id", edgeIdMap); - writer.writeEdgeMap("capacity", capacity); - writer.writeEdgeMap("cost", cost); - writer.writeNode("source", s); - writer.writeNode("target", t); - writer.run(); - } - - /// \brief Write a graph to the output. - /// - /// Write a graph to the output. - /// \param os The output stream. - /// \param g The graph. - /// \param capacity The capacity map. - /// \param s The source node. - /// \param t The target node. - template - void writeGraph(std::ostream& os, const Graph &g, - const CapacityMap& capacity, const typename Graph::Node &s, - const typename Graph::Node &t) { - GraphWriter writer(os, g); - IdMap nodeIdMap(g); - writer.writeNodeMap("id", nodeIdMap); - IdMap edgeIdMap(g); - writer.writeEdgeMap("id", edgeIdMap); - writer.writeEdgeMap("capacity", capacity); - writer.writeNode("source", s); - writer.writeNode("target", t); - writer.run(); - } - - /// \brief Write a graph to the output. - /// - /// Write a graph to the output. - /// \param os The output stream. - /// \param g The graph. - /// \param capacity The capacity map. - /// \param s The source node. - template - void writeGraph(std::ostream& os, const Graph &g, - const CapacityMap& capacity, const typename Graph::Node &s) { - GraphWriter writer(os, g); - IdMap nodeIdMap(g); - writer.writeNodeMap("id", nodeIdMap); - IdMap edgeIdMap(g); - writer.writeEdgeMap("id", edgeIdMap); - writer.writeEdgeMap("capacity", capacity); - writer.writeNode("source", s); - writer.run(); - } - - /// \brief Write a graph to the output. - /// - /// Write a graph to the output. - /// \param os The output stream. - /// \param g The graph. - /// \param capacity The capacity map. - template - void writeGraph(std::ostream& os, const Graph &g, - const CapacityMap& capacity) { - GraphWriter writer(os, g); - IdMap nodeIdMap(g); - writer.writeNodeMap("id", nodeIdMap); - IdMap edgeIdMap(g); - writer.writeEdgeMap("id", edgeIdMap); - writer.writeEdgeMap("capacity", capacity); - writer.run(); - } - - /// \brief Write a graph to the output. - /// - /// Write a graph to the output. - /// \param os The output stream. - /// \param g The graph. - template - void writeGraph(std::ostream& os, const Graph &g) { - GraphWriter writer(os, g); - IdMap nodeIdMap(g); - writer.writeNodeMap("id", nodeIdMap); - IdMap edgeIdMap(g); - writer.writeEdgeMap("id", edgeIdMap); - writer.run(); - } - - /// \brief The undirected graph writer class. - /// - /// The \c UndirGraphWriter class provides the undir graph output. To write - /// a graph you should first give writing commands for the writer. You can - /// declare write command as \c NodeMap, \c EdgeMap or \c UndirEdgeMap - /// writing and labeled Node, Edge or UndirEdge writing. - /// - /// \code - /// UndirGraphWriter writer(std::cout, graph); - /// \endcode - /// - /// The \c writeNodeMap() function declares a \c NodeMap writing - /// command in the \c UndirGraphWriter. You should give as parameter - /// the name of the map and the map object. The NodeMap writing - /// command with name "id" should write a unique map because it - /// is regarded as ID map. - /// - /// \code - /// IdMap nodeIdMap; - /// writer.writeNodeMap("id", nodeIdMap); - /// - /// writer.writeNodeMap("coords", coords); - /// writer.writeNodeMap("color", colorMap); - /// \endcode - /// - /// With the \c writeUndirEdgeMap() member function you can give an - /// undirected edge map writing command similar to the NodeMaps. - /// - /// \code - /// DescriptorMap > - /// edgeDescMap(graph); - /// writer.writeUndirEdgeMap("descriptor", edgeDescMap); - /// - /// writer.writeUndirEdgeMap("weight", weightMap); - /// writer.writeUndirEdgeMap("label", labelMap); - /// \endcode - /// - /// The EdgeMap handling is just a syntactical sugar. It writes - /// two undirected edge map with '+' and '-' prefix in the name. - /// - /// \code - /// writer.writeEdgeMap("capacity", capacityMap); - /// \endcode - /// - /// - /// With \c writeNode() and \c writeUndirEdge() functions you can - /// point out nodes and undirected edges in the graph. By example, you can - /// write out the source and target of the graph. - /// - /// \code - /// writer.writeNode("source", sourceNode); - /// writer.writeNode("target", targetNode); - /// - /// writer.writeUndirEdge("observed", undirEdge); - /// \endcode - /// - /// After you give all write commands you must call the \c run() member - /// function, which execute all the writer commands. - /// - /// \code - /// writer.run(); - /// \endcode - /// - /// \see DefaultWriterTraits - /// \see QuotedStringWriter - /// \see IdMap - /// \see DescriptorMap - /// \see \ref GraphWriter - /// \see \ref graph-io-page - /// \author Balazs Dezso - template - class UndirGraphWriter { - public: - - typedef _Graph Graph; - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - typedef typename Graph::UndirEdge UndirEdge; - - typedef _WriterTraits WriterTraits; - - /// \brief Construct a new UndirGraphWriter. - /// - /// Construct a new UndirGraphWriter. It writes the given graph - /// to the given stream. - UndirGraphWriter(std::ostream& _os, const Graph& _graph) - : writer(new LemonWriter(_os)), own_writer(true), - nodeset_writer(*writer, _graph, std::string()), - undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), - node_writer(*writer, nodeset_writer, std::string()), - undir_edge_writer(*writer, undir_edgeset_writer, std::string()), - attribute_writer(*writer, std::string()) {} - - /// \brief Construct a new UndirGraphWriter. - /// - /// Construct a new UndirGraphWriter. It writes into the given graph - /// to the given file. - UndirGraphWriter(const std::string& _filename, const Graph& _graph) - : writer(new LemonWriter(_filename)), own_writer(true), - nodeset_writer(*writer, _graph, std::string()), - undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), - node_writer(*writer, nodeset_writer, std::string()), - undir_edge_writer(*writer, undir_edgeset_writer, std::string()), - attribute_writer(*writer, std::string()) {} - - /// \brief Construct a new UndirGraphWriter. - /// - /// Construct a new UndirGraphWriter. It writes into the given graph - /// to given LemonReader. - UndirGraphWriter(LemonWriter& _writer, const Graph& _graph) - : writer(_writer), own_writer(false), - nodeset_writer(*writer, _graph, std::string()), - undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), - node_writer(*writer, nodeset_writer, std::string()), - undir_edge_writer(*writer, undir_edgeset_writer, std::string()), - attribute_writer(*writer, std::string()) {} - - /// \brief Destruct the graph writer. - /// - /// Destruct the graph writer. - ~UndirGraphWriter() { - if (own_writer) - delete writer; - } - - /// \brief Add a new node map writer command for the writer. - /// - /// Add a new node map writer command for the writer. - template - UndirGraphWriter& writeNodeMap(std::string name, const Map& map) { - nodeset_writer.writeNodeMap(name, map); - return *this; - } - - /// \brief Add a new node map writer command for the writer. - /// - /// Add a new node map writer command for the writer. - template - UndirGraphWriter& writeNodeMap(std::string name, const Map& map, - const Writer& writer = Writer()) { - nodeset_writer.writeNodeMap(name, map, writer); - return *this; - } - - /// \brief Add a new edge map writer command for the writer. - /// - /// Add a new edge map writer command for the writer. - template - UndirGraphWriter& writeEdgeMap(std::string name, const Map& map) { - undir_edgeset_writer.writeEdgeMap(name, map); - return *this; - } - - /// \brief Add a new edge map writer command for the writer. - /// - /// Add a new edge map writer command for the writer. - template - UndirGraphWriter& writeEdgeMap(std::string name, const Map& map, - const Writer& writer = Writer()) { - undir_edgeset_writer.writeEdgeMap(name, map, writer); - return *this; - } - - /// \brief Add a new undirected edge map writer command for the writer. - /// - /// Add a new undirected edge map writer command for the writer. - template - UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map) { - undir_edgeset_writer.writeUndirEdgeMap(name, map); - return *this; - } - - /// \brief Add a new undirected edge map writer command for the writer. - /// - /// Add a new edge undirected map writer command for the writer. - template - UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map, - const Writer& writer = Writer()) { - undir_edgeset_writer.writeUndirEdgeMap(name, map, writer); - return *this; - } - - /// \brief Add a new labeled node writer for the writer. - /// - /// Add a new labeled node writer for the writer. - UndirGraphWriter& writeNode(std::string name, const Node& node) { - node_writer.writeNode(name, node); - return *this; - } - - /// \brief Add a new labeled edge writer for the writer. - /// - /// Add a new labeled edge writer for the writer. - UndirGraphWriter& writeEdge(std::string name, const Edge& edge) { - undir_edge_writer.writeEdge(name, edge); - } - - /// \brief Add a new labeled undirected edge writer for the writer. - /// - /// Add a new labeled undirected edge writer for the writer. - UndirGraphWriter& writeUndirEdge(std::string name, const UndirEdge& edge) { - undir_edge_writer.writeUndirEdge(name, edge); - } - - /// \brief Add a new attribute writer command. - /// - /// Add a new attribute writer command. - template - UndirGraphWriter& writeAttribute(std::string name, const Value& value) { - attribute_writer.writeAttribute(name, value); - return *this; - } - - /// \brief Add a new attribute writer command. - /// - /// Add a new attribute writer command. - template - UndirGraphWriter& writeAttribute(std::string name, const Value& value, - const Writer& writer) { - attribute_writer.writeAttribute(name, value, writer); - return *this; - } - - /// \brief Conversion operator to LemonWriter. - /// - /// Conversion operator to LemonWriter. It make possible - /// to access the encapsulated \e LemonWriter, this way - /// you can attach to this writer new instances of - /// \e LemonWriter::SectionWriter. - operator LemonWriter&() { - return *writer; - } - - /// \brief Executes the writer commands. - /// - /// Executes the writer commands. - void run() { - writer->run(); - } - - /// \brief Write the id of the given node. - /// - /// It writes the id of the given node. If there was written an "id" - /// named node map then it will write the map value belongs to the node. - void writeId(std::ostream& os, const Node& item) const { - nodeset_writer.writeId(os, item); - } - - /// \brief Write the id of the given edge. - /// - /// It writes the id of the given edge. If there was written an "id" - /// named edge map then it will write the map value belongs to the edge. - void writeId(std::ostream& os, const Edge& item) const { - undir_edgeset_writer.writeId(os, item); - } - - /// \brief Write the id of the given undirected edge. - /// - /// It writes the id of the given undirected edge. If there was written - /// an "id" named edge map then it will write the map value belongs to - /// the edge. - void writeId(std::ostream& os, const UndirEdge& item) const { - undir_edgeset_writer.writeId(os, item); - } - - - private: - - LemonWriter* writer; - bool own_writer; - - NodeSetWriter nodeset_writer; - UndirEdgeSetWriter undir_edgeset_writer; - - NodeWriter node_writer; - UndirEdgeWriter undir_edge_writer; - - AttributeWriter attribute_writer; - }; - - - /// \brief Write an undirected graph to the output. - /// - /// Write an undirected graph to the output. - /// \param os The output stream. - /// \param g The graph. - /// \param capacity The capacity undirected map. - template - void writeUndirGraph(std::ostream& os, const Graph &g, - const CapacityMap& capacity) { - UndirGraphWriter writer(os, g); - writer.writeUndirEdgeMap("capacity", capacity); - writer.run(); - } - - /// \brief Write an undirected graph to the output. - /// - /// Write an undirected graph to the output. - /// \param os The output stream. - /// \param g The graph. - template - void writeUndirGraph(std::ostream& os, const Graph &g) { - UndirGraphWriter writer(os, g); - writer.run(); - } - - /// @} - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/invalid.h --- a/src/lemon/invalid.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* -*- C++ -*- - * src/lemon/invalid.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_INVALID_H -#define LEMON_INVALID_H - -///\file -///\brief Definition of INVALID. - -namespace lemon { - - /// Dummy type to make it easier to make invalid iterators. - - /// See \ref INVALID, how to use it. - - struct Invalid { - public: - bool operator==(Invalid) { return true; } - bool operator!=(Invalid) { return false; } - bool operator< (Invalid) { return false; } - }; - - /// Invalid iterators. - - /// \ref Invalid is a global type that converts to each iterator - /// in such a way that the value of the target iterator will be invalid. - - // It is also used to convert the \c INVALID constant to the - // node iterator that makes is possible to write - - //extern Invalid INVALID; - - //const Invalid &INVALID = *(Invalid *)0; - const Invalid INVALID = Invalid(); - -} //namespace lemon - -#endif - diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/kruskal.h --- a/src/lemon/kruskal.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,348 +0,0 @@ -/* -*- C++ -*- - * src/lemon/kruskal.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_KRUSKAL_H -#define LEMON_KRUSKAL_H - -#include -#include - -/** -@defgroup spantree Minimum Cost Spanning Tree Algorithms -@ingroup galgs -\brief This group containes the algorithms for finding a minimum cost spanning -tree in a graph - -This group containes the algorithms for finding a minimum cost spanning -tree in a graph -*/ - -///\ingroup spantree -///\file -///\brief Kruskal's algorithm to compute a minimum cost tree -/// -///Kruskal's algorithm to compute a minimum cost tree. - -namespace lemon { - - /// \addtogroup spantree - /// @{ - - /// Kruskal's algorithm to find a minimum cost tree of a graph. - - /// This function runs Kruskal's algorithm to find a minimum cost tree. - /// \param G The graph the algorithm runs on. The algorithm considers the - /// graph to be undirected, the direction of the edges are not used. - /// - /// \param in This object is used to describe the edge costs. It must - /// be an STL compatible 'Forward Container' - /// with std::pair as its value_type, - /// where X is the type of the costs. It must contain every edge in - /// cost-ascending order. - ///\par - /// For the sake of simplicity, there is a helper class KruskalMapInput, - /// which converts a - /// simple edge map to an input of this form. Alternatively, you can use - /// the function \ref kruskalEdgeMap to compute the minimum cost tree if - /// the edge costs are given by an edge map. - /// - /// \retval out This must be a writable \c bool edge map. - /// After running the algorithm - /// this will contain the found minimum cost spanning tree: the value of an - /// edge will be set to \c true if it belongs to the tree, otherwise it will - /// be set to \c false. The value of each edge will be set exactly once. - /// - /// \return The cost of the found tree. - - template - typename IN::value_type::second_type - kruskal(GR const& G, IN const& in, - OUT& out) - { - typedef typename IN::value_type::second_type EdgeCost; - typedef typename GR::template NodeMap NodeIntMap; - typedef typename GR::Node Node; - - NodeIntMap comp(G, -1); - UnionFind uf(comp); - - EdgeCost tot_cost = 0; - for (typename IN::const_iterator p = in.begin(); - p!=in.end(); ++p ) { - if ( uf.join(G.target((*p).first), - G.source((*p).first)) ) { - out.set((*p).first, true); - tot_cost += (*p).second; - } - else { - out.set((*p).first, false); - } - } - return tot_cost; - } - - /* A work-around for running Kruskal with const-reference bool maps... */ - - /// Helper class for calling kruskal with "constant" output map. - - /// Helper class for calling kruskal with output maps constructed - /// on-the-fly. - /// - /// A typical examle is the following call: - /// kruskal(G, some_input, makeSequenceOutput(iterator)). - /// Here, the third argument is a temporary object (which wraps around an - /// iterator with a writable bool map interface), and thus by rules of C++ - /// is a \c const object. To enable call like this exist this class and - /// the prototype of the \ref kruskal() function with const& OUT - /// third argument. - template - class NonConstMapWr { - const Map &m; - public: - typedef typename Map::Value Value; - - NonConstMapWr(const Map &_m) : m(_m) {} - - template - void set(Key const& k, Value const &v) const { m.set(k,v); } - }; - - template - inline - typename IN::value_type::second_type - kruskal(GR const& G, IN const& edges, OUT const& out_map) - { - NonConstMapWr map_wr(out_map); - return kruskal(G, edges, map_wr); - } - - /* ** ** Input-objects ** ** */ - - /// Kruskal's input source. - - /// Kruskal's input source. - /// - /// In most cases you possibly want to use the \ref kruskalEdgeMap() instead. - /// - /// \sa makeKruskalMapInput() - /// - ///\param GR The type of the graph the algorithm runs on. - ///\param Map An edge map containing the cost of the edges. - ///\par - ///The cost type can be any type satisfying - ///the STL 'LessThan comparable' - ///concept if it also has an operator+() implemented. (It is necessary for - ///computing the total cost of the tree). - /// - template - class KruskalMapInput - : public std::vector< std::pair > { - - public: - typedef std::vector< std::pair > Parent; - typedef typename Parent::value_type value_type; - - private: - class comparePair { - public: - bool operator()(const value_type& a, - const value_type& b) { - return a.second < b.second; - } - }; - - public: - - void sort() { - std::sort(this->begin(), this->end(), comparePair()); - } - - KruskalMapInput(GR const& G, Map const& m) { - typedef typename GR::EdgeIt EdgeIt; - - for(EdgeIt e(G);e!=INVALID;++e) push_back(value_type(e, m[e])); - sort(); - } - }; - - /// Creates a KruskalMapInput object for \ref kruskal() - - /// It makes easier to use - /// \ref KruskalMapInput by making it unnecessary - /// to explicitly give the type of the parameters. - /// - /// In most cases you possibly - /// want to use the function kruskalEdgeMap() instead. - /// - ///\param G The type of the graph the algorithm runs on. - ///\param m An edge map containing the cost of the edges. - ///\par - ///The cost type can be any type satisfying the - ///STL 'LessThan Comparable' - ///concept if it also has an operator+() implemented. (It is necessary for - ///computing the total cost of the tree). - /// - ///\return An appropriate input source for \ref kruskal(). - /// - template - inline - KruskalMapInput makeKruskalMapInput(const GR &G,const Map &m) - { - return KruskalMapInput(G,m); - } - - - - /* ** ** Output-objects: simple writable bool maps ** ** */ - - - - /// A writable bool-map that makes a sequence of "true" keys - - /// A writable bool-map that creates a sequence out of keys that receives - /// the value "true". - /// - /// \sa makeKruskalSequenceOutput() - /// - /// Very often, when looking for a min cost spanning tree, we want as - /// output a container containing the edges of the found tree. For this - /// purpose exist this class that wraps around an STL iterator with a - /// writable bool map interface. When a key gets value "true" this key - /// is added to sequence pointed by the iterator. - /// - /// A typical usage: - /// \code - /// std::vector v; - /// kruskal(g, input, makeKruskalSequenceOutput(back_inserter(v))); - /// \endcode - /// - /// For the most common case, when the input is given by a simple edge - /// map and the output is a sequence of the tree edges, a special - /// wrapper function exists: \ref kruskalEdgeMap_IteratorOut(). - /// - /// \warning Not a regular property map, as it doesn't know its Key - - template - class KruskalSequenceOutput { - mutable Iterator it; - - public: - typedef bool Value; - - KruskalSequenceOutput(Iterator const &_it) : it(_it) {} - - template - void set(Key const& k, bool v) const { if(v) {*it=k; ++it;} } - }; - - template - inline - KruskalSequenceOutput - makeKruskalSequenceOutput(Iterator it) { - return KruskalSequenceOutput(it); - } - - - - /* ** ** Wrapper funtions ** ** */ - - - - /// \brief Wrapper function to kruskal(). - /// Input is from an edge map, output is a plain bool map. - /// - /// Wrapper function to kruskal(). - /// Input is from an edge map, output is a plain bool map. - /// - ///\param G The type of the graph the algorithm runs on. - ///\param in An edge map containing the cost of the edges. - ///\par - ///The cost type can be any type satisfying the - ///STL 'LessThan Comparable' - ///concept if it also has an operator+() implemented. (It is necessary for - ///computing the total cost of the tree). - /// - /// \retval out This must be a writable \c bool edge map. - /// After running the algorithm - /// this will contain the found minimum cost spanning tree: the value of an - /// edge will be set to \c true if it belongs to the tree, otherwise it will - /// be set to \c false. The value of each edge will be set exactly once. - /// - /// \return The cost of the found tree. - - template - inline - typename IN::Value - kruskalEdgeMap(GR const& G, - IN const& in, - RET &out) { - return kruskal(G, - KruskalMapInput(G,in), - out); - } - - /// \brief Wrapper function to kruskal(). - /// Input is from an edge map, output is an STL Sequence. - /// - /// Wrapper function to kruskal(). - /// Input is from an edge map, output is an STL Sequence. - /// - ///\param G The type of the graph the algorithm runs on. - ///\param in An edge map containing the cost of the edges. - ///\par - ///The cost type can be any type satisfying the - ///STL 'LessThan Comparable' - ///concept if it also has an operator+() implemented. (It is necessary for - ///computing the total cost of the tree). - /// - /// \retval out This must be an iteraror of an STL Container with - /// GR::Edge as its value_type. - /// The algorithm copies the elements of the found tree into this sequence. - /// For example, if we know that the spanning tree of the graph \c G has - /// say 53 edges then - /// we can put its edges into a STL vector \c tree with a code like this. - /// \code - /// std::vector tree(53); - /// kruskalEdgeMap_IteratorOut(G,cost,tree.begin()); - /// \endcode - /// Or if we don't know in advance the size of the tree, we can write this. - /// \code - /// std::vector tree; - /// kruskalEdgeMap_IteratorOut(G,cost,std::back_inserter(tree)); - /// \endcode - /// - /// \return The cost of the found tree. - /// - /// \bug its name does not follow the coding style. - - template - inline - typename IN::Value - kruskalEdgeMap_IteratorOut(const GR& G, - const IN& in, - RET out) - { - KruskalSequenceOutput _out(out); - return kruskal(G, KruskalMapInput(G, in), _out); - } - - /// @} - -} //namespace lemon - -#endif //LEMON_KRUSKAL_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lemon.pc.in --- a/src/lemon/lemon.pc.in Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: @PACKAGE_NAME@ -Description: a Library of Efficient Models and Optimization in Networks -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lemon -Cflags: -I${includedir} diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lemon_reader.h --- a/src/lemon/lemon_reader.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1977 +0,0 @@ -/* -*- C++ -*- - * src/lemon/lemon_reader.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -///\ingroup io_group -///\file -///\brief Lemon Format reader. - - -#ifndef LEMON_LEMON_READER_H -#define LEMON_LEMON_READER_H - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -namespace lemon { - - namespace _reader_bits { - - template - bool operator<(T, T) { - throw DataFormatError("Id is not comparable"); - } - - template - struct Less { - bool operator()(const T& p, const T& q) const { - return p < q; - } - }; - - template - class WriteComposeMap { - public: - typedef True NeedCopy; - - typedef typename M2::Key Key; - typedef typename M1::Value Value; - - WriteComposeMap(typename SmartParameter::Type _m1, const M2& _m2) - : m1(_m1), m2(_m2) {} - - void set(const Key& key, const Value& value) { - m1.set(m2[key], value); - } - - private: - - typename SmartReference::Type m1; - typename SmartConstReference::Type m2; - - }; - - template - WriteComposeMap writeComposeMap(M1& m1, const M2& m2) { - return WriteComposeMap(m1, m2); - } - - template - WriteComposeMap writeComposeMap(const M1& m1, const M2& m2) { - return WriteComposeMap(m1, m2); - } - - } - - /// \ingroup io_group - /// \brief Lemon Format reader class. - /// - /// The Lemon Format contains several sections. We do not want to - /// determine what sections are in a lemon file we give only a framework - /// to read a section oriented format. - /// - /// In the Lemon Format each section starts with a line contains a \c \@ - /// character on the first not white space position. This line is the - /// header line of the section. Each next lines belong to this section - /// while it does not starts with \c \@ character. This line can start a - /// new section or if it can close the file with the \c \@end line. - /// The file format ignore the empty and comment lines. The line is - /// comment line if it starts with a \c # character. - /// - /// The framework provides an abstract LemonReader::SectionReader class - /// what defines the interface of a SectionReader. The SectionReader - /// has the \c header() member function what get a header line string and - /// decides if it want to process the next section. Several SectionReaders - /// can be attached to an LemonReader and the first attached what can - /// process the section will be used. Its \c read() member will called - /// with a stream contains the section. From this stream the empty and - /// comment lines are filtered out. - /// - /// \relates GraphReader - /// \relates NodeSetReader - /// \relates EdgeSetReader - /// \relates NodesReader - /// \relates EdgesReader - /// \relates AttributeReader - class LemonReader { - private: - - class FilterStreamBuf : public std::streambuf { - public: - - typedef std::streambuf Parent; - typedef Parent::char_type char_type; - FilterStreamBuf(std::istream& is, int& num) - : _is(is), _base(0), _eptr(0), - _num(num), skip_state(after_endl) {} - - protected: - - enum skip_state_type { - no_skip, - after_endl, - comment_line - }; - - char_type small_buf[1]; - - - std::istream& _is; - - char_type* _base; - char_type* _eptr; - - int& _num; - - skip_state_type skip_state; - - - char_type* base() { return _base; } - - char_type* eptr() { return _eptr; } - - int blen() { return _eptr - _base; } - - void setb(char_type* buf, int len) { - _base = buf; - _eptr = buf + len; - } - - virtual std::streambuf* setbuf(char *buf, int len) { - if (base()) return 0; - if (buf != 0 && len >= (int)sizeof(small_buf)) { - setb(buf, len); - } else { - setb(small_buf, sizeof(small_buf)); - } - setg(0, 0, 0); - return this; - } - - bool put_char(char c) { - switch (skip_state) { - case no_skip: - switch (c) { - case '\n': - skip_state = after_endl; - return true; - default: - return true; - } - case after_endl: - switch (c) { - case '@': - return false; - case '\n': - return false; - case '#': - skip_state = comment_line; - return false; - default: - if (!isspace(c)) { - skip_state = no_skip; - return true; - } else { - return false; - } - } - break; - case comment_line: - switch (c) { - case '\n': - skip_state = after_endl; - return false; - default: - return false; - } - } - return false; - } - - virtual int underflow() { - char c; - if (_is.read(&c, 1)) { - _is.putback(c); - if (c == '@') { - return EOF; - } - } else { - return EOF; - } - char_type *ptr; - for (ptr = base(); ptr != eptr(); ++ptr) { - if (_is.read(&c, 1)) { - if (c == '\n') ++_num; - if (put_char(c)) { - *ptr = c; - } else { - if (skip_state == after_endl && c == '@') { - _is.putback('@'); - break; - } - --ptr; - } - } else { - break; - } - } - setg(base(), base(), ptr); - return *base(); - } - - virtual int sync() { - return EOF; - } - }; - - public: - - /// \brief Abstract base class for reading a section. - /// - /// This class has an \c header() member function what get a - /// header line string and decides if it want to process the next - /// section. Several SectionReaders can be attached to an LemonReader - /// and the first attached what can process the section will be used. - /// Its \c read() member will called with a stream contains the section. - /// From this stream the empty lines and comments are filtered out. - class SectionReader { - friend class LemonReader; - protected: - /// \brief Constructor for SectionReader. - /// - /// Constructor for SectionReader. It attach this reader to - /// the given LemonReader. - SectionReader(LemonReader& reader) { - reader.attach(*this); - } - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the SectionReader can process - /// the section with the given header line. - virtual bool header(const std::string& line) = 0; - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) = 0; - }; - - /// \brief Constructor for LemonReader. - /// - /// Constructor for LemonReader which reads from the given stream. - LemonReader(std::istream& _is) - : is(&_is), own_is(false) {} - - /// \brief Constructor for LemonReader. - /// - /// Constructor for LemonReader which reads from the given file. - LemonReader(const std::string& filename) - : is(0), own_is(true) { - is = new std::ifstream(filename.c_str()); - } - - /// \brief Desctructor for LemonReader. - /// - /// Desctructor for LemonReader. - ~LemonReader() { - if (own_is) { - delete is; - } - } - - private: - LemonReader(const LemonReader&); - void operator=(const LemonReader&); - - void attach(SectionReader& reader) { - readers.push_back(&reader); - } - - public: - /// \brief Executes the LemonReader. - /// - /// It executes the LemonReader. - void run() { - int line_num = 0; - std::string line; - try { - while ((++line_num, getline(*is, line)) && line.find("@end") != 0) { - SectionReaders::iterator it; - for (it = readers.begin(); it != readers.end(); ++it) { - if ((*it)->header(line)) { - char buf[2048]; - FilterStreamBuf buffer(*is, line_num); - buffer.pubsetbuf(buf, sizeof(buf)); - std::istream is(&buffer); - (*it)->read(is); - break; - } - } - } - } catch (DataFormatError& error) { - error.line(line_num); - throw error; - } - } - - - private: - - std::istream* is; - bool own_is; - - typedef std::vector SectionReaders; - SectionReaders readers; - - }; - - /// \brief Helper class for implementing the common SectionReaders. - /// - /// Helper class for implementing the common SectionReaders. - class CommonSectionReaderBase : public LemonReader::SectionReader { - typedef LemonReader::SectionReader Parent; - protected: - - /// \brief Constructor for CommonSectionReaderBase. - /// - /// Constructor for CommonSectionReaderBase. It attach this reader to - /// the given LemonReader. - CommonSectionReaderBase(LemonReader& _reader) - : Parent(_reader) {} - - template - class ReaderBase; - - template - class InverterBase : public ReaderBase<_Item> { - public: - typedef _Item Item; - virtual void read(std::istream&, const Item&) = 0; - virtual Item read(std::istream&) const = 0; - - virtual InverterBase<_Item>* getInverter() { - return this; - } - }; - - template - class MapReaderInverter : public InverterBase<_Item> { - public: - typedef _Item Item; - typedef _Reader Reader; - typedef typename Reader::Value Value; - typedef _Map Map; - typedef std::map > Inverse; - - typename SmartReference::Type map; - Reader reader; - Inverse inverse; - - MapReaderInverter(typename SmartParameter::Type _map, - const Reader& _reader) - : map(_map), reader(_reader) {} - - virtual ~MapReaderInverter() {} - - virtual void read(std::istream& is, const Item& item) { - Value value; - reader.read(is, value); - map.set(item, value); - typename Inverse::iterator it = inverse.find(value); - if (it == inverse.end()) { - inverse.insert(std::make_pair(value, item)); - } else { - throw DataFormatError("Multiple ID occurence"); - } - } - - virtual Item read(std::istream& is) const { - Value value; - reader.read(is, value); - typename Inverse::const_iterator it = inverse.find(value); - if (it != inverse.end()) { - return it->second; - } else { - throw DataFormatError("Invalid ID error"); - } - } - }; - - template - class SkipReaderInverter : public InverterBase<_Item> { - public: - typedef _Item Item; - typedef _Reader Reader; - typedef typename Reader::Value Value; - typedef std::map > Inverse; - - Reader reader; - - SkipReaderInverter(const Reader& _reader) - : reader(_reader) {} - - virtual ~SkipReaderInverter() {} - - virtual void read(std::istream& is, const Item& item) { - Value value; - reader.read(is, value); - typename Inverse::iterator it = inverse.find(value); - if (it == inverse.end()) { - inverse.insert(std::make_pair(value, item)); - } else { - throw DataFormatError("Multiple ID occurence error"); - } - } - - virtual Item read(std::istream& is) const { - Value value; - reader.read(is, value); - typename Inverse::const_iterator it = inverse.find(value); - if (it != inverse.end()) { - return it->second; - } else { - throw DataFormatError("Invalid ID error"); - } - } - - private: - Inverse inverse; - }; - - template - class ReaderBase { - public: - typedef _Item Item; - - virtual ~ReaderBase() {} - - virtual void read(std::istream& is, const Item& item) = 0; - virtual InverterBase<_Item>* getInverter() = 0; - }; - - template - class MapReader : public ReaderBase<_Item> { - public: - typedef _Map Map; - typedef _Reader Reader; - typedef typename Reader::Value Value; - typedef _Item Item; - - typename SmartReference::Type map; - Reader reader; - - MapReader(typename SmartParameter::Type _map, - const Reader& _reader) - : map(_map), reader(_reader) {} - - virtual ~MapReader() {} - - virtual void read(std::istream& is, const Item& item) { - Value value; - reader.read(is, value); - map.set(item, value); - } - - virtual InverterBase<_Item>* getInverter() { - return new MapReaderInverter(map, reader); - } - }; - - - template - class SkipReader : public ReaderBase<_Item> { - public: - typedef _Reader Reader; - typedef typename Reader::Value Value; - typedef _Item Item; - - Reader reader; - SkipReader(const Reader& _reader) : reader(_reader) {} - - virtual ~SkipReader() {} - - virtual void read(std::istream& is, const Item&) { - Value value; - reader.read(is, value); - } - - virtual InverterBase* getInverter() { - return new SkipReaderInverter(reader); - } - }; - - template - class IdReaderBase { - public: - typedef _Item Item; - virtual Item read(std::istream& is) const = 0; - }; - - template - class IdReader : public IdReaderBase<_Item> { - public: - typedef _Item Item; - typedef _BoxedIdReader BoxedIdReader; - - const BoxedIdReader& boxedIdReader; - - IdReader(const BoxedIdReader& _boxedIdReader) - : boxedIdReader(_boxedIdReader) {} - - virtual Item read(std::istream& is) const { - return boxedIdReader.readId(is, Item()); - } - }; - - class ValueReaderBase { - public: - virtual void read(std::istream&) {}; - }; - - template - class ValueReader : public ValueReaderBase { - public: - typedef _Value Value; - typedef _Reader Reader; - - ValueReader(Value& _value, const Reader& _reader) - : value(_value), reader(_reader) {} - - virtual void read(std::istream& is) { - reader.read(is, value); - } - private: - Value& value; - Reader reader; - }; - - }; - - /// \ingroup io_group - /// \brief SectionReader for reading a graph's nodeset. - /// - /// The lemon format can store multiple graph nodesets with several maps. - /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the - /// \c nodeset_id may be empty. - /// - /// The first line of the section contains the names of the maps separated - /// with white spaces. Each next lines describes a node in the nodeset, and - /// contains the mapped values for each map. - /// - /// If the nodeset contains an \c "id" named map then it will be regarded - /// as id map. This map should contain only unique values and when the - /// \c readId() member will read a value from the given stream it will - /// give back that node which is mapped to this value. - /// - /// \relates LemonReader - template - class NodeSetReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - public: - - typedef _Graph Graph; - typedef _Traits Traits; - typedef typename Graph::Node Node; - typedef typename Traits::Skipper DefaultSkipper; - - /// \brief Constructor. - /// - /// Constructor for NodeSetReader. It creates the NodeSetReader and - /// attach it into the given LemonReader. The nodeset reader will - /// add the readed nodes to the given Graph. The reader will read - /// the section when the \c section_id and the \c _id are the same. - NodeSetReader(LemonReader& _reader, - typename SmartParameter::Type _graph, - const std::string& _id = std::string(), - const DefaultSkipper& _skipper = DefaultSkipper()) - : Parent(_reader), graph(_graph), id(_id), skipper(_skipper) {} - - - /// \brief Destructor. - /// - /// Destructor for NodeSetReader. - virtual ~NodeSetReader() { - for (typename MapReaders::iterator it = readers.begin(); - it != readers.end(); ++it) { - delete it->second; - } - } - - private: - NodeSetReader(const NodeSetReader&); - void operator=(const NodeSetReader&); - - public: - - /// \brief Add a new node map reader command for the reader. - /// - /// Add a new node map reader command for the reader. - template - NodeSetReader& readNodeMap(std::string name, Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - template - NodeSetReader& readNodeMap(std::string name, const Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - /// \brief Add a new node map reader command for the reader. - /// - /// Add a new node map reader command for the reader. - template - NodeSetReader& readNodeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - return _readMap::Type> - (name, map, reader); - } - - template - NodeSetReader& readNodeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - return _readMap::Type> - (name, map, reader); - } - - private: - - template - NodeSetReader& _readMap(std::string name, MapParameter map, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for node map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert( - make_pair(name, new MapReader(map, reader))); - return *this; - } - - public: - - /// \brief Add a new node map skipper command for the reader. - /// - /// Add a new node map skipper command for the reader. - template - NodeSetReader& skipNodeMap(std::string name, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for node map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, new SkipReader(reader))); - return *this; - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line starts with \c \@nodeset, - /// and the header line's id and the nodeset's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@nodeset" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::vector* > index; - std::string line; - - getline(is, line); - std::istringstream ls(line); - while (ls >> id) { - typename MapReaders::iterator it = readers.find(id); - if (it != readers.end()) { - index.push_back(it->second); - } else { - index.push_back(&skipper); - } - if (id == "id" && inverter.get() == 0) { - inverter.reset(index.back()->getInverter()); - index.back() = inverter.get(); - } - } - while (getline(is, line)) { - Node node = graph.addNode(); - std::istringstream ls(line); - for (int i = 0; i < (int)index.size(); ++i) { - index[i]->read(ls, node); - } - } - } - - public: - - /// \brief Returns true if the nodeset can give back the node by its id. - /// - /// Returns true if the nodeset can give back the node by its id. - /// It is possible only if an "id" named map was read. - bool isIdReader() const { - return inverter.get() != 0; - } - - /// \brief Gives back the node by its id. - /// - /// It reads an id from the stream and gives back which node belongs to - /// it. It is possible only if there was read an "id" named map. - Node readId(std::istream& is, Node = Node()) const { - return inverter->read(is); - } - - private: - - typedef std::map*> MapReaders; - MapReaders readers; - - typename SmartReference::Type graph; - std::string id; - SkipReader skipper; - - std::auto_ptr > inverter; - }; - - /// \ingroup io_group - /// \brief SectionReader for reading a graph's edgeset. - /// - /// The lemon format can store multiple graph edgesets with several maps. - /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the - /// \c edgeset_id may be empty. - /// - /// The first line of the section contains the names of the maps separated - /// with white spaces. Each next lines describes an edge in the edgeset. The - /// line contains the source and the target nodes' id and the mapped - /// values for each map. - /// - /// If the edgeset contains an \c "id" named map then it will be regarded - /// as id map. This map should contain only unique values and when the - /// \c readId() member will read a value from the given stream it will - /// give back that edge which is mapped to this value. - /// - /// The edgeset reader needs a node id reader to identify which nodes - /// have to be connected. If a NodeSetReader reads an "id" named map, - /// it will be able to resolve the nodes by ids. - /// - /// \relates LemonReader - template - class EdgeSetReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - public: - - typedef _Graph Graph; - typedef _Traits Traits; - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - typedef typename Traits::Skipper DefaultSkipper; - - /// \brief Constructor. - /// - /// Constructor for EdgeSetReader. It creates the EdgeSetReader and - /// attach it into the given LemonReader. The edgeset reader will - /// add the readed edges to the given Graph. It will use the given - /// node id reader to read the source and target nodes of the edges. - /// The reader will read the section only if the \c _id and the - /// \c edgset_id are the same. - template - EdgeSetReader(LemonReader& _reader, - typename SmartParameter::Type _graph, - const NodeIdReader& _nodeIdReader, - const std::string& _id = std::string(), - const DefaultSkipper& _skipper = DefaultSkipper()) - : Parent(_reader), graph(_graph), id(_id), skipper(_skipper), - nodeIdReader(new IdReader(_nodeIdReader)) {} - - /// \brief Destructor. - /// - /// Destructor for EdgeSetReader. - virtual ~EdgeSetReader() { - for (typename MapReaders::iterator it = readers.begin(); - it != readers.end(); ++it) { - delete it->second; - } - } - - private: - EdgeSetReader(const EdgeSetReader&); - void operator=(const EdgeSetReader&); - - public: - - /// \brief Add a new edge map reader command for the reader. - /// - /// Add a new edge map reader command for the reader. - template - EdgeSetReader& readEdgeMap(std::string name, Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - template - EdgeSetReader& readEdgeMap(std::string name, const Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - /// \brief Add a new edge map reader command for the reader. - /// - /// Add a new edge map reader command for the reader. - template - EdgeSetReader& readEdgeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - return _readMap::Type>(name, map, reader); - } - - template - EdgeSetReader& readEdgeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - return _readMap::Type>(name, map, reader); - } - - private: - - template - EdgeSetReader& _readMap(std::string name, MapParameter map, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for edge map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert( - make_pair(name, new MapReader(map, reader))); - return *this; - } - - public: - - /// \brief Add a new edge map skipper command for the reader. - /// - /// Add a new edge map skipper command for the reader. - template - EdgeSetReader& skipEdgeMap(std::string name, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for edge map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, new SkipReader(reader))); - return *this; - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line starts with \c \@edgeset, - /// and the header line's id and the edgeset's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@edgeset" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::vector* > index; - std::string line; - - getline(is, line); - std::istringstream ls(line); - while (ls >> id) { - typename MapReaders::iterator it = readers.find(id); - if (it != readers.end()) { - index.push_back(it->second); - } else { - index.push_back(&skipper); - } - if (id == "id" && inverter.get() == 0) { - inverter.reset(index.back()->getInverter()); - index.back() = inverter.get(); - } - } - while (getline(is, line)) { - std::istringstream ls(line); - Node from = nodeIdReader->read(ls); - Node to = nodeIdReader->read(ls); - Edge edge = graph.addEdge(from, to); - for (int i = 0; i < (int)index.size(); ++i) { - index[i]->read(ls, edge); - } - } - } - - public: - - /// \brief Returns true if the edgeset can give back the edge by its id. - /// - /// Returns true if the edgeset can give back the edge by its id. - /// It is possible only if an "id" named map was read. - bool isIdReader() const { - return inverter.get() != 0; - } - - /// \brief Gives back the edge by its id. - /// - /// It reads an id from the stream and gives back which edge belongs to - /// it. It is possible only if there was read an "id" named map. - Edge readId(std::istream& is, Edge = Edge()) const { - return inverter->read(is); - } - - private: - - typedef std::map*> MapReaders; - MapReaders readers; - - typename SmartReference::Type graph; - std::string id; - SkipReader skipper; - - std::auto_ptr > inverter; - std::auto_ptr > nodeIdReader; - }; - - /// \ingroup io_group - /// \brief SectionReader for reading a undirected graph's edgeset. - /// - /// The lemon format can store multiple undirected edgesets with several - /// maps. The undirected edgeset section's header line is \c \@undiredgeset - /// \c undiredgeset_id, but the \c undiredgeset_id may be empty. - /// - /// The first line of the section contains the names of the maps separated - /// with white spaces. Each next lines describes an edge in the edgeset. The - /// line contains the connected nodes' id and the mapped values for each map. - /// - /// The section can handle the directed as a syntactical sugar. Two - /// undirected edge map describes one directed edge map. This two maps - /// are the forward map and the backward map and the names of this map - /// is near the same just with a prefix \c '+' or \c '-' character - /// difference. - /// - /// If the edgeset contains an \c "id" named map then it will be regarded - /// as id map. This map should contain only unique values and when the - /// \c readId() member will read a value from the given stream it will - /// give back that undiricted edge which is mapped to this value. - /// - /// The undirected edgeset reader needs a node id reader to identify which - /// nodes have to be connected. If a NodeSetReader reads an "id" named map, - /// it will be able to resolve the nodes by ids. - /// - /// \relates LemonReader - template - class UndirEdgeSetReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - public: - - typedef _Graph Graph; - typedef _Traits Traits; - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - typedef typename Graph::UndirEdge UndirEdge; - typedef typename Traits::Skipper DefaultSkipper; - - /// \brief Constructor. - /// - /// Constructor for UndirEdgeSetReader. It creates the UndirEdgeSetReader - /// and attach it into the given LemonReader. The undirected edgeset - /// reader will add the readed undirected edges to the given Graph. It - /// will use the given node id reader to read the source and target - /// nodes of the edges. The reader will read the section only if the - /// \c _id and the \c undiredgset_id are the same. - template - UndirEdgeSetReader(LemonReader& _reader, - typename SmartParameter::Type _graph, - const NodeIdReader& _nodeIdReader, - const std::string& _id = std::string(), - const DefaultSkipper& _skipper = DefaultSkipper()) - : Parent(_reader), graph(_graph), id(_id), skipper(_skipper), - nodeIdReader(new IdReader(_nodeIdReader)) {} - - /// \brief Destructor. - /// - /// Destructor for UndirEdgeSetReader. - virtual ~UndirEdgeSetReader() { - for (typename MapReaders::iterator it = readers.begin(); - it != readers.end(); ++it) { - delete it->second; - } - } - - private: - UndirEdgeSetReader(const UndirEdgeSetReader&); - void operator=(const UndirEdgeSetReader&); - - public: - - /// \brief Add a new undirected edge map reader command for the reader. - /// - /// Add a new edge undirected map reader command for the reader. - template - UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - template - UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map) { - return _readMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - /// \brief Add a new undirected edge map reader command for the reader. - /// - /// Add a new edge undirected map reader command for the reader. - template - UndirEdgeSetReader& readUndirEdgeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - return _readMap::Type> - (name, map, reader); - } - - template - UndirEdgeSetReader& readUndirEdgeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - return _readMap::Type > - (name, map, reader); - } - - private: - - template - UndirEdgeSetReader& _readMap(std::string name, MapParameter map, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for edge map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert( - make_pair(name, new MapReader(map, reader))); - return *this; - } - - public: - - /// \brief Add a new undirected edge map skipper command for the reader. - /// - /// Add a new undirected edge map skipper command for the reader. - template - UndirEdgeSetReader& skipUndirEdgeMap(std::string name, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for node map: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, - new SkipReader(reader))); - return *this; - } - - /// \brief Add a new directed edge map reader command for the reader. - /// - /// Add a new directed edge map reader command for the reader. - template - UndirEdgeSetReader& readEdgeMap(std::string name, Map& map) { - return _readDirMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - template - UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map) { - return _readDirMap< - typename Traits::template Reader, Map, - typename SmartParameter::Type>(name, map); - } - - /// \brief Add a new directed edge map reader command for the reader. - /// - /// Add a new directed edge map reader command for the reader. - template - UndirEdgeSetReader& readEdgeMap(std::string name, Map& map, - const Reader& reader = Reader()) { - return _readDirMap::Type> - (name, map, reader); - } - - template - UndirEdgeSetReader& readEdgeMap(std::string name, const Map& map, - const Reader& reader = Reader()) { - return _readDirMap::Type> - (name, map, reader); - } - - private: - - template - UndirEdgeSetReader& _readDirMap(std::string name, MapParameter map, - const Reader& reader = Reader()) { - readMap("+" + name, - _reader_bits::writeComposeMap(map, forwardMap(graph)), reader); - readMap("-" + name, - _reader_bits::writeComposeMap(map, backwardMap(graph)), reader); - return *this; - } - - public: - - /// \brief Add a new directed edge map skipper command for the reader. - /// - /// Add a new directed edge map skipper command for the reader. - template - UndirEdgeSetReader& skipEdgeMap(std::string name, - const Reader& reader = Reader()) { - skipMap("+" + name, reader); - skipMap("-" + name, reader); - return *this; - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line starts with \c \@undiredgeset, - /// and the header line's id and the edgeset's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@undiredgeset" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::vector* > index; - std::string line; - - getline(is, line); - std::istringstream ls(line); - while (ls >> id) { - typename MapReaders::iterator it = readers.find(id); - if (it != readers.end()) { - index.push_back(it->second); - } else { - index.push_back(&skipper); - } - if (id == "id" && inverter.get() == 0) { - inverter.reset(index.back()->getInverter()); - index.back() = inverter.get(); - } - } - while (getline(is, line)) { - std::istringstream ls(line); - Node from = nodeIdReader->read(ls); - Node to = nodeIdReader->read(ls); - UndirEdge edge = graph.addEdge(from, to); - for (int i = 0; i < (int)index.size(); ++i) { - index[i]->read(ls, edge); - } - } - } - - public: - - /// \brief Returns true if the edgeset can give back the edge by its id. - /// - /// Returns true if the edgeset can give back the undirected edge by its - /// id. It is possible only if an "id" named map was read. - bool isIdReader() const { - return inverter.get() != 0; - } - - /// \brief Gives back the undirected edge by its id. - /// - /// It reads an id from the stream and gives back which undirected edge - /// belongs to it. It is possible only if there was read an "id" named map. - UndirEdge readId(std::istream& is, UndirEdge = UndirEdge()) const { - return inverter->read(is); - } - - /// \brief Gives back the directed edge by its id. - /// - /// It reads an id from the stream and gives back which directed edge - /// belongs to it. The directed edge id is the \c '+' or \c '-' character - /// and the undirected edge id. It is possible only if there was read - /// an "id" named map. - Edge readId(std::istream& is, Edge = Edge()) const { - char c; - is >> c; - UndirEdge undirEdge = inverter->read(is); - if (c == '+') { - return graph.edgeWithSource(undirEdge, graph.source(undirEdge)); - } else if (c == '-') { - return graph.edgeWithSource(undirEdge, graph.target(undirEdge)); - } else { - throw DataFormatError("Wrong id format for edge " - "in undirected edgeset"); - } - } - - private: - - typedef std::map*> MapReaders; - MapReaders readers; - - typename SmartReference::Type graph; - std::string id; - SkipReader skipper; - - std::auto_ptr > inverter; - std::auto_ptr > nodeIdReader; - }; - - /// \ingroup io_group - /// \brief SectionReader for reading labeled nodes. - /// - /// The nodes section's header line is \c \@nodes \c nodes_id, but the - /// \c nodes_id may be empty. - /// - /// Each line in the section contains the name of the node - /// and then the node id. - /// - /// \relates LemonReader - template - class NodeReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - typedef _Graph Graph; - typedef typename Graph::Node Node; - public: - - /// \brief Constructor. - /// - /// Constructor for NodeReader. It creates the NodeReader and - /// attach it into the given LemonReader. It will use the given - /// node id reader to give back the nodes. The reader will read the - /// section only if the \c _id and the \c nodes_id are the same. - template - NodeReader(LemonReader& _reader, const _IdReader& _idReader, - const std::string& _id = std::string()) - : Parent(_reader), id(_id), - idReader(new IdReader(_idReader)) {} - - /// \brief Destructor. - /// - /// Destructor for NodeReader. - virtual ~NodeReader() {} - - private: - NodeReader(const NodeReader&); - void operator=(const NodeReader&); - - public: - - /// \brief Add a node reader command for the NodeReader. - /// - /// Add a node reader command for the NodeReader. - void readNode(const std::string& name, Node& item) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for node: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, &item)); - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line start with \c \@nodes, - /// and the header line's id and the reader's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@nodes" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::string line; - while (getline(is, line)) { - std::istringstream ls(line); - std::string id; - ls >> id; - typename NodeReaders::iterator it = readers.find(id); - if (it != readers.end()) { - *(it->second) = idReader->read(ls); - } - } - } - - private: - - std::string id; - - typedef std::map NodeReaders; - NodeReaders readers; - std::auto_ptr > idReader; - }; - - /// \ingroup io_group - /// \brief SectionReader for reading labeled edges. - /// - /// The edges section's header line is \c \@edges \c edges_id, but the - /// \c edges_id may be empty. - /// - /// Each line in the section contains the name of the edge - /// and then the edge id. - /// - /// \relates LemonReader - template - class EdgeReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - typedef _Graph Graph; - typedef typename Graph::Edge Edge; - public: - - /// \brief Constructor. - /// - /// Constructor for EdgeReader. It creates the EdgeReader and - /// attach it into the given LemonReader. It will use the given - /// edge id reader to give back the edges. The reader will read the - /// section only if the \c _id and the \c edges_id are the same. - template - EdgeReader(LemonReader& _reader, const _IdReader& _idReader, - const std::string& _id = std::string()) - : Parent(_reader), id(_id), - idReader(new IdReader(_idReader)) {} - - /// \brief Destructor. - /// - /// Destructor for EdgeReader. - virtual ~EdgeReader() {} - private: - EdgeReader(const EdgeReader&); - void operator=(const EdgeReader&); - - public: - - /// \brief Add an edge reader command for the EdgeReader. - /// - /// Add an edge reader command for the EdgeReader. - void readEdge(const std::string& name, Edge& item) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for edge: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, &item)); - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line start with \c \@edges, - /// and the header line's id and the reader's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@edges" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::string line; - while (getline(is, line)) { - std::istringstream ls(line); - std::string id; - ls >> id; - typename EdgeReaders::iterator it = readers.find(id); - if (it != readers.end()) { - *(it->second) = idReader->read(ls); - } - } - } - - private: - - std::string id; - - typedef std::map EdgeReaders; - EdgeReaders readers; - std::auto_ptr > idReader; - }; - - /// \ingroup io_group - /// \brief SectionReader for reading labeled undirected edges. - /// - /// The undirected edges section's header line is \c \@undiredges - /// \c undiredges_id, but the \c undiredges_id may be empty. - /// - /// Each line in the section contains the name of the undirected edge - /// and then the undirected edge id. - /// - /// \relates LemonReader - template - class UndirEdgeReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - typedef _Graph Graph; - typedef typename Graph::Edge Edge; - typedef typename Graph::UndirEdge UndirEdge; - public: - - /// \brief Constructor. - /// - /// Constructor for UndirEdgeReader. It creates the UndirEdgeReader and - /// attach it into the given LemonReader. It will use the given - /// undirected edge id reader to give back the edges. The reader will - /// read the section only if the \c _id and the \c undiredges_id are - /// the same. - template - UndirEdgeReader(LemonReader& _reader, const _IdReader& _idReader, - const std::string& _id = std::string()) - : Parent(_reader), id(_id), - undirEdgeIdReader(new IdReader(_idReader)), - edgeIdReader(new IdReader(_idReader)) - {} - - /// \brief Destructor. - /// - /// Destructor for UndirEdgeReader. - virtual ~UndirEdgeReader() {} - private: - UndirEdgeReader(const UndirEdgeReader&); - void operator=(const UndirEdgeReader&); - - public: - - /// \brief Add an undirected edge reader command for the UndirEdgeReader. - /// - /// Add an undirected edge reader command for the UndirEdgeReader. - void readUndirEdge(const std::string& name, UndirEdge& item) { - if (undirEdgeReaders.find(name) != undirEdgeReaders.end()) { - ErrorMessage msg; - msg << "Multiple read rule for undirected edge: " << name; - throw IOParameterError(msg.message()); - } - undirEdgeReaders.insert(make_pair(name, &item)); - } - - /// \brief Add an edge reader command for the UndirEdgeReader. - /// - /// Add an edge reader command for the UndirEdgeReader. - void readEdge(const std::string& name, Edge& item) { - if (edgeReaders.find(name) != edgeReaders.end()) { - ErrorMessage msg; - msg << "Multiple read rule for edge: " << name; - throw IOParameterError(msg.message()); - } - edgeReaders.insert(make_pair(name, &item)); - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line start with \c \@edges, - /// and the header line's id and the reader's id are the same. - virtual bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@undiredges" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - virtual void read(std::istream& is) { - std::string line; - while (getline(is, line)) { - std::istringstream ls(line); - std::string id; - ls >> id; - { - typename UndirEdgeReaders::iterator it = undirEdgeReaders.find(id); - if (it != undirEdgeReaders.end()) { - *(it->second) = undirEdgeIdReader->read(ls); - break; - } - } { - typename EdgeReaders::iterator it = edgeReaders.find(id); - if (it != edgeReaders.end()) { - *(it->second) = edgeIdReader->read(ls); - break; - } - } - } - } - - private: - - std::string id; - - typedef std::map UndirEdgeReaders; - UndirEdgeReaders undirEdgeReaders; - std::auto_ptr > undirEdgeIdReader; - - typedef std::map EdgeReaders; - EdgeReaders edgeReaders; - std::auto_ptr > edgeIdReader; - }; - - /// \ingroup io_group - /// \brief SectionReader for attributes. - /// - /// The lemon format can store multiple attribute set. Each set has - /// the header line \c \@attributes \c attributeset_id, but the - /// attributeset_id may be empty. - /// - /// The attributeset section contains several lines. Each of them starts - /// with an attribute and then a the value for the id. - /// - /// \relates LemonReader - template - class AttributeReader : public CommonSectionReaderBase { - typedef CommonSectionReaderBase Parent; - typedef _Traits Traits; - public: - /// \brief Constructor. - /// - /// Constructor for AttributeReader. It creates the AttributeReader and - /// attach it into the given LemonReader. The reader process a section - /// only if the \c section_id and the \c _id are the same. - AttributeReader(LemonReader& _reader, - const std::string& _id = std::string()) - : Parent(_reader), id(_id) {} - - /// \brief Destructor. - /// - /// Destructor for AttributeReader. - virtual ~AttributeReader() { - for (typename Readers::iterator it = readers.begin(); - it != readers.end(); ++it) { - delete it->second; - } - } - - private: - AttributeReader(const AttributeReader&); - void operator=(AttributeReader&); - - public: - /// \brief Add an attribute reader command for the reader. - /// - /// Add an attribute reader command for the reader. - template - AttributeReader& readAttribute(const std::string& id, Value& value) { - return readAttribute > - (id, value); - } - - /// \brief Add an attribute reader command for the reader. - /// - /// Add an attribute reader command for the reader. - template - AttributeReader& readAttribute(const std::string& name, Value& value, - const Reader& reader = Reader()) { - if (readers.find(name) != readers.end()) { - ErrorMessage msg; - msg << "Multiple read rule for attribute: " << name; - throw IOParameterError(msg.message()); - } - readers.insert(make_pair(name, new ValueReader - (value, reader))); - return *this; - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the header line start with \c \@attributes, - /// and the header line's id and the attributeset's id are the same. - bool header(const std::string& line) { - std::istringstream ls(line); - std::string command; - std::string name; - ls >> command >> name; - return command == "@attributes" && name == id; - } - - /// \brief Reader function of the section. - /// - /// It reads the content of the section. - void read(std::istream& is) { - std::string line; - while (getline(is, line)) { - std::istringstream ls(line); - std::string id; - ls >> id; - typename Readers::iterator it = readers.find(id); - if (it != readers.end()) { - it->second->read(ls); - } - } - } - - private: - std::string id; - - typedef std::map Readers; - Readers readers; - }; - - /// \ingroup io_group - /// \brief SectionReader for retrieve what is in the file. - /// - /// SectionReader for retrieve what is in the file. If you want - /// to know which sections, maps and items are in the file - /// use the next code: - /// \code - /// LemonReader reader("input.lgf"); - /// ContentReader content(reader); - /// reader.run(); - /// \endcode - class ContentReader : public LemonReader::SectionReader { - typedef LemonReader::SectionReader Parent; - public: - /// \brief Constructor. - /// - /// Constructor for - ContentReader(LemonReader& _reader) : Parent(_reader) {} - - /// \brief Desctructor. - /// - /// Desctructor. - virtual ~ContentReader() {} - - /// \brief Gives back how many nodesets are in the file. - /// - /// Gives back how many nodesets are in the file. - int nodeSetNum() const { - return nodesets.size(); - } - - /// \brief Gives back the name of nodeset on the indiced position. - /// - /// Gives back the name of nodeset on the indiced position. - std::string nodeSetName(int index) const { - return nodesets[index].name; - } - - /// \brief Gives back the map names of nodeset on the indiced position. - /// - /// Gives back the map names of nodeset on the indiced position. - const std::vector& nodeSetMaps(int index) const { - return nodesets[index].items; - } - - /// \brief Gives back how many edgesets are in the file. - /// - /// Gives back how many edgesets are in the file. - int edgeSetNum() const { - return edgesets.size(); - } - - /// \brief Gives back the name of edgeset on the indiced position. - /// - /// Gives back the name of edgeset on the indiced position. - std::string edgeSetName(int index) const { - return edgesets[index].name; - } - - /// \brief Gives back the map names of edgeset on the indiced position. - /// - /// Gives back the map names of edgeset on the indiced position. - const std::vector& edgeSetMaps(int index) const { - return edgesets[index].items; - } - - /// \brief Gives back how many undirected edgesets are in the file. - /// - /// Gives back how many undirected edgesets are in the file. - int undirEdgeSetNum() const { - return undiredgesets.size(); - } - - /// \brief Gives back the name of undirected edgeset on the indiced - /// position. - /// - /// Gives back the name of undirected edgeset on the indiced position. - std::string undirEdgeSetName(int index) const { - return undiredgesets[index].name; - } - - /// \brief Gives back the map names of undirected edgeset on the indiced - /// position. - /// - /// Gives back the map names of undirected edgeset on the indiced position. - const std::vector& undirEdgeSetMaps(int index) const { - return undiredgesets[index].items; - } - - /// \brief Gives back how many labeled nodes section are in the file. - /// - /// Gives back how many labeled nodes section are in the file. - int nodesNum() const { - return nodes.size(); - } - - /// \brief Gives back the name of labeled nodes section on the indiced - /// position. - /// - /// Gives back the name of labeled nodes section on the indiced position. - std::string nodesName(int index) const { - return nodes[index].name; - } - - /// \brief Gives back the names of the labeled nodes in the indiced - /// section. - /// - /// Gives back the names of the labeled nodes in the indiced section. - const std::vector& nodesItems(int index) const { - return nodes[index].items; - } - - /// \brief Gives back how many labeled edges section are in the file. - /// - /// Gives back how many labeled edges section are in the file. - int edgesNum() const { - return edges.size(); - } - - /// \brief Gives back the name of labeled edges section on the indiced - /// position. - /// - /// Gives back the name of labeled edges section on the indiced position. - std::string edgesName(int index) const { - return edges[index].name; - } - - /// \brief Gives back the names of the labeled edges in the indiced - /// section. - /// - /// Gives back the names of the labeled edges in the indiced section. - const std::vector& edgesItems(int index) const { - return edges[index].items; - } - - /// \brief Gives back how many labeled undirected edges section are - /// in the file. - /// - /// Gives back how many labeled undirected edges section are in the file. - int undirEdgesNum() const { - return undiredges.size(); - } - - /// \brief Gives back the name of labeled undirected edges section - /// on the indiced position. - /// - /// Gives back the name of labeled undirected edges section on the - /// indiced position. - std::string undirEdgesName(int index) const { - return undiredges[index].name; - } - - /// \brief Gives back the names of the labeled undirected edges in - /// the indiced section. - /// - /// Gives back the names of the labeled undirected edges in the - /// indiced section. - const std::vector& undirEdgesItems(int index) const { - return undiredges[index].items; - } - - - /// \brief Gives back how many attributes section are in the file. - /// - /// Gives back how many attributes section are in the file. - int attributesNum() const { - return attributes.size(); - } - - /// \brief Gives back the name of attributes section on the indiced - /// position. - /// - /// Gives back the name of attributes section on the indiced position. - std::string attributesName(int index) const { - return attributes[index].name; - } - - /// \brief Gives back the names of the attributes in the indiced section. - /// - /// Gives back the names of the attributes in the indiced section. - const std::vector& attributesItems(int index) const { - return attributes[index].items; - } - - const std::vector& otherSections() const { - return sections; - } - - protected: - - /// \brief Gives back true when the SectionReader can process - /// the section with the given header line. - /// - /// It gives back true when the section is common section. - bool header(const std::string& line) { - std::istringstream ls(line); - std::string command, name; - ls >> command >> name; - if (command == "@nodeset") { - current = command; - nodesets.push_back(SectionInfo(name)); - } else if (command == "@edgeset") { - current = command; - edgesets.push_back(SectionInfo(name)); - } else if (command == "@undiredgeset") { - current = command; - undiredgesets.push_back(SectionInfo(name)); - } else if (command == "@nodes") { - current = command; - nodes.push_back(SectionInfo(name)); - } else if (command == "@edges") { - current = command; - edges.push_back(SectionInfo(name)); - } else if (command == "@undiredges") { - current = command; - undiredges.push_back(SectionInfo(name)); - } else if (command == "@attributes") { - current = command; - attributes.push_back(SectionInfo(name)); - } else { - sections.push_back(line); - return false; - } - return true; - } - - /// \brief Retrieve the items from various sections. - /// - /// Retrieve the items from various sections. - void read(std::istream& is) { - if (current == "@nodeset") { - readMapNames(is, nodesets.back().items); - } else if (current == "@edgeset") { - readMapNames(is, edgesets.back().items); - } else if (current == "@undiredgeset") { - readMapNames(is, undiredgesets.back().items); - } else if (current == "@nodes") { - readItemNames(is, nodes.back().items); - } else if (current == "@edges") { - readItemNames(is, edges.back().items); - } else if (current == "@undiredges") { - readItemNames(is, undiredges.back().items); - } else if (current == "@attributes") { - readItemNames(is, attributes.back().items); - } - } - - private: - - void readMapNames(std::istream& is, std::vector& maps) { - std::string line, id; - std::getline(is, line); - std::istringstream ls(line); - while (ls >> id) { - maps.push_back(id); - } - while (getline(is, line)); - } - - void readItemNames(std::istream& is, std::vector& maps) { - std::string line, id; - while (std::getline(is, line)) { - std::istringstream ls(line); - ls >> id; - maps.push_back(id); - } - } - - struct SectionInfo { - std::string name; - std::vector items; - - SectionInfo(const std::string& _name) : name(_name) {} - }; - - std::vector nodesets; - std::vector edgesets; - std::vector undiredgesets; - - std::vector nodes; - std::vector edges; - std::vector undiredges; - - std::vector attributes; - - std::vector sections; - - std::string current; - - }; - -} -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lemon_writer.h --- a/src/lemon/lemon_writer.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1129 +0,0 @@ -/* -*- C++ -*- - * src/lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -///\ingroup io_group -///\file -///\brief Lemon Format writer. - -#ifndef LEMON_LEMON_WRITER_H -#define LEMON_LEMON_WRITER_H - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -namespace lemon { - - /// \ingroup io_group - /// \brief Lemon Format writer class. - /// - /// The Lemon Format contains several sections. We do not want to - /// determine what sections are in a lemon file we give only a framework - /// to write a section oriented format. - /// - /// In the Lemon Format each section starts with a line contains a \c \@ - /// character on the first not white space position. This line is the - /// header line of the section. Each next lines belong to this section - /// while it does not starts with \c \@ character. This line can start a - /// new section or if it can close the file with the \c \@end line. - /// The file format ignore the empty lines and it may contain comments - /// started with a \c # character to the end of the line. - /// - /// The framework provides an abstract LemonWriter::SectionWriter class - /// what defines the interface of a SectionWriter. The SectionWriter - /// has the \c header() member function what gives back the header of the - /// section. After that it will be called the \c write() member which - /// should write the content of the section. - /// - /// \relates GraphWriter - /// \relates NodeSetWriter - /// \relates EdgeSetWriter - /// \relates NodesWriter - /// \relates EdgesWriter - /// \relates AttributeWriter - class LemonWriter { - public: - - /// \brief Abstract base class for writing a section. - /// - /// This class has an \c header() member function what gives back - /// the header line of the section. The \c write() member should - /// write the content of the section to the stream. - class SectionWriter { - friend class LemonWriter; - protected: - /// \brief Constructor for SectionWriter. - /// - /// Constructor for SectionWriter. It attach this writer to - /// the given LemonWriter. - SectionWriter(LemonWriter& writer) { - writer.attach(*this); - } - - /// \brief The header of section. - /// - /// It gives back the header of the section. - virtual std::string header() = 0; - - /// \brief Writer function of the section. - /// - /// Write the content of the section. - virtual void write(std::ostream& os) = 0; - }; - - /// \brief Constructor for LemonWriter. - /// - /// Constructor for LemonWriter which writes to the given stream. - LemonWriter(std::ostream& _os) - : os(&_os), own_os(false) {} - - /// \brief Constructor for LemonWriter. - /// - /// Constructor for LemonWriter which writes to the given file. - LemonWriter(const std::string& filename) - : os(0), own_os(true) { - os = new std::ofstream(filename.c_str()); - } - - /// \brief Desctructor for LemonWriter. - /// - /// Desctructor for LemonWriter. - ~LemonWriter() { - if (own_os) { - delete os; - } - } - - private: - LemonWriter(const LemonWriter&); - void operator=(const LemonWriter&); - - void attach(SectionWriter& writer) { - writers.push_back(&writer); - } - - public: - - /// \brief Executes the LemonWriter. - /// - /// It executes the LemonWriter. - void run() { - SectionWriters::iterator it; - for (it = writers.begin(); it != writers.end(); ++it) { - *os << (*it)->header() << std::endl; - (*it)->write(*os); - } - *os << "@end" << std::endl; - } - - - private: - - std::ostream* os; - bool own_os; - - typedef std::vector SectionWriters; - SectionWriters writers; - - }; - - /// \brief Helper class for implementing the common SectionWriters. - /// - /// Helper class for implementing the common SectionWriters. - class CommonSectionWriterBase : public LemonWriter::SectionWriter { - typedef LemonWriter::SectionWriter Parent; - protected: - - /// \brief Constructor for CommonSectionWriterBase. - /// - /// Constructor for CommonSectionWriterBase. It attach this writer to - /// the given LemonWriter. - CommonSectionWriterBase(LemonWriter& _writer) - : Parent(_writer) {} - - template - class WriterBase { - public: - typedef _Item Item; - - virtual ~WriterBase() {} - - virtual void write(std::ostream& os, const Item& item) = 0; - }; - - - template - class MapWriter : public WriterBase<_Item> { - public: - typedef _Map Map; - typedef _Writer Writer; - typedef typename Writer::Value Value; - typedef _Item Item; - - typename SmartConstReference::Type map; - Writer writer; - - MapWriter(const Map& _map, const Writer& _writer) - : map(_map), writer(_writer) {} - - virtual ~MapWriter() {} - - virtual void write(std::ostream& os, const Item& item) { - Value value = map[item]; - writer.write(os, value); - } - - }; - - - class ValueWriterBase { - public: - virtual void write(std::ostream&) = 0; - }; - - template - class ValueWriter : public ValueWriterBase { - public: - typedef _Value Value; - typedef _Writer Writer; - - ValueWriter(const Value& _value, const Writer& _writer) - : value(_value), writer(_writer) {} - - virtual void write(std::ostream& os) { - writer.write(os, value); - } - private: - const Value& value; - Writer writer; - }; - - - template - class IdWriterBase { - public: - typedef _Item Item; - virtual void write(std::ostream&, const Item&) const = 0; - }; - - template - class IdWriter : public IdWriterBase<_Item> { - public: - typedef _Item Item; - typedef _BoxedIdWriter BoxedIdWriter; - - const BoxedIdWriter& idWriter; - - IdWriter(const BoxedIdWriter& _idWriter) - : idWriter(_idWriter) {} - - virtual void write(std::ostream& os, const Item& item) const { - idWriter.writeId(os, item); - } - }; - }; - - /// \ingroup io_group - /// \brief SectionWriter for writing a graph's nodeset. - /// - /// The lemon format can store multiple graph nodesets with several maps. - /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the - /// \c nodeset_id may be empty. - /// - /// The first line of the section contains the names of the maps separated - /// with white spaces. Each next lines describes a node in the nodeset, and - /// contains the mapped values for each map. - /// - /// If the nodeset contains an \c "id" named map then it will be regarded - /// as id map. This map should contain only unique values and when the - /// \c writeId() member will be called with a node it will write it's id. - /// Otherwise if the \c _forceIdMap constructor parameter is true then - /// the id map will be the id in the graph. - /// - /// \relates LemonWriter - template - class NodeSetWriter : public CommonSectionWriterBase { - typedef CommonSectionWriterBase Parent; - public: - - typedef _Graph Graph; - typedef _Traits Traits; - typedef typename Graph::Node Node; - - /// \brief Constructor. - /// - /// Constructor for NodeSetWriter. It creates the NodeSetWriter and - /// attach it into the given LemonWriter. If the \c _forceIdMap - /// parameter is true then the writer will write own id map when - /// the user does not give "id" named map. - NodeSetWriter(LemonWriter& _writer, const Graph& _graph, - const std::string& _id = std::string(), - bool _forceIdMap = true) - : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), - graph(_graph), id(_id) {} - - /// \brief Destructor. - /// - /// Destructor for NodeSetWriter. - virtual ~NodeSetWriter() { - typename MapWriters::iterator it; - for (it = writers.begin(); it != writers.end(); ++it) { - delete it->second; - } - } - - private: - NodeSetWriter(const NodeSetWriter&); - void operator=(const NodeSetWriter&); - - public: - - /// \brief Add a new node map writer command for the writer. - /// - /// Add a new node map writer command for the writer. - template - NodeSetWriter& writeNodeMap(std::string name, const Map& map) { - return writeNodeMap, Map>(name, map); - } - - /// \brief Add a new node map writer command for the writer. - /// - /// Add a new node map writer command for the writer. - template - NodeSetWriter& writeNodeMap(std::string name, const Map& map, - const Writer& writer = Writer()) { - writers.push_back( - make_pair(name, new MapWriter(map, writer))); - return *this; - } - - protected: - - /// \brief The header of the section. - /// - /// It gives back the header of the section. - virtual std::string header() { - return "@nodeset " + id; - } - - /// \brief Writer function of the section. - /// - /// Write the content of the section. - virtual void write(std::ostream& os) { - for (int i = 0; i < (int)writers.size(); ++i) { - if (writers[i].first == "id") { - idMap = writers[i].second; - forceIdMap = false; - break; - } - } - if (forceIdMap) { - os << "id\t"; - } - for (int i = 0; i < (int)writers.size(); ++i) { - os << writers[i].first << '\t'; - } - os << std::endl; - for (typename Graph::NodeIt it(graph); it != INVALID; ++it) { - if (forceIdMap) { - os << graph.id(it) << '\t'; - } - for (int i = 0; i < (int)writers.size(); ++i) { - writers[i].second->write(os, it); - os << '\t'; - } - os << std::endl; - } - } - - public: - - /// \brief Returns true if the nodeset can write the ids of the nodes. - /// - /// Returns true if the nodeset can write the ids of the nodes. - /// It is possible only if an "id" named map was written or the - /// \c _forceIdMap constructor parameter was true. - bool isIdWriter() const { - return idMap != 0 || forceIdMap; - } - - /// \brief Write the id of the given node. - /// - /// It writes the id of the given node. If there was written an "id" - /// named map then it will write the map value belongs to the node. - /// Otherwise if the \c forceId parameter was true it will write - /// its id in the graph. - void writeId(std::ostream& os, const Node& item) const { - if (forceIdMap) { - os << graph.id(item); - } else { - idMap->write(os, item); - } - } - - private: - - typedef std::vector*> > MapWriters; - MapWriters writers; - - WriterBase* idMap; - bool forceIdMap; - - typename SmartConstReference::Type graph; - std::string id; - - }; - - /// \ingroup io_group - /// \brief SectionWriter for writing a graph's edgesets. - /// - /// The lemon format can store multiple graph edgesets with several maps. - /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the - /// \c edgeset_id may be empty. - /// - /// The first line of the section contains the names of the maps separated - /// with white spaces. Each next lines describes a edge in the edgeset. The - /// line contains the source and the target nodes' id and the mapped - /// values for each map. - /// - /// If the edgeset contains an \c "id" named map then it will be regarded - /// as id map. This map should contain only unique values and when the - /// \c writeId() member will be called with an edge it will write it's id. - /// Otherwise if the \c _forceIdMap constructor parameter is true then - /// the id map will be the id in the graph. - /// - /// The edgeset writer needs a node id writer to identify which nodes - /// have to be connected. If a NodeSetWriter can write the nodes' id, - /// it will be able to use with this class. - /// - /// \relates LemonWriter - template - class EdgeSetWriter : public CommonSectionWriterBase { - typedef CommonSectionWriterBase Parent; - public: - - typedef _Graph Graph; - typedef _Traits Traits; - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - - /// \brief Constructor. - /// - /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and - /// attach it into the given LemonWriter. It will write node ids by - /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true - /// then the writer will write own id map if the user does not give - /// "id" named map. - template - EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, - const NodeIdWriter& _nodeIdWriter, - const std::string& _id = std::string(), - bool _forceIdMap = true) - : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), - graph(_graph), id(_id), - nodeIdWriter(new IdWriter(_nodeIdWriter)) {} - - /// \brief Destructor. - /// - /// Destructor for EdgeSetWriter. - virtual ~EdgeSetWriter() { - typename MapWriters::iterator it; - for (it = writers.begin(); it != writers.end(); ++it) { - delete it->second; - } - } - - private: - EdgeSetWriter(const EdgeSetWriter&); - void operator=(const EdgeSetWriter&); - - public: - - /// \brief Add a new edge map writer command for the writer. - /// - /// Add a new edge map writer command for the writer. - template - EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) { - return writeEdgeMap, Map>(name, map); - } - - /// \brief Add a new edge map writer command for the writer. - /// - /// Add a new edge map writer command for the writer. - template - EdgeSetWriter& writeEdgeMap(std::string name, const Map& map, - const Writer& writer = Writer()) { - writers.push_back( - make_pair(name, new MapWriter(map, writer))); - return *this; - } - - protected: - - /// \brief The header of the section. - /// - /// It gives back the header of the section. - virtual std::string header() { - return "@edgeset " + id; - } - - /// \brief Writer function of the section. - /// - /// Write the content of the section. - virtual void write(std::ostream& os) { - for (int i = 0; i < (int)writers.size(); ++i) { - if (writers[i].first == "id") { - idMap = writers[i].second; - forceIdMap = false; - break; - } - } - os << "\t\t"; - if (forceIdMap) { - os << "id\t"; - } - for (int i = 0; i < (int)writers.size(); ++i) { - os << writers[i].first << '\t'; - } - os << std::endl; - for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) { - nodeIdWriter->write(os, graph.source(it)); - os << '\t'; - nodeIdWriter->write(os, graph.target(it)); - os << '\t'; - if (forceIdMap) { - os << graph.id(it) << '\t'; - } - for (int i = 0; i < (int)writers.size(); ++i) { - writers[i].second->write(os, it); - os << '\t'; - } - os << std::endl; - } - } - - public: - - /// \brief Returns true if the edgeset can write the ids of the edges. - /// - /// Returns true if the edgeset can write the ids of the edges. - /// It is possible only if an "id" named map was written or the - /// \c _forceIdMap constructor parameter was true. - bool isIdWriter() const { - return forceIdMap || idMap != 0; - } - - /// \brief Write the id of the given edge. - /// - /// It writes the id of the given edge. If there was written an "id" - /// named map then it will write the map value belongs to the edge. - /// Otherwise if the \c forceId parameter was true it will write - /// its id in the graph. - void writeId(std::ostream& os, const Edge& item) const { - if (forceIdMap) { - os << graph.id(item); - } else { - idMap->write(os, item); - } - } - - private: - - typedef std::vector*> > MapWriters; - MapWriters writers; - - WriterBase* idMap; - bool forceIdMap; - - typename SmartConstReference::Type graph; - std::string id; - - std::auto_ptr > nodeIdWriter; - }; - - /// \ingroup io_group - /// \brief SectionWriter for writing a undirected edgeset. - /// - /// The lemon format can store multiple undirected edgesets with several - /// maps. The undirected edgeset section's header line is \c \@undiredgeset - /// \c undiredgeset_id, but the \c undiredgeset_id may be empty. - /// - /// The first line of the section contains the names of the maps separated - /// with white spaces. Each next lines describes an undirected edge in the - /// edgeset. The line contains the two connected nodes' id and the mapped - /// values for each undirected map. - /// - /// The section can handle the directed as a syntactical sugar. Two - /// undirected edge map describes one directed edge map. This two maps - /// are the forward map and the backward map and the names of this map - /// is near the same just with a prefix \c '+' or \c '-' character - /// difference. - /// - /// If the edgeset contains an \c "id" named map then it will be regarded - /// as id map. This map should contain only unique values and when the - /// \c writeId() member will be called with an undirected edge it will - /// write it's id. Otherwise if the \c _forceIdMap constructor parameter - /// is true then the id map will be the id in the graph. - /// - /// The undirected edgeset writer needs a node id writer to identify - /// which nodes have to be connected. If a NodeSetWriter can write the - /// nodes' id, it will be able to use with this class. - /// - /// \relates LemonWriter - template - class UndirEdgeSetWriter : public CommonSectionWriterBase { - typedef CommonSectionWriterBase Parent; - public: - - typedef _Graph Graph; - typedef _Traits Traits; - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - typedef typename Graph::UndirEdge UndirEdge; - - /// \brief Constructor. - /// - /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter - /// and attach it into the given LemonWriter. It will write node ids by - /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true - /// then the writer will write own id map if the user does not give - /// "id" named map. - template - UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, - const NodeIdWriter& _nodeIdWriter, - const std::string& _id = std::string(), - bool _forceIdMap = true) - : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), - graph(_graph), id(_id), - nodeIdWriter(new IdWriter(_nodeIdWriter)) {} - - /// \brief Destructor. - /// - /// Destructor for UndirEdgeSetWriter. - virtual ~UndirEdgeSetWriter() { - typename MapWriters::iterator it; - for (it = writers.begin(); it != writers.end(); ++it) { - delete it->second; - } - } - - private: - UndirEdgeSetWriter(const UndirEdgeSetWriter&); - void operator=(const UndirEdgeSetWriter&); - - public: - - /// \brief Add a new undirected edge map writer command for the writer. - /// - /// Add a new undirected map writer command for the writer. - template - UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) { - return writeUndirEdgeMap, Map>(name, map); - } - - /// \brief Add a new undirected map writer command for the writer. - /// - /// Add a new undirected map writer command for the writer. - template - UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map, - const Writer& writer = Writer()) { - writers.push_back( - make_pair(name, new MapWriter(map, writer))); - return *this; - } - - /// \brief Add a new directed edge map writer command for the writer. - /// - /// Add a new directed map writer command for the writer. - template - UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) { - writeUndirEdgeMap("+" + name, composeMap(forwardMap(graph), map)); - writeUndirEdgeMap("-" + name, composeMap(backwardMap(graph), map)); - return *this; - } - - /// \brief Add a new directed map writer command for the writer. - /// - /// Add a new directed map writer command for the writer. - template - UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map, - const Writer& writer = Writer()) { - writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer); - writeUndirEdge("-" + name, composeMap(forwardMap(graph), map), writer); - return *this; - } - - protected: - - /// \brief The header of the section. - /// - /// It gives back the header of the section. - virtual std::string header() { - return "@undiredgeset " + id; - } - - /// \brief Writer function of the section. - /// - /// Write the content of the section. - virtual void write(std::ostream& os) { - for (int i = 0; i < (int)writers.size(); ++i) { - if (writers[i].first == "id") { - idMap = writers[i].second; - forceIdMap = false; - break; - } - } - os << "\t\t"; - if (forceIdMap) { - os << "id\t"; - } - for (int i = 0; i < (int)writers.size(); ++i) { - os << writers[i].first << '\t'; - } - os << std::endl; - for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) { - nodeIdWriter->write(os, graph.source(it)); - os << '\t'; - nodeIdWriter->write(os, graph.target(it)); - os << '\t'; - if (forceIdMap) { - os << graph.id(it) << '\t'; - } - for (int i = 0; i < (int)writers.size(); ++i) { - writers[i].second->write(os, it); - os << '\t'; - } - os << std::endl; - } - } - - public: - - /// \brief Returns true if the undirected edgeset can write the ids of - /// the edges. - /// - /// Returns true if the undirected edgeset can write the ids of the - /// undirected edges. It is possible only if an "id" named map was - /// written or the \c _forceIdMap constructor parameter was true. - bool isIdWriter() const { - return forceIdMap || idMap != 0; - } - - /// \brief Write the id of the given undirected edge. - /// - /// It writes the id of the given undirected edge. If there was written - /// an "id" named map then it will write the map value belongs to the - /// undirected edge. Otherwise if the \c forceId parameter was true it - /// will write its id in the graph. - void writeId(std::ostream& os, const UndirEdge& item) const { - if (forceIdMap) { - os << graph.id(item); - } else { - idMap->write(os, item); - } - } - - /// \brief Write the id of the given edge. - /// - /// It writes the id of the given edge. If there was written - /// an "id" named map then it will write the map value belongs to the - /// edge. Otherwise if the \c forceId parameter was true it - /// will write its id in the graph. If the edge is forward map - /// then its prefix character is \c '+' elsewhere \c '-'. - void writeId(std::ostream& os, const Edge& item) const { - if (graph.forward(item)) { - os << "+ "; - } else { - os << "- "; - } - if (forceIdMap) { - os << graph.id(item); - } else { - idMap->write(os, item); - } - } - - private: - - typedef std::vector*> > MapWriters; - MapWriters writers; - - WriterBase* idMap; - bool forceIdMap; - - typename SmartConstReference::Type graph; - std::string id; - - std::auto_ptr > nodeIdWriter; - }; - - /// \ingroup io_group - /// \brief SectionWriter for writing labeled nodes. - /// - /// The nodes section's header line is \c \@nodes \c nodes_id, but the - /// \c nodes_id may be empty. - /// - /// Each line in the section contains the label of the node and - /// then the node id. - /// - /// \relates LemonWriter - template - class NodeWriter : public CommonSectionWriterBase { - typedef CommonSectionWriterBase Parent; - typedef _Graph Graph; - typedef typename Graph::Node Node; - public: - - /// \brief Constructor. - /// - /// Constructor for NodeWriter. It creates the NodeWriter and - /// attach it into the given LemonWriter. The given \c _IdWriter - /// will write the nodes' id what can be a nodeset writer. - template - NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, - const std::string& _id = std::string()) - : Parent(_writer), id(_id), - idWriter(new IdWriter(_idWriter)) {} - - /// \brief Destructor. - /// - /// Destructor for NodeWriter. - virtual ~NodeWriter() {} - - private: - NodeWriter(const NodeWriter&); - void operator=(const NodeWriter&); - - public: - - /// \brief Add a node writer command for the NodeWriter. - /// - /// Add a node writer command for the NodeWriter. - void writeNode(const std::string& name, const Node& item) { - writers.push_back(make_pair(name, &item)); - } - - protected: - - /// \brief Header checking function. - /// - /// It gives back true when the header line start with \c \@nodes, - /// and the header line's id and the writer's id are the same. - virtual std::string header() { - return "@nodes " + id; - } - - /// \brief Writer function of the section. - /// - /// Write the content of the section. - virtual void write(std::ostream& os) { - for (int i = 0; i < (int)writers.size(); ++i) { - os << writers[i].first << ' '; - idWriter->write(os, *(writers[i].second)); - os << std::endl; - } - } - - private: - - std::string id; - - typedef std::vector > NodeWriters; - NodeWriters writers; - std::auto_ptr > idWriter; - }; - - /// \ingroup io_group - /// \brief SectionWriter for writing labeled edges. - /// - /// The edges section's header line is \c \@edges \c edges_id, but the - /// \c edges_id may be empty. - /// - /// Each line in the section contains the label of the edge and - /// then the edge id. - /// - /// \relates LemonWriter - template - class EdgeWriter : public CommonSectionWriterBase { - typedef CommonSectionWriterBase Parent; - typedef _Graph Graph; - typedef typename Graph::Edge Edge; - public: - - /// \brief Constructor. - /// - /// Constructor for EdgeWriter. It creates the EdgeWriter and - /// attach it into the given LemonWriter. The given \c _IdWriter - /// will write the edges' id what can be a edgeset writer. - template - EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, - const std::string& _id = std::string()) - : Parent(_writer), id(_id), - idWriter(new IdWriter(_idWriter)) {} - - /// \brief Destructor. - /// - /// Destructor for EdgeWriter. - virtual ~EdgeWriter() {} - private: - EdgeWriter(const EdgeWriter&); - void operator=(const EdgeWriter&); - - public: - - /// \brief Add an edge writer command for the EdgeWriter. - /// - /// Add an edge writer command for the EdgeWriter. - void writeEdge(const std::string& name, const Edge& item) { - writers.push_back(make_pair(name, &item)); - } - - protected: - - /// \brief Header checking function. - /// - /// It gives back true when the header line start with \c \@edges, - /// and the header line's id and the writer's id are the same. - virtual std::string header() { - return "@edges " + id; - } - - /// \brief Writer function of the section. - /// - /// Write the content of the section. - virtual void write(std::ostream& os) { - for (int i = 0; i < (int)writers.size(); ++i) { - os << writers[i].first << ' '; - idWriter->write(os, *(writers[i].second)); - os << std::endl; - } - } - - private: - - std::string id; - - typedef std::vector > EdgeWriters; - EdgeWriters writers; - - std::auto_ptr > idWriter; - }; - - /// \ingroup io_group - /// \brief SectionWriter for writing labeled undirected edges. - /// - /// The undirected edges section's header line is \c \@undiredges - /// \c undiredges_id, but the \c undiredges_id may be empty. - /// - /// Each line in the section contains the label of the undirected edge and - /// then the undirected edge id. - /// - /// \relates LemonWriter - template - class UndirEdgeWriter : public CommonSectionWriterBase { - typedef CommonSectionWriterBase Parent; - typedef _Graph Graph; - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - typedef typename Graph::UndirEdge UndirEdge; - public: - - /// \brief Constructor. - /// - /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and - /// attach it into the given LemonWriter. The given \c _IdWriter - /// will write the undirected edges' id what can be an undirected - /// edgeset writer. - template - UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, - const std::string& _id = std::string()) - : Parent(_writer), id(_id), - undirEdgeIdWriter(new IdWriter(_idWriter)), - edgeIdWriter(new IdWriter(_idWriter)) {} - - /// \brief Destructor. - /// - /// Destructor for UndirEdgeWriter. - virtual ~UndirEdgeWriter() {} - private: - UndirEdgeWriter(const UndirEdgeWriter&); - void operator=(const UndirEdgeWriter&); - - public: - - /// \brief Add an edge writer command for the UndirEdgeWriter. - /// - /// Add an edge writer command for the UndirEdgeWriter. - void writeEdge(const std::string& name, const Edge& item) { - edgeWriters.push_back(make_pair(name, &item)); - } - - /// \brief Add an undirected edge writer command for the UndirEdgeWriter. - /// - /// Add an undirected edge writer command for the UndirEdgeWriter. - void writeUndirEdge(const std::string& name, const UndirEdge& item) { - undirEdgeWriters.push_back(make_pair(name, &item)); - } - - protected: - - /// \brief Header checking function. - /// - /// It gives back true when the header line start with \c \@undiredges, - /// and the header line's id and the writer's id are the same. - virtual std::string header() { - return "@undiredges " + id; - } - - /// \brief Writer function of the section. - /// - /// Write the content of the section. - virtual void write(std::ostream& os) { - for (int i = 0; i < (int)undirEdgeWriters.size(); ++i) { - os << undirEdgeWriters[i].first << ' '; - undirEdgeIdWriter->write(os, *(undirEdgeWriters[i].second)); - os << std::endl; - } - for (int i = 0; i < (int)edgeWriters.size(); ++i) { - os << edgeWriters[i].first << ' '; - edgeIdWriter->write(os, *(edgeWriters[i].second)); - os << std::endl; - } - } - - private: - - std::string id; - - typedef std::vector > UndirEdgeWriters; - UndirEdgeWriters undirEdgeWriters; - std::auto_ptr > undirEdgeIdWriter; - - typedef std::vector > EdgeWriters; - EdgeWriters edgeWriters; - std::auto_ptr > edgeIdWriter; - - }; - - /// \ingroup io_group - /// \brief SectionWriter for attributes. - /// - /// The lemon format can store multiple attribute set. Each set has - /// the header line \c \@attributes \c attributeset_id, but the - /// attributeset_id may be empty. - /// - /// The attributeset section contains several lines. Each of them starts - /// with the name of attribute and then the value. - /// - /// \relates LemonWriter - template - class AttributeWriter : public CommonSectionWriterBase { - typedef CommonSectionWriterBase Parent; - typedef _Traits Traits; - public: - /// \brief Constructor. - /// - /// Constructor for AttributeWriter. It creates the AttributeWriter and - /// attach it into the given LemonWriter. - AttributeWriter(LemonWriter& _writer, - const std::string& _id = std::string()) - : Parent(_writer), id(_id) {} - - /// \brief Destructor. - /// - /// Destructor for AttributeWriter. - virtual ~AttributeWriter() { - typename Writers::iterator it; - for (it = writers.begin(); it != writers.end(); ++it) { - delete it->second; - } - } - - private: - AttributeWriter(const AttributeWriter&); - void operator=(AttributeWriter&); - - public: - /// \brief Add an attribute writer command for the writer. - /// - /// Add an attribute writer command for the writer. - template - AttributeWriter& writeAttribute(const std::string& id, - const Value& value) { - return - writeAttribute >(id, value); - } - - /// \brief Add an attribute writer command for the writer. - /// - /// Add an attribute writer command for the writer. - template - AttributeWriter& writeAttribute(const std::string& name, - const Value& value, - const Writer& writer = Writer()) { - writers.push_back(make_pair(name, new ValueWriter - (value, writer))); - return *this; - } - - protected: - - /// \brief The header of section. - /// - /// It gives back the header of the section. - std::string header() { - return "@attributes " + id; - } - - /// \brief Writer function of the section. - /// - /// Write the content of the section. - void write(std::ostream& os) { - typename Writers::iterator it; - for (it = writers.begin(); it != writers.end(); ++it) { - os << it->first << ' '; - it->second->write(os); - os << std::endl; - } - } - - private: - std::string id; - - typedef std::vector > Writers; - Writers writers; - }; - - -} -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/list_graph.h --- a/src/lemon/list_graph.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,565 +0,0 @@ -/* -*- C++ -*- - * src/lemon/list_graph.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_LIST_GRAPH_H -#define LEMON_LIST_GRAPH_H - -///\ingroup graphs -///\file -///\brief ListGraph, SymListGraph classes. - -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace lemon { - - class ListGraphBase { - - protected: - struct NodeT { - int first_in,first_out; - int prev, next; - }; - - struct EdgeT { - int target, source; - int prev_in, prev_out; - int next_in, next_out; - }; - - std::vector nodes; - - int first_node; - - int first_free_node; - - std::vector edges; - - int first_free_edge; - - public: - - typedef ListGraphBase Graph; - - class Node { - friend class ListGraphBase; - protected: - - int id; - Node(int pid) { id = pid;} - - public: - Node() {} - Node (Invalid) { id = -1; } - bool operator==(const Node& node) const {return id == node.id;} - bool operator!=(const Node& node) const {return id != node.id;} - bool operator<(const Node& node) const {return id < node.id;} - }; - - class Edge { - friend class ListGraphBase; - protected: - - int id; - Edge(int pid) { id = pid;} - - public: - Edge() {} - Edge (Invalid) { id = -1; } - bool operator==(const Edge& edge) const {return id == edge.id;} - bool operator!=(const Edge& edge) const {return id != edge.id;} - bool operator<(const Edge& edge) const {return id < edge.id;} - }; - - - - ListGraphBase() - : nodes(), first_node(-1), - first_free_node(-1), edges(), first_free_edge(-1) {} - - - /// Maximum node ID. - - /// Maximum node ID. - ///\sa id(Node) - int maxId(Node = INVALID) const { return nodes.size()-1; } - - /// Maximum edge ID. - - /// Maximum edge ID. - ///\sa id(Edge) - int maxId(Edge = INVALID) const { return edges.size()-1; } - - Node source(Edge e) const { return edges[e.id].source; } - Node target(Edge e) const { return edges[e.id].target; } - - - void first(Node& node) const { - node.id = first_node; - } - - void next(Node& node) const { - node.id = nodes[node.id].next; - } - - - void first(Edge& e) const { - int n; - for(n = first_node; - n!=-1 && nodes[n].first_in == -1; - n = nodes[n].next); - e.id = (n == -1) ? -1 : nodes[n].first_in; - } - - void next(Edge& edge) const { - if (edges[edge.id].next_in != -1) { - edge.id = edges[edge.id].next_in; - } else { - int n; - for(n = nodes[edges[edge.id].target].next; - n!=-1 && nodes[n].first_in == -1; - n = nodes[n].next); - edge.id = (n == -1) ? -1 : nodes[n].first_in; - } - } - - void firstOut(Edge &e, const Node& v) const { - e.id = nodes[v.id].first_out; - } - void nextOut(Edge &e) const { - e.id=edges[e.id].next_out; - } - - void firstIn(Edge &e, const Node& v) const { - e.id = nodes[v.id].first_in; - } - void nextIn(Edge &e) const { - e.id=edges[e.id].next_in; - } - - - static int id(Node v) { return v.id; } - static int id(Edge e) { return e.id; } - - static Node fromId(int id, Node) { return Node(id);} - static Edge fromId(int id, Edge) { return Edge(id);} - - /// Adds a new node to the graph. - - /// \warning It adds the new node to the front of the list. - /// (i.e. the lastly added node becomes the first.) - Node addNode() { - int n; - - if(first_free_node==-1) { - n = nodes.size(); - nodes.push_back(NodeT()); - } else { - n = first_free_node; - first_free_node = nodes[n].next; - } - - nodes[n].next = first_node; - if(first_node != -1) nodes[first_node].prev = n; - first_node = n; - nodes[n].prev = -1; - - nodes[n].first_in = nodes[n].first_out = -1; - - return Node(n); - } - - Edge addEdge(Node u, Node v) { - int n; - - if (first_free_edge == -1) { - n = edges.size(); - edges.push_back(EdgeT()); - } else { - n = first_free_edge; - first_free_edge = edges[n].next_in; - } - - edges[n].source = u.id; - edges[n].target = v.id; - - edges[n].next_out = nodes[u.id].first_out; - if(nodes[u.id].first_out != -1) { - edges[nodes[u.id].first_out].prev_out = n; - } - - edges[n].next_in = nodes[v.id].first_in; - if(nodes[v.id].first_in != -1) { - edges[nodes[v.id].first_in].prev_in = n; - } - - edges[n].prev_in = edges[n].prev_out = -1; - - nodes[u.id].first_out = nodes[v.id].first_in = n; - - return Edge(n); - } - - void erase(const Node& node) { - int n = node.id; - - if(nodes[n].next != -1) { - nodes[nodes[n].next].prev = nodes[n].prev; - } - - if(nodes[n].prev != -1) { - nodes[nodes[n].prev].next = nodes[n].next; - } else { - first_node = nodes[n].next; - } - - nodes[n].next = first_free_node; - first_free_node = n; - - } - - void erase(const Edge& edge) { - int n = edge.id; - - if(edges[n].next_in!=-1) { - edges[edges[n].next_in].prev_in = edges[n].prev_in; - } - - if(edges[n].prev_in!=-1) { - edges[edges[n].prev_in].next_in = edges[n].next_in; - } else { - nodes[edges[n].target].first_in = edges[n].next_in; - } - - - if(edges[n].next_out!=-1) { - edges[edges[n].next_out].prev_out = edges[n].prev_out; - } - - if(edges[n].prev_out!=-1) { - edges[edges[n].prev_out].next_out = edges[n].next_out; - } else { - nodes[edges[n].source].first_out = edges[n].next_out; - } - - edges[n].next_in = first_free_edge; - first_free_edge = n; - - } - - void clear() { - edges.clear(); - nodes.clear(); - first_node = first_free_node = first_free_edge = -1; - } - - protected: - void _moveTarget(Edge e, Node n) - { - if(edges[e.id].next_in != -1) - edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in; - if(edges[e.id].prev_in != -1) - edges[edges[e.id].prev_in].next_in = edges[e.id].next_in; - else nodes[edges[e.id].target].first_in = edges[e.id].next_in; - edges[e.id].target = n.id; - edges[e.id].prev_in = -1; - edges[e.id].next_in = nodes[n.id].first_in; - nodes[n.id].first_in = e.id; - } - void _moveSource(Edge e, Node n) - { - if(edges[e.id].next_out != -1) - edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out; - if(edges[e.id].prev_out != -1) - edges[edges[e.id].prev_out].next_out = edges[e.id].next_out; - else nodes[edges[e.id].source].first_out = edges[e.id].next_out; - edges[e.id].source = n.id; - edges[e.id].prev_out = -1; - edges[e.id].next_out = nodes[n.id].first_out; - nodes[n.id].first_out = e.id; - } - - }; - - typedef AlterableGraphExtender AlterableListGraphBase; - typedef IterableGraphExtender IterableListGraphBase; - typedef DefaultMappableGraphExtender MappableListGraphBase; - typedef ExtendableGraphExtender ExtendableListGraphBase; - typedef ClearableGraphExtender ClearableListGraphBase; - typedef ErasableGraphExtender ErasableListGraphBase; - -/// \addtogroup graphs -/// @{ - - ///A list graph class. - - ///This is a simple and fast erasable graph implementation. - /// - ///It addition that it conforms to the - ///\ref concept::ErasableGraph "ErasableGraph" concept, - ///it also provides several additional useful extra functionalities. - ///\sa concept::ErasableGraph. - - class ListGraph : public ErasableListGraphBase - { - public: - /// Moves the target of \c e to \c n - - /// Moves the target of \c e to \c n - /// - ///\note The Edge's and OutEdge's - ///referencing the moved edge remain - ///valid. However InEdge's are invalidated. - void moveTarget(Edge e, Node n) { _moveTarget(e,n); } - /// Moves the source of \c e to \c n - - /// Moves the source of \c e to \c n - /// - ///\note The Edge's and InEdge's - ///referencing the moved edge remain - ///valid. However OutEdge's are invalidated. - void moveSource(Edge e, Node n) { _moveSource(e,n); } - - /// Invert the direction of an edge. - - ///\note The Edge's - ///referencing the moved edge remain - ///valid. However OutEdge's and InEdge's are invalidated. - void reverseEdge(Edge e) { - Node t=target(e); - _moveTarget(e,source(e)); - _moveSource(e,t); - } - - ///Using this it possible to avoid the superfluous memory allocation. - - ///Using this it possible to avoid the superfluous memory allocation. - ///\todo more docs... - void reserveEdge(int n) { edges.reserve(n); }; - - ///Contract two nodes. - - ///This function contracts two nodes. - /// - ///Node \p b will be removed but instead of deleting - ///its neighboring edges, they will be joined to \p a. - ///The last parameter \p r controls whether to remove loops. \c true - ///means that loops will be removed. - /// - ///\note The Edges - ///referencing a moved edge remain - ///valid. However InEdge's and OutEdge's - ///may be invalidated. - void contract(Node a,Node b,bool r=true) - { - for(OutEdgeIt e(*this,b);e!=INVALID;) { - OutEdgeIt f=e; - ++f; - if(r && target(e)==a) erase(e); - else moveSource(e,a); - e=f; - } - for(InEdgeIt e(*this,b);e!=INVALID;) { - InEdgeIt f=e; - ++f; - if(r && source(e)==a) erase(e); - else moveTarget(e,a); - e=f; - } - erase(b); - } - - ///Split a node. - - ///This function splits a node. First a new node is added to the graph, - ///then the source of each outgoing edge of \c n is moved to this new node. - ///If \c connect is \c true (this is the default value), then a new edge - ///from \c n to the newly created node is also added. - ///\return The newly created node. - /// - ///\note The Edges - ///referencing a moved edge remain - ///valid. However InEdge's and OutEdge's - ///may be invalidated. - ///\warning This functionality cannot be used together with the SnapShot - ///feature. - ///\todo It could be implemented in a bit faster way. - Node split(Node n, bool connect = true) - { - Node b = addNode(); - for(OutEdgeIt e(*this,n);e!=INVALID;) { - OutEdgeIt f=e; - ++f; - moveSource(e,b); - e=f; - } - if(connect) addEdge(n,b); - return b; - } - - ///Class to make a snapshot of the graph and to restrore to it later. - - ///Class to make a snapshot of the graph and to restrore to it later. - /// - ///The newly added nodes and edges can be removed using the - ///restore() function. - /// - ///\warning Edge and node deletions cannot be restored. - ///\warning SnapShots cannot be nested. - ///\todo \c SnapShot or \c Snapshot? - class SnapShot : protected AlterationNotifier::ObserverBase, - protected AlterationNotifier::ObserverBase - { - protected: - - ListGraph *g; - std::list added_nodes; - std::list added_edges; - - bool active; - virtual void add(const Node& n) { - added_nodes.push_back(n); - }; - ///\bug Exception... - /// - virtual void erase(const Node&) - { - exit(1); - } - virtual void add(const Edge& n) { - added_edges.push_back(n); - }; - ///\bug Exception... - /// - virtual void erase(const Edge&) - { - exit(1); - } - - void regist(ListGraph &_g) { - g=&_g; - AlterationNotifier::ObserverBase:: - attach(g->getNotifier(Node())); - AlterationNotifier::ObserverBase:: - attach(g->getNotifier(Edge())); - } - - void deregist() { - AlterationNotifier::ObserverBase:: - detach(); - AlterationNotifier::ObserverBase:: - detach(); - g=0; - } - - public: - ///Default constructur. - - ///Default constructur. - ///To actually make a snapshot you must call save(). - /// - SnapShot() : g(0) {} - ///Constructor that immediately makes a snapshot. - - ///This constructor immediately makes a snapshot of the graph. - ///\param _g The graph we make a snapshot of. - SnapShot(ListGraph &_g) { - regist(_g); - } - ///\bug Is it necessary? - /// - ~SnapShot() - { - if(g) deregist(); - } - - ///Make a snapshot. - - ///Make a snapshot of the graph. - /// - ///This function can be called more than once. In case of a repeated - ///call, the previous snapshot gets lost. - ///\param _g The graph we make the snapshot of. - void save(ListGraph &_g) - { - if(g!=&_g) { - if(g) deregist(); - regist(_g); - } - added_nodes.clear(); - added_edges.clear(); - } - - ///Undo the changes until the last snapshot. - - ///Undo the changes until last snapshot created by save(). - /// - ///\todo This function might be called undo(). - void restore() { - deregist(); - while(!added_edges.empty()) { - g->erase(added_edges.front()); - added_edges.pop_front(); - } - while(!added_nodes.empty()) { - g->erase(added_nodes.front()); - added_nodes.pop_front(); - } - } - }; - - }; - - - /**************** Undirected List Graph ****************/ - - typedef ErasableUndirGraphExtender< - ClearableUndirGraphExtender< - ExtendableUndirGraphExtender< - MappableUndirGraphExtender< - IterableUndirGraphExtender< - AlterableUndirGraphExtender< - UndirGraphExtender > > > > > > ErasableUndirListGraphBase; - - ///An undirected list graph class. - - ///This is a simple and fast erasable undirected graph implementation. - /// - ///It conforms to the - ///\ref concept::UndirGraph "UndirGraph" concept. - /// - ///\sa concept::UndirGraph. - /// - ///\todo SnapShot, reverseEdge(), moveTarget(), moveSource(), contract() - ///haven't been implemented yet. - /// - class UndirListGraph : public ErasableUndirListGraphBase { - }; - - - /// @} -} //namespace lemon - - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lp_base.cc --- a/src/lemon/lp_base.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* -*- C++ -*- - * src/lib/lp_base.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -///\file -///\brief The implementation of the LP solver interface. - -#include -namespace lemon { - - const LpSolverBase::Value - LpSolverBase::INF = std::numeric_limits::infinity(); - const LpSolverBase::Value - LpSolverBase::NaN = std::numeric_limits::quiet_NaN(); - -// const LpSolverBase::Constr::Value -// LpSolverBase::Constr::INF = std::numeric_limits::infinity(); -// const LpSolverBase::Constr::Value -// LpSolverBase::Constr::NaN = std::numeric_limits::quiet_NaN(); - -} //namespace lemon diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lp_base.h --- a/src/lemon/lp_base.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,907 +0,0 @@ -/* -*- C++ -*- - * src/lemon/lp_base.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_LP_BASE_H -#define LEMON_LP_BASE_H - -#include -#include -#include -#include - -#include -#include -#include - -//#include"lin_expr.h" - -///\file -///\brief The interface of the LP solver interface. -///\ingroup gen_opt_group -namespace lemon { - - ///Internal data structure to convert floating id's to fix one's - - ///\todo This might be implemented to be also usable in other places. - class _FixId - { - std::vector index; - std::vector cross; - int first_free; - public: - _FixId() : first_free(-1) {}; - ///Convert a floating id to a fix one - - ///\param n is a floating id - ///\return the corresponding fix id - int fixId(int n) {return cross[n];} - ///Convert a fix id to a floating one - - ///\param n is a fix id - ///\return the corresponding floating id - int floatingId(int n) { return index[n];} - ///Add a new floating id. - - ///\param n is a floating id - ///\return the fix id of the new value - ///\todo Multiple additions should also be handled. - int insert(int n) - { - if(n>=int(cross.size())) { - cross.resize(n+1); - if(first_free==-1) { - cross[n]=index.size(); - index.push_back(n); - } - else { - cross[n]=first_free; - int next=index[first_free]; - index[first_free]=n; - first_free=next; - } - return cross[n]; - } - ///\todo Create an own exception type. - else throw LogicError(); //floatingId-s must form a continuous range; - } - ///Remove a fix id. - - ///\param n is a fix id - /// - void erase(int n) - { - int fl=index[n]; - index[n]=first_free; - first_free=n; - for(int i=fl+1;i, so for expamle - ///if \c e is an Expr and \c v and \c w are of type \ref Col, then you can - ///read and modify the coefficients like - ///these. - ///\code - ///e[v]=5; - ///e[v]+=12; - ///e.erase(v); - ///\endcode - ///or you can also iterate through its elements. - ///\code - ///double s=0; - ///for(LpSolverBase::Expr::iterator i=e.begin();i!=e.end();++i) - /// s+=i->second; - ///\endcode - ///(This code computes the sum of all coefficients). - ///- Numbers (double's) - ///and variables (\ref Col "Col"s) directly convert to an - ///\ref Expr and the usual linear operations are defined so - ///\code - ///v+w - ///2*v-3.12*(v-w/2)+2 - ///v*2.1+(3*v+(v*12+w+6)*3)/2 - ///\endcode - ///are valid \ref Expr "Expr"essions. - ///The usual assignment operations are also defined. - ///\code - ///e=v+w; - ///e+=2*v-3.12*(v-w/2)+2; - ///e*=3.4; - ///e/=5; - ///\endcode - ///- The constant member can be set and read by \ref constComp() - ///\code - ///e.constComp()=12; - ///double c=e.constComp(); - ///\endcode - /// - ///\note \ref clear() not only sets all coefficients to 0 but also - ///clears the constant components. - /// - ///\sa Constr - /// - class Expr : public std::map - { - public: - typedef LpSolverBase::Col Key; - typedef LpSolverBase::Value Value; - - protected: - typedef std::map Base; - - Value const_comp; - public: - typedef True IsLinExpression; - ///\e - Expr() : Base(), const_comp(0) { } - ///\e - Expr(const Key &v) : const_comp(0) { - Base::insert(std::make_pair(v, 1)); - } - ///\e - Expr(const Value &v) : const_comp(v) {} - ///\e - void set(const Key &v,const Value &c) { - Base::insert(std::make_pair(v, c)); - } - ///\e - Value &constComp() { return const_comp; } - ///\e - const Value &constComp() const { return const_comp; } - - ///Removes the components with zero coefficient. - void simplify() { - for (Base::iterator i=Base::begin(); i!=Base::end();) { - Base::iterator j=i; - ++j; - if ((*i).second==0) Base::erase(i); - j=i; - } - } - - ///Sets all coefficients and the constant component to 0. - void clear() { - Base::clear(); - const_comp=0; - } - - ///\e - Expr &operator+=(const Expr &e) { - for (Base::const_iterator j=e.begin(); j!=e.end(); ++j) - (*this)[j->first]+=j->second; - ///\todo it might be speeded up using "hints" - const_comp+=e.const_comp; - return *this; - } - ///\e - Expr &operator-=(const Expr &e) { - for (Base::const_iterator j=e.begin(); j!=e.end(); ++j) - (*this)[j->first]-=j->second; - const_comp-=e.const_comp; - return *this; - } - ///\e - Expr &operator*=(const Value &c) { - for (Base::iterator j=Base::begin(); j!=Base::end(); ++j) - j->second*=c; - const_comp*=c; - return *this; - } - ///\e - Expr &operator/=(const Value &c) { - for (Base::iterator j=Base::begin(); j!=Base::end(); ++j) - j->second/=c; - const_comp/=c; - return *this; - } - }; - - ///Linear constraint - - ///This data stucture represents a linear constraint in the LP. - ///Basically it is a linear expression with a lower or an upper bound - ///(or both). These parts of the constraint can be obtained by the member - ///functions \ref expr(), \ref lowerBound() and \ref upperBound(), - ///respectively. - ///There are two ways to construct a constraint. - ///- You can set the linear expression and the bounds directly - /// by the functions above. - ///- The operators \<=, == and \>= - /// are defined between expressions, or even between constraints whenever - /// it makes sense. Therefore if \c e and \c f are linear expressions and - /// \c s and \c t are numbers, then the followings are valid expressions - /// and thus they can be used directly e.g. in \ref addRow() whenever - /// it makes sense. - /// \code - /// e<=s - /// e<=f - /// s<=e<=t - /// e>=t - /// \endcode - ///\warning The validity of a constraint is checked only at run time, so - ///e.g. \ref addRow(x[1]\<=x[2]<=5) will compile, but will throw a - ///\ref LogicError exception. - class Constr - { - public: - typedef LpSolverBase::Expr Expr; - typedef Expr::Key Key; - typedef Expr::Value Value; - -// static const Value INF; -// static const Value NaN; - - protected: - Expr _expr; - Value _lb,_ub; - public: - ///\e - Constr() : _expr(), _lb(NaN), _ub(NaN) {} - ///\e - Constr(Value lb,const Expr &e,Value ub) : - _expr(e), _lb(lb), _ub(ub) {} - ///\e - Constr(const Expr &e,Value ub) : - _expr(e), _lb(NaN), _ub(ub) {} - ///\e - Constr(Value lb,const Expr &e) : - _expr(e), _lb(lb), _ub(NaN) {} - ///\e - Constr(const Expr &e) : - _expr(e), _lb(NaN), _ub(NaN) {} - ///\e - void clear() - { - _expr.clear(); - _lb=_ub=NaN; - } - - ///Reference to the linear expression - Expr &expr() { return _expr; } - ///Cont reference to the linear expression - const Expr &expr() const { return _expr; } - ///Reference to the lower bound. - - ///\return - ///- -\ref INF: the constraint is lower unbounded. - ///- -\ref NaN: lower bound has not been set. - ///- finite number: the lower bound - Value &lowerBound() { return _lb; } - ///The const version of \ref lowerBound() - const Value &lowerBound() const { return _lb; } - ///Reference to the upper bound. - - ///\return - ///- -\ref INF: the constraint is upper unbounded. - ///- -\ref NaN: upper bound has not been set. - ///- finite number: the upper bound - Value &upperBound() { return _ub; } - ///The const version of \ref upperBound() - const Value &upperBound() const { return _ub; } - ///Is the constraint lower bounded? - bool lowerBounded() const { - using namespace std; - return finite(_lb); - } - ///Is the constraint upper bounded? - bool upperBounded() const { - using namespace std; - return finite(_ub); - } - }; - - - protected: - _FixId rows; - _FixId cols; - - //Abstract virtual functions - virtual LpSolverBase &_newLp() = 0; - virtual LpSolverBase &_copyLp() = 0; - - virtual int _addCol() = 0; - virtual int _addRow() = 0; - virtual void _setRowCoeffs(int i, - int length, - int const * indices, - Value const * values ) = 0; - virtual void _setColCoeffs(int i, - int length, - int const * indices, - Value const * values ) = 0; - virtual void _setCoeff(int row, int col, Value value) = 0; - virtual void _setColLowerBound(int i, Value value) = 0; - virtual void _setColUpperBound(int i, Value value) = 0; -// virtual void _setRowLowerBound(int i, Value value) = 0; -// virtual void _setRowUpperBound(int i, Value value) = 0; - virtual void _setRowBounds(int i, Value lower, Value upper) = 0; - virtual void _setObjCoeff(int i, Value obj_coef) = 0; - virtual void _clearObj()=0; -// virtual void _setObj(int length, -// int const * indices, -// Value const * values ) = 0; - virtual SolveExitStatus _solve() = 0; - virtual Value _getPrimal(int i) = 0; - virtual Value _getPrimalValue() = 0; - virtual SolutionStatus _getPrimalStatus() = 0; - virtual void _setMax() = 0; - virtual void _setMin() = 0; - - //Own protected stuff - - //Constant component of the objective function - Value obj_const_comp; - - - - - public: - - ///\e - LpSolverBase() : obj_const_comp(0) {} - - ///\e - virtual ~LpSolverBase() {} - - ///Creates a new LP problem - LpSolverBase &newLp() {return _newLp();} - ///Makes a copy of the LP problem - LpSolverBase ©Lp() {return _copyLp();} - - ///\name Build up and modify of the LP - - ///@{ - - ///Add a new empty column (i.e a new variable) to the LP - Col addCol() { Col c; c.id=cols.insert(_addCol()); return c;} - - ///\brief Adds several new columns - ///(i.e a variables) at once - /// - ///This magic function takes a container as its argument - ///and fills its elements - ///with new columns (i.e. variables) - ///\param t can be - ///- a standard STL compatible iterable container with - ///\ref Col as its \c values_type - ///like - ///\code - ///std::vector - ///std::list - ///\endcode - ///- a standard STL compatible iterable container with - ///\ref Col as its \c mapped_type - ///like - ///\code - ///std::map - ///\endcode - ///- an iterable lemon \ref concept::WriteMap "write map" like - ///\code - ///ListGraph::NodeMap - ///ListGraph::EdgeMap - ///\endcode - ///\return The number of the created column. -#ifdef DOXYGEN - template - int addColSet(T &t) { return 0;} -#else - template - typename enable_if::type - addColSet(T &t,dummy<0> = 0) { - int s=0; - for(typename T::iterator i=t.begin();i!=t.end();++i) {*i=addCol();s++;} - return s; - } - template - typename enable_if::type - addColSet(T &t,dummy<1> = 1) { - int s=0; - for(typename T::iterator i=t.begin();i!=t.end();++i) { - i->second=addCol(); - s++; - } - return s; - } - template - typename enable_if::type - addColSet(T &t,dummy<2> = 2) { - ///\bug return addColSet(t.valueSet()); should also work. - int s=0; - for(typename T::ValueSet::iterator i=t.valueSet().begin(); - i!=t.valueSet().end(); - ++i) - { - *i=addCol(); - s++; - } - return s; - } -#endif - - ///Add a new empty row (i.e a new constaint) to the LP - - ///This function adds a new empty row (i.e a new constaint) to the LP. - ///\return The created row - Row addRow() { Row r; r.id=rows.insert(_addRow()); return r;} - - ///Set a row (i.e a constaint) of the LP - - ///\param r is the row to be modified - ///\param l is lower bound (-\ref INF means no bound) - ///\param e is a linear expression (see \ref Expr) - ///\param u is the upper bound (\ref INF means no bound) - ///\bug This is a temportary function. The interface will change to - ///a better one. - ///\todo Option to control whether a constraint with a single variable is - ///added or not. - void setRow(Row r, Value l,const Expr &e, Value u) { - std::vector indices; - std::vector values; - indices.push_back(0); - values.push_back(0); - for(Expr::const_iterator i=e.begin(); i!=e.end(); ++i) - if((*i).second!=0) { ///\bug EPSILON would be necessary here!!! - indices.push_back(cols.floatingId((*i).first.id)); - values.push_back((*i).second); - } - _setRowCoeffs(rows.floatingId(r.id),indices.size()-1, - &indices[0],&values[0]); -// _setRowLowerBound(rows.floatingId(r.id),l-e.constComp()); -// _setRowUpperBound(rows.floatingId(r.id),u-e.constComp()); - _setRowBounds(rows.floatingId(r.id),l-e.constComp(),u-e.constComp()); - } - - ///Set a row (i.e a constaint) of the LP - - ///\param r is the row to be modified - ///\param c is a linear expression (see \ref Constr) - void setRow(Row r, const Constr &c) { - setRow(r, - c.lowerBounded()?c.lowerBound():-INF, - c.expr(), - c.upperBounded()?c.upperBound():INF); - } - - ///Add a new row (i.e a new constaint) to the LP - - ///\param l is the lower bound (-\ref INF means no bound) - ///\param e is a linear expression (see \ref Expr) - ///\param u is the upper bound (\ref INF means no bound) - ///\return The created row. - ///\bug This is a temportary function. The interface will change to - ///a better one. - Row addRow(Value l,const Expr &e, Value u) { - Row r=addRow(); - setRow(r,l,e,u); - return r; - } - - ///Add a new row (i.e a new constaint) to the LP - - ///\param c is a linear expression (see \ref Constr) - ///\return The created row. - Row addRow(const Constr &c) { - Row r=addRow(); - setRow(r,c); - return r; - } - - /// Set the lower bound of a column (i.e a variable) - - /// The upper bound of a variable (column) has to be given by an - /// extended number of type Value, i.e. a finite number of type - /// Value or -\ref INF. - void colLowerBound(Col c, Value value) { - _setColLowerBound(cols.floatingId(c.id),value); - } - /// Set the upper bound of a column (i.e a variable) - - /// The upper bound of a variable (column) has to be given by an - /// extended number of type Value, i.e. a finite number of type - /// Value or \ref INF. - void colUpperBound(Col c, Value value) { - _setColUpperBound(cols.floatingId(c.id),value); - }; - /// Set the lower and the upper bounds of a column (i.e a variable) - - /// The lower and the upper bounds of - /// a variable (column) have to be given by an - /// extended number of type Value, i.e. a finite number of type - /// Value, -\ref INF or \ref INF. - void colBounds(Col c, Value lower, Value upper) { - _setColLowerBound(cols.floatingId(c.id),lower); - _setColUpperBound(cols.floatingId(c.id),upper); - } - -// /// Set the lower bound of a row (i.e a constraint) - -// /// The lower bound of a linear expression (row) has to be given by an -// /// extended number of type Value, i.e. a finite number of type -// /// Value or -\ref INF. -// void rowLowerBound(Row r, Value value) { -// _setRowLowerBound(rows.floatingId(r.id),value); -// }; -// /// Set the upper bound of a row (i.e a constraint) - -// /// The upper bound of a linear expression (row) has to be given by an -// /// extended number of type Value, i.e. a finite number of type -// /// Value or \ref INF. -// void rowUpperBound(Row r, Value value) { -// _setRowUpperBound(rows.floatingId(r.id),value); -// }; - - /// Set the lower and the upper bounds of a row (i.e a constraint) - - /// The lower and the upper bounds of - /// a constraint (row) have to be given by an - /// extended number of type Value, i.e. a finite number of type - /// Value, -\ref INF or \ref INF. - void rowBounds(Row c, Value lower, Value upper) { - _setRowBounds(rows.floatingId(c.id),lower, upper); - // _setRowUpperBound(rows.floatingId(c.id),upper); - } - - ///Set an element of the objective function - void objCoeff(Col c, Value v) {_setObjCoeff(cols.floatingId(c.id),v); }; - ///Set the objective function - - ///\param e is a linear expression of type \ref Expr. - ///\bug The previous objective function is not cleared! - void setObj(Expr e) { - _clearObj(); - for (Expr::iterator i=e.begin(); i!=e.end(); ++i) - objCoeff((*i).first,(*i).second); - obj_const_comp=e.constComp(); - } - - ///Maximize - void max() { _setMax(); } - ///Minimize - void min() { _setMin(); } - - - ///@} - - - ///\name Solve the LP - - ///@{ - - ///\e - SolveExitStatus solve() { return _solve(); } - - ///@} - - ///\name Obtain the solution - - ///@{ - - ///\e - SolutionStatus primalStatus() { - return _getPrimalStatus(); - } - - ///\e - Value primal(Col c) { return _getPrimal(cols.floatingId(c.id)); } - - ///\e - - ///\return - ///- \ref INF or -\ref INF means either infeasibility or unboundedness - /// of the primal problem, depending on whether we minimize or maximize. - ///- \ref NaN if no primal solution is found. - ///- The (finite) objective value if an optimal solution is found. - Value primalValue() { return _getPrimalValue()+obj_const_comp;} - ///@} - - }; - - ///\e - - ///\relates LpSolverBase::Expr - /// - inline LpSolverBase::Expr operator+(const LpSolverBase::Expr &a, - const LpSolverBase::Expr &b) - { - LpSolverBase::Expr tmp(a); - tmp+=b; ///\todo Doesn't STL have some special 'merge' algorithm? - return tmp; - } - ///\e - - ///\relates LpSolverBase::Expr - /// - inline LpSolverBase::Expr operator-(const LpSolverBase::Expr &a, - const LpSolverBase::Expr &b) - { - LpSolverBase::Expr tmp(a); - tmp-=b; ///\todo Doesn't STL have some special 'merge' algorithm? - return tmp; - } - ///\e - - ///\relates LpSolverBase::Expr - /// - inline LpSolverBase::Expr operator*(const LpSolverBase::Expr &a, - const LpSolverBase::Value &b) - { - LpSolverBase::Expr tmp(a); - tmp*=b; ///\todo Doesn't STL have some special 'merge' algorithm? - return tmp; - } - - ///\e - - ///\relates LpSolverBase::Expr - /// - inline LpSolverBase::Expr operator*(const LpSolverBase::Value &a, - const LpSolverBase::Expr &b) - { - LpSolverBase::Expr tmp(b); - tmp*=a; ///\todo Doesn't STL have some special 'merge' algorithm? - return tmp; - } - ///\e - - ///\relates LpSolverBase::Expr - /// - inline LpSolverBase::Expr operator/(const LpSolverBase::Expr &a, - const LpSolverBase::Value &b) - { - LpSolverBase::Expr tmp(a); - tmp/=b; ///\todo Doesn't STL have some special 'merge' algorithm? - return tmp; - } - - ///\e - - ///\relates LpSolverBase::Constr - /// - inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e, - const LpSolverBase::Expr &f) - { - return LpSolverBase::Constr(-LpSolverBase::INF,e-f,0); - } - - ///\e - - ///\relates LpSolverBase::Constr - /// - inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &e, - const LpSolverBase::Expr &f) - { - return LpSolverBase::Constr(e,f); - } - - ///\e - - ///\relates LpSolverBase::Constr - /// - inline LpSolverBase::Constr operator<=(const LpSolverBase::Expr &e, - const LpSolverBase::Value &f) - { - return LpSolverBase::Constr(e,f); - } - - ///\e - - ///\relates LpSolverBase::Constr - /// - inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e, - const LpSolverBase::Expr &f) - { - return LpSolverBase::Constr(-LpSolverBase::INF,f-e,0); - } - - - ///\e - - ///\relates LpSolverBase::Constr - /// - inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &e, - const LpSolverBase::Expr &f) - { - return LpSolverBase::Constr(f,e); - } - - - ///\e - - ///\relates LpSolverBase::Constr - /// - inline LpSolverBase::Constr operator>=(const LpSolverBase::Expr &e, - const LpSolverBase::Value &f) - { - return LpSolverBase::Constr(f,e); - } - - ///\e - - ///\relates LpSolverBase::Constr - /// - inline LpSolverBase::Constr operator==(const LpSolverBase::Expr &e, - const LpSolverBase::Expr &f) - { - return LpSolverBase::Constr(0,e-f,0); - } - - ///\e - - ///\relates LpSolverBase::Constr - /// - inline LpSolverBase::Constr operator<=(const LpSolverBase::Value &n, - const LpSolverBase::Constr&c) - { - LpSolverBase::Constr tmp(c); - ///\todo Create an own exception type. - if(!isnan(tmp.lowerBound())) throw LogicError(); - else tmp.lowerBound()=n; - return tmp; - } - ///\e - - ///\relates LpSolverBase::Constr - /// - inline LpSolverBase::Constr operator<=(const LpSolverBase::Constr& c, - const LpSolverBase::Value &n) - { - LpSolverBase::Constr tmp(c); - ///\todo Create an own exception type. - if(!isnan(tmp.upperBound())) throw LogicError(); - else tmp.upperBound()=n; - return tmp; - } - - ///\e - - ///\relates LpSolverBase::Constr - /// - inline LpSolverBase::Constr operator>=(const LpSolverBase::Value &n, - const LpSolverBase::Constr&c) - { - LpSolverBase::Constr tmp(c); - ///\todo Create an own exception type. - if(!isnan(tmp.upperBound())) throw LogicError(); - else tmp.upperBound()=n; - return tmp; - } - ///\e - - ///\relates LpSolverBase::Constr - /// - inline LpSolverBase::Constr operator>=(const LpSolverBase::Constr& c, - const LpSolverBase::Value &n) - { - LpSolverBase::Constr tmp(c); - ///\todo Create an own exception type. - if(!isnan(tmp.lowerBound())) throw LogicError(); - else tmp.lowerBound()=n; - return tmp; - } - - -} //namespace lemon - -#endif //LEMON_LP_BASE_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lp_cplex.cc --- a/src/lemon/lp_cplex.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,408 +0,0 @@ -/* -*- C++ -*- - * src/lemon/lp_cplex.cc - * - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ -#include -#include - -///\file -///\brief Implementation of the LEMON-CPLEX lp solver interface. -namespace lemon { - - LpCplex::LpCplex() : LpSolverBase() { - env = NULL; - lp = NULL; - env = CPXopenCPLEXdevelop(&status); -// if (Env == NULL) -// { -// fprintf(stderr,"A CPLEX környezet megnyitása sikertelen.\n"); -// CPXgeterrorstring(Env, Status, ErrorMsg); -// fprintf(stderr,"%s",ErrorMsg); -// goto Terminate; -// } - - // *** A problema létrehozása *** - lp = CPXcreateprob(env, &status, "LP problem"); - - // if (Problem == NULL) -// { -// fprintf(stderr,"Az LP létrehozása sikertelen"); -// goto Terminate; -// } - - } - - LpCplex::~LpCplex() { - status = CPXfreeprob(env,&lp); - // if (Status != 0) - // { -// fprintf(stderr,"A CPLEX feladat törlése sikertelen.\n"); -// CPXgeterrorstring(Env, Status, ErrorMsg); -// fprintf(stderr,"%s",ErrorMsg); -// goto Terminate; -// } - - status = CPXcloseCPLEX(&env); - // if (Status != 0) - // { - // fprintf(stderr,"A CPLEX környezet bezárása sikertelen.\n"); -// CPXgeterrorstring(Env, Status, ErrorMsg); -// fprintf(stderr,"%s",ErrorMsg); -// goto Terminate; -// } - - } - - LpSolverBase &LpCplex::_newLp() - { - return *(LpSolverBase*)0; - } - LpSolverBase &LpCplex::_copyLp() { - return *(LpSolverBase*)0; - //Ez lesz majd CPXcloneprob (env, lp, &status); - } - - int LpCplex::_addCol() - { - int i = CPXgetnumcols (env, lp); - Value lb[1],ub[1]; - lb[0]=-INF;//-CPX_INFBOUND; - ub[0]=INF;//CPX_INFBOUND; - status = CPXnewcols (env, lp, 1, NULL, lb, ub, NULL, NULL); - return i; - } - - int LpCplex::_addRow() - { - //We want a row that is not constrained - char sense[1]; - sense[0]='L';//<= constraint - Value rhs[1]; - rhs[0]=INF; - int i = CPXgetnumrows (env, lp); - status = CPXnewrows (env, lp, 1, rhs, sense, NULL, NULL); - return i; - } - - - void LpCplex::_eraseCol(int i) { - ///\todo Not implemented yet - } - - void LpCplex::_eraseRow(int i) { - ///\todo Not implemented yet - } - - - ///\warning Data at index 0 is ignored in the arrays. - void LpCplex::_setRowCoeffs(int i, - int length, - int const * indices, - Value const * values ) - { - int rowlist[length+1]; - int* p=rowlist; - for (int k=1;k<=length;++k){ - rowlist[k]=i; - } - status = CPXchgcoeflist(env, lp, - length, - p+1, - const_cast(indices+1), - const_cast(values+1)); - } - - void LpCplex::_setColCoeffs(int i, - int length, - int const * indices, - Value const * values) - { - int collist[length+1]; - int* p=collist; - for (int k=1;k<=length;++k){ - collist[k]=i; - } - status = CPXchgcoeflist(env, lp, - length, - const_cast(indices+1), - p+1, - const_cast(values+1)); - } - - void LpCplex::_setCoeff(int row, int col, Value value) - { - CPXchgcoef (env, lp, row, col, value); - } - - void LpCplex::_setColLowerBound(int i, Value value) - { - int indices[1]; - indices[0]=i; - char lu[1]; - lu[0]='L'; - Value bd[1]; - bd[0]=value; - status = CPXchgbds (env, lp, 1, indices, lu, bd); - - } - - void LpCplex::_setColUpperBound(int i, Value value) - { - int indices[1]; - indices[0]=i; - char lu[1]; - lu[0]='U'; - Value bd[1]; - bd[0]=value; - status = CPXchgbds (env, lp, 1, indices, lu, bd); - } - - //This will be easier to implement - void LpCplex::_setRowBounds(int i, Value lb, Value ub) - { - //Bad parameter - if (lb==INF || ub==-INF) { - //FIXME error - } - - int cnt=1; - int indices[1]; - indices[0]=i; - char sense[1]; - - if (lb==-INF){ - sense[0]='L'; - CPXchgsense (env, lp, cnt, indices, sense); - CPXchgcoef (env, lp, i, -1, ub); - - } - else{ - if (ub==INF){ - sense[0]='G'; - CPXchgsense (env, lp, cnt, indices, sense); - CPXchgcoef (env, lp, i, -1, lb); - } - else{ - if (lb == ub){ - sense[0]='E'; - CPXchgsense (env, lp, cnt, indices, sense); - CPXchgcoef (env, lp, i, -1, lb); - } - else{ - sense[0]='R'; - CPXchgsense (env, lp, cnt, indices, sense); - CPXchgcoef (env, lp, i, -1, lb); - CPXchgcoef (env, lp, i, -2, ub-lb); - } - } - } - } - -// void LpCplex::_setRowLowerBound(int i, Value value) -// { -// //Not implemented, obsolete -// } - -// void LpCplex::_setRowUpperBound(int i, Value value) -// { -// //Not implemented, obsolete -// // //TODO Ezt kell meg megirni -// // //type of the problem -// // char sense[1]; -// // status = CPXgetsense (env, lp, sense, i, i); -// // Value rhs[1]; -// // status = CPXgetrhs (env, lp, rhs, i, i); - -// // switch (sense[0]) { -// // case 'L'://<= constraint -// // break; -// // case 'E'://= constraint -// // break; -// // case 'G'://>= constraint -// // break; -// // case 'R'://ranged constraint -// // break; -// // default: ; -// // //FIXME error -// // } - -// // status = CPXchgcoef (env, lp, i, -2, value_rng); -// } - - void LpCplex::_setObjCoeff(int i, Value obj_coef) - { - CPXchgcoef (env, lp, -1, i, obj_coef); - } - - void LpCplex::_clearObj() - { - for (int i=0;i< CPXgetnumcols (env, lp);++i){ - CPXchgcoef (env, lp, -1, i, 0); - } - - } - - LpCplex::SolveExitStatus LpCplex::_solve() - { - - status = CPXlpopt (env, lp); - if (status == 0){ - return SOLVED; - } - else{ - return UNSOLVED; - } -// int i= lpx_simplex(lp); -// switch (i) { -// case LPX_E_OK: -// return SOLVED; -// break; -// default: -// return UNSOLVED; -// } - } - - LpCplex::SolutionStatus LpCplex::_getPrimalStatus() - { -//7.5-os cplex statusai -// #define CPX_OPTIMAL 1 -// #define CPX_INFEASIBLE 2 -// #define CPX_UNBOUNDED 3 -// #define CPX_OBJ_LIM 4 -// #define CPX_IT_LIM_FEAS 5 -// #define CPX_IT_LIM_INFEAS 6 -// #define CPX_TIME_LIM_FEAS 7 -// #define CPX_TIME_LIM_INFEAS 8 -// #define CPX_NUM_BEST_FEAS 9 -// #define CPX_NUM_BEST_INFEAS 10 -// #define CPX_OPTIMAL_INFEAS 11 -// #define CPX_ABORT_FEAS 12 -// #define CPX_ABORT_INFEAS 13 -// #define CPX_ABORT_DUAL_INFEAS 14 -// #define CPX_ABORT_PRIM_INFEAS 15 -// #define CPX_ABORT_PRIM_DUAL_INFEAS 16 -// #define CPX_ABORT_PRIM_DUAL_FEAS 17 -// #define CPX_ABORT_CROSSOVER 18 -// #define CPX_INForUNBD 19 -// #define CPX_PIVOT 20 - -// Ezeket hova tegyem: -// ??case CPX_ABORT_DUAL_INFEAS -// ??case CPX_ABORT_CROSSOVER -// ??case CPX_INForUNBD -// ??case CPX_PIVOT - - int stat = CPXgetstat (env, lp); - switch (stat) { - case 0: - return UNDEFINED; //Undefined - break; - case CPX_OPTIMAL://Optimal - return OPTIMAL; - break; - case CPX_UNBOUNDED://Unbounded - return INFINITE; - break; - case CPX_INFEASIBLE://Infeasible - case CPX_IT_LIM_INFEAS: - case CPX_TIME_LIM_INFEAS: - case CPX_NUM_BEST_INFEAS: - case CPX_OPTIMAL_INFEAS: - case CPX_ABORT_INFEAS: - case CPX_ABORT_PRIM_INFEAS: - case CPX_ABORT_PRIM_DUAL_INFEAS: - return INFEASIBLE; - break; - case CPX_OBJ_LIM: - case CPX_IT_LIM_FEAS: - case CPX_TIME_LIM_FEAS: - case CPX_NUM_BEST_FEAS: - case CPX_ABORT_FEAS: - case CPX_ABORT_PRIM_DUAL_FEAS: - return FEASIBLE; - break; - default: - return UNDEFINED; //Everything else comes here - //FIXME error - } - - - //Nem tudom, hanyas cplex verzio statusai -// CPX_STAT_ABORT_DUAL_OBJ_LIM -// CPX_STAT_ABORT_IT_LIM -// CPX_STAT_ABORT_OBJ_LIM -// CPX_STAT_ABORT_PRIM_OBJ_LIM -// CPX_STAT_ABORT_TIME_LIM -// CPX_STAT_ABORT_USER -// CPX_STAT_FEASIBLE_RELAXED -// CPX_STAT_INFEASIBLE -// CPX_STAT_INForUNBD -// CPX_STAT_NUM_BEST -// CPX_STAT_OPTIMAL -// CPX_STAT_OPTIMAL_FACE_UNBOUNDED -// CPX_STAT_OPTIMAL_INFEAS -// CPX_STAT_OPTIMAL_RELAXED -// CPX_STAT_UNBOUNDED - -// int stat = CPXgetstat (env, lp); -// switch (stat) { -// case CPX_STAT_OPTIMAL://Optimal -// return OPTIMAL; -// break; -// case CPX_STAT_INFEASIBLE://Infeasible -// return INFEASIBLE; -// break; -// case CPX_STAT_UNBOUNDED://Unbounded -// return INFINITE; -// break; -// case CPX_STAT_NUM_BEST://Feasible -// return FEASIBLE; -// break; -// default: -// return UNDEFINED; //Everything else comes here -// //FIXME error -// } - - } - - LpCplex::Value LpCplex::_getPrimal(int i) - { - Value x; - CPXgetx (env, lp, &x, i, i); - return x; - } - - LpCplex::Value LpCplex::_getPrimalValue() - { - Value objval; - //method = CPXgetmethod (env, lp); - status = CPXgetobjval (env, lp, &objval); - return objval; - } - - - - - void LpCplex::_setMax() - { - CPXchgobjsen (env, lp, CPX_MAX); - } - void LpCplex::_setMin() - { - CPXchgobjsen (env, lp, CPX_MIN); - } - -} //namespace lemon - diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lp_cplex.h --- a/src/lemon/lp_cplex.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -/* -*- C++ -*- - * src/lemon/lp_cplex.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_LP_CPLEX_H -#define LEMON_LP_CPLEX_H - -///\file -///\brief Header of the LEMON-CPLEX lp solver interface. - -#include - -extern "C" { -#include -} - -namespace lemon { - - - /// \brief Interface for the CPLEX solver - /// - /// This class implements an interface for the CPLEX LP solver. - class LpCplex : public LpSolverBase { - - public: - - typedef LpSolverBase Parent; - - /// \e - int status; - CPXENVptr env; - CPXLPptr lp; - - - /// \e - LpCplex(); - /// \e - ~LpCplex(); - - protected: - virtual LpSolverBase &_newLp(); - virtual LpSolverBase &_copyLp(); - - virtual int _addCol(); - virtual int _addRow(); - virtual void _eraseCol(int i); - virtual void _eraseRow(int i); - virtual void _setRowCoeffs(int i, - int length, - const int * indices, - const Value * values ); - virtual void _setColCoeffs(int i, - int length, - const int * indices, - const Value * values); - virtual void _setCoeff(int row, int col, Value value); - virtual void _setColLowerBound(int i, Value value); - virtual void _setColUpperBound(int i, Value value); -// virtual void _setRowLowerBound(int i, Value value); -// virtual void _setRowUpperBound(int i, Value value); - virtual void _setRowBounds(int i, Value lower, Value upper); - virtual void _setObjCoeff(int i, Value obj_coef); - virtual void _clearObj(); - ///\e - - ///\bug Unimplemented - /// - virtual SolveExitStatus _solve(); - ///\e - - ///\bug Unimplemented - /// - virtual Value _getPrimal(int i); - ///\e - - ///\bug Unimplemented - /// - virtual Value _getPrimalValue(); - ///\e - - ///\bug Unimplemented - /// - virtual SolutionStatus _getPrimalStatus(); - - ///\e - - ///\bug Unimplemented - /// - virtual void _setMax(); - ///\e - - ///\bug Unimplemented - /// - virtual void _setMin(); - - }; -} //END OF NAMESPACE LEMON - -#endif //LEMON_LP_CPLEX_H - diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lp_glpk.cc --- a/src/lemon/lp_glpk.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,447 +0,0 @@ -/* -*- C++ -*- - * src/lemon/lp_glpk.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_LP_GLPK_CC -#define LEMON_LP_GLPK_CC - -///\file -///\brief Implementation of the LEMON-GLPK lp solver interface. - -#include - -namespace lemon { - - ///\e - - ///\bug Unimplemented! - /// - LpSolverBase &LpGlpk::_newLp() - { - LpSolverBase *tmp=0; - return *tmp; - } - - ///\e - - ///\bug Unimplemented! - /// - LpSolverBase &LpGlpk::_copyLp() - { - LpSolverBase *tmp=0; - return *tmp; - } - - LpGlpk::LpGlpk() : Parent(), - lp(lpx_create_prob()) { - ///\todo constrol function for this: - lpx_set_int_parm(lp, LPX_K_DUAL, 1); - messageLevel(0); - } - - LpGlpk::~LpGlpk() { - lpx_delete_prob(lp); - } - - int LpGlpk::_addCol() { - int i=lpx_add_cols(lp, 1); - _setColLowerBound(i, -INF); - _setColUpperBound(i, INF); - return i; - } - - int LpGlpk::_addRow() { - int i=lpx_add_rows(lp, 1); - return i; - } - - - void LpGlpk::_eraseCol(int i) { - int cols[2]; - cols[1]=i; - lpx_del_cols(lp, 1, cols); - } - - void LpGlpk::_eraseRow(int i) { - int rows[2]; - rows[1]=i; - lpx_del_rows(lp, 1, rows); - } - - void LpGlpk::_setRowCoeffs(int i, - int length, - const int * indices, - const Value * values ) - { - lpx_set_mat_row(lp, i, length, - const_cast(indices) , - const_cast(values)); - } - - void LpGlpk::_setColCoeffs(int i, - int length, - const int * indices, - const Value * values) - { - lpx_set_mat_col(lp, i, length, - const_cast(indices), - const_cast(values)); - } - - - void LpGlpk::_setCoeff(int row, int col, Value value) - { - ///FIXME Of course this is not efficient at all, but GLPK knows not more. - // First approach: get one row, apply changes and set it again - //(one idea to improve this: maybe it is better to do this with 1 coloumn) - - int mem_length=2+lpx_get_num_cols(lp); - int* indices = new int[mem_length]; - Value* values = new Value[mem_length]; - - - int length=lpx_get_mat_row(lp, row, indices, values); - - //The following code does not suppose that the elements of the array indices are sorted - int i=1; - bool found=false; - while (i <= length && !found){ - if (indices[i]==col){ - found = true; - values[i]=value; - } - ++i; - } - if (!found){ - ++length; - indices[length]=col; - values[length]=value; - } - - lpx_set_mat_row(lp, row, length, indices, values); - delete [] indices; - delete [] values; - - } - - void LpGlpk::_setColLowerBound(int i, Value lo) - { - if (lo==INF) { - //FIXME error - } - int b=lpx_get_col_type(lp, i); - double up=lpx_get_col_ub(lp, i); - if (lo==-INF) { - switch (b) { - case LPX_FR: - case LPX_LO: - lpx_set_col_bnds(lp, i, LPX_FR, lo, up); - break; - case LPX_UP: - break; - case LPX_DB: - case LPX_FX: - lpx_set_col_bnds(lp, i, LPX_UP, lo, up); - break; - default: ; - //FIXME error - } - } else { - switch (b) { - case LPX_FR: - case LPX_LO: - lpx_set_col_bnds(lp, i, LPX_LO, lo, up); - break; - case LPX_UP: - case LPX_DB: - case LPX_FX: - if (lo==up) - lpx_set_col_bnds(lp, i, LPX_FX, lo, up); - else - lpx_set_col_bnds(lp, i, LPX_DB, lo, up); - break; - default: ; - //FIXME error - } - } - - } - - void LpGlpk::_setColUpperBound(int i, Value up) - { - if (up==-INF) { - //FIXME error - } - int b=lpx_get_col_type(lp, i); - double lo=lpx_get_col_lb(lp, i); - if (up==INF) { - switch (b) { - case LPX_FR: - case LPX_LO: - break; - case LPX_UP: - lpx_set_col_bnds(lp, i, LPX_FR, lo, up); - break; - case LPX_DB: - case LPX_FX: - lpx_set_col_bnds(lp, i, LPX_LO, lo, up); - break; - default: ; - //FIXME error - } - } else { - switch (b) { - case LPX_FR: - lpx_set_col_bnds(lp, i, LPX_UP, lo, up); - break; - case LPX_UP: - lpx_set_col_bnds(lp, i, LPX_UP, lo, up); - break; - case LPX_LO: - case LPX_DB: - case LPX_FX: - if (lo==up) - lpx_set_col_bnds(lp, i, LPX_FX, lo, up); - else - lpx_set_col_bnds(lp, i, LPX_DB, lo, up); - break; - default: ; - //FIXME error - } - } - } - -// void LpGlpk::_setRowLowerBound(int i, Value lo) -// { -// if (lo==INF) { -// //FIXME error -// } -// int b=lpx_get_row_type(lp, i); -// double up=lpx_get_row_ub(lp, i); -// if (lo==-INF) { -// switch (b) { -// case LPX_FR: -// case LPX_LO: -// lpx_set_row_bnds(lp, i, LPX_FR, lo, up); -// break; -// case LPX_UP: -// break; -// case LPX_DB: -// case LPX_FX: -// lpx_set_row_bnds(lp, i, LPX_UP, lo, up); -// break; -// default: ; -// //FIXME error -// } -// } else { -// switch (b) { -// case LPX_FR: -// case LPX_LO: -// lpx_set_row_bnds(lp, i, LPX_LO, lo, up); -// break; -// case LPX_UP: -// case LPX_DB: -// case LPX_FX: -// if (lo==up) -// lpx_set_row_bnds(lp, i, LPX_FX, lo, up); -// else -// lpx_set_row_bnds(lp, i, LPX_DB, lo, up); -// break; -// default: ; -// //FIXME error -// } -// } -// } - -// void LpGlpk::_setRowUpperBound(int i, Value up) -// { -// if (up==-INF) { -// //FIXME error -// } -// int b=lpx_get_row_type(lp, i); -// double lo=lpx_get_row_lb(lp, i); -// if (up==INF) { -// switch (b) { -// case LPX_FR: -// case LPX_LO: -// break; -// case LPX_UP: -// lpx_set_row_bnds(lp, i, LPX_FR, lo, up); -// break; -// case LPX_DB: -// case LPX_FX: -// lpx_set_row_bnds(lp, i, LPX_LO, lo, up); -// break; -// default: ; -// //FIXME error -// } -// } else { -// switch (b) { -// case LPX_FR: -// lpx_set_row_bnds(lp, i, LPX_UP, lo, up); -// break; -// case LPX_UP: -// lpx_set_row_bnds(lp, i, LPX_UP, lo, up); -// break; -// case LPX_LO: -// case LPX_DB: -// case LPX_FX: -// if (lo==up) -// lpx_set_row_bnds(lp, i, LPX_FX, lo, up); -// else -// lpx_set_row_bnds(lp, i, LPX_DB, lo, up); -// break; -// default: ; -// //FIXME error -// } -// } -// } - - void LpGlpk::_setRowBounds(int i, Value lb, Value ub) - { - //Bad parameter - if (lb==INF || ub==-INF) { - //FIXME error - } - - if (lb == -INF){ - if (ub == INF){ - lpx_set_row_bnds(lp, i, LPX_FR, lb, ub); - } - else{ - lpx_set_row_bnds(lp, i, LPX_UP, lb, ub); - } - } - else{ - if (ub==INF){ - lpx_set_row_bnds(lp, i, LPX_LO, lb, ub); - - } - else{ - if (lb == ub){ - lpx_set_row_bnds(lp, i, LPX_FX, lb, ub); - } - else{ - lpx_set_row_bnds(lp, i, LPX_DB, lb, ub); - } - } - } - - } - - void LpGlpk::_setObjCoeff(int i, Value obj_coef) - { - //i=0 means the constant term (shift) - lpx_set_obj_coef(lp, i, obj_coef); - } - - void LpGlpk::_clearObj() - { - for (int i=0;i<=lpx_get_num_cols(lp);++i){ - lpx_set_obj_coef(lp, i, 0); - } - } -// void LpGlpk::_setObj(int length, -// int const * indices, -// Value const * values ) -// { -// Value new_values[1+lpx_num_cols()]; -// for (i=0;i<=lpx_num_cols();++i){ -// new_values[i]=0; -// } -// for (i=1;i<=length;++i){ -// new_values[indices[i]]=values[i]; -// } - -// for (i=0;i<=lpx_num_cols();++i){ -// lpx_set_obj_coef(lp, i, new_values[i]); -// } -// } - - LpGlpk::SolveExitStatus LpGlpk::_solve() - { - int i= lpx_simplex(lp); - switch (i) { - case LPX_E_OK: - return SOLVED; - break; - default: - return UNSOLVED; - } - } - - LpGlpk::Value LpGlpk::_getPrimal(int i) - { - return lpx_get_col_prim(lp,i); - } - - LpGlpk::Value LpGlpk::_getPrimalValue() - { - return lpx_get_obj_val(lp); - } - - - LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() - { - int stat= lpx_get_status(lp); - switch (stat) { - case LPX_UNDEF://Undefined (no solve has been run yet) - return UNDEFINED; - break; - case LPX_NOFEAS://There is no feasible solution (primal, I guess) - case LPX_INFEAS://Infeasible - return INFEASIBLE; - break; - case LPX_UNBND://Unbounded - return INFINITE; - break; - case LPX_FEAS://Feasible - return FEASIBLE; - break; - case LPX_OPT://Feasible - return OPTIMAL; - break; - default: - return UNDEFINED; //to avoid gcc warning - //FIXME error - } - } - - - void LpGlpk::_setMax() - { - lpx_set_obj_dir(lp, LPX_MAX); - } - - void LpGlpk::_setMin() - { - lpx_set_obj_dir(lp, LPX_MIN); - } - - - void LpGlpk::messageLevel(int m) - { - lpx_set_int_parm(lp, LPX_K_MSGLEV, m); - } - - void LpGlpk::presolver(bool b) - { - lpx_set_int_parm(lp, LPX_K_PRESOL, b); - } - - -} //END OF NAMESPACE LEMON - -#endif //LEMON_LP_GLPK_CC diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lp_glpk.h --- a/src/lemon/lp_glpk.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -/* -*- C++ -*- - * src/lemon/lp_glpk.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_LP_GLPK_H -#define LEMON_LP_GLPK_H - -///\file -///\brief Header of the LEMON-GLPK lp solver interface. -///\ingroup gen_opt_group - -#include -extern "C" { -#include -} - -namespace lemon { - - - /// \brief Interface for the GLPK LP solver - /// - /// This class implements an interface for the GLPK LP solver. - ///\ingroup gen_opt_group - class LpGlpk : public LpSolverBase { - protected: - LPX* lp; - - public: - - typedef LpSolverBase Parent; - - LpGlpk(); - ~LpGlpk(); - - protected: - virtual LpSolverBase &_newLp(); - virtual LpSolverBase &_copyLp(); - - virtual int _addCol(); - virtual int _addRow(); - virtual void _eraseCol(int i); - virtual void _eraseRow(int i); - - virtual void _setRowCoeffs(int i, - int length, - const int * indices, - const Value * values ); - virtual void _setColCoeffs(int i, - int length, - const int * indices, - const Value * values); - virtual void _setCoeff(int row, int col, Value value); - virtual void _setColLowerBound(int i, Value value); - virtual void _setColUpperBound(int i, Value value); -// virtual void _setRowLowerBound(int i, Value value); -// virtual void _setRowUpperBound(int i, Value value); - virtual void _setRowBounds(int i, Value lower, Value upper); - virtual void _setObjCoeff(int i, Value obj_coef); - virtual void _clearObj(); -// virtual void _setObj(int length, -// int const * indices, -// Value const * values ) = 0; - - ///\e - - ///\todo It should be clarified - /// - virtual SolveExitStatus _solve(); - virtual Value _getPrimal(int i); - virtual Value _getPrimalValue(); - ///\e - - ///\todo It should be clarified - /// - virtual SolutionStatus _getPrimalStatus(); - virtual void _setMax(); - virtual void _setMin(); - - public: - ///Set the verbosity of the messages - - ///Set the verbosity of the messages - /// - ///\param m is the level of the messages output by the solver routines. - ///The possible values are: - ///- 0 --- no output (default value) - ///- 1 --- error messages only - ///- 2 --- normal output - ///- 3 --- full output (includes informational messages) - void messageLevel(int m); - ///Turns on or off the presolver - - ///Turns on (\c b is \c true) or off (\c b is \c false) the presolver - /// - ///The presolver is off by default. - void presolver(bool b); - - }; -} //END OF NAMESPACE LEMON - -#endif //LEMON_LP_GLPK_H - diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lp_skeleton.cc --- a/src/lemon/lp_skeleton.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* -*- C++ -*- - * src/lemon/lp_skeleton.cc - * - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include - -///\file -///\brief A skeleton file to implement LP solver interfaces -namespace lemon { - - LpSolverBase &LpSkeleton::_newLp() - { - LpSolverBase *tmp=0; - return *tmp; - } - - LpSolverBase &LpSkeleton::_copyLp() - { - LpSolverBase *tmp=0; - return *tmp; - } - - int LpSkeleton::_addCol() - { - return ++col_num; - } - - int LpSkeleton::_addRow() - { - return ++row_num; - } - - void LpSkeleton::_eraseCol(int ) { - } - - void LpSkeleton::_eraseRow(int) { - } - - void LpSkeleton::_setRowCoeffs(int, - int, - int const *, - Value const *) - { - } - - void LpSkeleton::_setColCoeffs(int, - int, - int const *, - Value const *) - { - } - - void LpSkeleton::_setCoeff(int, int, Value ) - { - } - - - void LpSkeleton::_setColLowerBound(int, Value) - { - } - - void LpSkeleton::_setColUpperBound(int, Value) - { - } - -// void LpSkeleton::_setRowLowerBound(int, Value) -// { -// } - -// void LpSkeleton::_setRowUpperBound(int, Value) -// { -// } - - void LpSkeleton::_setRowBounds(int, Value, Value) - { - } - - void LpSkeleton::_setObjCoeff(int, Value) - { - } - - void LpSkeleton::_setMax() - { - } - - void LpSkeleton::_setMin() - { - } - - void LpSkeleton::_clearObj() - { - } - - LpSkeleton::SolveExitStatus LpSkeleton::_solve() - { - return SOLVED; - } - - LpSkeleton::Value LpSkeleton::_getPrimal(int) - { - return 0; - } - - LpSkeleton::Value LpSkeleton::_getPrimalValue() - { - return 0; - } - - LpSkeleton::SolutionStatus LpSkeleton::_getPrimalStatus() - { - return OPTIMAL; - } - -} //namespace lemon - diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/lp_skeleton.h --- a/src/lemon/lp_skeleton.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/* -*- C++ -*- - * src/lemon/lp_skeleton.h - * - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_LP_SKELETON -#define LEMON_LP_SKELETON - -#include - -///\file -///\brief A skeleton file to implement LP solver interfaces -namespace lemon { - - ///A skeleton class to implement LP solver interfaces - class LpSkeleton :public LpSolverBase { - int col_num,row_num; - - protected: - ///\e - virtual LpSolverBase &_newLp(); - ///\e - virtual LpSolverBase &_copyLp(); - /// \e - virtual int _addCol(); - /// \e - virtual int _addRow(); - /// \e - virtual void _eraseCol(int i); - /// \e - virtual void _eraseRow(int i); - /// \e - - /// \warning Arrays are indexed from 1 (datum at index 0 is ignored) - /// - virtual void _setRowCoeffs(int i, - int length, - int const * indices, - Value const * values ); - /// \e - - /// \warning Arrays are indexed from 1 (datum at index 0 is ignored) - /// - virtual void _setColCoeffs(int i, - int length, - int const * indices, - Value const * values ); - - /// Set one element of the coefficient matrix - virtual void _setCoeff(int row, int col, Value value); - - /// The lower bound of a variable (column) have to be given by an - /// extended number of type Value, i.e. a finite number of type - /// Value or -\ref INF. - virtual void _setColLowerBound(int i, Value value); - /// \e - - /// The upper bound of a variable (column) have to be given by an - /// extended number of type Value, i.e. a finite number of type - /// Value or \ref INF. - virtual void _setColUpperBound(int i, Value value); - /// \e - -// /// The lower bound of a linear expression (row) have to be given by an -// /// extended number of type Value, i.e. a finite number of type -// /// Value or -\ref INF. -// virtual void _setRowLowerBound(int i, Value value); -// /// \e - -// /// The upper bound of a linear expression (row) have to be given by an -// /// extended number of type Value, i.e. a finite number of type -// /// Value or \ref INF. -// virtual void _setRowUpperBound(int i, Value value); - - /// The lower and upper bound of a linear expression (row) have to be - /// given by an - /// extended number of type Value, i.e. a finite number of type - /// Value or +/-\ref INF. - virtual void _setRowBounds(int i, Value lb, Value ub); - /// \e - - - /// \e - virtual void _clearObj(); - /// \e - virtual void _setObjCoeff(int i, Value obj_coef); - - ///\e - - ///\bug Wrong interface - /// - virtual SolveExitStatus _solve(); - - ///\e - - ///\bug Wrong interface - /// - virtual Value _getPrimal(int i); - ///\e - - ///\bug Wrong interface - /// - virtual Value _getPrimalValue(); - ///\e - - ///\bug Wrong interface - /// - virtual SolutionStatus _getPrimalStatus(); - - ///\e - virtual void _setMax(); - ///\e - virtual void _setMin(); - - - public: - LpSkeleton() : LpSolverBase(), col_num(0), row_num(0) {} - }; - -} //namespace lemon - -#endif // LEMON_LP_SKELETON diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/maps.h --- a/src/lemon/maps.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,841 +0,0 @@ -/* -*- C++ -*- - * src/lemon/maps.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_MAPS_H -#define LEMON_MAPS_H - -#include -#include - - -///\file -///\ingroup maps -///\brief Miscellaneous property maps -/// -///\todo This file has the same name as the concept file in concept/, -/// and this is not easily detectable in docs... - -#include - -namespace lemon { - - /// \addtogroup maps - /// @{ - - /// Base class of maps. - - /// Base class of maps. - /// It provides the necessary typedefs required by the map concept. - template - class MapBase - { - public: - ///\e - typedef K Key; - ///\e - typedef T Value; - }; - - /// Null map. (a.k.a. DoNothingMap) - - /// If you have to provide a map only for its type definitions, - /// or if you have to provide a writable map, but - /// data written to it will sent to /dev/null... - template - class NullMap : public MapBase - { - public: - - typedef True NeedCopy; - - /// Gives back a default constructed element. - T operator[](const K&) const { return T(); } - /// Absorbs the value. - void set(const K&, const T&) {} - }; - - template - NullMap nullMap() { - return NullMap(); - } - - - /// Constant map. - - /// This is a readable map which assigns a specified value to each key. - /// In other aspects it is equivalent to the \ref NullMap. - /// \todo set could be used to set the value. - template - class ConstMap : public MapBase - { - T v; - public: - - typedef True NeedCopy; - - /// Default constructor - - /// The value of the map will be uninitialized. - /// (More exactly it will be default constructed.) - ConstMap() {} - ///\e - - /// \param _v The initial value of the map. - /// - ConstMap(const T &_v) : v(_v) {} - - T operator[](const K&) const { return v; } - void set(const K&, const T&) {} - - template - struct rebind { - typedef ConstMap other; - }; - - template - ConstMap(const ConstMap &, const T &_v) : v(_v) {} - }; - - ///Returns a \ref ConstMap class - - ///This function just returns a \ref ConstMap class. - ///\relates ConstMap - template - inline ConstMap constMap(const K &k) - { - return ConstMap(k); - } - - - //to document later - template - struct Const { }; - //to document later - template - class ConstMap > : public MapBase - { - public: - ConstMap() { } - V operator[](const K&) const { return v; } - void set(const K&, const V&) { } - }; - - /// \c std::map wrapper - - /// This is essentially a wrapper for \c std::map. With addition that - /// you can specify a default value different from \c Value() . - /// - /// \todo Provide allocator parameter... - template > - class StdMap : public std::map { - typedef std::map parent; - T v; - typedef typename parent::value_type PairType; - - public: - typedef K Key; - typedef T Value; - typedef T& Reference; - typedef const T& ConstReference; - - - StdMap() : v() {} - /// Constructor with specified default value - StdMap(const T& _v) : v(_v) {} - - /// \brief Constructs the map from an appropriate std::map. - /// - /// \warning Inefficient: copies the content of \c m ! - StdMap(const parent &m) : parent(m) {} - /// \brief Constructs the map from an appropriate std::map, and explicitly - /// specifies a default value. - /// - /// \warning Inefficient: copies the content of \c m ! - StdMap(const parent &m, const T& _v) : parent(m), v(_v) {} - - template - StdMap(const StdMap &m, const T &_v) { - //FIXME; - } - - Reference operator[](const Key &k) { - return insert(PairType(k,v)).first -> second; - } - ConstReference operator[](const Key &k) const { - typename parent::iterator i = lower_bound(k); - if (i == parent::end() || parent::key_comp()(k, (*i).first)) - return v; - return (*i).second; - } - void set(const Key &k, const T &t) { - parent::operator[](k) = t; - } - - /// Changes the default value of the map. - /// \return Returns the previous default value. - /// - /// \warning The value of some keys (which has already been queried, but - /// the value has been unchanged from the default) may change! - T setDefault(const T &_v) { T old=v; v=_v; return old; } - - template - struct rebind { - typedef StdMap other; - }; - }; - - /// @} - - /// \addtogroup map_adaptors - /// @{ - - - ///Convert the \c Value of a maps to another type. - - ///This \ref concept::ReadMap "read only map" - ///converts the \c Value of a maps to type \c T. - ///Its \c Value is inherited from \c M. - /// - ///Actually, - ///\code - /// ConvertMap sh(x,v); - ///\endcode - ///it is equivalent with - ///\code - /// ConstMap c_tmp(v); - /// AddMap > sh(x,v); - ///\endcode - ///\bug wrong documentation - template - class ConvertMap { - typename SmartConstReference::Type m; - public: - - typedef True NeedCopy; - - typedef typename M::Key Key; - typedef T Value; - - ///Constructor - - ///Constructor - ///\param _m is the undelying map - ///\param _v is the convert value - ConvertMap(const M &_m) : m(_m) {}; - - /// \brief The subscript operator. - /// - /// The subscript operator. - /// \param edge The edge - /// \return The target of the edge - Value operator[](Key k) const {return m[k];} - }; - - ///Returns an \ref ConvertMap class - - ///This function just returns an \ref ConvertMap class. - ///\relates ConvertMap - ///\todo The order of the template parameters are changed. - template - inline ConvertMap convertMap(const M &m) - { - return ConvertMap(m); - } - - ///Sum of two maps - - ///This \ref concept::ReadMap "read only map" returns the sum of the two - ///given maps. Its \c Key and \c Value will be inherited from \c M1. - ///The \c Key and \c Value of M2 must be convertible to those of \c M1. - - template - class AddMap - { - typename SmartConstReference::Type m1; - typename SmartConstReference::Type m2; - - public: - - typedef True NeedCopy; - - typedef typename M1::Key Key; - typedef typename M1::Value Value; - - ///Constructor - - ///\e - /// - AddMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; - Value operator[](Key k) const {return m1[k]+m2[k];} - }; - - ///Returns an \ref AddMap class - - ///This function just returns an \ref AddMap class. - ///\todo How to call these type of functions? - /// - ///\relates AddMap - ///\todo Wrong scope in Doxygen when \c \\relates is used - template - inline AddMap addMap(const M1 &m1,const M2 &m2) - { - return AddMap(m1,m2); - } - - ///Shift a maps with a constant. - - ///This \ref concept::ReadMap "read only map" returns the sum of the - ///given map and a constant value. - ///Its \c Key and \c Value is inherited from \c M. - /// - ///Actually, - ///\code - /// ShiftMap sh(x,v); - ///\endcode - ///it is equivalent with - ///\code - /// ConstMap c_tmp(v); - /// AddMap > sh(x,v); - ///\endcode - template - class ShiftMap - { - typename SmartConstReference::Type m; - typename M::Value v; - public: - - typedef True NeedCopy; - typedef typename M::Key Key; - typedef typename M::Value Value; - - ///Constructor - - ///Constructor - ///\param _m is the undelying map - ///\param _v is the shift value - ShiftMap(const M &_m,const Value &_v ) : m(_m), v(_v) {}; - Value operator[](Key k) const {return m[k]+v;} - }; - - ///Returns an \ref ShiftMap class - - ///This function just returns an \ref ShiftMap class. - ///\relates ShiftMap - ///\todo A better name is required. - template - inline ShiftMap shiftMap(const M &m,const typename M::Value &v) - { - return ShiftMap(m,v); - } - - ///Difference of two maps - - ///This \ref concept::ReadMap "read only map" returns the difference - ///of the values returned by the two - ///given maps. Its \c Key and \c Value will be inherited from \c M1. - ///The \c Key and \c Value of \c M2 must be convertible to those of \c M1. - - template - class SubMap - { - typename SmartConstReference::Type m1; - typename SmartConstReference::Type m2; - public: - - typedef True NeedCopy; - typedef typename M1::Key Key; - typedef typename M1::Value Value; - - ///Constructor - - ///\e - /// - SubMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; - Value operator[](Key k) const {return m1[k]-m2[k];} - }; - - ///Returns a \ref SubMap class - - ///This function just returns a \ref SubMap class. - /// - ///\relates SubMap - template - inline SubMap subMap(const M1 &m1,const M2 &m2) - { - return SubMap(m1,m2); - } - - ///Product of two maps - - ///This \ref concept::ReadMap "read only map" returns the product of the - ///values returned by the two - ///given - ///maps. Its \c Key and \c Value will be inherited from \c M1. - ///The \c Key and \c Value of \c M2 must be convertible to those of \c M1. - - template - class MulMap - { - typename SmartConstReference::Type m1; - typename SmartConstReference::Type m2; - public: - - typedef True NeedCopy; - typedef typename M1::Key Key; - typedef typename M1::Value Value; - - ///Constructor - - ///\e - /// - MulMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; - Value operator[](Key k) const {return m1[k]*m2[k];} - }; - - ///Returns a \ref MulMap class - - ///This function just returns a \ref MulMap class. - ///\relates MulMap - template - inline MulMap mulMap(const M1 &m1,const M2 &m2) - { - return MulMap(m1,m2); - } - - ///Scale a maps with a constant. - - ///This \ref concept::ReadMap "read only map" returns the value of the - ///given map multipied with a constant value. - ///Its \c Key and \c Value is inherited from \c M. - /// - ///Actually, - ///\code - /// ScaleMap sc(x,v); - ///\endcode - ///it is equivalent with - ///\code - /// ConstMap c_tmp(v); - /// MulMap > sc(x,v); - ///\endcode - template - class ScaleMap - { - typename SmartConstReference::Type m; - typename M::Value v; - public: - - typedef True NeedCopy; - typedef typename M::Key Key; - typedef typename M::Value Value; - - ///Constructor - - ///Constructor - ///\param _m is the undelying map - ///\param _v is the scaling value - ScaleMap(const M &_m,const Value &_v ) : m(_m), v(_v) {}; - Value operator[](Key k) const {return m[k]*v;} - }; - - ///Returns an \ref ScaleMap class - - ///This function just returns an \ref ScaleMap class. - ///\relates ScaleMap - ///\todo A better name is required. - template - inline ScaleMap scaleMap(const M &m,const typename M::Value &v) - { - return ScaleMap(m,v); - } - - ///Quotient of two maps - - ///This \ref concept::ReadMap "read only map" returns the quotient of the - ///values returned by the two - ///given maps. Its \c Key and \c Value will be inherited from \c M1. - ///The \c Key and \c Value of \c M2 must be convertible to those of \c M1. - - template - class DivMap - { - typename SmartConstReference::Type m1; - typename SmartConstReference::Type m2; - public: - - typedef True NeedCopy; - typedef typename M1::Key Key; - typedef typename M1::Value Value; - - ///Constructor - - ///\e - /// - DivMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; - Value operator[](Key k) const {return m1[k]/m2[k];} - }; - - ///Returns a \ref DivMap class - - ///This function just returns a \ref DivMap class. - ///\relates DivMap - template - inline DivMap divMap(const M1 &m1,const M2 &m2) - { - return DivMap(m1,m2); - } - - ///Composition of two maps - - ///This \ref concept::ReadMap "read only map" returns the composition of - ///two - ///given maps. That is to say, if \c m1 is of type \c M1 and \c m2 is - ///of \c M2, - ///then for - ///\code - /// ComposeMap cm(m1,m2); - ///\endcode - /// cm[x] will be equal to m1[m2[x]] - /// - ///Its \c Key is inherited from \c M2 and its \c Value is from - ///\c M1. - ///The \c M2::Value must be convertible to \c M1::Key. - ///\todo Check the requirements. - - template - class ComposeMap - { - typename SmartConstReference::Type m1; - typename SmartConstReference::Type m2; - public: - - typedef True NeedCopy; - typedef typename M2::Key Key; - typedef typename M1::Value Value; - - typedef True NeedCopy; - - ///Constructor - - ///\e - /// - ComposeMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; - Value operator[](Key k) const {return m1[m2[k]];} - }; - ///Returns a \ref ComposeMap class - - ///This function just returns a \ref ComposeMap class. - /// - ///\relates ComposeMap - template - inline ComposeMap composeMap(const M1 &m1,const M2 &m2) - { - return ComposeMap(m1,m2); - } - - ///Combine of two maps using an STL (binary) functor. - - ///Combine of two maps using an STL (binary) functor. - /// - /// - ///This \ref concept::ReadMap "read only map" takes to maps and a - ///binary functor and returns the composition of - ///two - ///given maps unsing the functor. - ///That is to say, if \c m1 and \c m2 is of type \c M1 and \c M2 - ///and \c f is of \c F, - ///then for - ///\code - /// CombineMap cm(m1,m2,f); - ///\endcode - /// cm[x] will be equal to f(m1[x],m2[x]) - /// - ///Its \c Key is inherited from \c M1 and its \c Value is \c V. - ///The \c M2::Value and \c M1::Value must be convertible to the corresponding - ///input parameter of \c F and the return type of \c F must be convertible - ///to \c V. - ///\todo Check the requirements. - - template - class CombineMap - { - typename SmartConstReference::Type m1; - typename SmartConstReference::Type m2; - F f; - public: - - typedef True NeedCopy; - typedef typename M1::Key Key; - typedef V Value; - - ///Constructor - - ///\e - /// - CombineMap(const M1 &_m1,const M2 &_m2,const F &_f) - : m1(_m1), m2(_m2), f(_f) {}; - Value operator[](Key k) const {return f(m1[k],m2[k]);} - }; - - ///Returns a \ref CombineMap class - - ///This function just returns a \ref CombineMap class. - /// - ///Only the first template parameter (the value type) must be given. - /// - ///For example if \c m1 and \c m2 are both \c double valued maps, then - ///\code - ///combineMap(m1,m2,std::plus) - ///\endcode - ///is equivalent with - ///\code - ///addMap(m1,m2) - ///\endcode - /// - ///\relates CombineMap - template - inline CombineMap combineMap(const M1 &m1,const M2 &m2,const F &f) - { - return CombineMap(m1,m2,f); - } - - ///Negative value of a map - - ///This \ref concept::ReadMap "read only map" returns the negative - ///value of the - ///value returned by the - ///given map. Its \c Key and \c Value will be inherited from \c M. - ///The unary \c - operator must be defined for \c Value, of course. - - template - class NegMap - { - typename SmartConstReference::Type m; - public: - - typedef True NeedCopy; - typedef typename M::Key Key; - typedef typename M::Value Value; - - ///Constructor - - ///\e - /// - NegMap(const M &_m) : m(_m) {}; - Value operator[](Key k) const {return -m[k];} - }; - - ///Returns a \ref NegMap class - - ///This function just returns a \ref NegMap class. - ///\relates NegMap - template - inline NegMap negMap(const M &m) - { - return NegMap(m); - } - - - ///Absolute value of a map - - ///This \ref concept::ReadMap "read only map" returns the absolute value - ///of the - ///value returned by the - ///given map. Its \c Key and \c Value will be inherited - ///from M. Value - ///must be comparable to 0 and the unary - - ///operator must be defined for it, of course. - /// - ///\bug We need a unified way to handle the situation below: - ///\code - /// struct _UnConvertible {}; - /// template inline A t_abs(A a) {return _UnConvertible();} - /// template<> inline int t_abs<>(int n) {return abs(n);} - /// template<> inline long int t_abs<>(long int n) {return labs(n);} - /// template<> inline long long int t_abs<>(long long int n) {return ::llabs(n);} - /// template<> inline float t_abs<>(float n) {return fabsf(n);} - /// template<> inline double t_abs<>(double n) {return fabs(n);} - /// template<> inline long double t_abs<>(long double n) {return fabsl(n);} - ///\endcode - - - template - class AbsMap - { - typename SmartConstReference::Type m; - public: - - typedef True NeedCopy; - typedef typename M::Key Key; - typedef typename M::Value Value; - - ///Constructor - - ///\e - /// - AbsMap(const M &_m) : m(_m) {}; - Value operator[](Key k) const {Value tmp=m[k]; return tmp>=0?tmp:-tmp;} - }; - - ///Returns a \ref AbsMap class - - ///This function just returns a \ref AbsMap class. - ///\relates AbsMap - template - inline AbsMap absMap(const M &m) - { - return AbsMap(m); - } - - ///Converts an STL style functor to a map - - ///This \ref concept::ReadMap "read only map" returns the value - ///of a - ///given map. - /// - ///Template parameters \c K and \c V will become its - ///\c Key and \c Value. They must be given explicitely - ///because a functor does not provide such typedefs. - /// - ///Parameter \c F is the type of the used functor. - - - template - class FunctorMap - { - const F &f; - public: - - typedef True NeedCopy; - typedef K Key; - typedef V Value; - - ///Constructor - - ///\e - /// - FunctorMap(const F &_f) : f(_f) {}; - Value operator[](Key k) const {return f(k);} - }; - - ///Returns a \ref FunctorMap class - - ///This function just returns a \ref FunctorMap class. - /// - ///The third template parameter isn't necessary to be given. - ///\relates FunctorMap - template - inline FunctorMap functorMap(const F &f) - { - return FunctorMap(f); - } - - ///Converts a map to an STL style (unary) functor - - ///This class Converts a map to an STL style (unary) functor. - ///that is it provides an operator() to read its values. - /// - ///For the sake of convenience it also works as - ///a ususal \ref concept::ReadMap "readable map", i.e - ///operator[] and the \c Key and \c Value typedefs also exist. - - template - class MapFunctor - { - typename SmartConstReference::Type m; - public: - - typedef True NeedCopy; - typedef typename M::Key argument_type; - typedef typename M::Value result_type; - typedef typename M::Key Key; - typedef typename M::Value Value; - - ///Constructor - - ///\e - /// - MapFunctor(const M &_m) : m(_m) {}; - ///Returns a value of the map - - ///\e - /// - Value operator()(Key k) const {return m[k];} - ///\e - /// - Value operator[](Key k) const {return m[k];} - }; - - ///Returns a \ref MapFunctor class - - ///This function just returns a \ref MapFunctor class. - ///\relates MapFunctor - template - inline MapFunctor mapFunctor(const M &m) - { - return MapFunctor(m); - } - - - ///Apply all map setting operations to two maps - - ///This map has two \ref concept::WriteMap "writable map" - ///parameters and each write request will be passed to both of them. - ///If \c M1 is also \ref concept::ReadMap "readable", - ///then the read operations will return the - ///corresponding values of \c M1. - /// - ///The \c Key and \c Value will be inherited from \c M1. - ///The \c Key and \c Value of M2 must be convertible from those of \c M1. - - template - class ForkMap - { - typename SmartConstReference::Type m1; - typename SmartConstReference::Type m2; - public: - - typedef True NeedCopy; - typedef typename M1::Key Key; - typedef typename M1::Value Value; - - ///Constructor - - ///\e - /// - ForkMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {}; - Value operator[](Key k) const {return m1[k];} - void set(Key k,const Value &v) {m1.set(k,v); m2.set(k,v);} - }; - - ///Returns an \ref ForkMap class - - ///This function just returns an \ref ForkMap class. - ///\todo How to call these type of functions? - /// - ///\relates ForkMap - ///\todo Wrong scope in Doxygen when \c \\relates is used - template - inline ForkMap forkMap(const M1 &m1,const M2 &m2) - { - return ForkMap(m1,m2); - } - - /// @} - -} - - -#endif // LEMON_MAPS_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/max_matching.h --- a/src/lemon/max_matching.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,583 +0,0 @@ -/* -*- C++ -*- - * src/lemon/max_matching.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_MAX_MATCHING_H -#define LEMON_MAX_MATCHING_H - -#include -#include -#include -#include - -///\ingroup galgs -///\file -///\brief Maximum matching algorithm. - -namespace lemon { - - /// \addtogroup galgs - /// @{ - - ///Edmonds' alternating forest maximum matching algorithm. - - ///This class provides Edmonds' alternating forest matching - ///algorithm. The starting matching (if any) can be passed to the - ///algorithm using read-in functions \ref readNMapNode, \ref - ///readNMapEdge or \ref readEMapBool depending on the container. The - ///resulting maximum matching can be attained by write-out functions - ///\ref writeNMapNode, \ref writeNMapEdge or \ref writeEMapBool - ///depending on the preferred container. - /// - ///The dual side of a matching is a map of the nodes to - ///MaxMatching::pos_enum, having values D, A and C showing the - ///Gallai-Edmonds decomposition of the graph. The nodes in D induce - ///a graph with factor-critical components, the nodes in A form the - ///barrier, and the nodes in C induce a graph having a perfect - ///matching. This decomposition can be attained by calling \ref - ///writePos after running the algorithm. - /// - ///\param Graph The undirected graph type the algorithm runs on. - /// - ///\author Jacint Szabo - template - class MaxMatching { - - protected: - - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - typedef typename Graph::UndirEdge UndirEdge; - typedef typename Graph::UndirEdgeIt UndirEdgeIt; - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::IncEdgeIt IncEdgeIt; - - typedef UnionFindEnum UFE; - - public: - - ///Indicates the Gallai-Edmonds decomposition of the graph. - - ///Indicates the Gallai-Edmonds decomposition of the graph, which - ///shows an upper bound on the size of a maximum matching. The - ///nodes with pos_enum \c D induce a graph with factor-critical - ///components, the nodes in \c A form the canonical barrier, and the - ///nodes in \c C induce a graph having a perfect matching. - enum pos_enum { - D=0, - A=1, - C=2 - }; - - protected: - - static const int HEUR_density=2; - const Graph& g; - typename Graph::template NodeMap _mate; - typename Graph::template NodeMap position; - - public: - - MaxMatching(const Graph& _g) : g(_g), _mate(_g,INVALID), position(_g) {} - - ///Runs Edmonds' algorithm. - - ///Runs Edmonds' algorithm for sparse graphs (number of edges < - ///2*number of nodes), and a heuristical Edmonds' algorithm with a - ///heuristic of postponing shrinks for dense graphs. - inline void run(); - - ///Runs Edmonds' algorithm. - - ///If heur=0 it runs Edmonds' algorithm. If heur=1 it runs - ///Edmonds' algorithm with a heuristic of postponing shrinks, - ///giving a faster algorithm for dense graphs. - void runEdmonds( int heur ); - - ///Finds a greedy matching starting from the actual matching. - - ///Starting form the actual matching stored, it finds a maximal - ///greedy matching. - void greedyMatching(); - - ///Returns the size of the actual matching stored. - - ///Returns the size of the actual matching stored. After \ref - ///run() it returns the size of a maximum matching in the graph. - int size() const; - - ///Resets the actual matching to the empty matching. - - ///Resets the actual matching to the empty matching. - /// - void resetMatching(); - - ///Returns the mate of a node in the actual matching. - - ///Returns the mate of a \c node in the actual matching. - ///Returns INVALID if the \c node is not covered by the actual matching. - Node mate(Node& node) const { - return _mate[node]; - } - - ///Reads a matching from a \c Node valued \c Node map. - - ///Reads a matching from a \c Node valued \c Node map. This map - ///must be \e symmetric, i.e. if \c map[u]==v then \c map[v]==u - ///must hold, and \c uv will be an edge of the matching. - template - void readNMapNode(NMapN& map) { - for(NodeIt v(g); v!=INVALID; ++v) { - _mate.set(v,map[v]); - } - } - - ///Writes the stored matching to a \c Node valued \c Node map. - - ///Writes the stored matching to a \c Node valued \c Node map. The - ///resulting map will be \e symmetric, i.e. if \c map[u]==v then \c - ///map[v]==u will hold, and now \c uv is an edge of the matching. - template - void writeNMapNode (NMapN& map) const { - for(NodeIt v(g); v!=INVALID; ++v) { - map.set(v,_mate[v]); - } - } - - ///Reads a matching from an \c UndirEdge valued \c Node map. - - ///Reads a matching from an \c UndirEdge valued \c Node map. \c - ///map[v] must be an \c UndirEdge incident to \c v. This map must - ///have the property that if \c g.oppositeNode(u,map[u])==v then - ///\c \c g.oppositeNode(v,map[v])==u holds, and now some edge - ///joining \c u to \c v will be an edge of the matching. - template - void readNMapEdge(NMapE& map) { - for(NodeIt v(g); v!=INVALID; ++v) { - UndirEdge e=map[v]; - if ( e!=INVALID ) - _mate.set(v,g.oppositeNode(v,e)); - } - } - - ///Writes the matching stored to an \c UndirEdge valued \c Node map. - - ///Writes the stored matching to an \c UndirEdge valued \c Node - ///map. \c map[v] will be an \c UndirEdge incident to \c v. This - ///map will have the property that if \c g.oppositeNode(u,map[u]) - ///== v then \c map[u]==map[v] holds, and now this edge is an edge - ///of the matching. - template - void writeNMapEdge (NMapE& map) const { - typename Graph::template NodeMap todo(g,true); - for(NodeIt v(g); v!=INVALID; ++v) { - if ( todo[v] && _mate[v]!=INVALID ) { - Node u=_mate[v]; - for(IncEdgeIt e(g,v); e!=INVALID; ++e) { - if ( g.runningNode(e) == u ) { - map.set(u,e); - map.set(v,e); - todo.set(u,false); - todo.set(v,false); - break; - } - } - } - } - } - - - ///Reads a matching from a \c bool valued \c Edge map. - - ///Reads a matching from a \c bool valued \c Edge map. This map - ///must have the property that there are no two incident edges \c - ///e, \c f with \c map[e]==map[f]==true. The edges \c e with \c - ///map[e]==true form the matching. - template - void readEMapBool(EMapB& map) { - for(UndirEdgeIt e(g); e!=INVALID; ++e) { - if ( map[e] ) { - Node u=g.source(e); - Node v=g.target(e); - _mate.set(u,v); - _mate.set(v,u); - } - } - } - - - ///Writes the matching stored to a \c bool valued \c Edge map. - - ///Writes the matching stored to a \c bool valued \c Edge - ///map. This map will have the property that there are no two - ///incident edges \c e, \c f with \c map[e]==map[f]==true. The - ///edges \c e with \c map[e]==true form the matching. - template - void writeEMapBool (EMapB& map) const { - for(UndirEdgeIt e(g); e!=INVALID; ++e) map.set(e,false); - - typename Graph::template NodeMap todo(g,true); - for(NodeIt v(g); v!=INVALID; ++v) { - if ( todo[v] && _mate[v]!=INVALID ) { - Node u=_mate[v]; - for(IncEdgeIt e(g,v); e!=INVALID; ++e) { - if ( g.runningNode(e) == u ) { - map.set(e,true); - todo.set(u,false); - todo.set(v,false); - break; - } - } - } - } - } - - - ///Writes the canonical decomposition of the graph after running - ///the algorithm. - - ///After calling any run methods of the class, it writes the - ///Gallai-Edmonds canonical decomposition of the graph. \c map - ///must be a node map of \ref pos_enum 's. - template - void writePos (NMapEnum& map) const { - for(NodeIt v(g); v!=INVALID; ++v) map.set(v,position[v]); - } - - private: - - - void lateShrink(Node v, typename Graph::template NodeMap& ear, - UFE& blossom, UFE& tree); - - void normShrink(Node v, typename Graph::template NodeMap& ear, - UFE& blossom, UFE& tree); - - bool noShrinkStep(Node x, typename Graph::template NodeMap& ear, - UFE& blossom, UFE& tree, std::queue& Q); - - void shrinkStep(Node& top, Node& middle, Node& bottom, - typename Graph::template NodeMap& ear, - UFE& blossom, UFE& tree, std::queue& Q); - - void augment(Node x, typename Graph::template NodeMap& ear, - UFE& blossom, UFE& tree); - - }; - - - // ********************************************************************** - // IMPLEMENTATIONS - // ********************************************************************** - - - template - void MaxMatching::run() { - if ( countUndirEdges(g) < HEUR_density*countNodes(g) ) { - greedyMatching(); - runEdmonds(0); - } else runEdmonds(1); - } - - - template - void MaxMatching::runEdmonds( int heur=1 ) { - - for(NodeIt v(g); v!=INVALID; ++v) - position.set(v,C); - - typename Graph::template NodeMap ear(g,INVALID); - //undefined for the base nodes of the blossoms (i.e. for the - //representative elements of UFE blossom) and for the nodes in C - - typename UFE::MapType blossom_base(g); - UFE blossom(blossom_base); - typename UFE::MapType tree_base(g); - UFE tree(tree_base); - //If these UFE's would be members of the class then also - //blossom_base and tree_base should be a member. - - for(NodeIt v(g); v!=INVALID; ++v) { - if ( position[v]==C && _mate[v]==INVALID ) { - blossom.insert(v); - tree.insert(v); - position.set(v,D); - if ( heur == 1 ) lateShrink( v, ear, blossom, tree ); - else normShrink( v, ear, blossom, tree ); - } - } - } - - - template - void MaxMatching::lateShrink(Node v, typename Graph::template NodeMap& ear, - UFE& blossom, UFE& tree) { - - std::queue Q; //queue of the totally unscanned nodes - Q.push(v); - std::queue R; - //queue of the nodes which must be scanned for a possible shrink - - while ( !Q.empty() ) { - Node x=Q.front(); - Q.pop(); - if ( noShrinkStep( x, ear, blossom, tree, Q ) ) return; - else R.push(x); - } - - while ( !R.empty() ) { - Node x=R.front(); - R.pop(); - - for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) { - Node y=g.runningNode(e); - - if ( position[y] == D && blossom.find(x) != blossom.find(y) ) { - //x and y must be in the same tree - - typename Graph::template NodeMap path(g,false); - - Node b=blossom.find(x); - path.set(b,true); - b=_mate[b]; - while ( b!=INVALID ) { - b=blossom.find(ear[b]); - path.set(b,true); - b=_mate[b]; - } //going till the root - - Node top=y; - Node middle=blossom.find(top); - Node bottom=x; - while ( !path[middle] ) - shrinkStep(top, middle, bottom, ear, blossom, tree, Q); - - Node base=middle; - top=x; - middle=blossom.find(top); - bottom=y; - Node blossom_base=blossom.find(base); - while ( middle!=blossom_base ) - shrinkStep(top, middle, bottom, ear, blossom, tree, Q); - - blossom.makeRep(base); - } // if shrink is needed - - while ( !Q.empty() ) { - Node x=Q.front(); - Q.pop(); - if ( noShrinkStep(x, ear, blossom, tree, Q) ) return; - else R.push(x); - } - } //for e - } // while ( !R.empty() ) - } - - - template - void MaxMatching::normShrink(Node v, - typename Graph::template - NodeMap& ear, - UFE& blossom, UFE& tree) { - std::queue Q; //queue of the unscanned nodes - Q.push(v); - while ( !Q.empty() ) { - - Node x=Q.front(); - Q.pop(); - - for( IncEdgeIt e(g,x); e!=INVALID; ++e ) { - Node y=g.runningNode(e); - - switch ( position[y] ) { - case D: //x and y must be in the same tree - - if ( blossom.find(x) != blossom.find(y) ) { //shrink - typename Graph::template NodeMap path(g,false); - - Node b=blossom.find(x); - path.set(b,true); - b=_mate[b]; - while ( b!=INVALID ) { - b=blossom.find(ear[b]); - path.set(b,true); - b=_mate[b]; - } //going till the root - - Node top=y; - Node middle=blossom.find(top); - Node bottom=x; - while ( !path[middle] ) - shrinkStep(top, middle, bottom, ear, blossom, tree, Q); - - Node base=middle; - top=x; - middle=blossom.find(top); - bottom=y; - Node blossom_base=blossom.find(base); - while ( middle!=blossom_base ) - shrinkStep(top, middle, bottom, ear, blossom, tree, Q); - - blossom.makeRep(base); - } - break; - case C: - if ( _mate[y]!=INVALID ) { //grow - - ear.set(y,x); - Node w=_mate[y]; - blossom.insert(w); - position.set(y,A); - position.set(w,D); - tree.insert(y); - tree.insert(w); - tree.join(y,blossom.find(x)); - tree.join(w,y); - Q.push(w); - } else { //augment - augment(x, ear, blossom, tree); - _mate.set(x,y); - _mate.set(y,x); - return; - } //if - break; - default: break; - } - } - } - } - - template - void MaxMatching::greedyMatching() { - for(NodeIt v(g); v!=INVALID; ++v) - if ( _mate[v]==INVALID ) { - for( IncEdgeIt e(g,v); e!=INVALID ; ++e ) { - Node y=g.runningNode(e); - if ( _mate[y]==INVALID && y!=v ) { - _mate.set(v,y); - _mate.set(y,v); - break; - } - } - } - } - - template - int MaxMatching::size() const { - int s=0; - for(NodeIt v(g); v!=INVALID; ++v) { - if ( _mate[v]!=INVALID ) { - ++s; - } - } - return s/2; - } - - template - void MaxMatching::resetMatching() { - for(NodeIt v(g); v!=INVALID; ++v) - _mate.set(v,INVALID); - } - - template - bool MaxMatching::noShrinkStep(Node x, - typename Graph::template - NodeMap& ear, - UFE& blossom, UFE& tree, - std::queue& Q) { - for( IncEdgeIt e(g,x); e!= INVALID; ++e ) { - Node y=g.runningNode(e); - - if ( position[y]==C ) { - if ( _mate[y]!=INVALID ) { //grow - ear.set(y,x); - Node w=_mate[y]; - blossom.insert(w); - position.set(y,A); - position.set(w,D); - tree.insert(y); - tree.insert(w); - tree.join(y,blossom.find(x)); - tree.join(w,y); - Q.push(w); - } else { //augment - augment(x, ear, blossom, tree); - _mate.set(x,y); - _mate.set(y,x); - return true; - } - } - } - return false; - } - - template - void MaxMatching::shrinkStep(Node& top, Node& middle, Node& bottom, - typename Graph::template - NodeMap& ear, - UFE& blossom, UFE& tree, - std::queue& Q) { - ear.set(top,bottom); - Node t=top; - while ( t!=middle ) { - Node u=_mate[t]; - t=ear[u]; - ear.set(t,u); - } - bottom=_mate[middle]; - position.set(bottom,D); - Q.push(bottom); - top=ear[bottom]; - Node oldmiddle=middle; - middle=blossom.find(top); - tree.erase(bottom); - tree.erase(oldmiddle); - blossom.insert(bottom); - blossom.join(bottom, oldmiddle); - blossom.join(top, oldmiddle); - } - - template - void MaxMatching::augment(Node x, - typename Graph::template NodeMap& ear, - UFE& blossom, UFE& tree) { - Node v=_mate[x]; - while ( v!=INVALID ) { - - Node u=ear[v]; - _mate.set(v,u); - Node tmp=v; - v=_mate[u]; - _mate.set(u,tmp); - } - typename UFE::ItemIt it; - for (tree.first(it,blossom.find(x)); tree.valid(it); tree.next(it)) { - if ( position[it] == D ) { - typename UFE::ItemIt b_it; - for (blossom.first(b_it,it); blossom.valid(b_it); blossom.next(b_it)) { - position.set( b_it ,C); - } - blossom.eraseClass(it); - } else position.set( it ,C); - } - tree.eraseClass(x); - - } - - /// @} - -} //END OF NAMESPACE LEMON - -#endif //LEMON_MAX_MATCHING_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/min_cost_flow.h --- a/src/lemon/min_cost_flow.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,260 +0,0 @@ -/* -*- C++ -*- - * src/lemon/min_cost_flow.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_MIN_COST_FLOW_H -#define LEMON_MIN_COST_FLOW_H - -///\ingroup flowalgs -///\file -///\brief An algorithm for finding a flow of value \c k (for small values of \c k) having minimal total cost - - -#include -#include -#include -#include - -namespace lemon { - -/// \addtogroup flowalgs -/// @{ - - ///\brief Implementation of an algorithm for finding a flow of value \c k - ///(for small values of \c k) having minimal total cost between 2 nodes - /// - /// - /// The class \ref lemon::MinCostFlow "MinCostFlow" implements an - /// algorithm for finding a flow of value \c k having minimal total - /// cost from a given source node to a given target node in an - /// edge-weighted directed graph. To this end, the edge-capacities - /// and edge-weights have to be nonnegative. The edge-capacities - /// should be integers, but the edge-weights can be integers, reals - /// or of other comparable numeric type. This algorithm is intended - /// to be used only for small values of \c k, since it is only - /// polynomial in k, not in the length of k (which is log k): in - /// order to find the minimum cost flow of value \c k it finds the - /// minimum cost flow of value \c i for every \c i between 0 and \c - /// k. - /// - ///\param Graph The directed graph type the algorithm runs on. - ///\param LengthMap The type of the length map. - ///\param CapacityMap The capacity map type. - /// - ///\author Attila Bernath - template - class MinCostFlow { - - typedef typename LengthMap::Value Length; - - //Warning: this should be integer type - typedef typename CapacityMap::Value Capacity; - - typedef typename Graph::Node Node; - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::Edge Edge; - typedef typename Graph::OutEdgeIt OutEdgeIt; - typedef typename Graph::template EdgeMap EdgeIntMap; - - typedef ResGraphAdaptor ResGW; - typedef typename ResGW::Edge ResGraphEdge; - - protected: - - const Graph& g; - const LengthMap& length; - const CapacityMap& capacity; - - EdgeIntMap flow; - typedef typename Graph::template NodeMap PotentialMap; - PotentialMap potential; - - Node s; - Node t; - - Length total_length; - - class ModLengthMap { - typedef typename Graph::template NodeMap NodeMap; - const ResGW& g; - const LengthMap &length; - const NodeMap &pot; - public : - typedef typename LengthMap::Key Key; - typedef typename LengthMap::Value Value; - - ModLengthMap(const ResGW& _g, - const LengthMap &_length, const NodeMap &_pot) : - g(_g), /*rev(_rev),*/ length(_length), pot(_pot) { } - - Value operator[](typename ResGW::Edge e) const { - if (g.forward(e)) - return length[e]-(pot[g.target(e)]-pot[g.source(e)]); - else - return -length[e]-(pot[g.target(e)]-pot[g.source(e)]); - } - - }; //ModLengthMap - - ResGW res_graph; - ModLengthMap mod_length; - Dijkstra dijkstra; - - public : - - /*! \brief The constructor of the class. - - \param _g The directed graph the algorithm runs on. - \param _length The length (weight or cost) of the edges. - \param _cap The capacity of the edges. - \param _s Source node. - \param _t Target node. - */ - MinCostFlow(Graph& _g, LengthMap& _length, CapacityMap& _cap, - Node _s, Node _t) : - g(_g), length(_length), capacity(_cap), flow(_g), potential(_g), - s(_s), t(_t), - res_graph(g, capacity, flow), - mod_length(res_graph, length, potential), - dijkstra(res_graph, mod_length) { - reset(); - } - - /*! Tries to augment the flow between s and t by 1. - The return value shows if the augmentation is successful. - */ - bool augment() { - dijkstra.run(s); - if (!dijkstra.reached(t)) { - - //Unsuccessful augmentation. - return false; - } else { - - //We have to change the potential - for(typename ResGW::NodeIt n(res_graph); n!=INVALID; ++n) - potential.set(n, potential[n]+dijkstra.distMap()[n]); - - //Augmenting on the shortest path - Node n=t; - ResGraphEdge e; - while (n!=s){ - e = dijkstra.pred(n); - n = dijkstra.predNode(n); - res_graph.augment(e,1); - //Let's update the total length - if (res_graph.forward(e)) - total_length += length[e]; - else - total_length -= length[e]; - } - - return true; - } - } - - /*! \brief Runs the algorithm. - - Runs the algorithm. - Returns k if there is a flow of value at least k from s to t. - Otherwise it returns the maximum value of a flow from s to t. - - \param k The value of the flow we are looking for. - - \todo May be it does make sense to be able to start with a nonzero - feasible primal-dual solution pair as well. - - \todo If the actual flow value is bigger than k, then everything is - cleared and the algorithm starts from zero flow. Is it a good approach? - */ - int run(int k) { - if (flowValue()>k) reset(); - while (flowValue() 0 && fl_e != 0) - return false; - if (mod_pot < 0 && fl_e != capacity[e]) - return false; - } - } - return true; - } - - }; //class MinCostFlow - - ///@} - -} //namespace lemon - -#endif //LEMON_MIN_COST_FLOW_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/path.h --- a/src/lemon/path.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,703 +0,0 @@ -/* -*- C++ -*- - * src/lemon/path.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -/** -@defgroup paths Path Structures -@ingroup datas -\brief Path structures implemented in LEMON. - -LEMON provides flexible data structures -to work with paths. - -All of them have the same interface, especially they can be built or extended -using a standard Builder subclass. This make is easy to have e.g. the Dijkstra -algorithm to store its result in any kind of path structure. - -\sa lemon::concept::Path - -*/ - -///\ingroup paths -///\file -///\brief Classes for representing paths in graphs. -/// -///\todo Iterators have obsolete style - -#ifndef LEMON_PATH_H -#define LEMON_PATH_H - -#include -#include -#include - -#include - -namespace lemon { - - /// \addtogroup paths - /// @{ - - - //! \brief A structure for representing directed paths in a graph. - //! - //! A structure for representing directed path in a graph. - //! \param Graph The graph type in which the path is. - //! \param DM DebugMode, defaults to DefaultDebugMode. - //! - //! In a sense, the path can be treated as a graph, for is has \c NodeIt - //! and \c EdgeIt with the same usage. These types converts to the \c Node - //! and \c Edge of the original graph. - //! - //! \todo Thoroughfully check all the range and consistency tests. - template - class DirPath { - public: - /// Edge type of the underlying graph. - typedef typename Graph::Edge GraphEdge; - /// Node type of the underlying graph. - typedef typename Graph::Node GraphNode; - class NodeIt; - class EdgeIt; - - protected: - const Graph *gr; - typedef std::vector Container; - Container edges; - - public: - - /// \param _G The graph in which the path is. - /// - DirPath(const Graph &_G) : gr(&_G) {} - - /// \brief Subpath constructor. - /// - /// Subpath defined by two nodes. - /// \warning It is an error if the two edges are not in order! - DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b) { - gr = P.gr; - edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); - } - - /// \brief Subpath constructor. - /// - /// Subpath defined by two edges. Contains edges in [a,b) - /// \warning It is an error if the two edges are not in order! - DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b) { - gr = P.gr; - edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); - } - - /// Length of the path. - int length() const { return edges.size(); } - /// Returns whether the path is empty. - bool empty() const { return edges.empty(); } - - /// Resets the path to an empty path. - void clear() { edges.clear(); } - - /// \brief Starting point of the path. - /// - /// Starting point of the path. - /// Returns INVALID if the path is empty. - GraphNode source() const { - return empty() ? INVALID : gr->source(edges[0]); - } - /// \brief End point of the path. - /// - /// End point of the path. - /// Returns INVALID if the path is empty. - GraphNode target() const { - return empty() ? INVALID : gr->target(edges[length()-1]); - } - - /// \brief Initializes node or edge iterator to point to the first - /// node or edge. - /// - /// \sa nth - template - It& first(It &i) const { return i=It(*this); } - - /// \brief Initializes node iterator to point to the node of a given index. - NodeIt& nth(NodeIt &i, int n) const { - return i=NodeIt(*this, n); - } - - /// \brief Initializes edge iterator to point to the edge of a given index. - EdgeIt& nth(EdgeIt &i, int n) const { - return i=EdgeIt(*this, n); - } - - /// \brief Returns node iterator pointing to the target node of the - /// given edge iterator. - NodeIt target(const EdgeIt& e) const { - return NodeIt(*this, e.idx+1); - } - - /// \brief Returns node iterator pointing to the source node of the - /// given edge iterator. - NodeIt source(const EdgeIt& e) const { - return NodeIt(*this, e.idx); - } - - - /* Iterator classes */ - - /** - * \brief Iterator class to iterate on the edges of the paths - * - * This class is used to iterate on the edges of the paths - * - * Of course it converts to Graph::Edge - * - */ - class EdgeIt { - friend class DirPath; - - int idx; - const DirPath *p; - public: - /// Default constructor - EdgeIt() {} - /// Invalid constructor - EdgeIt(Invalid) : idx(-1), p(0) {} - /// Constructor with starting point - EdgeIt(const DirPath &_p, int _idx = 0) : - idx(_idx), p(&_p) { validate(); } - - ///Validity check - bool valid() const { return idx!=-1; } - - ///Conversion to Graph::Edge - operator GraphEdge () const { - return valid() ? p->edges[idx] : INVALID; - } - - /// Next edge - EdgeIt& operator++() { ++idx; validate(); return *this; } - - /// Comparison operator - bool operator==(const EdgeIt& e) const { return idx==e.idx; } - /// Comparison operator - bool operator!=(const EdgeIt& e) const { return idx!=e.idx; } - /// Comparison operator - bool operator<(const EdgeIt& e) const { return idx= p->length() ) idx=-1; } - }; - - /** - * \brief Iterator class to iterate on the nodes of the paths - * - * This class is used to iterate on the nodes of the paths - * - * Of course it converts to Graph::Node - * - */ - class NodeIt { - friend class DirPath; - - int idx; - const DirPath *p; - public: - /// Default constructor - NodeIt() {} - /// Invalid constructor - NodeIt(Invalid) : idx(-1), p(0) {} - /// Constructor with starting point - NodeIt(const DirPath &_p, int _idx = 0) : - idx(_idx), p(&_p) { validate(); } - - ///Validity check - bool valid() const { return idx!=-1; } - - ///Conversion to Graph::Node - operator const GraphNode& () const { - if(idx >= p->length()) - return p->target(); - else if(idx >= 0) - return p->gr->source(p->edges[idx]); - else - return INVALID; - } - /// Next node - NodeIt& operator++() { ++idx; validate(); return *this; } - - /// Comparison operator - bool operator==(const NodeIt& e) const { return idx==e.idx; } - /// Comparison operator - bool operator!=(const NodeIt& e) const { return idx!=e.idx; } - /// Comparison operator - bool operator<(const NodeIt& e) const { return idx p->length() ) idx=-1; } - }; - - friend class Builder; - - /** - * \brief Class to build paths - * - * This class is used to fill a path with edges. - * - * You can push new edges to the front and to the back of the path in - * arbitrary order then you should commit these changes to the graph. - * - * Fundamentally, for most "Paths" (classes fulfilling the - * PathConcept) while the builder is active (after the first modifying - * operation and until the commit()) the original Path is in a - * "transitional" state (operations on it have undefined result). But - * in the case of DirPath the original path remains unchanged until the - * commit. However we don't recomend that you use this feature. - */ - class Builder { - DirPath &P; - Container front, back; - - public: - ///\param _p the path you want to fill in. - /// - Builder(DirPath &_p) : P(_p) {} - - /// Sets the starting node of the path. - - /// Sets the starting node of the path. Edge added to the path - /// afterwards have to be incident to this node. - /// It should be called if and only if - /// the path is empty and before any call to - /// \ref pushFront() or \ref pushBack() - void setStartNode(const GraphNode &) {} - - ///Push a new edge to the front of the path - - ///Push a new edge to the front of the path. - ///\sa setStartNode - void pushFront(const GraphEdge& e) { - front.push_back(e); - } - - ///Push a new edge to the back of the path - - ///Push a new edge to the back of the path. - ///\sa setStartNode - void pushBack(const GraphEdge& e) { - back.push_back(e); - } - - ///Commit the changes to the path. - void commit() { - if( !front.empty() || !back.empty() ) { - Container tmp; - tmp.reserve(front.size()+back.size()+P.length()); - tmp.insert(tmp.end(), front.rbegin(), front.rend()); - tmp.insert(tmp.end(), P.edges.begin(), P.edges.end()); - tmp.insert(tmp.end(), back.begin(), back.end()); - P.edges.swap(tmp); - front.clear(); - back.clear(); - } - } - - ///Reserve storage for the builder in advance. - - ///If you know a reasonable upper bound of the number of the edges - ///to add to the front, using this function you can speed up the building. - - void reserveFront(size_t r) {front.reserve(r);} - - ///Reserve storage for the builder in advance. - - ///If you know a reasonable upper bound of the number of the edges - ///to add to the back, using this function you can speed up the building. - - void reserveBack(size_t r) {back.reserve(r);} - - private: - bool empty() { - return front.empty() && back.empty() && P.empty(); - } - - GraphNode source() const { - if( ! front.empty() ) - return P.gr->source(front[front.size()-1]); - else if( ! P.empty() ) - return P.gr->source(P.edges[0]); - else if( ! back.empty() ) - return P.gr->source(back[0]); - else - return INVALID; - } - GraphNode target() const { - if( ! back.empty() ) - return P.gr->target(back[back.size()-1]); - else if( ! P.empty() ) - return P.gr->target(P.edges[P.length()-1]); - else if( ! front.empty() ) - return P.gr->target(front[0]); - else - return INVALID; - } - - }; - - }; - - - - - - - - - - - /**********************************************************************/ - - - //! \brief A structure for representing undirected path in a graph. - //! - //! A structure for representing undirected path in a graph. Ie. this is - //! a path in a \e directed graph but the edges should not be directed - //! forward. - //! - //! \param Graph The graph type in which the path is. - //! \param DM DebugMode, defaults to DefaultDebugMode. - //! - //! In a sense, the path can be treated as a graph, for is has \c NodeIt - //! and \c EdgeIt with the same usage. These types converts to the \c Node - //! and \c Edge of the original graph. - //! - //! \todo Thoroughfully check all the range and consistency tests. - template - class UndirPath { - public: - /// Edge type of the underlying graph. - typedef typename Graph::Edge GraphEdge; - /// Node type of the underlying graph. - typedef typename Graph::Node GraphNode; - class NodeIt; - class EdgeIt; - - protected: - const Graph *gr; - typedef std::vector Container; - Container edges; - - public: - - /// \param _G The graph in which the path is. - /// - UndirPath(const Graph &_G) : gr(&_G) {} - - /// \brief Subpath constructor. - /// - /// Subpath defined by two nodes. - /// \warning It is an error if the two edges are not in order! - UndirPath(const UndirPath &P, const NodeIt &a, const NodeIt &b) { - gr = P.gr; - edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); - } - - /// \brief Subpath constructor. - /// - /// Subpath defined by two edges. Contains edges in [a,b) - /// \warning It is an error if the two edges are not in order! - UndirPath(const UndirPath &P, const EdgeIt &a, const EdgeIt &b) { - gr = P.gr; - edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx); - } - - /// Length of the path. - size_t length() const { return edges.size(); } - /// Returns whether the path is empty. - bool empty() const { return edges.empty(); } - - /// Resets the path to an empty path. - void clear() { edges.clear(); } - - /// \brief Starting point of the path. - /// - /// Starting point of the path. - /// Returns INVALID if the path is empty. - GraphNode source() const { - return empty() ? INVALID : gr->source(edges[0]); - } - /// \brief End point of the path. - /// - /// End point of the path. - /// Returns INVALID if the path is empty. - GraphNode target() const { - return empty() ? INVALID : gr->target(edges[length()-1]); - } - - /// \brief Initializes node or edge iterator to point to the first - /// node or edge. - /// - /// \sa nth - template - It& first(It &i) const { return i=It(*this); } - - /// \brief Initializes node iterator to point to the node of a given index. - NodeIt& nth(NodeIt &i, int n) const { - return i=NodeIt(*this, n); - } - - /// \brief Initializes edge iterator to point to the edge of a given index. - EdgeIt& nth(EdgeIt &i, int n) const { - return i=EdgeIt(*this, n); - } - - /// Checks validity of a node or edge iterator. - template - static - bool valid(const It &i) { return i.valid(); } - - /// Steps the given node or edge iterator. - template - static - It& next(It &e) { - return ++e; - } - - /// \brief Returns node iterator pointing to the target node of the - /// given edge iterator. - NodeIt target(const EdgeIt& e) const { - return NodeIt(*this, e.idx+1); - } - - /// \brief Returns node iterator pointing to the source node of the - /// given edge iterator. - NodeIt source(const EdgeIt& e) const { - return NodeIt(*this, e.idx); - } - - - - /** - * \brief Iterator class to iterate on the edges of the paths - * - * This class is used to iterate on the edges of the paths - * - * Of course it converts to Graph::Edge - * - * \todo Its interface differs from the standard edge iterator. - * Yes, it shouldn't. - */ - class EdgeIt { - friend class UndirPath; - - int idx; - const UndirPath *p; - public: - /// Default constructor - EdgeIt() {} - /// Invalid constructor - EdgeIt(Invalid) : idx(-1), p(0) {} - /// Constructor with starting point - EdgeIt(const UndirPath &_p, int _idx = 0) : - idx(_idx), p(&_p) { validate(); } - - ///Validity check - bool valid() const { return idx!=-1; } - - ///Conversion to Graph::Edge - operator GraphEdge () const { - return valid() ? p->edges[idx] : INVALID; - } - /// Next edge - EdgeIt& operator++() { ++idx; validate(); return *this; } - - /// Comparison operator - bool operator==(const EdgeIt& e) const { return idx==e.idx; } - /// Comparison operator - bool operator!=(const EdgeIt& e) const { return idx!=e.idx; } - /// Comparison operator - bool operator<(const EdgeIt& e) const { return idx= p->length() ) idx=-1; } - }; - - /** - * \brief Iterator class to iterate on the nodes of the paths - * - * This class is used to iterate on the nodes of the paths - * - * Of course it converts to Graph::Node - * - * \todo Its interface differs from the standard node iterator. - * Yes, it shouldn't. - */ - class NodeIt { - friend class UndirPath; - - int idx; - const UndirPath *p; - public: - /// Default constructor - NodeIt() {} - /// Invalid constructor - NodeIt(Invalid) : idx(-1), p(0) {} - /// Constructor with starting point - NodeIt(const UndirPath &_p, int _idx = 0) : - idx(_idx), p(&_p) { validate(); } - - ///Validity check - bool valid() const { return idx!=-1; } - - ///Conversion to Graph::Node - operator const GraphNode& () const { - if(idx >= p->length()) - return p->target(); - else if(idx >= 0) - return p->gr->source(p->edges[idx]); - else - return INVALID; - } - /// Next node - NodeIt& operator++() { ++idx; validate(); return *this; } - - /// Comparison operator - bool operator==(const NodeIt& e) const { return idx==e.idx; } - /// Comparison operator - bool operator!=(const NodeIt& e) const { return idx!=e.idx; } - /// Comparison operator - bool operator<(const NodeIt& e) const { return idx p->length() ) idx=-1; } - }; - - friend class Builder; - - /** - * \brief Class to build paths - * - * This class is used to fill a path with edges. - * - * You can push new edges to the front and to the back of the path in - * arbitrary order then you should commit these changes to the graph. - * - * Fundamentally, for most "Paths" (classes fulfilling the - * PathConcept) while the builder is active (after the first modifying - * operation and until the commit()) the original Path is in a - * "transitional" state (operations ot it have undefined result). But - * in the case of UndirPath the original path is unchanged until the - * commit. However we don't recomend that you use this feature. - */ - class Builder { - UndirPath &P; - Container front, back; - - public: - ///\param _p the path you want to fill in. - /// - Builder(UndirPath &_p) : P(_p) {} - - /// Sets the starting node of the path. - - /// Sets the starting node of the path. Edge added to the path - /// afterwards have to be incident to this node. - /// It should be called if and only if - /// the path is empty and before any call to - /// \ref pushFront() or \ref pushBack() - void setStartNode(const GraphNode &) {} - - ///Push a new edge to the front of the path - - ///Push a new edge to the front of the path. - ///\sa setStartNode - void pushFront(const GraphEdge& e) { - front.push_back(e); - } - - ///Push a new edge to the back of the path - - ///Push a new edge to the back of the path. - ///\sa setStartNode - void pushBack(const GraphEdge& e) { - back.push_back(e); - } - - ///Commit the changes to the path. - void commit() { - if( !(front.empty() && back.empty()) ) { - Container tmp; - tmp.reserve(front.size()+back.size()+P.length()); - tmp.insert(tmp.end(), front.rbegin(), front.rend()); - tmp.insert(tmp.end(), P.edges.begin(), P.edges.end()); - tmp.insert(tmp.end(), back.begin(), back.end()); - P.edges.swap(tmp); - front.clear(); - back.clear(); - } - } - - - ///Reserve storage for the builder in advance. - - ///If you know a reasonable upper bound of the number of the edges - ///to add to the front, using this function you can speed up the building. - - void reserveFront(size_t r) {front.reserve(r);} - - ///Reserve storage for the builder in advance. - - ///If you know a reasonable upper bound of the number of the edges - ///to add to the back, using this function you can speed up the building. - - void reserveBack(size_t r) {back.reserve(r);} - - private: - bool empty() { - return front.empty() && back.empty() && P.empty(); - } - - GraphNode source() const { - if( ! front.empty() ) - return P.gr->source(front[front.size()-1]); - else if( ! P.empty() ) - return P.gr->source(P.edges[0]); - else if( ! back.empty() ) - return P.gr->source(back[0]); - else - return INVALID; - } - GraphNode target() const { - if( ! back.empty() ) - return P.gr->target(back[back.size()-1]); - else if( ! P.empty() ) - return P.gr->target(P.edges[P.length()-1]); - else if( ! front.empty() ) - return P.gr->target(front[0]); - else - return INVALID; - } - - }; - - }; - - - ///@} - -} // namespace lemon - -#endif // LEMON_PATH_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/preflow.h --- a/src/lemon/preflow.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,868 +0,0 @@ -/* -*- C++ -*- - * src/lemon/preflow.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_PREFLOW_H -#define LEMON_PREFLOW_H - -#include -#include - -#include -#include -#include - -/// \file -/// \ingroup flowalgs -/// Implementation of the preflow algorithm. - -namespace lemon { - - /// \addtogroup flowalgs - /// @{ - - ///%Preflow algorithms class. - - ///This class provides an implementation of the \e preflow \e - ///algorithm producing a flow of maximum value in a directed - ///graph. The preflow algorithms are the fastest known max flow algorithms - ///up to now. The \e source node, the \e target node, the \e - ///capacity of the edges and the \e starting \e flow value of the - ///edges should be passed to the algorithm through the - ///constructor. It is possible to change these quantities using the - ///functions \ref source, \ref target, \ref capacityMap and \ref - ///flowMap. - /// - ///After running \ref lemon::Preflow::phase1() "phase1()" - ///or \ref lemon::Preflow::run() "run()", the maximal flow - ///value can be obtained by calling \ref flowValue(). The minimum - ///value cut can be written into a bool node map by - ///calling \ref minCut(). (\ref minMinCut() and \ref maxMinCut() writes - ///the inclusionwise minimum and maximum of the minimum value cuts, - ///resp.) - /// - ///\param Graph The directed graph type the algorithm runs on. - ///\param Num The number type of the capacities and the flow values. - ///\param CapacityMap The capacity map type. - ///\param FlowMap The flow map type. - /// - ///\author Jacint Szabo - ///\todo Second template parameter is superfluous - template , - typename FlowMap=typename Graph::template EdgeMap > - class Preflow { - protected: - typedef typename Graph::Node Node; - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::EdgeIt EdgeIt; - typedef typename Graph::OutEdgeIt OutEdgeIt; - typedef typename Graph::InEdgeIt InEdgeIt; - - typedef typename Graph::template NodeMap NNMap; - typedef typename std::vector VecNode; - - const Graph* _g; - Node _source; - Node _target; - const CapacityMap* _capacity; - FlowMap* _flow; - int _node_num; //the number of nodes of G - - typename Graph::template NodeMap level; - typename Graph::template NodeMap excess; - - // constants used for heuristics - static const int H0=20; - static const int H1=1; - - public: - - ///Indicates the property of the starting flow map. - - ///Indicates the property of the starting flow map. - ///The meanings are as follows: - ///- \c ZERO_FLOW: constant zero flow - ///- \c GEN_FLOW: any flow, i.e. the sum of the in-flows equals to - ///the sum of the out-flows in every node except the \e source and - ///the \e target. - ///- \c PRE_FLOW: any preflow, i.e. the sum of the in-flows is at - ///least the sum of the out-flows in every node except the \e source. - ///- \c NO_FLOW: indicates an unspecified edge map. \c flow will be - ///set to the constant zero flow in the beginning of - ///the algorithm in this case. - /// - enum FlowEnum{ - NO_FLOW, - ZERO_FLOW, - GEN_FLOW, - PRE_FLOW - }; - - ///Indicates the state of the preflow algorithm. - - ///Indicates the state of the preflow algorithm. - ///The meanings are as follows: - ///- \c AFTER_NOTHING: before running the algorithm or - /// at an unspecified state. - ///- \c AFTER_PREFLOW_PHASE_1: right after running \c phase1 - ///- \c AFTER_PREFLOW_PHASE_2: after running \ref phase2() - /// - enum StatusEnum { - AFTER_NOTHING, - AFTER_PREFLOW_PHASE_1, - AFTER_PREFLOW_PHASE_2 - }; - - protected: - FlowEnum flow_prop; - StatusEnum status; // Do not needle this flag only if necessary. - - public: - ///The constructor of the class. - - ///The constructor of the class. - ///\param _gr The directed graph the algorithm runs on. - ///\param _s The source node. - ///\param _t The target node. - ///\param _cap The capacity of the edges. - ///\param _f The flow of the edges. - ///Except the graph, all of these parameters can be reset by - ///calling \ref source, \ref target, \ref capacityMap and \ref - ///flowMap, resp. - Preflow(const Graph& _gr, Node _s, Node _t, - const CapacityMap& _cap, FlowMap& _f) : - _g(&_gr), _source(_s), _target(_t), _capacity(&_cap), - _flow(&_f), _node_num(countNodes(_gr)), level(_gr), excess(_gr,0), - flow_prop(NO_FLOW), status(AFTER_NOTHING) { } - - - - ///Runs the preflow algorithm. - - ///Runs the preflow algorithm. - /// - void run() { - phase1(flow_prop); - phase2(); - } - - ///Runs the preflow algorithm. - - ///Runs the preflow algorithm. - ///\pre The starting flow map must be - /// - a constant zero flow if \c fp is \c ZERO_FLOW, - /// - an arbitrary flow if \c fp is \c GEN_FLOW, - /// - an arbitrary preflow if \c fp is \c PRE_FLOW, - /// - any map if \c fp is NO_FLOW. - ///If the starting flow map is a flow or a preflow then - ///the algorithm terminates faster. - void run(FlowEnum fp) { - flow_prop=fp; - run(); - } - - ///Runs the first phase of the preflow algorithm. - - ///The preflow algorithm consists of two phases, this method runs - ///the first phase. After the first phase the maximum flow value - ///and a minimum value cut can already be computed, although a - ///maximum flow is not yet obtained. So after calling this method - ///\ref flowValue returns the value of a maximum flow and \ref - ///minCut returns a minimum cut. - ///\warning \ref minMinCut and \ref maxMinCut do not give minimum - ///value cuts unless calling \ref phase2. - ///\pre The starting flow must be - ///- a constant zero flow if \c fp is \c ZERO_FLOW, - ///- an arbitary flow if \c fp is \c GEN_FLOW, - ///- an arbitary preflow if \c fp is \c PRE_FLOW, - ///- any map if \c fp is NO_FLOW. - void phase1(FlowEnum fp) - { - flow_prop=fp; - phase1(); - } - - - ///Runs the first phase of the preflow algorithm. - - ///The preflow algorithm consists of two phases, this method runs - ///the first phase. After the first phase the maximum flow value - ///and a minimum value cut can already be computed, although a - ///maximum flow is not yet obtained. So after calling this method - ///\ref flowValue returns the value of a maximum flow and \ref - ///minCut returns a minimum cut. - ///\warning \ref minCut(), \ref minMinCut() and \ref maxMinCut() do not - ///give minimum value cuts unless calling \ref phase2(). - void phase1() - { - int heur0=(int)(H0*_node_num); //time while running 'bound decrease' - int heur1=(int)(H1*_node_num); //time while running 'highest label' - int heur=heur1; //starting time interval (#of relabels) - int numrelabel=0; - - bool what_heur=1; - //It is 0 in case 'bound decrease' and 1 in case 'highest label' - - bool end=false; - //Needed for 'bound decrease', true means no active - //nodes are above bound b. - - int k=_node_num-2; //bound on the highest level under n containing a node - int b=k; //bound on the highest level under n of an active node - - VecNode first(_node_num, INVALID); - NNMap next(*_g, INVALID); - - NNMap left(*_g, INVALID); - NNMap right(*_g, INVALID); - VecNode level_list(_node_num,INVALID); - //List of the nodes in level i 0 ) { - b=k; - end=true; - } else break; - } - - if ( first[b]==INVALID ) --b; - else { - end=false; - Node w=first[b]; - first[b]=next[w]; - int newlevel=push(w, next, first); - if ( excess[w] > 0 ) relabel(w, newlevel, first, next, level_list, - left, right, b, k, what_heur); - - ++numrelabel; - if ( numrelabel >= heur ) { - numrelabel=0; - if ( what_heur ) { - what_heur=0; - heur=heur0; - end=false; - } else { - what_heur=1; - heur=heur1; - b=k; - } - } - } - } - flow_prop=PRE_FLOW; - status=AFTER_PREFLOW_PHASE_1; - } - // Heuristics: - // 2 phase - // gap - // list 'level_list' on the nodes on level i implemented by hand - // stack 'active' on the active nodes on level i - // runs heuristic 'highest label' for H1*n relabels - // runs heuristic 'bound decrease' for H0*n relabels, - // starts with 'highest label' - // Parameters H0 and H1 are initialized to 20 and 1. - - - ///Runs the second phase of the preflow algorithm. - - ///The preflow algorithm consists of two phases, this method runs - ///the second phase. After calling \ref phase1 and then \ref - ///phase2, \ref flow contains a maximum flow, \ref flowValue - ///returns the value of a maximum flow, \ref minCut returns a - ///minimum cut, while the methods \ref minMinCut and \ref - ///maxMinCut return the inclusionwise minimum and maximum cuts of - ///minimum value, resp. \pre \ref phase1 must be called before. - void phase2() - { - - int k=_node_num-2; //bound on the highest level under n containing a node - int b=k; //bound on the highest level under n of an active node - - - VecNode first(_node_num, INVALID); - NNMap next(*_g, INVALID); - level.set(_source,0); - std::queue bfs_queue; - bfs_queue.push(_source); - - while ( !bfs_queue.empty() ) { - - Node v=bfs_queue.front(); - bfs_queue.pop(); - int l=level[v]+1; - - for(InEdgeIt e(*_g,v); e!=INVALID; ++e) { - if ( (*_capacity)[e] <= (*_flow)[e] ) continue; - Node u=_g->source(e); - if ( level[u] >= _node_num ) { - bfs_queue.push(u); - level.set(u, l); - if ( excess[u] > 0 ) { - next.set(u,first[l]); - first[l]=u; - } - } - } - - for(OutEdgeIt e(*_g,v); e!=INVALID; ++e) { - if ( 0 >= (*_flow)[e] ) continue; - Node u=_g->target(e); - if ( level[u] >= _node_num ) { - bfs_queue.push(u); - level.set(u, l); - if ( excess[u] > 0 ) { - next.set(u,first[l]); - first[l]=u; - } - } - } - } - b=_node_num-2; - - while ( true ) { - - if ( b == 0 ) break; - if ( first[b]==INVALID ) --b; - else { - Node w=first[b]; - first[b]=next[w]; - int newlevel=push(w,next, first); - - //relabel - if ( excess[w] > 0 ) { - level.set(w,++newlevel); - next.set(w,first[newlevel]); - first[newlevel]=w; - b=newlevel; - } - } - } // while(true) - flow_prop=GEN_FLOW; - status=AFTER_PREFLOW_PHASE_2; - } - - /// Returns the value of the maximum flow. - - /// Returns the value of the maximum flow by returning the excess - /// of the target node \c t. This value equals to the value of - /// the maximum flow already after running \ref phase1. - Num flowValue() const { - return excess[_target]; - } - - - ///Returns a minimum value cut. - - ///Sets \c M to the characteristic vector of a minimum value - ///cut. This method can be called both after running \ref - ///phase1 and \ref phase2. It is much faster after - ///\ref phase1. \pre M should be a bool-valued node-map. \pre - ///If \ref minCut() is called after \ref phase2() then M should - ///be initialized to false. - template - void minCut(_CutMap& M) const { - switch ( status ) { - case AFTER_PREFLOW_PHASE_1: - for(NodeIt v(*_g); v!=INVALID; ++v) { - if (level[v] < _node_num) { - M.set(v, false); - } else { - M.set(v, true); - } - } - break; - case AFTER_PREFLOW_PHASE_2: - minMinCut(M); - break; - case AFTER_NOTHING: - break; - } - } - - ///Returns the inclusionwise minimum of the minimum value cuts. - - ///Sets \c M to the characteristic vector of the minimum value cut - ///which is inclusionwise minimum. It is computed by processing a - ///bfs from the source node \c s in the residual graph. \pre M - ///should be a node map of bools initialized to false. \pre \ref - ///phase2 should already be run. - template - void minMinCut(_CutMap& M) const { - - std::queue queue; - M.set(_source,true); - queue.push(_source); - - while (!queue.empty()) { - Node w=queue.front(); - queue.pop(); - - for(OutEdgeIt e(*_g,w) ; e!=INVALID; ++e) { - Node v=_g->target(e); - if (!M[v] && (*_flow)[e] < (*_capacity)[e] ) { - queue.push(v); - M.set(v, true); - } - } - - for(InEdgeIt e(*_g,w) ; e!=INVALID; ++e) { - Node v=_g->source(e); - if (!M[v] && (*_flow)[e] > 0 ) { - queue.push(v); - M.set(v, true); - } - } - } - } - - ///Returns the inclusionwise maximum of the minimum value cuts. - - ///Sets \c M to the characteristic vector of the minimum value cut - ///which is inclusionwise maximum. It is computed by processing a - ///backward bfs from the target node \c t in the residual graph. - ///\pre \ref phase2() or run() should already be run. - template - void maxMinCut(_CutMap& M) const { - - for(NodeIt v(*_g) ; v!=INVALID; ++v) M.set(v, true); - - std::queue queue; - - M.set(_target,false); - queue.push(_target); - - while (!queue.empty()) { - Node w=queue.front(); - queue.pop(); - - for(InEdgeIt e(*_g,w) ; e!=INVALID; ++e) { - Node v=_g->source(e); - if (M[v] && (*_flow)[e] < (*_capacity)[e] ) { - queue.push(v); - M.set(v, false); - } - } - - for(OutEdgeIt e(*_g,w) ; e!=INVALID; ++e) { - Node v=_g->target(e); - if (M[v] && (*_flow)[e] > 0 ) { - queue.push(v); - M.set(v, false); - } - } - } - } - - ///Sets the source node to \c _s. - - ///Sets the source node to \c _s. - /// - void source(Node _s) { - _source=_s; - if ( flow_prop != ZERO_FLOW ) flow_prop=NO_FLOW; - status=AFTER_NOTHING; - } - - ///Returns the source node. - - ///Returns the source node. - /// - Node source() const { - return _source; - } - - ///Sets the target node to \c _t. - - ///Sets the target node to \c _t. - /// - void target(Node _t) { - _target=_t; - if ( flow_prop == GEN_FLOW ) flow_prop=PRE_FLOW; - status=AFTER_NOTHING; - } - - ///Returns the target node. - - ///Returns the target node. - /// - Node target() const { - return _target; - } - - /// Sets the edge map of the capacities to _cap. - - /// Sets the edge map of the capacities to _cap. - /// - void capacityMap(const CapacityMap& _cap) { - _capacity=&_cap; - status=AFTER_NOTHING; - } - /// Returns a reference to capacity map. - - /// Returns a reference to capacity map. - /// - const CapacityMap &capacityMap() const { - return *_capacity; - } - - /// Sets the edge map of the flows to _flow. - - /// Sets the edge map of the flows to _flow. - /// - void flowMap(FlowMap& _f) { - _flow=&_f; - flow_prop=NO_FLOW; - status=AFTER_NOTHING; - } - - /// Returns a reference to flow map. - - /// Returns a reference to flow map. - /// - const FlowMap &flowMap() const { - return *_flow; - } - - private: - - int push(Node w, NNMap& next, VecNode& first) { - - int lev=level[w]; - Num exc=excess[w]; - int newlevel=_node_num; //bound on the next level of w - - for(OutEdgeIt e(*_g,w) ; e!=INVALID; ++e) { - if ( (*_flow)[e] >= (*_capacity)[e] ) continue; - Node v=_g->target(e); - - if( lev > level[v] ) { //Push is allowed now - - if ( excess[v]<=0 && v!=_target && v!=_source ) { - next.set(v,first[level[v]]); - first[level[v]]=v; - } - - Num cap=(*_capacity)[e]; - Num flo=(*_flow)[e]; - Num remcap=cap-flo; - - if ( remcap >= exc ) { //A nonsaturating push. - - _flow->set(e, flo+exc); - excess.set(v, excess[v]+exc); - exc=0; - break; - - } else { //A saturating push. - _flow->set(e, cap); - excess.set(v, excess[v]+remcap); - exc-=remcap; - } - } else if ( newlevel > level[v] ) newlevel = level[v]; - } //for out edges wv - - if ( exc > 0 ) { - for(InEdgeIt e(*_g,w) ; e!=INVALID; ++e) { - - if( (*_flow)[e] <= 0 ) continue; - Node v=_g->source(e); - - if( lev > level[v] ) { //Push is allowed now - - if ( excess[v]<=0 && v!=_target && v!=_source ) { - next.set(v,first[level[v]]); - first[level[v]]=v; - } - - Num flo=(*_flow)[e]; - - if ( flo >= exc ) { //A nonsaturating push. - - _flow->set(e, flo-exc); - excess.set(v, excess[v]+exc); - exc=0; - break; - } else { //A saturating push. - - excess.set(v, excess[v]+flo); - exc-=flo; - _flow->set(e,0); - } - } else if ( newlevel > level[v] ) newlevel = level[v]; - } //for in edges vw - - } // if w still has excess after the out edge for cycle - - excess.set(w, exc); - - return newlevel; - } - - - - void preflowPreproc(VecNode& first, NNMap& next, - VecNode& level_list, NNMap& left, NNMap& right) - { - for(NodeIt v(*_g); v!=INVALID; ++v) level.set(v,_node_num); - std::queue bfs_queue; - - if ( flow_prop == GEN_FLOW || flow_prop == PRE_FLOW ) { - //Reverse_bfs from t in the residual graph, - //to find the starting level. - level.set(_target,0); - bfs_queue.push(_target); - - while ( !bfs_queue.empty() ) { - - Node v=bfs_queue.front(); - bfs_queue.pop(); - int l=level[v]+1; - - for(InEdgeIt e(*_g,v) ; e!=INVALID; ++e) { - if ( (*_capacity)[e] <= (*_flow)[e] ) continue; - Node w=_g->source(e); - if ( level[w] == _node_num && w != _source ) { - bfs_queue.push(w); - Node z=level_list[l]; - if ( z!=INVALID ) left.set(z,w); - right.set(w,z); - level_list[l]=w; - level.set(w, l); - } - } - - for(OutEdgeIt e(*_g,v) ; e!=INVALID; ++e) { - if ( 0 >= (*_flow)[e] ) continue; - Node w=_g->target(e); - if ( level[w] == _node_num && w != _source ) { - bfs_queue.push(w); - Node z=level_list[l]; - if ( z!=INVALID ) left.set(z,w); - right.set(w,z); - level_list[l]=w; - level.set(w, l); - } - } - } //while - } //if - - - switch (flow_prop) { - case NO_FLOW: - for(EdgeIt e(*_g); e!=INVALID; ++e) _flow->set(e,0); - case ZERO_FLOW: - for(NodeIt v(*_g); v!=INVALID; ++v) excess.set(v,0); - - //Reverse_bfs from t, to find the starting level. - level.set(_target,0); - bfs_queue.push(_target); - - while ( !bfs_queue.empty() ) { - - Node v=bfs_queue.front(); - bfs_queue.pop(); - int l=level[v]+1; - - for(InEdgeIt e(*_g,v) ; e!=INVALID; ++e) { - Node w=_g->source(e); - if ( level[w] == _node_num && w != _source ) { - bfs_queue.push(w); - Node z=level_list[l]; - if ( z!=INVALID ) left.set(z,w); - right.set(w,z); - level_list[l]=w; - level.set(w, l); - } - } - } - - //the starting flow - for(OutEdgeIt e(*_g,_source) ; e!=INVALID; ++e) { - Num c=(*_capacity)[e]; - if ( c <= 0 ) continue; - Node w=_g->target(e); - if ( level[w] < _node_num ) { - if ( excess[w] <= 0 && w!=_target ) { //putting into the stack - next.set(w,first[level[w]]); - first[level[w]]=w; - } - _flow->set(e, c); - excess.set(w, excess[w]+c); - } - } - break; - - case GEN_FLOW: - for(NodeIt v(*_g); v!=INVALID; ++v) excess.set(v,0); - { - Num exc=0; - for(InEdgeIt e(*_g,_target) ; e!=INVALID; ++e) exc+=(*_flow)[e]; - for(OutEdgeIt e(*_g,_target) ; e!=INVALID; ++e) exc-=(*_flow)[e]; - excess.set(_target,exc); - } - - //the starting flow - for(OutEdgeIt e(*_g,_source); e!=INVALID; ++e) { - Num rem=(*_capacity)[e]-(*_flow)[e]; - if ( rem <= 0 ) continue; - Node w=_g->target(e); - if ( level[w] < _node_num ) { - if ( excess[w] <= 0 && w!=_target ) { //putting into the stack - next.set(w,first[level[w]]); - first[level[w]]=w; - } - _flow->set(e, (*_capacity)[e]); - excess.set(w, excess[w]+rem); - } - } - - for(InEdgeIt e(*_g,_source); e!=INVALID; ++e) { - if ( (*_flow)[e] <= 0 ) continue; - Node w=_g->source(e); - if ( level[w] < _node_num ) { - if ( excess[w] <= 0 && w!=_target ) { - next.set(w,first[level[w]]); - first[level[w]]=w; - } - excess.set(w, excess[w]+(*_flow)[e]); - _flow->set(e, 0); - } - } - break; - - case PRE_FLOW: - //the starting flow - for(OutEdgeIt e(*_g,_source) ; e!=INVALID; ++e) { - Num rem=(*_capacity)[e]-(*_flow)[e]; - if ( rem <= 0 ) continue; - Node w=_g->target(e); - if ( level[w] < _node_num ) _flow->set(e, (*_capacity)[e]); - } - - for(InEdgeIt e(*_g,_source) ; e!=INVALID; ++e) { - if ( (*_flow)[e] <= 0 ) continue; - Node w=_g->source(e); - if ( level[w] < _node_num ) _flow->set(e, 0); - } - - //computing the excess - for(NodeIt w(*_g); w!=INVALID; ++w) { - Num exc=0; - for(InEdgeIt e(*_g,w); e!=INVALID; ++e) exc+=(*_flow)[e]; - for(OutEdgeIt e(*_g,w); e!=INVALID; ++e) exc-=(*_flow)[e]; - excess.set(w,exc); - - //putting the active nodes into the stack - int lev=level[w]; - if ( exc > 0 && lev < _node_num && Node(w) != _target ) { - next.set(w,first[lev]); - first[lev]=w; - } - } - break; - } //switch - } //preflowPreproc - - - void relabel(Node w, int newlevel, VecNode& first, NNMap& next, - VecNode& level_list, NNMap& left, - NNMap& right, int& b, int& k, bool what_heur ) - { - - int lev=level[w]; - - Node right_n=right[w]; - Node left_n=left[w]; - - //unlacing starts - if ( right_n!=INVALID ) { - if ( left_n!=INVALID ) { - right.set(left_n, right_n); - left.set(right_n, left_n); - } else { - level_list[lev]=right_n; - left.set(right_n, INVALID); - } - } else { - if ( left_n!=INVALID ) { - right.set(left_n, INVALID); - } else { - level_list[lev]=INVALID; - } - } - //unlacing ends - - if ( level_list[lev]==INVALID ) { - - //gapping starts - for (int i=lev; i!=k ; ) { - Node v=level_list[++i]; - while ( v!=INVALID ) { - level.set(v,_node_num); - v=right[v]; - } - level_list[i]=INVALID; - if ( !what_heur ) first[i]=INVALID; - } - - level.set(w,_node_num); - b=lev-1; - k=b; - //gapping ends - - } else { - - if ( newlevel == _node_num ) level.set(w,_node_num); - else { - level.set(w,++newlevel); - next.set(w,first[newlevel]); - first[newlevel]=w; - if ( what_heur ) b=newlevel; - if ( k < newlevel ) ++k; //now k=newlevel - Node z=level_list[newlevel]; - if ( z!=INVALID ) left.set(z,w); - right.set(w,z); - left.set(w,INVALID); - level_list[newlevel]=w; - } - } - } //relabel - - }; - - ///Function type interface for Preflow algorithm. - - /// \ingroup flowalgs - ///Function type interface for Preflow algorithm. - ///\sa Preflow - template - Preflow preflow(const GR &g, - typename GR::Node source, - typename GR::Node target, - const CM &cap, - FM &flow - ) - { - return Preflow(g,source,target,cap,flow); - } - -} //namespace lemon - -#endif //LEMON_PREFLOW_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/radix_heap.h --- a/src/lemon/radix_heap.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,412 +0,0 @@ -/* -*- C++ -*- - * src/lemon/radix_heap.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_RADIX_HEAP_H -#define LEMON_RADIX_HEAP_H - -///\ingroup auxdat -///\file -///\brief Radix Heap implementation. - -#include -#include - -namespace lemon { - - /// \addtogroup auxdat - /// @{ - - /// \brief Exception thrown by RadixHeap. - /// - /// This Exception is thrown when a smaller priority - /// is inserted into the \e RadixHeap then the last time erased. - /// \see RadixHeap - /// \author Balazs Dezso - - class UnderFlowPriorityError : public RuntimeError { - public: - virtual const char* exceptionName() const { - return "lemon::UnderFlowPriorityError"; - } - }; - - /// \brief A Radix Heap implementation. - /// - /// This class implements the \e radix \e heap data structure. A \e heap - /// is a data structure for storing items with specified values called \e - /// priorities in such a way that finding the item with minimum priority is - /// efficient. This heap type can store only items with \e int priority. - /// In a heap one can change the priority of an item, add or erase an - /// item, but the priority cannot be decreased under the last removed - /// item's priority. - /// - /// \param _Item Type of the items to be stored. - /// \param _ItemIntMap A read and writable Item int map, used internally - /// to handle the cross references. - /// - /// \see BinHeap - /// \see Dijkstra - /// \author Balazs Dezso - - template - class RadixHeap { - - public: - typedef _Item Item; - typedef int Prio; - typedef _ItemIntMap ItemIntMap; - - /// \brief Type to represent the items states. - /// - /// Each Item element have a state associated to it. It may be "in heap", - /// "pre heap" or "post heap". The latter two are indifferent from the - /// heap's point of view, but may be useful to the user. - /// - /// The ItemIntMap \e should be initialized in such way that it maps - /// PRE_HEAP (-1) to any element to be put in the heap... - enum state_enum { - IN_HEAP = 0, - PRE_HEAP = -1, - POST_HEAP = -2 - }; - - private: - - struct RadixItem { - int prev, next, box; - Item item; - int prio; - RadixItem(Item _item, int _prio) : item(_item), prio(_prio) {} - }; - - struct RadixBox { - int first; - int min, size; - RadixBox(int _min, int _size) : first(-1), min(_min), size(_size) {} - }; - - std::vector data; - std::vector boxes; - - ItemIntMap &iim; - - - public: - /// \brief The constructor. - /// - /// The constructor. - /// \param _iim should be given to the constructor, since it is used - /// internally to handle the cross references. The value of the map - /// should be PRE_HEAP (-1) for each element. - explicit RadixHeap(ItemIntMap &_iim) : iim(_iim) { - boxes.push_back(RadixBox(0, 1)); - boxes.push_back(RadixBox(1, 1)); - } - - /// \brief The constructor. - /// - /// The constructor. - /// - /// \param _iim It should be given to the constructor, since it is used - /// internally to handle the cross references. The value of the map - /// should be PRE_HEAP (-1) for each element. - /// - /// \param capacity It determines the initial capacity of the heap. - RadixHeap(ItemIntMap &_iim, int capacity) : iim(_iim) { - boxes.push_back(RadixBox(0, 1)); - boxes.push_back(RadixBox(1, 1)); - while (upper(boxes.back(), capacity)) { - extend(); - } - } - - /// The number of items stored in the heap. - /// - /// \brief Returns the number of items stored in the heap. - int size() const { return data.size(); } - /// \brief Checks if the heap stores no items. - /// - /// Returns \c true if and only if the heap stores no items. - bool empty() const { return data.empty(); } - - private: - - bool upper(int box, Prio prio) { - return prio < boxes[box].min; - } - - bool lower(int box, Prio prio) { - return prio >= boxes[box].min + boxes[box].size; - } - - /// \brief Remove item from the box list. - void remove(int index) { - if (data[index].prev >= 0) { - data[data[index].prev].next = data[index].next; - } else { - boxes[data[index].box].first = data[index].next; - } - if (data[index].next >= 0) { - data[data[index].next].prev = data[index].prev; - } - } - - /// \brief Insert item into the box list. - void insert(int box, int index) { - if (boxes[box].first == -1) { - boxes[box].first = index; - data[index].next = data[index].prev = -1; - } else { - data[index].next = boxes[box].first; - data[boxes[box].first].prev = index; - data[index].prev = -1; - boxes[box].first = index; - } - data[index].box = box; - } - - /// \brief Add a new box to the box list. - void extend() { - int min = boxes.back().min + boxes.back().size; - int size = 2 * boxes.back().size; - boxes.push_back(RadixBox(min, size)); - } - - /// \brief Move an item up into the proper box. - void bubble_up(int index) { - if (!lower(data[index].box, data[index].prio)) return; - remove(index); - int box = findUp(data[index].box, data[index].prio); - insert(box, index); - } - - /// \brief Find up the proper box for the item with the given prio. - int findUp(int start, int prio) { - while (lower(start, prio)) { - if (++start == (int)boxes.size()) { - extend(); - } - } - return start; - } - - /// \brief Move an item down into the proper box. - void bubble_down(int index) { - if (!upper(data[index].box, data[index].prio)) return; - remove(index); - int box = findDown(data[index].box, data[index].prio); - insert(box, index); - } - - /// \brief Find up the proper box for the item with the given prio. - int findDown(int start, int prio) { - while (upper(start, prio)) { - if (--start < 0) throw UnderFlowPriorityError(); - } - return start; - } - - /// \brief Find the first not empty box. - int findFirst() { - int first = 0; - while (boxes[first].first == -1) ++first; - return first; - } - - /// \brief Gives back the minimal prio of the box. - int minValue(int box) { - int min = data[boxes[box].first].prio; - for (int k = boxes[box].first; k != -1; k = data[k].next) { - if (data[k].prio < min) min = data[k].prio; - } - return min; - } - - /// \brief Rearrange the items of the heap and makes the - /// first box not empty. - void moveDown() { - int box = findFirst(); - if (box == 0) return; - int min = minValue(box); - for (int i = 0; i <= box; ++i) { - boxes[i].min = min; - min += boxes[i].size; - } - int curr = boxes[box].first, next; - while (curr != -1) { - next = data[curr].next; - bubble_down(curr); - curr = next; - } - } - - void relocate_last(int index) { - if (index != (int)data.size() - 1) { - data[index] = data.back(); - if (data[index].prev != -1) { - data[data[index].prev].next = index; - } else { - boxes[data[index].box].first = index; - } - if (data[index].next != -1) { - data[data[index].next].prev = index; - } - iim[data[index].item] = index; - } - data.pop_back(); - } - - public: - - /// \brief Insert an item into the heap with the given heap. - /// - /// Adds \c i to the heap with priority \c p. - /// \param i The item to insert. - /// \param p The priority of the item. - void push(const Item &i, const Prio &p) { - int n = data.size(); - iim.set(i, n); - data.push_back(RadixItem(i, p)); - while (lower(boxes.size() - 1, p)) { - extend(); - } - int box = findDown(boxes.size() - 1, p); - insert(box, n); - } - - /// \brief Returns the item with minimum priority. - /// - /// This method returns the item with minimum priority. - /// \pre The heap must be nonempty. - Item top() const { - const_cast*>(this)->moveDown(); - return data[boxes[0].first].item; - } - - /// \brief Returns the minimum priority. - /// - /// It returns the minimum priority. - /// \pre The heap must be nonempty. - Prio prio() const { - const_cast*>(this)->moveDown(); - return data[boxes[0].first].prio; - } - - /// \brief Deletes the item with minimum priority. - /// - /// This method deletes the item with minimum priority. - /// \pre The heap must be non-empty. - void pop() { - moveDown(); - int index = boxes[0].first; - iim[data[index].item] = POST_HEAP; - remove(index); - relocate_last(index); - } - - /// \brief Deletes \c i from the heap. - /// - /// This method deletes item \c i from the heap, if \c i was - /// already stored in the heap. - /// \param i The item to erase. - void erase(const Item &i) { - int index = iim[i]; - iim[i] = POST_HEAP; - remove(index); - relocate_last(index); - } - - /// \brief Returns the priority of \c i. - /// - /// This function returns the priority of item \c i. - /// \pre \c i must be in the heap. - /// \param i The item. - Prio operator[](const Item &i) const { - int idx = iim[i]; - return data[idx].prio; - } - - /// \brief \c i gets to the heap with priority \c p independently - /// if \c i was already there. - /// - /// This method calls \ref push(\c i, \c p) if \c i is not stored - /// in the heap and sets the priority of \c i to \c p otherwise. - /// It may throw an \e UnderFlowPriorityException. - /// \param i The item. - /// \param p The priority. - void set(const Item &i, const Prio &p) { - int idx = iim[i]; - if( idx < 0 ) { - push(i, p); - } - else if( p >= data[idx].prio ) { - data[idx].prio = p; - bubble_up(idx); - } else { - data[idx].prio = p; - bubble_down(idx); - } - } - - - /// \brief Decreases the priority of \c i to \c p. - /// - /// This method decreases the priority of item \c i to \c p. - /// \pre \c i must be stored in the heap with priority at least \c p, and - /// \c should be greater then the last removed item's priority. - /// \param i The item. - /// \param p The priority. - void decrease(const Item &i, const Prio &p) { - int idx = iim[i]; - data[idx].prio = p; - bubble_down(idx); - } - - /// \brief Increases the priority of \c i to \c p. - /// - /// This method sets the priority of item \c i to \c p. - /// \pre \c i must be stored in the heap with priority at most \c - /// p relative to \c Compare. - /// \param i The item. - /// \param p The priority. - void increase(const Item &i, const Prio &p) { - int idx = iim[i]; - data[idx].prio = p; - bubble_up(idx); - } - - /// \brief Returns if \c item is in, has already been in, or has - /// never been in the heap. - /// - /// This method returns PRE_HEAP if \c item has never been in the - /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP - /// otherwise. In the latter case it is possible that \c item will - /// get back to the heap again. - /// \param i The item. - state_enum state(const Item &i) const { - int s = iim[i]; - if( s >= 0 ) s = 0; - return state_enum(s); - } - - }; // class RadixHeap - - - ///@} - -} // namespace lemon - -#endif // LEMON_RADIX_HEAP_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/smart_graph.h --- a/src/lemon/smart_graph.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,414 +0,0 @@ -/* -*- C++ -*- - * src/lemon/smart_graph.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_SMART_GRAPH_H -#define LEMON_SMART_GRAPH_H - -///\ingroup graphs -///\file -///\brief SmartGraph and SymSmartGraph classes. - -#include - -#include - -#include -#include -#include -#include -#include - -#include - -#include - -namespace lemon { - - class SmartGraph; - ///Base of SmartGraph - - ///Base of SmartGraph - /// - class SmartGraphBase { - - friend class SmatGraph; - - protected: - struct NodeT - { - int first_in,first_out; - NodeT() : first_in(-1), first_out(-1) {} - }; - struct EdgeT - { - int target, source, next_in, next_out; - //FIXME: is this necessary? - EdgeT() : next_in(-1), next_out(-1) {} - }; - - std::vector nodes; - - std::vector edges; - - - public: - - typedef SmartGraphBase Graph; - - class Node; - class Edge; - - - public: - - SmartGraphBase() : nodes(), edges() { } - SmartGraphBase(const SmartGraphBase &_g) : nodes(_g.nodes), edges(_g.edges) { } - - typedef True NodeNumTag; - typedef True EdgeNumTag; - - ///Number of nodes. - int nodeNum() const { return nodes.size(); } - ///Number of edges. - int edgeNum() const { return edges.size(); } - - /// Maximum node ID. - - /// Maximum node ID. - ///\sa id(Node) - int maxId(Node = INVALID) const { return nodes.size()-1; } - /// Maximum edge ID. - - /// Maximum edge ID. - ///\sa id(Edge) - int maxId(Edge = INVALID) const { return edges.size()-1; } - - Node source(Edge e) const { return edges[e.n].source; } - Node target(Edge e) const { return edges[e.n].target; } - - /// Node ID. - - /// The ID of a valid Node is a nonnegative integer not greater than - /// \ref maxNodeId(). The range of the ID's is not surely continuous - /// and the greatest node ID can be actually less then \ref maxNodeId(). - /// - /// The ID of the \ref INVALID node is -1. - ///\return The ID of the node \c v. - static int id(Node v) { return v.n; } - /// Edge ID. - - /// The ID of a valid Edge is a nonnegative integer not greater than - /// \ref maxEdgeId(). The range of the ID's is not surely continuous - /// and the greatest edge ID can be actually less then \ref maxEdgeId(). - /// - /// The ID of the \ref INVALID edge is -1. - ///\return The ID of the edge \c e. - static int id(Edge e) { return e.n; } - - static Node fromId(int id, Node) { return Node(id);} - - static Edge fromId(int id, Edge) { return Edge(id);} - - Node addNode() { - Node n; n.n=nodes.size(); - nodes.push_back(NodeT()); //FIXME: Hmmm... - return n; - } - - Edge addEdge(Node u, Node v) { - Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm... - edges[e.n].source=u.n; edges[e.n].target=v.n; - edges[e.n].next_out=nodes[u.n].first_out; - edges[e.n].next_in=nodes[v.n].first_in; - nodes[u.n].first_out=nodes[v.n].first_in=e.n; - - return e; - } - - void clear() { - edges.clear(); - nodes.clear(); - } - - - class Node { - friend class SmartGraphBase; - friend class SmartGraph; - - protected: - int n; - ///\todo It should be removed (or at least define a setToId() instead). - /// - Node(int nn) {n=nn;} - public: - Node() {} - Node (Invalid) { n=-1; } - bool operator==(const Node i) const {return n==i.n;} - bool operator!=(const Node i) const {return n!=i.n;} - bool operator<(const Node i) const {return n AlterableSmartGraphBase; - typedef IterableGraphExtender IterableSmartGraphBase; - typedef DefaultMappableGraphExtender MappableSmartGraphBase; - typedef ExtendableGraphExtender ExtendableSmartGraphBase; - typedef ClearableGraphExtender ClearableSmartGraphBase; - - /// \addtogroup graphs - /// @{ - - ///A smart graph class. - - ///This is a simple and fast graph implementation. - ///It is also quite memory efficient, but at the price - ///that it does support only limited (only stack-like) - ///node and edge deletions. - ///It conforms to - ///the \ref concept::ExtendableGraph "ExtendableGraph" concept. - ///\sa concept::ExtendableGraph. - /// - ///\author Alpar Juttner - class SmartGraph : public ClearableSmartGraphBase { - public: - /// Finds an edge between two nodes. - - /// Finds an edge from node \c u to node \c v. - /// - /// If \c prev is \ref INVALID (this is the default value), then - /// it finds the first edge from \c u to \c v. Otherwise it looks for - /// the next edge from \c u to \c v after \c prev. - /// \return The found edge or \ref INVALID if there is no such an edge. - /// - /// Thus you can iterate through each edge from \c u to \c v as it follows. - /// \code - /// for(Edge e=G.findEdge(u,v);e!=INVALID;e=G.findEdge(u,v,e)) { - /// ... - /// } - /// \endcode - /// \todo Possibly it should be a global function. - Edge findEdge(Node u,Node v, Edge prev = INVALID) - { - return _findEdge(u,v,prev); - } - - class SnapShot; - friend class SnapShot; - - protected: - void restoreSnapShot(const SnapShot &s) - { - while(s.edge_num>edges.size()) { - Parent::getNotifier(Edge()).erase(Edge(edges.size()-1)); - nodes[edges.back().target].first_in=edges.back().next_in; - nodes[edges.back().source].first_out=edges.back().next_out; - edges.pop_back(); - } - //nodes.resize(s.nodes_num); - while(s.node_num>nodes.size()) { - Parent::getNotifier(Node()).erase(Node(nodes.size()-1)); - nodes.pop_back(); - } - } - - public: - - ///Split a node. - - ///This function splits a node. First a new node is added to the graph, - ///then the source of each outgoing edge of \c n is moved to this new node. - ///If \c connect is \c true (this is the default value), then a new edge - ///from \c n to the newly created node is also added. - ///\return The newly created node. - /// - ///\note The Edges - ///referencing a moved edge remain - ///valid. However InEdge's and OutEdge's - ///may be invalidated. - ///\warning This functionality cannot be used together with the SnapShot - ///feature. - ///\todo It could be implemented in a bit faster way. - Node split(Node n, bool connect = true) - { - return _split(n,connect); - } - - - ///Class to make a snapshot of the graph and to restrore to it later. - - ///Class to make a snapshot of the graph and to restrore to it later. - /// - ///The newly added nodes and edges can be removed using the - ///restore() function. - ///\note After you restore a state, you cannot restore - ///a later state, in other word you cannot add again the edges deleted - ///by restore() using another SnapShot instance. - /// - class SnapShot - { - SmartGraph *g; - protected: - friend class SmartGraph; - unsigned int node_num; - unsigned int edge_num; - public: - ///Default constructor. - - ///Default constructor. - ///To actually make a snapshot you must call save(). - /// - SnapShot() : g(0) {} - ///Constructor that immediately makes a snapshot - - ///This constructor immediately makes a snapshot of the graph. - ///\param _g The graph we make a snapshot of. - SnapShot(SmartGraph &_g) :g(&_g) { - node_num=g->nodes.size(); - edge_num=g->edges.size(); - } - - ///Make a snapshot. - - ///Make a snapshot of the graph. - /// - ///This function can be called more than once. In case of a repeated - ///call, the previous snapshot gets lost. - ///\param _g The graph we make the snapshot of. - void save(SmartGraph &_g) - { - g=&_g; - node_num=g->nodes.size(); - edge_num=g->edges.size(); - } - - ///Undo the changes until a snapshot. - - ///Undo the changes until a snapshot created by save(). - /// - ///\param s an internal stucture given back by save() - ///\note After you restored a state, you cannot restore - ///a later state, in other word you cannot add again the edges deleted - ///by restore(). - /// - ///\todo This function might be called undo(). - - void restore() - { - g->restoreSnapShot(*this); - } - }; - }; - - - /**************** Undirected List Graph ****************/ - - typedef ClearableUndirGraphExtender< - ExtendableUndirGraphExtender< - MappableUndirGraphExtender< - IterableUndirGraphExtender< - AlterableUndirGraphExtender< - UndirGraphExtender > > > > > UndirSmartGraphBase; - - ///A smart undirected graph class. - - ///This is a simple and fast undirected graph implementation. - ///It is also quite memory efficient, but at the price - ///that it does support only limited (only stack-like) - ///node and edge deletions. - ///Except from this it conforms to - ///the \ref concept::UndirGraph "UndirGraph" concept. - ///\sa concept::UndirGraph. - /// - ///\todo SnapShot hasn't been implemented yet. - /// - class UndirSmartGraph : public UndirSmartGraphBase { - }; - - - /// @} -} //namespace lemon - - -#endif //LEMON_SMART_GRAPH_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/suurballe.h --- a/src/lemon/suurballe.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ -/* -*- C++ -*- - * src/lemon/suurballe.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_SUURBALLE_H -#define LEMON_SUURBALLE_H - -///\ingroup flowalgs -///\file -///\brief An algorithm for finding k paths of minimal total length. - - -#include -#include -#include - -namespace lemon { - -/// \addtogroup flowalgs -/// @{ - - ///\brief Implementation of an algorithm for finding k edge-disjoint paths between 2 nodes - /// of minimal total length - /// - /// The class \ref lemon::Suurballe implements - /// an algorithm for finding k edge-disjoint paths - /// from a given source node to a given target node in an - /// edge-weighted directed graph having minimal total weight (length). - /// - ///\warning Length values should be nonnegative. - /// - ///\param Graph The directed graph type the algorithm runs on. - ///\param LengthMap The type of the length map (values should be nonnegative). - /// - ///\note It it questionable whether it is correct to call this method after - ///%Suurballe for it is just a special case of Edmonds' and Karp's algorithm - ///for finding minimum cost flows. In fact, this implementation just - ///wraps the MinCostFlow algorithms. The paper of both %Suurballe and - ///Edmonds-Karp published in 1972, therefore it is possibly right to - ///state that they are - ///independent results. Most frequently this special case is referred as - ///%Suurballe method in the literature, especially in communication - ///network context. - ///\author Attila Bernath - template - class Suurballe{ - - - typedef typename LengthMap::Value Length; - - typedef typename Graph::Node Node; - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::Edge Edge; - typedef typename Graph::OutEdgeIt OutEdgeIt; - typedef typename Graph::template EdgeMap EdgeIntMap; - - typedef ConstMap ConstMap; - - const Graph& G; - - Node s; - Node t; - - //Auxiliary variables - //This is the capacity map for the mincostflow problem - ConstMap const1map; - //This MinCostFlow instance will actually solve the problem - MinCostFlow min_cost_flow; - - //Container to store found paths - std::vector< std::vector > paths; - - public : - - - /*! \brief The constructor of the class. - - \param _G The directed graph the algorithm runs on. - \param _length The length (weight or cost) of the edges. - \param _s Source node. - \param _t Target node. - */ - Suurballe(Graph& _G, LengthMap& _length, Node _s, Node _t) : - G(_G), s(_s), t(_t), const1map(1), - min_cost_flow(_G, _length, const1map, _s, _t) { } - - ///Runs the algorithm. - - ///Runs the algorithm. - ///Returns k if there are at least k edge-disjoint paths from s to t. - ///Otherwise it returns the number of edge-disjoint paths found - ///from s to t. - /// - ///\param k How many paths are we looking for? - /// - int run(int k) { - int i = min_cost_flow.run(k); - - //Let's find the paths - //We put the paths into stl vectors (as an inner representation). - //In the meantime we lose the information stored in 'reversed'. - //We suppose the lengths to be positive now. - - //We don't want to change the flow of min_cost_flow, so we make a copy - //The name here suggests that the flow has only 0/1 values. - EdgeIntMap reversed(G); - - for(typename Graph::EdgeIt e(G); e!=INVALID; ++e) - reversed[e] = min_cost_flow.getFlow()[e]; - - paths.clear(); - //total_length=0; - paths.resize(k); - for (int j=0; j - void getPath(Path& p, size_t j){ - - p.clear(); - if (j>paths.size()-1){ - return; - } - typename Path::Builder B(p); - for(typename std::vector::iterator i=paths[j].begin(); - i!=paths[j].end(); ++i ){ - B.pushBack(*i); - } - - B.commit(); - } - - }; //class Suurballe - - ///@} - -} //namespace lemon - -#endif //LEMON_SUURBALLE_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/time_measure.h --- a/src/lemon/time_measure.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,255 +0,0 @@ -/* -*- C++ -*- - * src/lemon/time_measure.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_TIME_MEASURE_H -#define LEMON_TIME_MEASURE_H - -///\ingroup misc -///\file -///\brief Tools for measuring cpu usage - -#include -#include -#include -#include -#include - -namespace lemon { - - /// \addtogroup misc - /// @{ - - /// A class to store (cpu)time instances. - - /// This class stores five time values. - /// - a real time - /// - a user cpu time - /// - a system cpu time - /// - a user cpu time of children - /// - a system cpu time of children - /// - /// TimeStamp's can be added to or substracted from each other and - /// they can be pushed to a stream. - /// - /// In most cases, perhaps \ref Timer class is what you want to use instead. - /// - ///\author Alpar Juttner - - class TimeStamp - { - tms ts; - double real_time; - - public: - - tms &getTms() {return ts;} - const tms &getTms() const {return ts;} - ///Read the current time values of the process - void stamp() - { - timeval tv; - times(&ts); - gettimeofday(&tv, 0);real_time=tv.tv_sec+double(tv.tv_usec)/1e6; - } - - /// Constructor initializing with zero - TimeStamp() - { ts.tms_utime=ts.tms_stime=ts.tms_cutime=ts.tms_cstime=0; real_time=0;} - ///Constructor initializing with the current time values of the process - TimeStamp(void *) { stamp();} - - ///\e - TimeStamp &operator+=(const TimeStamp &b) - { - ts.tms_utime+=b.ts.tms_utime; - ts.tms_stime+=b.ts.tms_stime; - ts.tms_cutime+=b.ts.tms_cutime; - ts.tms_cstime+=b.ts.tms_cstime; - real_time+=b.real_time; - return *this; - } - ///\e - TimeStamp operator+(const TimeStamp &b) const - { - TimeStamp t(*this); - return t+=b; - } - ///\e - TimeStamp &operator-=(const TimeStamp &b) - { - ts.tms_utime-=b.ts.tms_utime; - ts.tms_stime-=b.ts.tms_stime; - ts.tms_cutime-=b.ts.tms_cutime; - ts.tms_cstime-=b.ts.tms_cstime; - real_time-=b.real_time; - return *this; - } - ///\e - TimeStamp operator-(const TimeStamp &b) const - { - TimeStamp t(*this); - return t-=b; - } - ///The time ellapsed since the last call of stamp() - TimeStamp ellapsed() const - { - TimeStamp t(NULL); - return t-*this; - } - - friend std::ostream& operator<<(std::ostream& os,const TimeStamp &t); - - ///Gives back the user time of the process - double getUserTime() const - { - return double(ts.tms_utime)/sysconf(_SC_CLK_TCK); - } - ///Gives back the system time of the process - double getSystemTime() const - { - return double(ts.tms_stime)/sysconf(_SC_CLK_TCK); - } - ///Gives back the user time of the process' children - double getCUserTime() const - { - return double(ts.tms_cutime)/sysconf(_SC_CLK_TCK); - } - ///Gives back the user time of the process' children - double getCSystemTime() const - { - return double(ts.tms_cstime)/sysconf(_SC_CLK_TCK); - } - ///Gives back the real time of the process - double getRealTime() const {return real_time;} - }; - - ///Class measuring the cpu time and real time usage of the process - - ///Class measuring the cpu time and real time usage of the process. - ///It is quite easy-to-use, here is a short example. - ///\code - ///#include - ///#include - /// - ///int main() - ///{ - /// - /// ... - /// - /// Timer T; - /// doSomething(); - /// std::cout << T << '\n'; - /// T.reset(); - /// doSomethingElse(); - /// std::cout << T << '\n'; - /// - /// ... - /// - ///} - ///\endcode - /// - ///\todo This shouldn't be Unix (Linux) specific. - /// - ///\author Alpar Juttner - class Timer - { - TimeStamp start_time; - - void _reset() {start_time.stamp();} - - public: - ///Constructor. It starts with zero time counters - Timer() {_reset();} - - ///Computes the ellapsed time - - ///This conversion computes the ellapsed time - ///since the construction of \c t or since - ///the last \c t.reset(). - operator TimeStamp () const - { - TimeStamp t; - t.stamp(); - return t-start_time; - } - - ///Resets the time counters - - ///Resets the time counters - /// - void reset() - { - _reset(); - } - - - ///Gives back the ellapsed user time of the process - double getUserTime() const - { - return operator TimeStamp().getUserTime(); - } - ///Gives back the ellapsed system time of the process - double getSystemTime() const - { - return operator TimeStamp().getSystemTime(); - } - ///Gives back the ellapsed user time of the process' children - double getCUserTime() const - { - return operator TimeStamp().getCUserTime(); - } - ///Gives back the ellapsed user time of the process' children - double getCSystemTime() const - { - return operator TimeStamp().getCSystemTime(); - } - ///Gives back the ellapsed real time of the process - double getRealTime() const - { - return operator TimeStamp().getRealTime(); - } - - }; - - ///Prints the time counters - - ///Prints the time counters in the following form: - /// - /// u: XX.XXs s: XX.XXs cu: XX.XXs cs: XX.XXs real: XX.XXs - /// - /// where the values are the - /// \li \c u: user cpu time, - /// \li \c s: system cpu time, - /// \li \c cu: user cpu time of children, - /// \li \c cs: system cpu time of children, - /// \li \c real: real time. - /// \relates TimeStamp - inline std::ostream& operator<<(std::ostream& os,const TimeStamp &t) - { - long cls = sysconf(_SC_CLK_TCK); - os << "u: " << double(t.getTms().tms_utime)/cls << - "s, s: " << double(t.getTms().tms_stime)/cls << - "s, cu: " << double(t.getTms().tms_cutime)/cls << - "s, cs: " << double(t.getTms().tms_cstime)/cls << - "s, real: " << t.getRealTime() << "s"; - return os; - } - - /// @} - -} //namespace lemon - -#endif //LEMON_TIME_MEASURE_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/unionfind.h --- a/src/lemon/unionfind.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,724 +0,0 @@ -/* -*- C++ -*- - * src/lemon/unionfind.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_UNION_FIND_H -#define LEMON_UNION_FIND_H - -//!\ingroup auxdat -//!\file -//!\brief Union-Find data structures. -//! -//!\bug unionfind_test.cc doesn't work with Intel compiler. It compiles but -//!fails to run (Segmentation fault). - - -#include -#include -#include -#include - -#include - -namespace lemon { - - //! \addtogroup auxdat - //! @{ - - /** - * \brief A \e Union-Find data structure implementation - * - * The class implements the \e Union-Find data structure. - * The union operation uses rank heuristic, while - * the find operation uses path compression. - * This is a very simple but efficient implementation, providing - * only four methods: join (union), find, insert and size. - * For more features see the \ref UnionFindEnum class. - * - * It is primarily used in Kruskal algorithm for finding minimal - * cost spanning tree in a graph. - * \sa kruskal() - * - * \pre The elements are automatically added only if the map - * given to the constructor was filled with -1's. Otherwise you - * need to add all the elements by the \ref insert() method. - * \bug It is not clear what the constructor parameter is used for. - */ - - template - class UnionFind { - - public: - typedef T ElementType; - typedef std::pair PairType; - - private: - std::vector data; - TIntMap& map; - - public: - UnionFind(TIntMap& m) : map(m) {} - - /** - * \brief Returns the index of the element's component. - * - * The method returns the index of the element's component. - * This is an integer between zero and the number of inserted elements. - */ - - int find(T a) - { - int comp0 = map[a]; - if (comp0 < 0) { - return insert(a); - } - int comp = comp0; - int next; - while ( (next = data[comp].first) != comp) { - comp = next; - } - while ( (next = data[comp0].first) != comp) { - data[comp0].first = comp; - comp0 = next; - } - - return comp; - } - - /** - * \brief Inserts a new element into the structure. - * - * This method inserts a new element into the data structure. - * - * It is not required to use this method: - * if the map given to the constructor was filled - * with -1's then it is called automatically - * on the first \ref find or \ref join. - * - * The method returns the index of the new component. - */ - - int insert(T a) - { - int n = data.size(); - data.push_back(std::make_pair(n, 1)); - map.set(a,n); - return n; - } - - /** - * \brief Joining the components of element \e a and element \e b. - * - * This is the \e union operation of the Union-Find structure. - * Joins the component of element \e a and component of - * element \e b. If \e a and \e b are in the same component then - * it returns false otherwise it returns true. - */ - - bool join(T a, T b) - { - int ca = find(a); - int cb = find(b); - - if ( ca == cb ) - return false; - - if ( data[ca].second > data[cb].second ) { - data[cb].first = ca; - data[ca].second += data[cb].second; - } - else { - data[ca].first = cb; - data[cb].second += data[ca].second; - } - return true; - } - - /** - * \brief Returns the size of the component of element \e a. - * - * Returns the size of the component of element \e a. - */ - - int size(T a) - { - int ca = find(a); - return data[ca].second; - } - - }; - - - - - /*******************************************************/ - - -#ifdef DEVELOPMENT_DOCS - - /** - * \brief The auxiliary class for the \ref UnionFindEnum class. - * - * In the \ref UnionFindEnum class all components are represented as - * a std::list. - * Items of these lists are UnionFindEnumItem structures. - * - * The class has four fields: - * - T me - the actual element - * - IIter parent - the parent of the element in the union-find structure - * - int size - the size of the component of the element. - * Only valid if the element - * is the leader of the component. - * - CIter my_class - pointer into the list of components - * pointing to the component of the element. - * Only valid if the element is the leader of the component. - */ - -#endif - - template - struct UnionFindEnumItem { - - typedef std::list ItemList; - typedef std::list ClassList; - typedef typename ItemList::iterator IIter; - typedef typename ClassList::iterator CIter; - - T me; - IIter parent; - int size; - CIter my_class; - - UnionFindEnumItem() {} - UnionFindEnumItem(const T &_me, CIter _my_class): - me(_me), size(1), my_class(_my_class) {} - }; - - - /** - * \brief A \e Union-Find data structure implementation which - * is able to enumerate the components. - * - * The class implements a \e Union-Find data structure - * which is able to enumerate the components and the items in - * a component. If you don't need this feature then perhaps it's - * better to use the \ref UnionFind class which is more efficient. - * - * The union operation uses rank heuristic, while - * the find operation uses path compression. - * - * \pre You - * need to add all the elements by the \ref insert() method. - */ - - - template class Map> - class UnionFindEnum { - - typedef std::list > ItemList; - typedef std::list ClassList; - typedef typename ItemList::iterator IIter; - typedef typename ItemList::const_iterator IcIter; - typedef typename ClassList::iterator CIter; - typedef typename ClassList::const_iterator CcIter; - - public: - typedef T ElementType; - typedef UnionFindEnumItem ItemType; - typedef Map< IIter > MapType; - - private: - MapType& m; - ClassList classes; - - IIter _find(IIter a) const { - IIter comp = a; - IIter next; - while( (next = comp->parent) != comp ) { - comp = next; - } - - IIter comp1 = a; - while( (next = comp1->parent) != comp ) { - comp1->parent = comp->parent; - comp1 = next; - } - return comp; - } - - public: - UnionFindEnum(MapType& _m) : m(_m) {} - - - /** - * \brief Inserts the given element into a new component. - * - * This method creates a new component consisting only of the - * given element. - */ - - void insert(const T &a) - { - - - classes.push_back(ItemList()); - CIter aclass = classes.end(); - --aclass; - - ItemList &alist = *aclass; - alist.push_back(ItemType(a, aclass)); - IIter ai = alist.begin(); - - ai->parent = ai; - m.set(a, ai); - - } - - /** - * \brief Inserts the given element into the component of the others. - * - * This methods inserts the element \e a into the component of the - * element \e comp. - */ - - void insert(const T &a, const T &comp) { - - IIter clit = _find(m[comp]); - ItemList &c = *clit->my_class; - c.push_back(ItemType(a,0)); - IIter ai = c.end(); - --ai; - ai->parent = clit; - m.set(a, ai); - ++clit->size; - } - - - /** - * \brief Finds the leader of the component of the given element. - * - * The method returns the leader of the component of the given element. - */ - - T find(const T &a) const { - return _find(m[a])->me; - } - - - /** - * \brief Joining the component of element \e a and element \e b. - * - * This is the \e union operation of the Union-Find structure. - * Joins the component of element \e a and component of - * element \e b. If \e a and \e b are in the same component then - * returns false else returns true. - */ - - bool join(T a, T b) { - - IIter ca = _find(m[a]); - IIter cb = _find(m[b]); - - if ( ca == cb ) { - return false; - } - - if ( ca->size > cb->size ) { - - cb->parent = ca->parent; - ca->size += cb->size; - - ItemList &alist = *ca->my_class; - alist.splice(alist.end(),*cb->my_class); - - classes.erase(cb->my_class); - cb->my_class = 0; - } - else { - - ca->parent = cb->parent; - cb->size += ca->size; - - ItemList &blist = *cb->my_class; - blist.splice(blist.end(),*ca->my_class); - - classes.erase(ca->my_class); - ca->my_class = 0; - } - - return true; - } - - - /** - * \brief Returns the size of the component of element \e a. - * - * Returns the size of the component of element \e a. - */ - - int size(const T &a) const { - return _find(m[a])->size; - } - - - /** - * \brief Splits up the component of the element. - * - * Splitting the component of the element into sigleton - * components (component of size one). - */ - - void split(const T &a) { - - IIter ca = _find(m[a]); - - if ( ca->size == 1 ) - return; - - CIter aclass = ca->my_class; - - for(IIter curr = ca; ++curr != aclass->end(); curr=ca) { - classes.push_back(ItemList()); - CIter nl = --classes.end(); - nl->splice(nl->end(), *aclass, curr); - - curr->size=1; - curr->parent=curr; - curr->my_class = nl; - } - - ca->size=1; - return; - } - - - /** - * \brief Sets the given element to the leader element of its component. - * - * Sets the given element to the leader element of its component. - */ - - void makeRep(const T &a) { - - IIter ia = m[a]; - IIter la = _find(ia); - if (la == ia) return; - - ia->my_class = la->my_class; - la->my_class = 0; - - ia->size = la->size; - - CIter l = ia->my_class; - l->splice(l->begin(),*l,ia); - - ia->parent = ia; - la->parent = ia; - } - - /** - * \brief Moves the given element to an other component. - * - * This method moves the element \e a from its component - * to the component of \e comp. - * If \e a and \e comp are in the same component then - * it returns false otherwise it returns true. - */ - - bool move(const T &a, const T &comp) { - - IIter ai = m[a]; - IIter lai = _find(ai); - IIter clit = _find(m[comp]); - - if (lai == clit) - return false; - - ItemList &cl = *clit->my_class, - &al = *lai->my_class; - - bool is_leader = (lai == ai); - bool singleton = false; - - if (is_leader) { - ++lai; - } - - cl.splice(cl.end(), al, ai); - - if (is_leader) { - if (ai->size == 1) { - classes.erase(ai->my_class); - singleton = true; - } - else { - lai->size = ai->size; - lai->my_class = ai->my_class; - } - } - if (!singleton) { - for (IIter i = lai; i != al.end(); ++i) - i->parent = lai; - --lai->size; - } - - ai->parent = clit; - ai->my_class = 0; - ++clit->size; - - return true; - } - - - /** - * \brief Removes the given element from the structure. - * - * Removes the given element from the structure. - * - * Removes the element from its component and if the component becomes - * empty then removes that component from the component list. - */ - void erase(const T &a) { - - IIter ma = m[a]; - if (ma == 0) return; - - IIter la = _find(ma); - if (la == ma) { - if (ma -> size == 1){ - classes.erase(ma->my_class); - m.set(a,0); - return; - } - ++la; - la->size = ma->size; - la->my_class = ma->my_class; - } - - for (IIter i = la; i != la->my_class->end(); ++i) { - i->parent = la; - } - - la->size--; - la->my_class->erase(ma); - m.set(a,0); - } - - /** - * \brief Removes the component of the given element from the structure. - * - * Removes the component of the given element from the structure. - */ - - void eraseClass(const T &a) { - IIter ma = m[a]; - if (ma == 0) return; -# ifdef DEBUG - CIter c = _find(ma)->my_class; - for (IIter i=c->begin(); i!=c->end(); ++i) - m.set(i->me, 0); -# endif - classes.erase(_find(ma)->my_class); - } - - - class ClassIt { - friend class UnionFindEnum; - - CcIter i; - public: - ClassIt(Invalid): i(0) {} - ClassIt() {} - - operator const T& () const { - ItemList const &ll = *i; - return (ll.begin())->me; } - bool operator == (ClassIt it) const { - return (i == it.i); - } - bool operator != (ClassIt it) const { - return (i != it.i); - } - bool operator < (ClassIt it) const { - return (i < it.i); - } - - bool valid() const { return i != 0; } - private: - void first(const ClassList &l) { i = l.begin(); validate(l); } - void next(const ClassList &l) { - ++i; - validate(l); - } - void validate(const ClassList &l) { - if ( i == l.end() ) - i = 0; - } - }; - - /** - * \brief Sets the iterator to point to the first component. - * - * Sets the iterator to point to the first component. - * - * With the \ref first, \ref valid and \ref next methods you can - * iterate through the components. For example: - * \code - * UnionFindEnum::MapType map(G); - * UnionFindEnum U(map); - * UnionFindEnum::ClassIt iter; - * for (U.first(iter); U.valid(iter); U.next(iter)) { - * // iter is convertible to Graph::Node - * cout << iter << endl; - * } - * \endcode - */ - - ClassIt& first(ClassIt& it) const { - it.first(classes); - return it; - } - - /** - * \brief Returns whether the iterator is valid. - * - * Returns whether the iterator is valid. - * - * With the \ref first, \ref valid and \ref next methods you can - * iterate through the components. See the example here: \ref first. - */ - - bool valid(ClassIt const &it) const { - return it.valid(); - } - - /** - * \brief Steps the iterator to the next component. - * - * Steps the iterator to the next component. - * - * With the \ref first, \ref valid and \ref next methods you can - * iterate through the components. See the example here: \ref first. - */ - - ClassIt& next(ClassIt& it) const { - it.next(classes); - return it; - } - - - class ItemIt { - friend class UnionFindEnum; - - IcIter i; - const ItemList *l; - public: - ItemIt(Invalid): i(0) {} - ItemIt() {} - - operator const T& () const { return i->me; } - bool operator == (ItemIt it) const { - return (i == it.i); - } - bool operator != (ItemIt it) const { - return (i != it.i); - } - bool operator < (ItemIt it) const { - return (i < it.i); - } - - bool valid() const { return i != 0; } - private: - void first(const ItemList &il) { l=&il; i = l->begin(); validate(); } - void next() { - ++i; - validate(); - } - void validate() { - if ( i == l->end() ) - i = 0; - } - }; - - - - /** - * \brief Sets the iterator to point to the first element of the component. - * - * \anchor first2 - * Sets the iterator to point to the first element of the component. - * - * With the \ref first2 "first", \ref valid2 "valid" - * and \ref next2 "next" methods you can - * iterate through the elements of a component. For example - * (iterating through the component of the node \e node): - * \code - * Graph::Node node = ...; - * UnionFindEnum::MapType map(G); - * UnionFindEnum U(map); - * UnionFindEnum::ItemIt iiter; - * for (U.first(iiter, node); U.valid(iiter); U.next(iiter)) { - * // iiter is convertible to Graph::Node - * cout << iiter << endl; - * } - * \endcode - */ - - ItemIt& first(ItemIt& it, const T& a) const { - it.first( * _find(m[a])->my_class ); - return it; - } - - /** - * \brief Returns whether the iterator is valid. - * - * \anchor valid2 - * Returns whether the iterator is valid. - * - * With the \ref first2 "first", \ref valid2 "valid" - * and \ref next2 "next" methods you can - * iterate through the elements of a component. - * See the example here: \ref first2 "first". - */ - - bool valid(ItemIt const &it) const { - return it.valid(); - } - - /** - * \brief Steps the iterator to the next component. - * - * \anchor next2 - * Steps the iterator to the next component. - * - * With the \ref first2 "first", \ref valid2 "valid" - * and \ref next2 "next" methods you can - * iterate through the elements of a component. - * See the example here: \ref first2 "first". - */ - - ItemIt& next(ItemIt& it) const { - it.next(); - return it; - } - - }; - - - //! @} - -} //namespace lemon - -#endif //LEMON_UNION_FIND_H diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/utility.h --- a/src/lemon/utility.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -/* -*- C++ -*- - * - * src/lemon/utility.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi - * Kutatocsoport (Egervary Research Group on Combinatorial Optimization, - * EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - * This file contains a modified version of the enable_if library from BOOST. - * See the appropriate copyright notice below. - */ - -// Boost enable_if library - -// Copyright 2003 Š The Trustees of Indiana University. - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Authors: Jaakko Järvi (jajarvi at osl.iu.edu) -// Jeremiah Willcock (jewillco at osl.iu.edu) -// Andrew Lumsdaine (lums at osl.iu.edu) - - -#ifndef LEMON_UTILITY_H -#define LEMON_UTILITY_H - -namespace lemon -{ - - /// Basic type for defining "tags". A "YES" condition for enable_if. - - /// \todo This should go to a separate "basic_types.h" (or something) - /// file. - struct True { - static const bool value = true; - }; - - /// Basic type for defining "tags". A "NO" condition for enable_if. - struct False { - static const bool value = false; - }; - - template - struct Wrap { - const T &value; - Wrap(const T &t) : value(t) {} - }; - - /**************** dummy class to avoid ambiguity ****************/ - - template struct dummy { dummy(int) {} }; - - /**************** enable_if from BOOST ****************/ - - template - struct enable_if_c { - typedef T type; - }; - - template - struct enable_if_c {}; - - template - struct enable_if : public enable_if_c {}; - - template - struct lazy_enable_if_c { - typedef typename T::type type; - }; - - template - struct lazy_enable_if_c {}; - - template - struct lazy_enable_if : public lazy_enable_if_c {}; - - - template - struct disable_if_c { - typedef T type; - }; - - template - struct disable_if_c {}; - - template - struct disable_if : public disable_if_c {}; - - template - struct lazy_disable_if_c { - typedef typename T::type type; - }; - - template - struct lazy_disable_if_c {}; - - template - struct lazy_disable_if : public lazy_disable_if_c {}; - - // smart referencing - - template - struct SmartReference { - typedef _Type& Type; - }; - - template - struct SmartReference< - _Type, - typename enable_if::type - > { - typedef _Type Type; - }; - - template - struct SmartConstReference { - typedef const _Type& Type; - }; - - template - struct SmartConstReference< - _Type, - typename enable_if::type - > { - typedef const _Type Type; - }; - - template - struct SmartParameter { - typedef _Type& Type; - }; - - template - struct SmartParameter< - _Type, - typename enable_if::type - > { - typedef const _Type& Type; - }; - -} // namespace lemon - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/xy.h --- a/src/lemon/xy.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,518 +0,0 @@ -/* -*- C++ -*- - * src/lemon/xy.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_XY_H -#define LEMON_XY_H - -#include -#include - -///\ingroup misc -///\file -///\brief A simple two dimensional vector and a bounding box implementation -/// -/// The class \ref lemon::xy "xy" implements -///a two dimensional vector with the usual -/// operations. -/// -/// The class \ref lemon::BoundingBox "BoundingBox" can be used to determine -/// the rectangular bounding box of a set of \ref lemon::xy "xy"'s. -/// -///\author Attila Bernath - - -namespace lemon { - - /// \addtogroup misc - /// @{ - - /// A simple two dimensional vector (plainvector) implementation - - /// A simple two dimensional vector (plainvector) implementation - ///with the usual vector - /// operators. - /// - ///\author Attila Bernath - template - class xy { - - public: - - typedef T Value; - - T x,y; - - ///Default constructor - xy() {} - - ///Constructing the instance from coordinates - xy(T a, T b) : x(a), y(b) { } - - - ///Conversion constructor - template xy(const xy &p) : x(p.x), y(p.y) {} - - ///Gives back the square of the norm of the vector - T normSquare() const { - return x*x+y*y; - } - - ///Increments the left hand side by u - xy& operator +=(const xy& u) { - x += u.x; - y += u.y; - return *this; - } - - ///Decrements the left hand side by u - xy& operator -=(const xy& u) { - x -= u.x; - y -= u.y; - return *this; - } - - ///Multiplying the left hand side with a scalar - xy& operator *=(const T &u) { - x *= u; - y *= u; - return *this; - } - - ///Dividing the left hand side by a scalar - xy& operator /=(const T &u) { - x /= u; - y /= u; - return *this; - } - - ///Returns the scalar product of two vectors - T operator *(const xy& u) const { - return x*u.x+y*u.y; - } - - ///Returns the sum of two vectors - xy operator+(const xy &u) const { - xy b=*this; - return b+=u; - } - - ///Returns the neg of the vectors - xy operator-() const { - xy b=*this; - b.x=-b.x; b.y=-b.y; - return b; - } - - ///Returns the difference of two vectors - xy operator-(const xy &u) const { - xy b=*this; - return b-=u; - } - - ///Returns a vector multiplied by a scalar - xy operator*(const T &u) const { - xy b=*this; - return b*=u; - } - - ///Returns a vector divided by a scalar - xy operator/(const T &u) const { - xy b=*this; - return b/=u; - } - - ///Testing equality - bool operator==(const xy &u) const { - return (x==u.x) && (y==u.y); - } - - ///Testing inequality - bool operator!=(xy u) const { - return (x!=u.x) || (y!=u.y); - } - - }; - - ///Returns a vector multiplied by a scalar - - ///Returns a vector multiplied by a scalar - ///\relates xy - template xy operator*(const T &u,const xy &x) { - return x*u; - } - - ///Read a plainvector from a stream - - ///Read a plainvector from a stream - ///\relates xy - /// - template - inline std::istream& operator>>(std::istream &is, xy &z) { - char c; - if (is >> c) { - if (c != '(') is.putback(c); - } else { - is.clear(); - } - if (!(is >> z.x)) return is; - if (is >> c) { - if (c != ',') is.putback(c); - } else { - is.clear(); - } - if (!(is >> z.y)) return is; - if (is >> c) { - if (c != ')') is.putback(c); - } else { - is.clear(); - } - return is; - } - - ///Write a plainvector to a stream - - ///Write a plainvector to a stream - ///\relates xy - /// - template - inline std::ostream& operator<<(std::ostream &os, const xy& z) - { - os << "(" << z.x << ", " << z.y << ")"; - return os; - } - - ///Rotate by 90 degrees - - ///Returns its parameter rotated by 90 degrees in positive direction. - ///\relates xy - /// - template - inline xy rot90(const xy &z) - { - return xy(-z.y,z.x); - } - - ///Rotate by 270 degrees - - ///Returns its parameter rotated by 90 degrees in negative direction. - ///\relates xy - /// - template - inline xy rot270(const xy &z) - { - return xy(z.y,-z.x); - } - - - - /// A class to calculate or store the bounding box of plainvectors. - - /// A class to calculate or store the bounding box of plainvectors. - /// - ///\author Attila Bernath - template - class BoundingBox { - xy bottom_left, top_right; - bool _empty; - public: - - ///Default constructor: creates an empty bounding box - BoundingBox() { _empty = true; } - - ///Constructing the instance from one point - BoundingBox(xy a) { bottom_left=top_right=a; _empty = false; } - - ///Were any points added? - bool empty() const { - return _empty; - } - - ///Makes the BoundingBox empty - void clear() { - _empty=1; - } - - ///Gives back the bottom left corner (if the bounding box is empty, then the return value is not defined) - xy bottomLeft() const { - return bottom_left; - } - - ///Gives back the top right corner (if the bounding box is empty, then the return value is not defined) - xy topRight() const { - return top_right; - } - - ///Gives back the bottom right corner (if the bounding box is empty, then the return value is not defined) - xy bottomRight() const { - return xy(top_right.x,bottom_left.y); - } - - ///Gives back the top left corner (if the bounding box is empty, then the return value is not defined) - xy topLeft() const { - return xy(bottom_left.x,top_right.y); - } - - ///Gives back the bottom of the box (if the bounding box is empty, then the return value is not defined) - T bottom() const { - return bottom_left.y; - } - - ///Gives back the top of the box (if the bounding box is empty, then the return value is not defined) - T top() const { - return top_right.y; - } - - ///Gives back the left side of the box (if the bounding box is empty, then the return value is not defined) - T left() const { - return bottom_left.x; - } - - ///Gives back the right side of the box (if the bounding box is empty, then the return value is not defined) - T right() const { - return top_right.x; - } - - ///Gives back the height of the box (if the bounding box is empty, then the return value is not defined) - T height() const { - return top_right.y-bottom_left.y; - } - - ///Gives back the width of the box (if the bounding box is empty, then the return value is not defined) - T width() const { - return top_right.x-bottom_left.x; - } - - ///Checks whether a point is inside a bounding box - bool inside(const xy& u){ - if (_empty) - return false; - else{ - return ((u.x-bottom_left.x)*(top_right.x-u.x) >= 0 && - (u.y-bottom_left.y)*(top_right.y-u.y) >= 0 ); - } - } - - ///Increments a bounding box with a point - BoundingBox& operator +=(const xy& u){ - if (_empty){ - bottom_left=top_right=u; - _empty = false; - } - else{ - if (bottom_left.x > u.x) bottom_left.x = u.x; - if (bottom_left.y > u.y) bottom_left.y = u.y; - if (top_right.x < u.x) top_right.x = u.x; - if (top_right.y < u.y) top_right.y = u.y; - } - return *this; - } - - ///Sums a bounding box and a point - BoundingBox operator +(const xy& u){ - BoundingBox b = *this; - return b += u; - } - - ///Increments a bounding box with an other bounding box - BoundingBox& operator +=(const BoundingBox &u){ - if ( !u.empty() ){ - *this += u.bottomLeft(); - *this += u.topRight(); - } - return *this; - } - - ///Sums two bounding boxes - BoundingBox operator +(const BoundingBox& u){ - BoundingBox b = *this; - return b += u; - } - - };//class Boundingbox - - - ///Map of x-coordinates of an xy<>-map - - ///\ingroup maps - /// - template - class XMap - { - typename SmartReference::Type _map; - public: - typedef True NeedCopy; - - typedef typename M::Value::Value Value; - typedef typename M::Key Key; - ///\e - XMap(typename SmartParameter::Type map) : _map(map) {} - Value operator[](Key k) const {return _map[k].x;} - void set(Key k,Value v) {_map.set(k,typename M::Value(v,_map[k].y));} - }; - - ///Returns an \ref XMap class - - ///This function just returns an \ref XMap class. - /// - ///\ingroup maps - ///\relates XMap - template - inline XMap xMap(M &m) - { - return XMap(m); - } - - template - inline XMap xMap(const M &m) - { - return XMap(m); - } - - ///Constant (read only) version of \ref XMap - - ///\ingroup maps - /// - template - class ConstXMap - { - typename SmartConstReference::Type _map; - public: - typedef True NeedCopy; - - typedef typename M::Value::Value Value; - typedef typename M::Key Key; - ///\e - ConstXMap(const M &map) : _map(map) {} - Value operator[](Key k) const {return _map[k].x;} - }; - - ///Returns a \ref ConstXMap class - - ///This function just returns an \ref ConstXMap class. - /// - ///\ingroup maps - ///\relates ConstXMap - template - inline ConstXMap xMap(const M &m) - { - return ConstXMap(m); - } - - ///Map of y-coordinates of an xy<>-map - - ///\ingroup maps - /// - template - class YMap - { - typename SmartReference::Type _map; - public: - typedef True NeedCopy; - - typedef typename M::Value::Value Value; - typedef typename M::Key Key; - ///\e - YMap(typename SmartParameter::Type map) : _map(map) {} - Value operator[](Key k) const {return _map[k].y;} - void set(Key k,Value v) {_map.set(k,typename M::Value(_map[k].x,v));} - }; - - ///Returns an \ref YMap class - - ///This function just returns an \ref YMap class. - /// - ///\ingroup maps - ///\relates YMap - template - inline YMap yMap(M &m) - { - return YMap(m); - } - - template - inline YMap yMap(const M &m) - { - return YMap(m); - } - - ///Constant (read only) version of \ref YMap - - ///\ingroup maps - /// - template - class ConstYMap - { - typename SmartConstReference::Type _map; - public: - typedef True NeedCopy; - - typedef typename M::Value::Value Value; - typedef typename M::Key Key; - ///\e - ConstYMap(const M &map) : _map(map) {} - Value operator[](Key k) const {return _map[k].y;} - }; - - ///Returns a \ref ConstYMap class - - ///This function just returns an \ref ConstYMap class. - /// - ///\ingroup maps - ///\relates ConstYMap - template - inline ConstYMap yMap(const M &m) - { - return ConstYMap(m); - } - - - ///Map of the \ref xy::normSquare() "normSquare()" of an \ref xy "xy"-map - - ///Map of the \ref xy::normSquare() "normSquare()" of an \ref xy "xy"-map - ///\ingroup maps - /// - template - class NormSquareMap - { - typename SmartConstReference::Type _map; - public: - typedef True NeedCopy; - - typedef typename M::Value::Value Value; - typedef typename M::Key Key; - ///\e - NormSquareMap(const M &map) : _map(map) {} - Value operator[](Key k) const {return _map[k].normSquare();} - }; - - ///Returns a \ref NormSquareMap class - - ///This function just returns an \ref NormSquareMap class. - /// - ///\ingroup maps - ///\relates NormSquareMap - template - inline NormSquareMap normSquareMap(const M &m) - { - return NormSquareMap(m); - } - - /// @} - - -} //namespace lemon - -#endif //LEMON_XY_H diff -r d8475431bbbb -r 8e85e6bbefdf src/test/Makefile.am --- a/src/test/Makefile.am Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/src -LDADD = $(top_builddir)/src/lemon/libemon.la - -EXTRA_DIST = preflow_graph.dim dijkstra_test.lgf - -noinst_HEADERS = \ - test_tools.h \ - graph_test.h \ - sym_graph_test.h \ - map_test.h \ - graph_utils_test.h \ - heap_test.h - -check_PROGRAMS = \ - bfs_test \ - dfs_test \ - dijkstra_test \ - graph_test \ - graph_adaptor_test \ - graph_utils_test \ - kruskal_test \ - max_matching_test \ - maps_test \ - min_cost_flow_test \ - suurballe_test \ - path_test \ - preflow_test \ - test_tools_fail \ - test_tools_pass \ - time_measure_test \ - unionfind_test \ - undir_graph_test \ - xy_test \ - heap_test - -if HAVE_GLPK -check_PROGRAMS += lp_test -else !HAVE_GLPK -if HAVE_CPLEX -check_PROGRAMS += lp_test -endif HAVE_CPLEX -endif !HAVE_GLPK - -TESTS = $(check_PROGRAMS) -XFAIL_TESTS = test_tools_fail$(EXEEXT) - -bfs_test_SOURCES = bfs_test.cc -dfs_test_SOURCES = dfs_test.cc -dijkstra_test_SOURCES = dijkstra_test.cc -graph_test_SOURCES = graph_test.cc -graph_utils_test_SOURCES = graph_utils_test.cc -graph_adaptor_test_SOURCES = graph_adaptor_test.cc -kruskal_test_SOURCES = kruskal_test.cc -maps_test_SOURCES = maps_test.cc -min_cost_flow_test_SOURCES = min_cost_flow_test.cc -max_matching_test_SOURCES = max_matching_test.cc -suurballe_test_SOURCES = suurballe_test.cc -path_test_SOURCES = path_test.cc -preflow_test_SOURCES = preflow_test.cc -time_measure_test_SOURCES = time_measure_test.cc -test_tools_fail_SOURCES = test_tools_fail.cc -test_tools_pass_SOURCES = test_tools_pass.cc -unionfind_test_SOURCES = unionfind_test.cc -xy_test_SOURCES = xy_test.cc -undir_graph_test_SOURCES = undir_graph_test.cc -heap_test_SOURCES = heap_test.cc - -lp_test_SOURCES = lp_test.cc -lp_test_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) diff -r d8475431bbbb -r 8e85e6bbefdf src/test/bfs_test.cc --- a/src/test/bfs_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/* -*- C++ -*- - * src/test/bfs_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include "test_tools.h" -#include -#include -#include -#include - -using namespace lemon; - -const int PET_SIZE =5; - - -void check_Bfs_Compile() -{ - typedef concept::StaticGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - - typedef Bfs BType; - - Graph G; - Node n; - Edge e; - int l; - bool b; - BType::DistMap d(G); - BType::PredMap p(G); - // BType::PredNodeMap pn(G); - - BType bfs_test(G); - - bfs_test.run(n); - - l = bfs_test.dist(n); - e = bfs_test.pred(n); - n = bfs_test.predNode(n); - d = bfs_test.distMap(); - p = bfs_test.predMap(); - // pn = bfs_test.predNodeMap(); - b = bfs_test.reached(n); - - DirPath pp(G); - bfs_test.getPath(pp,n); -} - -void check_Bfs_Function_Compile() -{ - typedef int VType; - typedef concept::StaticGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef concept::ReadMap LengthMap; - - bfs(Graph(),Node()).run(); - bfs(Graph()).source(Node()).run(); - bfs(Graph()) - .predMap(concept::WriteMap()) - .distMap(concept::WriteMap()) - .reachedMap(concept::ReadWriteMap()) - .processedMap(concept::WriteMap()) - .run(Node()); - -} - -int main() -{ - - typedef SmartGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef Graph::EdgeMap LengthMap; - - Graph G; - Node s, t; - PetStruct ps = addPetersen(G,PET_SIZE); - - s=ps.outer[2]; - t=ps.inner[0]; - - Bfs bfs_test(G); - bfs_test.run(s); - - check(bfs_test.dist(t)==3,"Bfs found a wrong path. " << bfs_test.dist(t)); - - DirPath p(G); - check(bfs_test.getPath(p,t),"getPath() failed to set the path."); - check(p.length()==3,"getPath() found a wrong path."); - - - for(EdgeIt e(G); e==INVALID; ++e) { - Node u=G.source(e); - Node v=G.target(e); - check( !bfs_test.reached(u) || - (bfs_test.dist(v) > bfs_test.dist(u)+1), - "Wrong output."); - } - - for(NodeIt v(G); v==INVALID; ++v) { - check(bfs_test.reached(v),"Each node should be reached."); - if ( bfs_test.pred(v)!=INVALID ) { - Edge e=bfs_test.pred(v); - Node u=G.source(e); - check(u==bfs_test.predNode(v),"Wrong tree."); - check(bfs_test.dist(v) - bfs_test.dist(u) == 1, - "Wrong distance. Difference: " - << std::abs(bfs_test.dist(v) - bfs_test.dist(u) - - 1)); - } - } -} - diff -r d8475431bbbb -r 8e85e6bbefdf src/test/dfs_test.cc --- a/src/test/dfs_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -/* -*- C++ -*- - * src/test/dfs_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include "test_tools.h" -#include -#include -#include -#include - -using namespace lemon; - -const int PET_SIZE =5; - - -void check_Dfs_SmartGraph_Compile() -{ - typedef concept::StaticGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - - typedef Dfs DType; - - Graph G; - Node n; - Edge e; - int l; - bool b; - DType::DistMap d(G); - DType::PredMap p(G); - // DType::PredNodeMap pn(G); - - DType dfs_test(G); - - dfs_test.run(n); - - l = dfs_test.dist(n); - e = dfs_test.pred(n); - n = dfs_test.predNode(n); - d = dfs_test.distMap(); - p = dfs_test.predMap(); - // pn = dfs_test.predNodeMap(); - b = dfs_test.reached(n); - - DirPath pp(G); - dfs_test.getPath(pp,n); -} - - -void check_Dfs_Function_Compile() -{ - typedef int VType; - typedef concept::StaticGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef concept::ReadMap LengthMap; - - dfs(Graph(),Node()).run(); - dfs(Graph()).source(Node()).run(); - dfs(Graph()) - .predMap(concept::WriteMap()) - .distMap(concept::WriteMap()) - .reachedMap(concept::ReadWriteMap()) - .processedMap(concept::WriteMap()) - .run(Node()); - -} - -int main() -{ - - typedef SmartGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef Graph::EdgeMap LengthMap; - - Graph G; - Node s, t; - PetStruct ps = addPetersen(G,PET_SIZE); - - s=ps.outer[2]; - t=ps.inner[0]; - - Dfs dfs_test(G); - dfs_test.run(s); - - DirPath p(G); - check(dfs_test.getPath(p,t),"getPath() failed to set the path."); - check(p.length()==dfs_test.dist(t),"getPath() found a wrong path."); - - for(NodeIt v(G); v!=INVALID; ++v) { - check(dfs_test.reached(v),"Each node should be reached."); - if ( dfs_test.pred(v)!=INVALID ) { - Edge e=dfs_test.pred(v); - Node u=G.source(e); - check(u==dfs_test.predNode(v),"Wrong tree."); - check(dfs_test.dist(v) - dfs_test.dist(u) == 1, - "Wrong distance. (" << dfs_test.dist(u) << "->" - < -#include -#include -#include -#include -#include -using namespace lemon; - -const int PET_SIZE =5; - - -void check_Dijkstra_BinHeap_Compile() -{ - typedef int VType; - typedef concept::StaticGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef concept::ReadMap LengthMap; - - typedef Dijkstra DType; - - Graph G; - Node n; - Edge e; - VType l; - bool b; - DType::DistMap d(G); - DType::PredMap p(G); - // DType::PredNodeMap pn(G); - LengthMap cap; - - DType dijkstra_test(G,cap); - - dijkstra_test.run(n); - - l = dijkstra_test.dist(n); - e = dijkstra_test.pred(n); - n = dijkstra_test.predNode(n); - d = dijkstra_test.distMap(); - p = dijkstra_test.predMap(); - // pn = dijkstra_test.predNodeMap(); - b = dijkstra_test.reached(n); - - DirPath pp(G); - dijkstra_test.getPath(pp,n); -} - -void check_Dijkstra_Function_Compile() -{ - typedef int VType; - typedef concept::StaticGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef concept::ReadMap LengthMap; - - dijkstra(Graph(),LengthMap(),Node()).run(); - dijkstra(Graph(),LengthMap()).source(Node()).run(); - dijkstra(Graph(),LengthMap()) - .predMap(concept::WriteMap()) - .distMap(concept::WriteMap()) - .run(Node()); - -} - - -int main() -{ - - typedef SmartGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef Graph::EdgeMap LengthMap; - - Graph G; - Node s, t; - LengthMap cap(G); - PetStruct ps = addPetersen(G,PET_SIZE); - - for(int i=0;i - dijkstra_test(G, cap); - dijkstra_test.run(s); - - check(dijkstra_test.dist(t)==13,"Dijkstra found a wrong path."); - - - DirPath p(G); - check(dijkstra_test.getPath(p,t),"getPath() failed to set the path."); - check(p.length()==4,"getPath() found a wrong path."); - - - for(EdgeIt e(G); e!=INVALID; ++e) { - Node u=G.source(e); - Node v=G.target(e); - check( !dijkstra_test.reached(u) || - (dijkstra_test.dist(v) - dijkstra_test.dist(u) <= cap[e]), - "dist(target)-dist(source)- edge_length= " - << dijkstra_test.dist(v) - dijkstra_test.dist(u) - - cap[e]); - } - - ///\bug This works only for integer lengths - for(NodeIt v(G); v!=INVALID; ++v){ - check(dijkstra_test.reached(v),"Each node should be reached."); - if ( dijkstra_test.pred(v)!=INVALID ) { - Edge e=dijkstra_test.pred(v); - Node u=G.source(e); - check(u==dijkstra_test.predNode(v),"Wrong tree."); - check(dijkstra_test.dist(v) - dijkstra_test.dist(u) == cap[e], - "Wrong distance! Difference: " - << std::abs(dijkstra_test.dist(v) - dijkstra_test.dist(u) - - cap[e])); - } - } - - - { - NullMap myPredMap; - dijkstra(G,cap).predMap(myPredMap).run(s); - } - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/dijkstra_test.lgf --- a/src/test/dijkstra_test.lgf Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7914 +0,0 @@ -@nodeset -id -999 -998 -997 -996 -995 -994 -993 -992 -991 -990 -989 -988 -987 -986 -985 -984 -983 -982 -981 -980 -979 -978 -977 -976 -975 -974 -973 -972 -971 -970 -969 -968 -967 -966 -965 -964 -963 -962 -961 -960 -959 -958 -957 -956 -955 -954 -953 -952 -951 -950 -949 -948 -947 -946 -945 -944 -943 -942 -941 -940 -939 -938 -937 -936 -935 -934 -933 -932 -931 -930 -929 -928 -927 -926 -925 -924 -923 -922 -921 -920 -919 -918 -917 -916 -915 -914 -913 -912 -911 -910 -909 -908 -907 -906 -905 -904 -903 -902 -901 -900 -899 -898 -897 -896 -895 -894 -893 -892 -891 -890 -889 -888 -887 -886 -885 -884 -883 -882 -881 -880 -879 -878 -877 -876 -875 -874 -873 -872 -871 -870 -869 -868 -867 -866 -865 -864 -863 -862 -861 -860 -859 -858 -857 -856 -855 -854 -853 -852 -851 -850 -849 -848 -847 -846 -845 -844 -843 -842 -841 -840 -839 -838 -837 -836 -835 -834 -833 -832 -831 -830 -829 -828 -827 -826 -825 -824 -823 -822 -821 -820 -819 -818 -817 -816 -815 -814 -813 -812 -811 -810 -809 -808 -807 -806 -805 -804 -803 -802 -801 -800 -799 -798 -797 -796 -795 -794 -793 -792 -791 -790 -789 -788 -787 -786 -785 -784 -783 -782 -781 -780 -779 -778 -777 -776 -775 -774 -773 -772 -771 -770 -769 -768 -767 -766 -765 -764 -763 -762 -761 -760 -759 -758 -757 -756 -755 -754 -753 -752 -751 -750 -749 -748 -747 -746 -745 -744 -743 -742 -741 -740 -739 -738 -737 -736 -735 -734 -733 -732 -731 -730 -729 -728 -727 -726 -725 -724 -723 -722 -721 -720 -719 -718 -717 -716 -715 -714 -713 -712 -711 -710 -709 -708 -707 -706 -705 -704 -703 -702 -701 -700 -699 -698 -697 -696 -695 -694 -693 -692 -691 -690 -689 -688 -687 -686 -685 -684 -683 -682 -681 -680 -679 -678 -677 -676 -675 -674 -673 -672 -671 -670 -669 -668 -667 -666 -665 -664 -663 -662 -661 -660 -659 -658 -657 -656 -655 -654 -653 -652 -651 -650 -649 -648 -647 -646 -645 -644 -643 -642 -641 -640 -639 -638 -637 -636 -635 -634 -633 -632 -631 -630 -629 -628 -627 -626 -625 -624 -623 -622 -621 -620 -619 -618 -617 -616 -615 -614 -613 -612 -611 -610 -609 -608 -607 -606 -605 -604 -603 -602 -601 -600 -599 -598 -597 -596 -595 -594 -593 -592 -591 -590 -589 -588 -587 -586 -585 -584 -583 -582 -581 -580 -579 -578 -577 -576 -575 -574 -573 -572 -571 -570 -569 -568 -567 -566 -565 -564 -563 -562 -561 -560 -559 -558 -557 -556 -555 -554 -553 -552 -551 -550 -549 -548 -547 -546 -545 -544 -543 -542 -541 -540 -539 -538 -537 -536 -535 -534 -533 -532 -531 -530 -529 -528 -527 -526 -525 -524 -523 -522 -521 -520 -519 -518 -517 -516 -515 -514 -513 -512 -511 -510 -509 -508 -507 -506 -505 -504 -503 -502 -501 -500 -499 -498 -497 -496 -495 -494 -493 -492 -491 -490 -489 -488 -487 -486 -485 -484 -483 -482 -481 -480 -479 -478 -477 -476 -475 -474 -473 -472 -471 -470 -469 -468 -467 -466 -465 -464 -463 -462 -461 -460 -459 -458 -457 -456 -455 -454 -453 -452 -451 -450 -449 -448 -447 -446 -445 -444 -443 -442 -441 -440 -439 -438 -437 -436 -435 -434 -433 -432 -431 -430 -429 -428 -427 -426 -425 -424 -423 -422 -421 -420 -419 -418 -417 -416 -415 -414 -413 -412 -411 -410 -409 -408 -407 -406 -405 -404 -403 -402 -401 -400 -399 -398 -397 -396 -395 -394 -393 -392 -391 -390 -389 -388 -387 -386 -385 -384 -383 -382 -381 -380 -379 -378 -377 -376 -375 -374 -373 -372 -371 -370 -369 -368 -367 -366 -365 -364 -363 -362 -361 -360 -359 -358 -357 -356 -355 -354 -353 -352 -351 -350 -349 -348 -347 -346 -345 -344 -343 -342 -341 -340 -339 -338 -337 -336 -335 -334 -333 -332 -331 -330 -329 -328 -327 -326 -325 -324 -323 -322 -321 -320 -319 -318 -317 -316 -315 -314 -313 -312 -311 -310 -309 -308 -307 -306 -305 -304 -303 -302 -301 -300 -299 -298 -297 -296 -295 -294 -293 -292 -291 -290 -289 -288 -287 -286 -285 -284 -283 -282 -281 -280 -279 -278 -277 -276 -275 -274 -273 -272 -271 -270 -269 -268 -267 -266 -265 -264 -263 -262 -261 -260 -259 -258 -257 -256 -255 -254 -253 -252 -251 -250 -249 -248 -247 -246 -245 -244 -243 -242 -241 -240 -239 -238 -237 -236 -235 -234 -233 -232 -231 -230 -229 -228 -227 -226 -225 -224 -223 -222 -221 -220 -219 -218 -217 -216 -215 -214 -213 -212 -211 -210 -209 -208 -207 -206 -205 -204 -203 -202 -201 -200 -199 -198 -197 -196 -195 -194 -193 -192 -191 -190 -189 -188 -187 -186 -185 -184 -183 -182 -181 -180 -179 -178 -177 -176 -175 -174 -173 -172 -171 -170 -169 -168 -167 -166 -165 -164 -163 -162 -161 -160 -159 -158 -157 -156 -155 -154 -153 -152 -151 -150 -149 -148 -147 -146 -145 -144 -143 -142 -141 -140 -139 -138 -137 -136 -135 -134 -133 -132 -131 -130 -129 -128 -127 -126 -125 -124 -123 -122 -121 -120 -119 -118 -117 -116 -115 -114 -113 -112 -111 -110 -109 -108 -107 -106 -105 -104 -103 -102 -101 -100 -99 -98 -97 -96 -95 -94 -93 -92 -91 -90 -89 -88 -87 -86 -85 -84 -83 -82 -81 -80 -79 -78 -77 -76 -75 -74 -73 -72 -71 -70 -69 -68 -67 -66 -65 -64 -63 -62 -61 -60 -59 -58 -57 -56 -55 -54 -53 -52 -51 -50 -49 -48 -47 -46 -45 -44 -43 -42 -41 -40 -39 -38 -37 -36 -35 -34 -33 -32 -31 -30 -29 -28 -27 -26 -25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 -0 -@edgeset - id capacity -75 377 6906 27 -417 515 6905 69 -603 249 6904 80 -246 344 6903 69 -382 827 6902 19 -714 879 6901 76 -13 481 6900 22 -863 754 6899 97 -19 530 6898 64 -122 597 6897 78 -861 579 6896 17 -266 888 6895 65 -905 105 6894 81 -516 501 6893 35 -948 430 6892 86 -398 535 6891 66 -727 258 6890 70 -223 322 6889 15 -933 864 6888 84 -17 604 6887 89 -691 520 6886 26 -782 843 6885 59 -604 457 6884 36 -70 492 6883 38 -895 195 6882 56 -277 968 6881 55 -935 550 6880 67 -457 306 6879 50 -260 946 6878 29 -84 636 6877 91 -677 665 6876 32 -385 234 6875 90 -964 972 6874 17 -296 819 6873 53 -227 18 6872 17 -418 879 6871 61 -243 167 6870 34 -359 212 6869 47 -310 374 6868 19 -970 590 6867 17 -431 416 6866 40 -261 730 6865 29 -152 643 6864 42 -800 358 6863 66 -139 557 6862 6 -711 276 6861 80 -954 863 6860 17 -838 279 6859 88 -784 22 6858 4 -173 767 6857 33 -686 116 6856 53 -87 870 6855 16 -284 753 6854 10 -801 599 6853 35 -281 259 6852 66 -412 635 6851 42 -583 291 6850 75 -257 833 6849 11 -254 710 6848 5 -651 799 6847 61 -245 370 6846 48 -117 60 6845 59 -153 757 6844 80 -339 690 6843 48 -624 232 6842 52 -343 671 6841 86 -457 639 6840 82 -123 62 6839 32 -910 442 6838 0 -429 124 6837 60 -310 888 6836 40 -303 796 6835 12 -66 319 6834 96 -457 963 6833 81 -560 651 6832 71 -32 39 6831 28 -577 502 6830 88 -620 323 6829 33 -318 400 6828 21 -235 196 6827 48 -92 277 6826 11 -477 164 6825 0 -356 149 6824 23 -311 98 6823 60 -612 435 6822 89 -537 394 6821 52 -179 552 6820 45 -923 121 6819 95 -203 731 6818 30 -918 362 6817 8 -112 111 6816 14 -15 770 6815 61 -51 628 6814 12 -663 711 6813 4 -41 368 6812 69 -841 73 6811 7 -431 497 6810 35 -389 655 6809 25 -369 218 6808 71 -250 939 6807 28 -341 528 6806 80 -141 493 6805 9 -916 76 6804 96 -343 345 6803 38 -294 623 6802 62 -575 717 6801 19 -842 102 6800 41 -437 535 6799 4 -279 435 6798 2 -410 478 6797 11 -35 709 6796 90 -417 132 6795 20 -730 576 6794 22 -722 766 6793 57 -906 422 6792 4 -615 788 6791 71 -566 369 6790 73 -100 21 6789 40 -957 901 6788 15 -769 209 6787 86 -576 708 6786 37 -556 975 6785 61 -810 651 6784 68 -343 524 6783 0 -634 330 6782 81 -418 984 6781 29 -348 328 6780 4 -119 246 6779 46 -691 289 6778 14 -501 492 6777 18 -733 758 6776 19 -324 930 6775 1 -126 679 6774 74 -194 192 6773 46 -345 524 6772 70 -656 242 6771 21 -82 582 6770 7 -956 322 6769 22 -797 955 6768 42 -734 994 6767 19 -827 173 6766 76 -251 273 6765 40 -487 279 6764 19 -667 757 6763 93 -282 492 6762 84 -659 145 6761 68 -260 840 6760 57 -366 801 6759 12 -960 236 6758 15 -821 422 6757 6 -900 358 6756 90 -993 211 6755 57 -521 265 6754 76 -265 83 6753 81 -346 159 6752 38 -304 114 6751 62 -39 448 6750 39 -565 965 6749 89 -813 96 6748 40 -64 155 6747 13 -147 330 6746 92 -945 812 6745 90 -182 943 6744 47 -923 434 6743 25 -44 763 6742 91 -666 222 6741 4 -482 505 6740 26 -869 487 6739 47 -941 266 6738 75 -825 217 6737 74 -517 14 6736 91 -868 435 6735 20 -509 214 6734 76 -671 338 6733 25 -540 876 6732 87 -717 776 6731 37 -17 791 6730 18 -221 721 6729 61 -49 2 6728 92 -202 831 6727 11 -579 716 6726 30 -220 437 6725 64 -876 505 6724 35 -462 379 6723 83 -99 500 6722 13 -984 195 6721 82 -70 569 6720 69 -719 685 6719 79 -170 812 6718 17 -115 806 6717 84 -278 660 6716 62 -932 288 6715 35 -125 521 6714 34 -879 707 6713 41 -304 308 6712 36 -626 123 6711 11 -883 903 6710 91 -873 624 6709 35 -5 325 6708 54 -146 223 6707 5 -371 264 6706 83 -767 14 6705 34 -814 929 6704 80 -399 52 6703 24 -184 246 6702 57 -219 201 6701 67 -279 563 6700 74 -298 801 6699 0 -102 494 6698 86 -959 217 6697 85 -249 491 6696 77 -84 538 6695 60 -877 560 6694 95 -805 671 6693 41 -45 896 6692 21 -637 935 6691 96 -761 733 6690 94 -307 142 6689 98 -276 7 6688 19 -725 85 6687 14 -953 169 6686 70 -977 650 6685 16 -889 538 6684 20 -775 200 6683 7 -960 248 6682 75 -202 24 6681 40 -591 959 6680 87 -134 785 6679 45 -922 51 6678 3 -915 433 6677 55 -519 545 6676 77 -112 957 6675 97 -337 134 6674 8 -952 312 6673 11 -224 351 6672 81 -64 532 6671 75 -174 421 6670 61 -733 422 6669 45 -618 479 6668 21 -888 778 6667 0 -588 797 6666 39 -822 886 6665 40 -822 974 6664 77 -960 299 6663 38 -819 55 6662 72 -110 147 6661 15 -998 154 6660 89 -943 244 6659 44 -700 204 6658 11 -981 610 6657 73 -910 989 6656 29 -912 631 6655 76 -675 389 6654 0 -243 657 6653 86 -908 567 6652 14 -993 268 6651 70 -909 450 6650 11 -39 324 6649 5 -594 385 6648 24 -620 430 6647 71 -358 533 6646 7 -242 765 6645 99 -731 138 6644 23 -89 720 6643 43 -299 433 6642 33 -818 596 6641 91 -125 56 6640 8 -939 813 6639 86 -954 523 6638 44 -896 647 6637 97 -768 73 6636 26 -627 760 6635 11 -417 805 6634 51 -287 96 6633 64 -836 420 6632 79 -539 831 6631 48 -243 213 6630 69 -290 423 6629 18 -875 472 6628 98 -574 710 6627 5 -312 146 6626 12 -955 605 6625 14 -708 868 6624 20 -676 850 6623 13 -588 310 6622 45 -617 787 6621 29 -790 507 6620 29 -951 201 6619 95 -762 926 6618 41 -563 930 6617 30 -541 987 6616 26 -736 930 6615 35 -18 78 6614 24 -540 680 6613 3 -522 153 6612 8 -280 0 6611 97 -306 343 6610 82 -274 538 6609 83 -996 114 6608 18 -942 38 6607 19 -56 904 6606 2 -851 111 6605 80 -398 213 6604 71 -526 944 6603 47 -153 116 6602 1 -657 143 6601 24 -805 988 6600 97 -423 650 6599 3 -75 990 6598 27 -133 175 6597 5 -793 218 6596 88 -897 86 6595 20 -268 240 6594 45 -828 459 6593 87 -972 776 6592 37 -155 266 6591 49 -338 943 6590 85 -660 753 6589 38 -814 223 6588 34 -957 169 6587 94 -131 680 6586 34 -845 751 6585 89 -781 580 6584 62 -683 498 6583 44 -509 877 6582 85 -323 644 6581 81 -189 470 6580 81 -529 33 6579 67 -54 406 6578 84 -488 601 6577 85 -928 444 6576 82 -171 267 6575 28 -81 188 6574 6 -621 585 6573 9 -233 37 6572 17 -173 0 6571 18 -437 138 6570 13 -627 832 6569 66 -804 989 6568 47 -157 30 6567 56 -176 539 6566 56 -79 222 6565 75 -602 966 6564 8 -547 923 6563 46 -36 988 6562 38 -861 51 6561 5 -306 473 6560 73 -842 185 6559 81 -959 908 6558 82 -490 5 6557 64 -317 802 6556 98 -255 668 6555 9 -42 628 6554 47 -935 72 6553 5 -936 328 6552 51 -578 323 6551 17 -287 925 6550 55 -277 987 6549 46 -902 176 6548 88 -203 665 6547 46 -134 883 6546 17 -39 621 6545 6 -556 420 6544 21 -743 544 6543 10 -4 335 6542 99 -398 619 6541 35 -937 91 6540 29 -811 580 6539 1 -510 414 6538 37 -782 295 6537 69 -261 111 6536 6 -200 848 6535 9 -875 105 6534 48 -209 107 6533 81 -715 641 6532 73 -528 67 6531 60 -511 280 6530 46 -165 635 6529 12 -119 675 6528 30 -183 630 6527 72 -262 973 6526 52 -743 612 6525 6 -998 669 6524 32 -466 74 6523 66 -574 132 6522 49 -786 145 6521 18 -645 334 6520 1 -959 824 6519 34 -44 573 6518 4 -657 206 6517 93 -361 459 6516 92 -942 736 6515 51 -595 658 6514 74 -941 172 6513 53 -986 305 6512 89 -810 170 6511 78 -510 671 6510 14 -250 299 6509 68 -367 109 6508 91 -746 15 6507 38 -723 401 6506 29 -77 774 6505 41 -485 212 6504 34 -866 640 6503 65 -135 103 6502 95 -499 647 6501 17 -371 454 6500 30 -190 771 6499 25 -93 526 6498 88 -614 92 6497 62 -626 876 6496 2 -562 71 6495 64 -571 693 6494 59 -537 698 6493 61 -455 779 6492 73 -193 875 6491 63 -682 40 6490 12 -245 376 6489 18 -434 262 6488 9 -215 597 6487 47 -804 376 6486 98 -378 54 6485 6 -995 973 6484 99 -919 886 6483 3 -903 95 6482 8 -834 508 6481 26 -664 946 6480 51 -113 84 6479 43 -664 618 6478 81 -221 490 6477 21 -322 924 6476 41 -80 72 6475 42 -86 956 6474 38 -791 952 6473 7 -587 820 6472 1 -562 750 6471 6 -862 74 6470 16 -465 626 6469 55 -128 592 6468 44 -565 806 6467 44 -852 985 6466 89 -116 42 6465 24 -4 307 6464 99 -132 60 6463 29 -69 946 6462 20 -676 899 6461 2 -448 619 6460 70 -33 101 6459 39 -786 6 6458 33 -821 544 6457 56 -942 656 6456 71 -735 246 6455 73 -246 699 6454 11 -114 90 6453 87 -46 179 6452 6 -279 324 6451 39 -518 303 6450 22 -94 58 6449 41 -461 774 6448 24 -887 849 6447 96 -410 976 6446 87 -546 624 6445 20 -609 239 6444 48 -911 810 6443 13 -855 668 6442 6 -20 165 6441 76 -244 812 6440 76 -283 168 6439 42 -924 281 6438 63 -872 86 6437 57 -352 671 6436 47 -384 718 6435 86 -429 355 6434 93 -141 65 6433 69 -502 300 6432 5 -352 5 6431 83 -644 338 6430 77 -886 790 6429 96 -195 59 6428 35 -415 96 6427 5 -952 614 6426 51 -363 925 6425 96 -290 239 6424 95 -765 642 6423 28 -294 221 6422 63 -667 58 6421 15 -547 814 6420 70 -731 601 6419 75 -962 307 6418 69 -481 532 6417 78 -689 551 6416 46 -685 14 6415 58 -597 666 6414 7 -420 649 6413 52 -163 488 6412 47 -243 441 6411 62 -213 950 6410 11 -294 66 6409 81 -775 911 6408 76 -980 317 6407 48 -536 873 6406 79 -347 516 6405 0 -17 548 6404 8 -160 54 6403 17 -46 842 6402 25 -491 508 6401 91 -884 302 6400 3 -154 48 6399 91 -593 287 6398 51 -444 688 6397 79 -356 789 6396 44 -968 915 6395 18 -493 911 6394 33 -212 920 6393 85 -333 337 6392 11 -205 889 6391 55 -254 112 6390 60 -760 398 6389 72 -598 725 6388 56 -899 350 6387 14 -874 254 6386 8 -4 858 6385 38 -990 474 6384 47 -583 742 6383 28 -447 558 6382 87 -777 947 6381 12 -713 878 6380 95 -673 168 6379 49 -375 411 6378 16 -95 61 6377 69 -396 699 6376 2 -384 913 6375 87 -731 193 6374 1 -183 403 6373 40 -611 750 6372 13 -69 177 6371 67 -710 456 6370 6 -756 332 6369 4 -350 461 6368 29 -362 675 6367 27 -785 154 6366 69 -720 856 6365 1 -790 605 6364 65 -652 272 6363 54 -572 464 6362 57 -720 607 6361 54 -124 22 6360 35 -870 742 6359 95 -786 17 6358 40 -520 580 6357 98 -297 686 6356 57 -251 359 6355 6 -333 104 6354 93 -807 975 6353 13 -857 30 6352 8 -584 182 6351 85 -280 405 6350 59 -724 547 6349 25 -437 418 6348 8 -893 410 6347 26 -327 512 6346 22 -254 133 6345 4 -129 793 6344 91 -945 56 6343 52 -847 227 6342 94 -777 256 6341 27 -857 342 6340 30 -129 169 6339 55 -7 817 6338 28 -897 43 6337 54 -379 176 6336 56 -339 128 6335 7 -736 392 6334 12 -828 576 6333 18 -971 676 6332 9 -913 969 6331 7 -172 749 6330 91 -352 267 6329 72 -774 744 6328 12 -867 977 6327 11 -47 493 6326 51 -736 947 6325 3 -815 941 6324 60 -899 85 6323 90 -706 27 6322 85 -220 150 6321 5 -481 191 6320 74 -522 607 6319 82 -767 11 6318 57 -483 592 6317 90 -545 478 6316 81 -5 436 6315 31 -856 695 6314 92 -58 50 6313 91 -876 798 6312 19 -959 317 6311 48 -583 920 6310 73 -595 242 6309 95 -419 671 6308 75 -113 86 6307 28 -42 508 6306 93 -740 390 6305 54 -644 4 6304 14 -251 722 6303 79 -481 706 6302 18 -396 747 6301 91 -677 779 6300 37 -571 203 6299 98 -584 471 6298 17 -578 345 6297 30 -118 397 6296 7 -386 391 6295 30 -281 350 6294 9 -16 617 6293 39 -958 263 6292 77 -968 541 6291 8 -575 387 6290 71 -732 811 6289 10 -125 870 6288 98 -948 235 6287 0 -5 768 6286 45 -40 205 6285 73 -733 703 6284 10 -353 622 6283 26 -722 685 6282 5 -154 365 6281 99 -576 612 6280 39 -940 120 6279 84 -635 979 6278 60 -466 546 6277 17 -563 727 6276 94 -501 627 6275 96 -80 838 6274 30 -937 208 6273 38 -319 67 6272 63 -753 597 6271 56 -492 549 6270 57 -140 235 6269 63 -433 430 6268 30 -818 233 6267 16 -100 977 6266 90 -789 658 6265 6 -630 925 6264 42 -141 749 6263 14 -469 62 6262 61 -47 990 6261 56 -313 941 6260 26 -805 331 6259 35 -196 135 6258 70 -256 266 6257 61 -318 841 6256 71 -732 640 6255 31 -176 277 6254 15 -687 526 6253 48 -72 50 6252 67 -48 305 6251 42 -610 909 6250 73 -196 644 6249 50 -868 92 6248 60 -424 895 6247 93 -201 407 6246 93 -362 152 6245 58 -750 669 6244 55 -475 817 6243 48 -745 249 6242 61 -395 688 6241 2 -264 225 6240 43 -551 898 6239 41 -197 669 6238 32 -487 2 6237 44 -255 351 6236 22 -483 29 6235 83 -851 67 6234 61 -568 874 6233 27 -560 591 6232 73 -463 584 6231 34 -326 25 6230 13 -228 86 6229 71 -667 883 6228 35 -651 220 6227 70 -321 385 6226 23 -961 226 6225 77 -193 336 6224 63 -282 544 6223 28 -7 380 6222 0 -559 219 6221 9 -939 417 6220 13 -202 358 6219 9 -663 645 6218 56 -834 477 6217 1 -158 459 6216 32 -889 140 6215 36 -792 349 6214 76 -164 274 6213 91 -161 911 6212 27 -801 960 6211 44 -59 38 6210 61 -712 536 6209 73 -167 545 6208 53 -18 686 6207 82 -318 969 6206 67 -791 591 6205 26 -74 857 6204 9 -362 635 6203 62 -951 827 6202 0 -921 828 6201 36 -502 882 6200 74 -990 198 6199 34 -858 709 6198 54 -717 153 6197 14 -377 406 6196 69 -734 172 6195 52 -222 469 6194 71 -808 625 6193 71 -998 642 6192 41 -945 618 6191 3 -684 394 6190 41 -489 801 6189 51 -556 396 6188 13 -747 449 6187 14 -233 172 6186 34 -703 810 6185 64 -843 4 6184 51 -982 300 6183 41 -24 381 6182 80 -223 612 6181 5 -593 906 6180 26 -405 380 6179 19 -946 990 6178 93 -276 800 6177 80 -362 697 6176 51 -805 131 6175 53 -704 97 6174 85 -919 604 6173 86 -768 757 6172 95 -705 790 6171 80 -525 66 6170 63 -389 262 6169 18 -190 123 6168 45 -103 295 6167 67 -566 983 6166 91 -33 670 6165 55 -493 998 6164 10 -847 902 6163 78 -966 157 6162 15 -724 170 6161 6 -804 441 6160 17 -138 729 6159 13 -828 788 6158 19 -312 756 6157 8 -312 356 6156 53 -671 455 6155 53 -96 316 6154 53 -744 633 6153 64 -987 87 6152 88 -728 882 6151 24 -712 43 6150 91 -941 936 6149 66 -31 112 6148 30 -399 550 6147 51 -900 3 6146 99 -139 993 6145 64 -682 893 6144 57 -546 765 6143 35 -204 638 6142 75 -839 322 6141 25 -106 253 6140 1 -824 356 6139 77 -562 793 6138 90 -546 516 6137 63 -9 359 6136 49 -100 65 6135 76 -127 223 6134 45 -126 595 6133 13 -316 497 6132 34 -69 242 6131 36 -896 246 6130 73 -562 860 6129 28 -277 277 6128 26 -156 132 6127 1 -293 737 6126 53 -842 305 6125 90 -628 319 6124 97 -97 795 6123 0 -255 976 6122 81 -996 632 6121 24 -385 450 6120 17 -582 20 6119 33 -145 245 6118 28 -395 478 6117 12 -432 626 6116 86 -985 937 6115 45 -524 971 6114 21 -819 190 6113 53 -343 563 6112 84 -182 73 6111 25 -429 839 6110 61 -774 48 6109 80 -767 164 6108 43 -852 257 6107 75 -689 411 6106 96 -966 237 6105 44 -780 683 6104 46 -626 688 6103 70 -490 583 6102 47 -234 647 6101 16 -791 807 6100 75 -883 365 6099 65 -906 687 6098 0 -845 787 6097 91 -174 515 6096 16 -554 986 6095 72 -994 755 6094 18 -104 229 6093 15 -935 315 6092 13 -839 407 6091 25 -442 99 6090 44 -678 646 6089 90 -899 92 6088 97 -272 752 6087 6 -528 439 6086 67 -231 537 6085 62 -525 31 6084 55 -914 18 6083 88 -908 880 6082 16 -307 812 6081 9 -452 536 6080 39 -553 929 6079 76 -340 916 6078 77 -312 389 6077 62 -902 51 6076 74 -506 60 6075 29 -13 669 6074 70 -137 720 6073 61 -67 72 6072 0 -276 698 6071 60 -606 633 6070 85 -13 985 6069 89 -526 151 6068 21 -337 882 6067 2 -991 447 6066 41 -390 590 6065 39 -948 95 6064 49 -648 604 6063 87 -374 405 6062 7 -64 744 6061 79 -648 956 6060 66 -833 685 6059 59 -269 185 6058 48 -434 617 6057 18 -857 13 6056 34 -494 903 6055 60 -490 617 6054 44 -198 805 6053 30 -661 278 6052 27 -787 121 6051 30 -271 76 6050 41 -500 105 6049 81 -567 298 6048 56 -604 842 6047 83 -110 746 6046 57 -285 157 6045 36 -812 141 6044 0 -526 26 6043 29 -156 965 6042 53 -44 893 6041 87 -971 600 6040 51 -807 251 6039 77 -456 729 6038 93 -95 257 6037 96 -588 213 6036 49 -15 359 6035 82 -115 712 6034 47 -61 753 6033 28 -71 664 6032 36 -292 356 6031 11 -349 745 6030 7 -521 837 6029 16 -472 970 6028 35 -43 469 6027 36 -854 667 6026 50 -646 352 6025 57 -958 186 6024 90 -89 915 6023 5 -307 257 6022 98 -611 38 6021 77 -907 910 6020 94 -867 811 6019 82 -500 991 6018 4 -802 854 6017 42 -314 933 6016 18 -166 672 6015 20 -271 845 6014 68 -657 65 6013 86 -219 209 6012 78 -127 836 6011 69 -99 114 6010 70 -820 778 6009 3 -136 621 6008 36 -920 238 6007 69 -260 981 6006 48 -827 519 6005 14 -779 819 6004 89 -855 87 6003 61 -373 85 6002 43 -721 991 6001 9 -336 664 6000 2 -157 671 5999 27 -382 669 5998 68 -256 210 5997 21 -462 338 5996 66 -699 253 5995 43 -731 281 5994 4 -1 174 5993 92 -94 346 5992 48 -326 63 5991 65 -993 749 5990 38 -2 595 5989 17 -459 467 5988 77 -871 555 5987 12 -85 226 5986 79 -971 385 5985 76 -106 123 5984 96 -828 441 5983 73 -283 831 5982 90 -313 265 5981 76 -153 206 5980 33 -128 403 5979 99 -911 649 5978 54 -329 331 5977 58 -840 31 5976 78 -262 794 5975 11 -682 237 5974 86 -609 823 5973 27 -565 139 5972 54 -58 434 5971 96 -803 342 5970 15 -754 447 5969 2 -317 955 5968 21 -300 801 5967 58 -236 672 5966 48 -557 248 5965 57 -414 586 5964 57 -684 733 5963 7 -704 575 5962 4 -91 809 5961 50 -894 133 5960 25 -492 809 5959 4 -153 634 5958 43 -129 93 5957 1 -424 909 5956 6 -661 998 5955 67 -853 506 5954 14 -157 29 5953 73 -765 536 5952 97 -676 251 5951 61 -324 207 5950 19 -175 611 5949 40 -540 419 5948 33 -184 953 5947 2 -911 384 5946 70 -492 536 5945 76 -477 412 5944 80 -492 750 5943 69 -285 367 5942 39 -43 415 5941 8 -595 795 5940 35 -192 62 5939 14 -465 315 5938 63 -569 319 5937 35 -847 941 5936 27 -123 955 5935 41 -662 111 5934 1 -383 305 5933 98 -951 301 5932 20 -619 737 5931 24 -733 202 5930 44 -746 513 5929 40 -995 279 5928 72 -378 82 5927 89 -986 854 5926 72 -844 403 5925 72 -806 30 5924 46 -3 776 5923 27 -563 965 5922 43 -534 793 5921 33 -689 44 5920 88 -234 677 5919 98 -196 829 5918 75 -228 175 5917 61 -450 997 5916 39 -373 262 5915 14 -253 182 5914 3 -810 847 5913 80 -172 99 5912 43 -748 445 5911 2 -367 899 5910 84 -848 236 5909 45 -654 132 5908 3 -177 225 5907 96 -735 250 5906 77 -80 103 5905 7 -334 235 5904 11 -748 363 5903 44 -653 410 5902 63 -546 183 5901 42 -662 390 5900 38 -103 417 5899 51 -907 70 5898 19 -975 189 5897 47 -146 701 5896 44 -868 957 5895 65 -871 676 5894 74 -952 804 5893 58 -227 214 5892 9 -792 41 5891 10 -972 862 5890 88 -347 325 5889 55 -880 716 5888 19 -487 34 5887 93 -743 786 5886 82 -280 909 5885 27 -872 159 5884 99 -590 492 5883 91 -172 987 5882 72 -179 223 5881 43 -537 324 5880 81 -608 363 5879 62 -681 264 5878 46 -248 101 5877 39 -877 552 5876 74 -750 280 5875 46 -667 77 5874 40 -505 193 5873 28 -763 290 5872 41 -899 614 5871 99 -961 194 5870 64 -98 158 5869 92 -162 73 5868 92 -549 648 5867 43 -271 280 5866 37 -203 54 5865 12 -883 126 5864 8 -902 864 5863 16 -676 424 5862 74 -420 351 5861 86 -35 712 5860 93 -85 2 5859 86 -424 493 5858 93 -368 62 5857 61 -226 244 5856 27 -928 42 5855 6 -261 921 5854 31 -440 420 5853 98 -72 877 5852 22 -639 925 5851 25 -710 75 5850 38 -508 927 5849 95 -431 322 5848 66 -817 334 5847 5 -202 210 5846 14 -121 748 5845 29 -501 338 5844 66 -542 754 5843 82 -952 970 5842 36 -849 871 5841 43 -148 434 5840 92 -604 289 5839 20 -988 603 5838 7 -123 914 5837 61 -462 844 5836 61 -409 631 5835 8 -584 845 5834 61 -783 453 5833 95 -99 935 5832 58 -436 504 5831 10 -144 726 5830 70 -686 124 5829 54 -689 464 5828 61 -70 998 5827 86 -212 534 5826 66 -786 461 5825 5 -392 660 5824 82 -517 369 5823 80 -431 487 5822 68 -777 401 5821 66 -602 157 5820 29 -659 927 5819 45 -465 751 5818 99 -464 203 5817 61 -72 608 5816 85 -800 227 5815 42 -291 23 5814 39 -881 117 5813 87 -85 21 5812 8 -243 370 5811 65 -230 833 5810 17 -175 461 5809 94 -548 378 5808 19 -594 760 5807 0 -380 432 5806 39 -204 31 5805 27 -905 519 5804 50 -96 787 5803 40 -650 432 5802 79 -536 479 5801 84 -372 231 5800 1 -82 748 5799 5 -618 192 5798 62 -328 609 5797 95 -400 120 5796 21 -512 762 5795 17 -731 99 5794 29 -354 613 5793 80 -953 954 5792 44 -247 829 5791 11 -482 958 5790 16 -555 427 5789 28 -583 673 5788 46 -489 740 5787 29 -357 37 5786 92 -662 877 5785 88 -486 489 5784 78 -659 364 5783 37 -124 331 5782 40 -871 949 5781 70 -530 874 5780 76 -754 826 5779 92 -933 173 5778 97 -702 362 5777 9 -160 40 5776 13 -387 107 5775 69 -124 403 5774 17 -33 975 5773 82 -381 695 5772 53 -74 940 5771 25 -48 838 5770 34 -652 953 5769 77 -810 879 5768 82 -322 961 5767 23 -932 436 5766 54 -704 519 5765 77 -427 348 5764 26 -279 293 5763 9 -755 280 5762 65 -101 913 5761 30 -884 564 5760 2 -74 955 5759 39 -917 590 5758 84 -525 688 5757 48 -916 768 5756 38 -170 510 5755 22 -55 171 5754 27 -12 439 5753 14 -366 345 5752 52 -349 280 5751 65 -609 630 5750 21 -364 553 5749 81 -901 354 5748 15 -919 98 5747 39 -258 161 5746 60 -339 951 5745 74 -731 129 5744 11 -94 623 5743 4 -64 870 5742 64 -649 436 5741 1 -77 406 5740 73 -198 653 5739 24 -256 764 5738 46 -936 784 5737 98 -210 862 5736 66 -822 631 5735 91 -505 72 5734 60 -753 396 5733 63 -433 627 5732 2 -29 278 5731 41 -753 495 5730 57 -889 781 5729 87 -980 481 5728 94 -921 320 5727 31 -231 741 5726 72 -558 312 5725 38 -675 970 5724 31 -769 607 5723 75 -349 614 5722 31 -782 842 5721 40 -713 693 5720 27 -300 936 5719 86 -160 623 5718 90 -578 592 5717 5 -429 338 5716 69 -341 70 5715 67 -363 565 5714 88 -992 432 5713 90 -771 914 5712 41 -149 128 5711 56 -757 411 5710 6 -313 955 5709 41 -30 850 5708 13 -253 367 5707 58 -268 18 5706 14 -505 788 5705 8 -132 976 5704 97 -517 487 5703 37 -786 852 5702 22 -716 498 5701 62 -456 655 5700 39 -104 274 5699 44 -483 557 5698 28 -348 433 5697 77 -229 60 5696 98 -811 109 5695 76 -489 608 5694 37 -635 149 5693 61 -354 598 5692 73 -842 229 5691 6 -380 948 5690 26 -717 161 5689 35 -123 505 5688 62 -372 791 5687 13 -950 222 5686 11 -501 389 5685 41 -459 758 5684 32 -550 883 5683 85 -368 661 5682 28 -281 809 5681 51 -787 908 5680 46 -655 730 5679 66 -713 486 5678 59 -569 15 5677 75 -833 701 5676 42 -630 95 5675 44 -875 467 5674 4 -221 573 5673 90 -851 769 5672 18 -901 49 5671 8 -177 798 5670 49 -244 69 5669 13 -471 842 5668 94 -314 329 5667 14 -606 972 5666 73 -627 406 5665 20 -894 133 5664 75 -803 727 5663 65 -720 93 5662 37 -250 593 5661 94 -729 361 5660 72 -227 190 5659 93 -512 797 5658 77 -357 409 5657 15 -565 532 5656 70 -272 448 5655 97 -405 101 5654 73 -634 283 5653 9 -499 420 5652 8 -231 225 5651 46 -171 791 5650 52 -392 160 5649 50 -387 615 5648 71 -876 448 5647 15 -84 729 5646 79 -346 244 5645 29 -817 642 5644 86 -862 7 5643 77 -195 613 5642 13 -433 947 5641 26 -631 19 5640 5 -544 787 5639 77 -166 558 5638 0 -719 364 5637 51 -484 498 5636 79 -602 425 5635 73 -634 95 5634 52 -394 637 5633 95 -665 866 5632 66 -928 208 5631 76 -232 280 5630 80 -228 773 5629 8 -194 494 5628 37 -866 718 5627 44 -72 55 5626 23 -330 208 5625 88 -458 573 5624 96 -770 287 5623 23 -658 905 5622 72 -927 958 5621 73 -506 716 5620 69 -279 709 5619 0 -776 929 5618 3 -662 213 5617 32 -846 351 5616 79 -634 914 5615 74 -285 727 5614 87 -382 510 5613 68 -946 992 5612 11 -242 41 5611 73 -6 691 5610 42 -779 969 5609 22 -715 706 5608 50 -861 534 5607 11 -437 52 5606 81 -186 869 5605 21 -217 183 5604 34 -518 576 5603 90 -950 380 5602 43 -349 311 5601 70 -722 192 5600 23 -263 724 5599 22 -172 389 5598 6 -481 297 5597 85 -182 604 5596 42 -686 863 5595 25 -607 445 5594 96 -196 468 5593 69 -69 731 5592 56 -118 467 5591 60 -468 9 5590 62 -334 163 5589 45 -92 209 5588 9 -693 429 5587 69 -740 174 5586 29 -417 280 5585 49 -977 270 5584 7 -736 131 5583 41 -263 967 5582 12 -458 972 5581 95 -845 169 5580 65 -953 367 5579 13 -780 401 5578 24 -254 390 5577 39 -893 803 5576 95 -10 417 5575 32 -139 667 5574 44 -163 284 5573 24 -994 176 5572 47 -803 300 5571 80 -802 516 5570 61 -966 891 5569 89 -10 842 5568 17 -586 446 5567 52 -386 629 5566 36 -749 882 5565 88 -383 200 5564 87 -107 767 5563 97 -875 668 5562 16 -784 191 5561 19 -624 720 5560 0 -48 720 5559 83 -395 646 5558 95 -817 165 5557 42 -747 477 5556 20 -682 12 5555 63 -432 895 5554 36 -99 806 5553 27 -476 977 5552 23 -471 190 5551 9 -0 165 5550 15 -73 880 5549 57 -481 531 5548 65 -687 223 5547 57 -465 563 5546 7 -116 271 5545 6 -89 89 5544 24 -828 44 5543 33 -787 140 5542 62 -24 932 5541 0 -284 583 5540 47 -349 922 5539 92 -307 75 5538 59 -660 507 5537 79 -291 5 5536 22 -181 815 5535 34 -45 917 5534 2 -903 708 5533 26 -208 619 5532 4 -348 533 5531 76 -661 544 5530 74 -847 334 5529 93 -567 798 5528 4 -502 571 5527 64 -189 872 5526 36 -897 323 5525 11 -208 765 5524 13 -89 220 5523 14 -86 277 5522 69 -988 22 5521 85 -209 805 5520 68 -536 892 5519 81 -226 395 5518 28 -699 277 5517 6 -549 258 5516 31 -557 974 5515 29 -544 993 5514 68 -942 446 5513 11 -254 835 5512 0 -217 173 5511 9 -912 873 5510 77 -497 533 5509 67 -117 216 5508 31 -19 751 5507 52 -283 21 5506 14 -981 603 5505 99 -546 569 5504 1 -611 116 5503 60 -662 905 5502 68 -300 319 5501 3 -339 104 5500 30 -317 363 5499 41 -465 783 5498 37 -729 377 5497 9 -417 157 5496 73 -33 978 5495 30 -452 411 5494 43 -211 913 5493 93 -585 650 5492 94 -214 732 5491 36 -741 889 5490 96 -580 35 5489 2 -405 281 5488 85 -219 362 5487 73 -179 434 5486 31 -566 867 5485 38 -497 499 5484 58 -263 986 5483 24 -918 586 5482 62 -842 402 5481 37 -854 938 5480 47 -754 170 5479 16 -919 116 5478 17 -928 423 5477 18 -566 928 5476 4 -367 803 5475 61 -512 338 5474 6 -400 616 5473 23 -184 254 5472 34 -464 898 5471 7 -767 311 5470 98 -53 986 5469 9 -693 988 5468 83 -494 145 5467 99 -125 427 5466 36 -464 543 5465 19 -722 834 5464 85 -362 889 5463 11 -355 268 5462 21 -586 88 5461 71 -324 887 5460 69 -998 264 5459 71 -843 844 5458 35 -717 629 5457 19 -884 162 5456 36 -708 343 5455 66 -945 744 5454 74 -621 894 5453 35 -179 496 5452 0 -200 23 5451 76 -623 982 5450 26 -419 354 5449 32 -215 161 5448 15 -466 828 5447 12 -819 708 5446 83 -598 919 5445 17 -849 381 5444 76 -397 353 5443 32 -473 237 5442 44 -41 506 5441 97 -628 936 5440 57 -192 171 5439 20 -332 29 5438 20 -119 291 5437 74 -789 658 5436 64 -537 411 5435 22 -28 439 5434 74 -115 882 5433 45 -731 462 5432 92 -569 401 5431 43 -765 374 5430 41 -141 998 5429 43 -737 456 5428 86 -633 100 5427 21 -246 427 5426 33 -971 471 5425 25 -557 296 5424 50 -419 527 5423 91 -61 492 5422 38 -27 19 5421 16 -375 977 5420 80 -542 574 5419 62 -355 648 5418 40 -673 882 5417 10 -956 77 5416 38 -174 743 5415 27 -769 595 5414 41 -35 528 5413 13 -472 222 5412 35 -41 357 5411 3 -402 181 5410 65 -926 219 5409 83 -765 299 5408 18 -804 717 5407 68 -333 112 5406 71 -148 860 5405 78 -66 275 5404 40 -306 780 5403 73 -865 323 5402 56 -176 381 5401 43 -961 819 5400 63 -919 646 5399 47 -582 504 5398 16 -604 965 5397 96 -251 934 5396 47 -585 376 5395 18 -494 671 5394 8 -456 170 5393 76 -941 131 5392 44 -562 791 5391 68 -172 163 5390 21 -142 315 5389 4 -538 199 5388 33 -30 490 5387 97 -558 285 5386 35 -704 103 5385 66 -501 320 5384 9 -38 320 5383 3 -339 751 5382 51 -628 474 5381 37 -848 172 5380 38 -115 704 5379 3 -709 360 5378 60 -204 624 5377 50 -181 686 5376 47 -783 575 5375 85 -0 52 5374 20 -569 523 5373 46 -276 135 5372 69 -302 989 5371 71 -468 359 5370 78 -343 427 5369 73 -736 96 5368 40 -937 35 5367 50 -110 619 5366 2 -523 649 5365 39 -529 741 5364 78 -387 762 5363 43 -146 988 5362 29 -630 930 5361 97 -932 47 5360 83 -330 326 5359 12 -61 901 5358 60 -415 481 5357 79 -969 624 5356 82 -907 614 5355 58 -978 352 5354 99 -774 138 5353 14 -57 318 5352 24 -882 140 5351 51 -721 708 5350 69 -425 516 5349 60 -419 809 5348 26 -857 971 5347 64 -10 239 5346 44 -262 592 5345 6 -214 853 5344 92 -819 899 5343 20 -178 725 5342 71 -431 818 5341 17 -192 96 5340 16 -707 331 5339 29 -838 624 5338 0 -731 199 5337 56 -647 384 5336 84 -739 132 5335 74 -953 725 5334 4 -174 486 5333 39 -907 542 5332 64 -721 13 5331 74 -765 865 5330 23 -707 289 5329 48 -425 443 5328 86 -814 715 5327 10 -252 99 5326 8 -406 699 5325 90 -239 653 5324 78 -943 752 5323 77 -529 894 5322 26 -147 507 5321 18 -575 754 5320 95 -846 615 5319 5 -728 762 5318 28 -615 22 5317 61 -399 176 5316 56 -45 121 5315 84 -900 8 5314 16 -857 511 5313 29 -387 81 5312 41 -752 230 5311 38 -138 897 5310 57 -852 776 5309 72 -740 670 5308 11 -845 48 5307 11 -55 717 5306 21 -113 677 5305 35 -496 871 5304 14 -429 882 5303 4 -850 31 5302 47 -332 810 5301 63 -120 842 5300 61 -105 612 5299 28 -622 3 5298 11 -330 897 5297 89 -39 861 5296 78 -806 209 5295 94 -989 101 5294 61 -851 572 5293 6 -220 835 5292 57 -968 21 5291 51 -229 327 5290 21 -608 174 5289 1 -106 216 5288 48 -36 105 5287 29 -651 847 5286 29 -108 326 5285 23 -528 549 5284 81 -737 487 5283 13 -813 60 5282 63 -694 305 5281 25 -153 197 5280 73 -957 532 5279 62 -111 190 5278 50 -257 1 5277 7 -521 57 5276 38 -777 416 5275 54 -61 679 5274 57 -426 506 5273 79 -754 379 5272 92 -108 512 5271 11 -664 117 5270 54 -341 119 5269 19 -188 431 5268 84 -944 685 5267 85 -640 840 5266 73 -736 964 5265 74 -173 788 5264 71 -126 866 5263 63 -866 804 5262 67 -394 578 5261 64 -998 344 5260 44 -687 349 5259 32 -745 992 5258 15 -845 116 5257 24 -876 992 5256 30 -175 28 5255 90 -922 81 5254 56 -61 962 5253 4 -225 25 5252 26 -233 201 5251 47 -995 120 5250 39 -357 170 5249 31 -875 908 5248 94 -124 940 5247 90 -964 399 5246 96 -946 340 5245 70 -119 517 5244 25 -936 786 5243 86 -823 788 5242 83 -80 75 5241 99 -950 86 5240 23 -261 368 5239 63 -968 41 5238 48 -540 932 5237 75 -59 266 5236 15 -822 448 5235 1 -731 392 5234 82 -997 24 5233 18 -712 843 5232 11 -988 753 5231 74 -717 601 5230 13 -326 155 5229 68 -109 730 5228 29 -665 592 5227 42 -818 142 5226 48 -55 189 5225 23 -368 644 5224 9 -180 70 5223 73 -90 369 5222 28 -151 612 5221 72 -445 440 5220 27 -425 396 5219 39 -137 865 5218 21 -449 946 5217 44 -952 244 5216 84 -544 145 5215 76 -574 357 5214 68 -700 448 5213 18 -756 561 5212 8 -172 452 5211 93 -43 880 5210 70 -531 173 5209 1 -918 773 5208 28 -702 597 5207 68 -98 83 5206 49 -788 76 5205 40 -909 499 5204 97 -887 97 5203 87 -108 151 5202 94 -572 232 5201 58 -707 686 5200 12 -399 731 5199 51 -176 599 5198 61 -513 190 5197 21 -6 90 5196 60 -577 436 5195 31 -401 96 5194 87 -946 929 5193 2 -919 360 5192 77 -545 455 5191 53 -954 617 5190 86 -132 898 5189 30 -409 397 5188 22 -99 611 5187 66 -653 294 5186 50 -340 431 5185 42 -167 856 5184 17 -569 242 5183 45 -905 243 5182 2 -837 669 5181 37 -718 557 5180 59 -501 85 5179 82 -785 559 5178 72 -317 155 5177 30 -862 77 5176 44 -574 253 5175 31 -614 721 5174 17 -999 427 5173 59 -573 653 5172 66 -111 783 5171 6 -472 768 5170 11 -525 100 5169 21 -404 412 5168 71 -78 863 5167 46 -824 133 5166 45 -531 140 5165 28 -294 575 5164 96 -774 933 5163 61 -870 597 5162 42 -14 947 5161 46 -667 903 5160 63 -687 499 5159 94 -549 249 5158 12 -730 12 5157 32 -992 166 5156 25 -564 328 5155 29 -641 345 5154 23 -336 188 5153 52 -649 963 5152 90 -44 822 5151 85 -403 692 5150 34 -250 825 5149 98 -237 795 5148 13 -845 71 5147 81 -838 961 5146 73 -982 54 5145 42 -156 717 5144 92 -225 616 5143 30 -141 48 5142 68 -130 508 5141 60 -866 366 5140 64 -30 842 5139 15 -723 318 5138 1 -109 82 5137 39 -907 309 5136 0 -336 505 5135 85 -101 617 5134 82 -568 618 5133 93 -539 82 5132 8 -141 964 5131 1 -523 487 5130 26 -524 140 5129 83 -236 620 5128 30 -772 384 5127 61 -803 150 5126 20 -887 30 5125 57 -998 893 5124 23 -536 848 5123 53 -118 72 5122 2 -476 748 5121 39 -347 426 5120 61 -519 530 5119 99 -236 692 5118 28 -234 411 5117 46 -120 630 5116 96 -136 336 5115 91 -45 701 5114 88 -776 505 5113 46 -323 630 5112 41 -321 779 5111 64 -896 618 5110 12 -837 711 5109 82 -281 824 5108 28 -780 494 5107 0 -294 53 5106 11 -634 26 5105 98 -196 426 5104 9 -875 44 5103 26 -850 776 5102 45 -160 512 5101 0 -907 301 5100 42 -887 544 5099 5 -329 281 5098 55 -441 888 5097 50 -26 129 5096 48 -600 893 5095 65 -382 821 5094 43 -267 817 5093 32 -264 450 5092 2 -211 576 5091 68 -757 367 5090 25 -262 502 5089 1 -393 55 5088 55 -758 14 5087 88 -236 826 5086 41 -72 220 5085 42 -3 118 5084 21 -366 295 5083 11 -874 335 5082 0 -208 435 5081 5 -864 233 5080 45 -446 461 5079 49 -41 670 5078 86 -187 472 5077 63 -606 989 5076 52 -102 208 5075 16 -822 102 5074 6 -959 112 5073 63 -900 949 5072 49 -201 599 5071 66 -772 959 5070 34 -791 624 5069 41 -197 235 5068 40 -483 111 5067 85 -780 359 5066 58 -106 95 5065 50 -990 431 5064 27 -162 144 5063 86 -350 826 5062 5 -639 321 5061 69 -335 926 5060 42 -388 12 5059 98 -124 551 5058 59 -752 272 5057 71 -264 77 5056 70 -663 223 5055 67 -287 417 5054 11 -317 803 5053 82 -505 360 5052 81 -395 269 5051 71 -913 448 5050 30 -460 387 5049 94 -279 879 5048 26 -194 11 5047 37 -854 29 5046 48 -806 557 5045 60 -613 288 5044 37 -442 16 5043 96 -91 100 5042 81 -821 407 5041 11 -60 357 5040 48 -508 681 5039 45 -867 892 5038 18 -982 884 5037 8 -471 886 5036 34 -269 225 5035 4 -272 406 5034 19 -915 157 5033 17 -692 701 5032 35 -50 628 5031 26 -675 28 5030 76 -789 272 5029 55 -8 95 5028 64 -997 745 5027 88 -661 292 5026 51 -819 855 5025 20 -248 21 5024 99 -455 819 5023 35 -73 81 5022 22 -600 508 5021 64 -756 209 5020 37 -176 911 5019 88 -350 755 5018 78 -453 374 5017 1 -437 308 5016 33 -833 205 5015 84 -202 640 5014 57 -737 133 5013 79 -572 580 5012 38 -299 268 5011 47 -297 487 5010 84 -155 105 5009 57 -380 770 5008 82 -65 674 5007 89 -103 493 5006 1 -565 272 5005 60 -506 777 5004 63 -552 410 5003 46 -312 909 5002 16 -780 628 5001 27 -382 264 5000 0 -335 752 4999 14 -95 929 4998 77 -181 881 4997 31 -220 412 4996 96 -494 972 4995 53 -366 167 4994 5 -500 299 4993 95 -281 891 4992 23 -363 271 4991 53 -512 859 4990 39 -823 366 4989 4 -48 459 4988 23 -468 353 4987 91 -440 424 4986 96 -804 479 4985 72 -867 104 4984 12 -407 714 4983 86 -620 708 4982 21 -411 133 4981 91 -492 351 4980 85 -907 807 4979 68 -106 325 4978 77 -929 953 4977 57 -944 234 4976 2 -375 598 4975 63 -389 261 4974 93 -6 646 4973 46 -575 302 4972 78 -781 66 4971 20 -543 162 4970 91 -482 914 4969 58 -372 195 4968 80 -718 550 4967 17 -635 393 4966 98 -336 698 4965 56 -615 476 4964 98 -343 673 4963 38 -236 577 4962 43 -903 290 4961 79 -248 332 4960 23 -718 785 4959 6 -644 622 4958 11 -157 192 4957 65 -695 415 4956 8 -221 582 4955 29 -803 602 4954 72 -95 951 4953 27 -286 637 4952 10 -958 556 4951 33 -547 175 4950 65 -162 951 4949 52 -429 456 4948 7 -777 570 4947 48 -833 783 4946 46 -979 577 4945 47 -651 449 4944 41 -314 164 4943 70 -81 775 4942 80 -380 676 4941 32 -224 125 4940 41 -495 455 4939 38 -885 586 4938 73 -787 25 4937 65 -206 988 4936 94 -127 55 4935 85 -285 710 4934 32 -388 898 4933 33 -98 479 4932 23 -550 918 4931 70 -669 26 4930 15 -869 651 4929 72 -560 80 4928 60 -37 708 4927 9 -932 90 4926 58 -345 524 4925 7 -811 991 4924 84 -419 103 4923 89 -561 532 4922 29 -892 543 4921 54 -374 427 4920 88 -571 119 4919 80 -372 511 4918 30 -617 517 4917 52 -566 502 4916 10 -532 235 4915 58 -888 945 4914 53 -570 606 4913 39 -988 742 4912 85 -116 666 4911 66 -307 80 4910 51 -608 491 4909 80 -993 784 4908 19 -14 418 4907 75 -266 517 4906 5 -290 53 4905 3 -339 141 4904 64 -863 534 4903 31 -75 188 4902 58 -586 151 4901 87 -588 714 4900 80 -706 604 4899 69 -366 443 4898 61 -901 704 4897 97 -463 16 4896 74 -912 390 4895 97 -606 325 4894 95 -346 736 4893 47 -36 709 4892 78 -437 63 4891 48 -109 109 4890 99 -160 85 4889 88 -739 635 4888 34 -687 230 4887 46 -626 771 4886 43 -64 26 4885 55 -589 474 4884 30 -27 687 4883 26 -646 298 4882 31 -953 492 4881 59 -24 114 4880 32 -449 541 4879 94 -404 875 4878 42 -459 27 4877 5 -745 885 4876 6 -551 246 4875 56 -787 45 4874 47 -388 949 4873 56 -806 711 4872 38 -377 269 4871 69 -573 379 4870 92 -666 527 4869 57 -848 367 4868 4 -141 992 4867 94 -639 498 4866 71 -200 87 4865 19 -95 913 4864 76 -237 179 4863 39 -441 689 4862 58 -889 763 4861 42 -852 354 4860 80 -159 529 4859 90 -375 99 4858 81 -494 231 4857 70 -411 518 4856 50 -173 430 4855 43 -734 365 4854 10 -490 817 4853 85 -925 151 4852 79 -409 625 4851 55 -824 896 4850 3 -429 89 4849 69 -867 111 4848 78 -712 203 4847 88 -88 63 4846 8 -65 334 4845 23 -548 246 4844 43 -665 61 4843 24 -525 243 4842 56 -729 514 4841 51 -807 345 4840 58 -977 908 4839 39 -907 902 4838 56 -140 798 4837 15 -728 844 4836 62 -87 798 4835 2 -185 195 4834 51 -818 678 4833 88 -729 49 4832 13 -168 930 4831 79 -437 190 4830 92 -5 833 4829 82 -103 406 4828 6 -953 530 4827 76 -46 601 4826 41 -603 506 4825 64 -517 634 4824 90 -628 743 4823 36 -118 343 4822 8 -740 874 4821 56 -357 92 4820 73 -426 759 4819 43 -876 302 4818 90 -929 355 4817 15 -94 770 4816 90 -871 738 4815 44 -891 535 4814 8 -400 278 4813 88 -468 527 4812 51 -781 829 4811 37 -332 299 4810 38 -457 529 4809 93 -947 751 4808 55 -584 242 4807 94 -31 464 4806 83 -203 357 4805 22 -256 196 4804 98 -750 377 4803 49 -698 133 4802 93 -529 993 4801 68 -769 452 4800 44 -778 380 4799 87 -509 603 4798 50 -777 112 4797 36 -107 611 4796 55 -160 243 4795 82 -818 488 4794 94 -244 560 4793 50 -139 244 4792 5 -541 237 4791 16 -71 573 4790 75 -777 366 4789 99 -490 145 4788 26 -501 810 4787 73 -367 724 4786 67 -754 881 4785 94 -928 440 4784 34 -315 454 4783 57 -7 882 4782 10 -663 410 4781 59 -207 767 4780 46 -220 722 4779 29 -334 538 4778 28 -86 60 4777 98 -842 724 4776 13 -441 604 4775 61 -985 767 4774 82 -572 468 4773 61 -471 507 4772 30 -642 128 4771 34 -45 175 4770 45 -184 7 4769 98 -477 296 4768 88 -335 856 4767 24 -119 519 4766 24 -836 787 4765 40 -298 212 4764 45 -961 305 4763 41 -378 964 4762 10 -952 888 4761 82 -167 468 4760 59 -710 101 4759 86 -440 637 4758 70 -336 4 4757 14 -731 841 4756 21 -575 946 4755 28 -906 41 4754 53 -341 313 4753 33 -75 270 4752 58 -419 232 4751 42 -367 735 4750 78 -464 155 4749 45 -632 564 4748 27 -162 925 4747 10 -895 933 4746 60 -905 745 4745 15 -728 200 4744 66 -42 754 4743 56 -38 157 4742 26 -497 640 4741 65 -580 327 4740 5 -591 187 4739 90 -638 166 4738 83 -992 498 4737 46 -187 448 4736 26 -545 487 4735 99 -445 103 4734 17 -597 300 4733 68 -516 608 4732 0 -313 605 4731 54 -140 148 4730 91 -20 71 4729 98 -667 362 4728 95 -50 201 4727 64 -960 277 4726 80 -384 813 4725 64 -802 491 4724 9 -691 681 4723 84 -3 462 4722 8 -456 624 4721 20 -76 927 4720 17 -709 36 4719 12 -160 306 4718 35 -924 840 4717 61 -464 162 4716 8 -321 543 4715 57 -809 250 4714 58 -219 767 4713 11 -838 878 4712 68 -697 30 4711 54 -890 52 4710 38 -729 767 4709 36 -466 735 4708 54 -677 527 4707 23 -619 513 4706 45 -292 994 4705 14 -483 471 4704 51 -888 422 4703 58 -848 141 4702 38 -977 166 4701 14 -285 13 4700 80 -31 817 4699 16 -208 312 4698 26 -13 776 4697 78 -519 316 4696 5 -523 629 4695 32 -48 922 4694 80 -280 208 4693 59 -975 240 4692 4 -152 334 4691 87 -196 645 4690 69 -504 897 4689 25 -535 474 4688 82 -460 731 4687 19 -686 729 4686 49 -706 519 4685 99 -714 213 4684 47 -968 554 4683 76 -905 169 4682 30 -689 179 4681 82 -747 438 4680 95 -423 429 4679 69 -743 629 4678 96 -1 701 4677 7 -210 496 4676 77 -305 522 4675 97 -659 706 4674 99 -384 462 4673 74 -990 481 4672 6 -740 868 4671 21 -8 263 4670 94 -800 723 4669 32 -927 892 4668 67 -204 302 4667 74 -974 793 4666 79 -815 987 4665 90 -244 246 4664 64 -981 682 4663 27 -613 846 4662 39 -604 274 4661 24 -540 617 4660 73 -830 644 4659 20 -590 937 4658 87 -509 951 4657 72 -805 885 4656 22 -740 259 4655 15 -563 371 4654 57 -836 880 4653 26 -572 144 4652 36 -656 517 4651 0 -973 523 4650 6 -706 335 4649 71 -986 148 4648 24 -66 494 4647 8 -626 70 4646 70 -887 588 4645 6 -491 307 4644 17 -735 895 4643 72 -627 358 4642 26 -993 945 4641 91 -188 353 4640 68 -186 469 4639 26 -654 159 4638 72 -424 377 4637 91 -481 637 4636 44 -280 889 4635 73 -412 448 4634 39 -536 464 4633 75 -413 347 4632 10 -591 232 4631 63 -883 417 4630 80 -310 545 4629 0 -782 800 4628 53 -739 479 4627 23 -748 701 4626 94 -440 341 4625 20 -984 640 4624 86 -117 648 4623 87 -114 473 4622 12 -815 828 4621 82 -871 803 4620 70 -744 470 4619 57 -320 300 4618 52 -778 288 4617 4 -359 742 4616 99 -701 332 4615 30 -992 992 4614 45 -174 752 4613 86 -645 301 4612 0 -24 114 4611 29 -333 134 4610 94 -169 45 4609 12 -12 485 4608 42 -545 51 4607 54 -410 683 4606 41 -339 851 4605 65 -239 590 4604 70 -451 863 4603 81 -187 704 4602 52 -979 355 4601 62 -89 816 4600 69 -559 702 4599 16 -434 881 4598 15 -368 123 4597 46 -832 760 4596 13 -261 948 4595 7 -726 891 4594 10 -159 288 4593 78 -349 907 4592 26 -538 930 4591 20 -114 526 4590 89 -821 7 4589 52 -757 689 4588 12 -363 331 4587 6 -812 64 4586 53 -56 970 4585 57 -603 312 4584 53 -380 523 4583 56 -977 56 4582 81 -403 317 4581 81 -518 360 4580 42 -318 404 4579 29 -358 59 4578 6 -266 529 4577 39 -94 964 4576 55 -658 36 4575 75 -788 967 4574 45 -467 757 4573 22 -739 999 4572 40 -956 386 4571 57 -956 131 4570 88 -344 229 4569 20 -529 669 4568 95 -564 843 4567 9 -928 795 4566 17 -69 301 4565 43 -210 231 4564 86 -757 819 4563 32 -612 829 4562 72 -255 688 4561 78 -902 685 4560 0 -559 240 4559 61 -826 867 4558 81 -47 920 4557 96 -494 735 4556 63 -70 566 4555 85 -412 548 4554 85 -989 593 4553 45 -140 945 4552 14 -3 781 4551 35 -444 389 4550 35 -372 796 4549 34 -947 850 4548 73 -184 328 4547 77 -168 778 4546 55 -18 999 4545 42 -955 407 4544 65 -647 307 4543 42 -163 787 4542 84 -392 5 4541 13 -593 9 4540 55 -946 609 4539 7 -521 954 4538 42 -550 226 4537 76 -778 128 4536 1 -592 766 4535 14 -99 235 4534 6 -520 573 4533 30 -781 711 4532 48 -995 579 4531 77 -400 485 4530 79 -655 647 4529 64 -728 661 4528 42 -97 746 4527 97 -362 866 4526 77 -530 86 4525 18 -662 756 4524 49 -861 823 4523 57 -132 713 4522 73 -93 971 4521 78 -838 152 4520 59 -986 222 4519 74 -914 452 4518 92 -880 200 4517 63 -780 584 4516 73 -329 694 4515 83 -933 913 4514 86 -110 840 4513 80 -741 952 4512 72 -819 190 4511 3 -929 850 4510 25 -770 817 4509 85 -251 296 4508 7 -616 896 4507 3 -889 902 4506 9 -780 963 4505 45 -73 67 4504 39 -888 71 4503 82 -761 690 4502 36 -340 782 4501 92 -32 403 4500 88 -521 780 4499 15 -399 37 4498 51 -994 934 4497 63 -938 648 4496 72 -896 54 4495 10 -995 573 4494 70 -380 454 4493 18 -908 446 4492 12 -378 32 4491 42 -623 730 4490 30 -743 640 4489 51 -102 883 4488 12 -285 908 4487 40 -594 617 4486 5 -480 401 4485 4 -119 522 4484 90 -8 58 4483 61 -413 705 4482 47 -301 113 4481 52 -90 796 4480 75 -756 388 4479 87 -974 717 4478 64 -291 349 4477 81 -215 12 4476 69 -878 142 4475 11 -464 285 4474 36 -353 141 4473 11 -591 943 4472 59 -317 773 4471 11 -407 875 4470 21 -671 238 4469 33 -368 824 4468 78 -336 125 4467 68 -870 576 4466 7 -856 753 4465 33 -143 249 4464 41 -198 516 4463 11 -169 482 4462 76 -898 901 4461 27 -636 877 4460 90 -414 551 4459 73 -698 99 4458 30 -549 606 4457 3 -822 738 4456 46 -503 922 4455 1 -733 303 4454 71 -33 349 4453 94 -581 486 4452 2 -24 365 4451 27 -326 172 4450 26 -451 433 4449 22 -492 271 4448 71 -868 565 4447 14 -816 452 4446 72 -619 300 4445 31 -953 768 4444 77 -863 916 4443 69 -121 757 4442 45 -192 10 4441 55 -739 39 4440 69 -161 506 4439 87 -706 566 4438 95 -112 422 4437 62 -152 407 4436 5 -532 548 4435 19 -851 70 4434 66 -159 246 4433 9 -746 896 4432 74 -970 858 4431 92 -533 823 4430 45 -939 915 4429 57 -144 334 4428 45 -14 573 4427 59 -858 854 4426 96 -478 531 4425 62 -823 575 4424 68 -350 348 4423 69 -37 813 4422 41 -35 475 4421 77 -907 875 4420 43 -581 122 4419 59 -760 862 4418 79 -718 632 4417 12 -323 340 4416 15 -955 939 4415 38 -227 989 4414 65 -534 279 4413 47 -337 636 4412 31 -600 338 4411 0 -752 844 4410 12 -260 798 4409 32 -229 666 4408 82 -292 973 4407 4 -401 776 4406 39 -950 725 4405 36 -710 181 4404 72 -642 159 4403 69 -298 311 4402 19 -494 875 4401 73 -46 801 4400 84 -131 505 4399 49 -693 778 4398 3 -196 647 4397 93 -50 26 4396 89 -543 640 4395 45 -22 35 4394 24 -848 495 4393 6 -436 459 4392 34 -73 889 4391 80 -295 356 4390 44 -727 460 4389 91 -130 94 4388 43 -621 45 4387 49 -385 440 4386 14 -605 210 4385 50 -540 172 4384 52 -35 722 4383 17 -569 540 4382 41 -533 355 4381 36 -895 533 4380 77 -366 475 4379 56 -48 942 4378 59 -605 350 4377 50 -229 638 4376 23 -38 985 4375 78 -449 347 4374 6 -182 761 4373 50 -184 50 4372 46 -822 583 4371 3 -57 209 4370 63 -533 971 4369 52 -592 87 4368 31 -711 273 4367 44 -653 455 4366 37 -637 715 4365 19 -586 560 4364 58 -710 38 4363 26 -466 429 4362 99 -374 397 4361 36 -237 109 4360 76 -884 210 4359 52 -814 875 4358 94 -818 66 4357 88 -739 184 4356 5 -154 603 4355 1 -522 320 4354 5 -608 269 4353 87 -31 635 4352 24 -288 597 4351 9 -898 240 4350 13 -334 583 4349 35 -809 59 4348 6 -882 822 4347 99 -581 43 4346 7 -282 963 4345 58 -51 175 4344 63 -634 631 4343 91 -37 152 4342 57 -357 954 4341 74 -656 783 4340 38 -524 284 4339 56 -236 72 4338 52 -779 918 4337 92 -79 494 4336 30 -788 952 4335 29 -543 718 4334 23 -479 337 4333 41 -197 833 4332 59 -171 353 4331 68 -499 825 4330 70 -211 38 4329 13 -154 598 4328 28 -423 626 4327 45 -542 2 4326 70 -233 67 4325 29 -380 814 4324 24 -504 819 4323 6 -479 916 4322 28 -528 978 4321 2 -786 569 4320 67 -440 845 4319 28 -971 829 4318 5 -623 757 4317 73 -934 409 4316 88 -252 46 4315 30 -995 180 4314 85 -902 782 4313 87 -937 255 4312 2 -409 355 4311 95 -724 383 4310 74 -15 229 4309 34 -72 327 4308 46 -348 848 4307 34 -362 573 4306 68 -865 455 4305 68 -397 977 4304 25 -527 850 4303 9 -900 73 4302 96 -971 209 4301 52 -153 396 4300 68 -902 876 4299 70 -478 120 4298 94 -275 659 4297 72 -118 6 4296 98 -478 424 4295 49 -126 164 4294 46 -777 127 4293 87 -864 437 4292 62 -813 842 4291 92 -519 976 4290 81 -755 765 4289 25 -461 218 4288 42 -652 738 4287 20 -582 488 4286 15 -259 28 4285 64 -37 597 4284 35 -690 243 4283 34 -594 697 4282 91 -865 111 4281 5 -210 566 4280 29 -547 826 4279 76 -480 221 4278 29 -250 45 4277 80 -459 517 4276 7 -431 288 4275 32 -353 2 4274 22 -546 436 4273 34 -585 861 4272 9 -545 757 4271 72 -739 530 4270 65 -605 469 4269 66 -176 484 4268 6 -527 739 4267 23 -229 747 4266 79 -285 100 4265 2 -565 874 4264 7 -575 252 4263 80 -104 365 4262 96 -226 75 4261 3 -60 990 4260 80 -985 596 4259 13 -744 837 4258 42 -991 439 4257 64 -647 762 4256 29 -225 949 4255 94 -622 271 4254 71 -886 846 4253 99 -290 920 4252 47 -84 233 4251 87 -393 672 4250 16 -759 704 4249 7 -397 781 4248 24 -677 349 4247 75 -812 354 4246 34 -678 224 4245 42 -424 728 4244 60 -925 520 4243 73 -687 592 4242 59 -560 712 4241 20 -967 90 4240 69 -923 834 4239 63 -431 487 4238 36 -994 409 4237 71 -130 921 4236 86 -495 819 4235 13 -208 868 4234 25 -927 138 4233 49 -880 391 4232 23 -621 514 4231 12 -255 56 4230 59 -347 272 4229 4 -77 642 4228 49 -488 854 4227 43 -101 731 4226 86 -951 879 4225 63 -729 754 4224 28 -747 260 4223 28 -876 112 4222 4 -458 533 4221 25 -783 548 4220 36 -630 552 4219 90 -788 55 4218 26 -122 572 4217 58 -852 228 4216 38 -124 348 4215 15 -494 4 4214 22 -148 235 4213 98 -578 786 4212 87 -984 892 4211 41 -996 458 4210 67 -497 638 4209 15 -482 680 4208 84 -344 202 4207 66 -879 236 4206 27 -344 928 4205 72 -769 239 4204 63 -448 111 4203 34 -894 452 4202 56 -434 743 4201 59 -820 520 4200 98 -957 311 4199 49 -478 176 4198 1 -966 395 4197 13 -307 543 4196 46 -689 97 4195 53 -127 283 4194 57 -659 777 4193 32 -708 975 4192 55 -222 604 4191 45 -208 489 4190 61 -135 484 4189 86 -780 877 4188 47 -852 672 4187 51 -446 929 4186 65 -813 960 4185 61 -506 253 4184 56 -801 766 4183 46 -370 94 4182 95 -115 845 4181 48 -5 750 4180 1 -607 383 4179 7 -204 967 4178 35 -742 852 4177 92 -969 41 4176 40 -706 54 4175 63 -487 95 4174 30 -671 516 4173 70 -248 465 4172 43 -95 471 4171 25 -366 940 4170 11 -416 717 4169 39 -114 426 4168 40 -810 522 4167 46 -986 773 4166 77 -959 325 4165 26 -578 602 4164 21 -50 273 4163 81 -993 175 4162 42 -531 144 4161 15 -222 712 4160 72 -291 994 4159 95 -904 941 4158 30 -749 687 4157 30 -447 511 4156 82 -722 42 4155 2 -328 403 4154 38 -98 392 4153 52 -30 269 4152 5 -432 425 4151 46 -717 777 4150 30 -53 648 4149 93 -253 998 4148 38 -176 479 4147 15 -468 796 4146 30 -639 646 4145 72 -11 852 4144 39 -122 472 4143 23 -844 593 4142 6 -647 154 4141 59 -129 376 4140 71 -650 544 4139 66 -518 232 4138 79 -683 853 4137 7 -150 576 4136 70 -794 330 4135 82 -380 163 4134 62 -878 162 4133 88 -439 469 4132 27 -777 883 4131 19 -832 49 4130 51 -311 864 4129 47 -378 722 4128 13 -277 369 4127 83 -245 878 4126 53 -167 201 4125 35 -0 739 4124 41 -693 610 4123 50 -585 81 4122 43 -833 678 4121 66 -185 38 4120 94 -141 347 4119 52 -353 296 4118 93 -490 302 4117 10 -677 176 4116 3 -461 942 4115 7 -129 912 4114 16 -528 62 4113 30 -403 777 4112 10 -639 715 4111 75 -691 424 4110 64 -50 587 4109 4 -994 831 4108 78 -125 69 4107 86 -234 953 4106 81 -30 911 4105 21 -849 858 4104 33 -284 200 4103 60 -62 355 4102 12 -291 103 4101 76 -837 604 4100 94 -756 255 4099 64 -761 925 4098 5 -115 48 4097 86 -42 598 4096 89 -52 882 4095 20 -658 731 4094 18 -844 475 4093 56 -251 361 4092 22 -499 815 4091 77 -349 307 4090 45 -329 584 4089 8 -877 187 4088 99 -450 977 4087 64 -715 687 4086 7 -151 23 4085 98 -255 615 4084 39 -114 343 4083 81 -545 451 4082 59 -507 316 4081 75 -723 373 4080 14 -396 86 4079 2 -209 348 4078 45 -289 571 4077 42 -664 84 4076 73 -408 594 4075 56 -271 580 4074 89 -891 220 4073 14 -134 841 4072 56 -943 602 4071 3 -286 129 4070 78 -737 568 4069 32 -777 24 4068 18 -487 692 4067 92 -489 169 4066 62 -13 668 4065 25 -360 755 4064 13 -379 571 4063 38 -238 530 4062 75 -473 254 4061 19 -561 456 4060 65 -543 139 4059 54 -331 267 4058 96 -522 294 4057 28 -501 369 4056 99 -912 119 4055 47 -183 756 4054 65 -41 623 4053 98 -275 566 4052 14 -797 534 4051 76 -317 107 4050 91 -872 589 4049 1 -972 670 4048 21 -925 292 4047 80 -249 521 4046 2 -363 822 4045 58 -132 671 4044 72 -57 841 4043 14 -32 375 4042 76 -426 852 4041 47 -517 894 4040 48 -919 805 4039 44 -377 403 4038 90 -771 787 4037 4 -698 432 4036 67 -150 859 4035 88 -830 587 4034 23 -465 375 4033 7 -522 288 4032 2 -958 997 4031 60 -89 35 4030 90 -402 544 4029 59 -615 853 4028 54 -354 370 4027 60 -573 790 4026 7 -271 655 4025 54 -211 154 4024 31 -87 50 4023 36 -290 419 4022 94 -961 696 4021 56 -491 310 4020 86 -690 56 4019 68 -482 935 4018 78 -580 533 4017 26 -134 524 4016 78 -500 228 4015 30 -104 954 4014 5 -630 421 4013 12 -723 378 4012 79 -385 695 4011 32 -253 182 4010 46 -121 899 4009 80 -401 526 4008 20 -9 478 4007 90 -295 479 4006 44 -273 242 4005 63 -533 935 4004 39 -42 327 4003 47 -683 467 4002 90 -513 859 4001 33 -282 669 4000 13 -372 592 3999 13 -47 305 3998 72 -999 457 3997 39 -237 811 3996 71 -307 238 3995 2 -608 922 3994 74 -859 566 3993 49 -608 568 3992 35 -189 206 3991 17 -77 999 3990 23 -287 411 3989 91 -848 328 3988 32 -645 678 3987 4 -572 691 3986 76 -315 282 3985 93 -356 250 3984 69 -998 131 3983 74 -361 188 3982 25 -206 940 3981 41 -588 320 3980 11 -82 584 3979 78 -650 277 3978 43 -986 286 3977 20 -409 831 3976 7 -31 230 3975 25 -118 950 3974 95 -942 496 3973 35 -248 833 3972 63 -620 305 3971 15 -735 322 3970 61 -307 351 3969 50 -990 236 3968 43 -454 129 3967 66 -600 815 3966 57 -280 297 3965 37 -454 601 3964 91 -663 721 3963 17 -528 480 3962 69 -982 537 3961 62 -971 111 3960 88 -115 74 3959 42 -106 767 3958 31 -314 86 3957 53 -517 200 3956 85 -696 464 3955 32 -879 736 3954 82 -240 483 3953 79 -943 65 3952 13 -425 743 3951 54 -36 456 3950 1 -307 110 3949 85 -681 781 3948 0 -886 681 3947 79 -736 533 3946 79 -728 495 3945 82 -253 34 3944 81 -418 656 3943 63 -321 588 3942 29 -286 535 3941 51 -345 154 3940 38 -329 847 3939 72 -99 216 3938 62 -148 996 3937 79 -38 975 3936 14 -460 4 3935 0 -377 178 3934 47 -68 341 3933 83 -52 779 3932 9 -381 129 3931 3 -306 658 3930 94 -631 104 3929 1 -220 830 3928 23 -20 645 3927 95 -970 141 3926 11 -826 533 3925 57 -837 640 3924 8 -561 738 3923 30 -650 62 3922 1 -470 93 3921 67 -554 924 3920 7 -273 785 3919 67 -185 280 3918 41 -503 839 3917 19 -608 533 3916 5 -893 494 3915 14 -901 773 3914 98 -676 292 3913 27 -968 346 3912 91 -168 594 3911 18 -139 400 3910 91 -505 263 3909 28 -441 211 3908 8 -305 148 3907 68 -39 905 3906 89 -720 155 3905 71 -481 713 3904 99 -946 364 3903 22 -751 730 3902 70 -194 264 3901 80 -136 634 3900 2 -52 193 3899 63 -62 405 3898 6 -243 787 3897 13 -750 179 3896 26 -441 724 3895 31 -349 766 3894 23 -633 518 3893 53 -466 906 3892 19 -630 771 3891 55 -440 395 3890 5 -788 569 3889 8 -618 929 3888 98 -608 868 3887 81 -454 947 3886 49 -958 79 3885 30 -247 703 3884 9 -611 340 3883 71 -135 637 3882 16 -376 499 3881 83 -825 973 3880 19 -640 95 3879 65 -60 169 3878 16 -920 326 3877 0 -867 184 3876 15 -376 216 3875 49 -362 376 3874 71 -703 548 3873 63 -137 331 3872 47 -526 645 3871 75 -877 538 3870 55 -925 482 3869 18 -842 159 3868 58 -142 856 3867 13 -968 657 3866 5 -840 786 3865 49 -827 74 3864 1 -217 160 3863 65 -686 717 3862 56 -107 207 3861 61 -55 366 3860 64 -322 604 3859 95 -303 440 3858 8 -199 86 3857 70 -870 561 3856 17 -712 477 3855 12 -913 354 3854 1 -443 92 3853 61 -509 955 3852 53 -841 962 3851 57 -762 696 3850 5 -163 869 3849 73 -353 381 3848 1 -525 527 3847 10 -83 45 3846 32 -122 115 3845 15 -262 402 3844 79 -137 79 3843 47 -992 951 3842 93 -265 527 3841 66 -827 318 3840 7 -487 713 3839 59 -854 914 3838 80 -481 775 3837 82 -930 169 3836 44 -713 360 3835 96 -322 327 3834 86 -127 536 3833 12 -424 266 3832 14 -208 588 3831 72 -605 479 3830 43 -798 789 3829 33 -138 981 3828 63 -606 385 3827 37 -809 481 3826 55 -32 100 3825 21 -791 735 3824 39 -269 980 3823 19 -677 417 3822 70 -108 288 3821 21 -690 98 3820 60 -807 707 3819 80 -595 259 3818 65 -903 822 3817 53 -381 334 3816 79 -364 826 3815 77 -755 195 3814 24 -562 492 3813 52 -128 486 3812 59 -190 613 3811 56 -391 796 3810 41 -448 146 3809 88 -437 127 3808 21 -487 735 3807 69 -508 20 3806 52 -631 535 3805 1 -703 719 3804 60 -5 930 3803 19 -873 22 3802 43 -816 150 3801 93 -650 535 3800 79 -19 670 3799 94 -391 519 3798 1 -715 169 3797 94 -484 504 3796 97 -816 408 3795 87 -789 416 3794 92 -907 758 3793 69 -872 496 3792 13 -614 139 3791 5 -865 855 3790 16 -151 932 3789 63 -350 61 3788 62 -664 969 3787 67 -96 102 3786 23 -992 949 3785 66 -658 229 3784 2 -262 566 3783 88 -356 74 3782 3 -283 890 3781 25 -923 534 3780 74 -870 3 3779 71 -92 952 3778 80 -866 444 3777 68 -153 563 3776 56 -719 640 3775 10 -663 145 3774 33 -491 846 3773 39 -183 778 3772 90 -356 507 3771 7 -531 35 3770 35 -51 913 3769 5 -507 115 3768 77 -881 116 3767 22 -922 464 3766 71 -494 769 3765 43 -299 938 3764 5 -68 490 3763 17 -270 832 3762 30 -471 713 3761 82 -122 306 3760 82 -797 275 3759 48 -999 552 3758 54 -651 512 3757 62 -695 279 3756 95 -830 378 3755 42 -447 883 3754 19 -658 864 3753 23 -118 479 3752 79 -407 2 3751 79 -30 344 3750 34 -722 937 3749 32 -40 916 3748 79 -232 668 3747 34 -900 530 3746 95 -494 232 3745 86 -18 963 3744 38 -385 434 3743 78 -477 998 3742 53 -658 449 3741 71 -407 23 3740 37 -20 527 3739 30 -248 450 3738 68 -137 391 3737 80 -297 91 3736 33 -268 481 3735 40 -529 593 3734 47 -435 249 3733 63 -548 828 3732 90 -425 334 3731 81 -496 68 3730 25 -76 626 3729 38 -59 873 3728 77 -300 475 3727 11 -609 925 3726 83 -888 930 3725 2 -343 841 3724 73 -421 725 3723 9 -494 88 3722 88 -265 568 3721 12 -441 863 3720 92 -752 614 3719 42 -397 662 3718 1 -550 270 3717 75 -994 811 3716 69 -88 289 3715 72 -116 645 3714 54 -637 207 3713 92 -520 764 3712 92 -704 193 3711 22 -249 508 3710 82 -952 403 3709 68 -391 258 3708 35 -459 67 3707 84 -521 970 3706 55 -644 175 3705 90 -437 622 3704 97 -443 995 3703 47 -570 698 3702 11 -685 404 3701 81 -105 135 3700 45 -144 333 3699 29 -191 507 3698 56 -96 291 3697 93 -794 649 3696 93 -553 933 3695 87 -626 493 3694 20 -297 362 3693 99 -294 301 3692 87 -268 359 3691 88 -801 158 3690 57 -826 736 3689 96 -215 628 3688 95 -642 994 3687 9 -715 60 3686 30 -440 670 3685 24 -131 212 3684 92 -60 121 3683 32 -941 988 3682 0 -201 305 3681 2 -421 618 3680 46 -107 7 3679 97 -634 859 3678 61 -933 791 3677 57 -390 60 3676 92 -458 315 3675 27 -90 596 3674 30 -133 327 3673 7 -683 976 3672 11 -686 558 3671 74 -611 491 3670 77 -147 364 3669 31 -67 37 3668 47 -731 646 3667 70 -745 651 3666 54 -718 966 3665 93 -269 238 3664 36 -350 951 3663 95 -418 379 3662 45 -66 960 3661 99 -127 465 3660 7 -326 840 3659 46 -391 772 3658 8 -995 157 3657 33 -684 610 3656 98 -728 564 3655 2 -287 409 3654 44 -572 507 3653 91 -418 453 3652 93 -494 922 3651 35 -625 610 3650 93 -67 383 3649 80 -614 744 3648 93 -546 349 3647 39 -45 959 3646 31 -155 577 3645 95 -901 529 3644 44 -54 987 3643 71 -531 580 3642 15 -311 411 3641 92 -227 138 3640 86 -639 866 3639 55 -394 537 3638 45 -390 85 3637 6 -382 355 3636 50 -47 513 3635 89 -542 726 3634 25 -406 561 3633 84 -168 229 3632 52 -273 54 3631 21 -271 312 3630 8 -328 104 3629 58 -451 385 3628 24 -730 566 3627 0 -841 610 3626 0 -787 636 3625 33 -165 406 3624 50 -331 323 3623 13 -175 303 3622 23 -742 135 3621 89 -207 496 3620 0 -719 342 3619 94 -818 241 3618 87 -956 995 3617 72 -973 673 3616 88 -230 828 3615 5 -82 370 3614 62 -20 897 3613 83 -167 342 3612 15 -639 894 3611 43 -154 58 3610 53 -100 65 3609 48 -245 155 3608 90 -321 832 3607 86 -845 834 3606 98 -457 431 3605 74 -473 789 3604 14 -554 676 3603 6 -448 723 3602 85 -835 898 3601 52 -992 45 3600 48 -910 587 3599 5 -322 39 3598 85 -998 878 3597 92 -403 239 3596 47 -642 595 3595 38 -112 85 3594 98 -953 209 3593 91 -824 324 3592 10 -853 42 3591 61 -458 431 3590 84 -548 198 3589 8 -160 930 3588 58 -639 447 3587 32 -643 89 3586 59 -509 403 3585 76 -876 65 3584 53 -884 812 3583 15 -281 493 3582 12 -611 769 3581 97 -233 760 3580 39 -267 494 3579 90 -483 262 3578 38 -358 729 3577 52 -686 834 3576 99 -337 229 3575 13 -253 372 3574 63 -318 28 3573 99 -723 158 3572 60 -9 576 3571 67 -265 485 3570 37 -232 522 3569 96 -533 866 3568 78 -895 525 3567 12 -604 861 3566 67 -857 500 3565 34 -343 641 3564 8 -870 387 3563 93 -582 933 3562 59 -91 292 3561 71 -962 412 3560 74 -655 181 3559 3 -341 658 3558 69 -663 453 3557 63 -360 323 3556 29 -858 265 3555 74 -253 148 3554 51 -454 340 3553 47 -641 880 3552 28 -879 970 3551 49 -231 710 3550 12 -522 334 3549 30 -205 61 3548 31 -129 347 3547 67 -58 543 3546 30 -117 232 3545 50 -807 40 3544 60 -460 185 3543 79 -909 796 3542 81 -259 362 3541 76 -376 821 3540 64 -273 992 3539 70 -713 636 3538 31 -803 374 3537 7 -311 801 3536 7 -192 897 3535 94 -854 805 3534 30 -389 985 3533 34 -433 51 3532 55 -541 114 3531 65 -828 937 3530 88 -356 393 3529 10 -262 240 3528 55 -572 4 3527 91 -904 130 3526 49 -91 631 3525 11 -820 963 3524 33 -933 795 3523 46 -937 900 3522 95 -176 766 3521 89 -544 780 3520 71 -153 543 3519 47 -235 648 3518 9 -873 418 3517 69 -499 373 3516 66 -667 781 3515 81 -167 872 3514 27 -895 508 3513 88 -133 64 3512 99 -986 178 3511 76 -237 241 3510 63 -894 378 3509 39 -230 403 3508 91 -45 21 3507 36 -592 855 3506 37 -908 541 3505 83 -364 384 3504 50 -444 890 3503 27 -886 235 3502 76 -936 128 3501 14 -862 240 3500 74 -975 474 3499 34 -381 555 3498 66 -165 987 3497 18 -313 543 3496 45 -157 330 3495 68 -494 228 3494 54 -654 510 3493 91 -107 614 3492 55 -887 399 3491 94 -766 405 3490 7 -918 679 3489 88 -568 478 3488 59 -444 732 3487 21 -212 769 3486 85 -102 139 3485 15 -718 624 3484 66 -895 361 3483 83 -215 608 3482 54 -993 875 3481 21 -726 187 3480 12 -200 292 3479 84 -745 378 3478 35 -963 364 3477 12 -629 695 3476 23 -515 493 3475 10 -262 823 3474 38 -752 292 3473 82 -733 327 3472 68 -687 99 3471 22 -895 272 3470 26 -914 498 3469 52 -14 226 3468 45 -668 892 3467 78 -201 122 3466 33 -670 726 3465 11 -530 560 3464 25 -965 142 3463 50 -227 458 3462 1 -827 954 3461 4 -773 742 3460 79 -271 70 3459 98 -334 672 3458 90 -769 448 3457 34 -395 221 3456 46 -165 860 3455 53 -418 743 3454 13 -683 490 3453 56 -504 973 3452 73 -211 253 3451 40 -672 811 3450 5 -397 80 3449 50 -224 554 3448 93 -226 878 3447 56 -360 934 3446 37 -116 392 3445 23 -253 573 3444 74 -517 828 3443 73 -719 337 3442 17 -442 346 3441 29 -730 551 3440 53 -526 564 3439 27 -676 373 3438 17 -943 190 3437 99 -542 143 3436 86 -819 483 3435 24 -745 11 3434 86 -490 556 3433 73 -990 885 3432 79 -795 753 3431 27 -987 265 3430 71 -190 101 3429 20 -183 175 3428 84 -46 131 3427 73 -660 621 3426 40 -472 380 3425 72 -454 127 3424 7 -671 938 3423 25 -132 520 3422 50 -488 564 3421 19 -163 507 3420 80 -925 354 3419 79 -43 117 3418 0 -510 330 3417 13 -240 679 3416 38 -253 648 3415 18 -189 819 3414 1 -417 753 3413 78 -956 305 3412 53 -57 386 3411 64 -153 11 3410 32 -236 789 3409 23 -787 869 3408 88 -651 750 3407 53 -30 198 3406 26 -829 170 3405 98 -65 234 3404 6 -448 244 3403 77 -919 894 3402 46 -374 320 3401 89 -222 86 3400 90 -919 355 3399 91 -119 348 3398 44 -552 264 3397 13 -28 281 3396 62 -936 924 3395 20 -989 291 3394 76 -349 310 3393 61 -574 562 3392 52 -233 994 3391 54 -730 988 3390 15 -7 466 3389 30 -83 314 3388 80 -983 514 3387 56 -357 420 3386 52 -632 436 3385 9 -980 146 3384 94 -748 88 3383 63 -567 984 3382 77 -6 392 3381 34 -521 849 3380 50 -151 501 3379 72 -799 233 3378 92 -94 42 3377 10 -983 431 3376 62 -290 145 3375 72 -58 307 3374 65 -104 864 3373 23 -592 434 3372 18 -542 837 3371 56 -347 780 3370 48 -268 798 3369 36 -190 823 3368 35 -610 474 3367 70 -286 901 3366 11 -837 72 3365 69 -443 418 3364 23 -429 52 3363 95 -596 618 3362 51 -57 76 3361 4 -981 114 3360 19 -975 17 3359 7 -349 647 3358 7 -572 593 3357 58 -828 418 3356 32 -654 460 3355 44 -366 278 3354 39 -433 441 3353 1 -542 462 3352 83 -962 855 3351 53 -97 114 3350 7 -370 2 3349 0 -53 497 3348 62 -174 255 3347 77 -958 875 3346 74 -182 54 3345 17 -836 380 3344 28 -979 181 3343 93 -606 292 3342 89 -741 464 3341 58 -111 68 3340 86 -505 380 3339 72 -241 848 3338 31 -380 33 3337 87 -820 569 3336 21 -673 886 3335 77 -199 355 3334 34 -888 41 3333 85 -828 311 3332 37 -395 715 3331 86 -687 138 3330 62 -532 410 3329 60 -815 437 3328 26 -464 662 3327 86 -682 441 3326 55 -531 429 3325 14 -313 488 3324 47 -730 483 3323 31 -595 507 3322 6 -577 236 3321 43 -727 22 3320 70 -973 342 3319 15 -775 403 3318 71 -221 301 3317 35 -11 412 3316 78 -941 672 3315 15 -5 164 3314 21 -975 249 3313 58 -271 627 3312 13 -213 725 3311 1 -680 552 3310 84 -938 438 3309 75 -102 366 3308 19 -888 569 3307 55 -739 630 3306 20 -508 933 3305 7 -914 634 3304 93 -621 448 3303 2 -902 115 3302 70 -172 169 3301 5 -113 94 3300 53 -72 557 3299 74 -796 643 3298 83 -939 344 3297 21 -696 139 3296 14 -298 134 3295 23 -186 906 3294 59 -332 325 3293 29 -946 646 3292 71 -74 524 3291 72 -537 791 3290 5 -913 904 3289 4 -299 623 3288 27 -204 64 3287 85 -5 917 3286 24 -228 637 3285 39 -580 301 3284 11 -679 573 3283 85 -121 988 3282 38 -732 670 3281 87 -887 17 3280 53 -281 765 3279 62 -558 419 3278 61 -147 613 3277 9 -279 844 3276 19 -336 285 3275 77 -727 259 3274 64 -584 467 3273 90 -318 514 3272 55 -653 334 3271 38 -251 912 3270 84 -346 9 3269 60 -805 519 3268 72 -769 896 3267 41 -559 421 3266 86 -26 129 3265 94 -792 746 3264 60 -953 343 3263 14 -179 169 3262 26 -422 543 3261 66 -903 239 3260 40 -489 882 3259 90 -623 312 3258 54 -474 542 3257 3 -291 925 3256 21 -383 334 3255 53 -403 465 3254 23 -173 876 3253 83 -626 601 3252 77 -303 263 3251 75 -356 496 3250 51 -570 364 3249 41 -769 505 3248 86 -617 825 3247 14 -590 677 3246 18 -869 299 3245 90 -588 394 3244 98 -275 65 3243 22 -338 16 3242 54 -767 238 3241 32 -131 104 3240 94 -859 547 3239 78 -679 716 3238 80 -147 965 3237 15 -378 275 3236 2 -904 927 3235 72 -329 750 3234 28 -48 682 3233 31 -777 224 3232 93 -133 376 3231 57 -557 160 3230 63 -831 985 3229 27 -750 649 3228 17 -690 124 3227 53 -347 306 3226 76 -177 439 3225 47 -67 968 3224 57 -458 376 3223 28 -847 365 3222 27 -216 935 3221 64 -175 363 3220 57 -335 92 3219 72 -525 648 3218 8 -818 762 3217 6 -866 295 3216 34 -471 899 3215 17 -591 293 3214 10 -11 10 3213 60 -429 626 3212 61 -572 67 3211 63 -271 850 3210 4 -443 645 3209 83 -886 19 3208 81 -466 717 3207 70 -395 172 3206 95 -605 60 3205 39 -283 500 3204 87 -383 998 3203 58 -559 978 3202 58 -216 590 3201 85 -204 201 3200 30 -626 29 3199 82 -301 103 3198 55 -545 755 3197 41 -111 556 3196 7 -559 515 3195 78 -502 299 3194 32 -19 997 3193 90 -388 725 3192 82 -389 555 3191 34 -172 474 3190 1 -925 269 3189 57 -348 138 3188 32 -198 348 3187 75 -41 280 3186 43 -215 467 3185 55 -301 422 3184 5 -272 75 3183 48 -170 481 3182 63 -81 330 3181 99 -204 433 3180 21 -131 254 3179 24 -789 568 3178 57 -67 322 3177 15 -813 882 3176 15 -45 494 3175 82 -346 573 3174 91 -594 852 3173 2 -150 632 3172 10 -897 781 3171 8 -178 970 3170 87 -685 670 3169 7 -246 426 3168 34 -439 993 3167 72 -388 330 3166 25 -920 913 3165 76 -721 883 3164 69 -219 928 3163 75 -850 12 3162 44 -810 212 3161 25 -300 803 3160 71 -243 731 3159 49 -432 620 3158 43 -663 467 3157 80 -417 485 3156 5 -29 70 3155 46 -955 945 3154 19 -915 309 3153 50 -799 190 3152 36 -409 533 3151 4 -72 226 3150 51 -110 53 3149 5 -153 632 3148 81 -981 755 3147 76 -415 584 3146 24 -124 268 3145 38 -636 697 3144 7 -118 132 3143 3 -656 328 3142 11 -307 529 3141 39 -172 453 3140 33 -420 245 3139 96 -877 42 3138 95 -171 522 3137 17 -315 858 3136 56 -571 312 3135 29 -564 35 3134 48 -803 922 3133 51 -798 726 3132 46 -76 53 3131 34 -208 374 3130 13 -203 5 3129 75 -519 783 3128 54 -663 607 3127 70 -546 273 3126 85 -277 804 3125 74 -112 969 3124 0 -196 55 3123 76 -673 113 3122 0 -678 213 3121 72 -369 383 3120 86 -221 208 3119 0 -176 837 3118 68 -334 850 3117 85 -469 112 3116 11 -834 736 3115 26 -914 246 3114 16 -942 755 3113 91 -899 282 3112 52 -829 854 3111 99 -175 862 3110 30 -371 321 3109 14 -986 828 3108 4 -738 737 3107 84 -375 848 3106 86 -489 104 3105 63 -490 248 3104 92 -473 393 3103 97 -427 528 3102 4 -992 685 3101 7 -541 161 3100 65 -492 102 3099 80 -90 202 3098 38 -889 976 3097 24 -744 230 3096 36 -856 714 3095 88 -855 948 3094 99 -864 929 3093 1 -842 971 3092 4 -524 416 3091 43 -58 849 3090 45 -899 420 3089 4 -226 135 3088 40 -746 886 3087 20 -516 476 3086 14 -765 887 3085 88 -18 981 3084 0 -958 971 3083 99 -555 610 3082 2 -566 984 3081 31 -429 401 3080 46 -284 646 3079 15 -249 200 3078 67 -410 56 3077 47 -588 257 3076 22 -906 886 3075 75 -9 10 3074 74 -360 968 3073 6 -626 704 3072 40 -582 851 3071 98 -755 307 3070 13 -445 484 3069 14 -144 193 3068 3 -798 250 3067 83 -370 478 3066 82 -876 3 3065 68 -41 686 3064 89 -264 658 3063 64 -852 413 3062 73 -543 851 3061 4 -822 992 3060 82 -291 110 3059 30 -943 195 3058 30 -771 17 3057 34 -474 138 3056 42 -317 786 3055 49 -28 248 3054 83 -244 913 3053 77 -561 690 3052 41 -859 216 3051 30 -881 517 3050 72 -915 8 3049 53 -177 954 3048 34 -879 917 3047 17 -352 934 3046 29 -537 659 3045 15 -334 57 3044 28 -222 366 3043 78 -474 102 3042 68 -698 588 3041 70 -508 189 3040 97 -53 183 3039 96 -37 176 3038 73 -982 874 3037 29 -275 139 3036 52 -602 869 3035 81 -691 504 3034 20 -263 100 3033 11 -514 980 3032 74 -398 725 3031 77 -5 10 3030 19 -7 228 3029 45 -301 439 3028 1 -734 771 3027 5 -270 711 3026 70 -364 611 3025 67 -403 91 3024 91 -120 363 3023 42 -254 972 3022 74 -714 585 3021 11 -781 734 3020 39 -788 439 3019 99 -668 960 3018 70 -59 348 3017 56 -100 33 3016 46 -519 762 3015 90 -728 483 3014 96 -390 678 3013 28 -387 633 3012 86 -850 722 3011 54 -295 395 3010 93 -478 291 3009 99 -611 138 3008 12 -315 103 3007 60 -271 557 3006 95 -278 945 3005 58 -805 677 3004 79 -44 418 3003 33 -910 325 3002 0 -327 607 3001 53 -103 940 3000 55 -153 872 2999 81 -34 512 2998 86 -546 648 2997 29 -611 379 2996 4 -268 788 2995 99 -258 453 2994 47 -92 334 2993 76 -717 466 2992 13 -667 981 2991 58 -67 737 2990 22 -359 950 2989 95 -863 570 2988 11 -269 252 2987 48 -590 51 2986 93 -335 519 2985 34 -118 712 2984 0 -868 626 2983 16 -484 550 2982 37 -244 360 2981 5 -786 272 2980 59 -380 832 2979 70 -317 630 2978 49 -200 553 2977 59 -532 591 2976 67 -807 333 2975 25 -85 843 2974 21 -76 790 2973 25 -189 324 2972 38 -88 451 2971 23 -440 891 2970 45 -201 212 2969 40 -76 902 2968 6 -962 915 2967 11 -257 423 2966 66 -489 38 2965 72 -52 966 2964 72 -466 866 2963 0 -873 144 2962 88 -560 781 2961 10 -679 52 2960 64 -310 342 2959 23 -986 946 2958 12 -491 448 2957 11 -385 943 2956 70 -72 3 2955 76 -99 713 2954 43 -722 120 2953 58 -362 786 2952 59 -729 452 2951 31 -709 409 2950 88 -396 112 2949 36 -497 11 2948 32 -505 408 2947 49 -940 937 2946 10 -289 331 2945 31 -592 850 2944 97 -334 993 2943 37 -333 279 2942 35 -43 432 2941 63 -297 511 2940 1 -101 45 2939 31 -602 827 2938 89 -471 390 2937 99 -605 792 2936 56 -480 340 2935 65 -857 594 2934 69 -713 17 2933 25 -847 726 2932 0 -920 613 2931 29 -466 706 2930 74 -218 413 2929 19 -436 907 2928 49 -598 427 2927 13 -451 914 2926 86 -746 954 2925 12 -576 437 2924 62 -291 257 2923 14 -112 710 2922 86 -906 544 2921 92 -292 549 2920 45 -506 697 2919 24 -479 368 2918 78 -513 264 2917 83 -959 740 2916 14 -516 501 2915 70 -180 479 2914 16 -547 278 2913 28 -166 938 2912 17 -994 472 2911 20 -852 207 2910 61 -329 465 2909 78 -103 943 2908 2 -524 691 2907 96 -238 441 2906 55 -22 535 2905 44 -201 884 2904 33 -339 106 2903 63 -465 972 2902 38 -265 591 2901 17 -741 828 2900 14 -522 758 2899 52 -251 60 2898 22 -250 413 2897 57 -906 109 2896 28 -651 107 2895 21 -777 703 2894 82 -134 251 2893 86 -380 209 2892 87 -763 29 2891 19 -69 618 2890 52 -698 297 2889 21 -647 646 2888 27 -303 294 2887 0 -2 68 2886 34 -404 396 2885 25 -451 958 2884 87 -42 987 2883 64 -179 674 2882 75 -411 675 2881 61 -321 304 2880 69 -650 948 2879 37 -352 269 2878 5 -225 656 2877 34 -672 89 2876 30 -437 380 2875 59 -970 231 2874 95 -313 888 2873 40 -999 136 2872 86 -370 922 2871 76 -355 323 2870 9 -679 319 2869 67 -613 707 2868 29 -566 43 2867 12 -709 701 2866 55 -148 646 2865 23 -342 543 2864 46 -751 546 2863 65 -214 93 2862 31 -598 678 2861 62 -4 419 2860 1 -612 372 2859 67 -663 171 2858 6 -341 573 2857 4 -55 318 2856 85 -102 767 2855 56 -996 809 2854 80 -453 343 2853 59 -415 686 2852 53 -258 612 2851 61 -47 338 2850 59 -200 610 2849 39 -598 19 2848 94 -254 188 2847 32 -550 296 2846 28 -958 754 2845 95 -466 214 2844 10 -657 53 2843 54 -73 921 2842 3 -274 22 2841 15 -728 201 2840 21 -590 444 2839 84 -831 626 2838 60 -891 35 2837 34 -541 333 2836 70 -540 846 2835 59 -160 563 2834 49 -132 505 2833 80 -899 881 2832 58 -820 945 2831 79 -757 363 2830 54 -817 245 2829 13 -590 258 2828 75 -702 639 2827 93 -486 111 2826 34 -283 99 2825 0 -57 683 2824 37 -623 224 2823 2 -936 785 2822 23 -581 253 2821 7 -118 407 2820 6 -986 378 2819 93 -618 819 2818 22 -528 589 2817 88 -12 348 2816 21 -416 621 2815 20 -458 351 2814 22 -439 794 2813 43 -532 154 2812 68 -845 15 2811 35 -29 123 2810 46 -559 712 2809 13 -229 339 2808 36 -241 671 2807 9 -726 13 2806 51 -270 977 2805 59 -557 791 2804 95 -639 746 2803 1 -139 332 2802 90 -892 891 2801 68 -410 331 2800 81 -372 763 2799 47 -668 278 2798 32 -658 574 2797 98 -35 920 2796 51 -185 638 2795 45 -44 938 2794 71 -413 111 2793 91 -441 220 2792 50 -559 871 2791 24 -568 345 2790 48 -484 141 2789 3 -703 340 2788 70 -654 473 2787 0 -281 59 2786 62 -700 743 2785 85 -826 793 2784 14 -891 418 2783 63 -349 253 2782 97 -525 764 2781 88 -204 443 2780 99 -800 333 2779 8 -867 694 2778 78 -414 387 2777 4 -315 772 2776 37 -949 708 2775 58 -375 510 2774 87 -164 658 2773 93 -489 89 2772 54 -320 892 2771 82 -110 906 2770 32 -639 302 2769 40 -307 731 2768 93 -615 677 2767 45 -63 792 2766 9 -198 706 2765 36 -852 939 2764 57 -568 393 2763 21 -197 718 2762 67 -985 502 2761 16 -603 917 2760 21 -571 470 2759 47 -54 479 2758 33 -885 354 2757 69 -85 733 2756 55 -767 791 2755 86 -545 363 2754 34 -674 535 2753 28 -215 505 2752 37 -585 959 2751 21 -446 739 2750 38 -990 138 2749 3 -125 639 2748 51 -620 140 2747 16 -942 686 2746 79 -427 518 2745 31 -828 62 2744 22 -29 912 2743 87 -546 159 2742 45 -219 830 2741 63 -600 350 2740 13 -498 514 2739 45 -499 348 2738 86 -453 369 2737 50 -167 481 2736 67 -456 96 2735 51 -150 350 2734 59 -753 412 2733 79 -328 828 2732 48 -480 492 2731 32 -835 682 2730 61 -165 590 2729 10 -979 360 2728 99 -887 826 2727 4 -384 163 2726 28 -746 915 2725 71 -937 801 2724 30 -584 314 2723 39 -336 156 2722 42 -809 708 2721 84 -91 516 2720 64 -230 102 2719 67 -534 954 2718 18 -662 758 2717 9 -247 574 2716 50 -114 405 2715 63 -486 908 2714 80 -158 972 2713 35 -447 575 2712 24 -191 204 2711 52 -414 973 2710 71 -147 483 2709 86 -195 95 2708 69 -184 588 2707 87 -169 864 2706 41 -496 830 2705 13 -935 454 2704 62 -397 105 2703 32 -370 721 2702 71 -230 809 2701 25 -490 856 2700 77 -388 165 2699 26 -507 824 2698 95 -723 457 2697 1 -34 281 2696 1 -375 504 2695 67 -348 300 2694 56 -384 617 2693 53 -912 454 2692 2 -953 478 2691 14 -690 510 2690 74 -341 314 2689 10 -366 940 2688 88 -176 996 2687 78 -776 342 2686 68 -203 111 2685 65 -683 22 2684 2 -162 512 2683 96 -975 886 2682 47 -968 399 2681 95 -196 639 2680 26 -373 220 2679 34 -943 98 2678 97 -654 93 2677 19 -230 31 2676 39 -89 631 2675 57 -510 63 2674 51 -625 491 2673 52 -487 513 2672 18 -760 696 2671 0 -419 912 2670 77 -122 375 2669 82 -4 783 2668 42 -62 791 2667 28 -400 826 2666 42 -567 53 2665 14 -571 998 2664 57 -978 334 2663 88 -816 178 2662 13 -783 235 2661 72 -537 949 2660 34 -591 392 2659 29 -992 140 2658 11 -964 864 2657 94 -773 283 2656 66 -54 561 2655 83 -663 694 2654 99 -156 745 2653 59 -943 411 2652 16 -285 386 2651 3 -557 43 2650 24 -251 179 2649 94 -276 176 2648 59 -581 279 2647 2 -721 829 2646 19 -866 836 2645 71 -949 402 2644 39 -334 431 2643 50 -25 128 2642 21 -342 786 2641 65 -864 299 2640 72 -3 348 2639 30 -896 570 2638 97 -449 836 2637 69 -993 472 2636 85 -434 327 2635 85 -970 883 2634 91 -302 294 2633 61 -342 555 2632 30 -487 928 2631 68 -951 423 2630 47 -777 329 2629 86 -733 280 2628 10 -364 835 2627 44 -144 3 2626 45 -444 937 2625 55 -588 303 2624 46 -739 305 2623 66 -626 626 2622 96 -505 204 2621 85 -93 617 2620 53 -48 754 2619 17 -445 659 2618 4 -831 990 2617 36 -66 897 2616 22 -634 95 2615 69 -997 795 2614 85 -678 707 2613 84 -422 106 2612 11 -586 318 2611 12 -862 361 2610 41 -95 129 2609 4 -668 675 2608 60 -93 148 2607 61 -801 520 2606 76 -300 844 2605 43 -87 6 2604 63 -601 735 2603 31 -787 992 2602 25 -956 709 2601 83 -232 366 2600 72 -454 441 2599 76 -526 990 2598 42 -628 848 2597 57 -676 333 2596 29 -837 795 2595 50 -270 317 2594 21 -743 62 2593 48 -283 420 2592 81 -342 111 2591 83 -925 957 2590 72 -451 339 2589 77 -142 852 2588 92 -514 282 2587 89 -538 791 2586 95 -477 287 2585 83 -255 726 2584 56 -642 672 2583 52 -309 983 2582 45 -153 105 2581 94 -617 946 2580 41 -487 850 2579 47 -569 29 2578 30 -490 945 2577 62 -504 114 2576 97 -561 271 2575 6 -54 39 2574 22 -688 67 2573 61 -877 518 2572 33 -159 524 2571 15 -96 942 2570 53 -820 165 2569 13 -84 681 2568 91 -831 651 2567 7 -842 915 2566 98 -231 839 2565 94 -972 609 2564 50 -548 279 2563 36 -994 177 2562 81 -581 619 2561 71 -777 405 2560 6 -483 213 2559 27 -30 838 2558 73 -736 91 2557 25 -75 44 2556 98 -229 435 2555 61 -329 141 2554 25 -101 554 2553 42 -558 91 2552 55 -213 656 2551 41 -191 786 2550 80 -375 540 2549 29 -746 483 2548 45 -47 263 2547 29 -608 378 2546 66 -294 351 2545 84 -587 835 2544 90 -462 869 2543 22 -435 141 2542 54 -870 609 2541 34 -246 509 2540 2 -56 841 2539 81 -219 158 2538 62 -885 634 2537 69 -26 814 2536 43 -515 945 2535 31 -966 672 2534 70 -728 685 2533 12 -531 198 2532 2 -100 322 2531 56 -667 206 2530 62 -682 186 2529 18 -523 931 2528 83 -820 258 2527 33 -868 125 2526 85 -273 607 2525 51 -987 582 2524 54 -486 96 2523 23 -876 462 2522 19 -115 941 2521 43 -20 434 2520 43 -254 352 2519 98 -672 502 2518 15 -133 475 2517 70 -518 347 2516 95 -24 961 2515 59 -486 312 2514 28 -634 40 2513 50 -521 765 2512 61 -506 999 2511 76 -81 447 2510 9 -850 826 2509 76 -26 455 2508 58 -127 751 2507 53 -386 357 2506 61 -649 308 2505 49 -272 785 2504 53 -274 889 2503 85 -766 849 2502 11 -552 666 2501 1 -621 328 2500 42 -370 184 2499 23 -703 41 2498 82 -394 925 2497 89 -48 120 2496 74 -522 956 2495 73 -896 685 2494 37 -39 738 2493 99 -183 98 2492 50 -338 589 2491 21 -143 194 2490 93 -143 407 2489 25 -116 925 2488 66 -804 157 2487 30 -164 4 2486 34 -270 359 2485 52 -946 379 2484 62 -640 488 2483 85 -509 294 2482 85 -395 282 2481 84 -786 681 2480 19 -482 583 2479 0 -767 357 2478 2 -152 963 2477 31 -645 818 2476 64 -979 900 2475 89 -890 769 2474 32 -194 0 2473 30 -12 11 2472 13 -601 650 2471 11 -97 195 2470 60 -225 973 2469 30 -393 714 2468 71 -145 672 2467 61 -918 746 2466 50 -130 570 2465 66 -769 16 2464 8 -989 176 2463 69 -361 16 2462 18 -454 505 2461 41 -221 303 2460 50 -259 590 2459 87 -42 98 2458 83 -926 108 2457 24 -175 841 2456 22 -553 576 2455 78 -840 392 2454 36 -159 515 2453 78 -511 770 2452 62 -202 907 2451 90 -712 631 2450 23 -492 40 2449 96 -989 583 2448 21 -267 21 2447 11 -265 439 2446 75 -184 425 2445 62 -876 581 2444 71 -744 152 2443 68 -863 721 2442 64 -276 672 2441 30 -590 271 2440 48 -457 745 2439 22 -561 100 2438 50 -581 365 2437 72 -14 128 2436 0 -844 908 2435 8 -429 31 2434 30 -430 33 2433 13 -49 339 2432 88 -401 819 2431 58 -525 269 2430 68 -644 717 2429 13 -735 780 2428 89 -237 720 2427 98 -219 919 2426 56 -876 774 2425 16 -998 174 2424 41 -693 251 2423 99 -520 293 2422 38 -550 901 2421 64 -551 551 2420 87 -936 238 2419 88 -59 914 2418 90 -801 412 2417 49 -145 397 2416 1 -599 754 2415 34 -922 416 2414 87 -957 617 2413 30 -391 733 2412 17 -350 772 2411 96 -313 994 2410 99 -323 972 2409 61 -502 411 2408 87 -15 480 2407 25 -642 674 2406 65 -338 465 2405 54 -798 572 2404 67 -884 131 2403 96 -961 203 2402 56 -777 971 2401 4 -21 383 2400 3 -560 737 2399 98 -931 618 2398 82 -805 602 2397 48 -209 110 2396 37 -892 868 2395 30 -440 711 2394 53 -928 399 2393 91 -231 524 2392 92 -588 4 2391 18 -645 47 2390 75 -118 168 2389 46 -15 334 2388 62 -492 114 2387 12 -241 67 2386 59 -156 765 2385 31 -312 625 2384 45 -875 990 2383 51 -519 740 2382 69 -956 427 2381 64 -879 294 2380 94 -833 831 2379 52 -219 504 2378 10 -47 529 2377 52 -302 278 2376 25 -139 865 2375 8 -634 938 2374 84 -250 816 2373 43 -312 53 2372 35 -132 699 2371 56 -463 416 2370 7 -327 423 2369 4 -974 579 2368 61 -250 271 2367 17 -413 166 2366 74 -926 239 2365 16 -122 408 2364 50 -763 81 2363 38 -353 792 2362 93 -282 485 2361 18 -993 32 2360 66 -843 431 2359 13 -308 441 2358 35 -105 427 2357 72 -926 581 2356 83 -831 658 2355 48 -326 120 2354 80 -289 446 2353 35 -306 757 2352 41 -453 511 2351 7 -601 532 2350 28 -989 784 2349 15 -13 628 2348 53 -846 887 2347 20 -923 350 2346 17 -538 681 2345 9 -673 445 2344 50 -688 948 2343 3 -246 339 2342 98 -978 780 2341 85 -748 139 2340 85 -155 614 2339 61 -741 332 2338 97 -536 24 2337 16 -668 83 2336 92 -235 589 2335 38 -497 467 2334 86 -609 54 2333 98 -558 129 2332 44 -641 1 2331 26 -524 240 2330 22 -282 635 2329 59 -308 808 2328 41 -940 244 2327 20 -493 538 2326 86 -122 520 2325 43 -412 878 2324 73 -925 544 2323 88 -127 173 2322 5 -760 38 2321 91 -605 637 2320 11 -826 178 2319 24 -564 210 2318 97 -705 336 2317 36 -18 435 2316 44 -641 693 2315 37 -334 850 2314 71 -370 837 2313 48 -134 133 2312 79 -401 800 2311 36 -459 874 2310 15 -967 268 2309 77 -873 605 2308 26 -901 921 2307 85 -741 75 2306 68 -843 661 2305 37 -13 223 2304 30 -704 688 2303 96 -333 431 2302 23 -925 211 2301 73 -606 375 2300 94 -662 518 2299 49 -684 401 2298 9 -846 172 2297 97 -414 310 2296 16 -437 70 2295 89 -535 343 2294 83 -257 727 2293 30 -219 502 2292 37 -836 791 2291 40 -857 451 2290 31 -116 396 2289 94 -229 122 2288 97 -861 812 2287 83 -240 262 2286 43 -726 67 2285 97 -615 521 2284 90 -224 937 2283 27 -711 962 2282 3 -340 89 2281 38 -54 374 2280 97 -274 965 2279 74 -309 140 2278 88 -549 405 2277 36 -194 455 2276 62 -546 74 2275 51 -583 624 2274 11 -975 239 2273 39 -873 655 2272 51 -714 403 2271 37 -409 238 2270 28 -824 854 2269 77 -735 519 2268 96 -949 745 2267 76 -381 108 2266 35 -449 402 2265 64 -384 720 2264 96 -584 877 2263 60 -251 142 2262 10 -165 84 2261 15 -384 506 2260 30 -334 814 2259 58 -773 204 2258 8 -637 404 2257 78 -706 706 2256 56 -681 685 2255 93 -842 353 2254 6 -734 507 2253 80 -57 942 2252 33 -578 854 2251 8 -692 720 2250 78 -609 494 2249 4 -799 304 2248 56 -697 217 2247 13 -20 635 2246 93 -331 867 2245 2 -846 264 2244 83 -564 467 2243 10 -87 247 2242 67 -134 303 2241 47 -225 732 2240 88 -190 487 2239 8 -86 425 2238 80 -581 205 2237 10 -768 906 2236 67 -602 185 2235 68 -797 730 2234 48 -219 430 2233 28 -943 197 2232 47 -571 593 2231 95 -244 803 2230 90 -62 272 2229 3 -220 707 2228 10 -299 424 2227 50 -720 987 2226 81 -454 203 2225 16 -300 203 2224 80 -233 804 2223 57 -604 523 2222 27 -790 44 2221 37 -530 873 2220 32 -564 932 2219 18 -283 597 2218 84 -436 692 2217 92 -784 646 2216 57 -0 360 2215 26 -398 227 2214 15 -280 301 2213 6 -479 903 2212 62 -171 46 2211 81 -940 143 2210 25 -334 340 2209 96 -905 921 2208 28 -46 341 2207 84 -285 313 2206 65 -133 111 2205 78 -926 87 2204 60 -397 438 2203 11 -857 814 2202 80 -902 554 2201 30 -802 294 2200 23 -419 684 2199 60 -579 435 2198 42 -28 193 2197 85 -201 869 2196 76 -24 181 2195 15 -649 483 2194 20 -623 316 2193 52 -260 493 2192 54 -259 77 2191 95 -610 623 2190 10 -248 177 2189 38 -242 570 2188 83 -324 97 2187 55 -687 608 2186 82 -698 945 2185 17 -166 678 2184 37 -823 988 2183 2 -416 585 2182 36 -453 854 2181 0 -446 717 2180 64 -606 543 2179 36 -472 288 2178 0 -489 724 2177 91 -662 649 2176 63 -267 802 2175 98 -689 349 2174 53 -402 663 2173 34 -731 361 2172 40 -137 351 2171 96 -174 288 2170 0 -254 355 2169 84 -564 87 2168 13 -74 281 2167 98 -846 647 2166 82 -453 457 2165 39 -685 188 2164 57 -302 936 2163 28 -10 444 2162 67 -62 956 2161 59 -932 166 2160 96 -267 706 2159 91 -806 150 2158 68 -634 156 2157 48 -190 432 2156 22 -268 817 2155 39 -252 290 2154 76 -491 615 2153 38 -487 77 2152 29 -789 630 2151 94 -459 43 2150 13 -556 229 2149 66 -993 200 2148 46 -724 261 2147 17 -615 835 2146 44 -526 625 2145 92 -674 384 2144 1 -537 91 2143 76 -447 344 2142 0 -586 817 2141 69 -813 464 2140 32 -29 203 2139 90 -939 289 2138 56 -425 728 2137 26 -209 522 2136 10 -240 904 2135 8 -293 256 2134 85 -746 756 2133 13 -527 305 2132 9 -352 368 2131 86 -261 426 2130 77 -914 341 2129 78 -561 292 2128 9 -205 160 2127 51 -617 20 2126 21 -648 236 2125 96 -499 714 2124 94 -450 47 2123 54 -937 229 2122 21 -941 87 2121 17 -85 988 2120 9 -48 693 2119 34 -132 577 2118 35 -139 297 2117 35 -783 246 2116 58 -522 21 2115 96 -667 401 2114 14 -817 328 2113 4 -141 42 2112 51 -99 84 2111 99 -295 744 2110 85 -116 993 2109 3 -280 997 2108 91 -50 767 2107 99 -225 619 2106 35 -620 820 2105 26 -72 99 2104 85 -285 536 2103 84 -958 517 2102 67 -340 139 2101 4 -750 820 2100 80 -996 120 2099 17 -229 923 2098 83 -148 636 2097 23 -798 94 2096 82 -721 406 2095 60 -562 5 2094 54 -19 173 2093 78 -377 634 2092 32 -319 238 2091 61 -699 624 2090 58 -196 343 2089 75 -286 605 2088 76 -542 405 2087 8 -687 218 2086 34 -401 58 2085 7 -831 759 2084 15 -538 460 2083 54 -396 708 2082 64 -613 28 2081 5 -281 836 2080 61 -737 987 2079 50 -199 685 2078 90 -186 731 2077 74 -160 272 2076 85 -298 919 2075 28 -299 615 2074 56 -751 901 2073 29 -680 582 2072 14 -192 439 2071 78 -849 116 2070 33 -301 593 2069 54 -953 165 2068 53 -459 889 2067 1 -353 569 2066 2 -303 715 2065 86 -714 276 2064 99 -318 150 2063 54 -143 359 2062 7 -323 450 2061 48 -522 787 2060 34 -428 6 2059 54 -275 524 2058 34 -319 986 2057 49 -853 164 2056 10 -438 863 2055 4 -126 451 2054 58 -790 476 2053 39 -908 583 2052 17 -662 145 2051 82 -781 796 2050 80 -481 198 2049 9 -538 854 2048 15 -822 387 2047 95 -301 56 2046 46 -411 460 2045 41 -975 193 2044 31 -893 221 2043 33 -437 354 2042 88 -349 19 2041 24 -597 705 2040 88 -343 942 2039 30 -466 196 2038 94 -330 489 2037 71 -596 51 2036 52 -266 101 2035 88 -972 977 2034 43 -866 453 2033 8 -334 635 2032 45 -314 365 2031 8 -762 580 2030 75 -746 356 2029 25 -706 227 2028 87 -438 195 2027 13 -949 631 2026 73 -124 453 2025 33 -524 353 2024 29 -817 626 2023 10 -270 367 2022 53 -784 336 2021 2 -224 498 2020 55 -129 376 2019 1 -32 740 2018 4 -563 402 2017 26 -178 403 2016 48 -99 35 2015 82 -727 188 2014 59 -259 573 2013 70 -30 511 2012 54 -838 469 2011 48 -121 535 2010 55 -635 975 2009 9 -338 773 2008 9 -998 777 2007 46 -367 664 2006 38 -847 225 2005 7 -614 892 2004 37 -62 160 2003 46 -42 60 2002 22 -934 926 2001 19 -559 465 2000 71 -202 997 1999 48 -995 629 1998 29 -113 82 1997 34 -438 306 1996 63 -333 707 1995 52 -731 904 1994 23 -99 238 1993 55 -133 36 1992 1 -461 476 1991 10 -467 230 1990 37 -368 188 1989 35 -546 957 1988 20 -776 709 1987 88 -599 110 1986 67 -802 287 1985 10 -666 679 1984 60 -201 533 1983 63 -560 910 1982 96 -245 733 1981 67 -42 17 1980 99 -231 150 1979 9 -247 324 1978 82 -599 207 1977 77 -822 569 1976 17 -607 503 1975 79 -146 969 1974 13 -622 666 1973 46 -177 293 1972 64 -715 678 1971 31 -867 894 1970 20 -825 277 1969 81 -117 51 1968 98 -637 593 1967 64 -66 379 1966 77 -533 661 1965 21 -303 670 1964 46 -372 823 1963 52 -615 326 1962 44 -783 111 1961 46 -617 392 1960 84 -225 827 1959 4 -458 335 1958 70 -213 870 1957 48 -718 562 1956 57 -990 753 1955 53 -847 937 1954 23 -497 79 1953 93 -214 983 1952 75 -718 613 1951 83 -564 805 1950 16 -492 335 1949 39 -464 227 1948 76 -308 909 1947 24 -809 38 1946 49 -816 302 1945 72 -858 298 1944 14 -95 173 1943 35 -370 925 1942 28 -807 665 1941 49 -470 773 1940 15 -108 625 1939 7 -317 521 1938 2 -871 750 1937 15 -735 766 1936 49 -3 585 1935 99 -124 792 1934 95 -248 68 1933 76 -259 786 1932 72 -891 342 1931 56 -148 81 1930 33 -104 44 1929 36 -770 871 1928 79 -984 657 1927 44 -181 504 1926 13 -792 35 1925 73 -724 195 1924 87 -281 38 1923 87 -444 161 1922 98 -260 225 1921 36 -36 974 1920 74 -172 571 1919 4 -214 344 1918 33 -153 310 1917 78 -468 403 1916 80 -840 853 1915 38 -156 2 1914 6 -876 887 1913 44 -935 620 1912 83 -250 624 1911 18 -403 699 1910 22 -227 709 1909 86 -33 548 1908 95 -907 982 1907 6 -550 413 1906 68 -850 321 1905 62 -114 624 1904 68 -267 605 1903 27 -996 654 1902 94 -924 959 1901 68 -990 360 1900 84 -161 905 1899 17 -565 897 1898 19 -568 376 1897 12 -92 56 1896 35 -697 943 1895 69 -19 404 1894 73 -950 338 1893 84 -695 256 1892 27 -598 837 1891 7 -454 672 1890 93 -7 980 1889 82 -520 68 1888 59 -320 769 1887 99 -112 657 1886 47 -539 962 1885 39 -65 889 1884 67 -82 577 1883 6 -418 197 1882 25 -164 138 1881 9 -691 104 1880 14 -912 233 1879 44 -299 598 1878 48 -111 520 1877 20 -694 82 1876 20 -73 716 1875 57 -312 609 1874 47 -379 814 1873 98 -58 157 1872 66 -34 952 1871 25 -871 697 1870 47 -635 959 1869 77 -77 286 1868 61 -438 993 1867 18 -365 634 1866 41 -106 99 1865 62 -794 490 1864 76 -656 319 1863 93 -205 409 1862 32 -254 780 1861 2 -738 694 1860 16 -673 165 1859 23 -293 425 1858 55 -358 770 1857 63 -534 796 1856 7 -608 859 1855 25 -171 829 1854 31 -909 610 1853 13 -629 297 1852 45 -86 861 1851 95 -528 927 1850 51 -740 677 1849 6 -655 918 1848 38 -973 566 1847 93 -936 813 1846 82 -30 946 1845 92 -218 174 1844 43 -313 686 1843 26 -435 500 1842 28 -933 434 1841 54 -249 451 1840 55 -759 684 1839 78 -351 446 1838 8 -753 110 1837 68 -866 897 1836 3 -772 488 1835 90 -487 175 1834 81 -186 982 1833 90 -65 737 1832 87 -983 984 1831 50 -766 769 1830 68 -238 704 1829 49 -335 402 1828 40 -212 644 1827 59 -408 131 1826 88 -313 93 1825 9 -193 908 1824 28 -244 26 1823 30 -752 376 1822 12 -215 817 1821 8 -65 194 1820 21 -302 82 1819 52 -757 809 1818 90 -513 711 1817 12 -37 793 1816 80 -185 808 1815 9 -882 985 1814 12 -649 179 1813 94 -558 39 1812 49 -623 864 1811 53 -111 689 1810 14 -272 624 1809 76 -98 780 1808 54 -917 318 1807 24 -985 708 1806 47 -822 974 1805 85 -806 172 1804 30 -139 455 1803 23 -175 955 1802 9 -174 387 1801 93 -65 386 1800 51 -844 218 1799 83 -461 301 1798 17 -610 767 1797 18 -733 623 1796 93 -802 549 1795 16 -716 70 1794 1 -499 141 1793 66 -568 155 1792 96 -1 423 1791 0 -167 672 1790 10 -916 665 1789 22 -534 992 1788 38 -144 248 1787 85 -73 770 1786 87 -479 145 1785 93 -929 350 1784 8 -985 701 1783 21 -732 963 1782 93 -751 891 1781 56 -7 888 1780 83 -672 837 1779 25 -744 531 1778 38 -477 975 1777 38 -625 944 1776 7 -794 845 1775 59 -648 868 1774 54 -738 286 1773 94 -72 363 1772 25 -2 733 1771 98 -50 583 1770 74 -306 867 1769 33 -556 993 1768 92 -30 318 1767 26 -99 477 1766 85 -976 43 1765 83 -582 605 1764 14 -922 691 1763 91 -629 272 1762 66 -150 236 1761 7 -715 409 1760 95 -874 406 1759 74 -674 660 1758 74 -841 415 1757 52 -433 21 1756 93 -438 684 1755 12 -914 235 1754 39 -419 244 1753 65 -35 595 1752 29 -826 118 1751 47 -2 206 1750 43 -746 995 1749 84 -245 223 1748 20 -393 595 1747 83 -336 807 1746 40 -449 728 1745 99 -990 734 1744 52 -649 366 1743 49 -476 813 1742 38 -912 44 1741 20 -211 594 1740 82 -771 640 1739 25 -628 366 1738 50 -787 425 1737 85 -78 412 1736 5 -994 470 1735 88 -368 29 1734 45 -552 111 1733 34 -769 173 1732 17 -449 385 1731 56 -954 567 1730 70 -273 755 1729 43 -941 649 1728 14 -12 793 1727 84 -942 170 1726 70 -441 428 1725 8 -917 117 1724 62 -937 167 1723 81 -788 609 1722 78 -818 863 1721 32 -811 261 1720 49 -105 296 1719 68 -855 301 1718 33 -623 132 1717 92 -742 624 1716 7 -310 457 1715 50 -950 811 1714 52 -558 32 1713 97 -746 462 1712 14 -601 825 1711 96 -964 814 1710 0 -994 348 1709 70 -168 403 1708 25 -508 858 1707 23 -166 569 1706 88 -646 976 1705 43 -779 544 1704 35 -569 829 1703 39 -637 180 1702 81 -10 962 1701 14 -466 301 1700 63 -944 455 1699 96 -544 17 1698 82 -289 351 1697 66 -592 448 1696 34 -432 72 1695 51 -715 967 1694 86 -649 579 1693 21 -218 667 1692 93 -660 507 1691 62 -845 666 1690 54 -438 143 1689 52 -665 166 1688 40 -903 317 1687 25 -376 823 1686 69 -104 651 1685 16 -388 657 1684 71 -912 279 1683 6 -159 303 1682 43 -840 82 1681 55 -522 23 1680 81 -977 121 1679 40 -848 144 1678 77 -493 558 1677 76 -171 536 1676 52 -994 443 1675 27 -378 651 1674 71 -975 635 1673 47 -220 872 1672 75 -59 742 1671 31 -901 407 1670 31 -976 634 1669 54 -586 10 1668 12 -22 234 1667 35 -93 255 1666 32 -792 555 1665 17 -15 240 1664 61 -762 723 1663 40 -130 433 1662 75 -335 0 1661 16 -772 772 1660 15 -623 415 1659 92 -776 774 1658 39 -979 32 1657 56 -699 145 1656 92 -315 561 1655 30 -516 212 1654 77 -290 648 1653 25 -432 593 1652 63 -227 2 1651 79 -356 233 1650 56 -641 534 1649 14 -742 826 1648 84 -887 634 1647 79 -584 628 1646 28 -348 524 1645 38 -563 523 1644 79 -55 620 1643 22 -590 838 1642 85 -769 231 1641 20 -698 414 1640 87 -707 300 1639 71 -191 51 1638 89 -6 516 1637 85 -103 896 1636 30 -1 585 1635 23 -902 572 1634 78 -782 368 1633 50 -606 653 1632 46 -816 333 1631 82 -113 155 1630 7 -249 815 1629 99 -534 44 1628 51 -620 551 1627 18 -310 67 1626 90 -12 451 1625 10 -204 276 1624 9 -714 42 1623 11 -320 644 1622 17 -177 750 1621 79 -339 79 1620 70 -771 475 1619 86 -492 330 1618 71 -484 282 1617 91 -616 800 1616 30 -174 3 1615 29 -233 979 1614 80 -398 943 1613 49 -894 385 1612 39 -670 87 1611 14 -603 839 1610 83 -145 148 1609 56 -48 800 1608 27 -481 605 1607 0 -797 10 1606 86 -24 491 1605 44 -35 317 1604 94 -558 95 1603 83 -298 252 1602 50 -247 304 1601 22 -690 268 1600 6 -348 290 1599 45 -195 269 1598 9 -594 140 1597 56 -519 426 1596 68 -174 499 1595 77 -221 106 1594 98 -843 330 1593 47 -947 280 1592 25 -35 157 1591 5 -978 607 1590 55 -21 361 1589 34 -129 529 1588 15 -713 883 1587 60 -926 910 1586 7 -393 784 1585 34 -776 511 1584 95 -50 217 1583 37 -123 209 1582 89 -549 493 1581 91 -245 214 1580 5 -832 189 1579 95 -646 551 1578 89 -972 526 1577 41 -126 729 1576 78 -273 392 1575 53 -294 574 1574 61 -7 482 1573 72 -715 982 1572 92 -278 855 1571 57 -25 100 1570 30 -637 65 1569 41 -25 476 1568 18 -796 628 1567 67 -336 253 1566 84 -818 916 1565 85 -91 891 1564 97 -499 798 1563 28 -127 353 1562 29 -754 270 1561 43 -35 889 1560 25 -589 227 1559 38 -847 511 1558 61 -375 828 1557 22 -336 992 1556 45 -24 874 1555 51 -93 693 1554 72 -444 994 1553 59 -82 854 1552 37 -380 184 1551 37 -662 864 1550 71 -715 775 1549 44 -683 383 1548 74 -835 768 1547 47 -118 941 1546 3 -181 792 1545 31 -698 134 1544 93 -139 220 1543 64 -669 999 1542 36 -319 653 1541 70 -88 273 1540 71 -392 703 1539 94 -614 270 1538 3 -827 432 1537 84 -148 727 1536 71 -658 380 1535 93 -914 282 1534 48 -221 286 1533 55 -345 659 1532 46 -379 983 1531 35 -570 771 1530 23 -432 915 1529 69 -838 182 1528 77 -705 132 1527 78 -346 778 1526 67 -97 455 1525 48 -995 922 1524 74 -627 89 1523 69 -676 119 1522 87 -211 119 1521 96 -856 534 1520 80 -732 919 1519 13 -50 990 1518 59 -353 107 1517 13 -323 189 1516 35 -533 745 1515 24 -832 51 1514 10 -970 817 1513 36 -0 908 1512 95 -584 157 1511 46 -615 671 1510 35 -928 542 1509 12 -882 461 1508 68 -918 774 1507 69 -444 109 1506 3 -693 147 1505 79 -233 733 1504 70 -908 417 1503 86 -751 486 1502 96 -485 109 1501 41 -129 230 1500 96 -81 442 1499 68 -686 984 1498 4 -665 666 1497 96 -961 240 1496 47 -414 89 1495 75 -315 838 1494 45 -931 892 1493 32 -376 554 1492 15 -879 445 1491 26 -788 282 1490 35 -457 640 1489 4 -318 81 1488 39 -425 490 1487 2 -150 723 1486 70 -251 291 1485 54 -945 134 1484 9 -338 167 1483 38 -108 891 1482 55 -163 909 1481 49 -642 308 1480 9 -558 653 1479 33 -591 373 1478 13 -767 316 1477 89 -432 156 1476 27 -156 449 1475 89 -967 713 1474 30 -276 829 1473 60 -981 58 1472 22 -601 405 1471 94 -654 760 1470 52 -279 191 1469 8 -56 246 1468 96 -160 617 1467 82 -706 375 1466 33 -735 593 1465 27 -884 698 1464 18 -770 377 1463 69 -652 284 1462 29 -644 424 1461 38 -568 437 1460 94 -945 115 1459 37 -628 143 1458 22 -241 489 1457 89 -782 58 1456 45 -894 86 1455 97 -320 498 1454 85 -93 396 1453 11 -859 914 1452 11 -986 433 1451 0 -321 571 1450 7 -972 151 1449 62 -653 327 1448 31 -430 441 1447 38 -972 482 1446 45 -588 120 1445 88 -102 736 1444 57 -481 996 1443 22 -480 109 1442 23 -862 931 1441 87 -419 453 1440 66 -824 306 1439 34 -885 930 1438 31 -959 927 1437 22 -362 571 1436 45 -384 313 1435 38 -739 347 1434 48 -886 993 1433 62 -178 360 1432 0 -478 207 1431 61 -147 316 1430 44 -375 29 1429 59 -2 96 1428 93 -356 764 1427 92 -257 74 1426 59 -966 897 1425 97 -354 865 1424 64 -632 619 1423 85 -153 382 1422 70 -891 175 1421 69 -286 846 1420 33 -933 657 1419 77 -332 11 1418 37 -689 329 1417 64 -176 618 1416 9 -32 333 1415 29 -245 791 1414 61 -237 144 1413 72 -207 9 1412 47 -328 368 1411 26 -189 559 1410 60 -645 397 1409 35 -681 727 1408 60 -711 547 1407 64 -285 807 1406 51 -542 679 1405 14 -647 890 1404 78 -135 242 1403 0 -640 217 1402 2 -809 656 1401 87 -161 251 1400 13 -669 752 1399 54 -180 958 1398 96 -740 129 1397 97 -127 368 1396 42 -789 357 1395 74 -647 778 1394 89 -25 978 1393 51 -560 151 1392 49 -404 739 1391 83 -499 594 1390 64 -793 580 1389 49 -829 993 1388 48 -761 544 1387 44 -10 682 1386 61 -579 848 1385 33 -799 382 1384 14 -827 17 1383 62 -411 663 1382 46 -145 184 1381 15 -14 154 1380 90 -587 3 1379 70 -448 48 1378 96 -862 828 1377 6 -834 274 1376 75 -466 195 1375 43 -364 520 1374 78 -354 156 1373 97 -479 308 1372 41 -29 251 1371 26 -151 198 1370 13 -954 742 1369 42 -220 895 1368 13 -554 317 1367 58 -78 319 1366 2 -674 650 1365 36 -364 808 1364 10 -848 555 1363 0 -56 149 1362 87 -53 135 1361 44 -455 703 1360 87 -846 287 1359 19 -578 552 1358 73 -997 558 1357 66 -669 659 1356 47 -842 266 1355 40 -252 91 1354 31 -405 134 1353 51 -14 425 1352 79 -431 572 1351 0 -415 680 1350 59 -735 462 1349 60 -994 68 1348 26 -898 190 1347 58 -393 72 1346 32 -174 92 1345 82 -957 794 1344 58 -708 724 1343 84 -853 787 1342 39 -891 405 1341 58 -217 989 1340 1 -393 340 1339 68 -878 687 1338 74 -118 252 1337 9 -979 501 1336 50 -297 237 1335 21 -69 742 1334 21 -936 456 1333 24 -382 808 1332 85 -416 566 1331 96 -648 335 1330 67 -653 940 1329 82 -435 644 1328 51 -750 591 1327 76 -264 285 1326 13 -495 2 1325 68 -285 968 1324 22 -647 393 1323 13 -242 893 1322 55 -230 287 1321 96 -395 849 1320 76 -296 308 1319 99 -52 755 1318 21 -305 621 1317 68 -283 456 1316 48 -34 453 1315 76 -574 94 1314 20 -500 578 1313 63 -605 587 1312 40 -438 198 1311 1 -541 772 1310 83 -553 777 1309 9 -133 533 1308 24 -164 198 1307 74 -3 716 1306 2 -358 560 1305 24 -515 570 1304 45 -991 233 1303 7 -388 393 1302 89 -426 176 1301 16 -995 736 1300 89 -243 856 1299 98 -334 495 1298 42 -482 724 1297 96 -156 773 1296 16 -989 789 1295 64 -337 386 1294 84 -840 178 1293 52 -216 728 1292 60 -440 270 1291 96 -880 909 1290 43 -360 566 1289 75 -771 451 1288 90 -950 807 1287 85 -984 517 1286 32 -403 801 1285 16 -207 318 1284 65 -450 922 1283 49 -458 639 1282 62 -360 531 1281 77 -342 679 1280 56 -115 842 1279 51 -644 57 1278 58 -290 526 1277 82 -715 158 1276 96 -483 515 1275 58 -395 155 1274 19 -282 873 1273 75 -108 847 1272 99 -851 216 1271 9 -837 40 1270 1 -784 931 1269 22 -531 768 1268 47 -367 853 1267 35 -643 385 1266 57 -359 385 1265 23 -282 437 1264 8 -26 765 1263 11 -630 894 1262 17 -176 79 1261 25 -109 790 1260 1 -162 757 1259 5 -914 115 1258 25 -468 780 1257 16 -999 342 1256 72 -947 143 1255 28 -672 975 1254 7 -871 939 1253 25 -814 916 1252 39 -289 243 1251 45 -32 961 1250 6 -642 798 1249 94 -335 90 1248 24 -437 439 1247 44 -198 440 1246 46 -168 205 1245 5 -35 822 1244 27 -22 860 1243 80 -673 940 1242 5 -281 387 1241 52 -162 119 1240 25 -708 698 1239 39 -650 802 1238 30 -998 977 1237 89 -235 417 1236 23 -383 776 1235 3 -961 474 1234 13 -919 744 1233 1 -552 530 1232 34 -268 268 1231 39 -421 866 1230 11 -896 83 1229 45 -824 408 1228 5 -560 659 1227 65 -641 208 1226 76 -301 897 1225 85 -729 120 1224 42 -213 663 1223 4 -262 958 1222 36 -402 272 1221 28 -782 664 1220 84 -674 396 1219 52 -749 405 1218 7 -451 889 1217 26 -311 911 1216 91 -776 430 1215 33 -457 379 1214 57 -704 675 1213 51 -685 81 1212 95 -608 438 1211 86 -267 321 1210 61 -991 453 1209 10 -515 806 1208 92 -978 345 1207 29 -480 579 1206 14 -51 768 1205 53 -703 55 1204 31 -594 564 1203 75 -643 91 1202 1 -116 240 1201 7 -868 512 1200 34 -646 182 1199 27 -461 627 1198 47 -765 158 1197 53 -811 605 1196 49 -712 214 1195 42 -491 567 1194 34 -472 733 1193 10 -850 942 1192 95 -728 735 1191 52 -329 65 1190 24 -554 799 1189 22 -469 938 1188 18 -552 39 1187 69 -391 69 1186 95 -647 80 1185 9 -834 239 1184 22 -790 157 1183 1 -206 423 1182 62 -669 278 1181 12 -266 25 1180 39 -860 37 1179 77 -898 489 1178 8 -970 741 1177 91 -988 855 1176 16 -840 878 1175 74 -81 201 1174 81 -733 396 1173 4 -145 499 1172 58 -253 723 1171 53 -988 623 1170 40 -548 689 1169 40 -748 169 1168 96 -886 755 1167 92 -976 416 1166 98 -676 931 1165 14 -805 769 1164 75 -897 458 1163 34 -776 48 1162 58 -99 133 1161 89 -934 997 1160 26 -520 443 1159 44 -413 34 1158 79 -339 946 1157 86 -485 833 1156 90 -161 389 1155 29 -310 410 1154 87 -410 758 1153 90 -914 696 1152 12 -135 627 1151 67 -553 824 1150 16 -409 640 1149 41 -87 937 1148 10 -113 952 1147 7 -443 610 1146 85 -979 428 1145 32 -651 963 1144 85 -62 787 1143 90 -69 444 1142 49 -803 511 1141 77 -183 750 1140 58 -702 307 1139 14 -985 32 1138 32 -342 220 1137 97 -182 530 1136 67 -464 472 1135 46 -176 950 1134 32 -342 404 1133 58 -933 717 1132 99 -760 196 1131 26 -442 437 1130 62 -275 822 1129 48 -811 347 1128 71 -689 304 1127 64 -58 205 1126 16 -521 136 1125 71 -546 737 1124 28 -687 596 1123 83 -520 727 1122 40 -758 645 1121 17 -615 139 1120 31 -474 763 1119 16 -43 73 1118 46 -98 483 1117 12 -69 442 1116 63 -399 429 1115 53 -141 455 1114 97 -868 423 1113 85 -82 236 1112 16 -506 855 1111 76 -375 150 1110 14 -690 702 1109 14 -590 342 1108 43 -40 491 1107 94 -13 93 1106 2 -974 562 1105 66 -31 115 1104 25 -186 692 1103 27 -380 405 1102 78 -705 618 1101 57 -447 1 1100 13 -360 711 1099 68 -851 484 1098 9 -397 916 1097 55 -530 359 1096 2 -446 411 1095 3 -423 986 1094 94 -287 485 1093 84 -786 210 1092 80 -617 445 1091 67 -290 445 1090 25 -226 585 1089 8 -567 549 1088 50 -557 523 1087 45 -948 987 1086 86 -424 97 1085 8 -500 97 1084 2 -274 38 1083 13 -765 131 1082 50 -999 416 1081 16 -859 170 1080 32 -36 578 1079 6 -25 55 1078 65 -536 586 1077 1 -890 782 1076 60 -999 60 1075 52 -59 887 1074 92 -906 634 1073 22 -715 332 1072 50 -245 841 1071 76 -592 263 1070 13 -522 404 1069 82 -469 648 1068 1 -803 401 1067 48 -721 85 1066 64 -173 599 1065 89 -253 697 1064 93 -302 717 1063 15 -490 742 1062 19 -577 626 1061 46 -858 316 1060 65 -756 812 1059 7 -246 521 1058 5 -315 843 1057 66 -486 755 1056 8 -901 950 1055 54 -979 787 1054 91 -975 961 1053 95 -115 722 1052 81 -309 816 1051 91 -504 581 1050 71 -290 18 1049 10 -678 386 1048 51 -87 584 1047 93 -804 533 1046 82 -163 628 1045 58 -825 968 1044 92 -239 139 1043 0 -905 899 1042 86 -234 193 1041 80 -563 616 1040 80 -632 591 1039 21 -802 579 1038 61 -50 101 1037 59 -904 243 1036 28 -659 663 1035 64 -829 917 1034 33 -240 143 1033 58 -705 54 1032 33 -576 0 1031 67 -25 590 1030 67 -11 602 1029 93 -477 21 1028 82 -857 307 1027 75 -580 642 1026 14 -745 302 1025 24 -774 751 1024 83 -89 252 1023 58 -53 663 1022 53 -410 999 1021 12 -988 739 1020 55 -580 101 1019 1 -714 78 1018 53 -664 604 1017 61 -339 902 1016 27 -550 414 1015 83 -499 240 1014 97 -589 54 1013 68 -663 406 1012 3 -260 577 1011 64 -637 538 1010 42 -23 479 1009 40 -473 914 1008 86 -702 342 1007 5 -487 442 1006 32 -173 863 1005 78 -185 285 1004 5 -648 649 1003 91 -829 392 1002 92 -39 221 1001 40 -58 13 1000 62 -565 542 999 61 -571 815 998 54 -899 725 997 77 -578 535 996 21 -578 738 995 31 -636 141 994 98 -257 984 993 53 -170 522 992 81 -207 781 991 78 -471 7 990 98 -726 64 989 49 -89 778 988 99 -190 556 987 67 -797 900 986 32 -596 326 985 0 -156 450 984 94 -461 718 983 37 -741 29 982 8 -773 809 981 96 -942 486 980 73 -286 499 979 74 -221 321 978 63 -656 351 977 89 -573 320 976 39 -876 59 975 20 -731 562 974 44 -688 292 973 69 -220 123 972 72 -322 226 971 96 -986 991 970 83 -178 107 969 65 -970 737 968 6 -30 506 967 56 -261 192 966 8 -496 760 965 69 -270 745 964 14 -168 974 963 4 -896 752 962 46 -235 136 961 89 -883 174 960 33 -369 590 959 80 -231 501 958 20 -313 480 957 93 -432 387 956 76 -15 551 955 76 -770 101 954 22 -221 574 953 10 -615 571 952 27 -962 561 951 66 -584 527 950 35 -89 600 949 51 -20 268 948 13 -93 169 947 91 -835 4 946 88 -450 539 945 41 -526 122 944 24 -3 831 943 54 -9 609 942 60 -34 309 941 65 -926 837 940 37 -331 375 939 49 -98 221 938 6 -164 35 937 92 -465 464 936 25 -416 173 935 38 -291 695 934 92 -221 943 933 52 -299 951 932 99 -472 276 931 97 -461 882 930 10 -154 426 929 59 -185 142 928 23 -571 668 927 93 -291 873 926 69 -477 461 925 4 -751 401 924 12 -991 528 923 6 -675 19 922 92 -393 867 921 82 -455 512 920 1 -284 361 919 30 -474 298 918 96 -794 235 917 61 -412 650 916 28 -59 923 915 81 -873 55 914 72 -508 148 913 75 -152 94 912 31 -354 816 911 28 -151 703 910 93 -63 338 909 17 -63 355 908 81 -584 333 907 67 -727 467 906 38 -867 86 905 35 -907 966 904 18 -53 443 903 36 -277 34 902 35 -113 343 901 79 -364 766 900 20 -983 361 899 8 -22 130 898 99 -865 296 897 47 -380 29 896 85 -119 165 895 85 -523 821 894 96 -409 8 893 85 -690 557 892 77 -576 595 891 16 -405 115 890 74 -230 88 889 38 -834 520 888 96 -266 622 887 15 -864 997 886 48 -344 898 885 26 -812 106 884 59 -451 78 883 11 -962 611 882 71 -479 415 881 11 -27 367 880 17 -567 420 879 17 -898 804 878 39 -624 670 877 56 -99 224 876 40 -791 664 875 51 -28 482 874 53 -466 395 873 36 -195 603 872 48 -48 943 871 48 -946 995 870 45 -616 779 869 45 -133 828 868 66 -446 164 867 27 -559 883 866 52 -182 988 865 30 -86 169 864 76 -791 872 863 56 -660 5 862 27 -948 30 861 14 -215 992 860 10 -950 790 859 33 -664 394 858 48 -281 749 857 68 -894 217 856 88 -818 544 855 37 -296 201 854 9 -866 290 853 29 -975 123 852 13 -37 45 851 71 -202 771 850 73 -395 847 849 26 -645 795 848 28 -532 800 847 38 -672 508 846 38 -343 282 845 7 -910 800 844 52 -167 163 843 42 -78 418 842 89 -273 979 841 93 -924 467 840 83 -52 978 839 80 -995 903 838 75 -291 995 837 11 -226 311 836 85 -482 553 835 32 -636 92 834 43 -744 538 833 74 -439 953 832 8 -511 102 831 80 -489 28 830 34 -74 56 829 87 -907 636 828 5 -684 253 827 70 -758 530 826 6 -460 896 825 74 -554 690 824 84 -584 654 823 89 -851 284 822 30 -73 454 821 92 -972 477 820 2 -419 814 819 41 -383 352 818 16 -723 638 817 22 -633 320 816 92 -205 898 815 29 -35 953 814 90 -369 586 813 96 -829 378 812 73 -976 904 811 77 -662 607 810 10 -462 248 809 55 -714 943 808 3 -318 297 807 65 -421 627 806 8 -945 391 805 42 -366 936 804 17 -208 236 803 66 -473 955 802 54 -297 675 801 85 -358 548 800 31 -305 516 799 20 -645 377 798 74 -669 569 797 39 -236 661 796 89 -455 257 795 47 -699 504 794 57 -280 125 793 15 -280 687 792 73 -126 538 791 17 -32 113 790 93 -138 452 789 5 -808 351 788 65 -907 500 787 97 -404 419 786 43 -753 897 785 78 -378 420 784 75 -437 423 783 41 -149 559 782 0 -425 236 781 15 -660 885 780 9 -101 394 779 89 -851 683 778 33 -80 542 777 90 -522 653 776 50 -477 24 775 65 -996 336 774 37 -864 418 773 94 -322 847 772 28 -350 59 771 72 -491 200 770 76 -710 563 769 55 -141 429 768 24 -889 397 767 77 -628 852 766 55 -688 276 765 4 -917 433 764 48 -571 652 763 13 -787 564 762 54 -859 958 761 97 -636 205 760 85 -133 309 759 78 -32 477 758 56 -545 213 757 25 -576 513 756 26 -843 563 755 93 -780 348 754 77 -88 590 753 34 -605 569 752 78 -752 112 751 92 -895 79 750 22 -832 210 749 50 -264 317 748 10 -699 991 747 48 -949 321 746 96 -215 169 745 73 -758 424 744 6 -21 561 743 69 -457 855 742 48 -33 706 741 85 -868 718 740 85 -893 401 739 6 -326 614 738 56 -669 517 737 56 -152 236 736 75 -744 669 735 73 -862 370 734 45 -706 209 733 73 -149 629 732 56 -987 995 731 42 -316 793 730 16 -787 496 729 97 -97 2 728 56 -280 815 727 65 -566 15 726 51 -299 277 725 40 -161 719 724 88 -580 173 723 15 -633 140 722 55 -202 259 721 16 -296 189 720 67 -494 408 719 52 -186 910 718 68 -799 138 717 81 -737 110 716 71 -558 526 715 26 -546 725 714 13 -33 598 713 58 -880 395 712 94 -69 490 711 43 -780 140 710 90 -498 840 709 80 -771 872 708 30 -28 102 707 38 -584 446 706 6 -800 129 705 17 -126 557 704 1 -202 634 703 51 -905 515 702 15 -350 526 701 81 -300 102 700 28 -967 495 699 28 -770 920 698 72 -655 325 697 74 -316 882 696 44 -572 166 695 78 -922 499 694 67 -119 360 693 92 -989 341 692 29 -423 521 691 55 -607 6 690 4 -575 556 689 33 -594 983 688 19 -442 298 687 11 -716 660 686 33 -667 109 685 74 -138 750 684 65 -18 626 683 80 -819 742 682 13 -515 504 681 56 -449 717 680 81 -572 135 679 3 -684 82 678 98 -637 775 677 15 -551 594 676 72 -358 94 675 4 -124 846 674 52 -883 673 673 11 -237 564 672 19 -787 749 671 30 -581 783 670 6 -52 51 669 87 -306 827 668 88 -180 426 667 4 -500 677 666 8 -247 519 665 19 -173 409 664 23 -108 920 663 24 -814 895 662 64 -965 238 661 45 -731 188 660 20 -224 989 659 52 -401 840 658 74 -748 961 657 12 -158 893 656 68 -110 958 655 25 -488 993 654 7 -25 595 653 6 -656 195 652 29 -49 244 651 84 -199 677 650 23 -148 782 649 50 -879 620 648 82 -67 445 647 65 -935 426 646 59 -964 179 645 4 -398 9 644 62 -400 770 643 46 -951 445 642 36 -566 614 641 60 -894 726 640 84 -162 684 639 5 -174 170 638 26 -18 61 637 81 -247 543 636 13 -169 425 635 97 -238 158 634 56 -325 94 633 99 -830 761 632 44 -888 757 631 38 -41 798 630 67 -514 783 629 73 -108 456 628 98 -518 679 627 15 -117 161 626 77 -267 405 625 7 -63 567 624 93 -333 549 623 91 -3 64 622 49 -959 712 621 94 -15 939 620 84 -326 743 619 52 -776 833 618 40 -518 384 617 59 -756 693 616 40 -837 147 615 84 -18 17 614 20 -484 417 613 72 -351 554 612 33 -772 93 611 4 -196 320 610 94 -910 120 609 68 -449 815 608 55 -690 188 607 25 -546 551 606 76 -129 645 605 91 -599 474 604 81 -863 399 603 53 -460 286 602 13 -773 100 601 57 -199 255 600 57 -304 138 599 28 -627 292 598 46 -637 495 597 75 -906 843 596 14 -170 100 595 41 -75 285 594 52 -112 400 593 73 -185 553 592 40 -845 2 591 68 -116 291 590 57 -845 823 589 89 -796 703 588 67 -652 613 587 99 -742 727 586 73 -815 886 585 73 -884 794 584 9 -846 332 583 96 -551 716 582 92 -711 114 581 33 -467 678 580 72 -120 217 579 27 -89 687 578 4 -886 259 577 14 -841 995 576 90 -92 640 575 92 -462 132 574 93 -615 35 573 3 -602 587 572 29 -436 611 571 83 -460 457 570 24 -529 222 569 34 -428 904 568 3 -263 234 567 20 -355 981 566 4 -507 997 565 74 -97 892 564 63 -447 742 563 84 -976 455 562 1 -153 595 561 16 -234 896 560 97 -318 316 559 93 -670 827 558 10 -252 158 557 16 -984 296 556 90 -104 118 555 84 -150 784 554 41 -287 832 553 65 -859 848 552 47 -699 190 551 82 -579 44 550 91 -489 829 549 91 -668 936 548 64 -862 256 547 41 -178 60 546 26 -333 437 545 88 -952 759 544 95 -984 180 543 86 -657 647 542 42 -146 903 541 16 -214 3 540 11 -892 268 539 9 -680 230 538 82 -196 149 537 80 -622 387 536 68 -678 926 535 84 -579 91 534 38 -532 435 533 96 -744 267 532 32 -900 40 531 51 -735 29 530 93 -37 269 529 32 -80 14 528 21 -762 122 527 48 -460 839 526 57 -835 462 525 94 -656 413 524 9 -167 641 523 4 -226 815 522 78 -11 580 521 84 -759 609 520 16 -254 109 519 69 -892 728 518 95 -283 909 517 31 -376 630 516 30 -48 845 515 62 -772 52 514 17 -825 258 513 48 -235 944 512 94 -970 678 511 21 -500 467 510 25 -380 741 509 50 -819 638 508 36 -279 15 507 60 -785 676 506 90 -792 446 505 32 -793 690 504 27 -313 547 503 94 -265 725 502 59 -211 963 501 26 -726 746 500 47 -102 143 499 11 -622 752 498 56 -339 702 497 54 -229 578 496 49 -756 51 495 99 -142 329 494 99 -821 356 493 48 -762 326 492 4 -216 793 491 5 -603 351 490 48 -390 558 489 62 -50 20 488 47 -123 46 487 28 -527 501 486 10 -722 993 485 47 -973 519 484 61 -30 432 483 32 -532 993 482 5 -442 568 481 54 -792 861 480 61 -537 144 479 21 -974 195 478 34 -544 174 477 92 -508 635 476 59 -474 860 475 80 -86 292 474 74 -438 261 473 94 -424 512 472 49 -706 933 471 8 -717 399 470 65 -948 873 469 25 -20 413 468 56 -539 329 467 42 -774 792 466 3 -568 55 465 3 -30 806 464 38 -748 445 463 64 -579 408 462 1 -533 439 461 71 -526 395 460 98 -459 691 459 76 -84 133 458 92 -537 393 457 48 -736 2 456 76 -249 646 455 20 -360 739 454 53 -36 633 453 28 -969 296 452 16 -43 728 451 4 -703 220 450 0 -558 840 449 6 -740 446 448 37 -390 716 447 54 -355 558 446 80 -907 668 445 48 -106 256 444 88 -337 112 443 32 -568 122 442 6 -507 40 441 92 -379 938 440 34 -393 692 439 14 -730 827 438 81 -157 747 437 34 -890 312 436 3 -411 599 435 44 -144 564 434 80 -989 256 433 76 -82 142 432 76 -101 584 431 6 -246 194 430 12 -864 327 429 98 -80 468 428 66 -434 314 427 57 -713 587 426 26 -35 647 425 47 -307 31 424 26 -114 0 423 15 -557 708 422 90 -390 932 421 98 -867 141 420 85 -859 322 419 38 -154 90 418 78 -726 305 417 64 -939 788 416 72 -615 211 415 67 -31 112 414 72 -291 247 413 19 -775 925 412 55 -790 126 411 16 -819 473 410 52 -232 597 409 0 -784 138 408 70 -517 924 407 42 -576 43 406 78 -99 950 405 32 -864 533 404 58 -322 636 403 74 -798 389 402 51 -653 644 401 98 -875 514 400 97 -458 302 399 58 -214 278 398 44 -880 640 397 26 -92 463 396 94 -417 739 395 47 -897 844 394 23 -246 224 393 54 -745 530 392 52 -129 13 391 14 -212 385 390 77 -24 138 389 41 -637 182 388 24 -176 325 387 33 -723 464 386 78 -895 241 385 67 -619 693 384 52 -694 17 383 65 -517 378 382 50 -627 367 381 61 -247 360 380 91 -956 174 379 18 -856 909 378 38 -860 545 377 46 -222 112 376 45 -547 155 375 82 -675 870 374 27 -639 148 373 92 -11 886 372 17 -6 698 371 88 -186 729 370 38 -264 801 369 29 -363 925 368 9 -432 8 367 99 -957 624 366 63 -285 552 365 67 -721 350 364 87 -261 748 363 3 -188 287 362 62 -968 508 361 0 -928 89 360 82 -875 191 359 92 -916 103 358 90 -384 358 357 93 -71 962 356 47 -202 803 355 67 -601 835 354 56 -461 408 353 45 -778 622 352 7 -419 183 351 21 -897 899 350 3 -88 20 349 5 -745 970 348 95 -395 455 347 53 -159 802 346 31 -967 109 345 86 -426 103 344 60 -786 386 343 14 -438 853 342 68 -284 180 341 35 -879 986 340 52 -50 94 339 80 -514 426 338 34 -653 219 337 34 -693 444 336 23 -5 268 335 19 -717 460 334 54 -532 457 333 64 -673 323 332 34 -193 837 331 15 -892 711 330 40 -667 465 329 82 -207 994 328 53 -775 112 327 86 -175 44 326 95 -808 650 325 68 -2 900 324 28 -133 293 323 18 -485 192 322 85 -126 749 321 48 -246 576 320 30 -471 292 319 22 -881 674 318 46 -68 901 317 43 -394 272 316 59 -749 398 315 36 -607 104 314 80 -100 325 313 86 -443 378 312 64 -172 178 311 35 -284 76 310 88 -617 763 309 77 -773 28 308 59 -629 832 307 81 -873 232 306 67 -294 561 305 64 -778 936 304 14 -947 221 303 50 -199 287 302 65 -102 479 301 27 -312 105 300 88 -735 184 299 66 -195 777 298 84 -599 139 297 14 -671 29 296 75 -624 502 295 57 -714 635 294 51 -934 849 293 83 -807 387 292 74 -374 381 291 9 -921 221 290 78 -406 822 289 57 -638 700 288 53 -109 387 287 59 -527 177 286 92 -867 62 285 4 -785 684 284 91 -461 84 283 78 -5 649 282 12 -160 308 281 43 -399 211 280 45 -122 38 279 51 -312 943 278 76 -210 668 277 52 -114 880 276 58 -377 136 275 65 -600 129 274 8 -434 654 273 32 -341 692 272 45 -96 981 271 84 -173 937 270 76 -95 746 269 27 -274 239 268 80 -787 946 267 10 -743 922 266 9 -6 578 265 73 -475 757 264 77 -961 867 263 16 -711 611 262 9 -43 84 261 24 -190 483 260 92 -507 467 259 7 -292 708 258 82 -23 5 257 48 -343 359 256 4 -821 958 255 73 -889 611 254 53 -256 73 253 51 -526 848 252 25 -600 321 251 66 -16 845 250 85 -759 258 249 68 -703 332 248 21 -645 443 247 26 -400 307 246 67 -347 205 245 52 -538 16 244 93 -225 264 243 63 -526 582 242 72 -476 815 241 92 -587 168 240 58 -925 469 239 25 -889 945 238 5 -136 589 237 5 -101 157 236 24 -189 591 235 5 -752 297 234 80 -681 904 233 31 -766 803 232 69 -646 341 231 5 -699 327 230 88 -523 200 229 66 -356 997 228 3 -431 813 227 75 -566 190 226 3 -293 244 225 91 -393 496 224 43 -100 614 223 7 -461 648 222 91 -13 160 221 11 -126 227 220 94 -202 626 219 17 -184 282 218 16 -623 718 217 92 -946 122 216 86 -747 475 215 27 -882 366 214 89 -965 155 213 29 -487 795 212 63 -933 173 211 44 -601 770 210 88 -343 9 209 92 -563 242 208 1 -596 58 207 56 -646 592 206 67 -109 373 205 19 -210 606 204 86 -360 653 203 91 -622 191 202 47 -402 560 201 55 -761 963 200 33 -766 904 199 25 -183 458 198 78 -466 884 197 96 -219 477 196 94 -767 333 195 53 -952 948 194 89 -462 438 193 85 -630 923 192 73 -597 222 191 21 -58 74 190 64 -446 477 189 99 -573 812 188 58 -406 17 187 71 -143 413 186 24 -384 637 185 45 -510 48 184 81 -515 112 183 48 -700 518 182 83 -148 579 181 3 -596 645 180 53 -664 412 179 61 -795 865 178 87 -604 470 177 16 -775 794 176 26 -589 637 175 75 -935 324 174 87 -594 657 173 99 -939 799 172 81 -933 494 171 55 -233 926 170 55 -547 738 169 93 -394 706 168 86 -675 904 167 19 -157 503 166 82 -313 885 165 18 -667 879 164 65 -857 181 163 34 -305 261 162 65 -567 1 161 0 -187 618 160 70 -32 63 159 68 -801 677 158 15 -400 362 157 71 -618 642 156 51 -6 532 155 84 -697 311 154 64 -919 685 153 80 -260 649 152 55 -382 305 151 73 -555 14 150 38 -385 532 149 15 -315 434 148 23 -719 200 147 40 -109 674 146 78 -221 198 145 61 -625 836 144 30 -36 257 143 77 -344 814 142 65 -290 357 141 87 -481 225 140 82 -98 923 139 16 -233 829 138 7 -525 618 137 59 -476 169 136 60 -361 304 135 88 -578 529 134 59 -442 119 133 58 -457 780 132 69 -131 51 131 5 -301 657 130 80 -93 99 129 38 -210 473 128 86 -449 986 127 70 -865 721 126 4 -774 293 125 11 -410 5 124 78 -338 897 123 13 -729 638 122 98 -394 244 121 32 -557 426 120 82 -625 517 119 20 -487 157 118 88 -265 658 117 76 -427 934 116 58 -288 331 115 9 -107 647 114 36 -258 151 113 7 -394 658 112 60 -818 496 111 33 -908 622 110 83 -360 324 109 93 -498 121 108 13 -724 178 107 22 -603 492 106 83 -684 727 105 13 -495 291 104 18 -492 463 103 84 -162 273 102 86 -873 498 101 57 -297 904 100 90 -203 793 99 54 -943 916 98 86 -685 383 97 77 -764 699 96 12 -436 958 95 91 -827 331 94 18 -189 984 93 0 -775 288 92 32 -593 666 91 28 -111 361 90 57 -877 686 89 9 -532 87 88 26 -684 653 87 25 -740 202 86 92 -627 730 85 32 -347 184 84 60 -695 673 83 63 -621 40 82 41 -304 712 81 18 -675 482 80 48 -598 833 79 23 -434 3 78 34 -450 336 77 84 -471 592 76 94 -546 719 75 11 -510 971 74 28 -633 223 73 65 -328 231 72 7 -229 700 71 31 -649 248 70 62 -830 888 69 7 -666 497 68 16 -743 903 67 98 -873 831 66 97 -747 833 65 92 -747 628 64 3 -992 576 63 87 -530 757 62 30 -452 687 61 9 -359 552 60 57 -391 913 59 81 -593 180 58 16 -72 4 57 92 -997 54 56 87 -204 889 55 12 -51 157 54 99 -819 573 53 75 -69 204 52 46 -134 520 51 7 -639 759 50 9 -732 656 49 96 -176 240 48 79 -950 52 47 52 -164 745 46 7 -732 125 45 79 -584 244 44 15 -368 294 43 23 -684 383 42 74 -760 984 41 93 -103 126 40 49 -416 169 39 90 -187 276 38 55 -307 447 37 22 -619 281 36 78 -881 641 35 43 -950 920 34 14 -910 482 33 21 -398 814 32 68 -858 439 31 92 -956 588 30 65 -893 350 29 68 -829 330 28 22 -165 440 27 88 -639 354 26 68 -720 284 25 73 -437 931 24 93 -667 531 23 3 -375 760 22 51 -850 266 21 53 -238 970 20 90 -20 457 19 6 -890 348 18 6 -86 192 17 66 -69 949 16 52 -352 807 15 91 -400 891 14 28 -771 526 13 76 -493 972 12 29 -296 637 11 52 -512 839 10 61 -108 998 9 21 -156 400 8 12 -242 137 7 80 -141 606 6 1 -916 635 5 71 -364 513 4 95 -553 477 3 62 -335 768 2 27 -798 911 1 19 -840 394 0 78 -@nodes -source 252 -@end diff -r d8475431bbbb -r 8e85e6bbefdf src/test/error_test.cc --- a/src/test/error_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* -*- C++ -*- - * src/test/error_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include - -#include -#include "test_tools.h" -using namespace lemon; -using std::cout; -using std::endl; - -void faulty_fn() { - fault("This is a fault message"); -} - -void exception_fn() { - throw Exception("This is a fn throwing excpt with some args: ") - << 5 << ", " << 18; -} - -void unfinished_fn() { - FIXME("unfinished_fn() is unfinished!"); -} - - -int main() { - try { - faulty_fn(); - check(false, "A faulty function did not fail."); - } - catch(const Exception &e) { - cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl; - } - - try { - exception_fn(); - check(false, "The function did not throw Exception."); - } - catch(const Exception &e) { - cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl; - } - - try { - unfinished_fn(); - check(false, "FIXME macro does not work."); - } - catch(const Exception &e) { - cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl; - } - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/graph_adaptor_test.cc --- a/src/test/graph_adaptor_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* -*- C++ -*- - * src/test/graph_adaptor_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include"test/test_tools.h" -#include"test/graph_test.h" - -/** -\file -This test makes consistency checks of graph adaptors. - -\todo More extensive tests are needed -*/ - -using namespace lemon; -using namespace lemon::concept; - - - -int main() -{ - { - typedef StaticGraph Graph; - checkConcept >(); - - checkConcept >(); - - checkConcept , Graph::EdgeMap > >(); - checkConcept > >(); - checkConcept > >(); - - checkConcept, Graph::EdgeMap > >(); - // checkConcept >(); - checkConcept, Graph::EdgeMap > >(); - - checkConcept > >(); - - /// \bug why does not compile with StaticGraph - checkConcept >(); - checkConcept >(); - checkConcept >(); - } - std::cout << __FILE__ ": All tests passed.\n"; - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/graph_factory_test.cc --- a/src/test/graph_factory_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -/* -*- C++ -*- - * src/test/graph_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include -#include -#include -#include -#include -#include - -#include"test_tools.h" -#include"graph_test.h" - -/** -\file -This test makes consistency checks of list graph structures. - -G.addNode(), G.addEdge(), G.source(), G.target() - -\todo Checks for empty graphs and isolated points. -conversion. -*/ - -using namespace lemon; - -template void bidirPetersen(Graph &G) -{ - typedef typename Graph::Edge Edge; - typedef typename Graph::EdgeIt EdgeIt; - - checkGraphEdgeList(G,15); - - std::vector ee; - - for(EdgeIt e(G);e!=INVALID;++e) ee.push_back(e); - - for(typename std::vector::iterator p=ee.begin();p!=ee.end();p++) - G.addEdge(G.target(*p),G.source(*p)); -} - -template void checkPetersen(Graph &G) -{ - typedef typename Graph::Node Node; - - typedef typename Graph::EdgeIt EdgeIt; - typedef typename Graph::NodeIt NodeIt; - - checkGraphNodeList(G,10); - checkGraphEdgeList(G,30); - - for(NodeIt n(G);n!=INVALID;++n) { - checkGraphInEdgeList(G,n,3); - checkGraphOutEdgeList(G,n,3); - } -} - -//Compile Graph -template void lemon::concept::checkCompileStaticGraph -(concept::StaticGraph &); - -template -void lemon::concept::checkCompileExtendableGraph -(concept::ExtendableGraph &); - -template -void lemon::concept::checkCompileErasableGraph -(concept::ErasableGraph &); - -//Compile SmartGraph -template -void lemon::concept::checkCompileExtendableGraph(SmartGraph &); -template -void lemon::concept::checkCompileGraphFindEdge(SmartGraph &); - -//Compile SymSmartGraph -//template void hugo::checkCompileGraph(SymSmartGraph &); -//template void hugo::checkCompileGraphFindEdge(SymSmartGraph &); - -//Compile ListGraph -template -void lemon::concept::checkCompileExtendableGraph(ListGraph &); -template -void lemon::concept::checkCompileErasableGraph(ListGraph &); -template -void lemon::concept::checkCompileGraphFindEdge(ListGraph &); - - -//Compile SymListGraph -//template void hugo::checkCompileGraph(SymListGraph &); -//template void hugo::checkCompileErasableGraph(SymListGraph &); -//template void hugo::checkCompileGraphFindEdge(SymListGraph &); - -//Compile FullGraph -template void lemon::concept::checkCompileStaticGraph(FullGraph &); -template -void lemon::concept::checkCompileGraphFindEdge(FullGraph &); - - -int main() -{ - { - SmartGraph G; - addPetersen(G); - bidirPetersen(G); - checkPetersen(G); - } - { - ListGraph G; - addPetersen(G); - bidirPetersen(G); - checkPetersen(G); - } - { - // SymSmartGraph G; - // addPetersen(G); - // checkPetersen(G); - } - { - // SymListGraph G; - // addPetersen(G); - // checkPetersen(G); - } - - ///\file - ///\todo map tests. - ///\todo copy constr tests. - - - // Some map tests. - // FIXME: These shouldn't be here. - using namespace concept; - function_requires< ReadMapConcept< ReadMap > >(); - function_requires< WriteMapConcept< WriteMap > >(); - function_requires< ReadWriteMapConcept< ReadWriteMap > >(); - function_requires< ReferenceMapConcept< ReferenceMap > >(); - - - std::cout << __FILE__ ": All tests passed.\n"; - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/graph_test.cc --- a/src/test/graph_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -// -*- c++ -*- - -#include -#include - -#include -#include -#include -#include - -#include "test_tools.h" -#include "graph_test.h" -#include "map_test.h" - - -using namespace lemon; -using namespace lemon::concept; - - -int main() { - { // checking graph components - checkConcept(); - - checkConcept(); - - checkConcept(); - checkConcept(); - - checkConcept(); - checkConcept(); - - checkConcept(); - - checkConcept(); - - checkConcept(); - checkConcept(); - checkConcept(); - } - { // checking skeleton graphs - checkConcept(); - checkConcept(); - checkConcept(); - } - { // checking list graph - checkConcept(); - - checkGraph(); - checkGraphNodeMap(); - checkGraphEdgeMap(); - } - { // checking smart graph - checkConcept(); - - checkGraph(); - checkGraphNodeMap(); - checkGraphEdgeMap(); - } - { // checking full graph - checkConcept(); - } - - std::cout << __FILE__ ": All tests passed.\n"; - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/graph_test.h --- a/src/test/graph_test.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* -*- C++ -*- - * src/test/graph_test.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ -#ifndef LEMON_TEST_GRAPH_TEST_H -#define LEMON_TEST_GRAPH_TEST_H - - -#include "test_tools.h" - -//! \ingroup misc -//! \file -//! \brief Some utility and test cases to test graph classes. -namespace lemon { - - template void checkGraphNodeList(Graph &G, int nn) - { - typename Graph::NodeIt n(G); - for(int i=0;i - void checkGraphEdgeList(Graph &G, int nn) - { - typedef typename Graph::EdgeIt EdgeIt; - - EdgeIt e(G); - for(int i=0;i - void checkGraphOutEdgeList(Graph &G, typename Graph::Node n, int nn) - { - typename Graph::OutEdgeIt e(G,n); - for(int i=0;i void - checkGraphInEdgeList(Graph &G, typename Graph::Node n, int nn) - { - typename Graph::InEdgeIt e(G,n); - for(int i=0;i - void checkGraph() { - const int num = 5; - Graph G; - addPetersen(G, num); - bidirGraph(G); - checkBidirPetersen(G, num); - } - - ///\file - ///\todo Check target(), source() as well; - - -} //namespace lemon - - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/test/graph_utils_test.cc --- a/src/test/graph_utils_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -// -*- c++ -*- - -#include -#include - -#include - -#include -#include -#include - -#include "test_tools.h" -#include "graph_utils_test.h" - - -using namespace lemon; - - -int main() { - ///\file - { // checking list graph - checkGraphCounters(); - } - { // checking smart graph - checkGraphCounters(); - } - { - int num = 5; - FullGraph fg(num); - check(countNodes(fg) == num, "FullGraph: wrong node number."); - check(countEdges(fg) == num*num, "FullGraph: wrong edge number."); - } - - std::cout << __FILE__ ": All tests passed.\n"; - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/graph_utils_test.h --- a/src/test/graph_utils_test.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* -*- C++ -*- - * src/test/graph_utils_test.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ -#ifndef LEMON_TEST_GRAPH_UTILS_TEST_H -#define LEMON_TEST_GRAPH_UTILS_TEST_H - - -#include "test_tools.h" - -//! \ingroup misc -//! \file -//! \brief Test cases for graph utils. -namespace lemon { - - template - void checkGraphCounters() { - const int num = 5; - Graph graph; - addPetersen(graph, num); - bidirGraph(graph); - check(countNodes(graph) == 2*num, "Wrong node number."); - check(countEdges(graph) == 6*num, "Wrong edge number."); - for (typename Graph::NodeIt it(graph); it != INVALID; ++it) { - check(countOutEdges(graph, it) == 3, "Wrong out degree number."); - check(countInEdges(graph, it) == 3, "Wrong in degree number."); - } - } - -} //namespace lemon - - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/test/heap_test.cc --- a/src/test/heap_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -// -*- c++ -*- - -#include -#include -#include -#include - -#include -#include - -#include - -#include - -#include -#include -#include - -#include "test_tools.h" - -#include "heap_test.h" - - -using namespace lemon; -using namespace lemon::concept; - - -int main() { - - typedef int Item; - typedef int Prio; - typedef IntIntMap ItemIntMap; - - typedef ListGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef Graph::EdgeMap LengthMap; - - Graph graph; - LengthMap length(graph); - Node start; - - /// \todo create own test graph - - std::string f_name; - if( getenv("srcdir") ) - f_name = std::string(getenv("srcdir")); - else f_name = "."; - f_name += "/dijkstra_test.lgf"; - - std::ifstream input(f_name.c_str()); - check(input, "Input file '" << f_name << "' not found."); - readGraph(input, graph, length, start); - - { - std::cerr << "Checking Bin Heap" << std::endl; - - typedef BinHeap IntHeap; - checkConcept, IntHeap>(); - heapSortTest(100); - heapIncreaseTest(100); - - typedef FibHeap > NodeHeap; - checkConcept >, NodeHeap>(); - dijkstraHeapTest(graph, length, start); - } - { - std::cerr << "Checking Fib Heap" << std::endl; - - typedef FibHeap IntHeap; - checkConcept, IntHeap>(); - heapSortTest(100); - heapIncreaseTest(100); - - typedef FibHeap > NodeHeap; - checkConcept >, NodeHeap>(); - dijkstraHeapTest(graph, length, start); - } - { - std::cerr << "Checking Radix Heap" << std::endl; - - typedef RadixHeap IntHeap; - checkConcept, IntHeap>(); - heapSortTest(100); - heapIncreaseTest(100); - - typedef RadixHeap > NodeHeap; - checkConcept >, NodeHeap>(); - dijkstraHeapTest(graph, length, start); - } - - std::cout << __FILE__ ": All tests passed.\n"; - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/heap_test.h --- a/src/test/heap_test.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -// -+- c++ -+- - -#include -#include - -#include - -class IntIntMap : public std::vector { -public: - typedef std::vector Parent; - - IntIntMap() : Parent() {} - IntIntMap(int n) : Parent(n) {} - IntIntMap(int n, int v) : Parent(n, v) {} - - void set(int key, int value) { - Parent::operator[](key) = value; - } -}; - - -template -void heapSortTest(int n) { - typedef _Heap Heap; - IntIntMap map(n, -1); - - Heap heap(map); - - std::vector v(n); - - for (int i = 0; i < n; ++i) { - v[i] = rand() % 1000; - heap.push(i, v[i]); - } - std::sort(v.begin(), v.end()); - for (int i = 0; i < n; ++i) { - check(v[i] == heap.prio() ,"Wrong order in heap sort."); - heap.pop(); - } -} - -template -void heapIncreaseTest(int n) { - typedef _Heap Heap; - IntIntMap map(n, -1); - - Heap heap(map); - - std::vector v(n); - - for (int i = 0; i < n; ++i) { - v[i] = rand() % 1000; - heap.push(i, v[i]); - } - for (int i = 0; i < n; ++i) { - v[i] += rand() % 1000; - heap.increase(i, v[i]); - } - std::sort(v.begin(), v.end()); - for (int i = 0; i < n; ++i) { - check(v[i] == heap.prio() ,"Wrong order in heap increase test."); - heap.pop(); - } -} - - - -template -struct DefHeapTraits : public _Traits { - typedef _Heap Heap; -}; - -template -void dijkstraHeapTest(_Graph& graph, _LengthMap& length, - typename _Graph::Node& start) { - - typedef _Heap Heap; - typedef _Graph Graph; - typedef _LengthMap LengthMap; - - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::EdgeIt EdgeIt; - - Dijkstra, Heap> > - dijkstra(graph, length); - - dijkstra.run(start); - - for(EdgeIt e(graph); e!=INVALID; ++e) { - Node u=graph.source(e); - Node v=graph.target(e); - if (dijkstra.reached(u)) { - check( dijkstra.dist(v) - dijkstra.dist(u) <= length[e], - "Error in a shortest path tree edge!"); - } - } - - for(NodeIt v(graph); v!=INVALID; ++v) { - if ( dijkstra.reached(v) && dijkstra.pred(v) != INVALID ) { - Edge e=dijkstra.pred(v); - Node u=graph.source(e); - check( dijkstra.dist(v) - dijkstra .dist(u) == length[e], - "Error in a shortest path tree edge!"); - } - } - -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/kruskal_test.cc --- a/src/test/kruskal_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/* -*- C++ -*- - * src/test/kruskal_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include -#include - -#include "test_tools.h" -#include -#include -#include -#include -#include - - -using namespace std; -using namespace lemon; - -void checkCompileKruskal() -{ - concept::WriteMap w; - - kruskalEdgeMap(concept::StaticGraph(), - concept::ReadMap(), - w); -} - -int main() { - - typedef ListGraph::Node Node; - typedef ListGraph::Edge Edge; - typedef ListGraph::NodeIt NodeIt; - typedef ListGraph::EdgeIt EdgeIt; - - ListGraph G; - - Node s=G.addNode(); - Node v1=G.addNode(); - Node v2=G.addNode(); - Node v3=G.addNode(); - Node v4=G.addNode(); - Node t=G.addNode(); - - Edge e1 = G.addEdge(s, v1); - Edge e2 = G.addEdge(s, v2); - Edge e3 = G.addEdge(v1, v2); - Edge e4 = G.addEdge(v2, v1); - Edge e5 = G.addEdge(v1, v3); - Edge e6 = G.addEdge(v3, v2); - Edge e7 = G.addEdge(v2, v4); - Edge e8 = G.addEdge(v4, v3); - Edge e9 = G.addEdge(v3, t); - Edge e10 = G.addEdge(v4, t); - - typedef ListGraph::EdgeMap ECostMap; - typedef ListGraph::EdgeMap EBoolMap; - - ECostMap edge_cost_map(G, 2); - EBoolMap tree_map(G); - - - //Test with const map. - check(kruskalEdgeMap(G, ConstMap(2), tree_map)==10, - "Total cost should be 10"); - //Test with a edge map (filled with uniform costs). - check(kruskalEdgeMap(G, edge_cost_map, tree_map)==10, - "Total cost should be 10"); - - edge_cost_map.set(e1, -10); - edge_cost_map.set(e2, -9); - edge_cost_map.set(e3, -8); - edge_cost_map.set(e4, -7); - edge_cost_map.set(e5, -6); - edge_cost_map.set(e6, -5); - edge_cost_map.set(e7, -4); - edge_cost_map.set(e8, -3); - edge_cost_map.set(e9, -2); - edge_cost_map.set(e10, -1); - - vector tree_edge_vec; - - //Test with a edge map and inserter. - check(kruskalEdgeMap_IteratorOut(G, edge_cost_map, - back_inserter(tree_edge_vec)) - ==-31, - "Total cost should be -31."); - - tree_edge_vec.clear(); - - //The above test could also be coded like this: - check(kruskal(G, - makeKruskalMapInput(G, edge_cost_map), - makeKruskalSequenceOutput(back_inserter(tree_edge_vec))) - ==-31, - "Total cost should be -31."); - - check(tree_edge_vec.size()==5,"The tree should have 5 edges."); - - check(tree_edge_vec[0]==e1 && - tree_edge_vec[1]==e2 && - tree_edge_vec[2]==e5 && - tree_edge_vec[3]==e7 && - tree_edge_vec[4]==e9, - "Wrong tree."); - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/lp_test.cc --- a/src/test/lp_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_GLPK -#include -#elif HAVE_CPLEX -#include -#endif - -using namespace lemon; - -#ifdef HAVE_GLPK -typedef LpGlpk LpDefault; -#elif HAVE_CPLEX -typedef LpCplex LpDefault; -#endif - -void lpTest(LpSolverBase & lp) -{ - typedef LpSolverBase LP; - - std::vector x(10); - // for(int i=0;i<10;i++) x.push_back(lp.addCol()); - lp.addColSet(x); - - std::vector y(10); - lp.addColSet(y); - - std::map z; - - z.insert(std::make_pair(12,INVALID)); - z.insert(std::make_pair(2,INVALID)); - z.insert(std::make_pair(7,INVALID)); - z.insert(std::make_pair(5,INVALID)); - - lp.addColSet(z); - - - LP::Expr e,f,g; - LP::Col p1,p2,p3,p4,p5; - LP::Constr c; - - e[p1]=2; - e.constComp()=12; - e[p1]+=2; - e.constComp()+=12; - e[p1]-=2; - e.constComp()-=12; - - e=2; - e=2.2; - e=p1; - e=f; - - e+=2; - e+=2.2; - e+=p1; - e+=f; - - e-=2; - e-=2.2; - e-=p1; - e-=f; - - e*=2; - e*=2.2; - e/=2; - e/=2.2; - - e=((p1+p2)+(p1-p2)+(p1+12)+(12+p1)+(p1-12)+(12-p1)+ - (f+12)+(12+f)+(p1+f)+(f+p1)+(f+g)+ - (f-12)+(12-f)+(p1-f)+(f-p1)+(f-g)+ - 2.2*f+f*2.2+f/2.2+ - 2*f+f*2+f/2+ - 2.2*p1+p1*2.2+p1/2.2+ - 2*p1+p1*2+p1/2 - ); - - - c = (e <= f ); - c = (e <= 2.2); - c = (e <= 2 ); - c = (e <= p1 ); - c = (2.2<= f ); - c = (2 <= f ); - c = (p1 <= f ); - c = (p1 <= p2 ); - c = (p1 <= 2.2); - c = (p1 <= 2 ); - c = (2.2<= p2 ); - c = (2 <= p2 ); - - c = (e >= f ); - c = (e >= 2.2); - c = (e >= 2 ); - c = (e >= p1 ); - c = (2.2>= f ); - c = (2 >= f ); - c = (p1 >= f ); - c = (p1 >= p2 ); - c = (p1 >= 2.2); - c = (p1 >= 2 ); - c = (2.2>= p2 ); - c = (2 >= p2 ); - - c = (e == f ); - c = (e == 2.2); - c = (e == 2 ); - c = (e == p1 ); - c = (2.2== f ); - c = (2 == f ); - c = (p1 == f ); - //c = (p1 == p2 ); - c = (p1 == 2.2); - c = (p1 == 2 ); - c = (2.2== p2 ); - c = (2 == p2 ); - - c = (2 <= e <= 3); - c = (2 <= p1<= 3); - - c = (2 >= e >= 3); - c = (2 >= p1>= 3); - - e[x[3]]=2; - e[x[3]]=4; - e[x[3]]=1; - e.constComp()=12; - - lp.addRow(LP::INF,e,23); - lp.addRow(LP::INF,3.0*(x[1]+x[2]/2)-x[3],23); - lp.addRow(LP::INF,3.0*(x[1]+x[2]*2-5*x[3]+12-x[4]/3)+2*x[4]-4,23); - - lp.addRow(x[1]+x[3]<=x[5]-3); - lp.addRow(-7<=x[1]+x[3]-12<=3); - lp.addRow(x[1]<=x[5]); - - - -} - -int main() -{ - LpSkeleton lp_skel; - lpTest(lp_skel); - - LpDefault lp; - - lpTest(lp); - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/map_test.h --- a/src/test/map_test.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/* -*- C++ -*- - * src/test/map_test.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ -#ifndef LEMON_TEST_MAP_TEST_H -#define LEMON_TEST_MAP_TEST_H - - -#include - -#include "test_tools.h" - - -//! \ingroup misc -//! \file -//! \brief Some utilities to test map classes. - -namespace lemon { - - - template - void checkGraphNodeMap() { - Graph graph; - const int num = 16; - - typedef typename Graph::Node Node; - - std::vector nodes; - for (int i = 0; i < num; ++i) { - nodes.push_back(graph.addNode()); - } - typedef typename Graph::template NodeMap IntNodeMap; - IntNodeMap map(graph, 42); - for (int i = 0; i < (int)nodes.size(); ++i) { - check(map[nodes[i]] == 42, "Wrong map constructor."); - } - for (int i = 0; i < num; ++i) { - nodes.push_back(graph.addNode()); - map[nodes.back()] = 23; - } - graph.clear(); - nodes.clear(); - } - - template - void checkGraphEdgeMap() { - Graph graph; - const int num = 16; - - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - - std::vector nodes; - for (int i = 0; i < num; ++i) { - nodes.push_back(graph.addNode()); - } - - std::vector edges; - for (int i = 0; i < num; ++i) { - for (int j = 0; j < i; ++j) { - edges.push_back(graph.addEdge(nodes[i], nodes[j])); - } - } - - typedef typename Graph::template EdgeMap IntEdgeMap; - IntEdgeMap map(graph, 42); - - for (int i = 0; i < (int)edges.size(); ++i) { - check(map[edges[i]] == 42, "Wrong map constructor."); - } - - for (int i = 0; i < num; ++i) { - for (int j = i + 1; j < num; ++j) { - edges.push_back(graph.addEdge(nodes[i], nodes[j])); - map[edges.back()] = 23; - } - } - graph.clear(); - edges.clear(); - } - -} - -#endif diff -r d8475431bbbb -r 8e85e6bbefdf src/test/maps_test.cc --- a/src/test/maps_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -#include -#include -#include - -#include "test_tools.h" - -using namespace lemon; -using namespace lemon::concept; - -struct A {}; -struct B {}; -class F -{ -public: - B operator()(const A &) const {return B();} -}; - -int func(A) {return 3;} - -typedef ReadMap DoubleMap; - -int main() -{ // checking graph components - - checkConcept, ReadMap >(); - checkConcept, WriteMap >(); - checkConcept, ReadWriteMap >(); - checkConcept, ReferenceMap >(); - - checkConcept, AddMap >(); - checkConcept, SubMap >(); - checkConcept, MulMap >(); - checkConcept, DivMap >(); - checkConcept, NegMap >(); - checkConcept, AbsMap >(); - checkConcept, ShiftMap >(); - checkConcept, ScaleMap >(); - - checkConcept, ComposeMap > >(); - - checkConcept, FunctorMap >(); - - int a; - - a=mapFunctor(constMap(2))(A()); - check(a==2,"Something is wrong with mapFunctor"); - - B b; - b=functorMap(F())[A()]; - - a=functorMap(&func)[A()]; - check(a==3,"Something is wrong with functorMap"); - - std::cout << __FILE__ ": All tests passed.\n"; - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/max_matching_test.cc --- a/src/test/max_matching_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ -/* -*- C++ -*- - * src/test/max_matching_test.cc - - * Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include -#include -#include -#include -#include - -#include "test_tools.h" -#include -#include -#include - -using namespace std; -using namespace lemon; - -int main() { - - typedef UndirListGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::UndirEdgeIt UndirEdgeIt; - typedef Graph::IncEdgeIt IncEdgeIt; - typedef Graph::NodeIt NodeIt; - typedef Graph::Node Node; - - Graph g; - g.clear(); - - std::vector nodes; - for (int i=0; i<13; ++i) - nodes.push_back(g.addNode()); - - g.addEdge(nodes[0], nodes[0]); - g.addEdge(nodes[6], nodes[10]); - g.addEdge(nodes[5], nodes[10]); - g.addEdge(nodes[4], nodes[10]); - g.addEdge(nodes[3], nodes[11]); - g.addEdge(nodes[1], nodes[6]); - g.addEdge(nodes[4], nodes[7]); - g.addEdge(nodes[1], nodes[8]); - g.addEdge(nodes[0], nodes[8]); - g.addEdge(nodes[3], nodes[12]); - g.addEdge(nodes[6], nodes[9]); - g.addEdge(nodes[9], nodes[11]); - g.addEdge(nodes[2], nodes[10]); - g.addEdge(nodes[10], nodes[8]); - g.addEdge(nodes[5], nodes[8]); - g.addEdge(nodes[6], nodes[3]); - g.addEdge(nodes[0], nodes[5]); - g.addEdge(nodes[6], nodes[12]); - - MaxMatching max_matching(g); - max_matching.runEdmonds(0); - - int s=0; - Graph::NodeMap mate(g,INVALID); - max_matching.writeNMapNode(mate); - for(NodeIt v(g); v!=INVALID; ++v) { - if ( mate[v]!=INVALID ) ++s; - } - int size=(int)s/2; //size will be used as the size of a maxmatching - - for(NodeIt v(g); v!=INVALID; ++v) { - max_matching.mate(v); - } - - check ( size == max_matching.size(), "mate() returns a different size matching than max_matching.size()" ); - - Graph::NodeMap::pos_enum> pos0(g); - max_matching.writePos(pos0); - - max_matching.resetMatching(); - max_matching.runEdmonds(1); - s=0; - max_matching.writeNMapNode(mate); - for(NodeIt v(g); v!=INVALID; ++v) { - if ( mate[v]!=INVALID ) ++s; - } - check ( (int)s/2 == size, "The size does not equal!" ); - - Graph::NodeMap::pos_enum> pos1(g); - max_matching.writePos(pos1); - - max_matching.run(); - s=0; - max_matching.writeNMapNode(mate); - for(NodeIt v(g); v!=INVALID; ++v) { - if ( mate[v]!=INVALID ) ++s; - } - check ( (int)s/2 == size, "The size does not equal!" ); - - Graph::NodeMap::pos_enum> pos2(g); - max_matching.writePos(pos2); - - max_matching.resetMatching(); - max_matching.run(); - s=0; - max_matching.writeNMapNode(mate); - for(NodeIt v(g); v!=INVALID; ++v) { - if ( mate[v]!=INVALID ) ++s; - } - check ( (int)s/2 == size, "The size does not equal!" ); - - Graph::NodeMap::pos_enum> pos(g); - max_matching.writePos(pos); - - bool ismatching=true; - for(NodeIt v(g); v!=INVALID; ++v) { - if ( mate[v]!=INVALID ) { - Node u=mate[v]; - if (mate[u]!=v) ismatching=false; - } - } - check ( ismatching, "It is not a matching!" ); - - bool coincide=true; - for(NodeIt v(g); v!=INVALID; ++v) { - if ( pos0[v] != pos1[v] || pos1[v]!=pos2[v] || pos2[v]!=pos[v] ) { - coincide=false; - } - } - check ( coincide, "The decompositions do not coincide! " ); - - bool noedge=true; - for(UndirEdgeIt e(g); e!=INVALID; ++e) { - if ( (pos[g.target(e)]==max_matching.C && pos[g.source(e)]==max_matching.D) || - (pos[g.target(e)]==max_matching.D && pos[g.source(e)]==max_matching.C) ) - noedge=false; - } - check ( noedge, "There are edges between D and C!" ); - - bool oddcomp=true; - Graph::NodeMap todo(g,true); - int num_comp=0; - for(NodeIt v(g); v!=INVALID; ++v) { - if ( pos[v]==max_matching.D && todo[v] ) { - int comp_size=1; - ++num_comp; - std::queue Q; - Q.push(v); - todo.set(v,false); - while (!Q.empty()) { - Node w=Q.front(); - Q.pop(); - for(IncEdgeIt e(g,w); e!=INVALID; ++e) { - Node u=g.runningNode(e); - if ( pos[u]==max_matching.D && todo[u] ) { - ++comp_size; - Q.push(u); - todo.set(u,false); - } - } - } - if ( !(comp_size % 2) ) oddcomp=false; - } - } - check ( oddcomp, "A component of g[D] is not odd." ); - - int barrier=0; - for(NodeIt v(g); v!=INVALID; ++v) { - if ( pos[v]==max_matching.A ) ++barrier; - } - int expected_size=(int)( countNodes(g)-num_comp+barrier)/2; - check ( size==expected_size, "The size of the matching is wrong." ); - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/min_cost_flow_test.cc --- a/src/test/min_cost_flow_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* -*- C++ -*- - * src/test/min_cost_flow_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include -#include "test_tools.h" -#include -#include -//#include -//#include - -using namespace lemon; - - -bool passed = true; -/* -void check(bool rc, char *msg="") { - passed = passed && rc; - if(!rc) { - std::cerr << "Test failed! ("<< msg << ")" << std::endl; \ - - - } -} -*/ - - -int main() -{ - typedef ListGraph Graph; - typedef Graph::Node Node; - typedef Graph::Edge Edge; - - Graph graph; - - //Ahuja könyv példája - - Node s=graph.addNode(); - Node v1=graph.addNode(); - Node v2=graph.addNode(); - Node v3=graph.addNode(); - Node v4=graph.addNode(); - Node v5=graph.addNode(); - Node t=graph.addNode(); - - Edge s_v1=graph.addEdge(s, v1); - Edge v1_v2=graph.addEdge(v1, v2); - Edge s_v3=graph.addEdge(s, v3); - Edge v2_v4=graph.addEdge(v2, v4); - Edge v2_v5=graph.addEdge(v2, v5); - Edge v3_v5=graph.addEdge(v3, v5); - Edge v4_t=graph.addEdge(v4, t); - Edge v5_t=graph.addEdge(v5, t); - - - Graph::EdgeMap length(graph); - - length.set(s_v1, 6); - length.set(v1_v2, 4); - length.set(s_v3, 10); - length.set(v2_v4, 5); - length.set(v2_v5, 1); - length.set(v3_v5, 4); - length.set(v4_t, 8); - length.set(v5_t, 8); - - Graph::EdgeMap capacity(graph); - - capacity.set(s_v1, 2); - capacity.set(v1_v2, 2); - capacity.set(s_v3, 1); - capacity.set(v2_v4, 1); - capacity.set(v2_v5, 1); - capacity.set(v3_v5, 1); - capacity.set(v4_t, 1); - capacity.set(v5_t, 2); - - // ConstMap const1map(1); - std::cout << "Mincostflows algorithm test..." << std::endl; - - MinCostFlow< Graph, Graph::EdgeMap, Graph::EdgeMap > - surb_test(graph, length, capacity, s, t); - - int k=1; - - surb_test.augment(); - check( surb_test.flowValue() == 1 && surb_test.totalLength() == 19,"One path, total length should be 19"); - - check( surb_test.run(k) == 1 && surb_test.totalLength() == 19,"One path, total length should be 19"); - - check(surb_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?"); - - k=2; - - check( surb_test.run(k) == 2 && surb_test.totalLength() == 41,"Two paths, total length should be 41"); - - check(surb_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?"); - - surb_test.augment(); - surb_test.augment(); - surb_test.augment(); - k=4; - - check( surb_test.run(k) == 3 && surb_test.totalLength() == 64,"Three paths, total length should be 64"); - - check(surb_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?"); - - - std::cout << (passed ? "All tests passed." : "Some of the tests failed!!!") - << std::endl; - - return passed ? 0 : 1; - -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/path_test.cc --- a/src/test/path_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* -*- C++ -*- - * src/test/path_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include -#include -#include -#include -#include - -using namespace std; -using namespace lemon; -using namespace lemon::concept; - -template void checkCompilePath(Path &P) -{ - typedef typename Path::EdgeIt EdgeIt; - typedef typename Path::NodeIt NodeIt; - typedef typename Path::GraphNode GraphNode; - typedef typename Path::GraphEdge GraphEdge; - //typedef typename Path::Builder Builder; - //??? ha csinalok ilyet es siman Builderrel peldanyositok, akkor warningol. Talan friend miatt? De ki az? - - EdgeIt ei; - NodeIt ni; - GraphNode gn; - GraphEdge ge; - - size_t st; - bool b; - - //Path(const Graph &_G) {} //the constructor has been already called - - st=P.length(); //size_t length() const {return 0;} - b=P.empty(); //bool empty() const {} - P.clear(); //void clear() {} - - gn=P.target(); //GraphNode/*It*/ target() const {return INVALID;} - gn=P.source(); //GraphNode/*It*/ source() const {return INVALID;} - - ei=P.first(ei); //It& first(It &i) const { return i=It(*this); } - - ni=P.target(ei); //NodeIt target(const EdgeIt& e) const {} - ni=P.source(ei); //NodeIt source(const EdgeIt& e) const {} - - - ListGraph lg; - Path p(lg); - - EdgeIt i; //EdgeIt() {} - EdgeIt j(INVALID); //EdgeIt(Invalid) {} - EdgeIt k(p); //EdgeIt(const Path &_p) {} - - i=++j; //EdgeIt& operator++() {} - ++k; - b=(i==j); //bool operator==(const EdgeIt& e) const {return true;} - b=(i!=j); //bool operator!=(const EdgeIt& e) const {return true;} - - - NodeIt l; //NodeIt() {} - NodeIt m(INVALID); //NodeIt(Invalid) {} - NodeIt n(p); //NodeIt(const Path &_p) {} - - l=++m; //NodeIt& operator++() {} - b=(m==n); //bool operator==(const NodeIt& e) const {} - b=(m!=n); //bool operator!=(const NodeIt& e) const {} - - typename Path::Builder builder(p); //Builder(Path &_P) : P(_P) {} - builder.setStartNode(gn); //void setStartNode(const GraphNode &) {} - builder.pushFront(ge); //void pushFront(const GraphEdge& e) {} - builder.pushBack(ge); //void pushBack(const GraphEdge& e) {} - builder.commit(); //void commit() {} - builder.reserveFront(st); //void reserveFront(size_t r) {} - builder.reserveBack(st); //void reserveBack(size_t r) {} - -} - -template void checkCompilePath< concept::Path >(concept::Path &); -template void checkCompilePath< DirPath >(DirPath &); -template void checkCompilePath< UndirPath >(UndirPath &); - -int main() -{ -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/preflow_graph.dim --- a/src/test/preflow_graph.dim Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -p max 10 17 -n 2 s -n 9 t -a 1 2 20 -a 1 3 0 -a 2 2 3 -a 2 3 8 -a 2 4 8 -a 3 6 5 -a 4 3 5 -a 4 6 5 -a 4 7 5 -a 5 4 3 -a 6 8 3 -a 6 7 10 -a 6 9 10 -a 7 9 8 -a 9 10 20 -a 9 2 5 -a 10 6 5 \ No newline at end of file diff -r d8475431bbbb -r 8e85e6bbefdf src/test/preflow_test.cc --- a/src/test/preflow_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,201 +0,0 @@ -/* -*- C++ -*- - * src/test/preflow_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include -#include - -#include "test_tools.h" -#include -#include -#include -#include -#include - -using namespace lemon; - -void check_Preflow() -{ - typedef int VType; - typedef concept::StaticGraph Graph; - - typedef Graph::Node Node; - typedef Graph::Edge Edge; - typedef concept::ReadMap CapMap; - typedef concept::ReadWriteMap FlowMap; - typedef concept::ReadWriteMap CutMap; - - typedef Preflow PType; - - Graph g; - Node n; - CapMap cap; - FlowMap flow; - CutMap cut; - - PType preflow_test(g,n,n,cap,flow); - - preflow_test.run(); - preflow_test.flowValue(); - preflow_test.source(n); - preflow_test.flowMap(flow); - - preflow_test.phase1(PType::NO_FLOW); - preflow_test.minCut(cut); - - preflow_test.phase2(); - preflow_test.target(n); - preflow_test.capacityMap(cap); - preflow_test.minMinCut(cut); - preflow_test.maxMinCut(cut); -} - -int cut_value ( SmartGraph& g, SmartGraph::NodeMap& cut, - SmartGraph::EdgeMap& cap) { - - int c=0; - for(SmartGraph::EdgeIt e(g); e!=INVALID; ++e) { - if (cut[g.source(e)] && !cut[g.target(e)]) c+=cap[e]; - } - return c; -} - -int main() { - - typedef SmartGraph Graph; - - typedef Graph::Node Node; - typedef Graph::NodeIt NodeIt; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::EdgeMap CapMap; - typedef Graph::EdgeMap FlowMap; - typedef Graph::NodeMap CutMap; - - typedef Preflow PType; - - std::string f_name; - if( getenv("srcdir") ) - f_name = std::string(getenv("srcdir")); - else f_name = "."; - f_name += "/preflow_graph.dim"; - - std::ifstream file(f_name.c_str()); - - check(file, "Input file '" << f_name << "' not found."); - - Graph g; - Node s, t; - CapMap cap(g); - readDimacs(file, g, cap, s, t); - - FlowMap flow(g,0); - - - - PType preflow_test(g, s, t, cap, flow); - preflow_test.run(PType::ZERO_FLOW); - - CutMap min_cut(g,false); - preflow_test.minCut(min_cut); - int min_cut_value=cut_value(g,min_cut,cap); - - CutMap min_min_cut(g,false); - preflow_test.minMinCut(min_min_cut); - int min_min_cut_value=cut_value(g,min_min_cut,cap); - - CutMap max_min_cut(g,false); - preflow_test.maxMinCut(max_min_cut); - int max_min_cut_value=cut_value(g,max_min_cut,cap); - - check(preflow_test.flowValue() == min_cut_value && - min_cut_value == min_min_cut_value && - min_min_cut_value == max_min_cut_value, - "The max flow value is not equal to the three min cut values."); - - int flow_value=preflow_test.flowValue(); - - - - for(EdgeIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e]; - preflow_test.capacityMap(cap); - - preflow_test.phase1(PType::PRE_FLOW); - - CutMap min_cut1(g,false); - preflow_test.minCut(min_cut1); - min_cut_value=cut_value(g,min_cut1,cap); - - check(preflow_test.flowValue() == min_cut_value && - min_cut_value == 2*flow_value, - "The max flow value or the min cut value is wrong."); - - preflow_test.phase2(); - - CutMap min_cut2(g,false); - preflow_test.minCut(min_cut2); - min_cut_value=cut_value(g,min_cut2,cap); - - CutMap min_min_cut2(g,false); - preflow_test.minMinCut(min_min_cut2); - min_min_cut_value=cut_value(g,min_min_cut2,cap); - - preflow_test.maxMinCut(max_min_cut); - max_min_cut_value=cut_value(g,max_min_cut,cap); - - check(preflow_test.flowValue() == min_cut_value && - min_cut_value == min_min_cut_value && - min_min_cut_value == max_min_cut_value && - min_cut_value == 2*flow_value, - "The max flow value or the three min cut values were not doubled"); - - - - EdgeIt e(g); - for( int i=1; i==10; ++i ) { - flow.set(e,0); - ++e; - } - - preflow_test.flowMap(flow); - - NodeIt tmp1(g,s); - ++tmp1; - if ( tmp1 != INVALID ) s=tmp1; - - NodeIt tmp2(g,t); - ++tmp2; - if ( tmp2 != INVALID ) t=tmp2; - - preflow_test.source(s); - preflow_test.target(t); - - preflow_test.run(); - - CutMap min_cut3(g,false); - preflow_test.minCut(min_cut3); - min_cut_value=cut_value(g,min_cut3,cap); - - CutMap min_min_cut3(g,false); - preflow_test.minMinCut(min_min_cut3); - min_min_cut_value=cut_value(g,min_min_cut3,cap); - - preflow_test.maxMinCut(max_min_cut); - max_min_cut_value=cut_value(g,max_min_cut,cap); - - check(preflow_test.flowValue() == min_cut_value && - min_cut_value == min_min_cut_value && - min_min_cut_value == max_min_cut_value, - "The max flow value or the three min cut values are incorrect."); -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/suurballe_test.cc --- a/src/test/suurballe_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -/* -*- C++ -*- - * src/test/suurballe_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include -#include -#include -//#include -#include "test_tools.h" - -using namespace lemon; - - -bool passed = true; - - -int main() -{ - typedef ListGraph Graph; - typedef Graph::Node Node; - typedef Graph::Edge Edge; - - Graph graph; - - //Ahuja könyv példája - - Node s=graph.addNode(); - Node v1=graph.addNode(); - Node v2=graph.addNode(); - Node v3=graph.addNode(); - Node v4=graph.addNode(); - Node v5=graph.addNode(); - Node t=graph.addNode(); - - Edge s_v1=graph.addEdge(s, v1); - Edge v1_v2=graph.addEdge(v1, v2); - Edge s_v3=graph.addEdge(s, v3); - Edge v2_v4=graph.addEdge(v2, v4); - Edge v2_v5=graph.addEdge(v2, v5); - Edge v3_v5=graph.addEdge(v3, v5); - Edge v4_t=graph.addEdge(v4, t); - Edge v5_t=graph.addEdge(v5, t); - - - Graph::EdgeMap length(graph); - - length.set(s_v1, 6); - length.set(v1_v2, 4); - length.set(s_v3, 10); - length.set(v2_v4, 5); - length.set(v2_v5, 1); - length.set(v3_v5, 5); - length.set(v4_t, 8); - length.set(v5_t, 8); - - std::cout << "Minlengthpaths algorithm test..." << std::endl; - - - int k=3; - Suurballe< Graph, Graph::EdgeMap > - surb_test(graph, length, s, t); - - check( surb_test.run(k) == 2 && surb_test.totalLength() == 46, - "Two paths, total length should be 46"); - - check( surb_test.checkComplementarySlackness(), - "Complementary slackness conditions are not met."); - - // typedef DirPath DPath; - // DPath P(graph); - - /* - surb_test.getPath(P,0); - check(P.length() == 4, "First path should contain 4 edges."); - std::cout< - -#include - -#include -#include -#include - -#include"test_tools.h" -#include"graph_test.h" -#include"sym_graph_test.h" - -/** -\file -This test makes consistency checks of list graph structures. - -G.addNode(), G.addEdge(), G.source(), G.target() - -\todo Checks for empty graphs and isolated points. -conversion. -*/ - -using namespace lemon; - -template void checkPetersen(Graph &G) -{ - typedef typename Graph::NodeIt NodeIt; - - - checkGraphNodeList(G,10); - checkGraphEdgeList(G,30); - checkGraphSymEdgeList(G,15); - - for(NodeIt n(G);n!=INVALID;++n) { - checkGraphInEdgeList(G,n,3); - checkGraphOutEdgeList(G,n,3); - } -} - -//Compile Graph -template void lemon::checkCompileStaticSymGraph -(concept::StaticSymGraph &); - -template void lemon::checkCompileSymGraph -(concept::ExtendableSymGraph &); - -template void lemon::checkCompileErasableSymGraph -(concept::ErasableSymGraph &); - - -//Compile SymSmartGraph -template void lemon::checkCompileSymGraph(SymSmartGraph &); -template -void lemon::concept::checkCompileGraphFindEdge(SymSmartGraph &); - -//Compile SymListGraph -template void lemon::checkCompileSymGraph(SymListGraph &); -template void lemon::checkCompileErasableSymGraph(SymListGraph &); -template -void lemon::concept::checkCompileGraphFindEdge(SymListGraph &); - -int main() -{ - { - SymSmartGraph G; - addSymPetersen(G); - checkPetersen(G); - } - { - SymListGraph G; - addSymPetersen(G); - checkPetersen(G); - } - - ///\file - ///\todo map tests. - ///\todo copy constr tests. - - std::cout << __FILE__ ": All tests passed.\n"; - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/sym_graph_test.h --- a/src/test/sym_graph_test.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ -/* -*- C++ -*- - * src/test/sym_graph_test.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ -#ifndef LEMON_TEST_SYM_GRAPH_TEST_H -#define LEMON_TEST_SYM_GRAPH_TEST_H - - -#include "graph_test.h" -#include "test_tools.h" - -//! \ingroup misc -//! \file -//! \brief Some utility to test symmetric graph classes. -namespace lemon { - - /// \e - - /// \todo This should go to lemon/concept/symgraph.h - /// - template void checkCompileStaticSymGraph(Graph &G) - { - typedef typename Graph::Node Node; - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::SymEdge SymEdge; - typedef typename Graph::SymEdgeIt SymEdgeIt; - typedef typename Graph::Edge Edge; - typedef typename Graph::EdgeIt EdgeIt; - typedef typename Graph::InEdgeIt InEdgeIt; - typedef typename Graph::OutEdgeIt OutEdgeIt; - - lemon::concept::checkCompileStaticGraph(G); - - { - SymEdge i; SymEdge j(i); SymEdge k(INVALID); - i=j; - bool b; b=true; - b=(i==INVALID); b=(i!=INVALID); - b=(i==j); b=(i!=j); b=(iSymEdgeIt conversion - SymEdgeIt ni(G,n); - } - { - Edge i, j; - j = G.opposite(i); - } - { - Node n; - SymEdge se; - se=INVALID; - n=G.source(se); - n=G.target(se); - } - // id tests - { SymEdge n; int i=G.id(n); i=i; } - //SymEdgeMap tests - { - SymEdge k; - typename Graph::template SymEdgeMap m(G); - typename Graph::template SymEdgeMap const &cm = m; //Const map - //Inicialize with default value - typename Graph::template SymEdgeMap mdef(G,12); - typename Graph::template SymEdgeMap mm(cm); //Copy - typename Graph::template SymEdgeMap dm(cm); //Copy from another type - int v; - v=m[k]; m[k]=v; m.set(k,v); - v=cm[k]; - - m=cm; - dm=cm; //Copy from another type - { - //Check the typedef's - typename Graph::template SymEdgeMap::Value val; - val = 1; - typename Graph::template SymEdgeMap::Key key; - key = typename Graph::SymEdgeIt(G); - } - } - { //bool SymEdgeMap - SymEdge k; - typename Graph::template SymEdgeMap m(G); - typename Graph::template SymEdgeMap const &cm = m; //Const map - //Inicialize with default value - typename Graph::template SymEdgeMap mdef(G,12); - typename Graph::template SymEdgeMap mm(cm); //Copy - typename Graph::template SymEdgeMap dm(cm); //Copy from another type - bool v; - v=m[k]; m[k]=v; m.set(k,v); - v=cm[k]; - - m=cm; - dm=cm; //Copy from another type - m=dm; //Copy to another type - { - //Check the typedef's - typename Graph::template SymEdgeMap::Value val; - val=true; - typename Graph::template SymEdgeMap::Key key; - key= typename Graph::SymEdgeIt(G); - } - } - } - - template void checkCompileSymGraph(Graph &G) - { - checkCompileStaticSymGraph(G); - - typedef typename Graph::Node Node; - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::SymEdge SymEdge; - typedef typename Graph::SymEdgeIt SymEdgeIt; - typedef typename Graph::Edge Edge; - typedef typename Graph::EdgeIt EdgeIt; - typedef typename Graph::InEdgeIt InEdgeIt; - typedef typename Graph::OutEdgeIt OutEdgeIt; - - Node n,m; - n=G.addNode(); - m=G.addNode(); - SymEdge e; - e = G.addEdge(n,m); - - // G.clear(); - } - - template void checkCompileSymGraphEraseSymEdge(Graph &G) - { - typename Graph::SymEdge n; - G.erase(n); - } - - template void checkCompileErasableSymGraph(Graph &G) - { - checkCompileSymGraph(G); - lemon::concept::checkCompileGraphEraseNode(G); - checkCompileSymGraphEraseSymEdge(G); - } - - template void checkGraphSymEdgeList(Graph &G, int nn) - { - typedef typename Graph::SymEdgeIt SymEdgeIt; - - SymEdgeIt e(G); - for(int i=0;i -#include - -#include - -using namespace lemon; - -//! \ingroup misc -//! \file -//! \brief Some utilities to write test programs. - - -///If \c rc is fail, writes an error message end exit. - -///If \c rc is fail, writes an error message end exit. -///The error message contains the file name and the line number of the -///source code in a standard from, which makes it possible to go there -///using good source browsers like e.g. \c emacs. -/// -///For example -///\code check(0==1,"This is obviously false.");\endcode will -///print this (and then exits). -///\verbatim graph_test.cc:123: error: This is obviously false. \endverbatim -/// -///\todo It should be in \c error.h -#define check(rc, msg) \ - if(!(rc)) { \ - std::cerr << __FILE__ ":" << __LINE__ << ": error: " << msg << std::endl; \ - exit(1); \ - } else { } \ - -///Structure returned by \ref addPetersen(). - -///Structure returned by \ref addPetersen(). -/// -template struct PetStruct -{ - ///Vector containing the outer nodes. - std::vector outer; - ///Vector containing the inner nodes. - std::vector inner; - ///Vector containing the edges of the inner circle. - std::vector incir; - ///Vector containing the edges of the outer circle. - std::vector outcir; - ///Vector containing the chord edges. - std::vector chords; -}; - - - -///Adds a Petersen graph to \c G. - -///Adds a Petersen graph to \c G. -///\return The nodes and edges of the generated graph. - -template -PetStruct addPetersen(Graph &G,int num = 5) -{ - PetStruct n; - - for(int i=0;i void bidirGraph(Graph &G) -{ - typedef typename Graph::Edge Edge; - typedef typename Graph::EdgeIt EdgeIt; - - std::vector ee; - - for(EdgeIt e(G);e!=INVALID;++e) ee.push_back(e); - - for(typename std::vector::iterator p=ee.begin();p!=ee.end();p++) - G.addEdge(G.target(*p),G.source(*p)); -} - - -/// \brief Checks the bidirectioned Petersen graph. -/// -/// Checks the bidirectioned Petersen graph. -/// -template void checkBidirPetersen(Graph &G, int num = 5) -{ - typedef typename Graph::Node Node; - - typedef typename Graph::EdgeIt EdgeIt; - typedef typename Graph::NodeIt NodeIt; - - checkGraphNodeList(G, 2 * num); - checkGraphEdgeList(G, 6 * num); - - for(NodeIt n(G);n!=INVALID;++n) { - checkGraphInEdgeList(G, n, 3); - checkGraphOutEdgeList(G, n, 3); - } -} - -///Structure returned by \ref addSymPetersen(). - -///Structure returned by \ref addSymPetersen(). -/// -template struct SymPetStruct -{ - ///Vector containing the outer nodes. - std::vector outer; - ///Vector containing the inner nodes. - std::vector inner; - ///Vector containing the edges of the inner circle. - std::vector incir; - ///Vector containing the edges of the outer circle. - std::vector outcir; - ///Vector containing the chord edges. - std::vector chords; -}; - -///Adds a Petersen graph to the symmetric \c G. - -///Adds a Petersen graph to the symmetric \c G. -///\return The nodes and edges of the generated graph. - -template -SymPetStruct addSymPetersen(Graph &G,int num=5) -{ - SymPetStruct n; - - for(int i=0;i - -///\file \brief Test cases for time_measure.h -/// -///\todo To be extended - - -using namespace lemon; - -int main() -{ - Timer T; - while(T.getRealTime()<1.0) ; - std::cout << T << '\n'; - T.reset(); - while(T.getRealTime()<2.0) ; - std::cout << T << '\n'; - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/undir_graph_test.cc --- a/src/test/undir_graph_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -// -*- C++ -*- - -#include -#include -#include -#include -#include - -#include - -#include "test_tools.h" - - -using namespace lemon; -using namespace lemon::concept; - -void check_concepts() { - typedef UndirGraphExtender UndirListGraphBase; - - typedef IterableUndirGraphExtender< - AlterableUndirGraphExtender > IterableUndirListGraph; - - typedef MappableUndirGraphExtender - MappableUndirListGraph; - - typedef ErasableUndirGraphExtender< - ClearableUndirGraphExtender< - ExtendableUndirGraphExtender > > Graph; - - checkConcept(); - checkConcept(); - checkConcept(); - - checkConcept(); - checkConcept(); - - checkConcept(); - checkConcept(); - - checkConcept(); - checkConcept(); - - checkConcept(); -} - -template -void check_item_counts(Graph &g, int n, int e) { - check(countNodes(g)==n, "Wrong node number."); - check(countEdges(g)==2*e, "Wrong edge number."); -} - -template -void print_items(Graph &g) { - - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::UndirEdgeIt UEdgeIt; - typedef typename Graph::EdgeIt EdgeIt; - - std::cout << "Nodes" << std::endl; - int i=0; - for(NodeIt it(g); it!=INVALID; ++it, ++i) { - std::cout << " " << i << ": " << g.id(it) << std::endl; - } - - std::cout << "UndirEdge" << std::endl; - i=0; - for(UEdgeIt it(g); it!=INVALID; ++it, ++i) { - std::cout << " " << i << ": " << g.id(it) - << " (" << g.id(g.source(it)) << ", " << g.id(g.target(it)) - << ")" << std::endl; - } - - std::cout << "Edge" << std::endl; - i=0; - for(EdgeIt it(g); it!=INVALID; ++it, ++i) { - std::cout << " " << i << ": " << g.id(it) - << " (" << g.id(g.source(it)) << ", " << g.id(g.target(it)) - << ")" << std::endl; - } - -} - -template -void check_graph() { - - typedef typename Graph::Node Node; - typedef typename Graph::UndirEdge UEdge; - typedef typename Graph::Edge Edge; - typedef typename Graph::NodeIt NodeIt; - typedef typename Graph::UndirEdgeIt UEdgeIt; - typedef typename Graph::EdgeIt EdgeIt; - - Graph g; - - check_item_counts(g,0,0); - - Node - n1 = g.addNode(), - n2 = g.addNode(), - n3 = g.addNode(); - - UEdge - e1 = g.addEdge(n1, n2), - e2 = g.addEdge(n2, n3); - - // print_items(g); - - check_item_counts(g,3,2); - - -} - -int main() { - check_concepts(); - - check_graph(); - check_graph(); - - return 0; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/unionfind_test.cc --- a/src/test/unionfind_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,208 +0,0 @@ -/* -*- C++ -*- - * src/test/unionfind_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include - -#include -#include -#include "test_tools.h" - -using namespace lemon; -using namespace std; - -template -class BaseMap : public StdMap {}; - -typedef UnionFindEnum UFE; - -void print(UFE const &ufe) { - UFE::ClassIt cit; - cout << "Print the classes of the structure:" << endl; - int i = 1; - for (ufe.first(cit); ufe.valid(cit); ufe.next(cit)) { - cout << " " << i << " (" << cit << "):" << flush; - UFE::ItemIt iit; - for (ufe.first(iit, cit); ufe.valid(iit); ufe.next(iit)) { - cout << " " << iit << flush; - } - cout << endl; - i++; - } - cout << "done" << endl; -} - - -int main() { - UFE::MapType base; - UFE U(base); - -// print(U); - - cout << "Insert 1..." << endl; - U.insert(1); -// print(U); - - cout << "Insert 2..." << endl; - U.insert(2); -// print(U); - - cout << "Join 1 and 2..." << endl; - check(U.join(1,2),"Test failed."); -// print(U); - - cout << "Insert 3, 4, 5, 6, 7..." << endl; - U.insert(3); - U.insert(4); - U.insert(5); - U.insert(6); - U.insert(7); -// print (U); - - cout << "Join 1 - 4, 2 - 4 and 3 - 5 ..." << endl; - check(U.join(1,4),"Test failed."); - check(!U.join(2,4),"Test failed."); - check(U.join(3,5),"Test failed."); -// print(U); - - cout << "Insert 8 to the component of 5 ..." << endl; - U.insert(8,5); -// print(U); - - cout << "Size of the class of 4: " << U.size(4) << endl; - check(U.size(4) == 3,"Test failed."); - cout << "Size of the class of 5: " << U.size(5) << endl; - check(U.size(5) == 3,"Test failed."); - cout << "Size of the class of 6: " << U.size(6) << endl; - check(U.size(6) == 1,"Test failed."); - cout << "Size of the class of 2: " << U.size(2) << endl; - check(U.size(2) == 3,"Test failed."); - - cout << "Insert 9 ..." << endl; - U.insert(9); -// print(U); - cout << "Insert 10 to the component of 9 ..." << endl; - U.insert(10,9); -// print(U); - - cout << "Join 8 and 10..." << endl; - check(U.join(8,10),"Test failed."); -// print(U); - - cout << "Move 9 to the class of 4 ..." << endl; - check(U.move(9,4),"Test failed."); -// print(U); - - cout << "Move 9 to the class of 2 ..." << endl; - check(!U.move(9,2),"Test failed."); -// print(U); - - cout << "Size of the class of 4: " << U.size(4) << endl; - check(U.size(4) == 4,"Test failed."); - cout << "Size of the class of 9: " << U.size(9) << endl; - check(U.size(9) == 4,"Test failed."); - - cout << "Move 5 to the class of 6 ..." << endl; - check(U.move(5,6),"Test failed."); -// print(U); - - cout << "Size of the class of 5: " << U.size(5) << endl; - check(U.size(5) == 2,"Test failed."); - cout << "Size of the class of 8: " << U.size(8) << endl; - check(U.size(8) == 3,"Test failed."); - - cout << "Move 7 to the class of 10 ..." << endl; - check(U.move(7,10),"Test failed."); -// print(U); - - cout << "Size of the class of 7: " << U.size(7) << endl; - check(U.size(7) == 4,"Test failed."); - - cout <<"Erase 9... " << endl; - U.erase(9); -// print(U); - - cout <<"Erase 1... " << endl; - U.erase(1); -// print(U); - - cout << "Size of the class of 4: " << U.size(4) << endl; - check(U.size(4) == 2,"Test failed."); - cout << "Size of the class of 2: " << U.size(2) << endl; - check(U.size(2) == 2,"Test failed."); - - - cout <<"Erase 1... " << endl; - U.erase(1); -// print(U); - - cout <<"Erase 6... " << endl; - U.erase(6); -// print(U); - - cout << "Split the class of 8... " << endl; - U.split(8); -// print(U); - - - cout << "Size of the class of 4: " << U.size(4) << endl; - check(U.size(4) == 2,"Test failed."); - cout << "Size of the class of 3: " << U.size(3) << endl; - check(U.size(3) == 1,"Test failed."); - cout << "Size of the class of 2: " << U.size(2) << endl; - check(U.size(2) == 2,"Test failed."); - - - cout << "Join 3 - 4 and 2 - 4 ..." << endl; - check(U.join(3,4),"Test failed."); - check(!U.join(2,4),"Test failed."); -// print(U); - - - cout << "Size of the class of 4: " << U.size(4) << endl; - check(U.size(4) == 3,"Test failed."); - cout << "Size of the class of 3: " << U.size(3) << endl; - check(U.size(3) == 3,"Test failed."); - cout << "Size of the class of 2: " << U.size(2) << endl; - check(U.size(2) == 3,"Test failed."); - - cout << "Calling makeRep(4)..." << endl; - U.makeRep(4); -// print(U); - cout << "Calling makeRep(3)..." << endl; - U.makeRep(3); -// print(U); - cout << "Calling makeRep(2)..." << endl; - U.makeRep(2); -// print(U); - - cout << "Size of the class of 4: " << U.size(4) << endl; - check(U.size(4) == 3,"Test failed."); - cout << "Size of the class of 3: " << U.size(3) << endl; - check(U.size(3) == 3,"Test failed."); - cout << "Size of the class of 2: " << U.size(2) << endl; - check(U.size(2) == 3,"Test failed."); - - - cout << "eraseClass 4 ..." << endl; - U.eraseClass(4); -// print(U); - - cout << "eraseClass 7 ..." << endl; - U.eraseClass(7); -// print(U); - - cout << "done." << endl; -} diff -r d8475431bbbb -r 8e85e6bbefdf src/test/xy_test.cc --- a/src/test/xy_test.cc Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* -*- C++ -*- - * src/test/xy_test.cc - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#include -#include -#include "test_tools.h" - -using namespace std; -using namespace lemon; -int main() -{ - - cout << "Testing classes `xy' and `boundingbox'." << endl; - - typedef xy XY; - - XY seged; - XY a(1,2); - XY b(3,4); - - seged = a+b; - check(seged.x==4 && seged.y==6, "Wrong vector addition"); - - seged = a-b; - check(seged.x==-2 && seged.y==-2, "a-b"); - - check(a.normSquare()==5,"Wrong norm calculation"); - check(a*b==11, "a*b"); - - int l=2; - seged = a*l; - check(seged.x==2 && seged.y==4, "a*l"); - - seged = b/l; - check(seged.x==1 && seged.y==2, "b/l"); - - typedef BoundingBox BB; - BB doboz1; - check(doboz1.empty(), "It should be empty."); - - doboz1 += a; - check(!doboz1.empty(), "It should not be empty."); - doboz1 += b; - - check(doboz1.bottomLeft().x==1 && - doboz1.bottomLeft().y==2 && - doboz1.topRight().x==3 && - doboz1.topRight().y==4, - "added points to box"); - - seged.x=2;seged.y=3; - check(doboz1.inside(seged),"It should be inside."); - - seged.x=1;seged.y=3; - check(doboz1.inside(seged),"It should be inside."); - - seged.x=0;seged.y=3; - check(!doboz1.inside(seged),"It should not be inside."); - - BB doboz2(seged); - check(!doboz2.empty(), - "It should not be empty. Constructed from 1 point."); - - doboz2 += doboz1; - check(doboz2.inside(seged), - "It should be inside. Incremented a box with an other."); -} diff -r d8475431bbbb -r 8e85e6bbefdf test/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/Makefile.am Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,69 @@ +AM_CPPFLAGS = -I$(top_srcdir) +LDADD = $(top_builddir)/lemon/libemon.la + +EXTRA_DIST = preflow_graph.dim dijkstra_test.lgf + +noinst_HEADERS = \ + test_tools.h \ + graph_test.h \ + sym_graph_test.h \ + map_test.h \ + graph_utils_test.h \ + heap_test.h + +check_PROGRAMS = \ + bfs_test \ + dfs_test \ + dijkstra_test \ + graph_test \ + graph_adaptor_test \ + graph_utils_test \ + kruskal_test \ + max_matching_test \ + maps_test \ + min_cost_flow_test \ + suurballe_test \ + path_test \ + preflow_test \ + test_tools_fail \ + test_tools_pass \ + time_measure_test \ + unionfind_test \ + undir_graph_test \ + xy_test \ + heap_test + +if HAVE_GLPK +check_PROGRAMS += lp_test +else !HAVE_GLPK +if HAVE_CPLEX +check_PROGRAMS += lp_test +endif HAVE_CPLEX +endif !HAVE_GLPK + +TESTS = $(check_PROGRAMS) +XFAIL_TESTS = test_tools_fail$(EXEEXT) + +bfs_test_SOURCES = bfs_test.cc +dfs_test_SOURCES = dfs_test.cc +dijkstra_test_SOURCES = dijkstra_test.cc +graph_test_SOURCES = graph_test.cc +graph_utils_test_SOURCES = graph_utils_test.cc +graph_adaptor_test_SOURCES = graph_adaptor_test.cc +kruskal_test_SOURCES = kruskal_test.cc +maps_test_SOURCES = maps_test.cc +min_cost_flow_test_SOURCES = min_cost_flow_test.cc +max_matching_test_SOURCES = max_matching_test.cc +suurballe_test_SOURCES = suurballe_test.cc +path_test_SOURCES = path_test.cc +preflow_test_SOURCES = preflow_test.cc +time_measure_test_SOURCES = time_measure_test.cc +test_tools_fail_SOURCES = test_tools_fail.cc +test_tools_pass_SOURCES = test_tools_pass.cc +unionfind_test_SOURCES = unionfind_test.cc +xy_test_SOURCES = xy_test.cc +undir_graph_test_SOURCES = undir_graph_test.cc +heap_test_SOURCES = heap_test.cc + +lp_test_SOURCES = lp_test.cc +lp_test_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) diff -r d8475431bbbb -r 8e85e6bbefdf test/bfs_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bfs_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,135 @@ +/* -*- C++ -*- + * test/bfs_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include "test_tools.h" +#include +#include +#include +#include + +using namespace lemon; + +const int PET_SIZE =5; + + +void check_Bfs_Compile() +{ + typedef concept::StaticGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + + typedef Bfs BType; + + Graph G; + Node n; + Edge e; + int l; + bool b; + BType::DistMap d(G); + BType::PredMap p(G); + // BType::PredNodeMap pn(G); + + BType bfs_test(G); + + bfs_test.run(n); + + l = bfs_test.dist(n); + e = bfs_test.pred(n); + n = bfs_test.predNode(n); + d = bfs_test.distMap(); + p = bfs_test.predMap(); + // pn = bfs_test.predNodeMap(); + b = bfs_test.reached(n); + + DirPath pp(G); + bfs_test.getPath(pp,n); +} + +void check_Bfs_Function_Compile() +{ + typedef int VType; + typedef concept::StaticGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef concept::ReadMap LengthMap; + + bfs(Graph(),Node()).run(); + bfs(Graph()).source(Node()).run(); + bfs(Graph()) + .predMap(concept::WriteMap()) + .distMap(concept::WriteMap()) + .reachedMap(concept::ReadWriteMap()) + .processedMap(concept::WriteMap()) + .run(Node()); + +} + +int main() +{ + + typedef SmartGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef Graph::EdgeMap LengthMap; + + Graph G; + Node s, t; + PetStruct ps = addPetersen(G,PET_SIZE); + + s=ps.outer[2]; + t=ps.inner[0]; + + Bfs bfs_test(G); + bfs_test.run(s); + + check(bfs_test.dist(t)==3,"Bfs found a wrong path. " << bfs_test.dist(t)); + + DirPath p(G); + check(bfs_test.getPath(p,t),"getPath() failed to set the path."); + check(p.length()==3,"getPath() found a wrong path."); + + + for(EdgeIt e(G); e==INVALID; ++e) { + Node u=G.source(e); + Node v=G.target(e); + check( !bfs_test.reached(u) || + (bfs_test.dist(v) > bfs_test.dist(u)+1), + "Wrong output."); + } + + for(NodeIt v(G); v==INVALID; ++v) { + check(bfs_test.reached(v),"Each node should be reached."); + if ( bfs_test.pred(v)!=INVALID ) { + Edge e=bfs_test.pred(v); + Node u=G.source(e); + check(u==bfs_test.predNode(v),"Wrong tree."); + check(bfs_test.dist(v) - bfs_test.dist(u) == 1, + "Wrong distance. Difference: " + << std::abs(bfs_test.dist(v) - bfs_test.dist(u) + - 1)); + } + } +} + diff -r d8475431bbbb -r 8e85e6bbefdf test/dfs_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/dfs_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,124 @@ +/* -*- C++ -*- + * test/dfs_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include "test_tools.h" +#include +#include +#include +#include + +using namespace lemon; + +const int PET_SIZE =5; + + +void check_Dfs_SmartGraph_Compile() +{ + typedef concept::StaticGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + + typedef Dfs DType; + + Graph G; + Node n; + Edge e; + int l; + bool b; + DType::DistMap d(G); + DType::PredMap p(G); + // DType::PredNodeMap pn(G); + + DType dfs_test(G); + + dfs_test.run(n); + + l = dfs_test.dist(n); + e = dfs_test.pred(n); + n = dfs_test.predNode(n); + d = dfs_test.distMap(); + p = dfs_test.predMap(); + // pn = dfs_test.predNodeMap(); + b = dfs_test.reached(n); + + DirPath pp(G); + dfs_test.getPath(pp,n); +} + + +void check_Dfs_Function_Compile() +{ + typedef int VType; + typedef concept::StaticGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef concept::ReadMap LengthMap; + + dfs(Graph(),Node()).run(); + dfs(Graph()).source(Node()).run(); + dfs(Graph()) + .predMap(concept::WriteMap()) + .distMap(concept::WriteMap()) + .reachedMap(concept::ReadWriteMap()) + .processedMap(concept::WriteMap()) + .run(Node()); + +} + +int main() +{ + + typedef SmartGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef Graph::EdgeMap LengthMap; + + Graph G; + Node s, t; + PetStruct ps = addPetersen(G,PET_SIZE); + + s=ps.outer[2]; + t=ps.inner[0]; + + Dfs dfs_test(G); + dfs_test.run(s); + + DirPath p(G); + check(dfs_test.getPath(p,t),"getPath() failed to set the path."); + check(p.length()==dfs_test.dist(t),"getPath() found a wrong path."); + + for(NodeIt v(G); v!=INVALID; ++v) { + check(dfs_test.reached(v),"Each node should be reached."); + if ( dfs_test.pred(v)!=INVALID ) { + Edge e=dfs_test.pred(v); + Node u=G.source(e); + check(u==dfs_test.predNode(v),"Wrong tree."); + check(dfs_test.dist(v) - dfs_test.dist(u) == 1, + "Wrong distance. (" << dfs_test.dist(u) << "->" + < +#include +#include +#include +#include +#include +using namespace lemon; + +const int PET_SIZE =5; + + +void check_Dijkstra_BinHeap_Compile() +{ + typedef int VType; + typedef concept::StaticGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef concept::ReadMap LengthMap; + + typedef Dijkstra DType; + + Graph G; + Node n; + Edge e; + VType l; + bool b; + DType::DistMap d(G); + DType::PredMap p(G); + // DType::PredNodeMap pn(G); + LengthMap cap; + + DType dijkstra_test(G,cap); + + dijkstra_test.run(n); + + l = dijkstra_test.dist(n); + e = dijkstra_test.pred(n); + n = dijkstra_test.predNode(n); + d = dijkstra_test.distMap(); + p = dijkstra_test.predMap(); + // pn = dijkstra_test.predNodeMap(); + b = dijkstra_test.reached(n); + + DirPath pp(G); + dijkstra_test.getPath(pp,n); +} + +void check_Dijkstra_Function_Compile() +{ + typedef int VType; + typedef concept::StaticGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef concept::ReadMap LengthMap; + + dijkstra(Graph(),LengthMap(),Node()).run(); + dijkstra(Graph(),LengthMap()).source(Node()).run(); + dijkstra(Graph(),LengthMap()) + .predMap(concept::WriteMap()) + .distMap(concept::WriteMap()) + .run(Node()); + +} + + +int main() +{ + + typedef SmartGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef Graph::EdgeMap LengthMap; + + Graph G; + Node s, t; + LengthMap cap(G); + PetStruct ps = addPetersen(G,PET_SIZE); + + for(int i=0;i + dijkstra_test(G, cap); + dijkstra_test.run(s); + + check(dijkstra_test.dist(t)==13,"Dijkstra found a wrong path."); + + + DirPath p(G); + check(dijkstra_test.getPath(p,t),"getPath() failed to set the path."); + check(p.length()==4,"getPath() found a wrong path."); + + + for(EdgeIt e(G); e!=INVALID; ++e) { + Node u=G.source(e); + Node v=G.target(e); + check( !dijkstra_test.reached(u) || + (dijkstra_test.dist(v) - dijkstra_test.dist(u) <= cap[e]), + "dist(target)-dist(source)- edge_length= " + << dijkstra_test.dist(v) - dijkstra_test.dist(u) + - cap[e]); + } + + ///\bug This works only for integer lengths + for(NodeIt v(G); v!=INVALID; ++v){ + check(dijkstra_test.reached(v),"Each node should be reached."); + if ( dijkstra_test.pred(v)!=INVALID ) { + Edge e=dijkstra_test.pred(v); + Node u=G.source(e); + check(u==dijkstra_test.predNode(v),"Wrong tree."); + check(dijkstra_test.dist(v) - dijkstra_test.dist(u) == cap[e], + "Wrong distance! Difference: " + << std::abs(dijkstra_test.dist(v) - dijkstra_test.dist(u) + - cap[e])); + } + } + + + { + NullMap myPredMap; + dijkstra(G,cap).predMap(myPredMap).run(s); + } + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/dijkstra_test.lgf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/dijkstra_test.lgf Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,7914 @@ +@nodeset +id +999 +998 +997 +996 +995 +994 +993 +992 +991 +990 +989 +988 +987 +986 +985 +984 +983 +982 +981 +980 +979 +978 +977 +976 +975 +974 +973 +972 +971 +970 +969 +968 +967 +966 +965 +964 +963 +962 +961 +960 +959 +958 +957 +956 +955 +954 +953 +952 +951 +950 +949 +948 +947 +946 +945 +944 +943 +942 +941 +940 +939 +938 +937 +936 +935 +934 +933 +932 +931 +930 +929 +928 +927 +926 +925 +924 +923 +922 +921 +920 +919 +918 +917 +916 +915 +914 +913 +912 +911 +910 +909 +908 +907 +906 +905 +904 +903 +902 +901 +900 +899 +898 +897 +896 +895 +894 +893 +892 +891 +890 +889 +888 +887 +886 +885 +884 +883 +882 +881 +880 +879 +878 +877 +876 +875 +874 +873 +872 +871 +870 +869 +868 +867 +866 +865 +864 +863 +862 +861 +860 +859 +858 +857 +856 +855 +854 +853 +852 +851 +850 +849 +848 +847 +846 +845 +844 +843 +842 +841 +840 +839 +838 +837 +836 +835 +834 +833 +832 +831 +830 +829 +828 +827 +826 +825 +824 +823 +822 +821 +820 +819 +818 +817 +816 +815 +814 +813 +812 +811 +810 +809 +808 +807 +806 +805 +804 +803 +802 +801 +800 +799 +798 +797 +796 +795 +794 +793 +792 +791 +790 +789 +788 +787 +786 +785 +784 +783 +782 +781 +780 +779 +778 +777 +776 +775 +774 +773 +772 +771 +770 +769 +768 +767 +766 +765 +764 +763 +762 +761 +760 +759 +758 +757 +756 +755 +754 +753 +752 +751 +750 +749 +748 +747 +746 +745 +744 +743 +742 +741 +740 +739 +738 +737 +736 +735 +734 +733 +732 +731 +730 +729 +728 +727 +726 +725 +724 +723 +722 +721 +720 +719 +718 +717 +716 +715 +714 +713 +712 +711 +710 +709 +708 +707 +706 +705 +704 +703 +702 +701 +700 +699 +698 +697 +696 +695 +694 +693 +692 +691 +690 +689 +688 +687 +686 +685 +684 +683 +682 +681 +680 +679 +678 +677 +676 +675 +674 +673 +672 +671 +670 +669 +668 +667 +666 +665 +664 +663 +662 +661 +660 +659 +658 +657 +656 +655 +654 +653 +652 +651 +650 +649 +648 +647 +646 +645 +644 +643 +642 +641 +640 +639 +638 +637 +636 +635 +634 +633 +632 +631 +630 +629 +628 +627 +626 +625 +624 +623 +622 +621 +620 +619 +618 +617 +616 +615 +614 +613 +612 +611 +610 +609 +608 +607 +606 +605 +604 +603 +602 +601 +600 +599 +598 +597 +596 +595 +594 +593 +592 +591 +590 +589 +588 +587 +586 +585 +584 +583 +582 +581 +580 +579 +578 +577 +576 +575 +574 +573 +572 +571 +570 +569 +568 +567 +566 +565 +564 +563 +562 +561 +560 +559 +558 +557 +556 +555 +554 +553 +552 +551 +550 +549 +548 +547 +546 +545 +544 +543 +542 +541 +540 +539 +538 +537 +536 +535 +534 +533 +532 +531 +530 +529 +528 +527 +526 +525 +524 +523 +522 +521 +520 +519 +518 +517 +516 +515 +514 +513 +512 +511 +510 +509 +508 +507 +506 +505 +504 +503 +502 +501 +500 +499 +498 +497 +496 +495 +494 +493 +492 +491 +490 +489 +488 +487 +486 +485 +484 +483 +482 +481 +480 +479 +478 +477 +476 +475 +474 +473 +472 +471 +470 +469 +468 +467 +466 +465 +464 +463 +462 +461 +460 +459 +458 +457 +456 +455 +454 +453 +452 +451 +450 +449 +448 +447 +446 +445 +444 +443 +442 +441 +440 +439 +438 +437 +436 +435 +434 +433 +432 +431 +430 +429 +428 +427 +426 +425 +424 +423 +422 +421 +420 +419 +418 +417 +416 +415 +414 +413 +412 +411 +410 +409 +408 +407 +406 +405 +404 +403 +402 +401 +400 +399 +398 +397 +396 +395 +394 +393 +392 +391 +390 +389 +388 +387 +386 +385 +384 +383 +382 +381 +380 +379 +378 +377 +376 +375 +374 +373 +372 +371 +370 +369 +368 +367 +366 +365 +364 +363 +362 +361 +360 +359 +358 +357 +356 +355 +354 +353 +352 +351 +350 +349 +348 +347 +346 +345 +344 +343 +342 +341 +340 +339 +338 +337 +336 +335 +334 +333 +332 +331 +330 +329 +328 +327 +326 +325 +324 +323 +322 +321 +320 +319 +318 +317 +316 +315 +314 +313 +312 +311 +310 +309 +308 +307 +306 +305 +304 +303 +302 +301 +300 +299 +298 +297 +296 +295 +294 +293 +292 +291 +290 +289 +288 +287 +286 +285 +284 +283 +282 +281 +280 +279 +278 +277 +276 +275 +274 +273 +272 +271 +270 +269 +268 +267 +266 +265 +264 +263 +262 +261 +260 +259 +258 +257 +256 +255 +254 +253 +252 +251 +250 +249 +248 +247 +246 +245 +244 +243 +242 +241 +240 +239 +238 +237 +236 +235 +234 +233 +232 +231 +230 +229 +228 +227 +226 +225 +224 +223 +222 +221 +220 +219 +218 +217 +216 +215 +214 +213 +212 +211 +210 +209 +208 +207 +206 +205 +204 +203 +202 +201 +200 +199 +198 +197 +196 +195 +194 +193 +192 +191 +190 +189 +188 +187 +186 +185 +184 +183 +182 +181 +180 +179 +178 +177 +176 +175 +174 +173 +172 +171 +170 +169 +168 +167 +166 +165 +164 +163 +162 +161 +160 +159 +158 +157 +156 +155 +154 +153 +152 +151 +150 +149 +148 +147 +146 +145 +144 +143 +142 +141 +140 +139 +138 +137 +136 +135 +134 +133 +132 +131 +130 +129 +128 +127 +126 +125 +124 +123 +122 +121 +120 +119 +118 +117 +116 +115 +114 +113 +112 +111 +110 +109 +108 +107 +106 +105 +104 +103 +102 +101 +100 +99 +98 +97 +96 +95 +94 +93 +92 +91 +90 +89 +88 +87 +86 +85 +84 +83 +82 +81 +80 +79 +78 +77 +76 +75 +74 +73 +72 +71 +70 +69 +68 +67 +66 +65 +64 +63 +62 +61 +60 +59 +58 +57 +56 +55 +54 +53 +52 +51 +50 +49 +48 +47 +46 +45 +44 +43 +42 +41 +40 +39 +38 +37 +36 +35 +34 +33 +32 +31 +30 +29 +28 +27 +26 +25 +24 +23 +22 +21 +20 +19 +18 +17 +16 +15 +14 +13 +12 +11 +10 +9 +8 +7 +6 +5 +4 +3 +2 +1 +0 +@edgeset + id capacity +75 377 6906 27 +417 515 6905 69 +603 249 6904 80 +246 344 6903 69 +382 827 6902 19 +714 879 6901 76 +13 481 6900 22 +863 754 6899 97 +19 530 6898 64 +122 597 6897 78 +861 579 6896 17 +266 888 6895 65 +905 105 6894 81 +516 501 6893 35 +948 430 6892 86 +398 535 6891 66 +727 258 6890 70 +223 322 6889 15 +933 864 6888 84 +17 604 6887 89 +691 520 6886 26 +782 843 6885 59 +604 457 6884 36 +70 492 6883 38 +895 195 6882 56 +277 968 6881 55 +935 550 6880 67 +457 306 6879 50 +260 946 6878 29 +84 636 6877 91 +677 665 6876 32 +385 234 6875 90 +964 972 6874 17 +296 819 6873 53 +227 18 6872 17 +418 879 6871 61 +243 167 6870 34 +359 212 6869 47 +310 374 6868 19 +970 590 6867 17 +431 416 6866 40 +261 730 6865 29 +152 643 6864 42 +800 358 6863 66 +139 557 6862 6 +711 276 6861 80 +954 863 6860 17 +838 279 6859 88 +784 22 6858 4 +173 767 6857 33 +686 116 6856 53 +87 870 6855 16 +284 753 6854 10 +801 599 6853 35 +281 259 6852 66 +412 635 6851 42 +583 291 6850 75 +257 833 6849 11 +254 710 6848 5 +651 799 6847 61 +245 370 6846 48 +117 60 6845 59 +153 757 6844 80 +339 690 6843 48 +624 232 6842 52 +343 671 6841 86 +457 639 6840 82 +123 62 6839 32 +910 442 6838 0 +429 124 6837 60 +310 888 6836 40 +303 796 6835 12 +66 319 6834 96 +457 963 6833 81 +560 651 6832 71 +32 39 6831 28 +577 502 6830 88 +620 323 6829 33 +318 400 6828 21 +235 196 6827 48 +92 277 6826 11 +477 164 6825 0 +356 149 6824 23 +311 98 6823 60 +612 435 6822 89 +537 394 6821 52 +179 552 6820 45 +923 121 6819 95 +203 731 6818 30 +918 362 6817 8 +112 111 6816 14 +15 770 6815 61 +51 628 6814 12 +663 711 6813 4 +41 368 6812 69 +841 73 6811 7 +431 497 6810 35 +389 655 6809 25 +369 218 6808 71 +250 939 6807 28 +341 528 6806 80 +141 493 6805 9 +916 76 6804 96 +343 345 6803 38 +294 623 6802 62 +575 717 6801 19 +842 102 6800 41 +437 535 6799 4 +279 435 6798 2 +410 478 6797 11 +35 709 6796 90 +417 132 6795 20 +730 576 6794 22 +722 766 6793 57 +906 422 6792 4 +615 788 6791 71 +566 369 6790 73 +100 21 6789 40 +957 901 6788 15 +769 209 6787 86 +576 708 6786 37 +556 975 6785 61 +810 651 6784 68 +343 524 6783 0 +634 330 6782 81 +418 984 6781 29 +348 328 6780 4 +119 246 6779 46 +691 289 6778 14 +501 492 6777 18 +733 758 6776 19 +324 930 6775 1 +126 679 6774 74 +194 192 6773 46 +345 524 6772 70 +656 242 6771 21 +82 582 6770 7 +956 322 6769 22 +797 955 6768 42 +734 994 6767 19 +827 173 6766 76 +251 273 6765 40 +487 279 6764 19 +667 757 6763 93 +282 492 6762 84 +659 145 6761 68 +260 840 6760 57 +366 801 6759 12 +960 236 6758 15 +821 422 6757 6 +900 358 6756 90 +993 211 6755 57 +521 265 6754 76 +265 83 6753 81 +346 159 6752 38 +304 114 6751 62 +39 448 6750 39 +565 965 6749 89 +813 96 6748 40 +64 155 6747 13 +147 330 6746 92 +945 812 6745 90 +182 943 6744 47 +923 434 6743 25 +44 763 6742 91 +666 222 6741 4 +482 505 6740 26 +869 487 6739 47 +941 266 6738 75 +825 217 6737 74 +517 14 6736 91 +868 435 6735 20 +509 214 6734 76 +671 338 6733 25 +540 876 6732 87 +717 776 6731 37 +17 791 6730 18 +221 721 6729 61 +49 2 6728 92 +202 831 6727 11 +579 716 6726 30 +220 437 6725 64 +876 505 6724 35 +462 379 6723 83 +99 500 6722 13 +984 195 6721 82 +70 569 6720 69 +719 685 6719 79 +170 812 6718 17 +115 806 6717 84 +278 660 6716 62 +932 288 6715 35 +125 521 6714 34 +879 707 6713 41 +304 308 6712 36 +626 123 6711 11 +883 903 6710 91 +873 624 6709 35 +5 325 6708 54 +146 223 6707 5 +371 264 6706 83 +767 14 6705 34 +814 929 6704 80 +399 52 6703 24 +184 246 6702 57 +219 201 6701 67 +279 563 6700 74 +298 801 6699 0 +102 494 6698 86 +959 217 6697 85 +249 491 6696 77 +84 538 6695 60 +877 560 6694 95 +805 671 6693 41 +45 896 6692 21 +637 935 6691 96 +761 733 6690 94 +307 142 6689 98 +276 7 6688 19 +725 85 6687 14 +953 169 6686 70 +977 650 6685 16 +889 538 6684 20 +775 200 6683 7 +960 248 6682 75 +202 24 6681 40 +591 959 6680 87 +134 785 6679 45 +922 51 6678 3 +915 433 6677 55 +519 545 6676 77 +112 957 6675 97 +337 134 6674 8 +952 312 6673 11 +224 351 6672 81 +64 532 6671 75 +174 421 6670 61 +733 422 6669 45 +618 479 6668 21 +888 778 6667 0 +588 797 6666 39 +822 886 6665 40 +822 974 6664 77 +960 299 6663 38 +819 55 6662 72 +110 147 6661 15 +998 154 6660 89 +943 244 6659 44 +700 204 6658 11 +981 610 6657 73 +910 989 6656 29 +912 631 6655 76 +675 389 6654 0 +243 657 6653 86 +908 567 6652 14 +993 268 6651 70 +909 450 6650 11 +39 324 6649 5 +594 385 6648 24 +620 430 6647 71 +358 533 6646 7 +242 765 6645 99 +731 138 6644 23 +89 720 6643 43 +299 433 6642 33 +818 596 6641 91 +125 56 6640 8 +939 813 6639 86 +954 523 6638 44 +896 647 6637 97 +768 73 6636 26 +627 760 6635 11 +417 805 6634 51 +287 96 6633 64 +836 420 6632 79 +539 831 6631 48 +243 213 6630 69 +290 423 6629 18 +875 472 6628 98 +574 710 6627 5 +312 146 6626 12 +955 605 6625 14 +708 868 6624 20 +676 850 6623 13 +588 310 6622 45 +617 787 6621 29 +790 507 6620 29 +951 201 6619 95 +762 926 6618 41 +563 930 6617 30 +541 987 6616 26 +736 930 6615 35 +18 78 6614 24 +540 680 6613 3 +522 153 6612 8 +280 0 6611 97 +306 343 6610 82 +274 538 6609 83 +996 114 6608 18 +942 38 6607 19 +56 904 6606 2 +851 111 6605 80 +398 213 6604 71 +526 944 6603 47 +153 116 6602 1 +657 143 6601 24 +805 988 6600 97 +423 650 6599 3 +75 990 6598 27 +133 175 6597 5 +793 218 6596 88 +897 86 6595 20 +268 240 6594 45 +828 459 6593 87 +972 776 6592 37 +155 266 6591 49 +338 943 6590 85 +660 753 6589 38 +814 223 6588 34 +957 169 6587 94 +131 680 6586 34 +845 751 6585 89 +781 580 6584 62 +683 498 6583 44 +509 877 6582 85 +323 644 6581 81 +189 470 6580 81 +529 33 6579 67 +54 406 6578 84 +488 601 6577 85 +928 444 6576 82 +171 267 6575 28 +81 188 6574 6 +621 585 6573 9 +233 37 6572 17 +173 0 6571 18 +437 138 6570 13 +627 832 6569 66 +804 989 6568 47 +157 30 6567 56 +176 539 6566 56 +79 222 6565 75 +602 966 6564 8 +547 923 6563 46 +36 988 6562 38 +861 51 6561 5 +306 473 6560 73 +842 185 6559 81 +959 908 6558 82 +490 5 6557 64 +317 802 6556 98 +255 668 6555 9 +42 628 6554 47 +935 72 6553 5 +936 328 6552 51 +578 323 6551 17 +287 925 6550 55 +277 987 6549 46 +902 176 6548 88 +203 665 6547 46 +134 883 6546 17 +39 621 6545 6 +556 420 6544 21 +743 544 6543 10 +4 335 6542 99 +398 619 6541 35 +937 91 6540 29 +811 580 6539 1 +510 414 6538 37 +782 295 6537 69 +261 111 6536 6 +200 848 6535 9 +875 105 6534 48 +209 107 6533 81 +715 641 6532 73 +528 67 6531 60 +511 280 6530 46 +165 635 6529 12 +119 675 6528 30 +183 630 6527 72 +262 973 6526 52 +743 612 6525 6 +998 669 6524 32 +466 74 6523 66 +574 132 6522 49 +786 145 6521 18 +645 334 6520 1 +959 824 6519 34 +44 573 6518 4 +657 206 6517 93 +361 459 6516 92 +942 736 6515 51 +595 658 6514 74 +941 172 6513 53 +986 305 6512 89 +810 170 6511 78 +510 671 6510 14 +250 299 6509 68 +367 109 6508 91 +746 15 6507 38 +723 401 6506 29 +77 774 6505 41 +485 212 6504 34 +866 640 6503 65 +135 103 6502 95 +499 647 6501 17 +371 454 6500 30 +190 771 6499 25 +93 526 6498 88 +614 92 6497 62 +626 876 6496 2 +562 71 6495 64 +571 693 6494 59 +537 698 6493 61 +455 779 6492 73 +193 875 6491 63 +682 40 6490 12 +245 376 6489 18 +434 262 6488 9 +215 597 6487 47 +804 376 6486 98 +378 54 6485 6 +995 973 6484 99 +919 886 6483 3 +903 95 6482 8 +834 508 6481 26 +664 946 6480 51 +113 84 6479 43 +664 618 6478 81 +221 490 6477 21 +322 924 6476 41 +80 72 6475 42 +86 956 6474 38 +791 952 6473 7 +587 820 6472 1 +562 750 6471 6 +862 74 6470 16 +465 626 6469 55 +128 592 6468 44 +565 806 6467 44 +852 985 6466 89 +116 42 6465 24 +4 307 6464 99 +132 60 6463 29 +69 946 6462 20 +676 899 6461 2 +448 619 6460 70 +33 101 6459 39 +786 6 6458 33 +821 544 6457 56 +942 656 6456 71 +735 246 6455 73 +246 699 6454 11 +114 90 6453 87 +46 179 6452 6 +279 324 6451 39 +518 303 6450 22 +94 58 6449 41 +461 774 6448 24 +887 849 6447 96 +410 976 6446 87 +546 624 6445 20 +609 239 6444 48 +911 810 6443 13 +855 668 6442 6 +20 165 6441 76 +244 812 6440 76 +283 168 6439 42 +924 281 6438 63 +872 86 6437 57 +352 671 6436 47 +384 718 6435 86 +429 355 6434 93 +141 65 6433 69 +502 300 6432 5 +352 5 6431 83 +644 338 6430 77 +886 790 6429 96 +195 59 6428 35 +415 96 6427 5 +952 614 6426 51 +363 925 6425 96 +290 239 6424 95 +765 642 6423 28 +294 221 6422 63 +667 58 6421 15 +547 814 6420 70 +731 601 6419 75 +962 307 6418 69 +481 532 6417 78 +689 551 6416 46 +685 14 6415 58 +597 666 6414 7 +420 649 6413 52 +163 488 6412 47 +243 441 6411 62 +213 950 6410 11 +294 66 6409 81 +775 911 6408 76 +980 317 6407 48 +536 873 6406 79 +347 516 6405 0 +17 548 6404 8 +160 54 6403 17 +46 842 6402 25 +491 508 6401 91 +884 302 6400 3 +154 48 6399 91 +593 287 6398 51 +444 688 6397 79 +356 789 6396 44 +968 915 6395 18 +493 911 6394 33 +212 920 6393 85 +333 337 6392 11 +205 889 6391 55 +254 112 6390 60 +760 398 6389 72 +598 725 6388 56 +899 350 6387 14 +874 254 6386 8 +4 858 6385 38 +990 474 6384 47 +583 742 6383 28 +447 558 6382 87 +777 947 6381 12 +713 878 6380 95 +673 168 6379 49 +375 411 6378 16 +95 61 6377 69 +396 699 6376 2 +384 913 6375 87 +731 193 6374 1 +183 403 6373 40 +611 750 6372 13 +69 177 6371 67 +710 456 6370 6 +756 332 6369 4 +350 461 6368 29 +362 675 6367 27 +785 154 6366 69 +720 856 6365 1 +790 605 6364 65 +652 272 6363 54 +572 464 6362 57 +720 607 6361 54 +124 22 6360 35 +870 742 6359 95 +786 17 6358 40 +520 580 6357 98 +297 686 6356 57 +251 359 6355 6 +333 104 6354 93 +807 975 6353 13 +857 30 6352 8 +584 182 6351 85 +280 405 6350 59 +724 547 6349 25 +437 418 6348 8 +893 410 6347 26 +327 512 6346 22 +254 133 6345 4 +129 793 6344 91 +945 56 6343 52 +847 227 6342 94 +777 256 6341 27 +857 342 6340 30 +129 169 6339 55 +7 817 6338 28 +897 43 6337 54 +379 176 6336 56 +339 128 6335 7 +736 392 6334 12 +828 576 6333 18 +971 676 6332 9 +913 969 6331 7 +172 749 6330 91 +352 267 6329 72 +774 744 6328 12 +867 977 6327 11 +47 493 6326 51 +736 947 6325 3 +815 941 6324 60 +899 85 6323 90 +706 27 6322 85 +220 150 6321 5 +481 191 6320 74 +522 607 6319 82 +767 11 6318 57 +483 592 6317 90 +545 478 6316 81 +5 436 6315 31 +856 695 6314 92 +58 50 6313 91 +876 798 6312 19 +959 317 6311 48 +583 920 6310 73 +595 242 6309 95 +419 671 6308 75 +113 86 6307 28 +42 508 6306 93 +740 390 6305 54 +644 4 6304 14 +251 722 6303 79 +481 706 6302 18 +396 747 6301 91 +677 779 6300 37 +571 203 6299 98 +584 471 6298 17 +578 345 6297 30 +118 397 6296 7 +386 391 6295 30 +281 350 6294 9 +16 617 6293 39 +958 263 6292 77 +968 541 6291 8 +575 387 6290 71 +732 811 6289 10 +125 870 6288 98 +948 235 6287 0 +5 768 6286 45 +40 205 6285 73 +733 703 6284 10 +353 622 6283 26 +722 685 6282 5 +154 365 6281 99 +576 612 6280 39 +940 120 6279 84 +635 979 6278 60 +466 546 6277 17 +563 727 6276 94 +501 627 6275 96 +80 838 6274 30 +937 208 6273 38 +319 67 6272 63 +753 597 6271 56 +492 549 6270 57 +140 235 6269 63 +433 430 6268 30 +818 233 6267 16 +100 977 6266 90 +789 658 6265 6 +630 925 6264 42 +141 749 6263 14 +469 62 6262 61 +47 990 6261 56 +313 941 6260 26 +805 331 6259 35 +196 135 6258 70 +256 266 6257 61 +318 841 6256 71 +732 640 6255 31 +176 277 6254 15 +687 526 6253 48 +72 50 6252 67 +48 305 6251 42 +610 909 6250 73 +196 644 6249 50 +868 92 6248 60 +424 895 6247 93 +201 407 6246 93 +362 152 6245 58 +750 669 6244 55 +475 817 6243 48 +745 249 6242 61 +395 688 6241 2 +264 225 6240 43 +551 898 6239 41 +197 669 6238 32 +487 2 6237 44 +255 351 6236 22 +483 29 6235 83 +851 67 6234 61 +568 874 6233 27 +560 591 6232 73 +463 584 6231 34 +326 25 6230 13 +228 86 6229 71 +667 883 6228 35 +651 220 6227 70 +321 385 6226 23 +961 226 6225 77 +193 336 6224 63 +282 544 6223 28 +7 380 6222 0 +559 219 6221 9 +939 417 6220 13 +202 358 6219 9 +663 645 6218 56 +834 477 6217 1 +158 459 6216 32 +889 140 6215 36 +792 349 6214 76 +164 274 6213 91 +161 911 6212 27 +801 960 6211 44 +59 38 6210 61 +712 536 6209 73 +167 545 6208 53 +18 686 6207 82 +318 969 6206 67 +791 591 6205 26 +74 857 6204 9 +362 635 6203 62 +951 827 6202 0 +921 828 6201 36 +502 882 6200 74 +990 198 6199 34 +858 709 6198 54 +717 153 6197 14 +377 406 6196 69 +734 172 6195 52 +222 469 6194 71 +808 625 6193 71 +998 642 6192 41 +945 618 6191 3 +684 394 6190 41 +489 801 6189 51 +556 396 6188 13 +747 449 6187 14 +233 172 6186 34 +703 810 6185 64 +843 4 6184 51 +982 300 6183 41 +24 381 6182 80 +223 612 6181 5 +593 906 6180 26 +405 380 6179 19 +946 990 6178 93 +276 800 6177 80 +362 697 6176 51 +805 131 6175 53 +704 97 6174 85 +919 604 6173 86 +768 757 6172 95 +705 790 6171 80 +525 66 6170 63 +389 262 6169 18 +190 123 6168 45 +103 295 6167 67 +566 983 6166 91 +33 670 6165 55 +493 998 6164 10 +847 902 6163 78 +966 157 6162 15 +724 170 6161 6 +804 441 6160 17 +138 729 6159 13 +828 788 6158 19 +312 756 6157 8 +312 356 6156 53 +671 455 6155 53 +96 316 6154 53 +744 633 6153 64 +987 87 6152 88 +728 882 6151 24 +712 43 6150 91 +941 936 6149 66 +31 112 6148 30 +399 550 6147 51 +900 3 6146 99 +139 993 6145 64 +682 893 6144 57 +546 765 6143 35 +204 638 6142 75 +839 322 6141 25 +106 253 6140 1 +824 356 6139 77 +562 793 6138 90 +546 516 6137 63 +9 359 6136 49 +100 65 6135 76 +127 223 6134 45 +126 595 6133 13 +316 497 6132 34 +69 242 6131 36 +896 246 6130 73 +562 860 6129 28 +277 277 6128 26 +156 132 6127 1 +293 737 6126 53 +842 305 6125 90 +628 319 6124 97 +97 795 6123 0 +255 976 6122 81 +996 632 6121 24 +385 450 6120 17 +582 20 6119 33 +145 245 6118 28 +395 478 6117 12 +432 626 6116 86 +985 937 6115 45 +524 971 6114 21 +819 190 6113 53 +343 563 6112 84 +182 73 6111 25 +429 839 6110 61 +774 48 6109 80 +767 164 6108 43 +852 257 6107 75 +689 411 6106 96 +966 237 6105 44 +780 683 6104 46 +626 688 6103 70 +490 583 6102 47 +234 647 6101 16 +791 807 6100 75 +883 365 6099 65 +906 687 6098 0 +845 787 6097 91 +174 515 6096 16 +554 986 6095 72 +994 755 6094 18 +104 229 6093 15 +935 315 6092 13 +839 407 6091 25 +442 99 6090 44 +678 646 6089 90 +899 92 6088 97 +272 752 6087 6 +528 439 6086 67 +231 537 6085 62 +525 31 6084 55 +914 18 6083 88 +908 880 6082 16 +307 812 6081 9 +452 536 6080 39 +553 929 6079 76 +340 916 6078 77 +312 389 6077 62 +902 51 6076 74 +506 60 6075 29 +13 669 6074 70 +137 720 6073 61 +67 72 6072 0 +276 698 6071 60 +606 633 6070 85 +13 985 6069 89 +526 151 6068 21 +337 882 6067 2 +991 447 6066 41 +390 590 6065 39 +948 95 6064 49 +648 604 6063 87 +374 405 6062 7 +64 744 6061 79 +648 956 6060 66 +833 685 6059 59 +269 185 6058 48 +434 617 6057 18 +857 13 6056 34 +494 903 6055 60 +490 617 6054 44 +198 805 6053 30 +661 278 6052 27 +787 121 6051 30 +271 76 6050 41 +500 105 6049 81 +567 298 6048 56 +604 842 6047 83 +110 746 6046 57 +285 157 6045 36 +812 141 6044 0 +526 26 6043 29 +156 965 6042 53 +44 893 6041 87 +971 600 6040 51 +807 251 6039 77 +456 729 6038 93 +95 257 6037 96 +588 213 6036 49 +15 359 6035 82 +115 712 6034 47 +61 753 6033 28 +71 664 6032 36 +292 356 6031 11 +349 745 6030 7 +521 837 6029 16 +472 970 6028 35 +43 469 6027 36 +854 667 6026 50 +646 352 6025 57 +958 186 6024 90 +89 915 6023 5 +307 257 6022 98 +611 38 6021 77 +907 910 6020 94 +867 811 6019 82 +500 991 6018 4 +802 854 6017 42 +314 933 6016 18 +166 672 6015 20 +271 845 6014 68 +657 65 6013 86 +219 209 6012 78 +127 836 6011 69 +99 114 6010 70 +820 778 6009 3 +136 621 6008 36 +920 238 6007 69 +260 981 6006 48 +827 519 6005 14 +779 819 6004 89 +855 87 6003 61 +373 85 6002 43 +721 991 6001 9 +336 664 6000 2 +157 671 5999 27 +382 669 5998 68 +256 210 5997 21 +462 338 5996 66 +699 253 5995 43 +731 281 5994 4 +1 174 5993 92 +94 346 5992 48 +326 63 5991 65 +993 749 5990 38 +2 595 5989 17 +459 467 5988 77 +871 555 5987 12 +85 226 5986 79 +971 385 5985 76 +106 123 5984 96 +828 441 5983 73 +283 831 5982 90 +313 265 5981 76 +153 206 5980 33 +128 403 5979 99 +911 649 5978 54 +329 331 5977 58 +840 31 5976 78 +262 794 5975 11 +682 237 5974 86 +609 823 5973 27 +565 139 5972 54 +58 434 5971 96 +803 342 5970 15 +754 447 5969 2 +317 955 5968 21 +300 801 5967 58 +236 672 5966 48 +557 248 5965 57 +414 586 5964 57 +684 733 5963 7 +704 575 5962 4 +91 809 5961 50 +894 133 5960 25 +492 809 5959 4 +153 634 5958 43 +129 93 5957 1 +424 909 5956 6 +661 998 5955 67 +853 506 5954 14 +157 29 5953 73 +765 536 5952 97 +676 251 5951 61 +324 207 5950 19 +175 611 5949 40 +540 419 5948 33 +184 953 5947 2 +911 384 5946 70 +492 536 5945 76 +477 412 5944 80 +492 750 5943 69 +285 367 5942 39 +43 415 5941 8 +595 795 5940 35 +192 62 5939 14 +465 315 5938 63 +569 319 5937 35 +847 941 5936 27 +123 955 5935 41 +662 111 5934 1 +383 305 5933 98 +951 301 5932 20 +619 737 5931 24 +733 202 5930 44 +746 513 5929 40 +995 279 5928 72 +378 82 5927 89 +986 854 5926 72 +844 403 5925 72 +806 30 5924 46 +3 776 5923 27 +563 965 5922 43 +534 793 5921 33 +689 44 5920 88 +234 677 5919 98 +196 829 5918 75 +228 175 5917 61 +450 997 5916 39 +373 262 5915 14 +253 182 5914 3 +810 847 5913 80 +172 99 5912 43 +748 445 5911 2 +367 899 5910 84 +848 236 5909 45 +654 132 5908 3 +177 225 5907 96 +735 250 5906 77 +80 103 5905 7 +334 235 5904 11 +748 363 5903 44 +653 410 5902 63 +546 183 5901 42 +662 390 5900 38 +103 417 5899 51 +907 70 5898 19 +975 189 5897 47 +146 701 5896 44 +868 957 5895 65 +871 676 5894 74 +952 804 5893 58 +227 214 5892 9 +792 41 5891 10 +972 862 5890 88 +347 325 5889 55 +880 716 5888 19 +487 34 5887 93 +743 786 5886 82 +280 909 5885 27 +872 159 5884 99 +590 492 5883 91 +172 987 5882 72 +179 223 5881 43 +537 324 5880 81 +608 363 5879 62 +681 264 5878 46 +248 101 5877 39 +877 552 5876 74 +750 280 5875 46 +667 77 5874 40 +505 193 5873 28 +763 290 5872 41 +899 614 5871 99 +961 194 5870 64 +98 158 5869 92 +162 73 5868 92 +549 648 5867 43 +271 280 5866 37 +203 54 5865 12 +883 126 5864 8 +902 864 5863 16 +676 424 5862 74 +420 351 5861 86 +35 712 5860 93 +85 2 5859 86 +424 493 5858 93 +368 62 5857 61 +226 244 5856 27 +928 42 5855 6 +261 921 5854 31 +440 420 5853 98 +72 877 5852 22 +639 925 5851 25 +710 75 5850 38 +508 927 5849 95 +431 322 5848 66 +817 334 5847 5 +202 210 5846 14 +121 748 5845 29 +501 338 5844 66 +542 754 5843 82 +952 970 5842 36 +849 871 5841 43 +148 434 5840 92 +604 289 5839 20 +988 603 5838 7 +123 914 5837 61 +462 844 5836 61 +409 631 5835 8 +584 845 5834 61 +783 453 5833 95 +99 935 5832 58 +436 504 5831 10 +144 726 5830 70 +686 124 5829 54 +689 464 5828 61 +70 998 5827 86 +212 534 5826 66 +786 461 5825 5 +392 660 5824 82 +517 369 5823 80 +431 487 5822 68 +777 401 5821 66 +602 157 5820 29 +659 927 5819 45 +465 751 5818 99 +464 203 5817 61 +72 608 5816 85 +800 227 5815 42 +291 23 5814 39 +881 117 5813 87 +85 21 5812 8 +243 370 5811 65 +230 833 5810 17 +175 461 5809 94 +548 378 5808 19 +594 760 5807 0 +380 432 5806 39 +204 31 5805 27 +905 519 5804 50 +96 787 5803 40 +650 432 5802 79 +536 479 5801 84 +372 231 5800 1 +82 748 5799 5 +618 192 5798 62 +328 609 5797 95 +400 120 5796 21 +512 762 5795 17 +731 99 5794 29 +354 613 5793 80 +953 954 5792 44 +247 829 5791 11 +482 958 5790 16 +555 427 5789 28 +583 673 5788 46 +489 740 5787 29 +357 37 5786 92 +662 877 5785 88 +486 489 5784 78 +659 364 5783 37 +124 331 5782 40 +871 949 5781 70 +530 874 5780 76 +754 826 5779 92 +933 173 5778 97 +702 362 5777 9 +160 40 5776 13 +387 107 5775 69 +124 403 5774 17 +33 975 5773 82 +381 695 5772 53 +74 940 5771 25 +48 838 5770 34 +652 953 5769 77 +810 879 5768 82 +322 961 5767 23 +932 436 5766 54 +704 519 5765 77 +427 348 5764 26 +279 293 5763 9 +755 280 5762 65 +101 913 5761 30 +884 564 5760 2 +74 955 5759 39 +917 590 5758 84 +525 688 5757 48 +916 768 5756 38 +170 510 5755 22 +55 171 5754 27 +12 439 5753 14 +366 345 5752 52 +349 280 5751 65 +609 630 5750 21 +364 553 5749 81 +901 354 5748 15 +919 98 5747 39 +258 161 5746 60 +339 951 5745 74 +731 129 5744 11 +94 623 5743 4 +64 870 5742 64 +649 436 5741 1 +77 406 5740 73 +198 653 5739 24 +256 764 5738 46 +936 784 5737 98 +210 862 5736 66 +822 631 5735 91 +505 72 5734 60 +753 396 5733 63 +433 627 5732 2 +29 278 5731 41 +753 495 5730 57 +889 781 5729 87 +980 481 5728 94 +921 320 5727 31 +231 741 5726 72 +558 312 5725 38 +675 970 5724 31 +769 607 5723 75 +349 614 5722 31 +782 842 5721 40 +713 693 5720 27 +300 936 5719 86 +160 623 5718 90 +578 592 5717 5 +429 338 5716 69 +341 70 5715 67 +363 565 5714 88 +992 432 5713 90 +771 914 5712 41 +149 128 5711 56 +757 411 5710 6 +313 955 5709 41 +30 850 5708 13 +253 367 5707 58 +268 18 5706 14 +505 788 5705 8 +132 976 5704 97 +517 487 5703 37 +786 852 5702 22 +716 498 5701 62 +456 655 5700 39 +104 274 5699 44 +483 557 5698 28 +348 433 5697 77 +229 60 5696 98 +811 109 5695 76 +489 608 5694 37 +635 149 5693 61 +354 598 5692 73 +842 229 5691 6 +380 948 5690 26 +717 161 5689 35 +123 505 5688 62 +372 791 5687 13 +950 222 5686 11 +501 389 5685 41 +459 758 5684 32 +550 883 5683 85 +368 661 5682 28 +281 809 5681 51 +787 908 5680 46 +655 730 5679 66 +713 486 5678 59 +569 15 5677 75 +833 701 5676 42 +630 95 5675 44 +875 467 5674 4 +221 573 5673 90 +851 769 5672 18 +901 49 5671 8 +177 798 5670 49 +244 69 5669 13 +471 842 5668 94 +314 329 5667 14 +606 972 5666 73 +627 406 5665 20 +894 133 5664 75 +803 727 5663 65 +720 93 5662 37 +250 593 5661 94 +729 361 5660 72 +227 190 5659 93 +512 797 5658 77 +357 409 5657 15 +565 532 5656 70 +272 448 5655 97 +405 101 5654 73 +634 283 5653 9 +499 420 5652 8 +231 225 5651 46 +171 791 5650 52 +392 160 5649 50 +387 615 5648 71 +876 448 5647 15 +84 729 5646 79 +346 244 5645 29 +817 642 5644 86 +862 7 5643 77 +195 613 5642 13 +433 947 5641 26 +631 19 5640 5 +544 787 5639 77 +166 558 5638 0 +719 364 5637 51 +484 498 5636 79 +602 425 5635 73 +634 95 5634 52 +394 637 5633 95 +665 866 5632 66 +928 208 5631 76 +232 280 5630 80 +228 773 5629 8 +194 494 5628 37 +866 718 5627 44 +72 55 5626 23 +330 208 5625 88 +458 573 5624 96 +770 287 5623 23 +658 905 5622 72 +927 958 5621 73 +506 716 5620 69 +279 709 5619 0 +776 929 5618 3 +662 213 5617 32 +846 351 5616 79 +634 914 5615 74 +285 727 5614 87 +382 510 5613 68 +946 992 5612 11 +242 41 5611 73 +6 691 5610 42 +779 969 5609 22 +715 706 5608 50 +861 534 5607 11 +437 52 5606 81 +186 869 5605 21 +217 183 5604 34 +518 576 5603 90 +950 380 5602 43 +349 311 5601 70 +722 192 5600 23 +263 724 5599 22 +172 389 5598 6 +481 297 5597 85 +182 604 5596 42 +686 863 5595 25 +607 445 5594 96 +196 468 5593 69 +69 731 5592 56 +118 467 5591 60 +468 9 5590 62 +334 163 5589 45 +92 209 5588 9 +693 429 5587 69 +740 174 5586 29 +417 280 5585 49 +977 270 5584 7 +736 131 5583 41 +263 967 5582 12 +458 972 5581 95 +845 169 5580 65 +953 367 5579 13 +780 401 5578 24 +254 390 5577 39 +893 803 5576 95 +10 417 5575 32 +139 667 5574 44 +163 284 5573 24 +994 176 5572 47 +803 300 5571 80 +802 516 5570 61 +966 891 5569 89 +10 842 5568 17 +586 446 5567 52 +386 629 5566 36 +749 882 5565 88 +383 200 5564 87 +107 767 5563 97 +875 668 5562 16 +784 191 5561 19 +624 720 5560 0 +48 720 5559 83 +395 646 5558 95 +817 165 5557 42 +747 477 5556 20 +682 12 5555 63 +432 895 5554 36 +99 806 5553 27 +476 977 5552 23 +471 190 5551 9 +0 165 5550 15 +73 880 5549 57 +481 531 5548 65 +687 223 5547 57 +465 563 5546 7 +116 271 5545 6 +89 89 5544 24 +828 44 5543 33 +787 140 5542 62 +24 932 5541 0 +284 583 5540 47 +349 922 5539 92 +307 75 5538 59 +660 507 5537 79 +291 5 5536 22 +181 815 5535 34 +45 917 5534 2 +903 708 5533 26 +208 619 5532 4 +348 533 5531 76 +661 544 5530 74 +847 334 5529 93 +567 798 5528 4 +502 571 5527 64 +189 872 5526 36 +897 323 5525 11 +208 765 5524 13 +89 220 5523 14 +86 277 5522 69 +988 22 5521 85 +209 805 5520 68 +536 892 5519 81 +226 395 5518 28 +699 277 5517 6 +549 258 5516 31 +557 974 5515 29 +544 993 5514 68 +942 446 5513 11 +254 835 5512 0 +217 173 5511 9 +912 873 5510 77 +497 533 5509 67 +117 216 5508 31 +19 751 5507 52 +283 21 5506 14 +981 603 5505 99 +546 569 5504 1 +611 116 5503 60 +662 905 5502 68 +300 319 5501 3 +339 104 5500 30 +317 363 5499 41 +465 783 5498 37 +729 377 5497 9 +417 157 5496 73 +33 978 5495 30 +452 411 5494 43 +211 913 5493 93 +585 650 5492 94 +214 732 5491 36 +741 889 5490 96 +580 35 5489 2 +405 281 5488 85 +219 362 5487 73 +179 434 5486 31 +566 867 5485 38 +497 499 5484 58 +263 986 5483 24 +918 586 5482 62 +842 402 5481 37 +854 938 5480 47 +754 170 5479 16 +919 116 5478 17 +928 423 5477 18 +566 928 5476 4 +367 803 5475 61 +512 338 5474 6 +400 616 5473 23 +184 254 5472 34 +464 898 5471 7 +767 311 5470 98 +53 986 5469 9 +693 988 5468 83 +494 145 5467 99 +125 427 5466 36 +464 543 5465 19 +722 834 5464 85 +362 889 5463 11 +355 268 5462 21 +586 88 5461 71 +324 887 5460 69 +998 264 5459 71 +843 844 5458 35 +717 629 5457 19 +884 162 5456 36 +708 343 5455 66 +945 744 5454 74 +621 894 5453 35 +179 496 5452 0 +200 23 5451 76 +623 982 5450 26 +419 354 5449 32 +215 161 5448 15 +466 828 5447 12 +819 708 5446 83 +598 919 5445 17 +849 381 5444 76 +397 353 5443 32 +473 237 5442 44 +41 506 5441 97 +628 936 5440 57 +192 171 5439 20 +332 29 5438 20 +119 291 5437 74 +789 658 5436 64 +537 411 5435 22 +28 439 5434 74 +115 882 5433 45 +731 462 5432 92 +569 401 5431 43 +765 374 5430 41 +141 998 5429 43 +737 456 5428 86 +633 100 5427 21 +246 427 5426 33 +971 471 5425 25 +557 296 5424 50 +419 527 5423 91 +61 492 5422 38 +27 19 5421 16 +375 977 5420 80 +542 574 5419 62 +355 648 5418 40 +673 882 5417 10 +956 77 5416 38 +174 743 5415 27 +769 595 5414 41 +35 528 5413 13 +472 222 5412 35 +41 357 5411 3 +402 181 5410 65 +926 219 5409 83 +765 299 5408 18 +804 717 5407 68 +333 112 5406 71 +148 860 5405 78 +66 275 5404 40 +306 780 5403 73 +865 323 5402 56 +176 381 5401 43 +961 819 5400 63 +919 646 5399 47 +582 504 5398 16 +604 965 5397 96 +251 934 5396 47 +585 376 5395 18 +494 671 5394 8 +456 170 5393 76 +941 131 5392 44 +562 791 5391 68 +172 163 5390 21 +142 315 5389 4 +538 199 5388 33 +30 490 5387 97 +558 285 5386 35 +704 103 5385 66 +501 320 5384 9 +38 320 5383 3 +339 751 5382 51 +628 474 5381 37 +848 172 5380 38 +115 704 5379 3 +709 360 5378 60 +204 624 5377 50 +181 686 5376 47 +783 575 5375 85 +0 52 5374 20 +569 523 5373 46 +276 135 5372 69 +302 989 5371 71 +468 359 5370 78 +343 427 5369 73 +736 96 5368 40 +937 35 5367 50 +110 619 5366 2 +523 649 5365 39 +529 741 5364 78 +387 762 5363 43 +146 988 5362 29 +630 930 5361 97 +932 47 5360 83 +330 326 5359 12 +61 901 5358 60 +415 481 5357 79 +969 624 5356 82 +907 614 5355 58 +978 352 5354 99 +774 138 5353 14 +57 318 5352 24 +882 140 5351 51 +721 708 5350 69 +425 516 5349 60 +419 809 5348 26 +857 971 5347 64 +10 239 5346 44 +262 592 5345 6 +214 853 5344 92 +819 899 5343 20 +178 725 5342 71 +431 818 5341 17 +192 96 5340 16 +707 331 5339 29 +838 624 5338 0 +731 199 5337 56 +647 384 5336 84 +739 132 5335 74 +953 725 5334 4 +174 486 5333 39 +907 542 5332 64 +721 13 5331 74 +765 865 5330 23 +707 289 5329 48 +425 443 5328 86 +814 715 5327 10 +252 99 5326 8 +406 699 5325 90 +239 653 5324 78 +943 752 5323 77 +529 894 5322 26 +147 507 5321 18 +575 754 5320 95 +846 615 5319 5 +728 762 5318 28 +615 22 5317 61 +399 176 5316 56 +45 121 5315 84 +900 8 5314 16 +857 511 5313 29 +387 81 5312 41 +752 230 5311 38 +138 897 5310 57 +852 776 5309 72 +740 670 5308 11 +845 48 5307 11 +55 717 5306 21 +113 677 5305 35 +496 871 5304 14 +429 882 5303 4 +850 31 5302 47 +332 810 5301 63 +120 842 5300 61 +105 612 5299 28 +622 3 5298 11 +330 897 5297 89 +39 861 5296 78 +806 209 5295 94 +989 101 5294 61 +851 572 5293 6 +220 835 5292 57 +968 21 5291 51 +229 327 5290 21 +608 174 5289 1 +106 216 5288 48 +36 105 5287 29 +651 847 5286 29 +108 326 5285 23 +528 549 5284 81 +737 487 5283 13 +813 60 5282 63 +694 305 5281 25 +153 197 5280 73 +957 532 5279 62 +111 190 5278 50 +257 1 5277 7 +521 57 5276 38 +777 416 5275 54 +61 679 5274 57 +426 506 5273 79 +754 379 5272 92 +108 512 5271 11 +664 117 5270 54 +341 119 5269 19 +188 431 5268 84 +944 685 5267 85 +640 840 5266 73 +736 964 5265 74 +173 788 5264 71 +126 866 5263 63 +866 804 5262 67 +394 578 5261 64 +998 344 5260 44 +687 349 5259 32 +745 992 5258 15 +845 116 5257 24 +876 992 5256 30 +175 28 5255 90 +922 81 5254 56 +61 962 5253 4 +225 25 5252 26 +233 201 5251 47 +995 120 5250 39 +357 170 5249 31 +875 908 5248 94 +124 940 5247 90 +964 399 5246 96 +946 340 5245 70 +119 517 5244 25 +936 786 5243 86 +823 788 5242 83 +80 75 5241 99 +950 86 5240 23 +261 368 5239 63 +968 41 5238 48 +540 932 5237 75 +59 266 5236 15 +822 448 5235 1 +731 392 5234 82 +997 24 5233 18 +712 843 5232 11 +988 753 5231 74 +717 601 5230 13 +326 155 5229 68 +109 730 5228 29 +665 592 5227 42 +818 142 5226 48 +55 189 5225 23 +368 644 5224 9 +180 70 5223 73 +90 369 5222 28 +151 612 5221 72 +445 440 5220 27 +425 396 5219 39 +137 865 5218 21 +449 946 5217 44 +952 244 5216 84 +544 145 5215 76 +574 357 5214 68 +700 448 5213 18 +756 561 5212 8 +172 452 5211 93 +43 880 5210 70 +531 173 5209 1 +918 773 5208 28 +702 597 5207 68 +98 83 5206 49 +788 76 5205 40 +909 499 5204 97 +887 97 5203 87 +108 151 5202 94 +572 232 5201 58 +707 686 5200 12 +399 731 5199 51 +176 599 5198 61 +513 190 5197 21 +6 90 5196 60 +577 436 5195 31 +401 96 5194 87 +946 929 5193 2 +919 360 5192 77 +545 455 5191 53 +954 617 5190 86 +132 898 5189 30 +409 397 5188 22 +99 611 5187 66 +653 294 5186 50 +340 431 5185 42 +167 856 5184 17 +569 242 5183 45 +905 243 5182 2 +837 669 5181 37 +718 557 5180 59 +501 85 5179 82 +785 559 5178 72 +317 155 5177 30 +862 77 5176 44 +574 253 5175 31 +614 721 5174 17 +999 427 5173 59 +573 653 5172 66 +111 783 5171 6 +472 768 5170 11 +525 100 5169 21 +404 412 5168 71 +78 863 5167 46 +824 133 5166 45 +531 140 5165 28 +294 575 5164 96 +774 933 5163 61 +870 597 5162 42 +14 947 5161 46 +667 903 5160 63 +687 499 5159 94 +549 249 5158 12 +730 12 5157 32 +992 166 5156 25 +564 328 5155 29 +641 345 5154 23 +336 188 5153 52 +649 963 5152 90 +44 822 5151 85 +403 692 5150 34 +250 825 5149 98 +237 795 5148 13 +845 71 5147 81 +838 961 5146 73 +982 54 5145 42 +156 717 5144 92 +225 616 5143 30 +141 48 5142 68 +130 508 5141 60 +866 366 5140 64 +30 842 5139 15 +723 318 5138 1 +109 82 5137 39 +907 309 5136 0 +336 505 5135 85 +101 617 5134 82 +568 618 5133 93 +539 82 5132 8 +141 964 5131 1 +523 487 5130 26 +524 140 5129 83 +236 620 5128 30 +772 384 5127 61 +803 150 5126 20 +887 30 5125 57 +998 893 5124 23 +536 848 5123 53 +118 72 5122 2 +476 748 5121 39 +347 426 5120 61 +519 530 5119 99 +236 692 5118 28 +234 411 5117 46 +120 630 5116 96 +136 336 5115 91 +45 701 5114 88 +776 505 5113 46 +323 630 5112 41 +321 779 5111 64 +896 618 5110 12 +837 711 5109 82 +281 824 5108 28 +780 494 5107 0 +294 53 5106 11 +634 26 5105 98 +196 426 5104 9 +875 44 5103 26 +850 776 5102 45 +160 512 5101 0 +907 301 5100 42 +887 544 5099 5 +329 281 5098 55 +441 888 5097 50 +26 129 5096 48 +600 893 5095 65 +382 821 5094 43 +267 817 5093 32 +264 450 5092 2 +211 576 5091 68 +757 367 5090 25 +262 502 5089 1 +393 55 5088 55 +758 14 5087 88 +236 826 5086 41 +72 220 5085 42 +3 118 5084 21 +366 295 5083 11 +874 335 5082 0 +208 435 5081 5 +864 233 5080 45 +446 461 5079 49 +41 670 5078 86 +187 472 5077 63 +606 989 5076 52 +102 208 5075 16 +822 102 5074 6 +959 112 5073 63 +900 949 5072 49 +201 599 5071 66 +772 959 5070 34 +791 624 5069 41 +197 235 5068 40 +483 111 5067 85 +780 359 5066 58 +106 95 5065 50 +990 431 5064 27 +162 144 5063 86 +350 826 5062 5 +639 321 5061 69 +335 926 5060 42 +388 12 5059 98 +124 551 5058 59 +752 272 5057 71 +264 77 5056 70 +663 223 5055 67 +287 417 5054 11 +317 803 5053 82 +505 360 5052 81 +395 269 5051 71 +913 448 5050 30 +460 387 5049 94 +279 879 5048 26 +194 11 5047 37 +854 29 5046 48 +806 557 5045 60 +613 288 5044 37 +442 16 5043 96 +91 100 5042 81 +821 407 5041 11 +60 357 5040 48 +508 681 5039 45 +867 892 5038 18 +982 884 5037 8 +471 886 5036 34 +269 225 5035 4 +272 406 5034 19 +915 157 5033 17 +692 701 5032 35 +50 628 5031 26 +675 28 5030 76 +789 272 5029 55 +8 95 5028 64 +997 745 5027 88 +661 292 5026 51 +819 855 5025 20 +248 21 5024 99 +455 819 5023 35 +73 81 5022 22 +600 508 5021 64 +756 209 5020 37 +176 911 5019 88 +350 755 5018 78 +453 374 5017 1 +437 308 5016 33 +833 205 5015 84 +202 640 5014 57 +737 133 5013 79 +572 580 5012 38 +299 268 5011 47 +297 487 5010 84 +155 105 5009 57 +380 770 5008 82 +65 674 5007 89 +103 493 5006 1 +565 272 5005 60 +506 777 5004 63 +552 410 5003 46 +312 909 5002 16 +780 628 5001 27 +382 264 5000 0 +335 752 4999 14 +95 929 4998 77 +181 881 4997 31 +220 412 4996 96 +494 972 4995 53 +366 167 4994 5 +500 299 4993 95 +281 891 4992 23 +363 271 4991 53 +512 859 4990 39 +823 366 4989 4 +48 459 4988 23 +468 353 4987 91 +440 424 4986 96 +804 479 4985 72 +867 104 4984 12 +407 714 4983 86 +620 708 4982 21 +411 133 4981 91 +492 351 4980 85 +907 807 4979 68 +106 325 4978 77 +929 953 4977 57 +944 234 4976 2 +375 598 4975 63 +389 261 4974 93 +6 646 4973 46 +575 302 4972 78 +781 66 4971 20 +543 162 4970 91 +482 914 4969 58 +372 195 4968 80 +718 550 4967 17 +635 393 4966 98 +336 698 4965 56 +615 476 4964 98 +343 673 4963 38 +236 577 4962 43 +903 290 4961 79 +248 332 4960 23 +718 785 4959 6 +644 622 4958 11 +157 192 4957 65 +695 415 4956 8 +221 582 4955 29 +803 602 4954 72 +95 951 4953 27 +286 637 4952 10 +958 556 4951 33 +547 175 4950 65 +162 951 4949 52 +429 456 4948 7 +777 570 4947 48 +833 783 4946 46 +979 577 4945 47 +651 449 4944 41 +314 164 4943 70 +81 775 4942 80 +380 676 4941 32 +224 125 4940 41 +495 455 4939 38 +885 586 4938 73 +787 25 4937 65 +206 988 4936 94 +127 55 4935 85 +285 710 4934 32 +388 898 4933 33 +98 479 4932 23 +550 918 4931 70 +669 26 4930 15 +869 651 4929 72 +560 80 4928 60 +37 708 4927 9 +932 90 4926 58 +345 524 4925 7 +811 991 4924 84 +419 103 4923 89 +561 532 4922 29 +892 543 4921 54 +374 427 4920 88 +571 119 4919 80 +372 511 4918 30 +617 517 4917 52 +566 502 4916 10 +532 235 4915 58 +888 945 4914 53 +570 606 4913 39 +988 742 4912 85 +116 666 4911 66 +307 80 4910 51 +608 491 4909 80 +993 784 4908 19 +14 418 4907 75 +266 517 4906 5 +290 53 4905 3 +339 141 4904 64 +863 534 4903 31 +75 188 4902 58 +586 151 4901 87 +588 714 4900 80 +706 604 4899 69 +366 443 4898 61 +901 704 4897 97 +463 16 4896 74 +912 390 4895 97 +606 325 4894 95 +346 736 4893 47 +36 709 4892 78 +437 63 4891 48 +109 109 4890 99 +160 85 4889 88 +739 635 4888 34 +687 230 4887 46 +626 771 4886 43 +64 26 4885 55 +589 474 4884 30 +27 687 4883 26 +646 298 4882 31 +953 492 4881 59 +24 114 4880 32 +449 541 4879 94 +404 875 4878 42 +459 27 4877 5 +745 885 4876 6 +551 246 4875 56 +787 45 4874 47 +388 949 4873 56 +806 711 4872 38 +377 269 4871 69 +573 379 4870 92 +666 527 4869 57 +848 367 4868 4 +141 992 4867 94 +639 498 4866 71 +200 87 4865 19 +95 913 4864 76 +237 179 4863 39 +441 689 4862 58 +889 763 4861 42 +852 354 4860 80 +159 529 4859 90 +375 99 4858 81 +494 231 4857 70 +411 518 4856 50 +173 430 4855 43 +734 365 4854 10 +490 817 4853 85 +925 151 4852 79 +409 625 4851 55 +824 896 4850 3 +429 89 4849 69 +867 111 4848 78 +712 203 4847 88 +88 63 4846 8 +65 334 4845 23 +548 246 4844 43 +665 61 4843 24 +525 243 4842 56 +729 514 4841 51 +807 345 4840 58 +977 908 4839 39 +907 902 4838 56 +140 798 4837 15 +728 844 4836 62 +87 798 4835 2 +185 195 4834 51 +818 678 4833 88 +729 49 4832 13 +168 930 4831 79 +437 190 4830 92 +5 833 4829 82 +103 406 4828 6 +953 530 4827 76 +46 601 4826 41 +603 506 4825 64 +517 634 4824 90 +628 743 4823 36 +118 343 4822 8 +740 874 4821 56 +357 92 4820 73 +426 759 4819 43 +876 302 4818 90 +929 355 4817 15 +94 770 4816 90 +871 738 4815 44 +891 535 4814 8 +400 278 4813 88 +468 527 4812 51 +781 829 4811 37 +332 299 4810 38 +457 529 4809 93 +947 751 4808 55 +584 242 4807 94 +31 464 4806 83 +203 357 4805 22 +256 196 4804 98 +750 377 4803 49 +698 133 4802 93 +529 993 4801 68 +769 452 4800 44 +778 380 4799 87 +509 603 4798 50 +777 112 4797 36 +107 611 4796 55 +160 243 4795 82 +818 488 4794 94 +244 560 4793 50 +139 244 4792 5 +541 237 4791 16 +71 573 4790 75 +777 366 4789 99 +490 145 4788 26 +501 810 4787 73 +367 724 4786 67 +754 881 4785 94 +928 440 4784 34 +315 454 4783 57 +7 882 4782 10 +663 410 4781 59 +207 767 4780 46 +220 722 4779 29 +334 538 4778 28 +86 60 4777 98 +842 724 4776 13 +441 604 4775 61 +985 767 4774 82 +572 468 4773 61 +471 507 4772 30 +642 128 4771 34 +45 175 4770 45 +184 7 4769 98 +477 296 4768 88 +335 856 4767 24 +119 519 4766 24 +836 787 4765 40 +298 212 4764 45 +961 305 4763 41 +378 964 4762 10 +952 888 4761 82 +167 468 4760 59 +710 101 4759 86 +440 637 4758 70 +336 4 4757 14 +731 841 4756 21 +575 946 4755 28 +906 41 4754 53 +341 313 4753 33 +75 270 4752 58 +419 232 4751 42 +367 735 4750 78 +464 155 4749 45 +632 564 4748 27 +162 925 4747 10 +895 933 4746 60 +905 745 4745 15 +728 200 4744 66 +42 754 4743 56 +38 157 4742 26 +497 640 4741 65 +580 327 4740 5 +591 187 4739 90 +638 166 4738 83 +992 498 4737 46 +187 448 4736 26 +545 487 4735 99 +445 103 4734 17 +597 300 4733 68 +516 608 4732 0 +313 605 4731 54 +140 148 4730 91 +20 71 4729 98 +667 362 4728 95 +50 201 4727 64 +960 277 4726 80 +384 813 4725 64 +802 491 4724 9 +691 681 4723 84 +3 462 4722 8 +456 624 4721 20 +76 927 4720 17 +709 36 4719 12 +160 306 4718 35 +924 840 4717 61 +464 162 4716 8 +321 543 4715 57 +809 250 4714 58 +219 767 4713 11 +838 878 4712 68 +697 30 4711 54 +890 52 4710 38 +729 767 4709 36 +466 735 4708 54 +677 527 4707 23 +619 513 4706 45 +292 994 4705 14 +483 471 4704 51 +888 422 4703 58 +848 141 4702 38 +977 166 4701 14 +285 13 4700 80 +31 817 4699 16 +208 312 4698 26 +13 776 4697 78 +519 316 4696 5 +523 629 4695 32 +48 922 4694 80 +280 208 4693 59 +975 240 4692 4 +152 334 4691 87 +196 645 4690 69 +504 897 4689 25 +535 474 4688 82 +460 731 4687 19 +686 729 4686 49 +706 519 4685 99 +714 213 4684 47 +968 554 4683 76 +905 169 4682 30 +689 179 4681 82 +747 438 4680 95 +423 429 4679 69 +743 629 4678 96 +1 701 4677 7 +210 496 4676 77 +305 522 4675 97 +659 706 4674 99 +384 462 4673 74 +990 481 4672 6 +740 868 4671 21 +8 263 4670 94 +800 723 4669 32 +927 892 4668 67 +204 302 4667 74 +974 793 4666 79 +815 987 4665 90 +244 246 4664 64 +981 682 4663 27 +613 846 4662 39 +604 274 4661 24 +540 617 4660 73 +830 644 4659 20 +590 937 4658 87 +509 951 4657 72 +805 885 4656 22 +740 259 4655 15 +563 371 4654 57 +836 880 4653 26 +572 144 4652 36 +656 517 4651 0 +973 523 4650 6 +706 335 4649 71 +986 148 4648 24 +66 494 4647 8 +626 70 4646 70 +887 588 4645 6 +491 307 4644 17 +735 895 4643 72 +627 358 4642 26 +993 945 4641 91 +188 353 4640 68 +186 469 4639 26 +654 159 4638 72 +424 377 4637 91 +481 637 4636 44 +280 889 4635 73 +412 448 4634 39 +536 464 4633 75 +413 347 4632 10 +591 232 4631 63 +883 417 4630 80 +310 545 4629 0 +782 800 4628 53 +739 479 4627 23 +748 701 4626 94 +440 341 4625 20 +984 640 4624 86 +117 648 4623 87 +114 473 4622 12 +815 828 4621 82 +871 803 4620 70 +744 470 4619 57 +320 300 4618 52 +778 288 4617 4 +359 742 4616 99 +701 332 4615 30 +992 992 4614 45 +174 752 4613 86 +645 301 4612 0 +24 114 4611 29 +333 134 4610 94 +169 45 4609 12 +12 485 4608 42 +545 51 4607 54 +410 683 4606 41 +339 851 4605 65 +239 590 4604 70 +451 863 4603 81 +187 704 4602 52 +979 355 4601 62 +89 816 4600 69 +559 702 4599 16 +434 881 4598 15 +368 123 4597 46 +832 760 4596 13 +261 948 4595 7 +726 891 4594 10 +159 288 4593 78 +349 907 4592 26 +538 930 4591 20 +114 526 4590 89 +821 7 4589 52 +757 689 4588 12 +363 331 4587 6 +812 64 4586 53 +56 970 4585 57 +603 312 4584 53 +380 523 4583 56 +977 56 4582 81 +403 317 4581 81 +518 360 4580 42 +318 404 4579 29 +358 59 4578 6 +266 529 4577 39 +94 964 4576 55 +658 36 4575 75 +788 967 4574 45 +467 757 4573 22 +739 999 4572 40 +956 386 4571 57 +956 131 4570 88 +344 229 4569 20 +529 669 4568 95 +564 843 4567 9 +928 795 4566 17 +69 301 4565 43 +210 231 4564 86 +757 819 4563 32 +612 829 4562 72 +255 688 4561 78 +902 685 4560 0 +559 240 4559 61 +826 867 4558 81 +47 920 4557 96 +494 735 4556 63 +70 566 4555 85 +412 548 4554 85 +989 593 4553 45 +140 945 4552 14 +3 781 4551 35 +444 389 4550 35 +372 796 4549 34 +947 850 4548 73 +184 328 4547 77 +168 778 4546 55 +18 999 4545 42 +955 407 4544 65 +647 307 4543 42 +163 787 4542 84 +392 5 4541 13 +593 9 4540 55 +946 609 4539 7 +521 954 4538 42 +550 226 4537 76 +778 128 4536 1 +592 766 4535 14 +99 235 4534 6 +520 573 4533 30 +781 711 4532 48 +995 579 4531 77 +400 485 4530 79 +655 647 4529 64 +728 661 4528 42 +97 746 4527 97 +362 866 4526 77 +530 86 4525 18 +662 756 4524 49 +861 823 4523 57 +132 713 4522 73 +93 971 4521 78 +838 152 4520 59 +986 222 4519 74 +914 452 4518 92 +880 200 4517 63 +780 584 4516 73 +329 694 4515 83 +933 913 4514 86 +110 840 4513 80 +741 952 4512 72 +819 190 4511 3 +929 850 4510 25 +770 817 4509 85 +251 296 4508 7 +616 896 4507 3 +889 902 4506 9 +780 963 4505 45 +73 67 4504 39 +888 71 4503 82 +761 690 4502 36 +340 782 4501 92 +32 403 4500 88 +521 780 4499 15 +399 37 4498 51 +994 934 4497 63 +938 648 4496 72 +896 54 4495 10 +995 573 4494 70 +380 454 4493 18 +908 446 4492 12 +378 32 4491 42 +623 730 4490 30 +743 640 4489 51 +102 883 4488 12 +285 908 4487 40 +594 617 4486 5 +480 401 4485 4 +119 522 4484 90 +8 58 4483 61 +413 705 4482 47 +301 113 4481 52 +90 796 4480 75 +756 388 4479 87 +974 717 4478 64 +291 349 4477 81 +215 12 4476 69 +878 142 4475 11 +464 285 4474 36 +353 141 4473 11 +591 943 4472 59 +317 773 4471 11 +407 875 4470 21 +671 238 4469 33 +368 824 4468 78 +336 125 4467 68 +870 576 4466 7 +856 753 4465 33 +143 249 4464 41 +198 516 4463 11 +169 482 4462 76 +898 901 4461 27 +636 877 4460 90 +414 551 4459 73 +698 99 4458 30 +549 606 4457 3 +822 738 4456 46 +503 922 4455 1 +733 303 4454 71 +33 349 4453 94 +581 486 4452 2 +24 365 4451 27 +326 172 4450 26 +451 433 4449 22 +492 271 4448 71 +868 565 4447 14 +816 452 4446 72 +619 300 4445 31 +953 768 4444 77 +863 916 4443 69 +121 757 4442 45 +192 10 4441 55 +739 39 4440 69 +161 506 4439 87 +706 566 4438 95 +112 422 4437 62 +152 407 4436 5 +532 548 4435 19 +851 70 4434 66 +159 246 4433 9 +746 896 4432 74 +970 858 4431 92 +533 823 4430 45 +939 915 4429 57 +144 334 4428 45 +14 573 4427 59 +858 854 4426 96 +478 531 4425 62 +823 575 4424 68 +350 348 4423 69 +37 813 4422 41 +35 475 4421 77 +907 875 4420 43 +581 122 4419 59 +760 862 4418 79 +718 632 4417 12 +323 340 4416 15 +955 939 4415 38 +227 989 4414 65 +534 279 4413 47 +337 636 4412 31 +600 338 4411 0 +752 844 4410 12 +260 798 4409 32 +229 666 4408 82 +292 973 4407 4 +401 776 4406 39 +950 725 4405 36 +710 181 4404 72 +642 159 4403 69 +298 311 4402 19 +494 875 4401 73 +46 801 4400 84 +131 505 4399 49 +693 778 4398 3 +196 647 4397 93 +50 26 4396 89 +543 640 4395 45 +22 35 4394 24 +848 495 4393 6 +436 459 4392 34 +73 889 4391 80 +295 356 4390 44 +727 460 4389 91 +130 94 4388 43 +621 45 4387 49 +385 440 4386 14 +605 210 4385 50 +540 172 4384 52 +35 722 4383 17 +569 540 4382 41 +533 355 4381 36 +895 533 4380 77 +366 475 4379 56 +48 942 4378 59 +605 350 4377 50 +229 638 4376 23 +38 985 4375 78 +449 347 4374 6 +182 761 4373 50 +184 50 4372 46 +822 583 4371 3 +57 209 4370 63 +533 971 4369 52 +592 87 4368 31 +711 273 4367 44 +653 455 4366 37 +637 715 4365 19 +586 560 4364 58 +710 38 4363 26 +466 429 4362 99 +374 397 4361 36 +237 109 4360 76 +884 210 4359 52 +814 875 4358 94 +818 66 4357 88 +739 184 4356 5 +154 603 4355 1 +522 320 4354 5 +608 269 4353 87 +31 635 4352 24 +288 597 4351 9 +898 240 4350 13 +334 583 4349 35 +809 59 4348 6 +882 822 4347 99 +581 43 4346 7 +282 963 4345 58 +51 175 4344 63 +634 631 4343 91 +37 152 4342 57 +357 954 4341 74 +656 783 4340 38 +524 284 4339 56 +236 72 4338 52 +779 918 4337 92 +79 494 4336 30 +788 952 4335 29 +543 718 4334 23 +479 337 4333 41 +197 833 4332 59 +171 353 4331 68 +499 825 4330 70 +211 38 4329 13 +154 598 4328 28 +423 626 4327 45 +542 2 4326 70 +233 67 4325 29 +380 814 4324 24 +504 819 4323 6 +479 916 4322 28 +528 978 4321 2 +786 569 4320 67 +440 845 4319 28 +971 829 4318 5 +623 757 4317 73 +934 409 4316 88 +252 46 4315 30 +995 180 4314 85 +902 782 4313 87 +937 255 4312 2 +409 355 4311 95 +724 383 4310 74 +15 229 4309 34 +72 327 4308 46 +348 848 4307 34 +362 573 4306 68 +865 455 4305 68 +397 977 4304 25 +527 850 4303 9 +900 73 4302 96 +971 209 4301 52 +153 396 4300 68 +902 876 4299 70 +478 120 4298 94 +275 659 4297 72 +118 6 4296 98 +478 424 4295 49 +126 164 4294 46 +777 127 4293 87 +864 437 4292 62 +813 842 4291 92 +519 976 4290 81 +755 765 4289 25 +461 218 4288 42 +652 738 4287 20 +582 488 4286 15 +259 28 4285 64 +37 597 4284 35 +690 243 4283 34 +594 697 4282 91 +865 111 4281 5 +210 566 4280 29 +547 826 4279 76 +480 221 4278 29 +250 45 4277 80 +459 517 4276 7 +431 288 4275 32 +353 2 4274 22 +546 436 4273 34 +585 861 4272 9 +545 757 4271 72 +739 530 4270 65 +605 469 4269 66 +176 484 4268 6 +527 739 4267 23 +229 747 4266 79 +285 100 4265 2 +565 874 4264 7 +575 252 4263 80 +104 365 4262 96 +226 75 4261 3 +60 990 4260 80 +985 596 4259 13 +744 837 4258 42 +991 439 4257 64 +647 762 4256 29 +225 949 4255 94 +622 271 4254 71 +886 846 4253 99 +290 920 4252 47 +84 233 4251 87 +393 672 4250 16 +759 704 4249 7 +397 781 4248 24 +677 349 4247 75 +812 354 4246 34 +678 224 4245 42 +424 728 4244 60 +925 520 4243 73 +687 592 4242 59 +560 712 4241 20 +967 90 4240 69 +923 834 4239 63 +431 487 4238 36 +994 409 4237 71 +130 921 4236 86 +495 819 4235 13 +208 868 4234 25 +927 138 4233 49 +880 391 4232 23 +621 514 4231 12 +255 56 4230 59 +347 272 4229 4 +77 642 4228 49 +488 854 4227 43 +101 731 4226 86 +951 879 4225 63 +729 754 4224 28 +747 260 4223 28 +876 112 4222 4 +458 533 4221 25 +783 548 4220 36 +630 552 4219 90 +788 55 4218 26 +122 572 4217 58 +852 228 4216 38 +124 348 4215 15 +494 4 4214 22 +148 235 4213 98 +578 786 4212 87 +984 892 4211 41 +996 458 4210 67 +497 638 4209 15 +482 680 4208 84 +344 202 4207 66 +879 236 4206 27 +344 928 4205 72 +769 239 4204 63 +448 111 4203 34 +894 452 4202 56 +434 743 4201 59 +820 520 4200 98 +957 311 4199 49 +478 176 4198 1 +966 395 4197 13 +307 543 4196 46 +689 97 4195 53 +127 283 4194 57 +659 777 4193 32 +708 975 4192 55 +222 604 4191 45 +208 489 4190 61 +135 484 4189 86 +780 877 4188 47 +852 672 4187 51 +446 929 4186 65 +813 960 4185 61 +506 253 4184 56 +801 766 4183 46 +370 94 4182 95 +115 845 4181 48 +5 750 4180 1 +607 383 4179 7 +204 967 4178 35 +742 852 4177 92 +969 41 4176 40 +706 54 4175 63 +487 95 4174 30 +671 516 4173 70 +248 465 4172 43 +95 471 4171 25 +366 940 4170 11 +416 717 4169 39 +114 426 4168 40 +810 522 4167 46 +986 773 4166 77 +959 325 4165 26 +578 602 4164 21 +50 273 4163 81 +993 175 4162 42 +531 144 4161 15 +222 712 4160 72 +291 994 4159 95 +904 941 4158 30 +749 687 4157 30 +447 511 4156 82 +722 42 4155 2 +328 403 4154 38 +98 392 4153 52 +30 269 4152 5 +432 425 4151 46 +717 777 4150 30 +53 648 4149 93 +253 998 4148 38 +176 479 4147 15 +468 796 4146 30 +639 646 4145 72 +11 852 4144 39 +122 472 4143 23 +844 593 4142 6 +647 154 4141 59 +129 376 4140 71 +650 544 4139 66 +518 232 4138 79 +683 853 4137 7 +150 576 4136 70 +794 330 4135 82 +380 163 4134 62 +878 162 4133 88 +439 469 4132 27 +777 883 4131 19 +832 49 4130 51 +311 864 4129 47 +378 722 4128 13 +277 369 4127 83 +245 878 4126 53 +167 201 4125 35 +0 739 4124 41 +693 610 4123 50 +585 81 4122 43 +833 678 4121 66 +185 38 4120 94 +141 347 4119 52 +353 296 4118 93 +490 302 4117 10 +677 176 4116 3 +461 942 4115 7 +129 912 4114 16 +528 62 4113 30 +403 777 4112 10 +639 715 4111 75 +691 424 4110 64 +50 587 4109 4 +994 831 4108 78 +125 69 4107 86 +234 953 4106 81 +30 911 4105 21 +849 858 4104 33 +284 200 4103 60 +62 355 4102 12 +291 103 4101 76 +837 604 4100 94 +756 255 4099 64 +761 925 4098 5 +115 48 4097 86 +42 598 4096 89 +52 882 4095 20 +658 731 4094 18 +844 475 4093 56 +251 361 4092 22 +499 815 4091 77 +349 307 4090 45 +329 584 4089 8 +877 187 4088 99 +450 977 4087 64 +715 687 4086 7 +151 23 4085 98 +255 615 4084 39 +114 343 4083 81 +545 451 4082 59 +507 316 4081 75 +723 373 4080 14 +396 86 4079 2 +209 348 4078 45 +289 571 4077 42 +664 84 4076 73 +408 594 4075 56 +271 580 4074 89 +891 220 4073 14 +134 841 4072 56 +943 602 4071 3 +286 129 4070 78 +737 568 4069 32 +777 24 4068 18 +487 692 4067 92 +489 169 4066 62 +13 668 4065 25 +360 755 4064 13 +379 571 4063 38 +238 530 4062 75 +473 254 4061 19 +561 456 4060 65 +543 139 4059 54 +331 267 4058 96 +522 294 4057 28 +501 369 4056 99 +912 119 4055 47 +183 756 4054 65 +41 623 4053 98 +275 566 4052 14 +797 534 4051 76 +317 107 4050 91 +872 589 4049 1 +972 670 4048 21 +925 292 4047 80 +249 521 4046 2 +363 822 4045 58 +132 671 4044 72 +57 841 4043 14 +32 375 4042 76 +426 852 4041 47 +517 894 4040 48 +919 805 4039 44 +377 403 4038 90 +771 787 4037 4 +698 432 4036 67 +150 859 4035 88 +830 587 4034 23 +465 375 4033 7 +522 288 4032 2 +958 997 4031 60 +89 35 4030 90 +402 544 4029 59 +615 853 4028 54 +354 370 4027 60 +573 790 4026 7 +271 655 4025 54 +211 154 4024 31 +87 50 4023 36 +290 419 4022 94 +961 696 4021 56 +491 310 4020 86 +690 56 4019 68 +482 935 4018 78 +580 533 4017 26 +134 524 4016 78 +500 228 4015 30 +104 954 4014 5 +630 421 4013 12 +723 378 4012 79 +385 695 4011 32 +253 182 4010 46 +121 899 4009 80 +401 526 4008 20 +9 478 4007 90 +295 479 4006 44 +273 242 4005 63 +533 935 4004 39 +42 327 4003 47 +683 467 4002 90 +513 859 4001 33 +282 669 4000 13 +372 592 3999 13 +47 305 3998 72 +999 457 3997 39 +237 811 3996 71 +307 238 3995 2 +608 922 3994 74 +859 566 3993 49 +608 568 3992 35 +189 206 3991 17 +77 999 3990 23 +287 411 3989 91 +848 328 3988 32 +645 678 3987 4 +572 691 3986 76 +315 282 3985 93 +356 250 3984 69 +998 131 3983 74 +361 188 3982 25 +206 940 3981 41 +588 320 3980 11 +82 584 3979 78 +650 277 3978 43 +986 286 3977 20 +409 831 3976 7 +31 230 3975 25 +118 950 3974 95 +942 496 3973 35 +248 833 3972 63 +620 305 3971 15 +735 322 3970 61 +307 351 3969 50 +990 236 3968 43 +454 129 3967 66 +600 815 3966 57 +280 297 3965 37 +454 601 3964 91 +663 721 3963 17 +528 480 3962 69 +982 537 3961 62 +971 111 3960 88 +115 74 3959 42 +106 767 3958 31 +314 86 3957 53 +517 200 3956 85 +696 464 3955 32 +879 736 3954 82 +240 483 3953 79 +943 65 3952 13 +425 743 3951 54 +36 456 3950 1 +307 110 3949 85 +681 781 3948 0 +886 681 3947 79 +736 533 3946 79 +728 495 3945 82 +253 34 3944 81 +418 656 3943 63 +321 588 3942 29 +286 535 3941 51 +345 154 3940 38 +329 847 3939 72 +99 216 3938 62 +148 996 3937 79 +38 975 3936 14 +460 4 3935 0 +377 178 3934 47 +68 341 3933 83 +52 779 3932 9 +381 129 3931 3 +306 658 3930 94 +631 104 3929 1 +220 830 3928 23 +20 645 3927 95 +970 141 3926 11 +826 533 3925 57 +837 640 3924 8 +561 738 3923 30 +650 62 3922 1 +470 93 3921 67 +554 924 3920 7 +273 785 3919 67 +185 280 3918 41 +503 839 3917 19 +608 533 3916 5 +893 494 3915 14 +901 773 3914 98 +676 292 3913 27 +968 346 3912 91 +168 594 3911 18 +139 400 3910 91 +505 263 3909 28 +441 211 3908 8 +305 148 3907 68 +39 905 3906 89 +720 155 3905 71 +481 713 3904 99 +946 364 3903 22 +751 730 3902 70 +194 264 3901 80 +136 634 3900 2 +52 193 3899 63 +62 405 3898 6 +243 787 3897 13 +750 179 3896 26 +441 724 3895 31 +349 766 3894 23 +633 518 3893 53 +466 906 3892 19 +630 771 3891 55 +440 395 3890 5 +788 569 3889 8 +618 929 3888 98 +608 868 3887 81 +454 947 3886 49 +958 79 3885 30 +247 703 3884 9 +611 340 3883 71 +135 637 3882 16 +376 499 3881 83 +825 973 3880 19 +640 95 3879 65 +60 169 3878 16 +920 326 3877 0 +867 184 3876 15 +376 216 3875 49 +362 376 3874 71 +703 548 3873 63 +137 331 3872 47 +526 645 3871 75 +877 538 3870 55 +925 482 3869 18 +842 159 3868 58 +142 856 3867 13 +968 657 3866 5 +840 786 3865 49 +827 74 3864 1 +217 160 3863 65 +686 717 3862 56 +107 207 3861 61 +55 366 3860 64 +322 604 3859 95 +303 440 3858 8 +199 86 3857 70 +870 561 3856 17 +712 477 3855 12 +913 354 3854 1 +443 92 3853 61 +509 955 3852 53 +841 962 3851 57 +762 696 3850 5 +163 869 3849 73 +353 381 3848 1 +525 527 3847 10 +83 45 3846 32 +122 115 3845 15 +262 402 3844 79 +137 79 3843 47 +992 951 3842 93 +265 527 3841 66 +827 318 3840 7 +487 713 3839 59 +854 914 3838 80 +481 775 3837 82 +930 169 3836 44 +713 360 3835 96 +322 327 3834 86 +127 536 3833 12 +424 266 3832 14 +208 588 3831 72 +605 479 3830 43 +798 789 3829 33 +138 981 3828 63 +606 385 3827 37 +809 481 3826 55 +32 100 3825 21 +791 735 3824 39 +269 980 3823 19 +677 417 3822 70 +108 288 3821 21 +690 98 3820 60 +807 707 3819 80 +595 259 3818 65 +903 822 3817 53 +381 334 3816 79 +364 826 3815 77 +755 195 3814 24 +562 492 3813 52 +128 486 3812 59 +190 613 3811 56 +391 796 3810 41 +448 146 3809 88 +437 127 3808 21 +487 735 3807 69 +508 20 3806 52 +631 535 3805 1 +703 719 3804 60 +5 930 3803 19 +873 22 3802 43 +816 150 3801 93 +650 535 3800 79 +19 670 3799 94 +391 519 3798 1 +715 169 3797 94 +484 504 3796 97 +816 408 3795 87 +789 416 3794 92 +907 758 3793 69 +872 496 3792 13 +614 139 3791 5 +865 855 3790 16 +151 932 3789 63 +350 61 3788 62 +664 969 3787 67 +96 102 3786 23 +992 949 3785 66 +658 229 3784 2 +262 566 3783 88 +356 74 3782 3 +283 890 3781 25 +923 534 3780 74 +870 3 3779 71 +92 952 3778 80 +866 444 3777 68 +153 563 3776 56 +719 640 3775 10 +663 145 3774 33 +491 846 3773 39 +183 778 3772 90 +356 507 3771 7 +531 35 3770 35 +51 913 3769 5 +507 115 3768 77 +881 116 3767 22 +922 464 3766 71 +494 769 3765 43 +299 938 3764 5 +68 490 3763 17 +270 832 3762 30 +471 713 3761 82 +122 306 3760 82 +797 275 3759 48 +999 552 3758 54 +651 512 3757 62 +695 279 3756 95 +830 378 3755 42 +447 883 3754 19 +658 864 3753 23 +118 479 3752 79 +407 2 3751 79 +30 344 3750 34 +722 937 3749 32 +40 916 3748 79 +232 668 3747 34 +900 530 3746 95 +494 232 3745 86 +18 963 3744 38 +385 434 3743 78 +477 998 3742 53 +658 449 3741 71 +407 23 3740 37 +20 527 3739 30 +248 450 3738 68 +137 391 3737 80 +297 91 3736 33 +268 481 3735 40 +529 593 3734 47 +435 249 3733 63 +548 828 3732 90 +425 334 3731 81 +496 68 3730 25 +76 626 3729 38 +59 873 3728 77 +300 475 3727 11 +609 925 3726 83 +888 930 3725 2 +343 841 3724 73 +421 725 3723 9 +494 88 3722 88 +265 568 3721 12 +441 863 3720 92 +752 614 3719 42 +397 662 3718 1 +550 270 3717 75 +994 811 3716 69 +88 289 3715 72 +116 645 3714 54 +637 207 3713 92 +520 764 3712 92 +704 193 3711 22 +249 508 3710 82 +952 403 3709 68 +391 258 3708 35 +459 67 3707 84 +521 970 3706 55 +644 175 3705 90 +437 622 3704 97 +443 995 3703 47 +570 698 3702 11 +685 404 3701 81 +105 135 3700 45 +144 333 3699 29 +191 507 3698 56 +96 291 3697 93 +794 649 3696 93 +553 933 3695 87 +626 493 3694 20 +297 362 3693 99 +294 301 3692 87 +268 359 3691 88 +801 158 3690 57 +826 736 3689 96 +215 628 3688 95 +642 994 3687 9 +715 60 3686 30 +440 670 3685 24 +131 212 3684 92 +60 121 3683 32 +941 988 3682 0 +201 305 3681 2 +421 618 3680 46 +107 7 3679 97 +634 859 3678 61 +933 791 3677 57 +390 60 3676 92 +458 315 3675 27 +90 596 3674 30 +133 327 3673 7 +683 976 3672 11 +686 558 3671 74 +611 491 3670 77 +147 364 3669 31 +67 37 3668 47 +731 646 3667 70 +745 651 3666 54 +718 966 3665 93 +269 238 3664 36 +350 951 3663 95 +418 379 3662 45 +66 960 3661 99 +127 465 3660 7 +326 840 3659 46 +391 772 3658 8 +995 157 3657 33 +684 610 3656 98 +728 564 3655 2 +287 409 3654 44 +572 507 3653 91 +418 453 3652 93 +494 922 3651 35 +625 610 3650 93 +67 383 3649 80 +614 744 3648 93 +546 349 3647 39 +45 959 3646 31 +155 577 3645 95 +901 529 3644 44 +54 987 3643 71 +531 580 3642 15 +311 411 3641 92 +227 138 3640 86 +639 866 3639 55 +394 537 3638 45 +390 85 3637 6 +382 355 3636 50 +47 513 3635 89 +542 726 3634 25 +406 561 3633 84 +168 229 3632 52 +273 54 3631 21 +271 312 3630 8 +328 104 3629 58 +451 385 3628 24 +730 566 3627 0 +841 610 3626 0 +787 636 3625 33 +165 406 3624 50 +331 323 3623 13 +175 303 3622 23 +742 135 3621 89 +207 496 3620 0 +719 342 3619 94 +818 241 3618 87 +956 995 3617 72 +973 673 3616 88 +230 828 3615 5 +82 370 3614 62 +20 897 3613 83 +167 342 3612 15 +639 894 3611 43 +154 58 3610 53 +100 65 3609 48 +245 155 3608 90 +321 832 3607 86 +845 834 3606 98 +457 431 3605 74 +473 789 3604 14 +554 676 3603 6 +448 723 3602 85 +835 898 3601 52 +992 45 3600 48 +910 587 3599 5 +322 39 3598 85 +998 878 3597 92 +403 239 3596 47 +642 595 3595 38 +112 85 3594 98 +953 209 3593 91 +824 324 3592 10 +853 42 3591 61 +458 431 3590 84 +548 198 3589 8 +160 930 3588 58 +639 447 3587 32 +643 89 3586 59 +509 403 3585 76 +876 65 3584 53 +884 812 3583 15 +281 493 3582 12 +611 769 3581 97 +233 760 3580 39 +267 494 3579 90 +483 262 3578 38 +358 729 3577 52 +686 834 3576 99 +337 229 3575 13 +253 372 3574 63 +318 28 3573 99 +723 158 3572 60 +9 576 3571 67 +265 485 3570 37 +232 522 3569 96 +533 866 3568 78 +895 525 3567 12 +604 861 3566 67 +857 500 3565 34 +343 641 3564 8 +870 387 3563 93 +582 933 3562 59 +91 292 3561 71 +962 412 3560 74 +655 181 3559 3 +341 658 3558 69 +663 453 3557 63 +360 323 3556 29 +858 265 3555 74 +253 148 3554 51 +454 340 3553 47 +641 880 3552 28 +879 970 3551 49 +231 710 3550 12 +522 334 3549 30 +205 61 3548 31 +129 347 3547 67 +58 543 3546 30 +117 232 3545 50 +807 40 3544 60 +460 185 3543 79 +909 796 3542 81 +259 362 3541 76 +376 821 3540 64 +273 992 3539 70 +713 636 3538 31 +803 374 3537 7 +311 801 3536 7 +192 897 3535 94 +854 805 3534 30 +389 985 3533 34 +433 51 3532 55 +541 114 3531 65 +828 937 3530 88 +356 393 3529 10 +262 240 3528 55 +572 4 3527 91 +904 130 3526 49 +91 631 3525 11 +820 963 3524 33 +933 795 3523 46 +937 900 3522 95 +176 766 3521 89 +544 780 3520 71 +153 543 3519 47 +235 648 3518 9 +873 418 3517 69 +499 373 3516 66 +667 781 3515 81 +167 872 3514 27 +895 508 3513 88 +133 64 3512 99 +986 178 3511 76 +237 241 3510 63 +894 378 3509 39 +230 403 3508 91 +45 21 3507 36 +592 855 3506 37 +908 541 3505 83 +364 384 3504 50 +444 890 3503 27 +886 235 3502 76 +936 128 3501 14 +862 240 3500 74 +975 474 3499 34 +381 555 3498 66 +165 987 3497 18 +313 543 3496 45 +157 330 3495 68 +494 228 3494 54 +654 510 3493 91 +107 614 3492 55 +887 399 3491 94 +766 405 3490 7 +918 679 3489 88 +568 478 3488 59 +444 732 3487 21 +212 769 3486 85 +102 139 3485 15 +718 624 3484 66 +895 361 3483 83 +215 608 3482 54 +993 875 3481 21 +726 187 3480 12 +200 292 3479 84 +745 378 3478 35 +963 364 3477 12 +629 695 3476 23 +515 493 3475 10 +262 823 3474 38 +752 292 3473 82 +733 327 3472 68 +687 99 3471 22 +895 272 3470 26 +914 498 3469 52 +14 226 3468 45 +668 892 3467 78 +201 122 3466 33 +670 726 3465 11 +530 560 3464 25 +965 142 3463 50 +227 458 3462 1 +827 954 3461 4 +773 742 3460 79 +271 70 3459 98 +334 672 3458 90 +769 448 3457 34 +395 221 3456 46 +165 860 3455 53 +418 743 3454 13 +683 490 3453 56 +504 973 3452 73 +211 253 3451 40 +672 811 3450 5 +397 80 3449 50 +224 554 3448 93 +226 878 3447 56 +360 934 3446 37 +116 392 3445 23 +253 573 3444 74 +517 828 3443 73 +719 337 3442 17 +442 346 3441 29 +730 551 3440 53 +526 564 3439 27 +676 373 3438 17 +943 190 3437 99 +542 143 3436 86 +819 483 3435 24 +745 11 3434 86 +490 556 3433 73 +990 885 3432 79 +795 753 3431 27 +987 265 3430 71 +190 101 3429 20 +183 175 3428 84 +46 131 3427 73 +660 621 3426 40 +472 380 3425 72 +454 127 3424 7 +671 938 3423 25 +132 520 3422 50 +488 564 3421 19 +163 507 3420 80 +925 354 3419 79 +43 117 3418 0 +510 330 3417 13 +240 679 3416 38 +253 648 3415 18 +189 819 3414 1 +417 753 3413 78 +956 305 3412 53 +57 386 3411 64 +153 11 3410 32 +236 789 3409 23 +787 869 3408 88 +651 750 3407 53 +30 198 3406 26 +829 170 3405 98 +65 234 3404 6 +448 244 3403 77 +919 894 3402 46 +374 320 3401 89 +222 86 3400 90 +919 355 3399 91 +119 348 3398 44 +552 264 3397 13 +28 281 3396 62 +936 924 3395 20 +989 291 3394 76 +349 310 3393 61 +574 562 3392 52 +233 994 3391 54 +730 988 3390 15 +7 466 3389 30 +83 314 3388 80 +983 514 3387 56 +357 420 3386 52 +632 436 3385 9 +980 146 3384 94 +748 88 3383 63 +567 984 3382 77 +6 392 3381 34 +521 849 3380 50 +151 501 3379 72 +799 233 3378 92 +94 42 3377 10 +983 431 3376 62 +290 145 3375 72 +58 307 3374 65 +104 864 3373 23 +592 434 3372 18 +542 837 3371 56 +347 780 3370 48 +268 798 3369 36 +190 823 3368 35 +610 474 3367 70 +286 901 3366 11 +837 72 3365 69 +443 418 3364 23 +429 52 3363 95 +596 618 3362 51 +57 76 3361 4 +981 114 3360 19 +975 17 3359 7 +349 647 3358 7 +572 593 3357 58 +828 418 3356 32 +654 460 3355 44 +366 278 3354 39 +433 441 3353 1 +542 462 3352 83 +962 855 3351 53 +97 114 3350 7 +370 2 3349 0 +53 497 3348 62 +174 255 3347 77 +958 875 3346 74 +182 54 3345 17 +836 380 3344 28 +979 181 3343 93 +606 292 3342 89 +741 464 3341 58 +111 68 3340 86 +505 380 3339 72 +241 848 3338 31 +380 33 3337 87 +820 569 3336 21 +673 886 3335 77 +199 355 3334 34 +888 41 3333 85 +828 311 3332 37 +395 715 3331 86 +687 138 3330 62 +532 410 3329 60 +815 437 3328 26 +464 662 3327 86 +682 441 3326 55 +531 429 3325 14 +313 488 3324 47 +730 483 3323 31 +595 507 3322 6 +577 236 3321 43 +727 22 3320 70 +973 342 3319 15 +775 403 3318 71 +221 301 3317 35 +11 412 3316 78 +941 672 3315 15 +5 164 3314 21 +975 249 3313 58 +271 627 3312 13 +213 725 3311 1 +680 552 3310 84 +938 438 3309 75 +102 366 3308 19 +888 569 3307 55 +739 630 3306 20 +508 933 3305 7 +914 634 3304 93 +621 448 3303 2 +902 115 3302 70 +172 169 3301 5 +113 94 3300 53 +72 557 3299 74 +796 643 3298 83 +939 344 3297 21 +696 139 3296 14 +298 134 3295 23 +186 906 3294 59 +332 325 3293 29 +946 646 3292 71 +74 524 3291 72 +537 791 3290 5 +913 904 3289 4 +299 623 3288 27 +204 64 3287 85 +5 917 3286 24 +228 637 3285 39 +580 301 3284 11 +679 573 3283 85 +121 988 3282 38 +732 670 3281 87 +887 17 3280 53 +281 765 3279 62 +558 419 3278 61 +147 613 3277 9 +279 844 3276 19 +336 285 3275 77 +727 259 3274 64 +584 467 3273 90 +318 514 3272 55 +653 334 3271 38 +251 912 3270 84 +346 9 3269 60 +805 519 3268 72 +769 896 3267 41 +559 421 3266 86 +26 129 3265 94 +792 746 3264 60 +953 343 3263 14 +179 169 3262 26 +422 543 3261 66 +903 239 3260 40 +489 882 3259 90 +623 312 3258 54 +474 542 3257 3 +291 925 3256 21 +383 334 3255 53 +403 465 3254 23 +173 876 3253 83 +626 601 3252 77 +303 263 3251 75 +356 496 3250 51 +570 364 3249 41 +769 505 3248 86 +617 825 3247 14 +590 677 3246 18 +869 299 3245 90 +588 394 3244 98 +275 65 3243 22 +338 16 3242 54 +767 238 3241 32 +131 104 3240 94 +859 547 3239 78 +679 716 3238 80 +147 965 3237 15 +378 275 3236 2 +904 927 3235 72 +329 750 3234 28 +48 682 3233 31 +777 224 3232 93 +133 376 3231 57 +557 160 3230 63 +831 985 3229 27 +750 649 3228 17 +690 124 3227 53 +347 306 3226 76 +177 439 3225 47 +67 968 3224 57 +458 376 3223 28 +847 365 3222 27 +216 935 3221 64 +175 363 3220 57 +335 92 3219 72 +525 648 3218 8 +818 762 3217 6 +866 295 3216 34 +471 899 3215 17 +591 293 3214 10 +11 10 3213 60 +429 626 3212 61 +572 67 3211 63 +271 850 3210 4 +443 645 3209 83 +886 19 3208 81 +466 717 3207 70 +395 172 3206 95 +605 60 3205 39 +283 500 3204 87 +383 998 3203 58 +559 978 3202 58 +216 590 3201 85 +204 201 3200 30 +626 29 3199 82 +301 103 3198 55 +545 755 3197 41 +111 556 3196 7 +559 515 3195 78 +502 299 3194 32 +19 997 3193 90 +388 725 3192 82 +389 555 3191 34 +172 474 3190 1 +925 269 3189 57 +348 138 3188 32 +198 348 3187 75 +41 280 3186 43 +215 467 3185 55 +301 422 3184 5 +272 75 3183 48 +170 481 3182 63 +81 330 3181 99 +204 433 3180 21 +131 254 3179 24 +789 568 3178 57 +67 322 3177 15 +813 882 3176 15 +45 494 3175 82 +346 573 3174 91 +594 852 3173 2 +150 632 3172 10 +897 781 3171 8 +178 970 3170 87 +685 670 3169 7 +246 426 3168 34 +439 993 3167 72 +388 330 3166 25 +920 913 3165 76 +721 883 3164 69 +219 928 3163 75 +850 12 3162 44 +810 212 3161 25 +300 803 3160 71 +243 731 3159 49 +432 620 3158 43 +663 467 3157 80 +417 485 3156 5 +29 70 3155 46 +955 945 3154 19 +915 309 3153 50 +799 190 3152 36 +409 533 3151 4 +72 226 3150 51 +110 53 3149 5 +153 632 3148 81 +981 755 3147 76 +415 584 3146 24 +124 268 3145 38 +636 697 3144 7 +118 132 3143 3 +656 328 3142 11 +307 529 3141 39 +172 453 3140 33 +420 245 3139 96 +877 42 3138 95 +171 522 3137 17 +315 858 3136 56 +571 312 3135 29 +564 35 3134 48 +803 922 3133 51 +798 726 3132 46 +76 53 3131 34 +208 374 3130 13 +203 5 3129 75 +519 783 3128 54 +663 607 3127 70 +546 273 3126 85 +277 804 3125 74 +112 969 3124 0 +196 55 3123 76 +673 113 3122 0 +678 213 3121 72 +369 383 3120 86 +221 208 3119 0 +176 837 3118 68 +334 850 3117 85 +469 112 3116 11 +834 736 3115 26 +914 246 3114 16 +942 755 3113 91 +899 282 3112 52 +829 854 3111 99 +175 862 3110 30 +371 321 3109 14 +986 828 3108 4 +738 737 3107 84 +375 848 3106 86 +489 104 3105 63 +490 248 3104 92 +473 393 3103 97 +427 528 3102 4 +992 685 3101 7 +541 161 3100 65 +492 102 3099 80 +90 202 3098 38 +889 976 3097 24 +744 230 3096 36 +856 714 3095 88 +855 948 3094 99 +864 929 3093 1 +842 971 3092 4 +524 416 3091 43 +58 849 3090 45 +899 420 3089 4 +226 135 3088 40 +746 886 3087 20 +516 476 3086 14 +765 887 3085 88 +18 981 3084 0 +958 971 3083 99 +555 610 3082 2 +566 984 3081 31 +429 401 3080 46 +284 646 3079 15 +249 200 3078 67 +410 56 3077 47 +588 257 3076 22 +906 886 3075 75 +9 10 3074 74 +360 968 3073 6 +626 704 3072 40 +582 851 3071 98 +755 307 3070 13 +445 484 3069 14 +144 193 3068 3 +798 250 3067 83 +370 478 3066 82 +876 3 3065 68 +41 686 3064 89 +264 658 3063 64 +852 413 3062 73 +543 851 3061 4 +822 992 3060 82 +291 110 3059 30 +943 195 3058 30 +771 17 3057 34 +474 138 3056 42 +317 786 3055 49 +28 248 3054 83 +244 913 3053 77 +561 690 3052 41 +859 216 3051 30 +881 517 3050 72 +915 8 3049 53 +177 954 3048 34 +879 917 3047 17 +352 934 3046 29 +537 659 3045 15 +334 57 3044 28 +222 366 3043 78 +474 102 3042 68 +698 588 3041 70 +508 189 3040 97 +53 183 3039 96 +37 176 3038 73 +982 874 3037 29 +275 139 3036 52 +602 869 3035 81 +691 504 3034 20 +263 100 3033 11 +514 980 3032 74 +398 725 3031 77 +5 10 3030 19 +7 228 3029 45 +301 439 3028 1 +734 771 3027 5 +270 711 3026 70 +364 611 3025 67 +403 91 3024 91 +120 363 3023 42 +254 972 3022 74 +714 585 3021 11 +781 734 3020 39 +788 439 3019 99 +668 960 3018 70 +59 348 3017 56 +100 33 3016 46 +519 762 3015 90 +728 483 3014 96 +390 678 3013 28 +387 633 3012 86 +850 722 3011 54 +295 395 3010 93 +478 291 3009 99 +611 138 3008 12 +315 103 3007 60 +271 557 3006 95 +278 945 3005 58 +805 677 3004 79 +44 418 3003 33 +910 325 3002 0 +327 607 3001 53 +103 940 3000 55 +153 872 2999 81 +34 512 2998 86 +546 648 2997 29 +611 379 2996 4 +268 788 2995 99 +258 453 2994 47 +92 334 2993 76 +717 466 2992 13 +667 981 2991 58 +67 737 2990 22 +359 950 2989 95 +863 570 2988 11 +269 252 2987 48 +590 51 2986 93 +335 519 2985 34 +118 712 2984 0 +868 626 2983 16 +484 550 2982 37 +244 360 2981 5 +786 272 2980 59 +380 832 2979 70 +317 630 2978 49 +200 553 2977 59 +532 591 2976 67 +807 333 2975 25 +85 843 2974 21 +76 790 2973 25 +189 324 2972 38 +88 451 2971 23 +440 891 2970 45 +201 212 2969 40 +76 902 2968 6 +962 915 2967 11 +257 423 2966 66 +489 38 2965 72 +52 966 2964 72 +466 866 2963 0 +873 144 2962 88 +560 781 2961 10 +679 52 2960 64 +310 342 2959 23 +986 946 2958 12 +491 448 2957 11 +385 943 2956 70 +72 3 2955 76 +99 713 2954 43 +722 120 2953 58 +362 786 2952 59 +729 452 2951 31 +709 409 2950 88 +396 112 2949 36 +497 11 2948 32 +505 408 2947 49 +940 937 2946 10 +289 331 2945 31 +592 850 2944 97 +334 993 2943 37 +333 279 2942 35 +43 432 2941 63 +297 511 2940 1 +101 45 2939 31 +602 827 2938 89 +471 390 2937 99 +605 792 2936 56 +480 340 2935 65 +857 594 2934 69 +713 17 2933 25 +847 726 2932 0 +920 613 2931 29 +466 706 2930 74 +218 413 2929 19 +436 907 2928 49 +598 427 2927 13 +451 914 2926 86 +746 954 2925 12 +576 437 2924 62 +291 257 2923 14 +112 710 2922 86 +906 544 2921 92 +292 549 2920 45 +506 697 2919 24 +479 368 2918 78 +513 264 2917 83 +959 740 2916 14 +516 501 2915 70 +180 479 2914 16 +547 278 2913 28 +166 938 2912 17 +994 472 2911 20 +852 207 2910 61 +329 465 2909 78 +103 943 2908 2 +524 691 2907 96 +238 441 2906 55 +22 535 2905 44 +201 884 2904 33 +339 106 2903 63 +465 972 2902 38 +265 591 2901 17 +741 828 2900 14 +522 758 2899 52 +251 60 2898 22 +250 413 2897 57 +906 109 2896 28 +651 107 2895 21 +777 703 2894 82 +134 251 2893 86 +380 209 2892 87 +763 29 2891 19 +69 618 2890 52 +698 297 2889 21 +647 646 2888 27 +303 294 2887 0 +2 68 2886 34 +404 396 2885 25 +451 958 2884 87 +42 987 2883 64 +179 674 2882 75 +411 675 2881 61 +321 304 2880 69 +650 948 2879 37 +352 269 2878 5 +225 656 2877 34 +672 89 2876 30 +437 380 2875 59 +970 231 2874 95 +313 888 2873 40 +999 136 2872 86 +370 922 2871 76 +355 323 2870 9 +679 319 2869 67 +613 707 2868 29 +566 43 2867 12 +709 701 2866 55 +148 646 2865 23 +342 543 2864 46 +751 546 2863 65 +214 93 2862 31 +598 678 2861 62 +4 419 2860 1 +612 372 2859 67 +663 171 2858 6 +341 573 2857 4 +55 318 2856 85 +102 767 2855 56 +996 809 2854 80 +453 343 2853 59 +415 686 2852 53 +258 612 2851 61 +47 338 2850 59 +200 610 2849 39 +598 19 2848 94 +254 188 2847 32 +550 296 2846 28 +958 754 2845 95 +466 214 2844 10 +657 53 2843 54 +73 921 2842 3 +274 22 2841 15 +728 201 2840 21 +590 444 2839 84 +831 626 2838 60 +891 35 2837 34 +541 333 2836 70 +540 846 2835 59 +160 563 2834 49 +132 505 2833 80 +899 881 2832 58 +820 945 2831 79 +757 363 2830 54 +817 245 2829 13 +590 258 2828 75 +702 639 2827 93 +486 111 2826 34 +283 99 2825 0 +57 683 2824 37 +623 224 2823 2 +936 785 2822 23 +581 253 2821 7 +118 407 2820 6 +986 378 2819 93 +618 819 2818 22 +528 589 2817 88 +12 348 2816 21 +416 621 2815 20 +458 351 2814 22 +439 794 2813 43 +532 154 2812 68 +845 15 2811 35 +29 123 2810 46 +559 712 2809 13 +229 339 2808 36 +241 671 2807 9 +726 13 2806 51 +270 977 2805 59 +557 791 2804 95 +639 746 2803 1 +139 332 2802 90 +892 891 2801 68 +410 331 2800 81 +372 763 2799 47 +668 278 2798 32 +658 574 2797 98 +35 920 2796 51 +185 638 2795 45 +44 938 2794 71 +413 111 2793 91 +441 220 2792 50 +559 871 2791 24 +568 345 2790 48 +484 141 2789 3 +703 340 2788 70 +654 473 2787 0 +281 59 2786 62 +700 743 2785 85 +826 793 2784 14 +891 418 2783 63 +349 253 2782 97 +525 764 2781 88 +204 443 2780 99 +800 333 2779 8 +867 694 2778 78 +414 387 2777 4 +315 772 2776 37 +949 708 2775 58 +375 510 2774 87 +164 658 2773 93 +489 89 2772 54 +320 892 2771 82 +110 906 2770 32 +639 302 2769 40 +307 731 2768 93 +615 677 2767 45 +63 792 2766 9 +198 706 2765 36 +852 939 2764 57 +568 393 2763 21 +197 718 2762 67 +985 502 2761 16 +603 917 2760 21 +571 470 2759 47 +54 479 2758 33 +885 354 2757 69 +85 733 2756 55 +767 791 2755 86 +545 363 2754 34 +674 535 2753 28 +215 505 2752 37 +585 959 2751 21 +446 739 2750 38 +990 138 2749 3 +125 639 2748 51 +620 140 2747 16 +942 686 2746 79 +427 518 2745 31 +828 62 2744 22 +29 912 2743 87 +546 159 2742 45 +219 830 2741 63 +600 350 2740 13 +498 514 2739 45 +499 348 2738 86 +453 369 2737 50 +167 481 2736 67 +456 96 2735 51 +150 350 2734 59 +753 412 2733 79 +328 828 2732 48 +480 492 2731 32 +835 682 2730 61 +165 590 2729 10 +979 360 2728 99 +887 826 2727 4 +384 163 2726 28 +746 915 2725 71 +937 801 2724 30 +584 314 2723 39 +336 156 2722 42 +809 708 2721 84 +91 516 2720 64 +230 102 2719 67 +534 954 2718 18 +662 758 2717 9 +247 574 2716 50 +114 405 2715 63 +486 908 2714 80 +158 972 2713 35 +447 575 2712 24 +191 204 2711 52 +414 973 2710 71 +147 483 2709 86 +195 95 2708 69 +184 588 2707 87 +169 864 2706 41 +496 830 2705 13 +935 454 2704 62 +397 105 2703 32 +370 721 2702 71 +230 809 2701 25 +490 856 2700 77 +388 165 2699 26 +507 824 2698 95 +723 457 2697 1 +34 281 2696 1 +375 504 2695 67 +348 300 2694 56 +384 617 2693 53 +912 454 2692 2 +953 478 2691 14 +690 510 2690 74 +341 314 2689 10 +366 940 2688 88 +176 996 2687 78 +776 342 2686 68 +203 111 2685 65 +683 22 2684 2 +162 512 2683 96 +975 886 2682 47 +968 399 2681 95 +196 639 2680 26 +373 220 2679 34 +943 98 2678 97 +654 93 2677 19 +230 31 2676 39 +89 631 2675 57 +510 63 2674 51 +625 491 2673 52 +487 513 2672 18 +760 696 2671 0 +419 912 2670 77 +122 375 2669 82 +4 783 2668 42 +62 791 2667 28 +400 826 2666 42 +567 53 2665 14 +571 998 2664 57 +978 334 2663 88 +816 178 2662 13 +783 235 2661 72 +537 949 2660 34 +591 392 2659 29 +992 140 2658 11 +964 864 2657 94 +773 283 2656 66 +54 561 2655 83 +663 694 2654 99 +156 745 2653 59 +943 411 2652 16 +285 386 2651 3 +557 43 2650 24 +251 179 2649 94 +276 176 2648 59 +581 279 2647 2 +721 829 2646 19 +866 836 2645 71 +949 402 2644 39 +334 431 2643 50 +25 128 2642 21 +342 786 2641 65 +864 299 2640 72 +3 348 2639 30 +896 570 2638 97 +449 836 2637 69 +993 472 2636 85 +434 327 2635 85 +970 883 2634 91 +302 294 2633 61 +342 555 2632 30 +487 928 2631 68 +951 423 2630 47 +777 329 2629 86 +733 280 2628 10 +364 835 2627 44 +144 3 2626 45 +444 937 2625 55 +588 303 2624 46 +739 305 2623 66 +626 626 2622 96 +505 204 2621 85 +93 617 2620 53 +48 754 2619 17 +445 659 2618 4 +831 990 2617 36 +66 897 2616 22 +634 95 2615 69 +997 795 2614 85 +678 707 2613 84 +422 106 2612 11 +586 318 2611 12 +862 361 2610 41 +95 129 2609 4 +668 675 2608 60 +93 148 2607 61 +801 520 2606 76 +300 844 2605 43 +87 6 2604 63 +601 735 2603 31 +787 992 2602 25 +956 709 2601 83 +232 366 2600 72 +454 441 2599 76 +526 990 2598 42 +628 848 2597 57 +676 333 2596 29 +837 795 2595 50 +270 317 2594 21 +743 62 2593 48 +283 420 2592 81 +342 111 2591 83 +925 957 2590 72 +451 339 2589 77 +142 852 2588 92 +514 282 2587 89 +538 791 2586 95 +477 287 2585 83 +255 726 2584 56 +642 672 2583 52 +309 983 2582 45 +153 105 2581 94 +617 946 2580 41 +487 850 2579 47 +569 29 2578 30 +490 945 2577 62 +504 114 2576 97 +561 271 2575 6 +54 39 2574 22 +688 67 2573 61 +877 518 2572 33 +159 524 2571 15 +96 942 2570 53 +820 165 2569 13 +84 681 2568 91 +831 651 2567 7 +842 915 2566 98 +231 839 2565 94 +972 609 2564 50 +548 279 2563 36 +994 177 2562 81 +581 619 2561 71 +777 405 2560 6 +483 213 2559 27 +30 838 2558 73 +736 91 2557 25 +75 44 2556 98 +229 435 2555 61 +329 141 2554 25 +101 554 2553 42 +558 91 2552 55 +213 656 2551 41 +191 786 2550 80 +375 540 2549 29 +746 483 2548 45 +47 263 2547 29 +608 378 2546 66 +294 351 2545 84 +587 835 2544 90 +462 869 2543 22 +435 141 2542 54 +870 609 2541 34 +246 509 2540 2 +56 841 2539 81 +219 158 2538 62 +885 634 2537 69 +26 814 2536 43 +515 945 2535 31 +966 672 2534 70 +728 685 2533 12 +531 198 2532 2 +100 322 2531 56 +667 206 2530 62 +682 186 2529 18 +523 931 2528 83 +820 258 2527 33 +868 125 2526 85 +273 607 2525 51 +987 582 2524 54 +486 96 2523 23 +876 462 2522 19 +115 941 2521 43 +20 434 2520 43 +254 352 2519 98 +672 502 2518 15 +133 475 2517 70 +518 347 2516 95 +24 961 2515 59 +486 312 2514 28 +634 40 2513 50 +521 765 2512 61 +506 999 2511 76 +81 447 2510 9 +850 826 2509 76 +26 455 2508 58 +127 751 2507 53 +386 357 2506 61 +649 308 2505 49 +272 785 2504 53 +274 889 2503 85 +766 849 2502 11 +552 666 2501 1 +621 328 2500 42 +370 184 2499 23 +703 41 2498 82 +394 925 2497 89 +48 120 2496 74 +522 956 2495 73 +896 685 2494 37 +39 738 2493 99 +183 98 2492 50 +338 589 2491 21 +143 194 2490 93 +143 407 2489 25 +116 925 2488 66 +804 157 2487 30 +164 4 2486 34 +270 359 2485 52 +946 379 2484 62 +640 488 2483 85 +509 294 2482 85 +395 282 2481 84 +786 681 2480 19 +482 583 2479 0 +767 357 2478 2 +152 963 2477 31 +645 818 2476 64 +979 900 2475 89 +890 769 2474 32 +194 0 2473 30 +12 11 2472 13 +601 650 2471 11 +97 195 2470 60 +225 973 2469 30 +393 714 2468 71 +145 672 2467 61 +918 746 2466 50 +130 570 2465 66 +769 16 2464 8 +989 176 2463 69 +361 16 2462 18 +454 505 2461 41 +221 303 2460 50 +259 590 2459 87 +42 98 2458 83 +926 108 2457 24 +175 841 2456 22 +553 576 2455 78 +840 392 2454 36 +159 515 2453 78 +511 770 2452 62 +202 907 2451 90 +712 631 2450 23 +492 40 2449 96 +989 583 2448 21 +267 21 2447 11 +265 439 2446 75 +184 425 2445 62 +876 581 2444 71 +744 152 2443 68 +863 721 2442 64 +276 672 2441 30 +590 271 2440 48 +457 745 2439 22 +561 100 2438 50 +581 365 2437 72 +14 128 2436 0 +844 908 2435 8 +429 31 2434 30 +430 33 2433 13 +49 339 2432 88 +401 819 2431 58 +525 269 2430 68 +644 717 2429 13 +735 780 2428 89 +237 720 2427 98 +219 919 2426 56 +876 774 2425 16 +998 174 2424 41 +693 251 2423 99 +520 293 2422 38 +550 901 2421 64 +551 551 2420 87 +936 238 2419 88 +59 914 2418 90 +801 412 2417 49 +145 397 2416 1 +599 754 2415 34 +922 416 2414 87 +957 617 2413 30 +391 733 2412 17 +350 772 2411 96 +313 994 2410 99 +323 972 2409 61 +502 411 2408 87 +15 480 2407 25 +642 674 2406 65 +338 465 2405 54 +798 572 2404 67 +884 131 2403 96 +961 203 2402 56 +777 971 2401 4 +21 383 2400 3 +560 737 2399 98 +931 618 2398 82 +805 602 2397 48 +209 110 2396 37 +892 868 2395 30 +440 711 2394 53 +928 399 2393 91 +231 524 2392 92 +588 4 2391 18 +645 47 2390 75 +118 168 2389 46 +15 334 2388 62 +492 114 2387 12 +241 67 2386 59 +156 765 2385 31 +312 625 2384 45 +875 990 2383 51 +519 740 2382 69 +956 427 2381 64 +879 294 2380 94 +833 831 2379 52 +219 504 2378 10 +47 529 2377 52 +302 278 2376 25 +139 865 2375 8 +634 938 2374 84 +250 816 2373 43 +312 53 2372 35 +132 699 2371 56 +463 416 2370 7 +327 423 2369 4 +974 579 2368 61 +250 271 2367 17 +413 166 2366 74 +926 239 2365 16 +122 408 2364 50 +763 81 2363 38 +353 792 2362 93 +282 485 2361 18 +993 32 2360 66 +843 431 2359 13 +308 441 2358 35 +105 427 2357 72 +926 581 2356 83 +831 658 2355 48 +326 120 2354 80 +289 446 2353 35 +306 757 2352 41 +453 511 2351 7 +601 532 2350 28 +989 784 2349 15 +13 628 2348 53 +846 887 2347 20 +923 350 2346 17 +538 681 2345 9 +673 445 2344 50 +688 948 2343 3 +246 339 2342 98 +978 780 2341 85 +748 139 2340 85 +155 614 2339 61 +741 332 2338 97 +536 24 2337 16 +668 83 2336 92 +235 589 2335 38 +497 467 2334 86 +609 54 2333 98 +558 129 2332 44 +641 1 2331 26 +524 240 2330 22 +282 635 2329 59 +308 808 2328 41 +940 244 2327 20 +493 538 2326 86 +122 520 2325 43 +412 878 2324 73 +925 544 2323 88 +127 173 2322 5 +760 38 2321 91 +605 637 2320 11 +826 178 2319 24 +564 210 2318 97 +705 336 2317 36 +18 435 2316 44 +641 693 2315 37 +334 850 2314 71 +370 837 2313 48 +134 133 2312 79 +401 800 2311 36 +459 874 2310 15 +967 268 2309 77 +873 605 2308 26 +901 921 2307 85 +741 75 2306 68 +843 661 2305 37 +13 223 2304 30 +704 688 2303 96 +333 431 2302 23 +925 211 2301 73 +606 375 2300 94 +662 518 2299 49 +684 401 2298 9 +846 172 2297 97 +414 310 2296 16 +437 70 2295 89 +535 343 2294 83 +257 727 2293 30 +219 502 2292 37 +836 791 2291 40 +857 451 2290 31 +116 396 2289 94 +229 122 2288 97 +861 812 2287 83 +240 262 2286 43 +726 67 2285 97 +615 521 2284 90 +224 937 2283 27 +711 962 2282 3 +340 89 2281 38 +54 374 2280 97 +274 965 2279 74 +309 140 2278 88 +549 405 2277 36 +194 455 2276 62 +546 74 2275 51 +583 624 2274 11 +975 239 2273 39 +873 655 2272 51 +714 403 2271 37 +409 238 2270 28 +824 854 2269 77 +735 519 2268 96 +949 745 2267 76 +381 108 2266 35 +449 402 2265 64 +384 720 2264 96 +584 877 2263 60 +251 142 2262 10 +165 84 2261 15 +384 506 2260 30 +334 814 2259 58 +773 204 2258 8 +637 404 2257 78 +706 706 2256 56 +681 685 2255 93 +842 353 2254 6 +734 507 2253 80 +57 942 2252 33 +578 854 2251 8 +692 720 2250 78 +609 494 2249 4 +799 304 2248 56 +697 217 2247 13 +20 635 2246 93 +331 867 2245 2 +846 264 2244 83 +564 467 2243 10 +87 247 2242 67 +134 303 2241 47 +225 732 2240 88 +190 487 2239 8 +86 425 2238 80 +581 205 2237 10 +768 906 2236 67 +602 185 2235 68 +797 730 2234 48 +219 430 2233 28 +943 197 2232 47 +571 593 2231 95 +244 803 2230 90 +62 272 2229 3 +220 707 2228 10 +299 424 2227 50 +720 987 2226 81 +454 203 2225 16 +300 203 2224 80 +233 804 2223 57 +604 523 2222 27 +790 44 2221 37 +530 873 2220 32 +564 932 2219 18 +283 597 2218 84 +436 692 2217 92 +784 646 2216 57 +0 360 2215 26 +398 227 2214 15 +280 301 2213 6 +479 903 2212 62 +171 46 2211 81 +940 143 2210 25 +334 340 2209 96 +905 921 2208 28 +46 341 2207 84 +285 313 2206 65 +133 111 2205 78 +926 87 2204 60 +397 438 2203 11 +857 814 2202 80 +902 554 2201 30 +802 294 2200 23 +419 684 2199 60 +579 435 2198 42 +28 193 2197 85 +201 869 2196 76 +24 181 2195 15 +649 483 2194 20 +623 316 2193 52 +260 493 2192 54 +259 77 2191 95 +610 623 2190 10 +248 177 2189 38 +242 570 2188 83 +324 97 2187 55 +687 608 2186 82 +698 945 2185 17 +166 678 2184 37 +823 988 2183 2 +416 585 2182 36 +453 854 2181 0 +446 717 2180 64 +606 543 2179 36 +472 288 2178 0 +489 724 2177 91 +662 649 2176 63 +267 802 2175 98 +689 349 2174 53 +402 663 2173 34 +731 361 2172 40 +137 351 2171 96 +174 288 2170 0 +254 355 2169 84 +564 87 2168 13 +74 281 2167 98 +846 647 2166 82 +453 457 2165 39 +685 188 2164 57 +302 936 2163 28 +10 444 2162 67 +62 956 2161 59 +932 166 2160 96 +267 706 2159 91 +806 150 2158 68 +634 156 2157 48 +190 432 2156 22 +268 817 2155 39 +252 290 2154 76 +491 615 2153 38 +487 77 2152 29 +789 630 2151 94 +459 43 2150 13 +556 229 2149 66 +993 200 2148 46 +724 261 2147 17 +615 835 2146 44 +526 625 2145 92 +674 384 2144 1 +537 91 2143 76 +447 344 2142 0 +586 817 2141 69 +813 464 2140 32 +29 203 2139 90 +939 289 2138 56 +425 728 2137 26 +209 522 2136 10 +240 904 2135 8 +293 256 2134 85 +746 756 2133 13 +527 305 2132 9 +352 368 2131 86 +261 426 2130 77 +914 341 2129 78 +561 292 2128 9 +205 160 2127 51 +617 20 2126 21 +648 236 2125 96 +499 714 2124 94 +450 47 2123 54 +937 229 2122 21 +941 87 2121 17 +85 988 2120 9 +48 693 2119 34 +132 577 2118 35 +139 297 2117 35 +783 246 2116 58 +522 21 2115 96 +667 401 2114 14 +817 328 2113 4 +141 42 2112 51 +99 84 2111 99 +295 744 2110 85 +116 993 2109 3 +280 997 2108 91 +50 767 2107 99 +225 619 2106 35 +620 820 2105 26 +72 99 2104 85 +285 536 2103 84 +958 517 2102 67 +340 139 2101 4 +750 820 2100 80 +996 120 2099 17 +229 923 2098 83 +148 636 2097 23 +798 94 2096 82 +721 406 2095 60 +562 5 2094 54 +19 173 2093 78 +377 634 2092 32 +319 238 2091 61 +699 624 2090 58 +196 343 2089 75 +286 605 2088 76 +542 405 2087 8 +687 218 2086 34 +401 58 2085 7 +831 759 2084 15 +538 460 2083 54 +396 708 2082 64 +613 28 2081 5 +281 836 2080 61 +737 987 2079 50 +199 685 2078 90 +186 731 2077 74 +160 272 2076 85 +298 919 2075 28 +299 615 2074 56 +751 901 2073 29 +680 582 2072 14 +192 439 2071 78 +849 116 2070 33 +301 593 2069 54 +953 165 2068 53 +459 889 2067 1 +353 569 2066 2 +303 715 2065 86 +714 276 2064 99 +318 150 2063 54 +143 359 2062 7 +323 450 2061 48 +522 787 2060 34 +428 6 2059 54 +275 524 2058 34 +319 986 2057 49 +853 164 2056 10 +438 863 2055 4 +126 451 2054 58 +790 476 2053 39 +908 583 2052 17 +662 145 2051 82 +781 796 2050 80 +481 198 2049 9 +538 854 2048 15 +822 387 2047 95 +301 56 2046 46 +411 460 2045 41 +975 193 2044 31 +893 221 2043 33 +437 354 2042 88 +349 19 2041 24 +597 705 2040 88 +343 942 2039 30 +466 196 2038 94 +330 489 2037 71 +596 51 2036 52 +266 101 2035 88 +972 977 2034 43 +866 453 2033 8 +334 635 2032 45 +314 365 2031 8 +762 580 2030 75 +746 356 2029 25 +706 227 2028 87 +438 195 2027 13 +949 631 2026 73 +124 453 2025 33 +524 353 2024 29 +817 626 2023 10 +270 367 2022 53 +784 336 2021 2 +224 498 2020 55 +129 376 2019 1 +32 740 2018 4 +563 402 2017 26 +178 403 2016 48 +99 35 2015 82 +727 188 2014 59 +259 573 2013 70 +30 511 2012 54 +838 469 2011 48 +121 535 2010 55 +635 975 2009 9 +338 773 2008 9 +998 777 2007 46 +367 664 2006 38 +847 225 2005 7 +614 892 2004 37 +62 160 2003 46 +42 60 2002 22 +934 926 2001 19 +559 465 2000 71 +202 997 1999 48 +995 629 1998 29 +113 82 1997 34 +438 306 1996 63 +333 707 1995 52 +731 904 1994 23 +99 238 1993 55 +133 36 1992 1 +461 476 1991 10 +467 230 1990 37 +368 188 1989 35 +546 957 1988 20 +776 709 1987 88 +599 110 1986 67 +802 287 1985 10 +666 679 1984 60 +201 533 1983 63 +560 910 1982 96 +245 733 1981 67 +42 17 1980 99 +231 150 1979 9 +247 324 1978 82 +599 207 1977 77 +822 569 1976 17 +607 503 1975 79 +146 969 1974 13 +622 666 1973 46 +177 293 1972 64 +715 678 1971 31 +867 894 1970 20 +825 277 1969 81 +117 51 1968 98 +637 593 1967 64 +66 379 1966 77 +533 661 1965 21 +303 670 1964 46 +372 823 1963 52 +615 326 1962 44 +783 111 1961 46 +617 392 1960 84 +225 827 1959 4 +458 335 1958 70 +213 870 1957 48 +718 562 1956 57 +990 753 1955 53 +847 937 1954 23 +497 79 1953 93 +214 983 1952 75 +718 613 1951 83 +564 805 1950 16 +492 335 1949 39 +464 227 1948 76 +308 909 1947 24 +809 38 1946 49 +816 302 1945 72 +858 298 1944 14 +95 173 1943 35 +370 925 1942 28 +807 665 1941 49 +470 773 1940 15 +108 625 1939 7 +317 521 1938 2 +871 750 1937 15 +735 766 1936 49 +3 585 1935 99 +124 792 1934 95 +248 68 1933 76 +259 786 1932 72 +891 342 1931 56 +148 81 1930 33 +104 44 1929 36 +770 871 1928 79 +984 657 1927 44 +181 504 1926 13 +792 35 1925 73 +724 195 1924 87 +281 38 1923 87 +444 161 1922 98 +260 225 1921 36 +36 974 1920 74 +172 571 1919 4 +214 344 1918 33 +153 310 1917 78 +468 403 1916 80 +840 853 1915 38 +156 2 1914 6 +876 887 1913 44 +935 620 1912 83 +250 624 1911 18 +403 699 1910 22 +227 709 1909 86 +33 548 1908 95 +907 982 1907 6 +550 413 1906 68 +850 321 1905 62 +114 624 1904 68 +267 605 1903 27 +996 654 1902 94 +924 959 1901 68 +990 360 1900 84 +161 905 1899 17 +565 897 1898 19 +568 376 1897 12 +92 56 1896 35 +697 943 1895 69 +19 404 1894 73 +950 338 1893 84 +695 256 1892 27 +598 837 1891 7 +454 672 1890 93 +7 980 1889 82 +520 68 1888 59 +320 769 1887 99 +112 657 1886 47 +539 962 1885 39 +65 889 1884 67 +82 577 1883 6 +418 197 1882 25 +164 138 1881 9 +691 104 1880 14 +912 233 1879 44 +299 598 1878 48 +111 520 1877 20 +694 82 1876 20 +73 716 1875 57 +312 609 1874 47 +379 814 1873 98 +58 157 1872 66 +34 952 1871 25 +871 697 1870 47 +635 959 1869 77 +77 286 1868 61 +438 993 1867 18 +365 634 1866 41 +106 99 1865 62 +794 490 1864 76 +656 319 1863 93 +205 409 1862 32 +254 780 1861 2 +738 694 1860 16 +673 165 1859 23 +293 425 1858 55 +358 770 1857 63 +534 796 1856 7 +608 859 1855 25 +171 829 1854 31 +909 610 1853 13 +629 297 1852 45 +86 861 1851 95 +528 927 1850 51 +740 677 1849 6 +655 918 1848 38 +973 566 1847 93 +936 813 1846 82 +30 946 1845 92 +218 174 1844 43 +313 686 1843 26 +435 500 1842 28 +933 434 1841 54 +249 451 1840 55 +759 684 1839 78 +351 446 1838 8 +753 110 1837 68 +866 897 1836 3 +772 488 1835 90 +487 175 1834 81 +186 982 1833 90 +65 737 1832 87 +983 984 1831 50 +766 769 1830 68 +238 704 1829 49 +335 402 1828 40 +212 644 1827 59 +408 131 1826 88 +313 93 1825 9 +193 908 1824 28 +244 26 1823 30 +752 376 1822 12 +215 817 1821 8 +65 194 1820 21 +302 82 1819 52 +757 809 1818 90 +513 711 1817 12 +37 793 1816 80 +185 808 1815 9 +882 985 1814 12 +649 179 1813 94 +558 39 1812 49 +623 864 1811 53 +111 689 1810 14 +272 624 1809 76 +98 780 1808 54 +917 318 1807 24 +985 708 1806 47 +822 974 1805 85 +806 172 1804 30 +139 455 1803 23 +175 955 1802 9 +174 387 1801 93 +65 386 1800 51 +844 218 1799 83 +461 301 1798 17 +610 767 1797 18 +733 623 1796 93 +802 549 1795 16 +716 70 1794 1 +499 141 1793 66 +568 155 1792 96 +1 423 1791 0 +167 672 1790 10 +916 665 1789 22 +534 992 1788 38 +144 248 1787 85 +73 770 1786 87 +479 145 1785 93 +929 350 1784 8 +985 701 1783 21 +732 963 1782 93 +751 891 1781 56 +7 888 1780 83 +672 837 1779 25 +744 531 1778 38 +477 975 1777 38 +625 944 1776 7 +794 845 1775 59 +648 868 1774 54 +738 286 1773 94 +72 363 1772 25 +2 733 1771 98 +50 583 1770 74 +306 867 1769 33 +556 993 1768 92 +30 318 1767 26 +99 477 1766 85 +976 43 1765 83 +582 605 1764 14 +922 691 1763 91 +629 272 1762 66 +150 236 1761 7 +715 409 1760 95 +874 406 1759 74 +674 660 1758 74 +841 415 1757 52 +433 21 1756 93 +438 684 1755 12 +914 235 1754 39 +419 244 1753 65 +35 595 1752 29 +826 118 1751 47 +2 206 1750 43 +746 995 1749 84 +245 223 1748 20 +393 595 1747 83 +336 807 1746 40 +449 728 1745 99 +990 734 1744 52 +649 366 1743 49 +476 813 1742 38 +912 44 1741 20 +211 594 1740 82 +771 640 1739 25 +628 366 1738 50 +787 425 1737 85 +78 412 1736 5 +994 470 1735 88 +368 29 1734 45 +552 111 1733 34 +769 173 1732 17 +449 385 1731 56 +954 567 1730 70 +273 755 1729 43 +941 649 1728 14 +12 793 1727 84 +942 170 1726 70 +441 428 1725 8 +917 117 1724 62 +937 167 1723 81 +788 609 1722 78 +818 863 1721 32 +811 261 1720 49 +105 296 1719 68 +855 301 1718 33 +623 132 1717 92 +742 624 1716 7 +310 457 1715 50 +950 811 1714 52 +558 32 1713 97 +746 462 1712 14 +601 825 1711 96 +964 814 1710 0 +994 348 1709 70 +168 403 1708 25 +508 858 1707 23 +166 569 1706 88 +646 976 1705 43 +779 544 1704 35 +569 829 1703 39 +637 180 1702 81 +10 962 1701 14 +466 301 1700 63 +944 455 1699 96 +544 17 1698 82 +289 351 1697 66 +592 448 1696 34 +432 72 1695 51 +715 967 1694 86 +649 579 1693 21 +218 667 1692 93 +660 507 1691 62 +845 666 1690 54 +438 143 1689 52 +665 166 1688 40 +903 317 1687 25 +376 823 1686 69 +104 651 1685 16 +388 657 1684 71 +912 279 1683 6 +159 303 1682 43 +840 82 1681 55 +522 23 1680 81 +977 121 1679 40 +848 144 1678 77 +493 558 1677 76 +171 536 1676 52 +994 443 1675 27 +378 651 1674 71 +975 635 1673 47 +220 872 1672 75 +59 742 1671 31 +901 407 1670 31 +976 634 1669 54 +586 10 1668 12 +22 234 1667 35 +93 255 1666 32 +792 555 1665 17 +15 240 1664 61 +762 723 1663 40 +130 433 1662 75 +335 0 1661 16 +772 772 1660 15 +623 415 1659 92 +776 774 1658 39 +979 32 1657 56 +699 145 1656 92 +315 561 1655 30 +516 212 1654 77 +290 648 1653 25 +432 593 1652 63 +227 2 1651 79 +356 233 1650 56 +641 534 1649 14 +742 826 1648 84 +887 634 1647 79 +584 628 1646 28 +348 524 1645 38 +563 523 1644 79 +55 620 1643 22 +590 838 1642 85 +769 231 1641 20 +698 414 1640 87 +707 300 1639 71 +191 51 1638 89 +6 516 1637 85 +103 896 1636 30 +1 585 1635 23 +902 572 1634 78 +782 368 1633 50 +606 653 1632 46 +816 333 1631 82 +113 155 1630 7 +249 815 1629 99 +534 44 1628 51 +620 551 1627 18 +310 67 1626 90 +12 451 1625 10 +204 276 1624 9 +714 42 1623 11 +320 644 1622 17 +177 750 1621 79 +339 79 1620 70 +771 475 1619 86 +492 330 1618 71 +484 282 1617 91 +616 800 1616 30 +174 3 1615 29 +233 979 1614 80 +398 943 1613 49 +894 385 1612 39 +670 87 1611 14 +603 839 1610 83 +145 148 1609 56 +48 800 1608 27 +481 605 1607 0 +797 10 1606 86 +24 491 1605 44 +35 317 1604 94 +558 95 1603 83 +298 252 1602 50 +247 304 1601 22 +690 268 1600 6 +348 290 1599 45 +195 269 1598 9 +594 140 1597 56 +519 426 1596 68 +174 499 1595 77 +221 106 1594 98 +843 330 1593 47 +947 280 1592 25 +35 157 1591 5 +978 607 1590 55 +21 361 1589 34 +129 529 1588 15 +713 883 1587 60 +926 910 1586 7 +393 784 1585 34 +776 511 1584 95 +50 217 1583 37 +123 209 1582 89 +549 493 1581 91 +245 214 1580 5 +832 189 1579 95 +646 551 1578 89 +972 526 1577 41 +126 729 1576 78 +273 392 1575 53 +294 574 1574 61 +7 482 1573 72 +715 982 1572 92 +278 855 1571 57 +25 100 1570 30 +637 65 1569 41 +25 476 1568 18 +796 628 1567 67 +336 253 1566 84 +818 916 1565 85 +91 891 1564 97 +499 798 1563 28 +127 353 1562 29 +754 270 1561 43 +35 889 1560 25 +589 227 1559 38 +847 511 1558 61 +375 828 1557 22 +336 992 1556 45 +24 874 1555 51 +93 693 1554 72 +444 994 1553 59 +82 854 1552 37 +380 184 1551 37 +662 864 1550 71 +715 775 1549 44 +683 383 1548 74 +835 768 1547 47 +118 941 1546 3 +181 792 1545 31 +698 134 1544 93 +139 220 1543 64 +669 999 1542 36 +319 653 1541 70 +88 273 1540 71 +392 703 1539 94 +614 270 1538 3 +827 432 1537 84 +148 727 1536 71 +658 380 1535 93 +914 282 1534 48 +221 286 1533 55 +345 659 1532 46 +379 983 1531 35 +570 771 1530 23 +432 915 1529 69 +838 182 1528 77 +705 132 1527 78 +346 778 1526 67 +97 455 1525 48 +995 922 1524 74 +627 89 1523 69 +676 119 1522 87 +211 119 1521 96 +856 534 1520 80 +732 919 1519 13 +50 990 1518 59 +353 107 1517 13 +323 189 1516 35 +533 745 1515 24 +832 51 1514 10 +970 817 1513 36 +0 908 1512 95 +584 157 1511 46 +615 671 1510 35 +928 542 1509 12 +882 461 1508 68 +918 774 1507 69 +444 109 1506 3 +693 147 1505 79 +233 733 1504 70 +908 417 1503 86 +751 486 1502 96 +485 109 1501 41 +129 230 1500 96 +81 442 1499 68 +686 984 1498 4 +665 666 1497 96 +961 240 1496 47 +414 89 1495 75 +315 838 1494 45 +931 892 1493 32 +376 554 1492 15 +879 445 1491 26 +788 282 1490 35 +457 640 1489 4 +318 81 1488 39 +425 490 1487 2 +150 723 1486 70 +251 291 1485 54 +945 134 1484 9 +338 167 1483 38 +108 891 1482 55 +163 909 1481 49 +642 308 1480 9 +558 653 1479 33 +591 373 1478 13 +767 316 1477 89 +432 156 1476 27 +156 449 1475 89 +967 713 1474 30 +276 829 1473 60 +981 58 1472 22 +601 405 1471 94 +654 760 1470 52 +279 191 1469 8 +56 246 1468 96 +160 617 1467 82 +706 375 1466 33 +735 593 1465 27 +884 698 1464 18 +770 377 1463 69 +652 284 1462 29 +644 424 1461 38 +568 437 1460 94 +945 115 1459 37 +628 143 1458 22 +241 489 1457 89 +782 58 1456 45 +894 86 1455 97 +320 498 1454 85 +93 396 1453 11 +859 914 1452 11 +986 433 1451 0 +321 571 1450 7 +972 151 1449 62 +653 327 1448 31 +430 441 1447 38 +972 482 1446 45 +588 120 1445 88 +102 736 1444 57 +481 996 1443 22 +480 109 1442 23 +862 931 1441 87 +419 453 1440 66 +824 306 1439 34 +885 930 1438 31 +959 927 1437 22 +362 571 1436 45 +384 313 1435 38 +739 347 1434 48 +886 993 1433 62 +178 360 1432 0 +478 207 1431 61 +147 316 1430 44 +375 29 1429 59 +2 96 1428 93 +356 764 1427 92 +257 74 1426 59 +966 897 1425 97 +354 865 1424 64 +632 619 1423 85 +153 382 1422 70 +891 175 1421 69 +286 846 1420 33 +933 657 1419 77 +332 11 1418 37 +689 329 1417 64 +176 618 1416 9 +32 333 1415 29 +245 791 1414 61 +237 144 1413 72 +207 9 1412 47 +328 368 1411 26 +189 559 1410 60 +645 397 1409 35 +681 727 1408 60 +711 547 1407 64 +285 807 1406 51 +542 679 1405 14 +647 890 1404 78 +135 242 1403 0 +640 217 1402 2 +809 656 1401 87 +161 251 1400 13 +669 752 1399 54 +180 958 1398 96 +740 129 1397 97 +127 368 1396 42 +789 357 1395 74 +647 778 1394 89 +25 978 1393 51 +560 151 1392 49 +404 739 1391 83 +499 594 1390 64 +793 580 1389 49 +829 993 1388 48 +761 544 1387 44 +10 682 1386 61 +579 848 1385 33 +799 382 1384 14 +827 17 1383 62 +411 663 1382 46 +145 184 1381 15 +14 154 1380 90 +587 3 1379 70 +448 48 1378 96 +862 828 1377 6 +834 274 1376 75 +466 195 1375 43 +364 520 1374 78 +354 156 1373 97 +479 308 1372 41 +29 251 1371 26 +151 198 1370 13 +954 742 1369 42 +220 895 1368 13 +554 317 1367 58 +78 319 1366 2 +674 650 1365 36 +364 808 1364 10 +848 555 1363 0 +56 149 1362 87 +53 135 1361 44 +455 703 1360 87 +846 287 1359 19 +578 552 1358 73 +997 558 1357 66 +669 659 1356 47 +842 266 1355 40 +252 91 1354 31 +405 134 1353 51 +14 425 1352 79 +431 572 1351 0 +415 680 1350 59 +735 462 1349 60 +994 68 1348 26 +898 190 1347 58 +393 72 1346 32 +174 92 1345 82 +957 794 1344 58 +708 724 1343 84 +853 787 1342 39 +891 405 1341 58 +217 989 1340 1 +393 340 1339 68 +878 687 1338 74 +118 252 1337 9 +979 501 1336 50 +297 237 1335 21 +69 742 1334 21 +936 456 1333 24 +382 808 1332 85 +416 566 1331 96 +648 335 1330 67 +653 940 1329 82 +435 644 1328 51 +750 591 1327 76 +264 285 1326 13 +495 2 1325 68 +285 968 1324 22 +647 393 1323 13 +242 893 1322 55 +230 287 1321 96 +395 849 1320 76 +296 308 1319 99 +52 755 1318 21 +305 621 1317 68 +283 456 1316 48 +34 453 1315 76 +574 94 1314 20 +500 578 1313 63 +605 587 1312 40 +438 198 1311 1 +541 772 1310 83 +553 777 1309 9 +133 533 1308 24 +164 198 1307 74 +3 716 1306 2 +358 560 1305 24 +515 570 1304 45 +991 233 1303 7 +388 393 1302 89 +426 176 1301 16 +995 736 1300 89 +243 856 1299 98 +334 495 1298 42 +482 724 1297 96 +156 773 1296 16 +989 789 1295 64 +337 386 1294 84 +840 178 1293 52 +216 728 1292 60 +440 270 1291 96 +880 909 1290 43 +360 566 1289 75 +771 451 1288 90 +950 807 1287 85 +984 517 1286 32 +403 801 1285 16 +207 318 1284 65 +450 922 1283 49 +458 639 1282 62 +360 531 1281 77 +342 679 1280 56 +115 842 1279 51 +644 57 1278 58 +290 526 1277 82 +715 158 1276 96 +483 515 1275 58 +395 155 1274 19 +282 873 1273 75 +108 847 1272 99 +851 216 1271 9 +837 40 1270 1 +784 931 1269 22 +531 768 1268 47 +367 853 1267 35 +643 385 1266 57 +359 385 1265 23 +282 437 1264 8 +26 765 1263 11 +630 894 1262 17 +176 79 1261 25 +109 790 1260 1 +162 757 1259 5 +914 115 1258 25 +468 780 1257 16 +999 342 1256 72 +947 143 1255 28 +672 975 1254 7 +871 939 1253 25 +814 916 1252 39 +289 243 1251 45 +32 961 1250 6 +642 798 1249 94 +335 90 1248 24 +437 439 1247 44 +198 440 1246 46 +168 205 1245 5 +35 822 1244 27 +22 860 1243 80 +673 940 1242 5 +281 387 1241 52 +162 119 1240 25 +708 698 1239 39 +650 802 1238 30 +998 977 1237 89 +235 417 1236 23 +383 776 1235 3 +961 474 1234 13 +919 744 1233 1 +552 530 1232 34 +268 268 1231 39 +421 866 1230 11 +896 83 1229 45 +824 408 1228 5 +560 659 1227 65 +641 208 1226 76 +301 897 1225 85 +729 120 1224 42 +213 663 1223 4 +262 958 1222 36 +402 272 1221 28 +782 664 1220 84 +674 396 1219 52 +749 405 1218 7 +451 889 1217 26 +311 911 1216 91 +776 430 1215 33 +457 379 1214 57 +704 675 1213 51 +685 81 1212 95 +608 438 1211 86 +267 321 1210 61 +991 453 1209 10 +515 806 1208 92 +978 345 1207 29 +480 579 1206 14 +51 768 1205 53 +703 55 1204 31 +594 564 1203 75 +643 91 1202 1 +116 240 1201 7 +868 512 1200 34 +646 182 1199 27 +461 627 1198 47 +765 158 1197 53 +811 605 1196 49 +712 214 1195 42 +491 567 1194 34 +472 733 1193 10 +850 942 1192 95 +728 735 1191 52 +329 65 1190 24 +554 799 1189 22 +469 938 1188 18 +552 39 1187 69 +391 69 1186 95 +647 80 1185 9 +834 239 1184 22 +790 157 1183 1 +206 423 1182 62 +669 278 1181 12 +266 25 1180 39 +860 37 1179 77 +898 489 1178 8 +970 741 1177 91 +988 855 1176 16 +840 878 1175 74 +81 201 1174 81 +733 396 1173 4 +145 499 1172 58 +253 723 1171 53 +988 623 1170 40 +548 689 1169 40 +748 169 1168 96 +886 755 1167 92 +976 416 1166 98 +676 931 1165 14 +805 769 1164 75 +897 458 1163 34 +776 48 1162 58 +99 133 1161 89 +934 997 1160 26 +520 443 1159 44 +413 34 1158 79 +339 946 1157 86 +485 833 1156 90 +161 389 1155 29 +310 410 1154 87 +410 758 1153 90 +914 696 1152 12 +135 627 1151 67 +553 824 1150 16 +409 640 1149 41 +87 937 1148 10 +113 952 1147 7 +443 610 1146 85 +979 428 1145 32 +651 963 1144 85 +62 787 1143 90 +69 444 1142 49 +803 511 1141 77 +183 750 1140 58 +702 307 1139 14 +985 32 1138 32 +342 220 1137 97 +182 530 1136 67 +464 472 1135 46 +176 950 1134 32 +342 404 1133 58 +933 717 1132 99 +760 196 1131 26 +442 437 1130 62 +275 822 1129 48 +811 347 1128 71 +689 304 1127 64 +58 205 1126 16 +521 136 1125 71 +546 737 1124 28 +687 596 1123 83 +520 727 1122 40 +758 645 1121 17 +615 139 1120 31 +474 763 1119 16 +43 73 1118 46 +98 483 1117 12 +69 442 1116 63 +399 429 1115 53 +141 455 1114 97 +868 423 1113 85 +82 236 1112 16 +506 855 1111 76 +375 150 1110 14 +690 702 1109 14 +590 342 1108 43 +40 491 1107 94 +13 93 1106 2 +974 562 1105 66 +31 115 1104 25 +186 692 1103 27 +380 405 1102 78 +705 618 1101 57 +447 1 1100 13 +360 711 1099 68 +851 484 1098 9 +397 916 1097 55 +530 359 1096 2 +446 411 1095 3 +423 986 1094 94 +287 485 1093 84 +786 210 1092 80 +617 445 1091 67 +290 445 1090 25 +226 585 1089 8 +567 549 1088 50 +557 523 1087 45 +948 987 1086 86 +424 97 1085 8 +500 97 1084 2 +274 38 1083 13 +765 131 1082 50 +999 416 1081 16 +859 170 1080 32 +36 578 1079 6 +25 55 1078 65 +536 586 1077 1 +890 782 1076 60 +999 60 1075 52 +59 887 1074 92 +906 634 1073 22 +715 332 1072 50 +245 841 1071 76 +592 263 1070 13 +522 404 1069 82 +469 648 1068 1 +803 401 1067 48 +721 85 1066 64 +173 599 1065 89 +253 697 1064 93 +302 717 1063 15 +490 742 1062 19 +577 626 1061 46 +858 316 1060 65 +756 812 1059 7 +246 521 1058 5 +315 843 1057 66 +486 755 1056 8 +901 950 1055 54 +979 787 1054 91 +975 961 1053 95 +115 722 1052 81 +309 816 1051 91 +504 581 1050 71 +290 18 1049 10 +678 386 1048 51 +87 584 1047 93 +804 533 1046 82 +163 628 1045 58 +825 968 1044 92 +239 139 1043 0 +905 899 1042 86 +234 193 1041 80 +563 616 1040 80 +632 591 1039 21 +802 579 1038 61 +50 101 1037 59 +904 243 1036 28 +659 663 1035 64 +829 917 1034 33 +240 143 1033 58 +705 54 1032 33 +576 0 1031 67 +25 590 1030 67 +11 602 1029 93 +477 21 1028 82 +857 307 1027 75 +580 642 1026 14 +745 302 1025 24 +774 751 1024 83 +89 252 1023 58 +53 663 1022 53 +410 999 1021 12 +988 739 1020 55 +580 101 1019 1 +714 78 1018 53 +664 604 1017 61 +339 902 1016 27 +550 414 1015 83 +499 240 1014 97 +589 54 1013 68 +663 406 1012 3 +260 577 1011 64 +637 538 1010 42 +23 479 1009 40 +473 914 1008 86 +702 342 1007 5 +487 442 1006 32 +173 863 1005 78 +185 285 1004 5 +648 649 1003 91 +829 392 1002 92 +39 221 1001 40 +58 13 1000 62 +565 542 999 61 +571 815 998 54 +899 725 997 77 +578 535 996 21 +578 738 995 31 +636 141 994 98 +257 984 993 53 +170 522 992 81 +207 781 991 78 +471 7 990 98 +726 64 989 49 +89 778 988 99 +190 556 987 67 +797 900 986 32 +596 326 985 0 +156 450 984 94 +461 718 983 37 +741 29 982 8 +773 809 981 96 +942 486 980 73 +286 499 979 74 +221 321 978 63 +656 351 977 89 +573 320 976 39 +876 59 975 20 +731 562 974 44 +688 292 973 69 +220 123 972 72 +322 226 971 96 +986 991 970 83 +178 107 969 65 +970 737 968 6 +30 506 967 56 +261 192 966 8 +496 760 965 69 +270 745 964 14 +168 974 963 4 +896 752 962 46 +235 136 961 89 +883 174 960 33 +369 590 959 80 +231 501 958 20 +313 480 957 93 +432 387 956 76 +15 551 955 76 +770 101 954 22 +221 574 953 10 +615 571 952 27 +962 561 951 66 +584 527 950 35 +89 600 949 51 +20 268 948 13 +93 169 947 91 +835 4 946 88 +450 539 945 41 +526 122 944 24 +3 831 943 54 +9 609 942 60 +34 309 941 65 +926 837 940 37 +331 375 939 49 +98 221 938 6 +164 35 937 92 +465 464 936 25 +416 173 935 38 +291 695 934 92 +221 943 933 52 +299 951 932 99 +472 276 931 97 +461 882 930 10 +154 426 929 59 +185 142 928 23 +571 668 927 93 +291 873 926 69 +477 461 925 4 +751 401 924 12 +991 528 923 6 +675 19 922 92 +393 867 921 82 +455 512 920 1 +284 361 919 30 +474 298 918 96 +794 235 917 61 +412 650 916 28 +59 923 915 81 +873 55 914 72 +508 148 913 75 +152 94 912 31 +354 816 911 28 +151 703 910 93 +63 338 909 17 +63 355 908 81 +584 333 907 67 +727 467 906 38 +867 86 905 35 +907 966 904 18 +53 443 903 36 +277 34 902 35 +113 343 901 79 +364 766 900 20 +983 361 899 8 +22 130 898 99 +865 296 897 47 +380 29 896 85 +119 165 895 85 +523 821 894 96 +409 8 893 85 +690 557 892 77 +576 595 891 16 +405 115 890 74 +230 88 889 38 +834 520 888 96 +266 622 887 15 +864 997 886 48 +344 898 885 26 +812 106 884 59 +451 78 883 11 +962 611 882 71 +479 415 881 11 +27 367 880 17 +567 420 879 17 +898 804 878 39 +624 670 877 56 +99 224 876 40 +791 664 875 51 +28 482 874 53 +466 395 873 36 +195 603 872 48 +48 943 871 48 +946 995 870 45 +616 779 869 45 +133 828 868 66 +446 164 867 27 +559 883 866 52 +182 988 865 30 +86 169 864 76 +791 872 863 56 +660 5 862 27 +948 30 861 14 +215 992 860 10 +950 790 859 33 +664 394 858 48 +281 749 857 68 +894 217 856 88 +818 544 855 37 +296 201 854 9 +866 290 853 29 +975 123 852 13 +37 45 851 71 +202 771 850 73 +395 847 849 26 +645 795 848 28 +532 800 847 38 +672 508 846 38 +343 282 845 7 +910 800 844 52 +167 163 843 42 +78 418 842 89 +273 979 841 93 +924 467 840 83 +52 978 839 80 +995 903 838 75 +291 995 837 11 +226 311 836 85 +482 553 835 32 +636 92 834 43 +744 538 833 74 +439 953 832 8 +511 102 831 80 +489 28 830 34 +74 56 829 87 +907 636 828 5 +684 253 827 70 +758 530 826 6 +460 896 825 74 +554 690 824 84 +584 654 823 89 +851 284 822 30 +73 454 821 92 +972 477 820 2 +419 814 819 41 +383 352 818 16 +723 638 817 22 +633 320 816 92 +205 898 815 29 +35 953 814 90 +369 586 813 96 +829 378 812 73 +976 904 811 77 +662 607 810 10 +462 248 809 55 +714 943 808 3 +318 297 807 65 +421 627 806 8 +945 391 805 42 +366 936 804 17 +208 236 803 66 +473 955 802 54 +297 675 801 85 +358 548 800 31 +305 516 799 20 +645 377 798 74 +669 569 797 39 +236 661 796 89 +455 257 795 47 +699 504 794 57 +280 125 793 15 +280 687 792 73 +126 538 791 17 +32 113 790 93 +138 452 789 5 +808 351 788 65 +907 500 787 97 +404 419 786 43 +753 897 785 78 +378 420 784 75 +437 423 783 41 +149 559 782 0 +425 236 781 15 +660 885 780 9 +101 394 779 89 +851 683 778 33 +80 542 777 90 +522 653 776 50 +477 24 775 65 +996 336 774 37 +864 418 773 94 +322 847 772 28 +350 59 771 72 +491 200 770 76 +710 563 769 55 +141 429 768 24 +889 397 767 77 +628 852 766 55 +688 276 765 4 +917 433 764 48 +571 652 763 13 +787 564 762 54 +859 958 761 97 +636 205 760 85 +133 309 759 78 +32 477 758 56 +545 213 757 25 +576 513 756 26 +843 563 755 93 +780 348 754 77 +88 590 753 34 +605 569 752 78 +752 112 751 92 +895 79 750 22 +832 210 749 50 +264 317 748 10 +699 991 747 48 +949 321 746 96 +215 169 745 73 +758 424 744 6 +21 561 743 69 +457 855 742 48 +33 706 741 85 +868 718 740 85 +893 401 739 6 +326 614 738 56 +669 517 737 56 +152 236 736 75 +744 669 735 73 +862 370 734 45 +706 209 733 73 +149 629 732 56 +987 995 731 42 +316 793 730 16 +787 496 729 97 +97 2 728 56 +280 815 727 65 +566 15 726 51 +299 277 725 40 +161 719 724 88 +580 173 723 15 +633 140 722 55 +202 259 721 16 +296 189 720 67 +494 408 719 52 +186 910 718 68 +799 138 717 81 +737 110 716 71 +558 526 715 26 +546 725 714 13 +33 598 713 58 +880 395 712 94 +69 490 711 43 +780 140 710 90 +498 840 709 80 +771 872 708 30 +28 102 707 38 +584 446 706 6 +800 129 705 17 +126 557 704 1 +202 634 703 51 +905 515 702 15 +350 526 701 81 +300 102 700 28 +967 495 699 28 +770 920 698 72 +655 325 697 74 +316 882 696 44 +572 166 695 78 +922 499 694 67 +119 360 693 92 +989 341 692 29 +423 521 691 55 +607 6 690 4 +575 556 689 33 +594 983 688 19 +442 298 687 11 +716 660 686 33 +667 109 685 74 +138 750 684 65 +18 626 683 80 +819 742 682 13 +515 504 681 56 +449 717 680 81 +572 135 679 3 +684 82 678 98 +637 775 677 15 +551 594 676 72 +358 94 675 4 +124 846 674 52 +883 673 673 11 +237 564 672 19 +787 749 671 30 +581 783 670 6 +52 51 669 87 +306 827 668 88 +180 426 667 4 +500 677 666 8 +247 519 665 19 +173 409 664 23 +108 920 663 24 +814 895 662 64 +965 238 661 45 +731 188 660 20 +224 989 659 52 +401 840 658 74 +748 961 657 12 +158 893 656 68 +110 958 655 25 +488 993 654 7 +25 595 653 6 +656 195 652 29 +49 244 651 84 +199 677 650 23 +148 782 649 50 +879 620 648 82 +67 445 647 65 +935 426 646 59 +964 179 645 4 +398 9 644 62 +400 770 643 46 +951 445 642 36 +566 614 641 60 +894 726 640 84 +162 684 639 5 +174 170 638 26 +18 61 637 81 +247 543 636 13 +169 425 635 97 +238 158 634 56 +325 94 633 99 +830 761 632 44 +888 757 631 38 +41 798 630 67 +514 783 629 73 +108 456 628 98 +518 679 627 15 +117 161 626 77 +267 405 625 7 +63 567 624 93 +333 549 623 91 +3 64 622 49 +959 712 621 94 +15 939 620 84 +326 743 619 52 +776 833 618 40 +518 384 617 59 +756 693 616 40 +837 147 615 84 +18 17 614 20 +484 417 613 72 +351 554 612 33 +772 93 611 4 +196 320 610 94 +910 120 609 68 +449 815 608 55 +690 188 607 25 +546 551 606 76 +129 645 605 91 +599 474 604 81 +863 399 603 53 +460 286 602 13 +773 100 601 57 +199 255 600 57 +304 138 599 28 +627 292 598 46 +637 495 597 75 +906 843 596 14 +170 100 595 41 +75 285 594 52 +112 400 593 73 +185 553 592 40 +845 2 591 68 +116 291 590 57 +845 823 589 89 +796 703 588 67 +652 613 587 99 +742 727 586 73 +815 886 585 73 +884 794 584 9 +846 332 583 96 +551 716 582 92 +711 114 581 33 +467 678 580 72 +120 217 579 27 +89 687 578 4 +886 259 577 14 +841 995 576 90 +92 640 575 92 +462 132 574 93 +615 35 573 3 +602 587 572 29 +436 611 571 83 +460 457 570 24 +529 222 569 34 +428 904 568 3 +263 234 567 20 +355 981 566 4 +507 997 565 74 +97 892 564 63 +447 742 563 84 +976 455 562 1 +153 595 561 16 +234 896 560 97 +318 316 559 93 +670 827 558 10 +252 158 557 16 +984 296 556 90 +104 118 555 84 +150 784 554 41 +287 832 553 65 +859 848 552 47 +699 190 551 82 +579 44 550 91 +489 829 549 91 +668 936 548 64 +862 256 547 41 +178 60 546 26 +333 437 545 88 +952 759 544 95 +984 180 543 86 +657 647 542 42 +146 903 541 16 +214 3 540 11 +892 268 539 9 +680 230 538 82 +196 149 537 80 +622 387 536 68 +678 926 535 84 +579 91 534 38 +532 435 533 96 +744 267 532 32 +900 40 531 51 +735 29 530 93 +37 269 529 32 +80 14 528 21 +762 122 527 48 +460 839 526 57 +835 462 525 94 +656 413 524 9 +167 641 523 4 +226 815 522 78 +11 580 521 84 +759 609 520 16 +254 109 519 69 +892 728 518 95 +283 909 517 31 +376 630 516 30 +48 845 515 62 +772 52 514 17 +825 258 513 48 +235 944 512 94 +970 678 511 21 +500 467 510 25 +380 741 509 50 +819 638 508 36 +279 15 507 60 +785 676 506 90 +792 446 505 32 +793 690 504 27 +313 547 503 94 +265 725 502 59 +211 963 501 26 +726 746 500 47 +102 143 499 11 +622 752 498 56 +339 702 497 54 +229 578 496 49 +756 51 495 99 +142 329 494 99 +821 356 493 48 +762 326 492 4 +216 793 491 5 +603 351 490 48 +390 558 489 62 +50 20 488 47 +123 46 487 28 +527 501 486 10 +722 993 485 47 +973 519 484 61 +30 432 483 32 +532 993 482 5 +442 568 481 54 +792 861 480 61 +537 144 479 21 +974 195 478 34 +544 174 477 92 +508 635 476 59 +474 860 475 80 +86 292 474 74 +438 261 473 94 +424 512 472 49 +706 933 471 8 +717 399 470 65 +948 873 469 25 +20 413 468 56 +539 329 467 42 +774 792 466 3 +568 55 465 3 +30 806 464 38 +748 445 463 64 +579 408 462 1 +533 439 461 71 +526 395 460 98 +459 691 459 76 +84 133 458 92 +537 393 457 48 +736 2 456 76 +249 646 455 20 +360 739 454 53 +36 633 453 28 +969 296 452 16 +43 728 451 4 +703 220 450 0 +558 840 449 6 +740 446 448 37 +390 716 447 54 +355 558 446 80 +907 668 445 48 +106 256 444 88 +337 112 443 32 +568 122 442 6 +507 40 441 92 +379 938 440 34 +393 692 439 14 +730 827 438 81 +157 747 437 34 +890 312 436 3 +411 599 435 44 +144 564 434 80 +989 256 433 76 +82 142 432 76 +101 584 431 6 +246 194 430 12 +864 327 429 98 +80 468 428 66 +434 314 427 57 +713 587 426 26 +35 647 425 47 +307 31 424 26 +114 0 423 15 +557 708 422 90 +390 932 421 98 +867 141 420 85 +859 322 419 38 +154 90 418 78 +726 305 417 64 +939 788 416 72 +615 211 415 67 +31 112 414 72 +291 247 413 19 +775 925 412 55 +790 126 411 16 +819 473 410 52 +232 597 409 0 +784 138 408 70 +517 924 407 42 +576 43 406 78 +99 950 405 32 +864 533 404 58 +322 636 403 74 +798 389 402 51 +653 644 401 98 +875 514 400 97 +458 302 399 58 +214 278 398 44 +880 640 397 26 +92 463 396 94 +417 739 395 47 +897 844 394 23 +246 224 393 54 +745 530 392 52 +129 13 391 14 +212 385 390 77 +24 138 389 41 +637 182 388 24 +176 325 387 33 +723 464 386 78 +895 241 385 67 +619 693 384 52 +694 17 383 65 +517 378 382 50 +627 367 381 61 +247 360 380 91 +956 174 379 18 +856 909 378 38 +860 545 377 46 +222 112 376 45 +547 155 375 82 +675 870 374 27 +639 148 373 92 +11 886 372 17 +6 698 371 88 +186 729 370 38 +264 801 369 29 +363 925 368 9 +432 8 367 99 +957 624 366 63 +285 552 365 67 +721 350 364 87 +261 748 363 3 +188 287 362 62 +968 508 361 0 +928 89 360 82 +875 191 359 92 +916 103 358 90 +384 358 357 93 +71 962 356 47 +202 803 355 67 +601 835 354 56 +461 408 353 45 +778 622 352 7 +419 183 351 21 +897 899 350 3 +88 20 349 5 +745 970 348 95 +395 455 347 53 +159 802 346 31 +967 109 345 86 +426 103 344 60 +786 386 343 14 +438 853 342 68 +284 180 341 35 +879 986 340 52 +50 94 339 80 +514 426 338 34 +653 219 337 34 +693 444 336 23 +5 268 335 19 +717 460 334 54 +532 457 333 64 +673 323 332 34 +193 837 331 15 +892 711 330 40 +667 465 329 82 +207 994 328 53 +775 112 327 86 +175 44 326 95 +808 650 325 68 +2 900 324 28 +133 293 323 18 +485 192 322 85 +126 749 321 48 +246 576 320 30 +471 292 319 22 +881 674 318 46 +68 901 317 43 +394 272 316 59 +749 398 315 36 +607 104 314 80 +100 325 313 86 +443 378 312 64 +172 178 311 35 +284 76 310 88 +617 763 309 77 +773 28 308 59 +629 832 307 81 +873 232 306 67 +294 561 305 64 +778 936 304 14 +947 221 303 50 +199 287 302 65 +102 479 301 27 +312 105 300 88 +735 184 299 66 +195 777 298 84 +599 139 297 14 +671 29 296 75 +624 502 295 57 +714 635 294 51 +934 849 293 83 +807 387 292 74 +374 381 291 9 +921 221 290 78 +406 822 289 57 +638 700 288 53 +109 387 287 59 +527 177 286 92 +867 62 285 4 +785 684 284 91 +461 84 283 78 +5 649 282 12 +160 308 281 43 +399 211 280 45 +122 38 279 51 +312 943 278 76 +210 668 277 52 +114 880 276 58 +377 136 275 65 +600 129 274 8 +434 654 273 32 +341 692 272 45 +96 981 271 84 +173 937 270 76 +95 746 269 27 +274 239 268 80 +787 946 267 10 +743 922 266 9 +6 578 265 73 +475 757 264 77 +961 867 263 16 +711 611 262 9 +43 84 261 24 +190 483 260 92 +507 467 259 7 +292 708 258 82 +23 5 257 48 +343 359 256 4 +821 958 255 73 +889 611 254 53 +256 73 253 51 +526 848 252 25 +600 321 251 66 +16 845 250 85 +759 258 249 68 +703 332 248 21 +645 443 247 26 +400 307 246 67 +347 205 245 52 +538 16 244 93 +225 264 243 63 +526 582 242 72 +476 815 241 92 +587 168 240 58 +925 469 239 25 +889 945 238 5 +136 589 237 5 +101 157 236 24 +189 591 235 5 +752 297 234 80 +681 904 233 31 +766 803 232 69 +646 341 231 5 +699 327 230 88 +523 200 229 66 +356 997 228 3 +431 813 227 75 +566 190 226 3 +293 244 225 91 +393 496 224 43 +100 614 223 7 +461 648 222 91 +13 160 221 11 +126 227 220 94 +202 626 219 17 +184 282 218 16 +623 718 217 92 +946 122 216 86 +747 475 215 27 +882 366 214 89 +965 155 213 29 +487 795 212 63 +933 173 211 44 +601 770 210 88 +343 9 209 92 +563 242 208 1 +596 58 207 56 +646 592 206 67 +109 373 205 19 +210 606 204 86 +360 653 203 91 +622 191 202 47 +402 560 201 55 +761 963 200 33 +766 904 199 25 +183 458 198 78 +466 884 197 96 +219 477 196 94 +767 333 195 53 +952 948 194 89 +462 438 193 85 +630 923 192 73 +597 222 191 21 +58 74 190 64 +446 477 189 99 +573 812 188 58 +406 17 187 71 +143 413 186 24 +384 637 185 45 +510 48 184 81 +515 112 183 48 +700 518 182 83 +148 579 181 3 +596 645 180 53 +664 412 179 61 +795 865 178 87 +604 470 177 16 +775 794 176 26 +589 637 175 75 +935 324 174 87 +594 657 173 99 +939 799 172 81 +933 494 171 55 +233 926 170 55 +547 738 169 93 +394 706 168 86 +675 904 167 19 +157 503 166 82 +313 885 165 18 +667 879 164 65 +857 181 163 34 +305 261 162 65 +567 1 161 0 +187 618 160 70 +32 63 159 68 +801 677 158 15 +400 362 157 71 +618 642 156 51 +6 532 155 84 +697 311 154 64 +919 685 153 80 +260 649 152 55 +382 305 151 73 +555 14 150 38 +385 532 149 15 +315 434 148 23 +719 200 147 40 +109 674 146 78 +221 198 145 61 +625 836 144 30 +36 257 143 77 +344 814 142 65 +290 357 141 87 +481 225 140 82 +98 923 139 16 +233 829 138 7 +525 618 137 59 +476 169 136 60 +361 304 135 88 +578 529 134 59 +442 119 133 58 +457 780 132 69 +131 51 131 5 +301 657 130 80 +93 99 129 38 +210 473 128 86 +449 986 127 70 +865 721 126 4 +774 293 125 11 +410 5 124 78 +338 897 123 13 +729 638 122 98 +394 244 121 32 +557 426 120 82 +625 517 119 20 +487 157 118 88 +265 658 117 76 +427 934 116 58 +288 331 115 9 +107 647 114 36 +258 151 113 7 +394 658 112 60 +818 496 111 33 +908 622 110 83 +360 324 109 93 +498 121 108 13 +724 178 107 22 +603 492 106 83 +684 727 105 13 +495 291 104 18 +492 463 103 84 +162 273 102 86 +873 498 101 57 +297 904 100 90 +203 793 99 54 +943 916 98 86 +685 383 97 77 +764 699 96 12 +436 958 95 91 +827 331 94 18 +189 984 93 0 +775 288 92 32 +593 666 91 28 +111 361 90 57 +877 686 89 9 +532 87 88 26 +684 653 87 25 +740 202 86 92 +627 730 85 32 +347 184 84 60 +695 673 83 63 +621 40 82 41 +304 712 81 18 +675 482 80 48 +598 833 79 23 +434 3 78 34 +450 336 77 84 +471 592 76 94 +546 719 75 11 +510 971 74 28 +633 223 73 65 +328 231 72 7 +229 700 71 31 +649 248 70 62 +830 888 69 7 +666 497 68 16 +743 903 67 98 +873 831 66 97 +747 833 65 92 +747 628 64 3 +992 576 63 87 +530 757 62 30 +452 687 61 9 +359 552 60 57 +391 913 59 81 +593 180 58 16 +72 4 57 92 +997 54 56 87 +204 889 55 12 +51 157 54 99 +819 573 53 75 +69 204 52 46 +134 520 51 7 +639 759 50 9 +732 656 49 96 +176 240 48 79 +950 52 47 52 +164 745 46 7 +732 125 45 79 +584 244 44 15 +368 294 43 23 +684 383 42 74 +760 984 41 93 +103 126 40 49 +416 169 39 90 +187 276 38 55 +307 447 37 22 +619 281 36 78 +881 641 35 43 +950 920 34 14 +910 482 33 21 +398 814 32 68 +858 439 31 92 +956 588 30 65 +893 350 29 68 +829 330 28 22 +165 440 27 88 +639 354 26 68 +720 284 25 73 +437 931 24 93 +667 531 23 3 +375 760 22 51 +850 266 21 53 +238 970 20 90 +20 457 19 6 +890 348 18 6 +86 192 17 66 +69 949 16 52 +352 807 15 91 +400 891 14 28 +771 526 13 76 +493 972 12 29 +296 637 11 52 +512 839 10 61 +108 998 9 21 +156 400 8 12 +242 137 7 80 +141 606 6 1 +916 635 5 71 +364 513 4 95 +553 477 3 62 +335 768 2 27 +798 911 1 19 +840 394 0 78 +@nodes +source 252 +@end diff -r d8475431bbbb -r 8e85e6bbefdf test/error_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/error_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,65 @@ +/* -*- C++ -*- + * test/error_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include + +#include +#include "test_tools.h" +using namespace lemon; +using std::cout; +using std::endl; + +void faulty_fn() { + fault("This is a fault message"); +} + +void exception_fn() { + throw Exception("This is a fn throwing excpt with some args: ") + << 5 << ", " << 18; +} + +void unfinished_fn() { + FIXME("unfinished_fn() is unfinished!"); +} + + +int main() { + try { + faulty_fn(); + check(false, "A faulty function did not fail."); + } + catch(const Exception &e) { + cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl; + } + + try { + exception_fn(); + check(false, "The function did not throw Exception."); + } + catch(const Exception &e) { + cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl; + } + + try { + unfinished_fn(); + check(false, "FIXME macro does not work."); + } + catch(const Exception &e) { + cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl; + } + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/graph_adaptor_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/graph_adaptor_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,75 @@ +/* -*- C++ -*- + * test/graph_adaptor_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include"test/test_tools.h" +#include"test/graph_test.h" + +/** +\file +This test makes consistency checks of graph adaptors. + +\todo More extensive tests are needed +*/ + +using namespace lemon; +using namespace lemon::concept; + + + +int main() +{ + { + typedef StaticGraph Graph; + checkConcept >(); + + checkConcept >(); + + checkConcept , Graph::EdgeMap > >(); + checkConcept > >(); + checkConcept > >(); + + checkConcept, Graph::EdgeMap > >(); + // checkConcept >(); + checkConcept, Graph::EdgeMap > >(); + + checkConcept > >(); + + /// \bug why does not compile with StaticGraph + checkConcept >(); + checkConcept >(); + checkConcept >(); + } + std::cout << __FILE__ ": All tests passed.\n"; + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/graph_factory_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/graph_factory_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,154 @@ +/* -*- C++ -*- + * test/graph_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include +#include +#include +#include +#include + +#include"test_tools.h" +#include"graph_test.h" + +/** +\file +This test makes consistency checks of list graph structures. + +G.addNode(), G.addEdge(), G.source(), G.target() + +\todo Checks for empty graphs and isolated points. +conversion. +*/ + +using namespace lemon; + +template void bidirPetersen(Graph &G) +{ + typedef typename Graph::Edge Edge; + typedef typename Graph::EdgeIt EdgeIt; + + checkGraphEdgeList(G,15); + + std::vector ee; + + for(EdgeIt e(G);e!=INVALID;++e) ee.push_back(e); + + for(typename std::vector::iterator p=ee.begin();p!=ee.end();p++) + G.addEdge(G.target(*p),G.source(*p)); +} + +template void checkPetersen(Graph &G) +{ + typedef typename Graph::Node Node; + + typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::NodeIt NodeIt; + + checkGraphNodeList(G,10); + checkGraphEdgeList(G,30); + + for(NodeIt n(G);n!=INVALID;++n) { + checkGraphInEdgeList(G,n,3); + checkGraphOutEdgeList(G,n,3); + } +} + +//Compile Graph +template void lemon::concept::checkCompileStaticGraph +(concept::StaticGraph &); + +template +void lemon::concept::checkCompileExtendableGraph +(concept::ExtendableGraph &); + +template +void lemon::concept::checkCompileErasableGraph +(concept::ErasableGraph &); + +//Compile SmartGraph +template +void lemon::concept::checkCompileExtendableGraph(SmartGraph &); +template +void lemon::concept::checkCompileGraphFindEdge(SmartGraph &); + +//Compile SymSmartGraph +//template void hugo::checkCompileGraph(SymSmartGraph &); +//template void hugo::checkCompileGraphFindEdge(SymSmartGraph &); + +//Compile ListGraph +template +void lemon::concept::checkCompileExtendableGraph(ListGraph &); +template +void lemon::concept::checkCompileErasableGraph(ListGraph &); +template +void lemon::concept::checkCompileGraphFindEdge(ListGraph &); + + +//Compile SymListGraph +//template void hugo::checkCompileGraph(SymListGraph &); +//template void hugo::checkCompileErasableGraph(SymListGraph &); +//template void hugo::checkCompileGraphFindEdge(SymListGraph &); + +//Compile FullGraph +template void lemon::concept::checkCompileStaticGraph(FullGraph &); +template +void lemon::concept::checkCompileGraphFindEdge(FullGraph &); + + +int main() +{ + { + SmartGraph G; + addPetersen(G); + bidirPetersen(G); + checkPetersen(G); + } + { + ListGraph G; + addPetersen(G); + bidirPetersen(G); + checkPetersen(G); + } + { + // SymSmartGraph G; + // addPetersen(G); + // checkPetersen(G); + } + { + // SymListGraph G; + // addPetersen(G); + // checkPetersen(G); + } + + ///\file + ///\todo map tests. + ///\todo copy constr tests. + + + // Some map tests. + // FIXME: These shouldn't be here. + using namespace concept; + function_requires< ReadMapConcept< ReadMap > >(); + function_requires< WriteMapConcept< WriteMap > >(); + function_requires< ReadWriteMapConcept< ReadWriteMap > >(); + function_requires< ReferenceMapConcept< ReferenceMap > >(); + + + std::cout << __FILE__ ": All tests passed.\n"; + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/graph_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/graph_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,66 @@ +// -*- c++ -*- + +#include +#include + +#include +#include +#include +#include + +#include "test_tools.h" +#include "graph_test.h" +#include "map_test.h" + + +using namespace lemon; +using namespace lemon::concept; + + +int main() { + { // checking graph components + checkConcept(); + + checkConcept(); + + checkConcept(); + checkConcept(); + + checkConcept(); + checkConcept(); + + checkConcept(); + + checkConcept(); + + checkConcept(); + checkConcept(); + checkConcept(); + } + { // checking skeleton graphs + checkConcept(); + checkConcept(); + checkConcept(); + } + { // checking list graph + checkConcept(); + + checkGraph(); + checkGraphNodeMap(); + checkGraphEdgeMap(); + } + { // checking smart graph + checkConcept(); + + checkGraph(); + checkGraphNodeMap(); + checkGraphEdgeMap(); + } + { // checking full graph + checkConcept(); + } + + std::cout << __FILE__ ": All tests passed.\n"; + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/graph_test.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/graph_test.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,90 @@ +/* -*- C++ -*- + * test/graph_test.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ +#ifndef LEMON_TEST_GRAPH_TEST_H +#define LEMON_TEST_GRAPH_TEST_H + + +#include "test_tools.h" + +//! \ingroup misc +//! \file +//! \brief Some utility and test cases to test graph classes. +namespace lemon { + + template void checkGraphNodeList(Graph &G, int nn) + { + typename Graph::NodeIt n(G); + for(int i=0;i + void checkGraphEdgeList(Graph &G, int nn) + { + typedef typename Graph::EdgeIt EdgeIt; + + EdgeIt e(G); + for(int i=0;i + void checkGraphOutEdgeList(Graph &G, typename Graph::Node n, int nn) + { + typename Graph::OutEdgeIt e(G,n); + for(int i=0;i void + checkGraphInEdgeList(Graph &G, typename Graph::Node n, int nn) + { + typename Graph::InEdgeIt e(G,n); + for(int i=0;i + void checkGraph() { + const int num = 5; + Graph G; + addPetersen(G, num); + bidirGraph(G); + checkBidirPetersen(G, num); + } + + ///\file + ///\todo Check target(), source() as well; + + +} //namespace lemon + + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf test/graph_utils_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/graph_utils_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,37 @@ +// -*- c++ -*- + +#include +#include + +#include + +#include +#include +#include + +#include "test_tools.h" +#include "graph_utils_test.h" + + +using namespace lemon; + + +int main() { + ///\file + { // checking list graph + checkGraphCounters(); + } + { // checking smart graph + checkGraphCounters(); + } + { + int num = 5; + FullGraph fg(num); + check(countNodes(fg) == num, "FullGraph: wrong node number."); + check(countEdges(fg) == num*num, "FullGraph: wrong edge number."); + } + + std::cout << __FILE__ ": All tests passed.\n"; + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/graph_utils_test.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/graph_utils_test.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,44 @@ +/* -*- C++ -*- + * test/graph_utils_test.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ +#ifndef LEMON_TEST_GRAPH_UTILS_TEST_H +#define LEMON_TEST_GRAPH_UTILS_TEST_H + + +#include "test_tools.h" + +//! \ingroup misc +//! \file +//! \brief Test cases for graph utils. +namespace lemon { + + template + void checkGraphCounters() { + const int num = 5; + Graph graph; + addPetersen(graph, num); + bidirGraph(graph); + check(countNodes(graph) == 2*num, "Wrong node number."); + check(countEdges(graph) == 6*num, "Wrong edge number."); + for (typename Graph::NodeIt it(graph); it != INVALID; ++it) { + check(countOutEdges(graph, it) == 3, "Wrong out degree number."); + check(countInEdges(graph, it) == 3, "Wrong in degree number."); + } + } + +} //namespace lemon + + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf test/heap_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/heap_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,98 @@ +// -*- c++ -*- + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include + +#include "test_tools.h" + +#include "heap_test.h" + + +using namespace lemon; +using namespace lemon::concept; + + +int main() { + + typedef int Item; + typedef int Prio; + typedef IntIntMap ItemIntMap; + + typedef ListGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef Graph::EdgeMap LengthMap; + + Graph graph; + LengthMap length(graph); + Node start; + + /// \todo create own test graph + + std::string f_name; + if( getenv("srcdir") ) + f_name = std::string(getenv("srcdir")); + else f_name = "."; + f_name += "/dijkstra_test.lgf"; + + std::ifstream input(f_name.c_str()); + check(input, "Input file '" << f_name << "' not found."); + readGraph(input, graph, length, start); + + { + std::cerr << "Checking Bin Heap" << std::endl; + + typedef BinHeap IntHeap; + checkConcept, IntHeap>(); + heapSortTest(100); + heapIncreaseTest(100); + + typedef FibHeap > NodeHeap; + checkConcept >, NodeHeap>(); + dijkstraHeapTest(graph, length, start); + } + { + std::cerr << "Checking Fib Heap" << std::endl; + + typedef FibHeap IntHeap; + checkConcept, IntHeap>(); + heapSortTest(100); + heapIncreaseTest(100); + + typedef FibHeap > NodeHeap; + checkConcept >, NodeHeap>(); + dijkstraHeapTest(graph, length, start); + } + { + std::cerr << "Checking Radix Heap" << std::endl; + + typedef RadixHeap IntHeap; + checkConcept, IntHeap>(); + heapSortTest(100); + heapIncreaseTest(100); + + typedef RadixHeap > NodeHeap; + checkConcept >, NodeHeap>(); + dijkstraHeapTest(graph, length, start); + } + + std::cout << __FILE__ ": All tests passed.\n"; + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/heap_test.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/heap_test.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,110 @@ +// -+- c++ -+- + +#include +#include + +#include + +class IntIntMap : public std::vector { +public: + typedef std::vector Parent; + + IntIntMap() : Parent() {} + IntIntMap(int n) : Parent(n) {} + IntIntMap(int n, int v) : Parent(n, v) {} + + void set(int key, int value) { + Parent::operator[](key) = value; + } +}; + + +template +void heapSortTest(int n) { + typedef _Heap Heap; + IntIntMap map(n, -1); + + Heap heap(map); + + std::vector v(n); + + for (int i = 0; i < n; ++i) { + v[i] = rand() % 1000; + heap.push(i, v[i]); + } + std::sort(v.begin(), v.end()); + for (int i = 0; i < n; ++i) { + check(v[i] == heap.prio() ,"Wrong order in heap sort."); + heap.pop(); + } +} + +template +void heapIncreaseTest(int n) { + typedef _Heap Heap; + IntIntMap map(n, -1); + + Heap heap(map); + + std::vector v(n); + + for (int i = 0; i < n; ++i) { + v[i] = rand() % 1000; + heap.push(i, v[i]); + } + for (int i = 0; i < n; ++i) { + v[i] += rand() % 1000; + heap.increase(i, v[i]); + } + std::sort(v.begin(), v.end()); + for (int i = 0; i < n; ++i) { + check(v[i] == heap.prio() ,"Wrong order in heap increase test."); + heap.pop(); + } +} + + + +template +struct DefHeapTraits : public _Traits { + typedef _Heap Heap; +}; + +template +void dijkstraHeapTest(_Graph& graph, _LengthMap& length, + typename _Graph::Node& start) { + + typedef _Heap Heap; + typedef _Graph Graph; + typedef _LengthMap LengthMap; + + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::EdgeIt EdgeIt; + + Dijkstra, Heap> > + dijkstra(graph, length); + + dijkstra.run(start); + + for(EdgeIt e(graph); e!=INVALID; ++e) { + Node u=graph.source(e); + Node v=graph.target(e); + if (dijkstra.reached(u)) { + check( dijkstra.dist(v) - dijkstra.dist(u) <= length[e], + "Error in a shortest path tree edge!"); + } + } + + for(NodeIt v(graph); v!=INVALID; ++v) { + if ( dijkstra.reached(v) && dijkstra.pred(v) != INVALID ) { + Edge e=dijkstra.pred(v); + Node u=graph.source(e); + check( dijkstra.dist(v) - dijkstra .dist(u) == length[e], + "Error in a shortest path tree edge!"); + } + } + +} diff -r d8475431bbbb -r 8e85e6bbefdf test/kruskal_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/kruskal_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,119 @@ +/* -*- C++ -*- + * test/kruskal_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include + +#include "test_tools.h" +#include +#include +#include +#include +#include + + +using namespace std; +using namespace lemon; + +void checkCompileKruskal() +{ + concept::WriteMap w; + + kruskalEdgeMap(concept::StaticGraph(), + concept::ReadMap(), + w); +} + +int main() { + + typedef ListGraph::Node Node; + typedef ListGraph::Edge Edge; + typedef ListGraph::NodeIt NodeIt; + typedef ListGraph::EdgeIt EdgeIt; + + ListGraph G; + + Node s=G.addNode(); + Node v1=G.addNode(); + Node v2=G.addNode(); + Node v3=G.addNode(); + Node v4=G.addNode(); + Node t=G.addNode(); + + Edge e1 = G.addEdge(s, v1); + Edge e2 = G.addEdge(s, v2); + Edge e3 = G.addEdge(v1, v2); + Edge e4 = G.addEdge(v2, v1); + Edge e5 = G.addEdge(v1, v3); + Edge e6 = G.addEdge(v3, v2); + Edge e7 = G.addEdge(v2, v4); + Edge e8 = G.addEdge(v4, v3); + Edge e9 = G.addEdge(v3, t); + Edge e10 = G.addEdge(v4, t); + + typedef ListGraph::EdgeMap ECostMap; + typedef ListGraph::EdgeMap EBoolMap; + + ECostMap edge_cost_map(G, 2); + EBoolMap tree_map(G); + + + //Test with const map. + check(kruskalEdgeMap(G, ConstMap(2), tree_map)==10, + "Total cost should be 10"); + //Test with a edge map (filled with uniform costs). + check(kruskalEdgeMap(G, edge_cost_map, tree_map)==10, + "Total cost should be 10"); + + edge_cost_map.set(e1, -10); + edge_cost_map.set(e2, -9); + edge_cost_map.set(e3, -8); + edge_cost_map.set(e4, -7); + edge_cost_map.set(e5, -6); + edge_cost_map.set(e6, -5); + edge_cost_map.set(e7, -4); + edge_cost_map.set(e8, -3); + edge_cost_map.set(e9, -2); + edge_cost_map.set(e10, -1); + + vector tree_edge_vec; + + //Test with a edge map and inserter. + check(kruskalEdgeMap_IteratorOut(G, edge_cost_map, + back_inserter(tree_edge_vec)) + ==-31, + "Total cost should be -31."); + + tree_edge_vec.clear(); + + //The above test could also be coded like this: + check(kruskal(G, + makeKruskalMapInput(G, edge_cost_map), + makeKruskalSequenceOutput(back_inserter(tree_edge_vec))) + ==-31, + "Total cost should be -31."); + + check(tree_edge_vec.size()==5,"The tree should have 5 edges."); + + check(tree_edge_vec[0]==e1 && + tree_edge_vec[1]==e2 && + tree_edge_vec[2]==e5 && + tree_edge_vec[3]==e7 && + tree_edge_vec[4]==e9, + "Wrong tree."); + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/lp_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/lp_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,155 @@ +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_GLPK +#include +#elif HAVE_CPLEX +#include +#endif + +using namespace lemon; + +#ifdef HAVE_GLPK +typedef LpGlpk LpDefault; +#elif HAVE_CPLEX +typedef LpCplex LpDefault; +#endif + +void lpTest(LpSolverBase & lp) +{ + typedef LpSolverBase LP; + + std::vector x(10); + // for(int i=0;i<10;i++) x.push_back(lp.addCol()); + lp.addColSet(x); + + std::vector y(10); + lp.addColSet(y); + + std::map z; + + z.insert(std::make_pair(12,INVALID)); + z.insert(std::make_pair(2,INVALID)); + z.insert(std::make_pair(7,INVALID)); + z.insert(std::make_pair(5,INVALID)); + + lp.addColSet(z); + + + LP::Expr e,f,g; + LP::Col p1,p2,p3,p4,p5; + LP::Constr c; + + e[p1]=2; + e.constComp()=12; + e[p1]+=2; + e.constComp()+=12; + e[p1]-=2; + e.constComp()-=12; + + e=2; + e=2.2; + e=p1; + e=f; + + e+=2; + e+=2.2; + e+=p1; + e+=f; + + e-=2; + e-=2.2; + e-=p1; + e-=f; + + e*=2; + e*=2.2; + e/=2; + e/=2.2; + + e=((p1+p2)+(p1-p2)+(p1+12)+(12+p1)+(p1-12)+(12-p1)+ + (f+12)+(12+f)+(p1+f)+(f+p1)+(f+g)+ + (f-12)+(12-f)+(p1-f)+(f-p1)+(f-g)+ + 2.2*f+f*2.2+f/2.2+ + 2*f+f*2+f/2+ + 2.2*p1+p1*2.2+p1/2.2+ + 2*p1+p1*2+p1/2 + ); + + + c = (e <= f ); + c = (e <= 2.2); + c = (e <= 2 ); + c = (e <= p1 ); + c = (2.2<= f ); + c = (2 <= f ); + c = (p1 <= f ); + c = (p1 <= p2 ); + c = (p1 <= 2.2); + c = (p1 <= 2 ); + c = (2.2<= p2 ); + c = (2 <= p2 ); + + c = (e >= f ); + c = (e >= 2.2); + c = (e >= 2 ); + c = (e >= p1 ); + c = (2.2>= f ); + c = (2 >= f ); + c = (p1 >= f ); + c = (p1 >= p2 ); + c = (p1 >= 2.2); + c = (p1 >= 2 ); + c = (2.2>= p2 ); + c = (2 >= p2 ); + + c = (e == f ); + c = (e == 2.2); + c = (e == 2 ); + c = (e == p1 ); + c = (2.2== f ); + c = (2 == f ); + c = (p1 == f ); + //c = (p1 == p2 ); + c = (p1 == 2.2); + c = (p1 == 2 ); + c = (2.2== p2 ); + c = (2 == p2 ); + + c = (2 <= e <= 3); + c = (2 <= p1<= 3); + + c = (2 >= e >= 3); + c = (2 >= p1>= 3); + + e[x[3]]=2; + e[x[3]]=4; + e[x[3]]=1; + e.constComp()=12; + + lp.addRow(LP::INF,e,23); + lp.addRow(LP::INF,3.0*(x[1]+x[2]/2)-x[3],23); + lp.addRow(LP::INF,3.0*(x[1]+x[2]*2-5*x[3]+12-x[4]/3)+2*x[4]-4,23); + + lp.addRow(x[1]+x[3]<=x[5]-3); + lp.addRow(-7<=x[1]+x[3]-12<=3); + lp.addRow(x[1]<=x[5]); + + + +} + +int main() +{ + LpSkeleton lp_skel; + lpTest(lp_skel); + + LpDefault lp; + + lpTest(lp); + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/map_test.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/map_test.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,95 @@ +/* -*- C++ -*- + * test/map_test.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ +#ifndef LEMON_TEST_MAP_TEST_H +#define LEMON_TEST_MAP_TEST_H + + +#include + +#include "test_tools.h" + + +//! \ingroup misc +//! \file +//! \brief Some utilities to test map classes. + +namespace lemon { + + + template + void checkGraphNodeMap() { + Graph graph; + const int num = 16; + + typedef typename Graph::Node Node; + + std::vector nodes; + for (int i = 0; i < num; ++i) { + nodes.push_back(graph.addNode()); + } + typedef typename Graph::template NodeMap IntNodeMap; + IntNodeMap map(graph, 42); + for (int i = 0; i < (int)nodes.size(); ++i) { + check(map[nodes[i]] == 42, "Wrong map constructor."); + } + for (int i = 0; i < num; ++i) { + nodes.push_back(graph.addNode()); + map[nodes.back()] = 23; + } + graph.clear(); + nodes.clear(); + } + + template + void checkGraphEdgeMap() { + Graph graph; + const int num = 16; + + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + + std::vector nodes; + for (int i = 0; i < num; ++i) { + nodes.push_back(graph.addNode()); + } + + std::vector edges; + for (int i = 0; i < num; ++i) { + for (int j = 0; j < i; ++j) { + edges.push_back(graph.addEdge(nodes[i], nodes[j])); + } + } + + typedef typename Graph::template EdgeMap IntEdgeMap; + IntEdgeMap map(graph, 42); + + for (int i = 0; i < (int)edges.size(); ++i) { + check(map[edges[i]] == 42, "Wrong map constructor."); + } + + for (int i = 0; i < num; ++i) { + for (int j = i + 1; j < num; ++j) { + edges.push_back(graph.addEdge(nodes[i], nodes[j])); + map[edges.back()] = 23; + } + } + graph.clear(); + edges.clear(); + } + +} + +#endif diff -r d8475431bbbb -r 8e85e6bbefdf test/maps_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/maps_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,57 @@ +#include +#include +#include + +#include "test_tools.h" + +using namespace lemon; +using namespace lemon::concept; + +struct A {}; +struct B {}; +class F +{ +public: + B operator()(const A &) const {return B();} +}; + +int func(A) {return 3;} + +typedef ReadMap DoubleMap; + +int main() +{ // checking graph components + + checkConcept, ReadMap >(); + checkConcept, WriteMap >(); + checkConcept, ReadWriteMap >(); + checkConcept, ReferenceMap >(); + + checkConcept, AddMap >(); + checkConcept, SubMap >(); + checkConcept, MulMap >(); + checkConcept, DivMap >(); + checkConcept, NegMap >(); + checkConcept, AbsMap >(); + checkConcept, ShiftMap >(); + checkConcept, ScaleMap >(); + + checkConcept, ComposeMap > >(); + + checkConcept, FunctorMap >(); + + int a; + + a=mapFunctor(constMap(2))(A()); + check(a==2,"Something is wrong with mapFunctor"); + + B b; + b=functorMap(F())[A()]; + + a=functorMap(&func)[A()]; + check(a==3,"Something is wrong with functorMap"); + + std::cout << __FILE__ ": All tests passed.\n"; + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/max_matching_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/max_matching_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,183 @@ +/* -*- C++ -*- + * test/max_matching_test.cc - + * Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include +#include +#include +#include + +#include "test_tools.h" +#include +#include +#include + +using namespace std; +using namespace lemon; + +int main() { + + typedef UndirListGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::UndirEdgeIt UndirEdgeIt; + typedef Graph::IncEdgeIt IncEdgeIt; + typedef Graph::NodeIt NodeIt; + typedef Graph::Node Node; + + Graph g; + g.clear(); + + std::vector nodes; + for (int i=0; i<13; ++i) + nodes.push_back(g.addNode()); + + g.addEdge(nodes[0], nodes[0]); + g.addEdge(nodes[6], nodes[10]); + g.addEdge(nodes[5], nodes[10]); + g.addEdge(nodes[4], nodes[10]); + g.addEdge(nodes[3], nodes[11]); + g.addEdge(nodes[1], nodes[6]); + g.addEdge(nodes[4], nodes[7]); + g.addEdge(nodes[1], nodes[8]); + g.addEdge(nodes[0], nodes[8]); + g.addEdge(nodes[3], nodes[12]); + g.addEdge(nodes[6], nodes[9]); + g.addEdge(nodes[9], nodes[11]); + g.addEdge(nodes[2], nodes[10]); + g.addEdge(nodes[10], nodes[8]); + g.addEdge(nodes[5], nodes[8]); + g.addEdge(nodes[6], nodes[3]); + g.addEdge(nodes[0], nodes[5]); + g.addEdge(nodes[6], nodes[12]); + + MaxMatching max_matching(g); + max_matching.runEdmonds(0); + + int s=0; + Graph::NodeMap mate(g,INVALID); + max_matching.writeNMapNode(mate); + for(NodeIt v(g); v!=INVALID; ++v) { + if ( mate[v]!=INVALID ) ++s; + } + int size=(int)s/2; //size will be used as the size of a maxmatching + + for(NodeIt v(g); v!=INVALID; ++v) { + max_matching.mate(v); + } + + check ( size == max_matching.size(), "mate() returns a different size matching than max_matching.size()" ); + + Graph::NodeMap::pos_enum> pos0(g); + max_matching.writePos(pos0); + + max_matching.resetMatching(); + max_matching.runEdmonds(1); + s=0; + max_matching.writeNMapNode(mate); + for(NodeIt v(g); v!=INVALID; ++v) { + if ( mate[v]!=INVALID ) ++s; + } + check ( (int)s/2 == size, "The size does not equal!" ); + + Graph::NodeMap::pos_enum> pos1(g); + max_matching.writePos(pos1); + + max_matching.run(); + s=0; + max_matching.writeNMapNode(mate); + for(NodeIt v(g); v!=INVALID; ++v) { + if ( mate[v]!=INVALID ) ++s; + } + check ( (int)s/2 == size, "The size does not equal!" ); + + Graph::NodeMap::pos_enum> pos2(g); + max_matching.writePos(pos2); + + max_matching.resetMatching(); + max_matching.run(); + s=0; + max_matching.writeNMapNode(mate); + for(NodeIt v(g); v!=INVALID; ++v) { + if ( mate[v]!=INVALID ) ++s; + } + check ( (int)s/2 == size, "The size does not equal!" ); + + Graph::NodeMap::pos_enum> pos(g); + max_matching.writePos(pos); + + bool ismatching=true; + for(NodeIt v(g); v!=INVALID; ++v) { + if ( mate[v]!=INVALID ) { + Node u=mate[v]; + if (mate[u]!=v) ismatching=false; + } + } + check ( ismatching, "It is not a matching!" ); + + bool coincide=true; + for(NodeIt v(g); v!=INVALID; ++v) { + if ( pos0[v] != pos1[v] || pos1[v]!=pos2[v] || pos2[v]!=pos[v] ) { + coincide=false; + } + } + check ( coincide, "The decompositions do not coincide! " ); + + bool noedge=true; + for(UndirEdgeIt e(g); e!=INVALID; ++e) { + if ( (pos[g.target(e)]==max_matching.C && pos[g.source(e)]==max_matching.D) || + (pos[g.target(e)]==max_matching.D && pos[g.source(e)]==max_matching.C) ) + noedge=false; + } + check ( noedge, "There are edges between D and C!" ); + + bool oddcomp=true; + Graph::NodeMap todo(g,true); + int num_comp=0; + for(NodeIt v(g); v!=INVALID; ++v) { + if ( pos[v]==max_matching.D && todo[v] ) { + int comp_size=1; + ++num_comp; + std::queue Q; + Q.push(v); + todo.set(v,false); + while (!Q.empty()) { + Node w=Q.front(); + Q.pop(); + for(IncEdgeIt e(g,w); e!=INVALID; ++e) { + Node u=g.runningNode(e); + if ( pos[u]==max_matching.D && todo[u] ) { + ++comp_size; + Q.push(u); + todo.set(u,false); + } + } + } + if ( !(comp_size % 2) ) oddcomp=false; + } + } + check ( oddcomp, "A component of g[D] is not odd." ); + + int barrier=0; + for(NodeIt v(g); v!=INVALID; ++v) { + if ( pos[v]==max_matching.A ) ++barrier; + } + int expected_size=(int)( countNodes(g)-num_comp+barrier)/2; + check ( size==expected_size, "The size of the matching is wrong." ); + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/min_cost_flow_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/min_cost_flow_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,126 @@ +/* -*- C++ -*- + * test/min_cost_flow_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include "test_tools.h" +#include +#include +//#include +//#include + +using namespace lemon; + + +bool passed = true; +/* +void check(bool rc, char *msg="") { + passed = passed && rc; + if(!rc) { + std::cerr << "Test failed! ("<< msg << ")" << std::endl; \ + + + } +} +*/ + + +int main() +{ + typedef ListGraph Graph; + typedef Graph::Node Node; + typedef Graph::Edge Edge; + + Graph graph; + + //Ahuja könyv példája + + Node s=graph.addNode(); + Node v1=graph.addNode(); + Node v2=graph.addNode(); + Node v3=graph.addNode(); + Node v4=graph.addNode(); + Node v5=graph.addNode(); + Node t=graph.addNode(); + + Edge s_v1=graph.addEdge(s, v1); + Edge v1_v2=graph.addEdge(v1, v2); + Edge s_v3=graph.addEdge(s, v3); + Edge v2_v4=graph.addEdge(v2, v4); + Edge v2_v5=graph.addEdge(v2, v5); + Edge v3_v5=graph.addEdge(v3, v5); + Edge v4_t=graph.addEdge(v4, t); + Edge v5_t=graph.addEdge(v5, t); + + + Graph::EdgeMap length(graph); + + length.set(s_v1, 6); + length.set(v1_v2, 4); + length.set(s_v3, 10); + length.set(v2_v4, 5); + length.set(v2_v5, 1); + length.set(v3_v5, 4); + length.set(v4_t, 8); + length.set(v5_t, 8); + + Graph::EdgeMap capacity(graph); + + capacity.set(s_v1, 2); + capacity.set(v1_v2, 2); + capacity.set(s_v3, 1); + capacity.set(v2_v4, 1); + capacity.set(v2_v5, 1); + capacity.set(v3_v5, 1); + capacity.set(v4_t, 1); + capacity.set(v5_t, 2); + + // ConstMap const1map(1); + std::cout << "Mincostflows algorithm test..." << std::endl; + + MinCostFlow< Graph, Graph::EdgeMap, Graph::EdgeMap > + surb_test(graph, length, capacity, s, t); + + int k=1; + + surb_test.augment(); + check( surb_test.flowValue() == 1 && surb_test.totalLength() == 19,"One path, total length should be 19"); + + check( surb_test.run(k) == 1 && surb_test.totalLength() == 19,"One path, total length should be 19"); + + check(surb_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?"); + + k=2; + + check( surb_test.run(k) == 2 && surb_test.totalLength() == 41,"Two paths, total length should be 41"); + + check(surb_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?"); + + surb_test.augment(); + surb_test.augment(); + surb_test.augment(); + k=4; + + check( surb_test.run(k) == 3 && surb_test.totalLength() == 64,"Three paths, total length should be 64"); + + check(surb_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?"); + + + std::cout << (passed ? "All tests passed." : "Some of the tests failed!!!") + << std::endl; + + return passed ? 0 : 1; + +} diff -r d8475431bbbb -r 8e85e6bbefdf test/path_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/path_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,96 @@ +/* -*- C++ -*- + * test/path_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include +#include +#include +#include + +using namespace std; +using namespace lemon; +using namespace lemon::concept; + +template void checkCompilePath(Path &P) +{ + typedef typename Path::EdgeIt EdgeIt; + typedef typename Path::NodeIt NodeIt; + typedef typename Path::GraphNode GraphNode; + typedef typename Path::GraphEdge GraphEdge; + //typedef typename Path::Builder Builder; + //??? ha csinalok ilyet es siman Builderrel peldanyositok, akkor warningol. Talan friend miatt? De ki az? + + EdgeIt ei; + NodeIt ni; + GraphNode gn; + GraphEdge ge; + + size_t st; + bool b; + + //Path(const Graph &_G) {} //the constructor has been already called + + st=P.length(); //size_t length() const {return 0;} + b=P.empty(); //bool empty() const {} + P.clear(); //void clear() {} + + gn=P.target(); //GraphNode/*It*/ target() const {return INVALID;} + gn=P.source(); //GraphNode/*It*/ source() const {return INVALID;} + + ei=P.first(ei); //It& first(It &i) const { return i=It(*this); } + + ni=P.target(ei); //NodeIt target(const EdgeIt& e) const {} + ni=P.source(ei); //NodeIt source(const EdgeIt& e) const {} + + + ListGraph lg; + Path p(lg); + + EdgeIt i; //EdgeIt() {} + EdgeIt j(INVALID); //EdgeIt(Invalid) {} + EdgeIt k(p); //EdgeIt(const Path &_p) {} + + i=++j; //EdgeIt& operator++() {} + ++k; + b=(i==j); //bool operator==(const EdgeIt& e) const {return true;} + b=(i!=j); //bool operator!=(const EdgeIt& e) const {return true;} + + + NodeIt l; //NodeIt() {} + NodeIt m(INVALID); //NodeIt(Invalid) {} + NodeIt n(p); //NodeIt(const Path &_p) {} + + l=++m; //NodeIt& operator++() {} + b=(m==n); //bool operator==(const NodeIt& e) const {} + b=(m!=n); //bool operator!=(const NodeIt& e) const {} + + typename Path::Builder builder(p); //Builder(Path &_P) : P(_P) {} + builder.setStartNode(gn); //void setStartNode(const GraphNode &) {} + builder.pushFront(ge); //void pushFront(const GraphEdge& e) {} + builder.pushBack(ge); //void pushBack(const GraphEdge& e) {} + builder.commit(); //void commit() {} + builder.reserveFront(st); //void reserveFront(size_t r) {} + builder.reserveBack(st); //void reserveBack(size_t r) {} + +} + +template void checkCompilePath< concept::Path >(concept::Path &); +template void checkCompilePath< DirPath >(DirPath &); +template void checkCompilePath< UndirPath >(UndirPath &); + +int main() +{ +} diff -r d8475431bbbb -r 8e85e6bbefdf test/preflow_graph.dim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/preflow_graph.dim Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,20 @@ +p max 10 17 +n 2 s +n 9 t +a 1 2 20 +a 1 3 0 +a 2 2 3 +a 2 3 8 +a 2 4 8 +a 3 6 5 +a 4 3 5 +a 4 6 5 +a 4 7 5 +a 5 4 3 +a 6 8 3 +a 6 7 10 +a 6 9 10 +a 7 9 8 +a 9 10 20 +a 9 2 5 +a 10 6 5 \ No newline at end of file diff -r d8475431bbbb -r 8e85e6bbefdf test/preflow_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/preflow_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,201 @@ +/* -*- C++ -*- + * test/preflow_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include + +#include "test_tools.h" +#include +#include +#include +#include +#include + +using namespace lemon; + +void check_Preflow() +{ + typedef int VType; + typedef concept::StaticGraph Graph; + + typedef Graph::Node Node; + typedef Graph::Edge Edge; + typedef concept::ReadMap CapMap; + typedef concept::ReadWriteMap FlowMap; + typedef concept::ReadWriteMap CutMap; + + typedef Preflow PType; + + Graph g; + Node n; + CapMap cap; + FlowMap flow; + CutMap cut; + + PType preflow_test(g,n,n,cap,flow); + + preflow_test.run(); + preflow_test.flowValue(); + preflow_test.source(n); + preflow_test.flowMap(flow); + + preflow_test.phase1(PType::NO_FLOW); + preflow_test.minCut(cut); + + preflow_test.phase2(); + preflow_test.target(n); + preflow_test.capacityMap(cap); + preflow_test.minMinCut(cut); + preflow_test.maxMinCut(cut); +} + +int cut_value ( SmartGraph& g, SmartGraph::NodeMap& cut, + SmartGraph::EdgeMap& cap) { + + int c=0; + for(SmartGraph::EdgeIt e(g); e!=INVALID; ++e) { + if (cut[g.source(e)] && !cut[g.target(e)]) c+=cap[e]; + } + return c; +} + +int main() { + + typedef SmartGraph Graph; + + typedef Graph::Node Node; + typedef Graph::NodeIt NodeIt; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::EdgeMap CapMap; + typedef Graph::EdgeMap FlowMap; + typedef Graph::NodeMap CutMap; + + typedef Preflow PType; + + std::string f_name; + if( getenv("srcdir") ) + f_name = std::string(getenv("srcdir")); + else f_name = "."; + f_name += "/preflow_graph.dim"; + + std::ifstream file(f_name.c_str()); + + check(file, "Input file '" << f_name << "' not found."); + + Graph g; + Node s, t; + CapMap cap(g); + readDimacs(file, g, cap, s, t); + + FlowMap flow(g,0); + + + + PType preflow_test(g, s, t, cap, flow); + preflow_test.run(PType::ZERO_FLOW); + + CutMap min_cut(g,false); + preflow_test.minCut(min_cut); + int min_cut_value=cut_value(g,min_cut,cap); + + CutMap min_min_cut(g,false); + preflow_test.minMinCut(min_min_cut); + int min_min_cut_value=cut_value(g,min_min_cut,cap); + + CutMap max_min_cut(g,false); + preflow_test.maxMinCut(max_min_cut); + int max_min_cut_value=cut_value(g,max_min_cut,cap); + + check(preflow_test.flowValue() == min_cut_value && + min_cut_value == min_min_cut_value && + min_min_cut_value == max_min_cut_value, + "The max flow value is not equal to the three min cut values."); + + int flow_value=preflow_test.flowValue(); + + + + for(EdgeIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e]; + preflow_test.capacityMap(cap); + + preflow_test.phase1(PType::PRE_FLOW); + + CutMap min_cut1(g,false); + preflow_test.minCut(min_cut1); + min_cut_value=cut_value(g,min_cut1,cap); + + check(preflow_test.flowValue() == min_cut_value && + min_cut_value == 2*flow_value, + "The max flow value or the min cut value is wrong."); + + preflow_test.phase2(); + + CutMap min_cut2(g,false); + preflow_test.minCut(min_cut2); + min_cut_value=cut_value(g,min_cut2,cap); + + CutMap min_min_cut2(g,false); + preflow_test.minMinCut(min_min_cut2); + min_min_cut_value=cut_value(g,min_min_cut2,cap); + + preflow_test.maxMinCut(max_min_cut); + max_min_cut_value=cut_value(g,max_min_cut,cap); + + check(preflow_test.flowValue() == min_cut_value && + min_cut_value == min_min_cut_value && + min_min_cut_value == max_min_cut_value && + min_cut_value == 2*flow_value, + "The max flow value or the three min cut values were not doubled"); + + + + EdgeIt e(g); + for( int i=1; i==10; ++i ) { + flow.set(e,0); + ++e; + } + + preflow_test.flowMap(flow); + + NodeIt tmp1(g,s); + ++tmp1; + if ( tmp1 != INVALID ) s=tmp1; + + NodeIt tmp2(g,t); + ++tmp2; + if ( tmp2 != INVALID ) t=tmp2; + + preflow_test.source(s); + preflow_test.target(t); + + preflow_test.run(); + + CutMap min_cut3(g,false); + preflow_test.minCut(min_cut3); + min_cut_value=cut_value(g,min_cut3,cap); + + CutMap min_min_cut3(g,false); + preflow_test.minMinCut(min_min_cut3); + min_min_cut_value=cut_value(g,min_min_cut3,cap); + + preflow_test.maxMinCut(max_min_cut); + max_min_cut_value=cut_value(g,max_min_cut,cap); + + check(preflow_test.flowValue() == min_cut_value && + min_cut_value == min_min_cut_value && + min_min_cut_value == max_min_cut_value, + "The max flow value or the three min cut values are incorrect."); +} diff -r d8475431bbbb -r 8e85e6bbefdf test/suurballe_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/suurballe_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,108 @@ +/* -*- C++ -*- + * test/suurballe_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include +#include +//#include +#include "test_tools.h" + +using namespace lemon; + + +bool passed = true; + + +int main() +{ + typedef ListGraph Graph; + typedef Graph::Node Node; + typedef Graph::Edge Edge; + + Graph graph; + + //Ahuja könyv példája + + Node s=graph.addNode(); + Node v1=graph.addNode(); + Node v2=graph.addNode(); + Node v3=graph.addNode(); + Node v4=graph.addNode(); + Node v5=graph.addNode(); + Node t=graph.addNode(); + + Edge s_v1=graph.addEdge(s, v1); + Edge v1_v2=graph.addEdge(v1, v2); + Edge s_v3=graph.addEdge(s, v3); + Edge v2_v4=graph.addEdge(v2, v4); + Edge v2_v5=graph.addEdge(v2, v5); + Edge v3_v5=graph.addEdge(v3, v5); + Edge v4_t=graph.addEdge(v4, t); + Edge v5_t=graph.addEdge(v5, t); + + + Graph::EdgeMap length(graph); + + length.set(s_v1, 6); + length.set(v1_v2, 4); + length.set(s_v3, 10); + length.set(v2_v4, 5); + length.set(v2_v5, 1); + length.set(v3_v5, 5); + length.set(v4_t, 8); + length.set(v5_t, 8); + + std::cout << "Minlengthpaths algorithm test..." << std::endl; + + + int k=3; + Suurballe< Graph, Graph::EdgeMap > + surb_test(graph, length, s, t); + + check( surb_test.run(k) == 2 && surb_test.totalLength() == 46, + "Two paths, total length should be 46"); + + check( surb_test.checkComplementarySlackness(), + "Complementary slackness conditions are not met."); + + // typedef DirPath DPath; + // DPath P(graph); + + /* + surb_test.getPath(P,0); + check(P.length() == 4, "First path should contain 4 edges."); + std::cout< + +#include + +#include +#include +#include + +#include"test_tools.h" +#include"graph_test.h" +#include"sym_graph_test.h" + +/** +\file +This test makes consistency checks of list graph structures. + +G.addNode(), G.addEdge(), G.source(), G.target() + +\todo Checks for empty graphs and isolated points. +conversion. +*/ + +using namespace lemon; + +template void checkPetersen(Graph &G) +{ + typedef typename Graph::NodeIt NodeIt; + + + checkGraphNodeList(G,10); + checkGraphEdgeList(G,30); + checkGraphSymEdgeList(G,15); + + for(NodeIt n(G);n!=INVALID;++n) { + checkGraphInEdgeList(G,n,3); + checkGraphOutEdgeList(G,n,3); + } +} + +//Compile Graph +template void lemon::checkCompileStaticSymGraph +(concept::StaticSymGraph &); + +template void lemon::checkCompileSymGraph +(concept::ExtendableSymGraph &); + +template void lemon::checkCompileErasableSymGraph +(concept::ErasableSymGraph &); + + +//Compile SymSmartGraph +template void lemon::checkCompileSymGraph(SymSmartGraph &); +template +void lemon::concept::checkCompileGraphFindEdge(SymSmartGraph &); + +//Compile SymListGraph +template void lemon::checkCompileSymGraph(SymListGraph &); +template void lemon::checkCompileErasableSymGraph(SymListGraph &); +template +void lemon::concept::checkCompileGraphFindEdge(SymListGraph &); + +int main() +{ + { + SymSmartGraph G; + addSymPetersen(G); + checkPetersen(G); + } + { + SymListGraph G; + addSymPetersen(G); + checkPetersen(G); + } + + ///\file + ///\todo map tests. + ///\todo copy constr tests. + + std::cout << __FILE__ ": All tests passed.\n"; + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/sym_graph_test.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sym_graph_test.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,183 @@ +/* -*- C++ -*- + * test/sym_graph_test.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ +#ifndef LEMON_TEST_SYM_GRAPH_TEST_H +#define LEMON_TEST_SYM_GRAPH_TEST_H + + +#include "graph_test.h" +#include "test_tools.h" + +//! \ingroup misc +//! \file +//! \brief Some utility to test symmetric graph classes. +namespace lemon { + + /// \e + + /// \todo This should go to lemon/concept/symgraph.h + /// + template void checkCompileStaticSymGraph(Graph &G) + { + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::SymEdge SymEdge; + typedef typename Graph::SymEdgeIt SymEdgeIt; + typedef typename Graph::Edge Edge; + typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::InEdgeIt InEdgeIt; + typedef typename Graph::OutEdgeIt OutEdgeIt; + + lemon::concept::checkCompileStaticGraph(G); + + { + SymEdge i; SymEdge j(i); SymEdge k(INVALID); + i=j; + bool b; b=true; + b=(i==INVALID); b=(i!=INVALID); + b=(i==j); b=(i!=j); b=(iSymEdgeIt conversion + SymEdgeIt ni(G,n); + } + { + Edge i, j; + j = G.opposite(i); + } + { + Node n; + SymEdge se; + se=INVALID; + n=G.source(se); + n=G.target(se); + } + // id tests + { SymEdge n; int i=G.id(n); i=i; } + //SymEdgeMap tests + { + SymEdge k; + typename Graph::template SymEdgeMap m(G); + typename Graph::template SymEdgeMap const &cm = m; //Const map + //Inicialize with default value + typename Graph::template SymEdgeMap mdef(G,12); + typename Graph::template SymEdgeMap mm(cm); //Copy + typename Graph::template SymEdgeMap dm(cm); //Copy from another type + int v; + v=m[k]; m[k]=v; m.set(k,v); + v=cm[k]; + + m=cm; + dm=cm; //Copy from another type + { + //Check the typedef's + typename Graph::template SymEdgeMap::Value val; + val = 1; + typename Graph::template SymEdgeMap::Key key; + key = typename Graph::SymEdgeIt(G); + } + } + { //bool SymEdgeMap + SymEdge k; + typename Graph::template SymEdgeMap m(G); + typename Graph::template SymEdgeMap const &cm = m; //Const map + //Inicialize with default value + typename Graph::template SymEdgeMap mdef(G,12); + typename Graph::template SymEdgeMap mm(cm); //Copy + typename Graph::template SymEdgeMap dm(cm); //Copy from another type + bool v; + v=m[k]; m[k]=v; m.set(k,v); + v=cm[k]; + + m=cm; + dm=cm; //Copy from another type + m=dm; //Copy to another type + { + //Check the typedef's + typename Graph::template SymEdgeMap::Value val; + val=true; + typename Graph::template SymEdgeMap::Key key; + key= typename Graph::SymEdgeIt(G); + } + } + } + + template void checkCompileSymGraph(Graph &G) + { + checkCompileStaticSymGraph(G); + + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::SymEdge SymEdge; + typedef typename Graph::SymEdgeIt SymEdgeIt; + typedef typename Graph::Edge Edge; + typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::InEdgeIt InEdgeIt; + typedef typename Graph::OutEdgeIt OutEdgeIt; + + Node n,m; + n=G.addNode(); + m=G.addNode(); + SymEdge e; + e = G.addEdge(n,m); + + // G.clear(); + } + + template void checkCompileSymGraphEraseSymEdge(Graph &G) + { + typename Graph::SymEdge n; + G.erase(n); + } + + template void checkCompileErasableSymGraph(Graph &G) + { + checkCompileSymGraph(G); + lemon::concept::checkCompileGraphEraseNode(G); + checkCompileSymGraphEraseSymEdge(G); + } + + template void checkGraphSymEdgeList(Graph &G, int nn) + { + typedef typename Graph::SymEdgeIt SymEdgeIt; + + SymEdgeIt e(G); + for(int i=0;i +#include + +#include + +using namespace lemon; + +//! \ingroup misc +//! \file +//! \brief Some utilities to write test programs. + + +///If \c rc is fail, writes an error message end exit. + +///If \c rc is fail, writes an error message end exit. +///The error message contains the file name and the line number of the +///source code in a standard from, which makes it possible to go there +///using good source browsers like e.g. \c emacs. +/// +///For example +///\code check(0==1,"This is obviously false.");\endcode will +///print this (and then exits). +///\verbatim graph_test.cc:123: error: This is obviously false. \endverbatim +/// +///\todo It should be in \c error.h +#define check(rc, msg) \ + if(!(rc)) { \ + std::cerr << __FILE__ ":" << __LINE__ << ": error: " << msg << std::endl; \ + exit(1); \ + } else { } \ + +///Structure returned by \ref addPetersen(). + +///Structure returned by \ref addPetersen(). +/// +template struct PetStruct +{ + ///Vector containing the outer nodes. + std::vector outer; + ///Vector containing the inner nodes. + std::vector inner; + ///Vector containing the edges of the inner circle. + std::vector incir; + ///Vector containing the edges of the outer circle. + std::vector outcir; + ///Vector containing the chord edges. + std::vector chords; +}; + + + +///Adds a Petersen graph to \c G. + +///Adds a Petersen graph to \c G. +///\return The nodes and edges of the generated graph. + +template +PetStruct addPetersen(Graph &G,int num = 5) +{ + PetStruct n; + + for(int i=0;i void bidirGraph(Graph &G) +{ + typedef typename Graph::Edge Edge; + typedef typename Graph::EdgeIt EdgeIt; + + std::vector ee; + + for(EdgeIt e(G);e!=INVALID;++e) ee.push_back(e); + + for(typename std::vector::iterator p=ee.begin();p!=ee.end();p++) + G.addEdge(G.target(*p),G.source(*p)); +} + + +/// \brief Checks the bidirectioned Petersen graph. +/// +/// Checks the bidirectioned Petersen graph. +/// +template void checkBidirPetersen(Graph &G, int num = 5) +{ + typedef typename Graph::Node Node; + + typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::NodeIt NodeIt; + + checkGraphNodeList(G, 2 * num); + checkGraphEdgeList(G, 6 * num); + + for(NodeIt n(G);n!=INVALID;++n) { + checkGraphInEdgeList(G, n, 3); + checkGraphOutEdgeList(G, n, 3); + } +} + +///Structure returned by \ref addSymPetersen(). + +///Structure returned by \ref addSymPetersen(). +/// +template struct SymPetStruct +{ + ///Vector containing the outer nodes. + std::vector outer; + ///Vector containing the inner nodes. + std::vector inner; + ///Vector containing the edges of the inner circle. + std::vector incir; + ///Vector containing the edges of the outer circle. + std::vector outcir; + ///Vector containing the chord edges. + std::vector chords; +}; + +///Adds a Petersen graph to the symmetric \c G. + +///Adds a Petersen graph to the symmetric \c G. +///\return The nodes and edges of the generated graph. + +template +SymPetStruct addSymPetersen(Graph &G,int num=5) +{ + SymPetStruct n; + + for(int i=0;i + +///\file \brief Test cases for time_measure.h +/// +///\todo To be extended + + +using namespace lemon; + +int main() +{ + Timer T; + while(T.getRealTime()<1.0) ; + std::cout << T << '\n'; + T.reset(); + while(T.getRealTime()<2.0) ; + std::cout << T << '\n'; + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/undir_graph_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/undir_graph_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,120 @@ +// -*- C++ -*- + +#include +#include +#include +#include +#include + +#include + +#include "test_tools.h" + + +using namespace lemon; +using namespace lemon::concept; + +void check_concepts() { + typedef UndirGraphExtender UndirListGraphBase; + + typedef IterableUndirGraphExtender< + AlterableUndirGraphExtender > IterableUndirListGraph; + + typedef MappableUndirGraphExtender + MappableUndirListGraph; + + typedef ErasableUndirGraphExtender< + ClearableUndirGraphExtender< + ExtendableUndirGraphExtender > > Graph; + + checkConcept(); + checkConcept(); + checkConcept(); + + checkConcept(); + checkConcept(); + + checkConcept(); + checkConcept(); + + checkConcept(); + checkConcept(); + + checkConcept(); +} + +template +void check_item_counts(Graph &g, int n, int e) { + check(countNodes(g)==n, "Wrong node number."); + check(countEdges(g)==2*e, "Wrong edge number."); +} + +template +void print_items(Graph &g) { + + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::UndirEdgeIt UEdgeIt; + typedef typename Graph::EdgeIt EdgeIt; + + std::cout << "Nodes" << std::endl; + int i=0; + for(NodeIt it(g); it!=INVALID; ++it, ++i) { + std::cout << " " << i << ": " << g.id(it) << std::endl; + } + + std::cout << "UndirEdge" << std::endl; + i=0; + for(UEdgeIt it(g); it!=INVALID; ++it, ++i) { + std::cout << " " << i << ": " << g.id(it) + << " (" << g.id(g.source(it)) << ", " << g.id(g.target(it)) + << ")" << std::endl; + } + + std::cout << "Edge" << std::endl; + i=0; + for(EdgeIt it(g); it!=INVALID; ++it, ++i) { + std::cout << " " << i << ": " << g.id(it) + << " (" << g.id(g.source(it)) << ", " << g.id(g.target(it)) + << ")" << std::endl; + } + +} + +template +void check_graph() { + + typedef typename Graph::Node Node; + typedef typename Graph::UndirEdge UEdge; + typedef typename Graph::Edge Edge; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::UndirEdgeIt UEdgeIt; + typedef typename Graph::EdgeIt EdgeIt; + + Graph g; + + check_item_counts(g,0,0); + + Node + n1 = g.addNode(), + n2 = g.addNode(), + n3 = g.addNode(); + + UEdge + e1 = g.addEdge(n1, n2), + e2 = g.addEdge(n2, n3); + + // print_items(g); + + check_item_counts(g,3,2); + + +} + +int main() { + check_concepts(); + + check_graph(); + check_graph(); + + return 0; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/unionfind_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unionfind_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,208 @@ +/* -*- C++ -*- + * test/unionfind_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include + +#include +#include +#include "test_tools.h" + +using namespace lemon; +using namespace std; + +template +class BaseMap : public StdMap {}; + +typedef UnionFindEnum UFE; + +void print(UFE const &ufe) { + UFE::ClassIt cit; + cout << "Print the classes of the structure:" << endl; + int i = 1; + for (ufe.first(cit); ufe.valid(cit); ufe.next(cit)) { + cout << " " << i << " (" << cit << "):" << flush; + UFE::ItemIt iit; + for (ufe.first(iit, cit); ufe.valid(iit); ufe.next(iit)) { + cout << " " << iit << flush; + } + cout << endl; + i++; + } + cout << "done" << endl; +} + + +int main() { + UFE::MapType base; + UFE U(base); + +// print(U); + + cout << "Insert 1..." << endl; + U.insert(1); +// print(U); + + cout << "Insert 2..." << endl; + U.insert(2); +// print(U); + + cout << "Join 1 and 2..." << endl; + check(U.join(1,2),"Test failed."); +// print(U); + + cout << "Insert 3, 4, 5, 6, 7..." << endl; + U.insert(3); + U.insert(4); + U.insert(5); + U.insert(6); + U.insert(7); +// print (U); + + cout << "Join 1 - 4, 2 - 4 and 3 - 5 ..." << endl; + check(U.join(1,4),"Test failed."); + check(!U.join(2,4),"Test failed."); + check(U.join(3,5),"Test failed."); +// print(U); + + cout << "Insert 8 to the component of 5 ..." << endl; + U.insert(8,5); +// print(U); + + cout << "Size of the class of 4: " << U.size(4) << endl; + check(U.size(4) == 3,"Test failed."); + cout << "Size of the class of 5: " << U.size(5) << endl; + check(U.size(5) == 3,"Test failed."); + cout << "Size of the class of 6: " << U.size(6) << endl; + check(U.size(6) == 1,"Test failed."); + cout << "Size of the class of 2: " << U.size(2) << endl; + check(U.size(2) == 3,"Test failed."); + + cout << "Insert 9 ..." << endl; + U.insert(9); +// print(U); + cout << "Insert 10 to the component of 9 ..." << endl; + U.insert(10,9); +// print(U); + + cout << "Join 8 and 10..." << endl; + check(U.join(8,10),"Test failed."); +// print(U); + + cout << "Move 9 to the class of 4 ..." << endl; + check(U.move(9,4),"Test failed."); +// print(U); + + cout << "Move 9 to the class of 2 ..." << endl; + check(!U.move(9,2),"Test failed."); +// print(U); + + cout << "Size of the class of 4: " << U.size(4) << endl; + check(U.size(4) == 4,"Test failed."); + cout << "Size of the class of 9: " << U.size(9) << endl; + check(U.size(9) == 4,"Test failed."); + + cout << "Move 5 to the class of 6 ..." << endl; + check(U.move(5,6),"Test failed."); +// print(U); + + cout << "Size of the class of 5: " << U.size(5) << endl; + check(U.size(5) == 2,"Test failed."); + cout << "Size of the class of 8: " << U.size(8) << endl; + check(U.size(8) == 3,"Test failed."); + + cout << "Move 7 to the class of 10 ..." << endl; + check(U.move(7,10),"Test failed."); +// print(U); + + cout << "Size of the class of 7: " << U.size(7) << endl; + check(U.size(7) == 4,"Test failed."); + + cout <<"Erase 9... " << endl; + U.erase(9); +// print(U); + + cout <<"Erase 1... " << endl; + U.erase(1); +// print(U); + + cout << "Size of the class of 4: " << U.size(4) << endl; + check(U.size(4) == 2,"Test failed."); + cout << "Size of the class of 2: " << U.size(2) << endl; + check(U.size(2) == 2,"Test failed."); + + + cout <<"Erase 1... " << endl; + U.erase(1); +// print(U); + + cout <<"Erase 6... " << endl; + U.erase(6); +// print(U); + + cout << "Split the class of 8... " << endl; + U.split(8); +// print(U); + + + cout << "Size of the class of 4: " << U.size(4) << endl; + check(U.size(4) == 2,"Test failed."); + cout << "Size of the class of 3: " << U.size(3) << endl; + check(U.size(3) == 1,"Test failed."); + cout << "Size of the class of 2: " << U.size(2) << endl; + check(U.size(2) == 2,"Test failed."); + + + cout << "Join 3 - 4 and 2 - 4 ..." << endl; + check(U.join(3,4),"Test failed."); + check(!U.join(2,4),"Test failed."); +// print(U); + + + cout << "Size of the class of 4: " << U.size(4) << endl; + check(U.size(4) == 3,"Test failed."); + cout << "Size of the class of 3: " << U.size(3) << endl; + check(U.size(3) == 3,"Test failed."); + cout << "Size of the class of 2: " << U.size(2) << endl; + check(U.size(2) == 3,"Test failed."); + + cout << "Calling makeRep(4)..." << endl; + U.makeRep(4); +// print(U); + cout << "Calling makeRep(3)..." << endl; + U.makeRep(3); +// print(U); + cout << "Calling makeRep(2)..." << endl; + U.makeRep(2); +// print(U); + + cout << "Size of the class of 4: " << U.size(4) << endl; + check(U.size(4) == 3,"Test failed."); + cout << "Size of the class of 3: " << U.size(3) << endl; + check(U.size(3) == 3,"Test failed."); + cout << "Size of the class of 2: " << U.size(2) << endl; + check(U.size(2) == 3,"Test failed."); + + + cout << "eraseClass 4 ..." << endl; + U.eraseClass(4); +// print(U); + + cout << "eraseClass 7 ..." << endl; + U.eraseClass(7); +// print(U); + + cout << "done." << endl; +} diff -r d8475431bbbb -r 8e85e6bbefdf test/xy_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/xy_test.cc Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,80 @@ +/* -*- C++ -*- + * test/xy_test.cc - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include +#include "test_tools.h" + +using namespace std; +using namespace lemon; +int main() +{ + + cout << "Testing classes `xy' and `boundingbox'." << endl; + + typedef xy XY; + + XY seged; + XY a(1,2); + XY b(3,4); + + seged = a+b; + check(seged.x==4 && seged.y==6, "Wrong vector addition"); + + seged = a-b; + check(seged.x==-2 && seged.y==-2, "a-b"); + + check(a.normSquare()==5,"Wrong norm calculation"); + check(a*b==11, "a*b"); + + int l=2; + seged = a*l; + check(seged.x==2 && seged.y==4, "a*l"); + + seged = b/l; + check(seged.x==1 && seged.y==2, "b/l"); + + typedef BoundingBox BB; + BB doboz1; + check(doboz1.empty(), "It should be empty."); + + doboz1 += a; + check(!doboz1.empty(), "It should not be empty."); + doboz1 += b; + + check(doboz1.bottomLeft().x==1 && + doboz1.bottomLeft().y==2 && + doboz1.topRight().x==3 && + doboz1.topRight().y==4, + "added points to box"); + + seged.x=2;seged.y=3; + check(doboz1.inside(seged),"It should be inside."); + + seged.x=1;seged.y=3; + check(doboz1.inside(seged),"It should be inside."); + + seged.x=0;seged.y=3; + check(!doboz1.inside(seged),"It should not be inside."); + + BB doboz2(seged); + check(!doboz2.empty(), + "It should not be empty. Constructed from 1 point."); + + doboz2 += doboz1; + check(doboz2.inside(seged), + "It should be inside. Incremented a box with an other."); +}