lemon/dimacs.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 584 33c6b6e755cd
child 1092 dceba191c00d
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
alpar@385
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@385
     2
 *
alpar@385
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@385
     4
 *
alpar@877
     5
 * Copyright (C) 2003-2010
alpar@385
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@385
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@385
     8
 *
alpar@385
     9
 * Permission to use, modify and distribute this software is granted
alpar@385
    10
 * provided that this copyright notice appears in all copies. For
alpar@385
    11
 * precise terms see the accompanying LICENSE file.
alpar@385
    12
 *
alpar@385
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@385
    14
 * express or implied, and with no claim as to its suitability for any
alpar@385
    15
 * purpose.
alpar@385
    16
 *
alpar@385
    17
 */
alpar@385
    18
alpar@385
    19
#ifndef LEMON_DIMACS_H
alpar@385
    20
#define LEMON_DIMACS_H
alpar@385
    21
alpar@385
    22
#include <iostream>
alpar@385
    23
#include <string>
alpar@385
    24
#include <vector>
alpar@561
    25
#include <limits>
alpar@385
    26
#include <lemon/maps.h>
alpar@387
    27
#include <lemon/error.h>
alpar@385
    28
/// \ingroup dimacs_group
alpar@385
    29
/// \file
alpar@385
    30
/// \brief DIMACS file format reader.
alpar@385
    31
alpar@385
    32
