gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge
0 3 0
merge default
1 file changed with 32 insertions and 18 deletions:
↑ Collapse diff ↑
Show white space 128 line context
... ...
@@ -1086,186 +1086,187 @@
1086 1086

	
1087 1087
      _cap.resize(all_arc_num);
1088 1088
      _cost.resize(all_arc_num);
1089 1089
      _supply.resize(all_node_num);
1090 1090
      _flow.resize(all_arc_num);
1091 1091
      _pi.resize(all_node_num);
1092 1092

	
1093 1093
      _parent.resize(all_node_num);
1094 1094
      _pred.resize(all_node_num);
1095 1095
      _forward.resize(all_node_num);
1096 1096
      _thread.resize(all_node_num);
1097 1097
      _rev_thread.resize(all_node_num);
1098 1098
      _succ_num.resize(all_node_num);
1099 1099
      _last_succ.resize(all_node_num);
1100 1100
      _state.resize(all_arc_num);
1101 1101

	
1102 1102
      // Initialize node related data
1103 1103
      bool valid_supply = true;
1104 1104
      Flow sum_supply = 0;
1105 1105
      if (!_pstsup && !_psupply) {
1106 1106
        _pstsup = true;
1107 1107
        _psource = _ptarget = NodeIt(_graph);
1108 1108
        _pstflow = 0;
1109 1109
      }
1110 1110
      if (_psupply) {
1111 1111
        int i = 0;
1112 1112
        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
1113 1113
          _node_id[n] = i;
1114 1114
          _supply[i] = (*_psupply)[n];
1115 1115
          sum_supply += _supply[i];
1116 1116
        }
1117 1117
        valid_supply = (_ptype == GEQ && sum_supply <= 0) ||
1118 1118
                       (_ptype == LEQ && sum_supply >= 0);
1119 1119
      } else {
1120 1120
        int i = 0;
1121 1121
        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
1122 1122
          _node_id[n] = i;
1123 1123
          _supply[i] = 0;
1124 1124
        }
1125 1125
        _supply[_node_id[_psource]] =  _pstflow;
1126 1126
        _supply[_node_id[_ptarget]] = -_pstflow;
1127 1127
      }
1128 1128
      if (!valid_supply) return false;
1129 1129

	
1130 1130
      // Infinite capacity value
1131 1131
      Flow inf_cap =
1132 1132
        std::numeric_limits<Flow>::has_infinity ?
1133 1133
        std::numeric_limits<Flow>::infinity() :
1134 1134
        std::numeric_limits<Flow>::max();
1135 1135

	
1136 1136
      // Initialize artifical cost
1137 1137
      Cost art_cost;
1138 1138
      if (std::numeric_limits<Cost>::is_exact) {
1139 1139
        art_cost = std::numeric_limits<Cost>::max() / 4 + 1;
1140 1140
      } else {
1141 1141
        art_cost = std::numeric_limits<Cost>::min();
1142 1142
        for (int i = 0; i != _arc_num; ++i) {
1143 1143
          if (_cost[i] > art_cost) art_cost = _cost[i];
1144 1144
        }
1145 1145
        art_cost = (art_cost + 1) * _node_num;
1146 1146
      }
1147 1147

	
1148 1148
      // Run Circulation to check if a feasible solution exists
1149 1149
      typedef ConstMap<Arc, Flow> ConstArcMap;
1150
      ConstArcMap zero_arc_map(0), inf_arc_map(inf_cap);
1150 1151
      FlowNodeMap *csup = NULL;
1151 1152
      bool local_csup = false;
1152 1153
      if (_psupply) {
1153 1154
        csup = _psupply;
1154 1155
      } else {
1155 1156
        csup = new FlowNodeMap(_graph, 0);
1156 1157
        (*csup)[_psource] =  _pstflow;
1157 1158
        (*csup)[_ptarget] = -_pstflow;
1158 1159
        local_csup = true;
1159 1160
      }
1160 1161
      bool circ_result = false;
