gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Accept negative values as unbounded capacity in dimacs readers (#243) and some doc improvements.
0 3 0
default
3 files changed with 87 insertions and 26 deletions:
↑ Collapse diff ↑
Ignore white space 12 line context
... ...
@@ -19,15 +19,15 @@
19 19
#ifndef LEMON_DIMACS_H
20 20
#define LEMON_DIMACS_H
21 21

	
22 22
#include <iostream>
23 23
#include <string>
24 24
#include <vector>
25
#include <limits>
25 26
#include <lemon/maps.h>
26 27
#include <lemon/error.h>
27

	
28 28
/// \ingroup dimacs_group
29 29
/// \file
30 30
/// \brief DIMACS file format reader.
31 31

	
32 32
namespace lemon {
33 33

	
... ...
@@ -52,13 +52,13 @@
52 52
    /// Constructor. Sets the type to NONE.
53 53
    DimacsDescriptor() : type(NONE) {}
54 54
  };
55 55

	
56 56
  ///Discover the type of a DIMACS file
57 57

	
58
  ///It starts seeking the begining of the file for the problem type
58
  ///It starts seeking the beginning of the file for the problem type
59 59
  ///and size info. The found data is returned in a special struct
60 60
  ///that can be evaluated and passed to the appropriate reader
61 61
  ///function.
62 62
  DimacsDescriptor dimacsType(std::istream& is)
63 63
  {
64 64
    DimacsDescriptor r;
... ...
@@ -102,27 +102,36 @@
102 102
  /// This function reads a minimum cost flow instance from DIMACS format,
103 103
  /// i.e. from a DIMACS file having a line starting with
104 104
  /// \code
105 105
  ///   p min
106 106
  /// \endcode
107 107
  /// At the beginning, \c g is cleared by \c g.clear(). The supply
108
  /// amount of the nodes are written to \c supply (signed). The
109
  /// lower bounds, capacities and costs of the arcs are written to
110
  /// \c lower, \c capacity and \c cost.
108
  /// amount of the nodes are written to the \c supply node map
109
  /// (they are signed values). The lower bounds, capacities and costs
110
  /// of the arcs are written to the \c lower, \c capacity and \c cost
111
  /// arc maps.
112
  ///
113
  /// If the capacity of an arc is less than the lower bound, it will
114
  /// be set to "infinite" instead. The actual value of "infinite" is
115
  /// contolled by the \c infty parameter. If it is 0 (the default value),
116
  /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
117
  /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
118
  /// a non-zero value, that value will be used as "infinite".
111 119
  ///
112 120
  /// If the file type was previously evaluated by dimacsType(), then
113 121
  /// the descriptor struct should be given by the \c dest parameter.
114 122
  template <typename Digraph, typename LowerMap,
115 123
            typename CapacityMap, typename CostMap,
116 124
            typename SupplyMap>
117 125
  void readDimacsMin(std::istream& is,
118 126
                     Digraph &g,
119 127
                     LowerMap& lower,
120 128
                     CapacityMap& capacity,
121 129
                     CostMap& cost,
122 130
                     SupplyMap& supply,
131
                     typename CapacityMap::Value infty = 0,
123 132
                     DimacsDescriptor desc=DimacsDescriptor())
124 133
  {
125 134
    g.clear();
126 135
    std::vector<typename Digraph::Node> nodes;
127 136
    typename Digraph::Arc e;
128 137
    std::string problem, str;
... ...
@@ -139,43 +148,50 @@
139 148
    }
140 149

	
141 150
    typename SupplyMap::Value sup;
142 151
    typename CapacityMap::Value low;
143 152
    typename CapacityMap::Value cap;
144 153
    typename CostMap::Value co;
154
    typedef typename CapacityMap::Value Capacity;
155
    if(infty==0)
156
      infty = std::numeric_limits<Capacity>::has_infinity ?
157
        std::numeric_limits<Capacity>::infinity() :
158
        std::numeric_limits<Capacity>::max();
159

	
145 160
    while (is >> c) {
146 161
      switch (c) {
147 162
      case 'c': // comment line
148 163
        getline(is, str);
149 164
        break;
150 165
      case 'n': // node definition line
151 166
        is >> i >> sup;
152 167
        getline(is, str);
153 168
        supply.set(nodes[i], sup);
154 169
        break;
155
      case 'a': // arc (arc) definition line
170
      case 'a': // arc definition line
156 171
        is >> i >> j >> low >> cap >> co;
157 172
        getline(is, str);
158 173
        e = g.addArc(nodes[i], nodes[j]);
159 174
        lower.set(e, low);
160
        if (cap >= 0)
175
        if (cap >= low)
161 176
          capacity.set(e, cap);
162 177
        else
163
          capacity.set(e, -1);
178
          capacity.set(e, infty);
164 179
        cost.set(e, co);
165 180
        break;
166 181
      }
167 182
    }
168 183
  }
169 184

	
170 185
  template<typename Digraph, typename CapacityMap>
171 186
  void _readDimacs(std::istream& is,
172 187
                   Digraph &g,
173 188
                   CapacityMap& capacity,
174 189
                   typename Digraph::Node &s,
175 190
                   typename Digraph::Node &t,
191
                   typename CapacityMap::Value infty = 0,
176 192
                   DimacsDescriptor desc=DimacsDescriptor()) {
177 193
    g.clear();
178 194
    s=t=INVALID;
179 195
    std::vector<typename Digraph::Node> nodes;
180 196
    typename Digraph::Arc e;
181 197
    char c, d;
... ...
@@ -183,13 +199,19 @@
183 199
    typename CapacityMap::Value _cap;
184 200
    std::string str;
185 201
    nodes.resize(desc.nodeNum + 1);
186 202
    for (int k = 1; k <= desc.nodeNum; ++k) {
187 203
      nodes[k] = g.addNode();
188 204
    }
205
    typedef typename CapacityMap::Value Capacity;
189 206

	
207
    if(infty==0)
208
      infty = std::numeric_limits<Capacity>::has_infinity ?
209
        std::numeric_limits<Capacity>::infinity() :
210
        std::numeric_limits<Capacity>::max();
211
 
190 212
    while (is >> c) {
191 213
      switch (c) {
192 214
      case 'c': // comment line
193 215
        getline(is, str);
194 216
        break;
195 217
      case 'n': // node definition line
... ...
@@ -202,20 +224,29 @@
202 224
          is >> i >> d;
203 225
          getline(is, str);
204 226
          if (d == 's') s = nodes[i];
205 227
          if (d == 't') t = nodes[i];
206 228
        }
207 229
        break;
208
      case 'a': // arc (arc) definition line
209
        if (desc.type==DimacsDescriptor::SP ||
210
            desc.type==DimacsDescriptor::MAX) {
230
      case 'a': // arc definition line
231
        if (desc.type==DimacsDescriptor::SP) {
211 232
          is >> i >> j >> _cap;
212 233
          getline(is, str);
213 234
          e = g.addArc(nodes[i], nodes[j]);
214 235
          capacity.set(e, _cap);
215
        } else {
236
        } 
237
        else if (desc.type==DimacsDescriptor::MAX) {
238
          is >> i >> j >> _cap;
239
          getline(is, str);
240
          e = g.addArc(nodes[i], nodes[j]);
241
          if (_cap >= 0)
242
            capacity.set(e, _cap);
243
          else
244
            capacity.set(e, infty);
245
        }
246
        else {
216 247
          is >> i >> j;
217 248
          getline(is, str);
218 249
          g.addArc(nodes[i], nodes[j]);
219 250
        }
220 251
        break;
221 252
      }
... ...
@@ -227,39 +258,47 @@
227 258
  /// This function reads a maximum flow instance from DIMACS format,
228 259
  /// i.e. from a DIMACS file having a line starting with
229 260
  /// \code
230 261
  ///   p max
231 262
  /// \endcode
232 263
  /// At the beginning, \c g is cleared by \c g.clear(). The arc
233
  /// capacities are written to \c capacity and \c s and \c t are
234
  /// set to the source and the target nodes.
264
  /// capacities are written to the \c capacity arc map and \c s and
265
  /// \c t are set to the source and the target nodes.
266
  ///
267
  /// If the capacity of an arc is negative, it will
268
  /// be set to "infinite" instead. The actual value of "infinite" is
269
  /// contolled by the \c infty parameter. If it is 0 (the default value),
270
  /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
271
  /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
272
  /// a non-zero value, that value will be used as "infinite".
235 273
  ///
236 274
  /// If the file type was previously evaluated by dimacsType(), then
237 275
  /// the descriptor struct should be given by the \c dest parameter.
238 276
  template<typename Digraph, typename CapacityMap>
239 277
  void readDimacsMax(std::istream& is,
240 278
                     Digraph &g,
241 279
                     CapacityMap& capacity,
242 280
                     typename Digraph::Node &s,
243 281
                     typename Digraph::Node &t,
282
                     typename CapacityMap::Value infty = 0,
244 283
                     DimacsDescriptor desc=DimacsDescriptor()) {
245 284
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
246 285
    if(desc.type!=DimacsDescriptor::MAX)
247 286
      throw FormatError("Problem type mismatch");
248
    _readDimacs(is,g,capacity,s,t,desc);
287
    _readDimacs(is,g,capacity,s,t,infty,desc);
249 288
  }
250 289

	
251 290
  /// DIMACS shortest path reader function.
252 291
  ///
253 292
  /// This function reads a shortest path instance from DIMACS format,
254 293
  /// i.e. from a DIMACS file having a line starting with
255 294
  /// \code
256 295
  ///   p sp
257 296
  /// \endcode
258 297
  /// At the beginning, \c g is cleared by \c g.clear(). The arc
259
  /// lengths are written to \c length and \c s is set to the
298
  /// lengths are written to the \c length arc map and \c s is set to the
260 299
  /// source node.
261 300
  ///
262 301
  /// If the file type was previously evaluated by dimacsType(), then
263 302
  /// the descriptor struct should be given by the \c dest parameter.
264 303
  template<typename Digraph, typename LengthMap>
265 304
  void readDimacsSp(std::istream& is,
... ...
@@ -268,34 +307,44 @@
268 307
                    typename Digraph::Node &s,
269 308
                    DimacsDescriptor desc=DimacsDescriptor()) {
270 309
    typename Digraph::Node t;
271 310
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
272 311
    if(desc.type!=DimacsDescriptor::SP)
273 312
      throw FormatError("Problem type mismatch");
274
    _readDimacs(is, g, length, s, t,desc);
313
    _readDimacs(is, g, length, s, t, 0, desc);
275 314
  }
276 315

	
277 316
  /// DIMACS capacitated digraph reader function.
278 317
  ///
279 318
  /// This function reads an arc capacitated digraph instance from
280
  /// DIMACS 'mat' or 'sp' format.
319
  /// DIMACS 'max' or 'sp' format.
281 320
  /// At the beginning, \c g is cleared by \c g.clear()
282
  /// and the arc capacities/lengths are written to \c capacity.
321
  /// and the arc capacities/lengths are written to the \c capacity
322
  /// arc map.
323
  ///
324
  /// In case of the 'max' format, if the capacity of an arc is negative,
325
  /// it will
326
  /// be set to "infinite" instead. The actual value of "infinite" is
327
  /// contolled by the \c infty parameter. If it is 0 (the default value),
328
  /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
329
  /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
330
  /// a non-zero value, that value will be used as "infinite".
283 331
  ///
284 332
  /// If the file type was previously evaluated by dimacsType(), then
285 333
  /// the descriptor struct should be given by the \c dest parameter.
286 334
  template<typename Digraph, typename CapacityMap>
287 335
  void readDimacsCap(std::istream& is,
288 336
                     Digraph &g,
289 337
                     CapacityMap& capacity,
338
                     typename CapacityMap::Value infty = 0,
290 339
                     DimacsDescriptor desc=DimacsDescriptor()) {
291 340
    typename Digraph::Node u,v;
292 341
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
293 342
    if(desc.type!=DimacsDescriptor::MAX || desc.type!=DimacsDescriptor::SP)
294 343
      throw FormatError("Problem type mismatch");
295
    _readDimacs(is, g, capacity, u, v, desc);
344
    _readDimacs(is, g, capacity, u, v, infty, desc);
296 345
  }
297 346

	
298 347
  template<typename Graph>
299 348
  typename enable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
300 349
  _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
301 350
              dummy<0> = 0)
... ...
@@ -344,13 +393,13 @@
344 393
      switch (c) {
345 394
      case 'c': // comment line
346 395
        getline(is, str);
347 396
        break;
348 397
      case 'n': // node definition line
349 398
        break;
350
      case 'a': // arc (arc) definition line
399
      case 'a': // arc definition line
351 400
        is >> i >> j;
352 401
        getline(is, str);
353 402
        _addArcEdge(g,nodes[i], nodes[j]);
354 403
        break;
355 404
      }
356 405
    }
Ignore white space 6 line context
... ...
@@ -69,21 +69,21 @@
69 69
  dij.run(s);
70 70
  if(report) std::cerr << "Run Dijkstra: " << t << '\n';
71 71
}
72 72

	
73 73
template<class Value>
74 74
void solve_max(ArgParser &ap, std::istream &is, std::ostream &,
75
              DimacsDescriptor &desc)
