test/min_cost_arborescence_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 625 029a48052c67
child 1008 d216e1c8b3fa
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
deba@490
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
deba@490
     2
 *
deba@490
     3
 * This file is a part of LEMON, a generic C++ optimization library.
deba@490
     4
 *
alpar@877
     5
 * Copyright (C) 2003-2010
deba@490
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@490
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@490
     8
 *
deba@490
     9
 * Permission to use, modify and distribute this software is granted
deba@490
    10
 * provided that this copyright notice appears in all copies. For
deba@490
    11
 * precise terms see the accompanying LICENSE file.
deba@490
    12
 *
deba@490
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@490
    14
 * express or implied, and with no claim as to its suitability for any
deba@490
    15
 * purpose.
deba@490
    16
 *
deba@490
    17
 */
deba@490
    18
deba@490
    19
#include <iostream>
deba@490
    20
#include <set>
deba@490
    21
#include <vector>
deba@490
    22
#include <iterator>
deba@490
    23
deba@490
    24
#include <lemon/smart_graph.h>
deba@490
    25
#include <lemon/min_cost_arborescence.h>
deba@490
    26
#include <lemon/lgf_reader.h>
kpeter@625
    27
#include <lemon/concepts/digraph.h>
deba@490
    28
deba@490
    29
#include "test_tools.h"
deba@490
    30
deba@490
    31
using namespace lemon;
deba@490
    32
using namespace std;
deba@490
    33
deba@490
    34
const char test_lgf[] =
deba@490
    35
  "@nodes\n"
deba@490
    36
  "label\n"
deba@490
    37
  "0\n"
deba@490
    38
  "1\n"
deba@490
    39
  "2\n"
deba@490
    40
  "3\n"
deba@490
    41
  "4\n"
deba@490
    42
  "5\n"
deba@490
    43
  "6\n"
deba@490
    44
  "7\n"
deba@490
    45
  "8\n"
deba@490
    46
  "9\n"
deba@490
    47
  "@arcs\n"
deba@490
    48
  "     label  cost\n"
deba@490
    49
  "1 8  0      107\n"
deba@490
    50
  "0 3  1      70\n"
deba@490
    51
  "2 1  2      46\n"
deba@490
    52
  "4 1  3      28\n"
deba@490
    53
  "4 4  4      91\n"
deba@490
    54
  "3 9  5      76\n"
deba@490
    55
  "9 8  6      61\n"
deba@490
    56
  "8 1  7      39\n"
deba@490
    57
  "9 8  8      74\n"
deba@490
    58
  "8 0  9      39\n"
deba@490
    59
  "4 3  10     45\n"
deba@490
    60
  "2 2  11     34\n"
deba@490
    61
  "0 1  12     100\n"
deba@490
    62
  "6 3  13     95\n"
deba@490
    63
  "4 1  14     22\n"
deba@490
    64
  "1 1  15     31\n"
deba@490
    65
  "7 2  16     51\n"
deba@490
    66
  "2 6  17     29\n"
deba@490
    67
  "8 3  18     115\n"
deba@490
    68
  "6 9  19     32\n"
deba@490
    69
  "1 1  20     60\n"
deba@490
    70
  "0 3  21     40\n"
deba@490
    71
  "@attributes\n"
deba@490
    72
  "source 0\n";
deba@490
    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();
alpar@877
   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);
alpar@877
   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);
alpar@877
   128
kpeter@625
   129
  ignore_unused_variable_warning(am);
kpeter@625
   130
  ignore_unused_variable_warning(pm);
kpeter@625
   131
}
kpeter@625
   132
deba@490
   133
int main() {
deba@490
   134
  typedef SmartDigraph Digraph;
deba@490
   135
  DIGRAPH_TYPEDEFS(Digraph);
deba@490
   136
deba@490
   137
  typedef Digraph::ArcMap<double> CostMap;
deba@490
   138
deba@490
   139
  Digraph digraph;
deba@490
   140
  CostMap cost(digraph);
deba@490
   141
  Node source;
deba@490
   142
deba@490
   143
  std::istringstream is(test_lgf);
deba@490
   144
  digraphReader(digraph, is).
deba@490
   145
    arcMap("cost", cost).
deba@490
   146
    node("source", source).run();
deba@490
   147
deba@490
   148
  MinCostArborescence<Digraph, CostMap> mca(digraph, cost);
deba@490
   149
  mca.run(source);
deba@490
   150
deba@490
   151
  vector<pair<double, set<Node> > > dualSolution(mca.dualNum());
deba@490
   152
deba@490
   153
  for (int i = 0; i < mca.dualNum(); ++i) {
deba@490
   154
    dualSolution[i].first = mca.dualValue(i);
deba@490
   155
    for (MinCostArborescence<Digraph, CostMap>::DualIt it(mca, i);
deba@490
   156
         it != INVALID; ++it) {
deba@490
   157
      dualSolution[i].second.insert(it);
deba@490
   158
    }
deba@490
   159
  }
deba@490
   160
deba@490
   161
  for (ArcIt it(digraph); it != INVALID; ++it) {
deba@490
   162
    if (mca.reached(digraph.source(it))) {
deba@490
   163
      double sum = 0.0;
deba@490
   164
      for (int i = 0; i < int(dualSolution.size()); ++i) {
deba@490
   165
        if (dualSolution[i].second.find(digraph.target(it))
deba@490
   166
            != dualSolution[i].second.end() &&
deba@490
   167
            dualSolution[i].second.find(digraph.source(it))
deba@490
   168
            == dualSolution[i].second.end()) {
deba@490
   169
          sum += dualSolution[i].first;
deba@490
   170
        }
deba@490
   171
      }
deba@490
   172
      if (mca.arborescence(it)) {
kpeter@625
   173
        check(sum == cost[it], "Invalid dual solution");
deba@490
   174
      }
kpeter@625
   175
      check(sum <= cost[it], "Invalid dual solution");
deba@490
   176
    }
deba@490
   177
  }
deba@490
   178
deba@490
   179
kpeter@625
   180
  check(mca.dualValue() == mca.arborescenceCost(), "Invalid dual solution");
deba@490
   181
kpeter@625
   182
  check(mca.reached(source), "Invalid arborescence");
deba@490
   183
  for (ArcIt a(digraph); a != INVALID; ++a) {
deba@490
   184
    check(!mca.reached(digraph.source(a)) ||
kpeter@625
   185
          mca.reached(digraph.target(a)), "Invalid arborescence");
deba@490
   186
  }
deba@490
   187
deba@490
   188
  for (NodeIt n(digraph); n != INVALID; ++n) {
deba@490
   189
    if (!mca.reached(n)) continue;
deba@490
   190
    int cnt = 0;
deba@490
   191
    for (InArcIt a(digraph, n); a != INVALID; ++a) {
deba@490
   192
      if (mca.arborescence(a)) {
kpeter@625
   193
        check(mca.pred(n) == a, "Invalid arborescence");
deba@490
   194
        ++cnt;
deba@490
   195
      }
deba@490
   196
    }
kpeter@625
   197
    check((n == source ? cnt == 0 : cnt == 1), "Invalid arborescence");
deba@490
   198
  }
deba@490
   199
deba@490
   200
  Digraph::ArcMap<bool> arborescence(digraph);
kpeter@625
   201
  check(mca.arborescenceCost() ==
deba@490
   202
        minCostArborescence(digraph, cost, source, arborescence),
kpeter@625
   203
        "Wrong result of the function interface");
deba@490
   204
deba@490
   205
  return 0;
deba@490
   206
}