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.
36 #include <lemon/smart_graph.h>
37 #include <lemon/dimacs.h>
38 #include <lemon/lgf_writer.h>
39 #include <lemon/time_measure.h>
41 #include <lemon/arg_parser.h>
42 #include <lemon/error.h>
44 #include <lemon/dijkstra.h>
45 #include <lemon/preflow.h>
46 #include <lemon/max_matching.h>
47 #include <lemon/network_simplex.h>
49 using namespace lemon;
50 typedef SmartDigraph Digraph;
51 DIGRAPH_TYPEDEFS(Digraph);
52 typedef SmartGraph Graph;
55 void solve_sp(ArgParser &ap, std::istream &is, std::ostream &,
56 DimacsDescriptor &desc)
58 bool report = !ap.given("q");
61 Digraph::ArcMap<Value> len(g);
64 readDimacsSp(is, g, len, s, desc);
65 if(report) std::cerr << "Read the file: " << t << '\n';
67 Dijkstra<Digraph, Digraph::ArcMap<Value> > dij(g,len);
68 if(report) std::cerr << "Setup Dijkstra class: " << t << '\n';
71 if(report) std::cerr << "Run Dijkstra: " << t << '\n';
75 void solve_max(ArgParser &ap, std::istream &is, std::ostream &,
76 DimacsDescriptor &desc)
78 bool report = !ap.given("q");
81 Digraph::ArcMap<Value> cap(g);
84 readDimacsMax(is, g, cap, s, t, desc);
85 if(report) std::cerr << "Read the file: " << ti << '\n';
87 Preflow<Digraph, Digraph::ArcMap<Value> > pre(g,cap,s,t);
88 if(report) std::cerr << "Setup Preflow class: " << ti << '\n';
91 if(report) std::cerr << "Run Preflow: " << ti << '\n';
92 if(report) std::cerr << "\nMax flow value: " << pre.flowValue() << '\n';
96 void solve_min(ArgParser &ap, std::istream &is, std::ostream &,
97 DimacsDescriptor &desc)
99 bool report = !ap.given("q");
101 Digraph::ArcMap<Value> lower(g), cap(g), cost(g);
102 Digraph::NodeMap<Value> sup(g);
105 readDimacsMin(is, g, lower, cap, cost, sup, desc);
106 if (report) std::cerr << "Read the file: " << ti << '\n';
108 NetworkSimplex< Digraph, Digraph::ArcMap<Value>, Digraph::ArcMap<Value>,
109 Digraph::ArcMap<Value>, Digraph::NodeMap<Value> >
110 ns(g, lower, cap, cost, sup);
111 if (report) std::cerr << "Setup NetworkSimplex class: " << ti << '\n';
114 if (report) std::cerr << "Run NetworkSimplex: " << ti << '\n';
115 if (report) std::cerr << "\nMin flow cost: " << ns.totalCost() << '\n';
118 void solve_mat(ArgParser &ap, std::istream &is, std::ostream &,
119 DimacsDescriptor &desc)
121 bool report = !ap.given("q");
125 readDimacsMat(is, g, desc);
126 if(report) std::cerr << "Read the file: " << ti << '\n';
128 MaxMatching<Graph> mat(g);
129 if(report) std::cerr << "Setup MaxMatching class: " << ti << '\n';
132 if(report) std::cerr << "Run MaxMatching: " << ti << '\n';
133 if(report) std::cerr << "\nCardinality of max matching: "
134 << mat.matchingSize() << '\n';
138 template<class Value>
139 void solve(ArgParser &ap, std::istream &is, std::ostream &os,
140 DimacsDescriptor &desc)
144 case DimacsDescriptor::MIN:
145 solve_min<Value>(ap,is,os,desc);
147 case DimacsDescriptor::MAX:
148 solve_max<Value>(ap,is,os,desc);
150 case DimacsDescriptor::SP:
151 solve_sp<Value>(ap,is,os,desc);
153 case DimacsDescriptor::MAT:
154 solve_mat(ap,is,os,desc);
161 int main(int argc, const char *argv[]) {
162 typedef SmartDigraph Digraph;
164 typedef Digraph::Arc Arc;
166 std::string inputName;
167 std::string outputName;
169 ArgParser ap(argc, argv);
170 ap.other("[INFILE [OUTFILE]]",
171 "If either the INFILE or OUTFILE file is missing the standard\n"
172 " input/output will be used instead.")
173 .boolOption("q", "Do not print any report")
174 .boolOption("int","Use 'int' for capacities, costs etc. (default)")
175 .optionGroup("datatype","int")
176 #ifdef HAVE_LONG_LONG
177 .boolOption("long","Use 'long long' for capacities, costs etc.")
178 .optionGroup("datatype","long")
180 .boolOption("double","Use 'double' for capacities, costs etc.")
181 .optionGroup("datatype","double")
182 .boolOption("ldouble","Use 'long double' for capacities, costs etc.")
183 .optionGroup("datatype","ldouble")
184 .onlyOneGroup("datatype")
188 std::ofstream output;
190 switch(ap.files().size())
193 output.open(ap.files()[1].c_str());
195 throw IoError("Cannot open the file for writing", ap.files()[1]);
198 input.open(ap.files()[0].c_str());
200 throw IoError("File cannot be found", ap.files()[0]);
205 std::cerr << ap.commandName() << ": too many arguments\n";
208 std::istream& is = (ap.files().size()<1 ? std::cin : input);
209 std::ostream& os = (ap.files().size()<2 ? std::cout : output);
211 DimacsDescriptor desc = dimacsType(is);
215 std::cout << "Problem type: ";
218 case DimacsDescriptor::MIN:
221 case DimacsDescriptor::MAX:
224 case DimacsDescriptor::SP:
226 case DimacsDescriptor::MAT:
233 std::cout << "\nNum of nodes: " << desc.nodeNum;
234 std::cout << "\nNum of arcs: " << desc.edgeNum;
238 if(ap.given("double"))
239 solve<double>(ap,is,os,desc);
240 else if(ap.given("ldouble"))
241 solve<long double>(ap,is,os,desc);
242 #ifdef HAVE_LONG_LONG
243 else if(ap.given("long"))
244 solve<long long>(ap,is,os,desc);
246 else solve<int>(ap,is,os,desc);