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