/* -*- mode: C++; indent-tabs-mode: nil; -*-
* This file is a part of LEMON, a generic C++ optimization library.
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
/// \ingroup dimacs_group
/// \brief DIMACS file format reader.
/// \addtogroup dimacs_group
/// DIMACS file type descriptor.
///The number of nodes in the graph
///The number of edges in the graph
/// Constructor. Sets the type to NONE.
DimacsDescriptor() : type(NONE) {}
///Discover the type of a DIMACS file
///It starts seeking the begining of the file for the problem type
///and size info. The found data is returned in a special struct
///that can be evaluated and passed to the appropriate reader
DimacsDescriptor dimacsType(std::istream& is)
if(is >> problem >> r.nodeNum >> r.edgeNum)
if(problem=="min") r.type=DimacsDescriptor::MIN;
else if(problem=="max") r.type=DimacsDescriptor::MAX;
else if(problem=="sp") r.type=DimacsDescriptor::SP;
else if(problem=="mat") r.type=DimacsDescriptor::MAT;
else throw FormatError("Unknown problem type");
throw FormatError("Missing or wrong problem type declaration.");
throw FormatError("Unknown DIMACS declaration.");
throw FormatError("Missing problem type declaration.");
/// DIMACS minimum cost flow reader function.
/// This function reads a minimum cost flow instance from DIMACS format,
/// i.e. from a DIMACS file having a line starting with
/// At the beginning, \c g is cleared by \c g.clear(). The supply
/// amount of the nodes are written to \c supply (signed). The
/// lower bounds, capacities and costs of the arcs are written to
/// \c lower, \c capacity and \c cost.
/// If the file type was previously evaluated by dimacsType(), then
/// the descriptor struct should be given by the \c dest parameter.
template <typename Digraph, typename LowerMap,
typename CapacityMap, typename CostMap,
void readDimacsMin(std::istream& is,
DimacsDescriptor desc=DimacsDescriptor())
std::vector<typename Digraph::Node> nodes;
std::string problem, str;
if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
if(desc.type!=DimacsDescriptor::MIN)
throw FormatError("Problem type mismatch");
nodes.resize(desc.nodeNum + 1);
for (int k = 1; k <= desc.nodeNum; ++k) {
typename SupplyMap::Value sup;
typename CapacityMap::Value low;
typename CapacityMap::Value cap;
typename CostMap::Value co;
case 'c':
// comment line
case 'n':
// node definition line
supply.set(nodes[i], sup);
case 'a':
// arc (arc) definition line
is >> i >> j >> low >> cap >> co;
e = g.addArc(nodes[i], nodes[j]);
template<typename Digraph, typename CapacityMap>
void _readDimacs(std::istream& is,
typename Digraph::Node &s,
typename Digraph::Node &t,
DimacsDescriptor desc=DimacsDescriptor()) {
std::vector<typename Digraph::Node> nodes;
typename CapacityMap::Value _cap;
nodes.resize(desc.nodeNum + 1);
for (int k = 1; k <= desc.nodeNum; ++k) {
case 'c':
// comment line
case 'n':
// node definition line
if (desc.type==DimacsDescriptor::SP) { // shortest path problem
if (desc.type==DimacsDescriptor::MAX) { // max flow problem
if (d == 's') s = nodes[i];
if (d == 't') t = nodes[i];
case 'a':
// arc (arc) definition line
if (desc.type==DimacsDescriptor::SP ||
desc.type==DimacsDescriptor::MAX) {
e = g.addArc(nodes[i], nodes[j]);
g.addArc(nodes[i], nodes[j]);
/// DIMACS maximum flow reader function.
/// This function reads a maximum flow instance from DIMACS format,
/// i.e. from a DIMACS file having a line starting with
/// At the beginning, \c g is cleared by \c g.clear(). The arc
/// capacities are written to \c capacity and \c s and \c t are
/// set to the source and the target nodes.
/// If the file type was previously evaluated by dimacsType(), then
/// the descriptor struct should be given by the \c dest parameter.
template<typename Digraph, typename CapacityMap>
void readDimacsMax(std::istream& is,
typename Digraph::Node &s,
typename Digraph::Node &t,
DimacsDescriptor desc=DimacsDescriptor()) {
if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
if(desc.type!=DimacsDescriptor::MAX)
throw FormatError("Problem type mismatch");
_readDimacs(is,g,capacity,s,t,desc);
/// DIMACS shortest path reader function.
/// This function reads a shortest path instance from DIMACS format,
/// i.e. from a DIMACS file having a line starting with
/// At the beginning, \c g is cleared by \c g.clear(). The arc
/// lengths are written to \c length and \c s is set to the
/// If the file type was previously evaluated by dimacsType(), then
/// the descriptor struct should be given by the \c dest parameter.
template<typename Digraph, typename LengthMap>
void readDimacsSp(std::istream& is,
typename Digraph::Node &s,
DimacsDescriptor desc=DimacsDescriptor()) {
typename Digraph::Node t;
if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
if(desc.type!=DimacsDescriptor::SP)
throw FormatError("Problem type mismatch");
_readDimacs(is, g, length, s, t,desc);
/// DIMACS capacitated digraph reader function.
/// This function reads an arc capacitated digraph instance from
/// DIMACS 'mat' or 'sp' format.
/// At the beginning, \c g is cleared by \c g.clear()
/// and the arc capacities/lengths are written to \c capacity.
/// If the file type was previously evaluated by dimacsType(), then
/// the descriptor struct should be given by the \c dest parameter.
template<typename Digraph, typename CapacityMap>
void readDimacsCap(std::istream& is,
DimacsDescriptor desc=DimacsDescriptor()) {
typename Digraph::Node u,v;
if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
if(desc.type!=DimacsDescriptor::MAX || desc.type!=DimacsDescriptor::SP)
throw FormatError("Problem type mismatch");
_readDimacs(is, g, capacity, u, v, desc);
/// DIMACS plain digraph reader function.
/// This function reads a digraph without any designated nodes and
/// maps from DIMACS format, i.e. from DIMACS files having a line
/// At the beginning, \c g is cleared by \c g.clear().
/// If the file type was previously evaluated by dimacsType(), then
/// the descriptor struct should be given by the \c dest parameter.
template<typename Digraph>
void readDimacsMat(std::istream& is, Digraph &g,
DimacsDescriptor desc=DimacsDescriptor()) {
typename Digraph::Node u,v;
NullMap<typename Digraph::Arc, int> n;
if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
if(desc.type!=DimacsDescriptor::MAT)
throw FormatError("Problem type mismatch");
_readDimacs(is, g, n, u, v, desc);
/// DIMACS plain digraph writer function.
/// This function writes a digraph without any designated nodes and
/// maps into DIMACS format, i.e. into DIMACS file having a line
/// If \c comment is not empty, then it will be printed in the first line
template<typename Digraph>
void writeDimacsMat(std::ostream& os, const Digraph &g,
std::string comment="") {
typedef typename Digraph::NodeIt NodeIt;
typedef typename Digraph::ArcIt ArcIt;
os << "c " << comment << std::endl;
os << "p mat " << g.nodeNum() << " " << g.arcNum() << std::endl;
typename Digraph::template NodeMap<int> nodes(g);
for(NodeIt v(g); v != INVALID; ++v) {
for(ArcIt e(g); e != INVALID; ++e) {
os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)]