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