namespace lemon {
alpar@385
    33
alpar@385
    34
  /// \addtogroup dimacs_group
alpar@385
    35
  /// @{
alpar@385
    36
alpar@387
    37
  /// DIMACS file type descriptor.
alpar@387
    38
  struct DimacsDescriptor
alpar@387
    39
  {
kpeter@584
    40
    ///\brief DIMACS file type enum
kpeter@584
    41
    ///
kpeter@584
    42
    ///DIMACS file type enum.
kpeter@584
    43
    enum Type {
kpeter@584
    44
      NONE,  ///< Undefined type.
kpeter@584
    45
      MIN,   ///< DIMACS file type for minimum cost flow problems.
kpeter@584
    46
      MAX,   ///< DIMACS file type for maximum flow problems.
kpeter@584
    47
      SP,    ///< DIMACS file type for shostest path problems.
kpeter@584
    48
      MAT    ///< DIMACS file type for plain graphs and matching problems.
kpeter@584
    49
    };
alpar@387
    50
    ///The file type
alpar@387
    51
    Type type;
kpeter@388
    52
    ///The number of nodes in the graph
alpar@387
    53
    int nodeNum;
kpeter@388
    54
    ///The number of edges in the graph
alpar@387
    55
    int edgeNum;
alpar@387
    56
    int lineShift;
kpeter@584
    57
    ///Constructor. It sets the type to \c NONE.
alpar@387
    58
    DimacsDescriptor() : type(NONE) {}
alpar@387
    59
  };
alpar@387
    60
alpar@387
    61
  ///Discover the type of a DIMACS file
alpar@387
    62
kpeter@584
    63
  ///This function starts seeking the beginning of the given file for the
alpar@877
    64
  ///problem type and size info.
kpeter@584
    65
  ///The found data is returned in a special struct that can be evaluated
kpeter@584
    66
  ///and passed to the appropriate reader function.
alpar@387
    67
  DimacsDescriptor dimacsType(std::istream& is)
alpar@387
    68
  {
alpar@387
    69
    DimacsDescriptor r;
alpar@387
    70
    std::string problem,str;
alpar@387
    71
    char c;
alpar@387
    72
    r.lineShift=0;
alpar@387
    73
    while (is >> c)
alpar@387
    74
      switch(c)
alpar@387
    75
        {
alpar@387
    76
        case 'p':
alpar@387
    77
          if(is >> problem >> r.nodeNum >> r.edgeNum)
alpar@387
    78
            {
alpar@387
    79
              getline(is, str);
alpar@387
    80
              r.lineShift++;
alpar@387
    81
              if(problem=="min") r.type=DimacsDescriptor::MIN;
alpar@387
    82
              else if(problem=="max") r.type=DimacsDescriptor::MAX;
alpar@387
    83
              else if(problem=="sp") r.type=DimacsDescriptor::SP;
alpar@387
    84
              else if(problem=="mat") r.type=DimacsDescriptor::MAT;
alpar@387
    85
              else throw FormatError("Unknown problem type");
alpar@387
    86
              return r;
alpar@387
    87
            }
alpar@387
    88
          else
alpar@387
    89
            {
alpar@387
    90
              throw FormatError("Missing or wrong problem type declaration.");
alpar@387
    91
            }
alpar@387
    92
          break;
alpar@387
    93
        case 'c':
alpar@387
    94
          getline(is, str);
alpar@387
    95
          r.lineShift++;
alpar@387
    96
          break;
alpar@387
    97
        default:
alpar@387
    98
          throw FormatError("Unknown DIMACS declaration.");
alpar@387
    99
        }
alpar@387
   100
    throw FormatError("Missing problem type declaration.");
alpar@387
   101
  }
alpar@387
   102
alpar@387
   103
kpeter@584
   104
  /// \brief DIMACS minimum cost flow reader function.
alpar@385
   105
  ///
kpeter@388
   106
  /// This function reads a minimum cost flow instance from DIMACS format,
kpeter@388
   107
  /// i.e. from a DIMACS file having a line starting with
alpar@385
   108
  /// \code
alpar@385
   109
  ///   p min
alpar@385
   110
  /// \endcode
alpar@387
   111
  /// At the beginning, \c g is cleared by \c g.clear(). The supply
alpar@561
   112
  /// amount of the nodes are written to the \c supply node map
alpar@561
   113
  /// (they are signed values). The lower bounds, capacities and costs
alpar@561
   114
  /// of the arcs are written to the \c lower, \c capacity and \c cost
alpar@561
   115
  /// arc maps.
alpar@561
   116
  ///
alpar@561
   117
  /// If the capacity of an arc is less than the lower bound, it will
alpar@561
   118
  /// be set to "infinite" instead. The actual value of "infinite" is
alpar@561
   119
  /// contolled by the \c infty parameter. If it is 0 (the default value),
alpar@561
   120
  /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
alpar@561
   121
  /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
alpar@561
   122
  /// a non-zero value, that value will be used as "infinite".
alpar@387
   123
  ///
alpar@387
   124
  /// If the file type was previously evaluated by dimacsType(), then
alpar@387
   125
  /// the descriptor struct should be given by the \c dest parameter.
alpar@385
   126
  template <typename Digraph, typename LowerMap,
alpar@387
   127
            typename CapacityMap, typename CostMap,
alpar@387
   128
            typename SupplyMap>
alpar@387
   129
  void readDimacsMin(std::istream& is,
alpar@387
   130
                     Digraph &g,
alpar@387
   131
                     LowerMap& lower,
alpar@387
   132
                     CapacityMap& capacity,
alpar@387
   133
                     CostMap& cost,
alpar@387
   134
                     SupplyMap& supply,
alpar@561
   135
                     typename CapacityMap::Value infty = 0,
alpar@387
   136
                     DimacsDescriptor desc=DimacsDescriptor())
alpar@385
   137
  {
alpar@385
   138
    g.clear();
alpar@385
   139
    std::vector<typename Digraph::Node> nodes;
alpar@385
   140
    typename Digraph::Arc e;
alpar@385
   141
    std::string problem, str;
alpar@385
   142
    char c;
alpar@385
   143
    int i, j;
alpar@387
   144
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
alpar@387
   145
    if(desc.type!=DimacsDescriptor::MIN)
alpar@387
   146
      throw FormatError("Problem type mismatch");
alpar@387
   147
alpar@387
   148
    nodes.resize(desc.nodeNum + 1);
alpar@387
   149
    for (int k = 1; k <= desc.nodeNum; ++k) {
alpar@387
   150
      nodes[k] = g.addNode();
alpar@387
   151
      supply.set(nodes[k], 0);
alpar@387
   152
    }
alpar@387
   153
alpar@385
   154
    typename SupplyMap::Value sup;
alpar@385
   155
    typename CapacityMap::Value low;
alpar@385
   156
    typename CapacityMap::Value cap;
alpar@385
   157
    typename CostMap::Value co;
alpar@561
   158
    typedef typename CapacityMap::Value Capacity;
alpar@561
   159
    if(infty==0)
alpar@561
   160
      infty = std::numeric_limits<Capacity>::has_infinity ?
alpar@561
   161
        std::numeric_limits<Capacity>::infinity() :
alpar@561
   162
        std::numeric_limits<Capacity>::max();
alpar@561
   163
alpar@385
   164
    while (is >> c) {
alpar@385
   165
      switch (c) {
alpar@385
   166
      case 'c': // comment line
alpar@385
   167
        getline(is, str);
alpar@385
   168
        break;
alpar@385
   169
      case 'n': // node definition line
alpar@385
   170
        is >> i >> sup;
alpar@385
   171
        getline(is, str);
alpar@385
   172
        supply.set(nodes[i], sup);
alpar@385
   173
        break;
alpar@561
   174
      case 'a': // arc definition line
alpar@385
   175
        is >> i >> j >> low >> cap >> co;
alpar@385
   176
        getline(is, str);
alpar@385
   177
        e = g.addArc(nodes[i], nodes[j]);
alpar@385
   178
        lower.set(e, low);
alpar@561
   179
        if (cap >= low)
alpar@385
   180
          capacity.set(e, cap);
alpar@385
   181
        else
alpar@561
   182
          capacity.set(e, infty);
alpar@385
   183
        cost.set(e, co);
alpar@385
   184
        break;
alpar@385
   185
      }
alpar@385
   186
    }
alpar@385
   187
  }
alpar@385
   188
alpar@385
   189
  template<typename Digraph, typename CapacityMap>
alpar@387
   190
  void _readDimacs(std::istream& is,
alpar@387
   191
                   Digraph &g,
alpar@387
   192
                   CapacityMap& capacity,
alpar@387
   193
                   typename Digraph::Node &s,
alpar@387
   194
                   typename Digraph::Node &t,
alpar@561
   195
                   typename CapacityMap::Value infty = 0,
alpar@387
   196
                   DimacsDescriptor desc=DimacsDescriptor()) {
alpar@385
   197
    g.clear();
alpar@387
   198
    s=t=INVALID;
alpar@385
   199
    std::vector<typename Digraph::Node> nodes;
alpar@385
   200
    typename Digraph::Arc e;
alpar@385
   201
    char c, d;
alpar@385
   202
    int i, j;
alpar@385
   203
    typename CapacityMap::Value _cap;
alpar@385
   204
    std::string str;
alpar@387
   205
    nodes.resize(desc.nodeNum + 1);
alpar@387
   206
    for (int k = 1; k <= desc.nodeNum; ++k) {
alpar@387
   207
      nodes[k] = g.addNode();
alpar@387
   208
    }
alpar@561
   209
    typedef typename CapacityMap::Value Capacity;
alpar@387
   210
alpar@561
   211
    if(infty==0)
alpar@561
   212
      infty = std::numeric_limits<Capacity>::has_infinity ?
alpar@561
   213
        std::numeric_limits<Capacity>::infinity() :
alpar@561
   214
        std::numeric_limits<Capacity>::max();
alpar@877
   215
alpar@385
   216
    while (is >> c) {
alpar@385
   217
      switch (c) {
alpar@385
   218
      case 'c': // comment line
alpar@385
   219
        getline(is, str);
alpar@385
   220
        break;
alpar@385
   221
      case 'n': // node definition line
alpar@387
   222
        if (desc.type==DimacsDescriptor::SP) { // shortest path problem
alpar@385
   223
          is >> i;
alpar@385
   224
          getline(is, str);
alpar@385
   225
          s = nodes[i];
alpar@385
   226
        }
alpar@387
   227
        if (desc.type==DimacsDescriptor::MAX) { // max flow problem
alpar@385
   228
          is >> i >> d;
alpar@385
   229
          getline(is, str);
alpar@385
   230
          if (d == 's') s = nodes[i];
alpar@385
   231
          if (d == 't') t = nodes[i];
alpar@385
   232
        }
alpar@385
   233
        break;
alpar@561
   234
      case 'a': // arc definition line
alpar@561
   235
        if (desc.type==DimacsDescriptor::SP) {
alpar@385
   236
          is >> i >> j >> _cap;
alpar@385
   237
          getline(is, str);
alpar@385
   238
          e = g.addArc(nodes[i], nodes[j]);
alpar@385
   239
          capacity.set(e, _cap);
alpar@877
   240
        }
alpar@561
   241
        else if (desc.type==DimacsDescriptor::MAX) {
alpar@561
   242
          is >> i >> j >> _cap;
alpar@561
   243
          getline(is, str);
alpar@561
   244
          e = g.addArc(nodes[i], nodes[j]);
alpar@561
   245
          if (_cap >= 0)
alpar@561
   246
            capacity.set(e, _cap);
alpar@561
   247
          else
alpar@561
   248
            capacity.set(e, infty);
alpar@561
   249
        }
alpar@561
   250
        else {
alpar@385
   251
          is >> i >> j;
alpar@385
   252
          getline(is, str);
alpar@385
   253
          g.addArc(nodes[i], nodes[j]);
alpar@385
   254
        }
alpar@385
   255
        break;
alpar@385
   256
      }
alpar@385
   257
    }
alpar@385
   258
  }
alpar@385
   259
kpeter@584
   260
  /// \brief DIMACS maximum flow reader function.
alpar@387
   261
  ///
kpeter@388
   262
  /// This function reads a maximum flow instance from DIMACS format,
kpeter@388
   263
  /// i.e. from a DIMACS file having a line starting with
alpar@387
   264
  /// \code
alpar@387
   265
  ///   p max
alpar@387
   266
  /// \endcode
alpar@387
   267
  /// At the beginning, \c g is cleared by \c g.clear(). The arc
alpar@561
   268
  /// capacities are written to the \c capacity arc map and \c s and
alpar@561
   269
  /// \c t are set to the source and the target nodes.
alpar@561
   270
  ///
alpar@561
   271
  /// If the capacity of an arc is negative, it will
alpar@561
   272
  /// be set to "infinite" instead. The actual value of "infinite" is
alpar@561
   273
  /// contolled by the \c infty parameter. If it is 0 (the default value),
alpar@561
   274
  /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
alpar@561
   275
  /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
alpar@561
   276
  /// a non-zero value, that value will be used as "infinite".
alpar@387
   277
  ///
alpar@387
   278
  /// If the file type was previously evaluated by dimacsType(), then
alpar@387
   279
  /// the descriptor struct should be given by the \c dest parameter.
alpar@387
   280
  template<typename Digraph, typename CapacityMap>
alpar@387
   281
  void readDimacsMax(std::istream& is,
alpar@387
   282
                     Digraph &g,
alpar@387
   283
                     CapacityMap& capacity,
alpar@387
   284
                     typename Digraph::Node &s,
alpar@387
   285
                     typename Digraph::Node &t,
alpar@561
   286
                     typename CapacityMap::Value infty = 0,
alpar@387
   287
                     DimacsDescriptor desc=DimacsDescriptor()) {
alpar@387
   288
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
alpar@387
   289
    if(desc.type!=DimacsDescriptor::MAX)
alpar@387
   290
      throw FormatError("Problem type mismatch");
alpar@561
   291
    _readDimacs(is,g,capacity,s,t,infty,desc);
alpar@387
   292
  }
alpar@387
   293
kpeter@584
   294
  /// \brief DIMACS shortest path reader function.
alpar@385
   295
  ///
alpar@385
   296
  /// This function reads a shortest path instance from DIMACS format,
kpeter@388
   297
  /// i.e. from a DIMACS file having a line starting with
alpar@385
   298
  /// \code
alpar@385
   299
  ///   p sp
alpar@385
   300
  /// \endcode
alpar@387
   301
  /// At the beginning, \c g is cleared by \c g.clear(). The arc
alpar@561
   302
  /// lengths are written to the \c length arc map and \c s is set to the
alpar@385
   303
  /// source node.
alpar@387
   304
  ///
alpar@387
   305
  /// If the file type was previously evaluated by dimacsType(), then
alpar@387
   306
  /// the descriptor struct should be given by the \c dest parameter.
alpar@387
   307
  template<typename Digraph, typename LengthMap>
alpar@387
   308
  void readDimacsSp(std::istream& is,
alpar@387
   309
                    Digraph &g,
alpar@387
   310
                    LengthMap& length,
alpar@387
   311
                    typename Digraph::Node &s,
alpar@387
   312
                    DimacsDescriptor desc=DimacsDescriptor()) {
alpar@386
   313
    typename Digraph::Node t;
alpar@387
   314
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
alpar@387
   315
    if(desc.type!=DimacsDescriptor::SP)
alpar@387
   316
      throw FormatError("Problem type mismatch");
alpar@561
   317
    _readDimacs(is, g, length, s, t, 0, desc);
alpar@385
   318
  }
alpar@385
   319
kpeter@584
   320
  /// \brief DIMACS capacitated digraph reader function.
alpar@385
   321
  ///
alpar@385
   322
  /// This function reads an arc capacitated digraph instance from
alpar@561
   323
  /// DIMACS 'max' or 'sp' format.
alpar@387
   324
  /// At the beginning, \c g is cleared by \c g.clear()
alpar@561
   325
  /// and the arc capacities/lengths are written to the \c capacity
alpar@561
   326
  /// arc map.
alpar@561
   327
  ///
alpar@561
   328
  /// In case of the 'max' format, if the capacity of an arc is negative,
alpar@561
   329
  /// it will
alpar@561
   330
  /// be set to "infinite" instead. The actual value of "infinite" is
alpar@561
   331
  /// contolled by the \c infty parameter. If it is 0 (the default value),
alpar@561
   332
  /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
alpar@561
   333
  /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
alpar@561
   334
  /// a non-zero value, that value will be used as "infinite".
alpar@387
   335
  ///
alpar@387
   336
  /// If the file type was previously evaluated by dimacsType(), then
alpar@387
   337
  /// the descriptor struct should be given by the \c dest parameter.
alpar@385
   338
  template<typename Digraph, typename CapacityMap>
alpar@387
   339
  void readDimacsCap(std::istream& is,
alpar@387
   340
                     Digraph &g,
alpar@387
   341
                     CapacityMap& capacity,
alpar@561
   342
                     typename CapacityMap::Value infty = 0,
alpar@387
   343
                     DimacsDescriptor desc=DimacsDescriptor()) {
alpar@386
   344
    typename Digraph::Node u,v;
alpar@387
   345
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
alpar@387
   346
    if(desc.type!=DimacsDescriptor::MAX || desc.type!=DimacsDescriptor::SP)
alpar@387
   347
      throw FormatError("Problem type mismatch");
alpar@561
   348
    _readDimacs(is, g, capacity, u, v, infty, desc);
alpar@385
   349
  }
alpar@385
   350
alpar@525
   351
  template<typename Graph>
alpar@525
   352
  typename enable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
alpar@525
   353
  _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
alpar@525
   354
              dummy<0> = 0)
