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
43 NONE, MIN, MAX, SP, MAT
47 ///The number of nodes in the graph
49 ///The number of edges in the graph
52 /// Constructor. Sets the type to NONE.
53 DimacsDescriptor() : type(NONE) {}
56 ///Discover the type of a DIMACS file
58 ///It starts seeking the beginning of the file for the problem type
59 ///and size info. The found data is returned in a special struct
60 ///that can be evaluated and passed to the appropriate reader
62 DimacsDescriptor dimacsType(std::istream& is)
65 std::string problem,str;
72 if(is >> problem >> r.nodeNum >> r.edgeNum)
76 if(problem=="min") r.type=DimacsDescriptor::MIN;
77 else if(problem=="max") r.type=DimacsDescriptor::MAX;
78 else if(problem=="sp") r.type=DimacsDescriptor::SP;
79 else if(problem=="mat") r.type=DimacsDescriptor::MAT;
80 else throw FormatError("Unknown problem type");
85 throw FormatError("Missing or wrong problem type declaration.");
93 throw FormatError("Unknown DIMACS declaration.");
95 throw FormatError("Missing problem type declaration.");
100 /// DIMACS minimum cost flow reader function.
102 /// This function reads a minimum cost flow instance from DIMACS format,
103 /// i.e. from a DIMACS file having a line starting with
107 /// At the beginning, \c g is cleared by \c g.clear(). The supply
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
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".
120 /// If the file type was previously evaluated by dimacsType(), then
121 /// the descriptor struct should be given by the \c dest parameter.
122 template <typename Digraph, typename LowerMap,
123 typename CapacityMap, typename CostMap,
125 void readDimacsMin(std::istream& is,
128 CapacityMap& capacity,
131 typename CapacityMap::Value infty = 0,
132 DimacsDescriptor desc=DimacsDescriptor())
135 std::vector<typename Digraph::Node> nodes;
136 typename Digraph::Arc e;
137 std::string problem, str;
140 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
141 if(desc.type!=DimacsDescriptor::MIN)
142 throw FormatError("Problem type mismatch");
144 nodes.resize(desc.nodeNum + 1);
145 for (int k = 1; k <= desc.nodeNum; ++k) {
146 nodes[k] = g.addNode();
147 supply.set(nodes[k], 0);
150 typename SupplyMap::Value sup;
151 typename CapacityMap::Value low;
152 typename CapacityMap::Value cap;
153 typename CostMap::Value co;
154 typedef typename CapacityMap::Value Capacity;
156 infty = std::numeric_limits<Capacity>::has_infinity ?
157 std::numeric_limits<Capacity>::infinity() :
158 std::numeric_limits<Capacity>::max();
162 case 'c': // comment line
165 case 'n': // node definition line
168 supply.set(nodes[i], sup);
170 case 'a': // arc definition line
171 is >> i >> j >> low >> cap >> co;
173 e = g.addArc(nodes[i], nodes[j]);
176 capacity.set(e, cap);
178 capacity.set(e, infty);
185 template<typename Digraph, typename CapacityMap>
186 void _readDimacs(std::istream& is,
188 CapacityMap& capacity,
189 typename Digraph::Node &s,
190 typename Digraph::Node &t,
191 typename CapacityMap::Value infty = 0,
192 DimacsDescriptor desc=DimacsDescriptor()) {
195 std::vector<typename Digraph::Node> nodes;
196 typename Digraph::Arc e;
199 typename CapacityMap::Value _cap;
201 nodes.resize(desc.nodeNum + 1);
202 for (int k = 1; k <= desc.nodeNum; ++k) {
203 nodes[k] = g.addNode();
205 typedef typename CapacityMap::Value Capacity;
208 infty = std::numeric_limits<Capacity>::has_infinity ?
209 std::numeric_limits<Capacity>::infinity() :
210 std::numeric_limits<Capacity>::max();
214 case 'c': // comment line
217 case 'n': // node definition line
218 if (desc.type==DimacsDescriptor::SP) { // shortest path problem
223 if (desc.type==DimacsDescriptor::MAX) { // max flow problem
226 if (d == 's') s = nodes[i];
227 if (d == 't') t = nodes[i];
230 case 'a': // arc definition line
231 if (desc.type==DimacsDescriptor::SP) {
232 is >> i >> j >> _cap;
234 e = g.addArc(nodes[i], nodes[j]);
235 capacity.set(e, _cap);
237 else if (desc.type==DimacsDescriptor::MAX) {
238 is >> i >> j >> _cap;
240 e = g.addArc(nodes[i], nodes[j]);
242 capacity.set(e, _cap);
244 capacity.set(e, infty);
249 g.addArc(nodes[i], nodes[j]);
256 /// DIMACS maximum flow reader function.
258 /// This function reads a maximum flow instance from DIMACS format,
259 /// i.e. from a DIMACS file having a line starting with
263 /// At the beginning, \c g is cleared by \c g.clear(). The arc
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.
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".
274 /// If the file type was previously evaluated by dimacsType(), then
275 /// the descriptor struct should be given by the \c dest parameter.
276 template<typename Digraph, typename CapacityMap>
277 void readDimacsMax(std::istream& is,
279 CapacityMap& capacity,
280 typename Digraph::Node &s,
281 typename Digraph::Node &t,
282 typename CapacityMap::Value infty = 0,
283 DimacsDescriptor desc=DimacsDescriptor()) {
284 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
285 if(desc.type!=DimacsDescriptor::MAX)
286 throw FormatError("Problem type mismatch");
287 _readDimacs(is,g,capacity,s,t,infty,desc);
290 /// DIMACS shortest path reader function.
292 /// This function reads a shortest path instance from DIMACS format,
293 /// i.e. from a DIMACS file having a line starting with
297 /// At the beginning, \c g is cleared by \c g.clear(). The arc
298 /// lengths are written to the \c length arc map and \c s is set to the
301 /// If the file type was previously evaluated by dimacsType(), then
302 /// the descriptor struct should be given by the \c dest parameter.
303 template<typename Digraph, typename LengthMap>
304 void readDimacsSp(std::istream& is,
307 typename Digraph::Node &s,
308 DimacsDescriptor desc=DimacsDescriptor()) {
309 typename Digraph::Node t;
310 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
311 if(desc.type!=DimacsDescriptor::SP)
312 throw FormatError("Problem type mismatch");
313 _readDimacs(is, g, length, s, t, 0, desc);
316 /// DIMACS capacitated digraph reader function.
318 /// This function reads an arc capacitated digraph instance from
319 /// DIMACS 'max' or 'sp' format.
320 /// At the beginning, \c g is cleared by \c g.clear()
321 /// and the arc capacities/lengths are written to the \c capacity
324 /// In case of the 'max' format, if the capacity of an arc is negative,
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".
332 /// If the file type was previously evaluated by dimacsType(), then
333 /// the descriptor struct should be given by the \c dest parameter.
334 template<typename Digraph, typename CapacityMap>
335 void readDimacsCap(std::istream& is,
337 CapacityMap& capacity,
338 typename CapacityMap::Value infty = 0,
339 DimacsDescriptor desc=DimacsDescriptor()) {
340 typename Digraph::Node u,v;
341 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
342 if(desc.type!=DimacsDescriptor::MAX || desc.type!=DimacsDescriptor::SP)
343 throw FormatError("Problem type mismatch");
344 _readDimacs(is, g, capacity, u, v, infty, desc);
347 template<typename Graph>
348 typename enable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
349 _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
354 template<typename Graph>
355 typename disable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
356 _addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
362 /// DIMACS plain (di)graph reader function.
364 /// This function reads a (di)graph without any designated nodes and
365 /// maps from DIMACS format, i.e. from DIMACS files having a line
370 /// At the beginning, \c g is cleared by \c g.clear().
372 /// If the file type was previously evaluated by dimacsType(), then
373 /// the descriptor struct should be given by the \c dest parameter.
374 template<typename Graph>
375 void readDimacsMat(std::istream& is, Graph &g,
376 DimacsDescriptor desc=DimacsDescriptor())
378 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
379 if(desc.type!=DimacsDescriptor::MAT)
380 throw FormatError("Problem type mismatch");
383 std::vector<typename Graph::Node> nodes;
387 nodes.resize(desc.nodeNum + 1);
388 for (int k = 1; k <= desc.nodeNum; ++k) {
389 nodes[k] = g.addNode();
394 case 'c': // comment line
397 case 'n': // node definition line
399 case 'a': // arc definition line
402 _addArcEdge(g,nodes[i], nodes[j]);
408 /// DIMACS plain digraph writer function.
410 /// This function writes a digraph without any designated nodes and
411 /// maps into DIMACS format, i.e. into DIMACS file having a line
416 /// If \c comment is not empty, then it will be printed in the first line
418 template<typename Digraph>
419 void writeDimacsMat(std::ostream& os, const Digraph &g,
420 std::string comment="") {
421 typedef typename Digraph::NodeIt NodeIt;
422 typedef typename Digraph::ArcIt ArcIt;
425 os << "c " << comment << std::endl;
426 os << "p mat " << g.nodeNum() << " " << g.arcNum() << std::endl;
428 typename Digraph::template NodeMap<int> nodes(g);
430 for(NodeIt v(g); v != INVALID; ++v) {
434 for(ArcIt e(g); e != INVALID; ++e) {
435 os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)]
444 #endif //LEMON_DIMACS_H