gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
dimacs.h reads MAT files to both dir and undir graphs (#231)
0 1 0
default
1 file changed with 46 insertions and 8 deletions:
↑ Collapse diff ↑
Ignore white space 3145728 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
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 25
#include <lemon/maps.h>
26 26
#include <lemon/error.h>
27 27

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

	
32 32
namespace lemon {
33 33

	
34 34
  /// \addtogroup dimacs_group
35 35
  /// @{
36 36

	
37 37
  /// DIMACS file type descriptor.
38 38
  struct DimacsDescriptor
39 39
  {
40 40
    ///File type enum
41 41
    enum Type
42 42
      {
43 43
        NONE, MIN, MAX, SP, MAT
44 44
      };
45 45
    ///The file type
46 46
    Type type;
47 47
    ///The number of nodes in the graph
48 48
    int nodeNum;
49 49
    ///The number of edges in the graph
50 50
    int edgeNum;
51 51
    int lineShift;
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 58
  ///It starts seeking the begining 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;
65 65
    std::string problem,str;
66 66
    char c;
67 67
    r.lineShift=0;
68 68
    while (is >> c)
69 69
      switch(c)
70 70
        {
71 71
        case 'p':
72 72
          if(is >> problem >> r.nodeNum >> r.edgeNum)
73 73
            {
74 74
              getline(is, str);
75 75
              r.lineShift++;
76 76
              if(problem=="min") r.type=DimacsDescriptor::MIN;
77 77
              else if(problem=="max") r.type=DimacsDescriptor::MAX;
78 78
              else if(problem=="sp") r.type=DimacsDescriptor::SP;
79 79
              else if(problem=="mat") r.type=DimacsDescriptor::MAT;
80 80
              else throw FormatError("Unknown problem type");
81 81
              return r;
82 82
            }
83 83
          else
84 84
            {
85 85
              throw FormatError("Missing or wrong problem type declaration.");
86 86
            }
87 87
          break;
88 88
        case 'c':
89 89
          getline(is, str);
90 90
          r.lineShift++;
91 91
          break;
92 92
        default:
93 93
          throw FormatError("Unknown DIMACS declaration.");
94 94
        }
95 95
    throw FormatError("Missing problem type declaration.");
96 96
  }
97 97

	
98 98

	
99 99

	
100 100
  /// DIMACS minimum cost flow reader function.
101 101
  ///
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 108
  /// amount of the nodes are written to \c supply (signed). The
109 109
  /// lower bounds, capacities and costs of the arcs are written to
110 110
  /// \c lower, \c capacity and \c cost.
111 111
  ///
112 112
  /// If the file type was previously evaluated by dimacsType(), then
113 113
  /// the descriptor struct should be given by the \c dest parameter.
114 114
  template <typename Digraph, typename LowerMap,
115 115
            typename CapacityMap, typename CostMap,
116 116
            typename SupplyMap>
117 117
  void readDimacsMin(std::istream& is,
118 118
                     Digraph &g,
119 119
                     LowerMap& lower,
120 120
                     CapacityMap& capacity,
121 121
                     CostMap& cost,
122 122
                     SupplyMap& supply,
123 123
                     DimacsDescriptor desc=DimacsDescriptor())
124 124
  {
125 125
    g.clear();
126 126
    std::vector<typename Digraph::Node> nodes;
127 127
    typename Digraph::Arc e;
128 128
    std::string problem, str;
129 129
    char c;
130 130
    int i, j;
131 131
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
132 132
    if(desc.type!=DimacsDescriptor::MIN)
133 133
      throw FormatError("Problem type mismatch");
134 134

	
135 135
    nodes.resize(desc.nodeNum + 1);
136 136
    for (int k = 1; k <= desc.nodeNum; ++k) {
137 137
      nodes[k] = g.addNode();
138 138
      supply.set(nodes[k], 0);
139 139
    }
140 140

	
141 141
    typename SupplyMap::Value sup;
142 142
    typename CapacityMap::Value low;
143 143
    typename CapacityMap::Value cap;
144 144
    typename CostMap::Value co;
145 145
    while (is >> c) {
146 146
      switch (c) {
147 147
      case 'c': // comment line
148 148
        getline(is, str);
149 149
        break;
150 150
      case 'n': // node definition line
151 151
        is >> i >> sup;
152 152
        getline(is, str);
153 153
        supply.set(nodes[i], sup);
154 154
        break;
155 155
      case 'a': // arc (arc) definition line
156 156
        is >> i >> j >> low >> cap >> co;
157 157
        getline(is, str);
158 158
        e = g.addArc(nodes[i], nodes[j]);
159 159
        lower.set(e, low);
160 160
        if (cap >= 0)
161 161
          capacity.set(e, cap);
162 162
        else
163 163
          capacity.set(e, -1);
164 164
        cost.set(e, co);
165 165
        break;
166 166
      }
167 167
    }
168 168
  }
169 169

	
170 170
  template<typename Digraph, typename CapacityMap>
171 171
  void _readDimacs(std::istream& is,
172 172
                   Digraph &g,
173 173
                   CapacityMap& capacity,
174 174
                   typename Digraph::Node &s,
175 175
                   typename Digraph::Node &t,
176 176
                   DimacsDescriptor desc=DimacsDescriptor()) {
177 177
    g.clear();
178 178
    s=t=INVALID;
179 179
    std::vector<typename Digraph::Node> nodes;
180 180
    typename Digraph::Arc e;
181 181
    char c, d;
182 182
    int i, j;
183 183
    typename CapacityMap::Value _cap;
184 184
    std::string str;
185 185
    nodes.resize(desc.nodeNum + 1);
186 186
    for (int k = 1; k <= desc.nodeNum; ++k) {
187 187
      nodes[k] = g.addNode();
188 188
    }
189 189

	
190 190
    while (is >> c) {
191 191
      switch (c) {
192 192
      case 'c': // comment line
193 193
        getline(is, str);
194 194
        break;
195 195
      case 'n': // node definition line
196 196
        if (desc.type==DimacsDescriptor::SP) { // shortest path problem
197 197
          is >> i;
198 198
          getline(is, str);
199 199
          s = nodes[i];
200 200
        }
201 201
        if (desc.type==DimacsDescriptor::MAX) { // max flow problem
202 202
          is >> i >> d;
203 203
          getline(is, str);
204 204
          if (d == 's') s = nodes[i];
205 205
          if (d == 't') t = nodes[i];
206 206
        }
207 207
        break;
208 208
      case 'a': // arc (arc) definition line
209 209
        if (desc.type==DimacsDescriptor::SP ||
210 210
            desc.type==DimacsDescriptor::MAX) {
211 211
          is >> i >> j >> _cap;
212 212
          getline(is, str);
213 213
          e = g.addArc(nodes[i], nodes[j]);
214 214
          capacity.set(e, _cap);
215 215
        } else {
216 216
          is >> i >> j;
217 217
          getline(is, str);
218 218
          g.addArc(nodes[i], nodes[j]);
219 219
        }
220 220
        break;
221 221
      }
222 222
    }
223 223
  }
224 224

	
225 225
  /// DIMACS maximum flow reader function.
226 226
  ///
227 227
  /// This function reads a maximum flow instance from DIMACS format,
228 228
  /// i.e. from a DIMACS file having a line starting with
229 229
  /// \code
230 230
  ///   p max
231 231
  /// \endcode
232 232
  /// At the beginning, \c g is cleared by \c g.clear(). The arc
233 233
  /// capacities are written to \c capacity and \c s and \c t are
234 234
  /// set to the source and the target nodes.
235 235
  ///
236 236
  /// If the file type was previously evaluated by dimacsType(), then
237 237
  /// the descriptor struct should be given by the \c dest parameter.
238 238
  template<typename Digraph, typename CapacityMap>
239 239
  void readDimacsMax(std::istream& is,
240 240
                     Digraph &g,
241 241
                     CapacityMap& capacity,
242 242
                     typename Digraph::Node &s,
243 243
                     typename Digraph::Node &t,
244 244
                     DimacsDescriptor desc=DimacsDescriptor()) {
245 245
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
246 246
    if(desc.type!=DimacsDescriptor::MAX)
247 247
      throw FormatError("Problem type mismatch");
248 248
    _readDimacs(is,g,capacity,s,t,desc);
249 249
  }
250 250

	
251 251
  /// DIMACS shortest path reader function.
252 252
  ///
253 253
  /// This function reads a shortest path instance from DIMACS format,
254 254
  /// i.e. from a DIMACS file having a line starting with
255 255
  /// \code
256 256
  ///   p sp
257 257
  /// \endcode
258 258
  /// At the beginning, \c g is cleared by \c g.clear(). The arc
259 259
  /// lengths are written to \c length and \c s is set to the
260 260
  /// source node.
261 261
  ///
262 262
  /// If the file type was previously evaluated by dimacsType(), then
263 263
  /// the descriptor struct should be given by the \c dest parameter.
264 264
  template<typename Digraph, typename LengthMap>
265 265
  void readDimacsSp(std::istream& is,
266 266
                    Digraph &g,
267 267
                    LengthMap& length,
268 268
                    typename Digraph::Node &s,
269 269
                    DimacsDescriptor desc=DimacsDescriptor()) {
270 270
    typename Digraph::Node t;
271 271
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
272 272
    if(desc.type!=DimacsDescriptor::SP)
273 273
      throw FormatError("Problem type mismatch");
274 274
    _readDimacs(is, g, length, s, t,desc);
275 275
  }
276 276

	
277 277
  /// DIMACS capacitated digraph reader function.
278 278
  ///
279 279
  /// This function reads an arc capacitated digraph instance from
280 280
  /// DIMACS 'mat' or 'sp' format.
281 281
  /// At the beginning, \c g is cleared by \c g.clear()
282 282
  /// and the arc capacities/lengths are written to \c capacity.
283 283
  ///
284 284
  /// If the file type was previously evaluated by dimacsType(), then
285 285
  /// the descriptor struct should be given by the \c dest parameter.
286 286
  template<typename Digraph, typename CapacityMap>
287 287
  void readDimacsCap(std::istream& is,
288 288
                     Digraph &g,
289 289
                     CapacityMap& capacity,
290 290
                     DimacsDescriptor desc=DimacsDescriptor()) {
291 291
    typename Digraph::Node u,v;
292 292
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
293 293
    if(desc.type!=DimacsDescriptor::MAX || desc.type!=DimacsDescriptor::SP)
294 294
      throw FormatError("Problem type mismatch");
295 295
    _readDimacs(is, g, capacity, u, v, desc);
296 296
  }
297 297

	
298
  /// DIMACS plain digraph reader function.
298
  template<typename Graph>
299
  typename enable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
300
  _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
301
              dummy<0> = 0)
302
  {
303
    g.addEdge(s,t);
304
  }
305
  template<typename Graph>
306
  typename disable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
307
  _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
308
              dummy<1> = 1)