1161 1162
      if (_ptype == GEQ || (_ptype == LEQ && sum_supply == 0)) {
1162 1163
        // GEQ problem type
1163 1164
        if (_plower) {
1164 1165
          if (_pupper) {
1165 1166
            Circulation<GR, FlowArcMap, FlowArcMap, FlowNodeMap>
1166 1167
              circ(_graph, *_plower, *_pupper, *csup);
1167 1168
            circ_result = circ.run();
1168 1169
          } else {
1169 1170
            Circulation<GR, FlowArcMap, ConstArcMap, FlowNodeMap>
1170
              circ(_graph, *_plower, ConstArcMap(inf_cap), *csup);
1171
              circ(_graph, *_plower, inf_arc_map, *csup);
1171 1172
            circ_result = circ.run();
1172 1173
          }
1173 1174
        } else {
1174 1175
          if (_pupper) {
1175 1176
            Circulation<GR, ConstArcMap, FlowArcMap, FlowNodeMap>
1176
              circ(_graph, ConstArcMap(0), *_pupper, *csup);
1177
              circ(_graph, zero_arc_map, *_pupper, *csup);
1177 1178
            circ_result = circ.run();
1178 1179
          } else {
1179 1180
            Circulation<GR, ConstArcMap, ConstArcMap, FlowNodeMap>
1180
              circ(_graph, ConstArcMap(0), ConstArcMap(inf_cap), *csup);
1181
              circ(_graph, zero_arc_map, inf_arc_map, *csup);
1181 1182
            circ_result = circ.run();
1182 1183
          }
1183 1184
        }
1184 1185
      } else {
1185 1186
        // LEQ problem type
1186 1187
        typedef ReverseDigraph<const GR> RevGraph;
1187 1188
        typedef NegMap<FlowNodeMap> NegNodeMap;
1188 1189
        RevGraph rgraph(_graph);
1189 1190
        NegNodeMap neg_csup(*csup);
1190 1191
        if (_plower) {
1191 1192
          if (_pupper) {
1192 1193
            Circulation<RevGraph, FlowArcMap, FlowArcMap, NegNodeMap>
1193 1194
              circ(rgraph, *_plower, *_pupper, neg_csup);
1194 1195
            circ_result = circ.run();
1195 1196
          } else {
1196 1197
            Circulation<RevGraph, FlowArcMap, ConstArcMap, NegNodeMap>
1197
              circ(rgraph, *_plower, ConstArcMap(inf_cap), neg_csup);
1198
              circ(rgraph, *_plower, inf_arc_map, neg_csup);
1198 1199
            circ_result = circ.run();
1199 1200
          }
1200 1201
        } else {
1201 1202
          if (_pupper) {
1202 1203
            Circulation<RevGraph, ConstArcMap, FlowArcMap, NegNodeMap>
1203
              circ(rgraph, ConstArcMap(0), *_pupper, neg_csup);
1204
              circ(rgraph, zero_arc_map, *_pupper, neg_csup);
1204 1205
            circ_result = circ.run();
1205 1206
          } else {
1206 1207
            Circulation<RevGraph, ConstArcMap, ConstArcMap, NegNodeMap>
1207
              circ(rgraph, ConstArcMap(0), ConstArcMap(inf_cap), neg_csup);
1208
              circ(rgraph, zero_arc_map, inf_arc_map, neg_csup);
1208 1209
            circ_result = circ.run();
1209 1210
          }
1210 1211
        }
1211 1212
      }
1212 1213
      if (local_csup) delete csup;
1213 1214
      if (!circ_result) return false;
1214 1215

	
1215 1216
      // Set data for the artificial root node
1216 1217
      _root = _node_num;
1217 1218
      _parent[_root] = -1;
1218 1219
      _pred[_root] = -1;
1219 1220
      _thread[_root] = 0;
1220 1221
      _rev_thread[0] = _root;
1221 1222
      _succ_num[_root] = all_node_num;
1222 1223
      _last_succ[_root] = _root - 1;
1223 1224
      _supply[_root] = -sum_supply;
1224 1225
      if (sum_supply < 0) {
1225 1226
        _pi[_root] = -art_cost;
1226 1227
      } else {
1227 1228
        _pi[_root] = art_cost;
1228 1229
      }
1229 1230

	
1230 1231
      // Store the arcs in a mixed order
1231 1232
      int k = std::max(int(std::sqrt(double(_arc_num))), 10);
1232 1233
      int i = 0;
1233 1234
      for (ArcIt e(_graph); e != INVALID; ++e) {
1234 1235
        _arc_ref[i] = e;
1235 1236
        if ((i += k) >= _arc_num) i = (i % k) + 1;
1236 1237
      }
1237 1238

	
1238 1239
      // Initialize arc maps
