test/min_cost_arborescence_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Thu, 12 Nov 2009 23:26:13 +0100
changeset 872 fa6f37d7a25b
parent 522 7f8560cb9d65
child 956 141f9c0db4a3
child 1081 f1398882a928
child 1171 7e368d9b67f7
permissions -rw-r--r--
Entirely rework CapacityScaling (#180)

- Use the new interface similarly to NetworkSimplex.
- Rework the implementation using an efficient internal structure
for handling the residual network. This improvement made the
code much faster (up to 2-5 times faster on large graphs).
- Handle GEQ supply type (LEQ is not supported).
- Handle negative costs for arcs of finite capacity.
(Note that this algorithm cannot handle arcs of negative cost
and infinite upper bound, thus it returns UNBOUNDED if such
an arc exists.)
- Extend the documentation.
deba@522
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
deba@522
     2
 *
deba@522
     3
 * This file is a part of LEMON, a generic C++ optimization library.
deba@522
     4
 *
deba@522
     5
 * Copyright (C) 2003-2008
deba@522
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@522
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@522
     8
 *
deba@522
     9
 * Permission to use, modify and distribute this software is granted
deba@522
    10
 * provided that this copyright notice appears in all copies. For
deba@522
    11
 * precise terms see the accompanying LICENSE file.
deba@522
    12
 *
deba@522
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@522
    14
 * express or implied, and with no claim as to its suitability for any
deba@522
    15
 * purpose.
deba@522
    16
 *
deba@522
    17
 */
deba@522
    18
deba@522
    19
#include <iostream>
deba@522
    20
#include <set>
deba@522
    21
#include <vector>
deba@522
    22
#include <iterator>
deba@522
    23
deba@522
    24
#include <lemon/smart_graph.h>
deba@522
    25
#include <lemon/min_cost_arborescence.h>
deba@522
    26
#include <lemon/lgf_reader.h>
kpeter@672
    27
#include <lemon/concepts/digraph.h>
deba@522
    28
deba@522
    29
#include "test_tools.h"
deba@522
    30
deba@522
    31
using namespace lemon;
deba@522
    32
using namespace std;
deba@522
    33
deba@522
    34
const char test_lgf[] =
deba@522
    35
  "@nodes\n"
deba@522
    36
  "label\n"
deba@522
    37
  "0\n"
deba@522
    38
  "1\n"
deba@522
    39
  "2\n"
deba@522
    40
  "3\n"
deba@522
    41
  "4\n"
deba@522
    42
  "5\n"
deba@522
    43
  "6\n"
deba@522
    44
  "7\n"
deba@522
    45
  "8\n"
deba@522
    46
  "9\n"
deba@522
    47
  "@arcs\n"
deba@522
    48
  "     label  cost\n"
deba@522
    49
  "1 8  0      107\n"
deba@522
    50
  "0 3  1      70\n"
deba@522
    51
  "2 1  2      46\n"
deba@522
    52
  "4 1  3      28\n"
deba@522
    53
  "4 4  4      91\n"
deba@522
    54
  "3 9  5      76\n"
deba@522
    55
  "9 8  6      61\n"
deba@522
    56
  "8 1  7      39\n"
deba@522
    57
  "9 8  8      74\n"
deba@522
    58
  "8 0  9      39\n"
deba@522
    59
  "4 3  10     45\n"
deba@522
    60
  "2 2  11     34\n"
deba@522
    61
  "0 1  12     100\n"
deba@522
    62
  "6 3  13     95\n"
deba@522
    63
  "4 1  14     22\n"
deba@522
    64
  "1 1  15     31\n"
deba@522
    65
  "7 2  16     51\n"
deba@522
    66
  "2 6  17     29\n"
deba@522
    67
  "8 3  18     115\n"
deba@522
    68
  "6 9  19     32\n"
deba@522
    69
  "1 1  20     60\n"
deba@522
    70
  "0 3  21     40\n"
deba@522
    71
  "@attributes\n"
deba@522
    72
  "source 0\n";
deba@522
    73
kpeter@672
    74
kpeter@672
    75
void checkMinCostArborescenceCompile()
kpeter@672
    76
{
kpeter@672
    77
  typedef double VType;
kpeter@672
    78
  typedef concepts::Digraph Digraph;
kpeter@672
    79
  typedef concepts::ReadMap<Digraph::Arc, VType> CostMap;
kpeter@672
    80
  typedef Digraph::Node Node;
kpeter@672
    81
  typedef Digraph::Arc Arc;
kpeter@672
    82
  typedef concepts::WriteMap<Digraph::Arc, bool> ArbMap;
kpeter@672
    83
  typedef concepts::ReadWriteMap<Digraph::Node, Digraph::Arc> PredMap;
kpeter@672
    84
kpeter@672
    85
  typedef MinCostArborescence<Digraph, CostMap>::
kpeter@672
    86
            SetArborescenceMap<ArbMap>::
kpeter@672
    87
            SetPredMap<PredMap>::Create MinCostArbType;
kpeter@672
    88
kpeter@672
    89
  Digraph g;
kpeter@672
    90
  Node s, n;
kpeter@672
    91
  Arc e;
kpeter@672
    92
  VType c;
kpeter@672
    93
  bool b;
kpeter@672
    94
  int i;
kpeter@672
    95
  CostMap cost;
kpeter@672
    96
  ArbMap arb;
kpeter@672
    97
  PredMap pred;
kpeter@672
    98
kpeter@672
    99
  MinCostArbType mcarb_test(g, cost);
kpeter@672
   100
  const MinCostArbType& const_mcarb_test = mcarb_test;
kpeter@672
   101
kpeter@672
   102
  mcarb_test
kpeter@672
   103
    .arborescenceMap(arb)
kpeter@672
   104
    .predMap(pred)
kpeter@672
   105
    .run(s);
kpeter@672
   106
kpeter@672
   107
  mcarb_test.init();
kpeter@672
   108
  mcarb_test.addSource(s);
kpeter@672
   109
  mcarb_test.start();
kpeter@672
   110
  n = mcarb_test.processNextNode();
kpeter@672
   111
  b = const_mcarb_test.emptyQueue();
kpeter@672
   112
  i = const_mcarb_test.queueSize();
kpeter@672
   113
  
kpeter@672
   114
  c = const_mcarb_test.arborescenceCost();
kpeter@672
   115
  b = const_mcarb_test.arborescence(e);
kpeter@672
   116
  e = const_mcarb_test.pred(n);
kpeter@672
   117
  const MinCostArbType::ArborescenceMap &am =
kpeter@672
   118
    const_mcarb_test.arborescenceMap();
kpeter@672
   119
  const MinCostArbType::PredMap &pm =
kpeter@672
   120
    const_mcarb_test.predMap();
kpeter@672
   121
  b = const_mcarb_test.reached(n);
kpeter@672
   122
  b = const_mcarb_test.processed(n);
kpeter@672
   123
  
kpeter@672
   124
  i = const_mcarb_test.dualNum();
kpeter@672
   125
  c = const_mcarb_test.dualValue();
kpeter@672
   126
  i = const_mcarb_test.dualSize(i);
kpeter@672
   127
  c = const_mcarb_test.dualValue(i);
kpeter@672
   128
  
kpeter@672
   129
  ignore_unused_variable_warning(am);
kpeter@672
   130
  ignore_unused_variable_warning(pm);
kpeter@672
   131
}
kpeter@672
   132
deba@522
   133
int main() {
deba@522
   134
  typedef SmartDigraph Digraph;
deba@522
   135
  DIGRAPH_TYPEDEFS(Digraph);
deba@522
   136
deba@522
   137
  typedef Digraph::ArcMap<double> CostMap;
deba@522
   138
deba@522
   139
  Digraph digraph;
deba@522
   140
  CostMap cost(digraph);
deba@522
   141
  Node source;
deba@522
   142
deba@522
   143
  std::istringstream is(test_lgf);
deba@522
   144
  digraphReader(digraph, is).
deba@522
   145
    arcMap("cost", cost).
deba@522
   146
    node("source", source).run();
deba@522
   147
deba@522
   148
  MinCostArborescence<Digraph, CostMap> mca(digraph, cost);
deba@522
   149
  mca.run(source);
deba@522
   150
deba@522
   151
  vector<pair<double, set<Node> > > dualSolution(mca.dualNum());
deba@522
   152
deba@522
   153
  for (int i = 0; i < mca.dualNum(); ++i) {
deba@522
   154
    dualSolution[i].first = mca.dualValue(i);
deba@522
   155
    for (MinCostArborescence<Digraph, CostMap>::DualIt it(mca, i);
deba@522
   156
         it != INVALID; ++it) {
deba@522
   157
      dualSolution[i].second.insert(it);
deba@522
   158
    }
deba@522
   159
  }
deba@522
   160
deba@522
   161
  for (ArcIt it(digraph); it != INVALID; ++it) {
deba@522
   162
    if (mca.reached(digraph.source(it))) {
deba@522
   163
      double sum = 0.0;
deba@522
   164
      for (int i = 0; i < int(dualSolution.size()); ++i) {
deba@522
   165
        if (dualSolution[i].second.find(digraph.target(it))
deba@522
   166
            != dualSolution[i].second.end() &&
deba@522
   167
            dualSolution[i].second.find(digraph.source(it))
deba@522
   168
            == dualSolution[i].second.end()) {
deba@522
   169
          sum += dualSolution[i].first;
deba@522
   170
        }
deba@522
   171
      }
deba@522
   172
      if (mca.arborescence(it)) {
kpeter@672
   173
        check(sum == cost[it], "Invalid dual solution");
deba@522
   174
      }
kpeter@672
   175
      check(sum <= cost[it], "Invalid dual solution");
deba@522
   176
    }
deba@522
   177
  }
deba@522
   178
deba@522
   179
kpeter@672
   180
  check(mca.dualValue() == mca.arborescenceCost(), "Invalid dual solution");
deba@522
   181
kpeter@672
   182
  check(mca.reached(source), "Invalid arborescence");
deba@522
   183
  for (ArcIt a(digraph); a != INVALID; ++a) {
deba@522
   184
    check(!mca.reached(digraph.source(a)) ||
kpeter@672
   185
          mca.reached(digraph.target(a)), "Invalid arborescence");
deba@522
   186
  }
deba@522
   187
deba@522
   188
  for (NodeIt n(digraph); n != INVALID; ++n) {
deba@522
   189
    if (!mca.reached(n)) continue;
deba@522
   190
    int cnt = 0;
deba@522
   191
    for (InArcIt a(digraph, n); a != INVALID; ++a) {
deba@522
   192
      if (mca.arborescence(a)) {
kpeter@672
   193
        check(mca.pred(n) == a, "Invalid arborescence");
deba@522
   194
        ++cnt;
deba@522
   195
      }
deba@522
   196
    }
kpeter@672
   197
    check((n == source ? cnt == 0 : cnt == 1), "Invalid arborescence");
deba@522
   198
  }
deba@522
   199
deba@522
   200
  Digraph::ArcMap<bool> arborescence(digraph);
kpeter@672
   201
  check(mca.arborescenceCost() ==
deba@522
   202
        minCostArborescence(digraph, cost, source, arborescence),
kpeter@672
   203
        "Wrong result of the function interface");
deba@522
   204
deba@522
   205
  return 0;
deba@522
   206
}