[Lemon-commits] Alpar Juttner: Refactoring of DIMACS tools

Lemon HG hg at lemon.cs.elte.hu
Sun Nov 30 10:51:20 CET 2008


details:   http://lemon.cs.elte.hu/hg/lemon/rev/24a2c6ee6cb0
changeset: 402:24a2c6ee6cb0
user:      Alpar Juttner <alpar [at] cs.elte.hu>
date:      Fri Nov 28 06:38:20 2008 +0000
description:
	Refactoring of DIMACS tools

diffstat:

2 files changed, 258 insertions(+), 161 deletions(-)
lemon/dimacs.h         |  234 +++++++++++++++++++++++++++++++++++-------------
tools/dimacs-to-lgf.cc |  185 +++++++++++++++++--------------------

diffs (truncated from 559 to 300 lines):

diff -r 9d1faab5e0f1 -r 24a2c6ee6cb0 lemon/dimacs.h
--- a/lemon/dimacs.h	Thu Nov 27 22:05:35 2008 +0000
+++ b/lemon/dimacs.h	Fri Nov 28 06:38:20 2008 +0000
@@ -23,6 +23,7 @@
 #include <string>
 #include <vector>
 #include <lemon/maps.h>
+#include <lemon/error.h>
 
 /// \ingroup dimacs_group
 /// \file
@@ -40,6 +41,70 @@
   /// \addtogroup dimacs_group
   /// @{
 
+
+  /// DIMACS file type descriptor.
+  struct DimacsDescriptor
+  {
+    ///File type enum
+    enum Type
+      {
+        NONE, MIN, MAX, SP, MAT
+      };
+    ///The file type
+    Type type;
+    ///The number of nodes on the graph
+    int nodeNum;
+    ///The number of edges on the graph
+    int edgeNum;
+    int lineShift;
+    /// Constructor. Sets the type to NONE.
+    DimacsDescriptor() : type(NONE) {}
+  };
+
+  ///Discover the type of a DIMACS file
+
+  ///It starts seeking the begining of the file for the problem type
+  ///and size info. The found date is returned in a special struct
+  ///that can be evaluated and passed to the appropriate reader
+  ///function.
+  DimacsDescriptor dimacsType(std::istream& is)
+  {
+    DimacsDescriptor r;
+    std::string problem,str;
+    char c;
+    r.lineShift=0;
+    while (is >> c)
+      switch(c)
+        {
+        case 'p':
+          if(is >> problem >> r.nodeNum >> r.edgeNum)
+            {
+              getline(is, str);
+              r.lineShift++;
+              if(problem=="min") r.type=DimacsDescriptor::MIN;
+              else if(problem=="max") r.type=DimacsDescriptor::MAX;
+              else if(problem=="sp") r.type=DimacsDescriptor::SP;
+              else if(problem=="mat") r.type=DimacsDescriptor::MAT;
+              else throw FormatError("Unknown problem type");
+              return r;
+            }
+          else
+            {
+              throw FormatError("Missing or wrong problem type declaration.");
+            }
+          break;
+        case 'c':
+          getline(is, str);
+          r.lineShift++;
+          break;
+        default:
+          throw FormatError("Unknown DIMACS declaration.");
+        }
+    throw FormatError("Missing problem type declaration.");
+  }
+
+
+
   /// DIMACS min cost flow reader function.
   ///
   /// This function reads a min cost flow instance from DIMACS format,
@@ -47,27 +112,40 @@
   /// \code
   ///   p min
   /// \endcode
-  /// At the beginning \c g is cleared by \c g.clear(). The supply
+  /// 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 arcs are written to
   /// \c lower, \c capacity and \c cost.
+  ///
+  /// If the file type was previously evaluated by dimacsType(), then
+  /// the descriptor struct should be given by the \c dest parameter.
   template <typename Digraph, typename LowerMap,
-    typename CapacityMap, typename CostMap,
-    typename SupplyMap>
-  void readDimacsMin( std::istream& is,
-                   Digraph &g,
-                   LowerMap& lower,
-                   CapacityMap& capacity,
-                   CostMap& cost,
-                   SupplyMap& supply )
+            typename CapacityMap, typename CostMap,
+            typename SupplyMap>
+  void readDimacsMin(std::istream& is,
+                     Digraph &g,
+                     LowerMap& lower,
+                     CapacityMap& capacity,
+                     CostMap& cost,
+                     SupplyMap& supply,
+                     DimacsDescriptor desc=DimacsDescriptor())
   {
     g.clear();
     std::vector<typename Digraph::Node> nodes;
     typename Digraph::Arc e;
     std::string problem, str;
     char c;
-    int n, m;
     int i, j;
+    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
+    if(desc.type!=DimacsDescriptor::MIN)
+      throw FormatError("Problem type mismatch");
+
+    nodes.resize(desc.nodeNum + 1);
+    for (int k = 1; k <= desc.nodeNum; ++k) {
+      nodes[k] = g.addNode();
+      supply.set(nodes[k], 0);
+    }
+
     typename SupplyMap::Value sup;
     typename CapacityMap::Value low;
     typename CapacityMap::Value cap;
@@ -76,16 +154,6 @@
       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.set(nodes[k], 0);
-        }
         break;
       case 'n': // node definition line
         is >> i >> sup;