1239 1240
      if (_pupper && _pcost) {
1240 1241
        for (int i = 0; i != _arc_num; ++i) {
1241 1242
          Arc e = _arc_ref[i];
1242 1243
          _source[i] = _node_id[_graph.source(e)];
1243 1244
          _target[i] = _node_id[_graph.target(e)];
1244 1245
          _cap[i] = (*_pupper)[e];
1245 1246
          _cost[i] = (*_pcost)[e];
1246 1247
          _flow[i] = 0;
1247 1248
          _state[i] = STATE_LOWER;
1248 1249
        }
1249 1250
      } else {
1250 1251
        for (int i = 0; i != _arc_num; ++i) {
1251 1252
          Arc e = _arc_ref[i];
1252 1253
          _source[i] = _node_id[_graph.source(e)];
1253 1254
          _target[i] = _node_id[_graph.target(e)];
1254 1255
          _flow[i] = 0;
1255 1256
          _state[i] = STATE_LOWER;
1256 1257
        }
1257 1258
        if (_pupper) {
1258 1259
          for (int i = 0; i != _arc_num; ++i)
1259 1260
            _cap[i] = (*_pupper)[_arc_ref[i]];
1260 1261
        } else {
1261 1262
          for (int i = 0; i != _arc_num; ++i)
1262 1263
            _cap[i] = inf_cap;
1263 1264
        }
1264 1265
        if (_pcost) {
1265 1266
          for (int i = 0; i != _arc_num; ++i)
1266 1267
            _cost[i] = (*_pcost)[_arc_ref[i]];
1267 1268
        } else {
1268 1269
          for (int i = 0; i != _arc_num; ++i)
1269 1270
            _cost[i] = 1;
1270 1271
        }
1271 1272
      }
Show white space 128 line context
... ...
@@ -172,134 +172,129 @@
172 172
  }
173 173

	
174 174
  return true;
175 175
}
176 176

	
177 177
// Check the feasibility of the given potentials (dual soluiton)
178 178
// using the "Complementary Slackness" optimality condition
179 179
template < typename GR, typename LM, typename UM,
180 180
           typename CM, typename SM, typename FM, typename PM >
181 181
bool checkPotential( const GR& gr, const LM& lower, const UM& upper,
182 182
                     const CM& cost, const SM& supply, const FM& flow, 
183 183
                     const PM& pi )
184 184
{
185 185
  TEMPLATE_DIGRAPH_TYPEDEFS(GR);
186 186

	
187 187
  bool opt = true;
188 188
  for (ArcIt e(gr); opt && e != INVALID; ++e) {
189 189
    typename CM::Value red_cost =
190 190
      cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
191 191
    opt = red_cost == 0 ||
192 192
          (red_cost > 0 && flow[e] == lower[e]) ||
193 193
          (red_cost < 0 && flow[e] == upper[e]);
194 194
  }
195 195
  
196 196
  for (NodeIt n(gr); opt && n != INVALID; ++n) {
197 197
    typename SM::Value sum = 0;
198 198
    for (OutArcIt e(gr, n); e != INVALID; ++e)
199 199
      sum += flow[e];
200 200
    for (InArcIt e(gr, n); e != INVALID; ++e)
201 201
      sum -= flow[e];
202 202
    opt = (sum == supply[n]) || (pi[n] == 0);
203 203
  }
204 204
  
205 205
  return opt;
206 206
}
207 207

	
208 208
// Run a minimum cost flow algorithm and check the results
209 209
template < typename MCF, typename GR,
210 210
           typename LM, typename UM,
211 211
           typename CM, typename SM >
212 212
void checkMcf( const MCF& mcf, bool mcf_result,
213 213
               const GR& gr, const LM& lower, const UM& upper,
214 214
               const CM& cost, const SM& supply,
215 215
               bool result, typename CM::Value total,
216 216
               const std::string &test_id = "",
217 217
               ProblemType type = EQ )
