lemon/dimacs.h
author ladanyi
Sat, 01 Mar 2008 20:09:40 +0000
changeset 2591 3b4d5bc3b4fb
parent 2455 dc3f7991ad58
permissions -rw-r--r--
In C++98 array size shall be an integral constant expression. Fixes
ticket 12.
alpar@906
     1
/* -*- C++ -*-
alpar@906
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@2553
     5
 * Copyright (C) 2003-2008
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@906
     8
 *
alpar@906
     9
 * Permission to use, modify and distribute this software is granted
alpar@906
    10
 * provided that this copyright notice appears in all copies. For
alpar@906
    11
 * precise terms see the accompanying LICENSE file.
alpar@906
    12
 *
alpar@906
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    14
 * express or implied, and with no claim as to its suitability for any
alpar@906
    15
 * purpose.
alpar@906
    16
 *
alpar@906
    17
 */
alpar@906
    18
alpar@921
    19
#ifndef LEMON_DIMACS_H
alpar@921
    20
#define LEMON_DIMACS_H
marci@423
    21
marci@423
    22
#include <iostream>
marci@423
    23
#include <string>
marci@423
    24
#include <vector>
alpar@921
    25
#include <lemon/maps.h>
deba@1993
    26
#include <lemon/bits/invalid.h>
marci@423
    27
alpar@1287
    28
/// \ingroup dimacs_group
klao@442
    29
/// \file
deba@2413
    30
/// \brief DIMACS file format reader.
klao@427
    31
alpar@921
    32
