1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2013
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>
29 /// \ingroup dimacs_group
31 /// \brief DIMACS file format reader.
35 /// \addtogroup dimacs_group
38 /// DIMACS file type descriptor.
39 struct DimacsDescriptor
41 ///\brief DIMACS file type enum
43 ///DIMACS file type enum.
45 NONE, ///< Undefined type.
46 MIN, ///< DIMACS file type for minimum cost flow problems.
47 MAX, ///< DIMACS file type for maximum flow problems.
48 SP, ///< DIMACS file type for shostest path problems.
49 MAT ///< DIMACS file type for plain graphs and matching problems.
53 ///The number of nodes in the graph
55 ///The number of edges in the graph
58 ///Constructor. It sets the type to \c NONE.
59 DimacsDescriptor() : type(NONE) {}
62 ///Discover the type of a DIMACS file
64 ///This function starts seeking the beginning of the given file for the
65 ///problem type and size info.
66 ///The found data is returned in a special struct that can be evaluated
67 ///and passed to the appropriate reader function.
68 DimacsDescriptor dimacsType(std::istream& is)
71 std::string problem,str;
78 if(is >> problem >> r.nodeNum >> r.edgeNum)
82 if(problem=="min") r.type=DimacsDescriptor::MIN;
83 else if(problem=="max") r.type=DimacsDescriptor::MAX;
84 else if(problem=="sp") r.type=DimacsDescriptor::SP;
85 else if(problem=="mat") r.type=DimacsDescriptor::MAT;
86 else throw FormatError("Unknown problem type");
91 throw FormatError("Missing or wrong problem type declaration.");
99 throw FormatError("Unknown DIMACS declaration.");
101 throw FormatError("Missing problem type declaration.");
105 /// \brief DIMACS minimum cost flow reader function.
107 /// This function reads a minimum cost flow instance from DIMACS format,
108 /// i.e. from a DIMACS file having a line starting with
112 /// At the beginning, \c g is cleared by \c g.clear(). The supply
113 /// amount of the nodes are written to the \c supply node map
114 /// (they are signed values). The lower bounds, capacities and costs
115 /// of the arcs are written to the \c lower, \c capacity and \c cost
118 /// If the capacity of an arc is less than the lower bound, it will
119 /// be set to "infinite" instead. The actual value of "infinite" is
120 /// contolled by the \c infty parameter. If it is 0 (the default value),
121 /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
122 /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
123 /// a non-zero value, that value will be used as "infinite".
125 /// If the file type was previously evaluated by dimacsType(), then
126 /// the descriptor struct should be given by the \c desc parameter.
127 template <typename Digraph, typename LowerMap,
128 typename CapacityMap, typename CostMap,
130 void readDimacsMin(std::istream& is,
133 CapacityMap& capacity,
136 typename CapacityMap::Value infty = 0,
137 DimacsDescriptor desc=DimacsDescriptor())
140 std::vector<typename Digraph::Node> nodes;
141 typename Digraph::Arc e;
142 std::string problem, str;
145 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
146 if(desc.type!=DimacsDescriptor::MIN)
147 throw FormatError("Problem type mismatch");
149 nodes.resize(desc.nodeNum + 1);
150 for (int k = 1; k <= desc.nodeNum; ++k) {
151 nodes[k] = g.addNode();
152 supply.set(nodes[k], 0);
155 typename SupplyMap::Value sup;
156 typename CapacityMap::Value low;
157 typename CapacityMap::Value cap;
158 typename CostMap::Value co;
159 typedef typename CapacityMap::Value Capacity;
161 infty = std::numeric_limits<Capacity>::has_infinity ?
162 std::numeric_limits<Capacity>::infinity() :
163 std::numeric_limits<Capacity>::max();
167 case 'c': // comment line
170 case 'n': // node definition line
173 supply.set(nodes[i], sup);
175 case 'a': // arc definition line
176 is >> i >> j >> low >> cap >> co;
178 e = g.addArc(nodes[i], nodes[j]);
181 capacity.set(e, cap);
183 capacity.set(e, infty);
190 template<typename Digraph, typename CapacityMap>
191 void _readDimacs(std::istream& is,
193 CapacityMap& capacity,
194 typename Digraph::Node &s,
195 typename Digraph::Node &t,
196 typename CapacityMap::Value infty = 0,
197 DimacsDescriptor desc=DimacsDescriptor()) {
200 std::vector<typename Digraph::Node> nodes;
201 typename Digraph::Arc e;
204 typename CapacityMap::Value _cap;
206 nodes.resize(desc.nodeNum + 1);
207 for (int k = 1; k <= desc.nodeNum; ++k) {
208 nodes[k] = g.addNode();
210 typedef typename CapacityMap::Value Capacity;
213 infty = std::numeric_limits<Capacity>::has_infinity ?
214 std::numeric_limits<Capacity>::infinity() :
215 std::numeric_limits<Capacity>::max();
219 case 'c': // comment line
222 case 'n': // node definition line
223 if (desc.type==DimacsDescriptor::SP) { // shortest path problem
228 if (desc.type==DimacsDescriptor::MAX) { // max flow problem
231 if (d == 's') s = nodes[i];
232 if (d == 't') t = nodes[i];
235 case 'a': // arc definition line
236 if (desc.type==DimacsDescriptor::SP) {
237 is >> i >> j >> _cap;
239 e = g.addArc(nodes[i], nodes[j]);
240 capacity.set(e, _cap);
242 else if (desc.type==DimacsDescriptor::MAX) {
243 is >> i >> j >> _cap;
245 e = g.addArc(nodes[i], nodes[j]);
247 capacity.set(e, _cap);
249 capacity.set(e, infty);
254 g.addArc(nodes[i], nodes[j]);
261 /// \brief DIMACS maximum flow reader function.
263 /// This function reads a maximum flow instance from DIMACS format,
264 /// i.e. from a DIMACS file having a line starting with
268 /// At the beginning, \c g is cleared by \c g.clear(). The arc
269 /// capacities are written to the \c capacity arc map and \c s and
270 /// \c t are set to the source and the target nodes.
272 /// If the capacity of an arc is negative, it will
273 /// be set to "infinite" instead. The actual value of "infinite" is
274 /// contolled by the \c infty parameter. If it is 0 (the default value),
275 /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
276 /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
277 /// a non-zero value, that value will be used as "infinite".
279 /// If the file type was previously evaluated by dimacsType(), then
280 /// the descriptor struct should be given by the \c desc parameter.
281 template<typename Digraph, typename CapacityMap>
282 void readDimacsMax(std::istream& is,
284 CapacityMap& capacity,
285 typename Digraph::Node &s,
286 typename Digraph::Node &t,
287 typename CapacityMap::Value infty = 0,
288 DimacsDescriptor desc=DimacsDescriptor()) {
289 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
290 if(desc.type!=DimacsDescriptor::MAX)
291 throw FormatError("Problem type mismatch");
292 _readDimacs(is,g,capacity,s,t,infty,desc);
295 /// \brief DIMACS shortest path reader function.
297 /// This function reads a shortest path instance from DIMACS format,
298 /// i.e. from a DIMACS file having a line starting with
302 /// At the beginning, \c g is cleared by \c g.clear(). The arc
303 /// lengths are written to the \c length arc map and \c s is set to the
306 /// If the file type was previously evaluated by dimacsType(), then
307 /// the descriptor struct should be given by the \c desc parameter.
308 template<typename Digraph, typename LengthMap>
309 void readDimacsSp(std::istream& is,
312 typename Digraph::Node &s,
313 DimacsDescriptor desc=DimacsDescriptor()) {
314 typename Digraph::Node t;
315 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
316 if(desc.type!=DimacsDescriptor::SP)
317 throw FormatError("Problem type mismatch");
318 _readDimacs(is, g, length, s, t, 0, desc);
321 /// \brief DIMACS capacitated digraph reader function.
323 /// This function reads an arc capacitated digraph instance from
324 /// DIMACS 'max' or 'sp' format.
325 /// At the beginning, \c g is cleared by \c g.clear()
326 /// and the arc capacities/lengths are written to the \c capacity
329 /// In case of the 'max' format, if the capacity of an arc is negative,
331 /// be set to "infinite" instead. The actual value of "infinite" is
332 /// contolled by the \c infty parameter. If it is 0 (the default value),
333 /// \c std::numeric_limits<Capacity>::infinity() will be used if available,
334 /// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
335 /// a non-zero value, that value will be used as "infinite".
337 /// If the file type was previously evaluated by dimacsType(), then
338 /// the descriptor struct should be given by the \c desc parameter.
339 template<typename Digraph, typename CapacityMap>
340 void readDimacsCap(std::istream& is,
342 CapacityMap& capacity,
343 typename CapacityMap::Value infty = 0,
344 DimacsDescriptor desc=DimacsDescriptor()) {
345 typename Digraph::Node u,v;
346 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
347 if(desc.type!=DimacsDescriptor::MAX && desc.type!=DimacsDescriptor::SP)
348 throw FormatError("Problem type mismatch");
349 _readDimacs(is, g, capacity, u, v, infty, desc);
352 template<typename Graph>
353 typename enable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
354 _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
359 template<typename Graph>
360 typename disable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
361 _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
367 /// \brief DIMACS plain (di)graph reader function.
369 /// This function reads a plain (di)graph without any designated nodes
370 /// and maps (e.g. a matching instance) from DIMACS format, i.e. from
371 /// DIMACS files having a line starting with
375 /// At the beginning, \c g is cleared by \c g.clear().
377 /// If the file type was previously evaluated by dimacsType(), then
378 /// the descriptor struct should be given by the \c desc parameter.
379 template<typename Graph>
380 void readDimacsMat(std::istream& is, Graph &g,
381 DimacsDescriptor desc=DimacsDescriptor())
383 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
384 if(desc.type!=DimacsDescriptor::MAT)
385 throw FormatError("Problem type mismatch");
388 std::vector<typename Graph::Node> nodes;
392 nodes.resize(desc.nodeNum + 1);
393 for (int k = 1; k <= desc.nodeNum; ++k) {
394 nodes[k] = g.addNode();
399 case 'c': // comment line
402 case 'n': // node definition line
404 case 'a': // arc definition line
407 _addArcEdge(g,nodes[i], nodes[j]);
413 /// DIMACS plain digraph writer function.
415 /// This function writes a digraph without any designated nodes and
416 /// maps into DIMACS format, i.e. into DIMACS file having a line
421 /// If \c comment is not empty, then it will be printed in the first line
423 template<typename Digraph>
424 void writeDimacsMat(std::ostream& os, const Digraph &g,
425 std::string comment="") {
426 typedef typename Digraph::NodeIt NodeIt;
427 typedef typename Digraph::ArcIt ArcIt;
430 os << "c " << comment << std::endl;
431 os << "p mat " << g.nodeNum() << " " << g.arcNum() << std::endl;
433 typename Digraph::template NodeMap<int> nodes(g);
435 for(NodeIt v(g); v != INVALID; ++v) {
439 for(ArcIt e(g); e != INVALID; ++e) {
440 os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)]
449 #endif //LEMON_DIMACS_H