218 218
{
219 219
  check(mcf_result == result, "Wrong result " + test_id);
220 220
  if (result) {
221 221
    check(checkFlow(gr, lower, upper, supply, mcf.flowMap(), type),
222 222
          "The flow is not feasible " + test_id);
223 223
    check(mcf.totalCost() == total, "The flow is not optimal " + test_id);
224 224
    check(checkPotential(gr, lower, upper, cost, supply, mcf.flowMap(),
225 225
                         mcf.potentialMap()),
226 226
          "Wrong potentials " + test_id);
227 227
  }
228 228
}
229 229

	
230 230
int main()
231 231
{
232 232
  // Check the interfaces
233 233
  {
234 234
    typedef int Flow;
235 235
    typedef int Cost;
236
    // TODO: This typedef should be enabled if the standard maps are
237
    // reference maps in the graph concepts (See #190).
238
/**/
239
    //typedef concepts::Digraph GR;
240
    typedef ListDigraph GR;
241
/**/
236
    typedef concepts::Digraph GR;
242 237
    checkConcept< McfClassConcept<GR, Flow, Cost>,
243 238
                  NetworkSimplex<GR, Flow, Cost> >();
244 239
  }
245 240

	
246 241
  // Run various MCF tests
247 242
  typedef ListDigraph Digraph;
248 243
  DIGRAPH_TYPEDEFS(ListDigraph);
249 244

	
250 245
  // Read the test digraph
251 246
  Digraph gr;
252 247
  Digraph::ArcMap<int> c(gr), l1(gr), l2(gr), u(gr);
253 248
  Digraph::NodeMap<int> s1(gr), s2(gr), s3(gr), s4(gr), s5(gr);
254 249
  ConstMap<Arc, int> cc(1), cu(std::numeric_limits<int>::max());
255 250
  Node v, w;
256 251

	
257 252
  std::istringstream input(test_lgf);
258 253
  DigraphReader<Digraph>(gr, input)
259 254
    .arcMap("cost", c)
260 255
    .arcMap("cap", u)
261 256
    .arcMap("low1", l1)
262 257
    .arcMap("low2", l2)
263 258
    .nodeMap("sup1", s1)
264 259
    .nodeMap("sup2", s2)
265 260
    .nodeMap("sup3", s3)
266 261
    .nodeMap("sup4", s4)
267 262
    .nodeMap("sup5", s5)
268 263
    .node("source", v)
269 264
    .node("target", w)
270 265
    .run();
271 266

	
272 267
  // A. Test NetworkSimplex with the default pivot rule
273 268
  {
274 269
    NetworkSimplex<Digraph> mcf(gr);
275 270

	
276 271
    // Check the equality form
277 272
    mcf.upperMap(u).costMap(c);
278 273
    checkMcf(mcf, mcf.supplyMap(s1).run(),
279 274
             gr, l1, u, c, s1, true,  5240, "#A1");
280 275
    checkMcf(mcf, mcf.stSupply(v, w, 27).run(),
281 276
             gr, l1, u, c, s2, true,  7620, "#A2");
282 277
    mcf.lowerMap(l2);
283 278
    checkMcf(mcf, mcf.supplyMap(s1).run(),
284 279
             gr, l2, u, c, s1, true,  5970, "#A3");
285 280
    checkMcf(mcf, mcf.stSupply(v, w, 27).run(),
286 281
             gr, l2, u, c, s2, true,  8010, "#A4");
287 282
    mcf.reset();
288 283
    checkMcf(mcf, mcf.supplyMap(s1).run(),
289 284
             gr, l1, cu, cc, s1, true,  74, "#A5");
290 285
    checkMcf(mcf, mcf.lowerMap(l2).stSupply(v, w, 27).run(),
291 286
             gr, l2, cu, cc, s2, true,  94, "#A6");
292 287
    mcf.reset();
293 288
    checkMcf(mcf, mcf.run(),
294 289
             gr, l1, cu, cc, s3, true,   0, "#A7");
295 290
    checkMcf(mcf, mcf.boundMaps(l2, u).run(),
296 291
             gr, l2, u, cc, s3, false,   0, "#A8");
297 292

	
298 293
    // Check the GEQ form
299 294
    mcf.reset().upperMap(u).costMap(c).supplyMap(s4);
300 295
    checkMcf(mcf, mcf.run(),
301 296
             gr, l1, u, c, s4, true,  3530, "#A9", GEQ);
302 297
    mcf.problemType(mcf.GEQ);
303 298
    checkMcf(mcf, mcf.lowerMap(l2).run(),
304 299
             gr, l2, u, c, s4, true,  4540, "#A10", GEQ);
305 300
    mcf.problemType(mcf.CARRY_SUPPLIES).supplyMap(s5);
Show white space 128 line context
... ...
@@ -32,187 +32,205 @@
32 32
#include <fstream>
33 33
#include <cstring>
34 34

	
35 35
#include <lemon/smart_graph.h>
36 36
#include <lemon/dimacs.h>
37 37
#include <lemon/lgf_writer.h>
38 38
#include <lemon/time_measure.h>
39 39

	
40 40
#include <lemon/arg_parser.h>
41 41
#include <lemon/error.h>
42 42

	
43 43
#include <lemon/dijkstra.h>
44 44
#include <lemon/preflow.h>
45 45
#include <lemon/matching.h>
46 46
#include <lemon/network_simplex.h>
47 47

	
48 48
using namespace lemon;
49 49
typedef SmartDigraph Digraph;
50 50
DIGRAPH_TYPEDEFS(Digraph);
51 51
typedef SmartGraph Graph;
52 52

	
53 53
template<class Value>
54 54
void solve_sp(ArgParser &ap, std::istream &is, std::ostream &,
55 55
              DimacsDescriptor &desc)
56 56
{
57 57
  bool report = !ap.given("q");
58 58
  Digraph g;
59 59
  Node s;
60 60
  Digraph::ArcMap<Value> len(g);
61 61
  Timer t;
62 62
  t.restart();
63 63
  readDimacsSp(is, g, len, s, desc);
64 64
  if(report) std::cerr << "Read the file: " << t << '\n';
65 65
  t.restart();
66 66
  Dijkstra<Digraph, Digraph::ArcMap<Value> > dij(g,len);
67 67
  if(report) std::cerr << "Setup Dijkstra class: " << t << '\n';
68 68
  t.restart();
69 69
  dij.run(s);
70 70
  if(report) std::cerr << "Run Dijkstra: " << t << '\n';
71 71
}
72 72

	
73 73
template<class Value>
74 74
void solve_max(ArgParser &ap, std::istream &is, std::ostream &,
75 75
               Value infty, DimacsDescriptor &desc)
76 76
{
77 77
  bool report = !ap.given("q");
78 78
  Digraph g;
79 79
  Node s,t;
80 80
  Digraph::ArcMap<Value> cap(g);
81 81
  Timer ti;
82 82
  ti.restart();
83 83
  readDimacsMax(is, g, cap, s, t, infty, desc);
84 84
  if(report) std::cerr << "Read the file: " << ti << '\n';
85 85
  ti.restart();
86 86
  Preflow<Digraph, Digraph::ArcMap<Value> > pre(g,cap,s,t);
87 87
  if(report) std::cerr << "Setup Preflow class: " << ti << '\n';
88 88
  ti.restart();
89 89
  pre.run();
90 90
  if(report) std::cerr << "Run Preflow: " << ti << '\n';
91 91
  if(report) std::cerr << "\nMax flow value: " << pre.flowValue() << '\n';  
92 92
}
93 93

	
94 94
template<class Value>
95 95
void solve_min(ArgParser &ap, std::istream &is, std::ostream &,
96
               DimacsDescriptor &desc)
96
               Value infty, DimacsDescriptor &desc)
97 97
{
98 98
  bool report = !ap.given("q");
99 99
  Digraph g;
100 100
  Digraph::ArcMap<Value> lower(g), cap(g), cost(g);
101 101
  Digraph::NodeMap<Value> sup(g);
102 102
  Timer ti;
103

	
103 104
  ti.restart();
104
  readDimacsMin(is, g, lower, cap, cost, sup, 0, desc);
105
  readDimacsMin(is, g, lower, cap, cost, sup, infty, desc);
106
  ti.stop();
107
  Value sum_sup = 0;
108
  for (Digraph::NodeIt n(g); n != INVALID; ++n) {
109
    sum_sup += sup[n];
110
  }
111
  if (report) {
112
    std::cerr << "Sum of supply values: " << sum_sup << "\n";
113
    if (sum_sup <= 0)
114
      std::cerr << "GEQ supply contraints are used for NetworkSimplex\n\n";
115
    else
116
      std::cerr << "LEQ supply contraints are used for NetworkSimplex\n\n";
117
  }
105 118
  if (report) std::cerr << "Read the file: " << ti << '\n';
119

	
106 120
  ti.restart();
107 121
  NetworkSimplex<Digraph, Value> ns(g);
108 122
  ns.lowerMap(lower).capacityMap(cap).costMap(cost).supplyMap(sup);
123
  if (sum_sup > 0) ns.problemType(ns.LEQ);
109 124
  if (report) std::cerr << "Setup NetworkSimplex class: " << ti << '\n';
110 125
  ti.restart();
111
  ns.run();
112
  if (report) std::cerr << "Run NetworkSimplex: " << ti << '\n';
113
  if (report) std::cerr << "\nMin flow cost: " << ns.totalCost() << '\n';
126
  bool res = ns.run();
127
  if (report) {
128
    std::cerr << "Run NetworkSimplex: " << ti << "\n\n";
129
    std::cerr << "Feasible flow: " << (res ? "found" : "not found") << '\n';
130
    if (res) std::cerr << "Min flow cost: " << ns.totalCost() << '\n';
131
  }
114 132
}
115 133

	
116 134
void solve_mat(ArgParser &ap, std::istream &is, std::ostream &,
117 135
              DimacsDescriptor &desc)
118 136
{
119 137
  bool report = !ap.given("q");
120 138
  Graph g;
121 139
  Timer ti;
122 140
  ti.restart();
123 141
  readDimacsMat(is, g, desc);
124 142
  if(report) std::cerr << "Read the file: " << ti << '\n';
125 143
  ti.restart();
126 144
  MaxMatching<Graph> mat(g);
127 145
  if(report) std::cerr << "Setup MaxMatching class: " << ti << '\n';
128 146
  ti.restart();
129 147
  mat.run();
130 148
  if(report) std::cerr << "Run MaxMatching: " << ti << '\n';
131 149
  if(report) std::cerr << "\nCardinality of max matching: "
132 150
                       << mat.matchingSize() << '\n';  
133 151
}
134 152

	
135 153

	
136 154
template<class Value>
137 155
void solve(ArgParser &ap, std::istream &is, std::ostream &os,
138 156
           DimacsDescriptor &desc)
139 157
{
140 158
  std::stringstream iss(static_cast<std::string>(ap["infcap"]));
141 159
  Value infty;
142 160
  iss >> infty;
143 161
  if(iss.fail())
144 162
    {
145 163
      std::cerr << "Cannot interpret '"
146 164
                << static_cast<std::string>(ap["infcap"]) << "' as infinite"
147 165
                << std::endl;
148 166
      exit(1);
149 167
    }
150 168
  
151 169
  switch(desc.type)
152 170
    {
153 171
    case DimacsDescriptor::MIN:
154
      solve_min<Value>(ap,is,os,desc);
172
      solve_min<Value>(ap,is,os,infty,desc);
155 173
      break;
156 174
    case DimacsDescriptor::MAX:
157 175
      solve_max<Value>(ap,is,os,infty,desc);
158 176
      break;
159 177
    case DimacsDescriptor::SP:
160 178
      solve_sp<Value>(ap,is,os,desc);
161 179
      break;
162 180
    case DimacsDescriptor::MAT:
163 181
      solve_mat(ap,is,os,desc);
164 182
      break;
165 183
    default:
166 184
      break;
167 185
    }
168 186
}
169 187

	
170 188
int main(int argc, const char *argv[]) {
171 189
  typedef SmartDigraph Digraph;
172 190

	
173 191
  typedef Digraph::Arc Arc;
174 192

	
175 193
  std::string inputName;
176 194
  std::string outputName;
177 195

	
178 196
  ArgParser ap(argc, argv);
179 197
  ap.other("[INFILE [OUTFILE]]",
180 198
           "If either the INFILE or OUTFILE file is missing the standard\n"
181 199
           "     input/output will be used instead.")
182 200
    .boolOption("q", "Do not print any report")
183 201
    .boolOption("int","Use 'int' for capacities, costs etc. (default)")
184 202
    .optionGroup("datatype","int")
185 203
#ifdef HAVE_LONG_LONG
186 204
    .boolOption("long","Use 'long long' for capacities, costs etc.")
187 205
    .optionGroup("datatype","long")
188 206
#endif
189 207
    .boolOption("double","Use 'double' for capacities, costs etc.")
190 208
    .optionGroup("datatype","double")
191 209
    .boolOption("ldouble","Use 'long double' for capacities, costs etc.")
192 210
    .optionGroup("datatype","ldouble")
193 211
    .onlyOneGroup("datatype")
194 212
    .stringOption("infcap","Value used for 'very high' capacities","0")
195 213
    .run();
196 214

	
197 215
  std::ifstream input;
198 216
  std::ofstream output;
199 217

	
200 218
  switch(ap.files().size())
201 219
    {
202 220
    case 2:
203 221
      output.open(ap.files()[1].c_str());
204 222
      if (!output) {
205 223
        throw IoError("Cannot open the file for writing", ap.files()[1]);
206 224
      }
207 225
    case 1:
208 226
      input.open(ap.files()[0].c_str());
209 227
      if (!input) {
210 228
        throw IoError("File cannot be found", ap.files()[0]);
211 229
      }
212 230
    case 0:
213 231
      break;
214 232
    default:
215 233
      std::cerr << ap.commandName() << ": too many arguments\n";
216 234
      return 1;
217 235
    }
218 236
  std::istream& is = (ap.files().size()<1 ? std::cin : input);
0 comments (0 inline)