namespace lemon {
marci@423
    33
alpar@1287
    34
  ///@defgroup dimacs_group DIMACS format
alpar@1287
    35
  ///\brief Read and write files in DIMACS format
alpar@1287
    36
  ///
alpar@1287
    37
  ///Tools to read a graph from or write it to a file in DIMACS format
alpar@1287
    38
  ///data
alpar@1287
    39
  ///\ingroup io_group
marci@423
    40
alpar@1287
    41
  /// \addtogroup dimacs_group
jacint@575
    42
  /// @{
deba@2413
    43
  
deba@2413
    44
  /// DIMACS min cost flow reader function.
deba@2413
    45
  ///
deba@2413
    46
  /// This function reads a min cost flow instance from DIMACS format,
deba@2413
    47
  /// i.e. from DIMACS files having a line starting with
deba@2413
    48
  /// \code
deba@2413
    49
  ///   p min
deba@2413
    50
  /// \endcode
deba@2413
    51
  /// At the beginning \c g is cleared by \c g.clear(). The supply 
deba@2413
    52
  /// amount of the nodes are written to \c supply (signed). The 
deba@2413
    53
  /// lower bounds, capacities and costs of the edges are written to 
deba@2413
    54
  /// \c lower, \c capacity and \c cost.
deba@2413
    55
  ///
deba@2413
    56
  /// \author Marton Makai and Peter Kovacs
deba@2417
    57
  template <typename Graph, typename LowerMap, 
deba@2417
    58
    typename CapacityMap, typename CostMap, 
deba@2417
    59
    typename SupplyMap>
deba@2413
    60
  void readDimacs( std::istream& is,
deba@2413
    61
		   Graph &g,
deba@2417
    62
		   LowerMap& lower, 
deba@2413
    63
		   CapacityMap& capacity, 
deba@2417
    64
		   CostMap& cost,
deba@2417
    65
		   SupplyMap& supply )
deba@2413
    66
  {
deba@2413
    67
    g.clear();
deba@2413
    68
    std::vector<typename Graph::Node> nodes;
deba@2413
    69
    typename Graph::Edge e;
deba@2413
    70
    std::string problem, str;
deba@2413
    71
    char c;
deba@2413
    72
    int n, m; 
deba@2413
    73
    int i, j;
deba@2413
    74
    typename SupplyMap::Value sup;
deba@2413
    75
    typename CapacityMap::Value low;
deba@2413
    76
    typename CapacityMap::Value cap;
deba@2413
    77
    typename CostMap::Value co;
deba@2413
    78
    while (is >> c) {
deba@2413
    79
      switch (c) {
deba@2413
    80
      case 'c': // comment line
deba@2413
    81
	getline(is, str);
deba@2413
    82
	break;
deba@2413
    83
      case 'p': // problem definition line
deba@2413
    84
	is >> problem >> n >> m;
deba@2413
    85
	getline(is, str);
deba@2413
    86
	if (problem != "min") return;
deba@2413
    87
	nodes.resize(n + 1);
deba@2413
    88
	for (int k = 1; k <= n; ++k) {
deba@2413
    89
	  nodes[k] = g.addNode();
deba@2455
    90
	  supply.set(nodes[k], 0);
deba@2413
    91
	}
deba@2413
    92
	break;
deba@2413
    93
      case 'n': // node definition line
deba@2413
    94
	is >> i >> sup;
deba@2413
    95
	getline(is, str);
deba@2413
    96
	supply.set(nodes[i], sup);
deba@2413
    97
	break;
deba@2413
    98
      case 'a': // edge (arc) definition line
deba@2413
    99
	is >> i >> j >> low >> cap >> co;
deba@2413
   100
	getline(is, str);
deba@2413
   101
	e = g.addEdge(nodes[i], nodes[j]);
deba@2413
   102
	lower.set(e, low);
deba@2413
   103
	if (cap >= 0)
deba@2413
   104
	  capacity.set(e, cap);
deba@2413
   105
	else
deba@2413
   106
	  capacity.set(e, -1);
deba@2413
   107
	cost.set(e, co);
deba@2413
   108
	break;
deba@2413
   109
      }
deba@2413
   110
    }
deba@2413
   111
  }
jacint@575
   112
deba@2413
   113
  /// DIMACS max flow reader function.
deba@2413
   114
  ///
deba@2413
   115
  /// This function reads a max flow instance from DIMACS format,
deba@2413
   116
  /// i.e. from DIMACS files having a line starting with
deba@2413
   117
  /// \code
deba@2413
   118
  ///   p max
deba@2413
   119
  /// \endcode
deba@2413
   120
  /// At the beginning \c g is cleared by \c g.clear(). The edge 
deba@2413
   121
  /// capacities are written to \c capacity and \c s and \c t are
deba@2413
   122
  /// set to the source and the target nodes.
marci@465
   123
  ///
jacint@575
   124
  /// \author Marton Makai
deba@2413
   125
  template<typename Graph, typename CapacityMap>
jacint@528
   126
  void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity, 
deba@2413
   127
		  typename Graph::Node &s, typename Graph::Node &t) {
jacint@528
   128
    g.clear();
deba@2413
   129
    std::vector<typename Graph::Node> nodes;
deba@2413
   130
    typename Graph::Edge e;
deba@2413
   131
    std::string problem;
deba@2413
   132
    char c, d;
deba@2413
   133
    int n, m; 
deba@2413
   134
    int i, j;
alpar@987
   135
    typename CapacityMap::Value _cap;
jacint@528
   136
    std::string str;
deba@2413
   137
    while (is >> c) {
jacint@528
   138
      switch (c) {
deba@2413
   139
      case 'c': // comment line
jacint@528
   140
	getline(is, str);
jacint@528
   141
	break;
deba@2413
   142
      case 'p': // problem definition line
jacint@528
   143
	is >> problem >> n >> m;
jacint@528
   144
	getline(is, str);
deba@2413
   145
	nodes.resize(n + 1);
deba@2413
   146
	for (int k = 1; k <= n; ++k)
deba@2413
   147
	  nodes[k] = g.addNode();
jacint@528
   148
	break;
deba@2413
   149
      case 'n': // node definition line
deba@2413
   150
	if (problem == "sp") { // shortest path problem
jacint@528
   151
	  is >> i;
jacint@528
   152
	  getline(is, str);
deba@2413
   153
	  s = nodes[i];
jacint@528
   154
	}
deba@2413
   155
	if (problem == "max") { // max flow problem
jacint@528
   156
	  is >> i >> d;
jacint@528
   157
	  getline(is, str);
deba@2413
   158
	  if (d == 's') s = nodes[i];
deba@2413
   159
	  if (d == 't') t = nodes[i];
jacint@528
   160
	}
jacint@528
   161
	break;
deba@2413
   162
      case 'a': // edge (arc) definition line
deba@2413
   163
	if (problem == "max" || problem == "sp") {
jacint@528
   164
	  is >> i >> j >> _cap;
jacint@528
   165
	  getline(is, str);
deba@2413
   166
	  e = g.addEdge(nodes[i], nodes[j]);
jacint@528
   167
	  capacity.set(e, _cap);
jacint@575
   168
	} else {
deba@2413
   169
	  is >> i >> j;
deba@2413
   170
	  getline(is, str);
deba@2413
   171
	  g.addEdge(nodes[i], nodes[j]);
jacint@528
   172
	}
jacint@528
   173
	break;
jacint@528
   174
      }
jacint@528
   175
    }
jacint@528
   176
  }
jacint@528
   177