alpar@525
   355
  {
alpar@525
   356
    g.addEdge(s,t);
alpar@525
   357
  }
alpar@525
   358
  template<typename Graph>
alpar@525
   359
  typename disable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
alpar@525
   360
  _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
alpar@525
   361
              dummy<1> = 1)
alpar@525
   362
  {
alpar@525
   363
    g.addArc(s,t);
alpar@525
   364
  }
alpar@877
   365
kpeter@584
   366
  /// \brief DIMACS plain (di)graph reader function.
alpar@385
   367
  ///
kpeter@584
   368
  /// This function reads a plain (di)graph without any designated nodes
alpar@877
   369
  /// and maps (e.g. a matching instance) from DIMACS format, i.e. from
kpeter@584
   370
  /// DIMACS files having a line starting with
alpar@385
   371
  /// \code
alpar@385
   372
  ///   p mat
alpar@385
   373
  /// \endcode
alpar@387
   374
  /// At the beginning, \c g is cleared by \c g.clear().
alpar@387
   375
  ///
alpar@387
   376
  /// If the file type was previously evaluated by dimacsType(), then
alpar@387
   377
  /// the descriptor struct should be given by the \c dest parameter.
alpar@525
   378
  template<typename Graph>
alpar@525
   379
  void readDimacsMat(std::istream& is, Graph &g,
alpar@525
   380
                     DimacsDescriptor desc=DimacsDescriptor())
