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, Value> ns(g);
109 ns.lowerMap(lower).capacityMap(cap).costMap(cost).supplyMap(sup);
110 if (report) std::cerr << "Setup NetworkSimplex class: " << ti << '\n';
113 if (report) std::cerr << "Run NetworkSimplex: " << ti << '\n';
114 if (report) std::cerr << "\nMin flow cost: " << ns.totalCost() << '\n';
117 void solve_mat(ArgParser &ap, std::istream &is, std::ostream &,
118 DimacsDescriptor &desc)
120 bool report = !ap.given("q");
124 readDimacsMat(is, g, desc);
125 if(report) std::cerr << "Read the file: " << ti << '\n';
127 MaxMatching<Graph> mat(g);
128 if(report) std::cerr << "Setup MaxMatching class: " << ti << '\n';
131 if(report) std::cerr << "Run MaxMatching: " << ti << '\n';
132 if(report) std::cerr << "\nCardinality of max matching: "
133 << mat.matchingSize() << '\n';
137 template<class Value>
138 void solve(ArgParser &ap, std::istream &is, std::ostream &os,
139 DimacsDescriptor &desc)
143 case DimacsDescriptor::MIN:
144 solve_min<Value>(ap,is,os,desc);
146 case DimacsDescriptor::MAX:
147 solve_max<Value>(ap,is,os,desc);
149 case DimacsDescriptor::SP:
150 solve_sp<Value>(ap,is,os,desc);
152 case DimacsDescriptor::MAT:
153 solve_mat(ap,is,os,desc);
160 int main(int argc, const char *argv[]) {
161 typedef SmartDigraph Digraph;
163 typedef Digraph::Arc Arc;
165 std::string inputName;
166 std::string outputName;
168 ArgParser ap(argc, argv);
169 ap.other("[INFILE [OUTFILE]]",
170 "If either the INFILE or OUTFILE file is missing the standard\n"
171 " input/output will be used instead.")
172 .boolOption("q", "Do not print any report")
173 .boolOption("int","Use 'int' for capacities, costs etc. (default)")
174 .optionGroup("datatype","int")
175 #ifdef HAVE_LONG_LONG
176 .boolOption("long","Use 'long long' for capacities, costs etc.")
177 .optionGroup("datatype","long")
179 .boolOption("double","Use 'double' for capacities, costs etc.")
180 .optionGroup("datatype","double")
181 .boolOption("ldouble","Use 'long double' for capacities, costs etc.")
182 .optionGroup("datatype","ldouble")
183 .onlyOneGroup("datatype")
187 std::ofstream output;
189 switch(ap.files().size())
192 output.open(ap.files()[1].c_str());
194 throw IoError("Cannot open the file for writing", ap.files()[1]);
197 input.open(ap.files()[0].c_str());
199 throw IoError("File cannot be found", ap.files()[0]);
204 std::cerr << ap.commandName() << ": too many arguments\n";
207 std::istream& is = (ap.files().size()<1 ? std::cin : input);
208 std::ostream& os = (ap.files().size()<2 ? std::cout : output);
210 DimacsDescriptor desc = dimacsType(is);
214 std::cout << "Problem type: ";
217 case DimacsDescriptor::MIN:
220 case DimacsDescriptor::MAX:
223 case DimacsDescriptor::SP:
225 case DimacsDescriptor::MAT:
232 std::cout << "\nNum of nodes: " << desc.nodeNum;
233 std::cout << "\nNum of arcs: " << desc.edgeNum;
237 if(ap.given("double"))
238 solve<double>(ap,is,os,desc);
239 else if(ap.given("ldouble"))
240 solve<long double>(ap,is,os,desc);
241 #ifdef HAVE_LONG_LONG
242 else if(ap.given("long"))
243 solve<long long>(ap,is,os,desc);
245 else solve<int>(ap,is,os,desc);