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
21 ///\brief DIMACS problem solver.
23 /// This program solves various problems given in DIMACS format.
27 /// dimacs-solver --help
29 /// for more info on usage.
35 #include <lemon/smart_graph.h>
36 #include <lemon/dimacs.h>
37 #include <lemon/lgf_writer.h>
38 #include <lemon/time_measure.h>
40 #include <lemon/arg_parser.h>
41 #include <lemon/error.h>
43 #include <lemon/dijkstra.h>
44 #include <lemon/preflow.h>
45 #include <lemon/matching.h>
46 #include <lemon/network_simplex.h>
48 using namespace lemon;
49 typedef SmartDigraph Digraph;
50 DIGRAPH_TYPEDEFS(Digraph);
51 typedef SmartGraph Graph;
54 void solve_sp(ArgParser &ap, std::istream &is, std::ostream &,
55 DimacsDescriptor &desc)
57 bool report = !ap.given("q");
60 Digraph::ArcMap<Value> len(g);
63 readDimacsSp(is, g, len, s, desc);
64 if(report) std::cerr << "Read the file: " << t << '\n';
66 Dijkstra<Digraph, Digraph::ArcMap<Value> > dij(g,len);
67 if(report) std::cerr << "Setup Dijkstra class: " << t << '\n';
70 if(report) std::cerr << "Run Dijkstra: " << t << '\n';
74 void solve_max(ArgParser &ap, std::istream &is, std::ostream &,
75 Value infty, DimacsDescriptor &desc)
77 bool report = !ap.given("q");
80 Digraph::ArcMap<Value> cap(g);
83 readDimacsMax(is, g, cap, s, t, infty, desc);
84 if(report) std::cerr << "Read the file: " << ti << '\n';
86 Preflow<Digraph, Digraph::ArcMap<Value> > pre(g,cap,s,t);
87 if(report) std::cerr << "Setup Preflow class: " << ti << '\n';
90 if(report) std::cerr << "Run Preflow: " << ti << '\n';
91 if(report) std::cerr << "\nMax flow value: " << pre.flowValue() << '\n';
95 void solve_min(ArgParser &ap, std::istream &is, std::ostream &,
96 DimacsDescriptor &desc)
98 bool report = !ap.given("q");
100 Digraph::ArcMap<Value> lower(g), cap(g), cost(g);
101 Digraph::NodeMap<Value> sup(g);
104 readDimacsMin(is, g, lower, cap, cost, sup, 0, desc);
105 if (report) std::cerr << "Read the file: " << ti << '\n';
107 NetworkSimplex<Digraph, Value> ns(g);
108 ns.lowerMap(lower).capacityMap(cap).costMap(cost).supplyMap(sup);
109 if (report) std::cerr << "Setup NetworkSimplex class: " << ti << '\n';
112 if (report) std::cerr << "Run NetworkSimplex: " << ti << '\n';
113 if (report) std::cerr << "\nMin flow cost: " << ns.totalCost() << '\n';
116 void solve_mat(ArgParser &ap, std::istream &is, std::ostream &,
117 DimacsDescriptor &desc)
119 bool report = !ap.given("q");
123 readDimacsMat(is, g, desc);
124 if(report) std::cerr << "Read the file: " << ti << '\n';
126 MaxMatching<Graph> mat(g);
127 if(report) std::cerr << "Setup MaxMatching class: " << ti << '\n';
130 if(report) std::cerr << "Run MaxMatching: " << ti << '\n';
131 if(report) std::cerr << "\nCardinality of max matching: "
132 << mat.matchingSize() << '\n';
136 template<class Value>
137 void solve(ArgParser &ap, std::istream &is, std::ostream &os,
138 DimacsDescriptor &desc)
140 std::stringstream iss(static_cast<std::string>(ap["infcap"]));
145 std::cerr << "Cannot interpret '"
146 << static_cast<std::string>(ap["infcap"]) << "' as infinite"
153 case DimacsDescriptor::MIN:
154 solve_min<Value>(ap,is,os,desc);
156 case DimacsDescriptor::MAX:
157 solve_max<Value>(ap,is,os,infty,desc);
159 case DimacsDescriptor::SP:
160 solve_sp<Value>(ap,is,os,desc);
162 case DimacsDescriptor::MAT:
163 solve_mat(ap,is,os,desc);
170 int main(int argc, const char *argv[]) {
171 typedef SmartDigraph Digraph;
173 typedef Digraph::Arc Arc;
175 std::string inputName;
176 std::string outputName;
178 ArgParser ap(argc, argv);
179 ap.other("[INFILE [OUTFILE]]",
180 "If either the INFILE or OUTFILE file is missing the standard\n"
181 " input/output will be used instead.")
182 .boolOption("q", "Do not print any report")
183 .boolOption("int","Use 'int' for capacities, costs etc. (default)")
184 .optionGroup("datatype","int")
185 #ifdef HAVE_LONG_LONG
186 .boolOption("long","Use 'long long' for capacities, costs etc.")
187 .optionGroup("datatype","long")
189 .boolOption("double","Use 'double' for capacities, costs etc.")
190 .optionGroup("datatype","double")
191 .boolOption("ldouble","Use 'long double' for capacities, costs etc.")
192 .optionGroup("datatype","ldouble")
193 .onlyOneGroup("datatype")
194 .stringOption("infcap","Value used for 'very high' capacities","0")
198 std::ofstream output;
200 switch(ap.files().size())
203 output.open(ap.files()[1].c_str());
205 throw IoError("Cannot open the file for writing", ap.files()[1]);
208 input.open(ap.files()[0].c_str());
210 throw IoError("File cannot be found", ap.files()[0]);
215 std::cerr << ap.commandName() << ": too many arguments\n";
218 std::istream& is = (ap.files().size()<1 ? std::cin : input);
219 std::ostream& os = (ap.files().size()<2 ? std::cout : output);
221 DimacsDescriptor desc = dimacsType(is);
225 std::cout << "Problem type: ";
228 case DimacsDescriptor::MIN:
231 case DimacsDescriptor::MAX:
234 case DimacsDescriptor::SP:
236 case DimacsDescriptor::MAT:
243 std::cout << "\nNum of nodes: " << desc.nodeNum;
244 std::cout << "\nNum of arcs: " << desc.edgeNum;
248 if(ap.given("double"))
249 solve<double>(ap,is,os,desc);
250 else if(ap.given("ldouble"))
251 solve<long double>(ap,is,os,desc);
252 #ifdef HAVE_LONG_LONG
253 else if(ap.given("long"))
254 solve<long long>(ap,is,os,desc);
256 else solve<int>(ap,is,os,desc);