1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2009
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