@@ -107,47 +175,38 @@
     }
   }
 
-  /// 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 arc
-  /// capacities are written to \c capacity and \c s and \c t are
-  /// set to the source and the target nodes.
   template<typename Digraph, typename CapacityMap>
-  void readDimacsMax(std::istream& is, Digraph &g, CapacityMap& capacity,
-                  typename Digraph::Node &s, typename Digraph::Node &t) {
+  void _readDimacs(std::istream& is,
+                   Digraph &g,
+                   CapacityMap& capacity,
+                   typename Digraph::Node &s,
+                   typename Digraph::Node &t,
+                   DimacsDescriptor desc=DimacsDescriptor()) {
     g.clear();
+    s=t=INVALID;
     std::vector<typename Digraph::Node> nodes;
     typename Digraph::Arc e;
-    std::string problem;
     char c, d;
-    int n, m;
     int i, j;
     typename CapacityMap::Value _cap;
     std::string str;
+    nodes.resize(desc.nodeNum + 1);
+    for (int k = 1; k <= desc.nodeNum; ++k) {
+      nodes[k] = g.addNode();
+    }
+
     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);
-        nodes.resize(n + 1);
-        for (int k = 1; k <= n; ++k)
-          nodes[k] = g.addNode();
-        break;
       case 'n': // node definition line
-        if (problem == "sp") { // shortest path problem
+        if (desc.type==DimacsDescriptor::SP) { // shortest path problem
           is >> i;
           getline(is, str);
           s = nodes[i];
         }
-        if (problem == "max") { // max flow problem
+        if (desc.type==DimacsDescriptor::MAX) { // max flow problem
           is >> i >> d;
           getline(is, str);
           if (d == 's') s = nodes[i];
@@ -155,7 +214,8 @@
         }
         break;
       case 'a': // arc (arc) definition line
-        if (problem == "max" || problem == "sp") {
+        if (desc.type==DimacsDescriptor::SP ||
+            desc.type==DimacsDescriptor::MAX) {
           is >> i >> j >> _cap;
           getline(is, str);
           e = g.addArc(nodes[i], nodes[j]);
@@ -170,6 +230,32 @@
     }
   }
 
+  /// 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 arc
+  /// capacities are written to \c capacity and \c s and \c t are
+  /// set to the source and the target nodes.
+  ///
+  /// If the file type was previously evaluated by dimacsType(), then
+  /// the descriptor struct should be given by the \c dest parameter.
+  template<typename Digraph, typename CapacityMap>
+  void readDimacsMax(std::istream& is,
+                     Digraph &g,
+                     CapacityMap& capacity,
+                     typename Digraph::Node &s,
+                     typename Digraph::Node &t,
+                     DimacsDescriptor desc=DimacsDescriptor()) {
+    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
+    if(desc.type!=DimacsDescriptor::MAX)
+      throw FormatError("Problem type mismatch");
+    _readDimacs(is,g,capacity,s,t,desc);
+  }
+
   /// DIMACS shortest path reader function.
   ///
   /// This function reads a shortest path instance from DIMACS format,
@@ -177,25 +263,44 @@
   /// \code
   ///   p sp
   /// \endcode
-  /// At the beginning \c g is cleared by \c g.clear(). The arc
-  /// capacities are written to \c capacity and \c s is set to the
+  /// At the beginning, \c g is cleared by \c g.clear(). The arc
+  /// lengths are written to \c lenght and \c s is set to the
   /// source node.
-  template<typename Digraph, typename CapacityMap>
-  void readDimacsSp(std::istream& is, Digraph &g, CapacityMap& capacity,
-                  typename Digraph::Node &s) {
+  ///
+  /// If the file type was previously evaluated by dimacsType(), then
+  /// the descriptor struct should be given by the \c dest parameter.
+  template<typename Digraph, typename LengthMap>
+  void readDimacsSp(std::istream& is,
+                    Digraph &g,
+                    LengthMap& length,
+                    typename Digraph::Node &s,
+                    DimacsDescriptor desc=DimacsDescriptor()) {
     typename Digraph::Node t;
-    readDimacsMax(is, g, capacity, s, t);
+    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
+    if(desc.type!=DimacsDescriptor::SP)
+      throw FormatError("Problem type mismatch");
+    _readDimacs(is, g, length, s, t,desc);
   }
 
   /// DIMACS capacitated digraph reader function.
   ///
   /// This function reads an arc capacitated digraph instance from
-  /// DIMACS format. At the beginning \c g is cleared by \c g.clear()
-  /// and the arc capacities are written to \c capacity.
+  /// DIMACS 'mat' or 'sp' format.
+  /// At the beginning, \c g is cleared by \c g.clear()
+  /// and the arc capacities/lengths are written to \c capacity.
+  ///
+  /// If the file type was previously evaluated by dimacsType(), then
+  /// the descriptor struct should be given by the \c dest parameter.
   template<typename Digraph, typename CapacityMap>
-  void readDimacsMax(std::istream& is, Digraph &g, CapacityMap& capacity) {
+  void readDimacsCap(std::istream& is,
+                     Digraph &g,
+                     CapacityMap& capacity,



More information about the Lemon-commits mailing list