alpar@525
   381
  {
alpar@387
   382
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
alpar@387
   383
    if(desc.type!=DimacsDescriptor::MAT)
alpar@387
   384
      throw FormatError("Problem type mismatch");
alpar@525
   385
alpar@525
   386
    g.clear();
alpar@525
   387
    std::vector<typename Graph::Node> nodes;
alpar@525
   388
    char c;
alpar@525
   389
    int i, j;
alpar@525
   390
    std::string str;
alpar@525
   391
    nodes.resize(desc.nodeNum + 1);
alpar@525
   392
    for (int k = 1; k <= desc.nodeNum; ++k) {
alpar@525
   393
      nodes[k] = g.addNode();
alpar@525
   394
    }
alpar@877
   395
alpar@525
   396
    while (is >> c) {
alpar@525
   397
      switch (c) {
alpar@525
   398
      case 'c': // comment line
alpar@525
   399
        getline(is, str);
alpar@525
   400
        break;
alpar@525
   401
      case 'n': // node definition line
alpar@525
   402
        break;
alpar@561
   403
      case 'a': // arc definition line
alpar@525
   404
        is >> i >> j;
alpar@525
   405
        getline(is, str);
alpar@525
   406
        _addArcEdge(g,nodes[i], nodes[j]);
alpar@525
   407
        break;
alpar@525
   408
      }
alpar@525
   409
    }
alpar@385
   410
  }
