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
25 #include <lemon/maps.h>
26 #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 begining 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 \c supply (signed). The
109 /// lower bounds, capacities and costs of the arcs are written to
110 /// \c lower, \c capacity and \c cost.
112 /// If the file type was previously evaluated by dimacsType(), then
113 /// the descriptor struct should be given by the \c dest parameter.
114 template <typename Digraph, typename LowerMap,
115 typename CapacityMap, typename CostMap,
117 void readDimacsMin(std::istream& is,
120 CapacityMap& capacity,
123 DimacsDescriptor desc=DimacsDescriptor())
126 std::vector<typename Digraph::Node> nodes;
127 typename Digraph::Arc e;
128 std::string problem, str;
131 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
132 if(desc.type!=DimacsDescriptor::MIN)
133 throw FormatError("Problem type mismatch");
135 nodes.resize(desc.nodeNum + 1);
136 for (int k = 1; k <= desc.nodeNum; ++k) {
137 nodes[k] = g.addNode();
138 supply.set(nodes[k], 0);
141 typename SupplyMap::Value sup;
142 typename CapacityMap::Value low;
143 typename CapacityMap::Value cap;
144 typename CostMap::Value co;
147 case 'c': // comment line
150 case 'n': // node definition line
153 supply.set(nodes[i], sup);
155 case 'a': // arc (arc) definition line
156 is >> i >> j >> low >> cap >> co;
158 e = g.addArc(nodes[i], nodes[j]);
161 capacity.set(e, cap);
170 template<typename Digraph, typename CapacityMap>
171 void _readDimacs(std::istream& is,
173 CapacityMap& capacity,
174 typename Digraph::Node &s,
175 typename Digraph::Node &t,
176 DimacsDescriptor desc=DimacsDescriptor()) {
179 std::vector<typename Digraph::Node> nodes;
180 typename Digraph::Arc e;
183 typename CapacityMap::Value _cap;
185 nodes.resize(desc.nodeNum + 1);
186 for (int k = 1; k <= desc.nodeNum; ++k) {
187 nodes[k] = g.addNode();
192 case 'c': // comment line
195 case 'n': // node definition line
196 if (desc.type==DimacsDescriptor::SP) { // shortest path problem
201 if (desc.type==DimacsDescriptor::MAX) { // max flow problem
204 if (d == 's') s = nodes[i];
205 if (d == 't') t = nodes[i];
208 case 'a': // arc (arc) definition line
209 if (desc.type==DimacsDescriptor::SP ||
210 desc.type==DimacsDescriptor::MAX) {
211 is >> i >> j >> _cap;
213 e = g.addArc(nodes[i], nodes[j]);
214 capacity.set(e, _cap);
218 g.addArc(nodes[i], nodes[j]);
225 /// DIMACS maximum flow reader function.
227 /// This function reads a maximum flow instance from DIMACS format,
228 /// i.e. from a DIMACS file having a line starting with
232 /// 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.
236 /// If the file type was previously evaluated by dimacsType(), then
237 /// the descriptor struct should be given by the \c dest parameter.
238 template<typename Digraph, typename CapacityMap>
239 void readDimacsMax(std::istream& is,
241 CapacityMap& capacity,
242 typename Digraph::Node &s,
243 typename Digraph::Node &t,
244 DimacsDescriptor desc=DimacsDescriptor()) {
245 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
246 if(desc.type!=DimacsDescriptor::MAX)
247 throw FormatError("Problem type mismatch");
248 _readDimacs(is,g,capacity,s,t,desc);
251 /// DIMACS shortest path reader function.
253 /// This function reads a shortest path instance from DIMACS format,
254 /// i.e. from a DIMACS file having a line starting with
258 /// 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
262 /// If the file type was previously evaluated by dimacsType(), then
263 /// the descriptor struct should be given by the \c dest parameter.
264 template<typename Digraph, typename LengthMap>
265 void readDimacsSp(std::istream& is,
268 typename Digraph::Node &s,
269 DimacsDescriptor desc=DimacsDescriptor()) {
270 typename Digraph::Node t;
271 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
272 if(desc.type!=DimacsDescriptor::SP)
273 throw FormatError("Problem type mismatch");
274 _readDimacs(is, g, length, s, t,desc);
277 /// DIMACS capacitated digraph reader function.
279 /// This function reads an arc capacitated digraph instance from
280 /// DIMACS 'mat' or 'sp' format.
281 /// At the beginning, \c g is cleared by \c g.clear()
282 /// and the arc capacities/lengths are written to \c capacity.
284 /// If the file type was previously evaluated by dimacsType(), then
285 /// the descriptor struct should be given by the \c dest parameter.
286 template<typename Digraph, typename CapacityMap>
287 void readDimacsCap(std::istream& is,
289 CapacityMap& capacity,
290 DimacsDescriptor desc=DimacsDescriptor()) {
291 typename Digraph::Node u,v;
292 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
293 if(desc.type!=DimacsDescriptor::MAX || desc.type!=DimacsDescriptor::SP)
294 throw FormatError("Problem type mismatch");
295 _readDimacs(is, g, capacity, u, v, desc);
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,
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,
313 /// DIMACS plain (di)graph reader function.
315 /// This function reads a (di)graph without any designated nodes and
316 /// maps from DIMACS format, i.e. from DIMACS files having a line
321 /// At the beginning, \c g is cleared by \c g.clear().
323 /// If the file type was previously evaluated by dimacsType(), then
324 /// the descriptor struct should be given by the \c dest parameter.
325 template<typename Graph>
326 void readDimacsMat(std::istream& is, Graph &g,
327 DimacsDescriptor desc=DimacsDescriptor())
329 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
330 if(desc.type!=DimacsDescriptor::MAT)
331 throw FormatError("Problem type mismatch");
334 std::vector<typename Graph::Node> nodes;
338 nodes.resize(desc.nodeNum + 1);
339 for (int k = 1; k <= desc.nodeNum; ++k) {
340 nodes[k] = g.addNode();
345 case 'c': // comment line
348 case 'n': // node definition line
350 case 'a': // arc (arc) definition line
353 _addArcEdge(g,nodes[i], nodes[j]);
359 /// DIMACS plain digraph writer function.
361 /// This function writes a digraph without any designated nodes and
362 /// maps into DIMACS format, i.e. into DIMACS file having a line
367 /// If \c comment is not empty, then it will be printed in the first line
369 template<typename Digraph>
370 void writeDimacsMat(std::ostream& os, const Digraph &g,
371 std::string comment="") {
372 typedef typename Digraph::NodeIt NodeIt;
373 typedef typename Digraph::ArcIt ArcIt;
376 os << "c " << comment << std::endl;
377 os << "p mat " << g.nodeNum() << " " << g.arcNum() << std::endl;
379 typename Digraph::template NodeMap<int> nodes(g);
381 for(NodeIt v(g); v != INVALID; ++v) {
385 for(ArcIt e(g); e != INVALID; ++e) {
386 os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)]
395 #endif //LEMON_DIMACS_H