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