test/min_cost_arborescence_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 17 Apr 2009 18:04:36 +0200
changeset 656 e6927fe719e6
child 672 029a48052c67
permissions -rw-r--r--
Support >= and <= constraints in NetworkSimplex (#219, #234)

By default the same inequality constraints are supported as by
Circulation (the GEQ form), but the LEQ form can also be selected
using the problemType() function.

The documentation of the min. cost flow module is reworked and
extended with important notes and explanations about the different
variants of the problem and about the dual solution and optimality
conditions.
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>
deba@522
    27
deba@522
    28
#include "test_tools.h"
deba@522
    29
deba@522
    30
using namespace lemon;
deba@522
    31
using namespace std;
deba@522
    32
deba@522
    33
const char test_lgf[] =
deba@522
    34
  "@nodes\n"
deba@522
    35
  "label\n"
deba@522
    36
  "0\n"
deba@522
    37
  "1\n"
deba@522
    38
  "2\n"
deba@522
    39
  "3\n"
deba@522
    40
  "4\n"
deba@522
    41
  "5\n"
deba@522
    42
  "6\n"
deba@522
    43
  "7\n"
deba@522
    44
  "8\n"
deba@522
    45
  "9\n"
deba@522
    46
  "@arcs\n"
deba@522
    47
  "     label  cost\n"
deba@522
    48
  "1 8  0      107\n"
deba@522
    49
  "0 3  1      70\n"
deba@522
    50
  "2 1  2      46\n"
deba@522
    51
  "4 1  3      28\n"
deba@522
    52
  "4 4  4      91\n"
deba@522
    53
  "3 9  5      76\n"
deba@522
    54
  "9 8  6      61\n"
deba@522
    55
  "8 1  7      39\n"
deba@522
    56
  "9 8  8      74\n"
deba@522
    57
  "8 0  9      39\n"
deba@522
    58
  "4 3  10     45\n"
deba@522
    59
  "2 2  11     34\n"
deba@522
    60
  "0 1  12     100\n"
deba@522
    61
  "6 3  13     95\n"
deba@522
    62
  "4 1  14     22\n"
deba@522
    63
  "1 1  15     31\n"
deba@522
    64
  "7 2  16     51\n"
deba@522
    65
  "2 6  17     29\n"
deba@522
    66
  "8 3  18     115\n"
deba@522
    67
  "6 9  19     32\n"
deba@522
    68
  "1 1  20     60\n"
deba@522
    69
  "0 3  21     40\n"
deba@522
    70
  "@attributes\n"
deba@522
    71
  "source 0\n";
deba@522
    72
deba@522
    73
int main() {
deba@522
    74
  typedef SmartDigraph Digraph;
deba@522
    75
  DIGRAPH_TYPEDEFS(Digraph);
deba@522
    76
deba@522
    77
  typedef Digraph::ArcMap<double> CostMap;
deba@522
    78
deba@522
    79
  Digraph digraph;
deba@522
    80
  CostMap cost(digraph);
deba@522
    81
  Node source;
deba@522
    82
deba@522
    83
  std::istringstream is(test_lgf);
deba@522
    84
  digraphReader(digraph, is).
deba@522
    85
    arcMap("cost", cost).
deba@522
    86
    node("source", source).run();
deba@522
    87
deba@522
    88
  MinCostArborescence<Digraph, CostMap> mca(digraph, cost);
deba@522
    89
  mca.run(source);
deba@522
    90
deba@522
    91
  vector<pair<double, set<Node> > > dualSolution(mca.dualNum());
deba@522
    92
deba@522
    93
  for (int i = 0; i < mca.dualNum(); ++i) {
deba@522
    94
    dualSolution[i].first = mca.dualValue(i);
deba@522
    95
    for (MinCostArborescence<Digraph, CostMap>::DualIt it(mca, i);
deba@522
    96
         it != INVALID; ++it) {
deba@522
    97
      dualSolution[i].second.insert(it);
deba@522
    98
    }
deba@522
    99
  }
deba@522
   100
deba@522
   101
  for (ArcIt it(digraph); it != INVALID; ++it) {
deba@522
   102
    if (mca.reached(digraph.source(it))) {
deba@522
   103
      double sum = 0.0;
deba@522
   104
      for (int i = 0; i < int(dualSolution.size()); ++i) {
deba@522
   105
        if (dualSolution[i].second.find(digraph.target(it))
deba@522
   106
            != dualSolution[i].second.end() &&
deba@522
   107
            dualSolution[i].second.find(digraph.source(it))
deba@522
   108
            == dualSolution[i].second.end()) {
deba@522
   109
          sum += dualSolution[i].first;
deba@522
   110
        }
deba@522
   111
      }
deba@522
   112
      if (mca.arborescence(it)) {
deba@522
   113
        check(sum == cost[it], "INVALID DUAL");
deba@522
   114
      }
deba@522
   115
      check(sum <= cost[it], "INVALID DUAL");
deba@522
   116
    }
deba@522
   117
  }
deba@522
   118
deba@522
   119
deba@522
   120
  check(mca.dualValue() == mca.arborescenceValue(), "INVALID DUAL");
deba@522
   121
deba@522
   122
  check(mca.reached(source), "INVALID ARBORESCENCE");
deba@522
   123
  for (ArcIt a(digraph); a != INVALID; ++a) {
deba@522
   124
    check(!mca.reached(digraph.source(a)) ||
deba@522
   125
          mca.reached(digraph.target(a)), "INVALID ARBORESCENCE");
deba@522
   126
  }
deba@522
   127
deba@522
   128
  for (NodeIt n(digraph); n != INVALID; ++n) {
deba@522
   129
    if (!mca.reached(n)) continue;
deba@522
   130
    int cnt = 0;
deba@522
   131
    for (InArcIt a(digraph, n); a != INVALID; ++a) {
deba@522
   132
      if (mca.arborescence(a)) {
deba@522
   133
        check(mca.pred(n) == a, "INVALID ARBORESCENCE");
deba@522
   134
        ++cnt;
deba@522
   135
      }
deba@522
   136
    }
deba@522
   137
    check((n == source ? cnt == 0 : cnt == 1), "INVALID ARBORESCENCE");
deba@522
   138
  }
deba@522
   139
deba@522
   140
  Digraph::ArcMap<bool> arborescence(digraph);
deba@522
   141
  check(mca.arborescenceValue() ==
deba@522
   142
        minCostArborescence(digraph, cost, source, arborescence),
deba@522
   143
        "WRONG FUNCTION");
deba@522
   144
deba@522
   145
  return 0;
deba@522
   146
}