1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
 
     3  * This file is a part of LEMON, a generic C++ optimization library.
 
     5  * Copyright (C) 2003-2013
 
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
 
     9  * Permission to use, modify and distribute this software is granted
 
    10  * provided that this copyright notice appears in all copies. For
 
    11  * precise terms see the accompanying LICENSE file.
 
    13  * This software is provided "AS IS" with no warranty of any kind,
 
    14  * express or implied, and with no claim as to its suitability for any
 
    19 #ifndef LEMON_DIMACS_H
 
    20 #define LEMON_DIMACS_H
 
    26 #include <lemon/maps.h>
 
    27 #include <lemon/error.h>
 
    28 /// \ingroup dimacs_group
 
    30 /// \brief DIMACS file format reader.
 
    34   /// \addtogroup dimacs_group
 
    37   /// DIMACS file type descriptor.
 
    38   struct DimacsDescriptor
 
    40     ///\brief DIMACS file type enum
 
    42     ///DIMACS file type enum.
 
    44       NONE,  ///< Undefined type.
 
    45       MIN,   ///< DIMACS file type for minimum cost flow problems.
 
    46       MAX,   ///< DIMACS file type for maximum flow problems.
 
    47       SP,    ///< DIMACS file type for shostest path problems.
 
    48       MAT    ///< DIMACS file type for plain graphs and matching problems.
 
    52     ///The number of nodes in the graph
 
    54     ///The number of edges in the graph
 
    57     ///Constructor. It sets the type to \c NONE.
 
    58     DimacsDescriptor() : type(NONE) {}
 
    61   ///Discover the type of a DIMACS file
 
    63   ///This function starts seeking the beginning of the given file for the
 
    64   ///problem type and size info.
 
    65   ///The found data is returned in a special struct that can be evaluated
 
    66   ///and passed to the appropriate reader function.
 
    67   DimacsDescriptor dimacsType(std::istream& is)
 
    70     std::string problem,str;
 
    77           if(is >> problem >> r.nodeNum >> r.edgeNum)
 
    81               if(problem=="min") r.type=DimacsDescriptor::MIN;
 
    82               else if(problem=="max") r.type=DimacsDescriptor::MAX;
 
    83               else if(problem=="sp") r.type=DimacsDescriptor::SP;
 
    84               else if(problem=="mat") r.type=DimacsDescriptor::MAT;
 
    85               else throw FormatError("Unknown problem type");
 
    90               throw FormatError("Missing or wrong problem type declaration.");
 
    98           throw FormatError("Unknown DIMACS declaration.");
 
   100     throw FormatError("Missing problem type declaration.");
 
   104   /// \brief DIMACS minimum cost flow reader function.
 
   106   /// This function reads a minimum cost flow instance from DIMACS format,
 
   107   /// i.e. from a DIMACS file having a line starting with
 
   111   /// At the beginning, \c g is cleared by \c g.clear(). The supply
 
   112   /// amount of the nodes are written to the \c supply node map
 
   113   /// (they are signed values). The lower bounds, capacities and costs
 
   114   /// of the arcs are written to the \c lower, \c capacity and \c cost
 
   117   /// If the capacity of an arc is less than the lower bound, it will
 
   118   /// be set to "infinite" instead. The actual value of "infinite" is
 
   119   /// contolled by the \c infty parameter. If it is 0 (the default value),
 
   120   /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
 
   121   /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
 
   122   /// a non-zero value, that value will be used as "infinite".
 
   124   /// If the file type was previously evaluated by dimacsType(), then
 
   125   /// the descriptor struct should be given by the \c dest parameter.
 
   126   template <typename Digraph, typename LowerMap,
 
   127             typename CapacityMap, typename CostMap,
 
   129   void readDimacsMin(std::istream& is,
 
   132                      CapacityMap& capacity,
 
   135                      typename CapacityMap::Value infty = 0,
 
   136                      DimacsDescriptor desc=DimacsDescriptor())
 
   139     std::vector<typename Digraph::Node> nodes;
 
   140     typename Digraph::Arc e;
 
   141     std::string problem, str;
 
   144     if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
 
   145     if(desc.type!=DimacsDescriptor::MIN)
 
   146       throw FormatError("Problem type mismatch");
 
   148     nodes.resize(desc.nodeNum + 1);
 
   149     for (int k = 1; k <= desc.nodeNum; ++k) {
 
   150       nodes[k] = g.addNode();
 
   151       supply.set(nodes[k], 0);
 
   154     typename SupplyMap::Value sup;
 
   155     typename CapacityMap::Value low;
 
   156     typename CapacityMap::Value cap;
 
   157     typename CostMap::Value co;
 
   158     typedef typename CapacityMap::Value Capacity;
 
   160       infty = std::numeric_limits<Capacity>::has_infinity ?
 
   161         std::numeric_limits<Capacity>::infinity() :
 
   162         std::numeric_limits<Capacity>::max();
 
   166       case 'c': // comment line
 
   169       case 'n': // node definition line
 
   172         supply.set(nodes[i], sup);
 
   174       case 'a': // arc definition line
 
   175         is >> i >> j >> low >> cap >> co;
 
   177         e = g.addArc(nodes[i], nodes[j]);
 
   180           capacity.set(e, cap);
 
   182           capacity.set(e, infty);
 
   189   template<typename Digraph, typename CapacityMap>
 
   190   void _readDimacs(std::istream& is,
 
   192                    CapacityMap& capacity,
 
   193                    typename Digraph::Node &s,
 
   194                    typename Digraph::Node &t,
 
   195                    typename CapacityMap::Value infty = 0,
 
   196                    DimacsDescriptor desc=DimacsDescriptor()) {
 
   199     std::vector<typename Digraph::Node> nodes;
 
   200     typename Digraph::Arc e;
 
   203     typename CapacityMap::Value _cap;
 
   205     nodes.resize(desc.nodeNum + 1);
 
   206     for (int k = 1; k <= desc.nodeNum; ++k) {
 
   207       nodes[k] = g.addNode();
 
   209     typedef typename CapacityMap::Value Capacity;
 
   212       infty = std::numeric_limits<Capacity>::has_infinity ?
 
   213         std::numeric_limits<Capacity>::infinity() :
 
   214         std::numeric_limits<Capacity>::max();
 
   218       case 'c': // comment line
 
   221       case 'n': // node definition line
 
   222         if (desc.type==DimacsDescriptor::SP) { // shortest path problem
 
   227         if (desc.type==DimacsDescriptor::MAX) { // max flow problem
 
   230           if (d == 's') s = nodes[i];
 
   231           if (d == 't') t = nodes[i];
 
   234       case 'a': // arc definition line
 
   235         if (desc.type==DimacsDescriptor::SP) {
 
   236           is >> i >> j >> _cap;
 
   238           e = g.addArc(nodes[i], nodes[j]);
 
   239           capacity.set(e, _cap);
 
   241         else if (desc.type==DimacsDescriptor::MAX) {
 
   242           is >> i >> j >> _cap;
 
   244           e = g.addArc(nodes[i], nodes[j]);
 
   246             capacity.set(e, _cap);
 
   248             capacity.set(e, infty);
 
   253           g.addArc(nodes[i], nodes[j]);
 
   260   /// \brief DIMACS maximum flow reader function.
 
   262   /// This function reads a maximum flow instance from DIMACS format,
 
   263   /// i.e. from a DIMACS file having a line starting with
 
   267   /// At the beginning, \c g is cleared by \c g.clear(). The arc
 
   268   /// capacities are written to the \c capacity arc map and \c s and
 
   269   /// \c t are set to the source and the target nodes.
 
   271   /// If the capacity of an arc is negative, it will
 
   272   /// be set to "infinite" instead. The actual value of "infinite" is
 
   273   /// contolled by the \c infty parameter. If it is 0 (the default value),
 
   274   /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
 
   275   /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
 
   276   /// a non-zero value, that value will be used as "infinite".
 
   278   /// If the file type was previously evaluated by dimacsType(), then
 
   279   /// the descriptor struct should be given by the \c dest parameter.
 
   280   template<typename Digraph, typename CapacityMap>
 
   281   void readDimacsMax(std::istream& is,
 
   283                      CapacityMap& capacity,
 
   284                      typename Digraph::Node &s,
 
   285                      typename Digraph::Node &t,
 
   286                      typename CapacityMap::Value infty = 0,
 
   287                      DimacsDescriptor desc=DimacsDescriptor()) {
 
   288     if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
 
   289     if(desc.type!=DimacsDescriptor::MAX)
 
   290       throw FormatError("Problem type mismatch");
 
   291     _readDimacs(is,g,capacity,s,t,infty,desc);
 
   294   /// \brief DIMACS shortest path reader function.
 
   296   /// This function reads a shortest path instance from DIMACS format,
 
   297   /// i.e. from a DIMACS file having a line starting with
 
   301   /// At the beginning, \c g is cleared by \c g.clear(). The arc
 
   302   /// lengths are written to the \c length arc map and \c s is set to the
 
   305   /// If the file type was previously evaluated by dimacsType(), then
 
   306   /// the descriptor struct should be given by the \c dest parameter.
 
   307   template<typename Digraph, typename LengthMap>
 
   308   void readDimacsSp(std::istream& is,
 
   311                     typename Digraph::Node &s,
 
   312                     DimacsDescriptor desc=DimacsDescriptor()) {
 
   313     typename Digraph::Node t;
 
   314     if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
 
   315     if(desc.type!=DimacsDescriptor::SP)
 
   316       throw FormatError("Problem type mismatch");
 
   317     _readDimacs(is, g, length, s, t, 0, desc);
 
   320   /// \brief DIMACS capacitated digraph reader function.
 
   322   /// This function reads an arc capacitated digraph instance from
 
   323   /// DIMACS 'max' or 'sp' format.
 
   324   /// At the beginning, \c g is cleared by \c g.clear()
 
   325   /// and the arc capacities/lengths are written to the \c capacity
 
   328   /// In case of the 'max' format, if the capacity of an arc is negative,
 
   330   /// be set to "infinite" instead. The actual value of "infinite" is
 
   331   /// contolled by the \c infty parameter. If it is 0 (the default value),
 
   332   /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
 
   333   /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
 
   334   /// a non-zero value, that value will be used as "infinite".
 
   336   /// If the file type was previously evaluated by dimacsType(), then
 
   337   /// the descriptor struct should be given by the \c dest parameter.
 
   338   template<typename Digraph, typename CapacityMap>
 
   339   void readDimacsCap(std::istream& is,
 
   341                      CapacityMap& capacity,
 
   342                      typename CapacityMap::Value infty = 0,
 
   343                      DimacsDescriptor desc=DimacsDescriptor()) {
 
   344     typename Digraph::Node u,v;
 
   345     if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
 
   346     if(desc.type!=DimacsDescriptor::MAX || desc.type!=DimacsDescriptor::SP)
 
   347       throw FormatError("Problem type mismatch");
 
   348     _readDimacs(is, g, capacity, u, v, infty, desc);
 
   351   template<typename Graph>
 
   352   typename enable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
 
   353   _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
 
   358   template<typename Graph>
 
   359   typename disable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
 
   360   _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
 
   366   /// \brief DIMACS plain (di)graph reader function.
 
   368   /// This function reads a plain (di)graph without any designated nodes
 
   369   /// and maps (e.g. a matching instance) from DIMACS format, i.e. from
 
   370   /// DIMACS files having a line starting with
 
   374   /// At the beginning, \c g is cleared by \c g.clear().
 
   376   /// If the file type was previously evaluated by dimacsType(), then
 
   377   /// the descriptor struct should be given by the \c dest parameter.
 
   378   template<typename Graph>
 
   379   void readDimacsMat(std::istream& is, Graph &g,
 
   380                      DimacsDescriptor desc=DimacsDescriptor())
 
   382     if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
 
   383     if(desc.type!=DimacsDescriptor::MAT)
 
   384       throw FormatError("Problem type mismatch");
 
   387     std::vector<typename Graph::Node> nodes;
 
   391     nodes.resize(desc.nodeNum + 1);
 
   392     for (int k = 1; k <= desc.nodeNum; ++k) {
 
   393       nodes[k] = g.addNode();
 
   398       case 'c': // comment line
 
   401       case 'n': // node definition line
 
   403       case 'a': // arc definition line
 
   406         _addArcEdge(g,nodes[i], nodes[j]);
 
   412   /// DIMACS plain digraph writer function.
 
   414   /// This function writes a digraph without any designated nodes and
 
   415   /// maps into DIMACS format, i.e. into DIMACS file having a line
 
   420   /// If \c comment is not empty, then it will be printed in the first line
 
   422   template<typename Digraph>
 
   423   void writeDimacsMat(std::ostream& os, const Digraph &g,
 
   424                       std::string comment="") {
 
   425     typedef typename Digraph::NodeIt NodeIt;
 
   426     typedef typename Digraph::ArcIt ArcIt;
 
   429       os << "c " << comment << std::endl;
 
   430     os << "p mat " << g.nodeNum() << " " << g.arcNum() << std::endl;
 
   432     typename Digraph::template NodeMap<int> nodes(g);
 
   434     for(NodeIt v(g); v != INVALID; ++v) {
 
   438     for(ArcIt e(g); e != INVALID; ++e) {
 
   439       os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)]
 
   448 #endif //LEMON_DIMACS_H