75
               Value infty, DimacsDescriptor &desc)
76 76
{
77 77
  bool report = !ap.given("q");
78 78
  Digraph g;
79 79
  Node s,t;
80 80
  Digraph::ArcMap<Value> cap(g);
81 81
  Timer ti;
82 82
  ti.restart();
83
  readDimacsMax(is, g, cap, s, t, desc);
83
  readDimacsMax(is, g, cap, s, t, infty, desc);
84 84
  if(report) std::cerr << "Read the file: " << ti << '\n';
85 85
  ti.restart();
86 86
  Preflow<Digraph, Digraph::ArcMap<Value> > pre(g,cap,s,t);
87 87
  if(report) std::cerr << "Setup Preflow class: " << ti << '\n';
88 88
  ti.restart();
89 89
  pre.run();
... ...
@@ -112,20 +112,31 @@
112 112

	
113 113

	
114 114
template<class Value>
115 115
void solve(ArgParser &ap, std::istream &is, std::ostream &os,
116 116
           DimacsDescriptor &desc)
117 117
{
118
  std::stringstream iss(ap["infcap"]);
119
  Value infty;
120
  iss >> infty;
121
  if(iss.fail())
122
    {
123
      std::cerr << "Cannot interpret '"
124
                << static_cast<std::string>(ap["infcap"]) << "' as infinite"
125
                << std::endl;
126
      exit(1);
127
    }
128
  
118 129
  switch(desc.type)
119 130
    {
120 131
    case DimacsDescriptor::MIN:
121 132
      std::cerr <<
122 133
        "\n\n Sorry, the min. cost flow solver is not yet available.\n";
123 134
      break;
124 135
    case DimacsDescriptor::MAX:
125
      solve_max<Value>(ap,is,os,desc);
136
      solve_max<Value>(ap,is,os,infty,desc);
126 137
      break;
127 138
    case DimacsDescriptor::SP:
128 139
      solve_sp<Value>(ap,is,os,desc);
129 140
      break;
130 141
    case DimacsDescriptor::MAT:
131 142
      solve_mat(ap,is,os,desc);
... ...
@@ -156,12 +167,13 @@
156 167
#endif
157 168
    .boolOption("double","Use 'double' for capacities, costs etc.")
158 169
    .optionGroup("datatype","double")
159 170
    .boolOption("ldouble","Use 'long double' for capacities, costs etc.")
160 171
    .optionGroup("datatype","ldouble")
161 172
    .onlyOneGroup("datatype")
173
    .stringOption("infcap","Value used for 'very high' capacities","0")
162 174
    .run();
163 175

	
164 176
  std::ifstream input;
165 177
  std::ofstream output;
166 178

	
167 179
  switch(ap.files().size())
Ignore white space 6 line context
... ...
@@ -93,13 +93,13 @@
93 93
    {
94 94
    case DimacsDescriptor::MIN:
95 95
      {
96 96
        Digraph digraph;
97 97
        DoubleArcMap lower(digraph), capacity(digraph), cost(digraph);
98 98
        DoubleNodeMap supply(digraph);
99
        readDimacsMin(is, digraph, lower, capacity, cost, supply, desc);
99
        readDimacsMin(is, digraph, lower, capacity, cost, supply, 0, desc);
100 100
        DigraphWriter<Digraph>(digraph, os).
101 101
          nodeMap("supply", supply).
102 102
          arcMap("lower", lower).
103 103
          arcMap("capacity", capacity).
104 104
          arcMap("cost", cost).
105 105
          attribute("problem","min").
... ...
@@ -108,13 +108,13 @@
108 108
      break;
109 109
    case DimacsDescriptor::MAX:
110 110
      {
111 111
        Digraph digraph;
112 112
        Node s, t;
113 113
        DoubleArcMap capacity(digraph);
114
        readDimacsMax(is, digraph, capacity, s, t, desc);
114
        readDimacsMax(is, digraph, capacity, s, t, 0, desc);
115 115
        DigraphWriter<Digraph>(digraph, os).
116 116
          arcMap("capacity", capacity).
117 117
          node("source", s).
118 118
          node("target", t).
119 119
          attribute("problem","max").
120 120
          run();
0 comments (0 inline)