309
  {
310
    g.addArc(s,t);
311
  }
312
  
313
  /// DIMACS plain (di)graph reader function.
299 314
  ///
300
  /// This function reads a digraph without any designated nodes and
315
  /// This function reads a (di)graph without any designated nodes and
301 316
  /// maps from DIMACS format, i.e. from DIMACS files having a line
302 317
  /// starting with
303 318
  /// \code
304 319
  ///   p mat
305 320
  /// \endcode
306 321
  /// At the beginning, \c g is cleared by \c g.clear().
307 322
  ///
308 323
  /// If the file type was previously evaluated by dimacsType(), then
309 324
  /// the descriptor struct should be given by the \c dest parameter.
310
  template<typename Digraph>
311
  void readDimacsMat(std::istream& is, Digraph &g,
312
                     DimacsDescriptor desc=DimacsDescriptor()) {
313
    typename Digraph::Node u,v;
314
    NullMap<typename Digraph::Arc, int> n;
325
  template<typename Graph>
326
  void readDimacsMat(std::istream& is, Graph &g,
327
                     DimacsDescriptor desc=DimacsDescriptor())
328
  {
315 329
    if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
316 330
    if(desc.type!=DimacsDescriptor::MAT)
317 331
      throw FormatError("Problem type mismatch");
318
    _readDimacs(is, g, n, u, v, desc);
332

	
333
    g.clear();
334
    std::vector<typename Graph::Node> nodes;
335
    char c;
336
    int i, j;
337
    std::string str;
338
    nodes.resize(desc.nodeNum + 1);
339
    for (int k = 1; k <= desc.nodeNum; ++k) {
340
      nodes[k] = g.addNode();
341
    }
342
    
343
    while (is >> c) {
344
      switch (c) {
345
      case 'c': // comment line
346
        getline(is, str);
347
        break;
348
      case 'n': // node definition line
349
        break;
350
      case 'a': // arc (arc) definition line
351
        is >> i >> j;
352
        getline(is, str);
353
        _addArcEdge(g,nodes[i], nodes[j]);
354
        break;
355
      }
356
    }
319 357
  }
320 358

	
321 359
  /// DIMACS plain digraph writer function.
322 360
  ///
323 361
  /// This function writes a digraph without any designated nodes and
324 362
  /// maps into DIMACS format, i.e. into DIMACS file having a line
325 363
  /// starting with
326 364
  /// \code
327 365
  ///   p mat
328 366
  /// \endcode
329 367
  /// If \c comment is not empty, then it will be printed in the first line
330 368
  /// prefixed by 'c'.
331 369
  template<typename Digraph>
332 370
  void writeDimacsMat(std::ostream& os, const Digraph &g,
333 371
                      std::string comment="") {
334 372
    typedef typename Digraph::NodeIt NodeIt;
335 373
    typedef typename Digraph::ArcIt ArcIt;
336 374

	
337 375
    if(!comment.empty())
338 376
      os << "c " << comment << std::endl;
339 377
    os << "p mat " << g.nodeNum() << " " << g.arcNum() << std::endl;
340 378

	
341 379
    typename Digraph::template NodeMap<int> nodes(g);
342 380
    int i = 1;
343 381
    for(NodeIt v(g); v != INVALID; ++v) {
344 382
      nodes.set(v, i);
345 383
      ++i;
346 384
    }
347 385
    for(ArcIt e(g); e != INVALID; ++e) {
348 386
      os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)]
349 387
         << std::endl;
350 388
    }
351 389
  }
352 390

	
353 391
  /// @}
354 392

	
355 393
} //namespace lemon
356 394

	
357 395
#endif //LEMON_DIMACS_H
0 comments (0 inline)