test/min_cost_arborescence_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 17 Apr 2009 18:04:36 +0200
changeset 601 e6927fe719e6
child 617 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@512
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
deba@512
     2
 *
deba@512
     3
 * This file is a part of LEMON, a generic C++ optimization library.
deba@512
     4
 *
deba@512
     5
 * Copyright (C) 2003-2008
deba@512
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@512
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@512
     8
 *
deba@512
     9
 * Permission to use, modify and distribute this software is granted
deba@512
    10
 * provided that this copyright notice appears in all copies. For
deba@512
    11
 * precise terms see the accompanying LICENSE file.
deba@512
    12
 *
deba@512
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@512
    14
 * express or implied, and with no claim as to its suitability for any
deba@512
    15
 * purpose.
deba@512
    16
 *
deba@512
    17
 */
deba@512
    18
deba@512
    19
#include <iostream>
deba@512
    20
#include <set>
deba@512
    21
#include <vector>
deba@512
    22
#include <iterator>
deba@512
    23
deba@512
    24
#include <lemon/smart_graph.h>
deba@512
    25
#include <lemon/min_cost_arborescence.h>
deba@512
    26
#include <lemon/lgf_reader.h>
deba@512
    27
deba@512
    28
#include "test_tools.h"
deba@512
    29
deba@512
    30
using namespace lemon;
deba@512
    31
using namespace std;
deba@512
    32
deba@512
    33
const char test_lgf[] =
deba@512
    34
  "@nodes\n"
deba@512
    35
  "label\n"
deba@512
    36
  "0\n"
deba@512
    37
  "1\n"
deba@512
    38
  "2\n"
deba@512
    39
  "3\n"
deba@512
    40
  "4\n"
deba@512
    41
  "5\n"
deba@512
    42
  "6\n"
deba@512
    43
  "7\n"
deba@512
    44
  "8\n"
deba@512
    45
  "9\n"
deba@512
    46
  "@arcs\n"
deba@512
    47
  "     label  cost\n"
deba@512
    48
  "1 8  0      107\n"
deba@512
    49
  "0 3  1      70\n"
deba@512
    50
  "2 1  2      46\n"
deba@512
    51
  "4 1  3      28\n"
deba@512
    52
  "4 4  4      91\n"
deba@512
    53
  "3 9  5      76\n"
deba@512
    54
  "9 8  6      61\n"
deba@512
    55
  "8 1  7      39\n"
deba@512
    56
  "9 8  8      74\n"
deba@512
    57
  "8 0  9      39\n"
deba@512
    58
  "4 3  10     45\n"
deba@512
    59
  "2 2  11     34\n"
deba@512
    60
  "0 1  12     100\n"
deba@512
    61
  "6 3  13     95\n"
deba@512
    62
  "4 1  14     22\n"
deba@512
    63
  "1 1  15     31\n"
deba@512
    64
  "7 2  16     51\n"
deba@512
    65
  "2 6  17     29\n"
deba@512
    66
  "8 3  18     115\n"
deba@512
    67
  "6 9  19     32\n"
deba@512
    68
  "1 1  20     60\n"
deba@512
    69
  "0 3  21     40\n"
deba@512
    70
  "@attributes\n"
deba@512
    71
  "source 0\n";
deba@512
    72
deba@512
    73
int main() {
deba@512
    74
  typedef SmartDigraph Digraph;
deba@512
    75
  DIGRAPH_TYPEDEFS(Digraph);
deba@512
    76
deba@512
    77
  typedef Digraph::ArcMap<double> CostMap;
deba@512
    78
deba@512
    79
  Digraph digraph;
deba@512
    80
  CostMap cost(digraph);
deba@512
    81
  Node source;
deba@512
    82
deba@512
    83
  std::istringstream is(test_lgf);
deba@512
    84
  digraphReader(digraph, is).
deba@512
    85
    arcMap("cost", cost).
deba@512
    86
    node("source", source).run();
deba@512
    87
deba@512
    88
  MinCostArborescence<Digraph, CostMap> mca(digraph, cost);
deba@512
    89
  mca.run(source);
deba@512
    90
deba@512
    91
  vector<pair<double, set<Node> > > dualSolution(mca.dualNum());
deba@512
    92
deba@512
    93
  for (int i = 0; i < mca.dualNum(); ++i) {
deba@512
    94
    dualSolution[i].first = mca.dualValue(i);
deba@512
    95
    for (MinCostArborescence<Digraph, CostMap>::DualIt it(mca, i);
deba@512
    96
         it != INVALID; ++it) {
deba@512
    97
      dualSolution[i].second.insert(it);
deba@512
    98
    }
deba@512
    99
  }
deba@512
   100
deba@512
   101
  for (ArcIt it(digraph); it != INVALID; ++it) {
deba@512
   102
    if (mca.reached(digraph.source(it))) {
deba@512
   103
      double sum = 0.0;
deba@512
   104
      for (int i = 0; i < int(dualSolution.size()); ++i) {
deba@512
   105
        if (dualSolution[i].second.find(digraph.target(it))
deba@512
   106
            != dualSolution[i].second.end() &&
deba@512
   107
            dualSolution[i].second.find(digraph.source(it))
deba@512
   108
            == dualSolution[i].second.end()) {
deba@512
   109
          sum += dualSolution[i].first;
deba@512
   110
        }
deba@512
   111
      }
deba@512
   112
      if (mca.arborescence(it)) {
deba@512
   113
        check(sum == cost[it], "INVALID DUAL");
deba@512
   114
      }
deba@512
   115
      check(sum <= cost[it], "INVALID DUAL");
deba@512
   116
    }
deba@512
   117
  }
deba@512
   118
deba@512
   119
deba@512
   120
  check(mca.dualValue() == mca.arborescenceValue(), "INVALID DUAL");
deba@512
   121
deba@512
   122
  check(mca.reached(source), "INVALID ARBORESCENCE");
deba@512
   123
  for (ArcIt a(digraph); a != INVALID; ++a) {
deba@512
   124
    check(!mca.reached(digraph.source(a)) ||
deba@512
   125
          mca.reached(digraph.target(a)), "INVALID ARBORESCENCE");
deba@512
   126
  }
deba@512
   127
deba@512
   128
  for (NodeIt n(digraph); n != INVALID; ++n) {
deba@512
   129
    if (!mca.reached(n)) continue;
deba@512
   130
    int cnt = 0;
deba@512
   131
    for (InArcIt a(digraph, n); a != INVALID; ++a) {
deba@512
   132
      if (mca.arborescence(a)) {
deba@512
   133
        check(mca.pred(n) == a, "INVALID ARBORESCENCE");
deba@512
   134
        ++cnt;
deba@512
   135
      }
deba@512
   136
    }
deba@512
   137
    check((n == source ? cnt == 0 : cnt == 1), "INVALID ARBORESCENCE");
deba@512
   138
  }
deba@512
   139
deba@512
   140
  Digraph::ArcMap<bool> arborescence(digraph);
deba@512
   141
  check(mca.arborescenceValue() ==
deba@512
   142
        minCostArborescence(digraph, cost, source, arborescence),
deba@512
   143
        "WRONG FUNCTION");
deba@512
   144
deba@512
   145
  return 0;
deba@512
   146
}