tools/dimacs-solver.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 24 Mar 2009 00:18:25 +0100
changeset 651 8c3112a66878
parent 579 997a75bac45a
child 652 5232721b3f14
permissions -rw-r--r--
Use XTI implementation instead of ATI in NetworkSimplex (#234)

XTI (eXtended Threaded Index) is an imporved version of the widely
known ATI (Augmented Threaded Index) method for storing and updating
the spanning tree structure in Network Simplex algorithms.

In the ATI data structure three indices are stored for each node:
predecessor, thread and depth. In the XTI data structure depth is
replaced by the number of successors and the last successor
(according to the thread index).
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@649
   108
  NetworkSimplex< Digraph, Digraph::ArcMap<Value>, Digraph::ArcMap<Value>,
kpeter@649
   109
                  Digraph::ArcMap<Value>, Digraph::NodeMap<Value> >
kpeter@649
   110
    ns(g, lower, cap, cost, sup);
kpeter@649
   111
  if (report) std::cerr << "Setup NetworkSimplex class: " << ti << '\n';
kpeter@649
   112
  ti.restart();
kpeter@649
   113
  ns.run();
kpeter@649
   114
  if (report) std::cerr << "Run NetworkSimplex: " << ti << '\n';
kpeter@649
   115
  if (report) std::cerr << "\nMin flow cost: " << ns.totalCost() << '\n';
kpeter@649
   116
}
kpeter@649
   117
alpar@573
   118
void solve_mat(ArgParser &ap, std::istream &is, std::ostream &,
alpar@573
   119
              DimacsDescriptor &desc)
alpar@573
   120
{
alpar@573
   121
  bool report = !ap.given("q");
alpar@573
   122
  Graph g;
alpar@573
   123
  Timer ti;
alpar@573
   124
  ti.restart();
alpar@573
   125
  readDimacsMat(is, g, desc);
alpar@573
   126
  if(report) std::cerr << "Read the file: " << ti << '\n';
alpar@573
   127
  ti.restart();
alpar@573
   128
  MaxMatching<Graph> mat(g);
alpar@573
   129
  if(report) std::cerr << "Setup MaxMatching class: " << ti << '\n';
alpar@573
   130
  ti.restart();
alpar@573
   131
  mat.run();
alpar@573
   132
  if(report) std::cerr << "Run MaxMatching: " << ti << '\n';
alpar@573
   133
  if(report) std::cerr << "\nCardinality of max matching: "
alpar@573
   134
                       << mat.matchingSize() << '\n';  
alpar@573
   135
}
alpar@573
   136
alpar@573
   137
alpar@573
   138
template<class Value>
alpar@573
   139
void solve(ArgParser &ap, std::istream &is, std::ostream &os,
alpar@573
   140
           DimacsDescriptor &desc)
alpar@573
   141
{
alpar@573
   142
  switch(desc.type)
alpar@573
   143
    {
alpar@573
   144
    case DimacsDescriptor::MIN:
kpeter@649
   145
      solve_min<Value>(ap,is,os,desc);
alpar@573
   146
      break;
alpar@573
   147
    case DimacsDescriptor::MAX:
alpar@573
   148
      solve_max<Value>(ap,is,os,desc);
alpar@573
   149
      break;
alpar@573
   150
    case DimacsDescriptor::SP:
alpar@573
   151
      solve_sp<Value>(ap,is,os,desc);
alpar@573
   152
      break;
alpar@573
   153
    case DimacsDescriptor::MAT:
alpar@573
   154
      solve_mat(ap,is,os,desc);
alpar@573
   155
      break;
alpar@573
   156
    default:
alpar@573
   157
      break;
alpar@573
   158
    }
alpar@573
   159
}
alpar@400
   160
alpar@400
   161