deba@2413
   178
  /// DIMACS shortest path reader function.
jacint@575
   179
  ///
deba@2413
   180
  /// This function reads a shortest path instance from DIMACS format,
deba@2413
   181
  /// i.e. from DIMACS files having a line starting with
deba@2413
   182
  /// \code
deba@2413
   183
  ///   p sp
deba@2413
   184
  /// \endcode
jacint@575
   185
  /// At the beginning \c g is cleared by \c g.clear(). The edge
jacint@575
   186
  /// capacities are written to \c capacity and \c s is set to the
jacint@575
   187
  /// source node.
jacint@575
   188
  ///
jacint@575
   189
  /// \author Marton Makai
jacint@575
   190
  template<typename Graph, typename CapacityMap>
jacint@575
   191
  void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity, 
jacint@575
   192
		  typename Graph::Node &s) {
deba@2413
   193
    readDimacs(is, g, capacity, s, s);
jacint@575
   194
  }
jacint@575
   195
deba@2413
   196
  /// DIMACS capacitated graph reader function.
deba@2413
   197
  ///
jacint@575
   198
  /// This function reads an edge capacitated graph instance from
deba@2413
   199
  /// DIMACS format. At the beginning \c g is cleared by \c g.clear()
jacint@575
   200
  /// and the edge capacities are written to \c capacity.
jacint@575
   201
  ///
jacint@575
   202
  /// \author Marton Makai
jacint@575
   203
  template<typename Graph, typename CapacityMap>
jacint@575
   204
  void readDimacs(std::istream& is, Graph &g, CapacityMap& capacity) {
jacint@575
   205
    typename Graph::Node u;
deba@2413
   206
    readDimacs(is, g, capacity, u, u);
jacint@575
   207
  }
jacint@575
   208
deba@2413
   209
  /// DIMACS plain graph reader function.
deba@2413
   210
  ///
jacint@575
   211
  /// This function reads a graph without any designated nodes and
deba@2413
   212
  /// maps from DIMACS format, i.e. from DIMACS files having a line
alpar@964
   213
  /// starting with
deba@2413
   214
  /// \code
deba@2413
   215
  ///   p mat
deba@2413
   216
  /// \endcode
deba@2413
   217
  /// At the beginning \c g is cleared by \c g.clear().
jacint@575
   218
  ///
jacint@575
   219
  /// \author Marton Makai
jacint@575
   220
  template<typename Graph>
jacint@575
   221
  void readDimacs(std::istream& is, Graph &g) {
jacint@575
   222
    typename Graph::Node u;
jacint@575
   223
    NullMap<typename Graph::Edge, int> n;
deba@2413
   224
    readDimacs(is, g, n, u, u);
jacint@575
   225
  }
jacint@575
   226
  
deba@2413
   227
  /// DIMACS plain graph writer function.
deba@2413
   228
  ///
deba@2413
   229
  /// This function writes a graph without any designated nodes and
deba@2413
   230
  /// maps into DIMACS format, i.e. into DIMACS file having a line 
deba@2413
   231
  /// starting with
deba@2413
   232
  /// \code
deba@2413
   233
  ///   p mat
deba@2413
   234
  /// \endcode
deba@2413
   235
  ///
deba@2413
   236
  /// \author Marton Makai
jacint@528
   237
  template<typename Graph>
jacint@528
   238
  void writeDimacs(std::ostream& os, const Graph &g) {
jacint@528
   239
    typedef typename Graph::NodeIt NodeIt;
jacint@528
   240
    typedef typename Graph::EdgeIt EdgeIt;  
jacint@528
   241
    
deba@2413
   242
    os << "c matching problem" << std::endl;
deba@2413
   243
    os << "p mat " << g.nodeNum() << " " << g.edgeNum() << std::endl;
deba@2413
   244
jacint@528
   245
    typename Graph::template NodeMap<int> nodes(g);
deba@2413
   246
    int i = 1;
deba@2413
   247
    for(NodeIt v(g); v != INVALID; ++v) {
jacint@528
   248
      nodes.set(v, i);
jacint@528
   249
      ++i;
jacint@528
   250
    }    
deba@2413
   251
    for(EdgeIt e(g); e != INVALID; ++e) {
alpar@986
   252
      os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)] << std::endl; 
jacint@528
   253
    }
jacint@528
   254
  }
jacint@528
   255
jacint@575
   256
  /// @}
jacint@528
   257
alpar@921
   258
} //namespace lemon
marci@423
   259
alpar@921
   260
#endif //LEMON_DIMACS_H