# HG changeset patch # User deba # Date 1174578050 0 # Node ID 21eb3ccdc3dfa28b28a27d7a3a256743874d2d18 # Parent 086fc76d591d1a6638e97a6c835fe949c41bb326 Right dimacs format for min cost flows Bug fixes in tolerance and min_mean_cycle diff -r 086fc76d591d -r 21eb3ccdc3df demo/dim_to_dot.cc --- a/demo/dim_to_dot.cc Thu Mar 22 06:36:50 2007 +0000 +++ b/demo/dim_to_dot.cc Thu Mar 22 15:40:50 2007 +0000 @@ -17,17 +17,15 @@ */ ///\file -///\brief Dim (Dimacs) to Dot (Graphviz) converter +///\brief Dim (DIMACS) to Dot (Graphviz) converter /// -/// This program can convert the dimacs format to graphviz dot format. +/// This program can convert the DIMACS format to Graphviz format. /// -/// Use a DIMACS max flow file as stdin. +/// dim_to_dot dimacs_max_flow_file > dot_output_file /// -/// dim_to_dot < dimacs_max_flow_file > 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. +/// 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 dim_to_dot.cc @@ -46,12 +44,11 @@ { if(argc<2) { - std::cerr << "USAGE: sub_graph_adaptor_demo input_file.dim" << std::endl; + std::cerr << "USAGE: dim_to_dot input_file.dim" << std::endl; std::cerr << "The file 'input_file.dim' has to contain a max flow instance in DIMACS format (e.g. sub_graph_adaptor_demo.dim is such a file)." << std::endl; return 0; } - //input stream to read the graph from std::ifstream is(argv[1]); diff -r 086fc76d591d -r 21eb3ccdc3df lemon/dimacs.h --- a/lemon/dimacs.h Thu Mar 22 06:36:50 2007 +0000 +++ b/lemon/dimacs.h Thu Mar 22 15:40:50 2007 +0000 @@ -27,11 +27,10 @@ /// \ingroup dimacs_group /// \file -/// \brief Dimacs file format reader. +/// \brief DIMACS file format reader. namespace lemon { - /// ///@defgroup dimacs_group DIMACS format ///\brief Read and write files in DIMACS format /// @@ -41,114 +40,147 @@ /// \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 supply + /// amount of the nodes are written to \c supply (signed). The + /// lower bounds, capacities and costs of the edges are written to + /// \c lower, \c capacity and \c cost. + /// + /// \author Marton Makai and Peter Kovacs + template + void readDimacs( std::istream& is, + Graph &g, + SupplyMap& supply, + CapacityMap& lower, + CapacityMap& capacity, + CostMap& cost ) + { + g.clear(); + std::vector nodes; + typename Graph::Edge e; + std::string problem, str; + char c; + int n, m; + int i, j; + typename SupplyMap::Value sup; + typename CapacityMap::Value low; + typename CapacityMap::Value cap; + typename CostMap::Value co; + while (is >> c) { + switch (c) { + case 'c': // comment line + getline(is, str); + break; + case 'p': // problem definition line + is >> problem >> n >> m; + getline(is, str); + if (problem != "min") return; + nodes.resize(n + 1); + for (int k = 1; k <= n; ++k) { + nodes[k] = g.addNode(); + supply[nodes[k]] = 0; + } + break; + case 'n': // node definition line + is >> i >> sup; + getline(is, str); + supply.set(nodes[i], sup); + break; + case 'a': // edge (arc) definition line + is >> i >> j >> low >> cap >> co; + getline(is, str); + e = g.addEdge(nodes[i], nodes[j]); + lower.set(e, low); + if (cap >= 0) + capacity.set(e, cap); + else + capacity.set(e, -1); + cost.set(e, co); + break; + } + } + } - /// 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. + /// 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 + template void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity, - typename Graph::Node &s, typename Graph::Node &t, - CostMap& cost) { + typename Graph::Node &s, typename Graph::Node &t) { g.clear(); + std::vector nodes; + typename Graph::Edge e; + std::string problem; + char c, d; + int n, m; + int i, j; 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) { + while (is >> c) { switch (c) { - case 'c': //comment + case 'c': // comment line getline(is, str); break; - case 'p': //problem definition + case 'p': // problem definition line is >> problem >> n >> m; getline(is, str); - nodes.resize(n+1); - for (int k=1; k<=n; ++k) nodes[k]=g.addNode(); + 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 + case 'n': // node definition line + if (problem == "sp") { // shortest path problem is >> i; getline(is, str); - s=nodes[i]; + s = nodes[i]; } - if (problem=="max" || problem=="min") { //((max) or (min cost)) flow problem + if (problem == "max") { // max flow problem is >> i >> d; getline(is, str); - if (d=='s') s=nodes[i]; - if (d=='t') t=nodes[i]; + if (d == 's') s = nodes[i]; + if (d == 't') t = nodes[i]; } break; - case 'a': - if ( problem == "max" || problem == "sp") { + case 'a': // edge (arc) definition line + if (problem == "max" || problem == "sp") { is >> i >> j >> _cap; getline(is, str); - e=g.addEdge(nodes[i], nodes[j]); - //capacity.update(); + e = g.addEdge(nodes[i], nodes[j]); 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]); - } + 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. + /// DIMACS shortest path reader function. /// - /// \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 + /// 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. @@ -157,70 +189,67 @@ template void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity, typename Graph::Node &s) { - NullMap n; - readDimacs(is, g, capacity, s, s, n); + readDimacs(is, g, capacity, s, s); } - - /// Dimacs capacitated graph reader function. - + /// 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() + /// 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); + readDimacs(is, g, capacity, u, u); } - - /// Dimacs plain graph reader function. - + /// 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 + /// 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(). + /// \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); + readDimacs(is, g, n, u, u); } - - - - /// write matching problem + /// DIMACS plain graph writer function. + /// + /// This function writes a graph without any designated nodes and + /// maps into DIMACS format, i.e. into DIMACS file having a line + /// starting with + /// \code + /// p mat + /// \endcode + /// + /// \author Marton Makai template void writeDimacs(std::ostream& os, const Graph &g) { typedef typename Graph::NodeIt NodeIt; typedef typename Graph::EdgeIt EdgeIt; + os << "c matching problem" << std::endl; + os << "p mat " << g.nodeNum() << " " << g.edgeNum() << std::endl; + typename Graph::template NodeMap nodes(g); - - os << "c matching problem" << std::endl; - - int i=1; - for(NodeIt v(g); v!=INVALID; ++v) { + 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) { + for(EdgeIt e(g); e != INVALID; ++e) { os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)] << std::endl; } - } /// @} diff -r 086fc76d591d -r 21eb3ccdc3df lemon/min_mean_cycle.h --- a/lemon/min_mean_cycle.h Thu Mar 22 06:36:50 2007 +0000 +++ b/lemon/min_mean_cycle.h Thu Mar 22 15:40:50 2007 +0000 @@ -33,11 +33,11 @@ /// \addtogroup min_cost_flow /// @{ - /// \brief Implementation of Karp's algorithm for finding a - /// minimum mean cycle. + /// \brief Implementation of Karp's algorithm for finding a + /// minimum mean (directed) cycle. /// - /// The \ref lemon::MinMeanCycle "MinMeanCycle" implements Karp's - /// algorithm for finding a minimum mean cycle. + /// The \ref lemon::MinMeanCycle "MinMeanCycle" implements Karp's + /// algorithm for finding a minimum mean (directed) cycle. /// /// \param Graph The directed graph type the algorithm runs on. /// \param LengthMap The type of the length (cost) map. @@ -57,11 +57,10 @@ 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; typedef typename LengthMap::Value Length; - + typedef typename Graph::template NodeMap IntNodeMap; typedef typename Graph::template NodeMap PredNodeMap; typedef Path Path; @@ -69,22 +68,24 @@ typedef typename NodeVector::iterator NodeVectorIt; protected: - + /// \brief Data sturcture for path data. - struct PathData { + struct PathData + { bool found; Length dist; Edge pred; - PathData(bool _found = false, Length _dist = 0) : + PathData(bool _found = false, Length _dist = 0) : found(_found), dist(_dist), pred(INVALID) {} - PathData(bool _found, Length _dist, Edge _pred) : + PathData(bool _found, Length _dist, Edge _pred) : found(_found), dist(_dist), pred(_pred) {} }; - + private: - - typedef typename Graph::template NodeMap > PathVectorNodeMap; - + + typedef typename Graph::template NodeMap > + PathDataNodeMap; + protected: /// \brief Node map for storing path data. @@ -92,7 +93,7 @@ /// Node map for storing path data of all nodes in the current /// component. dmap[v][k] is the length of a shortest directed walk /// to node v from the starting node containing exactly k edges. - PathVectorNodeMap dmap; + PathDataNodeMap dmap; /// \brief The directed graph the algorithm runs on. const Graph& graph; @@ -103,16 +104,20 @@ Length cycle_length; /// \brief The number of edges in the found cycle. int cycle_size; + /// \brief A node for obtaining a minimum mean cycle. + Node cycle_node; + /// \brief The found cycle. Path *cycle_path; - /// \brief The found cycle. + /// \brief The algorithm uses local \ref lemon::Path "Path" + /// structure to store the found cycle. bool local_path; /// \brief Node map for identifying strongly connected components. IntNodeMap comp; /// \brief The number of strongly connected components. int comp_num; - /// \brief %Counter for identifying the current component. + /// \brief Counter for identifying the current component. int comp_cnt; /// \brief Nodes of the current component. NodeVector nodes; @@ -129,8 +134,8 @@ /// \param _length The length (cost) of the edges. MinMeanCycle( const Graph& _graph, const LengthMap& _length ) : - graph(_graph), length(_length), dmap(_graph), - cycle_length(0), cycle_size(-1), comp(_graph), + graph(_graph), length(_length), dmap(_graph), comp(_graph), + cycle_length(0), cycle_size(-1), cycle_node(INVALID), cycle_path(NULL), local_path(false) { } @@ -140,15 +145,6 @@ } protected: - - /// \brief Initializes the internal data structures. - void init() { - comp_num = stronglyConnectedComponents(graph, comp); - if (!cycle_path) { - local_path = true; - cycle_path = new Path; - } - } /// \brief Initializes the internal data structures for the current /// component. @@ -158,7 +154,6 @@ for (NodeIt v(graph); v != INVALID; ++v) { if (comp[v] == comp_cnt) nodes.push_back(v); } - // Creating vectors for all nodes int n = nodes.size(); for (NodeVectorIt vi = nodes.begin(); vi != nodes.end(); ++vi) { @@ -166,16 +161,19 @@ } } - /// \brief Processes all rounds of computing required path data. + /// \brief Processes all rounds of computing required path data for + /// the current component. void processRounds() { dmap[nodes[0]][0] = PathData(true, 0); process.clear(); - for (OutEdgeIt oe(graph, nodes[0]); oe != INVALID; ++oe) { - Node v = graph.target(oe); + // Processing the first round + for (OutEdgeIt e(graph, nodes[0]); e != INVALID; ++e) { + Node v = graph.target(e); if (comp[v] != comp_cnt || v == nodes[0]) continue; - dmap[v][1] = PathData(true, length[oe], oe); + dmap[v][1] = PathData(true, length[e], e); process.push_back(v); } + // Processing other rounds int n = nodes.size(), k; for (k = 2; k <= n && process.size() < n; ++k) { processNextBuildRound(k); @@ -190,12 +188,15 @@ void processNextBuildRound(int k) { NodeVector next; for (NodeVectorIt ui = process.begin(); ui != process.end(); ++ui) { - for (OutEdgeIt oe(graph, *ui); oe != INVALID; ++oe) { - Node v = graph.target(oe); + for (OutEdgeIt e(graph, *ui); e != INVALID; ++e) { + Node v = graph.target(e); if (comp[v] != comp_cnt) continue; - if ( !dmap[v][k].found || (dmap[v][k].dist > dmap[*ui][k-1].dist + length[oe]) ) { - if (!dmap[v][k].found) next.push_back(v); - dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[oe], oe); + if (!dmap[v][k].found) { + next.push_back(v); + dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[e], e); + } + else if (dmap[*ui][k-1].dist + length[e] < dmap[v][k].dist) { + dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[e], e); } } } @@ -206,44 +207,39 @@ /// using \ref nodes vector instead of \ref process vector. void processNextFullRound(int k) { for (NodeVectorIt ui = nodes.begin(); ui != nodes.end(); ++ui) { - for (OutEdgeIt oe(graph, *ui); oe != INVALID; ++oe) { - Node v = graph.target(oe); + for (OutEdgeIt e(graph, *ui); e != INVALID; ++e) { + Node v = graph.target(e); if (comp[v] != comp_cnt) continue; - if ( !dmap[v][k].found || (dmap[v][k].dist > dmap[*ui][k-1].dist + length[oe]) ) { - dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[oe], oe); + if ( !dmap[v][k].found || + dmap[*ui][k-1].dist + length[e] < dmap[v][k].dist ) { + dmap[v][k] = PathData(true, dmap[*ui][k-1].dist + length[e], e); } } } } - /// \brief Finds the minimum cycle mean value according to the path - /// data stored in \ref dmap. - /// - /// Finds the minimum cycle mean value according to the path data - /// stored in \ref dmap. - /// - /// \retval min_length The total length of the found cycle. - /// \retval min_size The number of edges in the found cycle. - /// \retval min_node A node for obtaining a critical cycle. - /// - /// \return \c true if a cycle exists in the graph. - bool findMinCycleMean(Length &min_length, int &min_size, Node &min_node) { + /// \brief Finds the minimum cycle mean value in the current + /// component. + bool findCurrentMin(Length &min_length, int &min_size, Node &min_node) { bool found_min = false; for (NodeVectorIt vi = nodes.begin(); vi != nodes.end(); ++vi) { + int n = nodes.size(); + if (!dmap[*vi][n].found) continue; Length len; int size; bool found_one = false; - int n = nodes.size(); for (int k = 0; k < n; ++k) { + if (!dmap[*vi][k].found) continue; Length _len = dmap[*vi][n].dist - dmap[*vi][k].dist; int _size = n - k; - if ( dmap[*vi][n].found && dmap[*vi][k].found && (!found_one || len * _size < _len * size) ) { + if (!found_one || len * _size < _len * size) { found_one = true; len = _len; size = _size; } } - if (found_one && (!found_min || len * min_size < min_length * size)) { + if ( found_one && + (!found_min || len * min_size < min_length * size) ) { found_min = true; min_length = len; min_size = size; @@ -253,94 +249,152 @@ return found_min; } - /// \brief Finds a critical (minimum mean) cycle according to the - /// path data stored in \ref dmap. - void findCycle(const Node &min_n) { - IntNodeMap reached(graph, -1); - int r = reached[min_n] = dmap[min_n].size() - 1; - Node u = graph.source(dmap[min_n][r].pred); - while (reached[u] < 0) { - reached[u] = --r; - u = graph.source(dmap[u][r].pred); - } - r = reached[u]; - Edge ce = dmap[u][r].pred; - cycle_path->addFront(ce); - Node v; - while ((v = graph.source(ce)) != u) { - ce = dmap[v][--r].pred; - cycle_path->addFront(ce); - } - } + public: - public: - /// \brief Runs the algorithm. /// /// Runs the algorithm. /// /// \return \c true if a cycle exists in the graph. + /// + /// \note Apart from the return value, m.run() is just a shortcut + /// of the following code. + /// \code + /// m.init(); + /// m.findMinMean(); + /// m.findCycle(); + /// \endcode bool run() { init(); - // Searching for the minimum mean cycle in all components - bool found_cycle = false; - Node cycle_node; + findMinMean(); + return findCycle(); + } + + /// \brief Initializes the internal data structures. + void init() { + comp_num = stronglyConnectedComponents(graph, comp); + if (!cycle_path) { + local_path = true; + cycle_path = new Path; + } + } + + /// \brief Finds the minimum cycle mean value in the graph. + /// + /// Computes all the required path data and finds the minimum cycle + /// mean value in the graph. + /// + /// \return \c true if a cycle exists in the graph. + /// + /// \pre \ref init() must be called before using this function. + bool findMinMean() { + cycle_node = INVALID; for (comp_cnt = 0; comp_cnt < comp_num; ++comp_cnt) { - initCurrent(); processRounds(); Length min_length; int min_size; Node min_node; - bool found_min = findMinCycleMean(min_length, min_size, min_node); + bool found_min = findCurrentMin(min_length, min_size, min_node); - if ( found_min && (!found_cycle || min_length * cycle_size < cycle_length * min_size) ) { - found_cycle = true; + if ( found_min && (cycle_node == INVALID || + min_length * cycle_size < cycle_length * min_size) ) { cycle_length = min_length; cycle_size = min_size; cycle_node = min_node; } } - if (found_cycle) findCycle(cycle_node); - return found_cycle; + return (cycle_node != INVALID); } - /// \brief Returns the total length of the found critical cycle. + /// \brief Finds a critical (minimum mean) cycle. /// - /// Returns the total length of the found critical cycle. + /// Finds a critical (minimum mean) cycle using the path data + /// stored in \ref dmap. + /// + /// \return \c true if a cycle exists in the graph. + /// + /// \pre \ref init() and \ref findMinMean() must be called before + /// using this function. + bool findCycle() { + if (cycle_node == INVALID) return false; + cycle_length = 0; + cycle_size = 0; + IntNodeMap reached(graph, -1); + int r = reached[cycle_node] = dmap[cycle_node].size() - 1; + Node u = graph.source(dmap[cycle_node][r].pred); + while (reached[u] < 0) { + reached[u] = --r; + u = graph.source(dmap[u][r].pred); + } + r = reached[u]; + Edge e = dmap[u][r].pred; + cycle_path->addFront(e); + cycle_length = cycle_length + length[e]; + ++cycle_size; + Node v; + while ((v = graph.source(e)) != u) { + e = dmap[v][--r].pred; + cycle_path->addFront(e); + cycle_length = cycle_length + length[e]; + ++cycle_size; + } + return true; + } + + /// \brief Resets the internal data structures. + /// + /// Resets the internal data structures so that \ref findMinMean() + /// and \ref findCycle() can be called again (e.g. when the + /// underlaying graph has been modified). + void reset() { + for (NodeIt u(graph); u != INVALID; ++u) + dmap[u].clear(); + cycle_node = INVALID; + if (cycle_path) cycle_path->clear(); + comp_num = stronglyConnectedComponents(graph, comp); + } + + /// \brief Returns the total length of the found cycle. + /// + /// Returns the total length of the found cycle. /// /// \pre \ref run() must be called before using this function. Length cycleLength() const { return cycle_length; } - /// \brief Returns the number of edges in the found critical - /// cycle. + /// \brief Returns the number of edges in the found cycle. /// - /// Returns the number of edges in the found critical cycle. + /// Returns the number of edges in the found cycle. /// /// \pre \ref run() must be called before using this function. int cycleEdgeNum() const { return cycle_size; } - /// \brief Returns the mean length of the found critical cycle. + /// \brief Returns the mean length of the found cycle. /// - /// Returns the mean length of the found critical cycle. + /// Returns the mean length of the found cycle. /// /// \pre \ref run() must be called before using this function. /// /// \warning LengthMap::Value must be convertible to double. + /// + /// \note m.minMean() is just a shortcut of the following code. + /// \code + /// return m.cycleEdgeNum() / double(m.cycleLength()); + /// \endcode double minMean() const { - return (double)cycle_length / (double)cycle_size; + return cycle_length / (double)cycle_size; } /// \brief Returns a const reference to the \ref lemon::Path "Path" - /// structure of the found flow. + /// structure of the found cycle. /// /// Returns a const reference to the \ref lemon::Path "Path" - /// structure of the found flow. + /// structure of the found cycle. /// /// \pre \ref run() must be called before using this function. /// diff -r 086fc76d591d -r 21eb3ccdc3df lemon/tolerance.h --- a/lemon/tolerance.h Thu Mar 22 06:36:50 2007 +0000 +++ b/lemon/tolerance.h Thu Mar 22 15:40:50 2007 +0000 @@ -305,6 +305,73 @@ ///Returns zero static Value zero() {return 0;} }; + + + ///Long integer specialization of \ref Tolerance. + + ///Long integer specialization of \ref Tolerance. + ///\sa Tolerance + template<> + class Tolerance + { + public: + ///\e + typedef long int Value; + + ///\name Comparisons + ///See \ref Tolerance for more details. + + ///@{ + + ///Returns \c true if \c a is \e surely strictly less than \c b + static bool less(Value a,Value b) { return aa; } + ///Returns \c true if \c a is \e surely non-zero + static bool nonZero(Value a) { return a!=0;}; + + ///@} + + ///Returns zero + static Value zero() {return 0;} + }; + + ///Unsigned long integer specialization of \ref Tolerance. + + ///Unsigned long integer specialization of \ref Tolerance. + ///\sa Tolerance + template<> + class Tolerance + { + public: + ///\e + typedef unsigned long int Value; + + ///\name Comparisons + ///See \ref Tolerance for more details. + + ///@{ + + ///Returns \c true if \c a is \e surely strictly less than \c b + static bool less(Value a,Value b) { return a DoubleMap; + typedef Graph::EdgeMap DoubleEdgeMap; + typedef Graph::NodeMap DoubleNodeMap; std::string inputName; std::string outputName; @@ -115,19 +116,19 @@ if (mincostflow) { Graph graph; - Node s, t; - DoubleMap cost(graph), capacity(graph); - readDimacs(is, graph, capacity, s, t, cost); + DoubleNodeMap supply(graph); + DoubleEdgeMap lower(graph), capacity(graph), cost(graph); + readDimacs(is, graph, supply, lower, capacity, cost); GraphWriter(os, graph). + writeNodeMap("supply", supply). + writeEdgeMap("lower", lower). writeEdgeMap("capacity", capacity). - writeNode("source", s). - writeNode("target", t). writeEdgeMap("cost", cost). run(); } else if (maxflow) { Graph graph; Node s, t; - DoubleMap capacity(graph); + DoubleEdgeMap capacity(graph); readDimacs(is, graph, capacity, s, t); GraphWriter(os, graph). writeEdgeMap("capacity", capacity). @@ -137,7 +138,7 @@ } else if (shortestpath) { Graph graph; Node s; - DoubleMap capacity(graph); + DoubleEdgeMap capacity(graph); readDimacs(is, graph, capacity, s); GraphWriter(os, graph). writeEdgeMap("capacity", capacity). @@ -145,7 +146,7 @@ run(); } else if (capacitated) { Graph graph; - DoubleMap capacity(graph); + DoubleEdgeMap capacity(graph); readDimacs(is, graph, capacity); GraphWriter(os, graph). writeEdgeMap("capacity", capacity).