int main(int argc, const char *argv[]) {
alpar@400
   162
  typedef SmartDigraph Digraph;
alpar@400
   163
alpar@400
   164
  typedef Digraph::Arc Arc;
alpar@400
   165
alpar@400
   166
  std::string inputName;
alpar@400
   167
  std::string outputName;
alpar@400
   168
alpar@400
   169
  ArgParser ap(argc, argv);
alpar@402
   170
  ap.other("[INFILE [OUTFILE]]",
alpar@402
   171
           "If either the INFILE or OUTFILE file is missing the standard\n"
alpar@402
   172
           "     input/output will be used instead.")
alpar@573
   173
    .boolOption("q", "Do not print any report")
alpar@573
   174
    .boolOption("int","Use 'int' for capacities, costs etc. (default)")
alpar@573
   175
    .optionGroup("datatype","int")
alpar@573
   176
#ifdef HAVE_LONG_LONG
alpar@573
   177
    .boolOption("long","Use 'long long' for capacities, costs etc.")
alpar@573
   178
    .optionGroup("datatype","long")
alpar@573
   179
#endif
alpar@573
   180
    .boolOption("double","Use 'double' for capacities, costs etc.")
alpar@573
   181
    .optionGroup("datatype","double")
alpar@573
   182
    .boolOption("ldouble","Use 'long double' for capacities, costs etc.")
alpar@573
   183
    .optionGroup("datatype","ldouble")
alpar@573
   184
    .onlyOneGroup("datatype")
alpar@400
   185
    .run();
alpar@400
   186
alpar@573
   187
  std::ifstream input;
alpar@573
   188
  std::ofstream output;
alpar@402
   189
alpar@402
   190
  switch(ap.files().size())
alpar@402
   191
    {
alpar@402
   192
    case 2:
alpar@402
   193
      output.open(ap.files()[1].c_str());
alpar@402
   194
      if (!output) {
alpar@402
   195
        throw IoError("Cannot open the file for writing", ap.files()[1]);
alpar@402
   196
      }
alpar@402
   197
    case 1:
alpar@402
   198
      input.open(ap.files()[0].c_str());
alpar@402
   199
      if (!input) {
alpar@402
   200
        throw IoError("File cannot be found", ap.files()[0]);
alpar@402
   201
      }
alpar@402
   202
    case 0:
alpar@402
   203
      break;
alpar@402
   204
    default:
alpar@573
   205
      std::cerr << ap.commandName() << ": too many arguments\n";
alpar@402
   206
      return 1;
kpeter@579
   207
    }
alpar@573
   208
  std::istream& is = (ap.files().size()<1 ? std::cin : input);
alpar@573
   209
  std::ostream& os = (ap.files().size()<2 ? std::cout : output);
alpar@402
   210
alpar@402
   211
  DimacsDescriptor desc = dimacsType(is);
alpar@573
   212
  
alpar@573
   213
  if(!ap.given("q"))
alpar@402
   214
    {
alpar@573
   215
      std::cout << "Problem type: ";
alpar@573
   216
      switch(desc.type)
alpar@573
   217
        {
alpar@573
   218
        case DimacsDescriptor::MIN:
alpar@573
   219
          std::cout << "min";
alpar@573
   220
          break;
alpar@573
   221
        case DimacsDescriptor::MAX:
alpar@573
   222
          std::cout << "max";
alpar@573
   223
          break;
alpar@573
   224
        case DimacsDescriptor::SP:
alpar@573
   225
          std::cout << "sp";
alpar@573
   226
        case DimacsDescriptor::MAT:
alpar@573
   227
          std::cout << "mat";
alpar@573
   228
          break;
alpar@573
   229
        default:
alpar@573
   230
          exit(1);
alpar@573
   231
          break;
alpar@573
   232
        }
alpar@573
   233
      std::cout << "\nNum of nodes: " << desc.nodeNum;
alpar@573
   234
      std::cout << "\nNum of arcs:  " << desc.edgeNum;
kpeter@579
   235
      std::cout << "\n\n";
alpar@400
   236
    }
alpar@573
   237
    
alpar@573
   238
  if(ap.given("double"))
alpar@573
   239
    solve<double>(ap,is,os,desc);
alpar@573
   240
  else if(ap.given("ldouble"))
alpar@573
   241
    solve<long double>(ap,is,os,desc);
alpar@573
   242
#ifdef HAVE_LONG_LONG
alpar@573
   243
  else if(ap.given("long"))
alpar@573
   244
    solve<long long>(ap,is,os,desc);
alpar@573
   245
#endif
alpar@573
   246
  else solve<int>(ap,is,os,desc);
alpar@573
   247
alpar@400
   248
  return 0;
alpar@400
   249
}