alpar@385
   411
alpar@385
   412
  /// DIMACS plain digraph writer function.
alpar@385
   413
  ///
alpar@385
   414
  /// This function writes a digraph without any designated nodes and
alpar@385
   415
  /// maps into DIMACS format, i.e. into DIMACS file having a line
alpar@385
   416
  /// starting with
alpar@385
   417
  /// \code
alpar@385
   418
  ///   p mat
alpar@385
   419
  /// \endcode
alpar@387
   420
  /// If \c comment is not empty, then it will be printed in the first line
alpar@387
   421
  /// prefixed by 'c'.
alpar@385
   422
  template<typename Digraph>
alpar@387
   423
  void writeDimacsMat(std::ostream& os, const Digraph &g,
alpar@387
   424
                      std::string comment="") {
alpar@385
   425
    typedef typename Digraph::NodeIt NodeIt;
alpar@385
   426
    typedef typename Digraph::ArcIt ArcIt;
alpar@385
   427
alpar@440
   428
    if(!comment.empty())
alpar@387
   429
      os << "c " << comment << std::endl;
alpar@385
   430
    os << "p mat " << g.nodeNum() << " " << g.arcNum() << std::endl;
alpar@385
   431
alpar@385
   432
    typename Digraph::template NodeMap<int> nodes(g);
alpar@385
   433
    int i = 1;
alpar@385
   434
    for(NodeIt v(g); v != INVALID; ++v) {
alpar@385
   435
      nodes.set(v, i);
alpar@385
   436
      ++i;
alpar@385
   437
    }
alpar@385
   438
    for(ArcIt e(g); e != INVALID; ++e) {
alpar@385
   439
      os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)]
alpar@385
   440
         << std::endl;
alpar@385
   441
    }
alpar@385
   442
  }
alpar@385
   443
alpar@385
   444
  /// @}
alpar@385
   445
alpar@385
   446
} //namespace lemon
alpar@385
   447
alpar@385
   448
#endif //LEMON_DIMACS_H