tools/dimacs-solver.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 03 Apr 2009 18:59:15 +0200
changeset 655 6ac5d9ae1d3d
parent 649 a79ef774fae1
child 658 85cb3aa71cce
permissions -rw-r--r--
Support real types + numerical stability fix in NS (#254)

- Real types are supported by appropriate inicialization.
- A feature of the XTI spanning tree structure is removed to ensure
numerical stability (could cause problems using integer types).
The node potentials are updated always on the lower subtree,
in order to prevent overflow problems.
The former method isn't notably faster during to our tests.
alpar@400
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@400
     2
 *
alpar@400
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@400
     4
 *
alpar@463
     5
 * Copyright (C) 2003-2009
alpar@400
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@400
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@400
     8
 *
alpar@400
     9
 * Permission to use, modify and distribute this software is granted
alpar@400
    10
 * provided that this copyright notice appears in all copies. For
alpar@400
    11
 * precise terms see the accompanying LICENSE file.
alpar@400
    12
 *
alpar@400
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@400
    14
 * express or implied, and with no claim as to its suitability for any
alpar@400
    15
 * purpose.
alpar@400
    16
 *
alpar@400
    17
 */
alpar@400
    18
alpar@400
    19
///\ingroup tools
alpar@400
    20
///\file
kpeter@579
    21
///\brief DIMACS problem solver.
alpar@400
    22
///
kpeter@579
    23
/// This program solves various problems given in DIMACS format.
alpar@400
    24
///
alpar@400
    25
/// See
alpar@400
    26
/// \verbatim
alpar@573
    27
///  dimacs-solver --help
alpar@400
    28
/// \endverbatim
alpar@400
    29
/// for more info on usage.
alpar@400
    30
///
alpar@400
    31
alpar@400
    32
#include <iostream>
alpar@400
    33
#include <fstream>
alpar@400
    34
#include <cstring>
alpar@400
    35
alpar@400
    36
#include <lemon/smart_graph.h>
alpar@400
    37
#include <lemon/dimacs.h>
alpar@400
    38
#include <lemon/lgf_writer.h>
alpar@573
    39
#include <lemon/time_measure.h>
alpar@400
    40
alpar@400
    41
#include <lemon/arg_parser.h>
alpar@402
    42
#include <lemon/error.h>
alpar@400
    43
alpar@573
    44
#include <lemon/dijkstra.h>
alpar@573
    45
#include <lemon/preflow.h>
alpar@573
    46
#include <lemon/max_matching.h>
kpeter@649
    47
#include <lemon/network_simplex.h>
alpar@573
    48
alpar@400
    49
using namespace lemon;
alpar@573
    50
typedef SmartDigraph Digraph;
alpar@573
    51
DIGRAPH_TYPEDEFS(Digraph);
alpar@573
    52
typedef SmartGraph Graph;
alpar@400
    53
alpar@573
    54
template<class Value>
alpar@573
    55
void solve_sp(ArgParser &ap, std::istream &is, std::ostream &,
alpar@573
    56
              DimacsDescriptor &desc)
alpar@573
    57
{
alpar@573
    58
  bool report = !ap.given("q");
alpar@573
    59
  Digraph g;
alpar@573
    60
  Node s;
alpar@573
    61
  Digraph::ArcMap<Value> len(g);
alpar@573
    62
  Timer t;
alpar@573
    63
  t.restart();
alpar@573
    64
  readDimacsSp(is, g, len, s, desc);
alpar@573
    65
  if(report) std::cerr << "Read the file: " << t << '\n';
alpar@573
    66
  t.restart();
alpar@573
    67
  Dijkstra<Digraph, Digraph::ArcMap<Value> > dij(g,len);
alpar@573
    68
  if(report) std::cerr << "Setup Dijkstra class: " << t << '\n';
alpar@573
    69
  t.restart();
alpar@573
    70
  dij.run(s);
alpar@573
    71
  if(report) std::cerr << "Run Dijkstra: " << t << '\n';
alpar@573
    72
}
alpar@573
    73
alpar@573
    74
template<class Value>
alpar@573
    75
void solve_max(ArgParser &ap, std::istream &is, std::ostream &,
alpar@573
    76
              DimacsDescriptor &desc)
alpar@573
    77
{
alpar@573
    78
  bool report = !ap.given("q");
alpar@573
    79
  Digraph g;
alpar@573
    80
  Node s,t;
alpar@573
    81
  Digraph::ArcMap<Value> cap(g);
alpar@573
    82
  Timer ti;
alpar@573
    83
  ti.restart();
alpar@573
    84
  readDimacsMax(is, g, cap, s, t, desc);
alpar@573
    85
  if(report) std::cerr << "Read the file: " << ti << '\n';
alpar@573
    86
  ti.restart();
alpar@573
    87
  Preflow<Digraph, Digraph::ArcMap<Value> > pre(g,cap,s,t);
alpar@573
    88
  if(report) std::cerr << "Setup Preflow class: " << ti << '\n';
alpar@573
    89
  ti.restart();
alpar@573
    90
  pre.run();
alpar@573
    91
  if(report) std::cerr << "Run Preflow: " << ti << '\n';
alpar@573
    92
  if(report) std::cerr << "\nMax flow value: " << pre.flowValue() << '\n';  
alpar@573
    93
}
alpar@573
    94
kpeter@649
    95
template<class Value>
kpeter@649
    96
void solve_min(ArgParser &ap, std::istream &is, std::ostream &,
kpeter@649
    97
               DimacsDescriptor &desc)
kpeter@649
    98
{
kpeter@649
    99
  bool report = !ap.given("q");
kpeter@649
   100
  Digraph g;
kpeter@649
   101
  Digraph::ArcMap<Value> lower(g), cap(g), cost(g);
kpeter@649
   102
  Digraph::NodeMap<Value> sup(g);
kpeter@649
   103
  Timer ti;
kpeter@649
   104
  ti.restart();
kpeter@649
   105
  readDimacsMin(is, g, lower, cap, cost, sup, desc);
kpeter@649
   106
  if (report) std::cerr << "Read the file: " << ti << '\n';
kpeter@649
   107
  ti.restart();
kpeter@652
   108
  NetworkSimplex<Digraph, Value> ns(g);
kpeter@652
   109
  ns.lowerMap(lower).capacityMap(cap).costMap(cost).supplyMap(sup);
kpeter@649
   110
  if (report) std::cerr << "Setup NetworkSimplex class: " << ti << '\n';
kpeter@649
   111
  ti.restart();
kpeter@649
   112
  ns.run();
kpeter@649
   113
  if (report) std::cerr << "Run NetworkSimplex: " << ti << '\n';
kpeter@649
   114
  if (report) std::cerr << "\nMin flow cost: " << ns.totalCost() << '\n';
kpeter@649
   115
}
kpeter@649
   116
alpar@573
   117
void solve_mat(ArgParser &ap, std::istream &is, std::ostream &,
alpar@573
   118
              DimacsDescriptor &desc)
alpar@573
   119
{
alpar@573
   120
  bool report = !ap.given("q");
alpar@573
   121
  Graph g;
alpar@573
   122
  Timer ti;
alpar@573
   123
  ti.restart();
alpar@573
   124
  readDimacsMat(is, g, desc);
alpar@573
   125
  if(report) std::cerr << "Read the file: " << ti << '\n';
alpar@573
   126
  ti.restart();
alpar@573
   127
  MaxMatching<Graph> mat(g);
alpar@573
   128
  if(report) std::cerr << "Setup MaxMatching class: " << ti << '\n';
alpar@573
   129
  ti.restart();
alpar@573
   130
  mat.run();
alpar@573
   131
  if(report) std::cerr << "Run MaxMatching: " << ti << '\n';
alpar@573
   132
  if(report) std::cerr << "\nCardinality of max matching: "
alpar@573
   133
                       << mat.matchingSize() << '\n';  
alpar@573
   134
}
alpar@573
   135
alpar@573
   136
alpar@573
   137
template<class Value>
alpar@573
   138
void solve(ArgParser &ap, std::istream &is, std::ostream &os,
alpar@573
   139
           DimacsDescriptor &desc)
alpar@573
   140
{
alpar@573
   141
  switch(desc.type)
alpar@573
   142
    {
alpar@573
   143
    case DimacsDescriptor::MIN:
kpeter@649
   144
      solve_min<Value>(ap,is,os,desc);
alpar@573
   145
      break;
alpar@573
   146
    case DimacsDescriptor::MAX:
alpar@573
   147
      solve_max<Value>(ap,is,os,desc);
alpar@573
   148
      break;
alpar@573
   149
    case DimacsDescriptor::SP:
alpar@573
   150
      solve_sp<Value>(ap,is,os,desc);
alpar@573
   151
      break;
alpar@573
   152
    case DimacsDescriptor::MAT:
alpar@573
   153
      solve_mat(ap,is,os,desc);
alpar@573
   154
      break;
alpar@573
   155
    default:
alpar@573
   156
      break;
alpar@573
   157
    }
alpar@573
   158
}
alpar@400
   159
alpar@400
   160
int main(int argc, const char *argv[]) {
alpar@400
   161
  typedef SmartDigraph Digraph;
alpar@400
   162
alpar@400
   163
  typedef Digraph::Arc Arc;
alpar@400
   164
alpar@400
   165
  std::string inputName;
alpar@400
   166
  std::string outputName;
alpar@400
   167
alpar@400
   168
  ArgParser ap(argc, argv);
alpar@402
   169
  ap.other("[INFILE [OUTFILE]]",
alpar@402
   170
           "If either the INFILE or OUTFILE file is missing the standard\n"
alpar@402
   171
           "     input/output will be used instead.")
alpar@573
   172
    .boolOption("q", "Do not print any report")
alpar@573
   173
    .boolOption("int","Use 'int' for capacities, costs etc. (default)")
alpar@573
   174
    .optionGroup("datatype","int")
alpar@573
   175
#ifdef HAVE_LONG_LONG
alpar@573
   176
    .boolOption("long","Use 'long long' for capacities, costs etc.")
alpar@573
   177
    .optionGroup("datatype","long")
alpar@573
   178
#endif
alpar@573
   179
    .boolOption("double","Use 'double' for capacities, costs etc.")
alpar@573
   180
    .optionGroup("datatype","double")
alpar@573
   181
    .boolOption("ldouble","Use 'long double' for capacities, costs etc.")
alpar@573
   182
    .optionGroup("datatype","ldouble")
alpar@573
   183
    .onlyOneGroup("datatype")
alpar@400
   184
    .run();
alpar@400
   185
alpar@573
   186
  std::ifstream input;
alpar@573
   187
  std::ofstream output;
alpar@402
   188
alpar@402
   189
  switch(ap.files().size())
alpar@402
   190
    {
alpar@402
   191
    case 2:
alpar@402
   192
      output.open(ap.files()[1].c_str());
alpar@402
   193
      if (!output) {
alpar@402
   194
        throw IoError("Cannot open the file for writing", ap.files()[1]);
alpar@402
   195
      }
alpar@402
   196
    case 1:
alpar@402
   197
      input.open(ap.files()[0].c_str());
alpar@402
   198
      if (!input) {
alpar@402
   199
        throw IoError("File cannot be found", ap.files()[0]);
alpar@402
   200
      }
alpar@402
   201
    case 0:
alpar@402
   202
      break;
alpar@402
   203
    default:
alpar@573
   204
      std::cerr << ap.commandName() << ": too many arguments\n";
alpar@402
   205
      return 1;
kpeter@579
   206
    }
alpar@573
   207
  std::istream& is = (ap.files().size()<1 ? std::cin : input);
alpar@573
   208
  std::ostream& os = (ap.files().size()<2 ? std::cout : output);
alpar@402
   209
alpar@402
   210
  DimacsDescriptor desc = dimacsType(is);
alpar@573
   211
  
alpar@573
   212
  if(!ap.given("q"))
alpar@402
   213
    {
alpar@573
   214
      std::cout << "Problem type: ";
alpar@573
   215
      switch(desc.type)
alpar@573
   216
        {
alpar@573
   217
        case DimacsDescriptor::MIN:
alpar@573
   218
          std::cout << "min";
alpar@573
   219
          break;
alpar@573
   220
        case DimacsDescriptor::MAX:
alpar@573
   221
          std::cout << "max";
alpar@573
   222
          break;
alpar@573
   223
        case DimacsDescriptor::SP:
alpar@573
   224
          std::cout << "sp";
alpar@573
   225
        case DimacsDescriptor::MAT:
alpar@573
   226
          std::cout << "mat";
alpar@573
   227
          break;
alpar@573
   228
        default:
alpar@573
   229
          exit(1);
alpar@573
   230
          break;
alpar@573
   231
        }
alpar@573
   232
      std::cout << "\nNum of nodes: " << desc.nodeNum;
alpar@573
   233
      std::cout << "\nNum of arcs:  " << desc.edgeNum;
kpeter@579
   234
      std::cout << "\n\n";
alpar@400
   235
    }
alpar@573
   236
    
alpar@573
   237
  if(ap.given("double"))
alpar@573
   238
    solve<double>(ap,is,os,desc);
alpar@573
   239
  else if(ap.given("ldouble"))
alpar@573
   240
    solve<long double>(ap,is,os,desc);
alpar@573
   241
#ifdef HAVE_LONG_LONG
alpar@573
   242
  else if(ap.given("long"))
alpar@573
   243
    solve<long long>(ap,is,os,desc);
alpar@573
   244
#endif
alpar@573
   245
  else solve<int>(ap,is,os,desc);
alpar@573
   246
alpar@400
   247
  return 0;
alpar@400
   248
}