test/circulation_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Thu, 12 Nov 2009 23:26:13 +0100
changeset 806 fa6f37d7a25b
parent 611 85cb3aa71cce
child 877 141f9c0db4a3
permissions -rw-r--r--
Entirely rework CapacityScaling (#180)

- Use the new interface similarly to NetworkSimplex.
- Rework the implementation using an efficient internal structure
for handling the residual network. This improvement made the
code much faster (up to 2-5 times faster on large graphs).
- Handle GEQ supply type (LEQ is not supported).
- Handle negative costs for arcs of finite capacity.
(Note that this algorithm cannot handle arcs of negative cost
and infinite upper bound, thus it returns UNBOUNDED if such
an arc exists.)
- Extend the documentation.
alpar@400
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@400
     2
 *
alpar@400
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@400
     4
 *
alpar@440
     5
 * Copyright (C) 2003-2009
alpar@400
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@400
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@400
     8
 *
alpar@400
     9
 * Permission to use, modify and distribute this software is granted
alpar@400
    10
 * provided that this copyright notice appears in all copies. For
alpar@400
    11
 * precise terms see the accompanying LICENSE file.
alpar@400
    12
 *
alpar@400
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@400
    14
 * express or implied, and with no claim as to its suitability for any
alpar@400
    15
 * purpose.
alpar@400
    16
 *
alpar@400
    17
 */
alpar@400
    18
alpar@400
    19
#include <iostream>
alpar@400
    20
alpar@400
    21
#include "test_tools.h"
alpar@400
    22
#include <lemon/list_graph.h>
alpar@400
    23
#include <lemon/circulation.h>
alpar@400
    24
#include <lemon/lgf_reader.h>
kpeter@403
    25
#include <lemon/concepts/digraph.h>
kpeter@403
    26
#include <lemon/concepts/maps.h>
alpar@400
    27
alpar@400
    28
using namespace lemon;
alpar@400
    29
alpar@400
    30
char test_lgf[] =
alpar@400
    31
  "@nodes\n"
kpeter@403
    32
  "label\n"
kpeter@403
    33
  "0\n"
kpeter@403
    34
  "1\n"
kpeter@403
    35
  "2\n"
kpeter@403
    36
  "3\n"
kpeter@403
    37
  "4\n"
kpeter@403
    38
  "5\n"
kpeter@403
    39
  "@arcs\n"
kpeter@403
    40
  "     lcap  ucap\n"
kpeter@403
    41
  "0 1  2  10\n"
kpeter@403
    42
  "0 2  2  6\n"
kpeter@403
    43
  "1 3  4  7\n"
kpeter@403
    44
  "1 4  0  5\n"
kpeter@403
    45
  "2 4  1  3\n"
kpeter@403
    46
  "3 5  3  8\n"
kpeter@403
    47
  "4 5  3  7\n"
alpar@400
    48
  "@attributes\n"
kpeter@403
    49
  "source 0\n"
kpeter@403
    50
  "sink   5\n";
kpeter@403
    51
kpeter@403
    52
void checkCirculationCompile()
kpeter@403
    53
{
kpeter@403
    54
  typedef int VType;
kpeter@403
    55
  typedef concepts::Digraph Digraph;
kpeter@403
    56
kpeter@403
    57
  typedef Digraph::Node Node;
kpeter@403
    58
  typedef Digraph::Arc Arc;
kpeter@403
    59
  typedef concepts::ReadMap<Arc,VType> CapMap;
kpeter@610
    60
  typedef concepts::ReadMap<Node,VType> SupplyMap;
kpeter@403
    61
  typedef concepts::ReadWriteMap<Arc,VType> FlowMap;
kpeter@403
    62
  typedef concepts::WriteMap<Node,bool> BarrierMap;
kpeter@403
    63
kpeter@403
    64
  typedef Elevator<Digraph, Digraph::Node> Elev;
kpeter@403
    65
  typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
kpeter@403
    66
kpeter@403
    67
  Digraph g;
kpeter@403
    68
  Node n;
kpeter@403
    69
  Arc a;
kpeter@403
    70
  CapMap lcap, ucap;
kpeter@610
    71
  SupplyMap supply;
kpeter@403
    72
  FlowMap flow;
kpeter@403
    73
  BarrierMap bar;
kpeter@585
    74
  VType v;
kpeter@585
    75
  bool b;
kpeter@403
    76
alpar@611
    77
  typedef Circulation<Digraph, CapMap, CapMap, SupplyMap>
kpeter@585
    78
            ::SetFlowMap<FlowMap>
kpeter@585
    79
            ::SetElevator<Elev>
kpeter@585
    80
            ::SetStandardElevator<LinkedElev>
kpeter@585
    81
            ::Create CirculationType;
alpar@611
    82
  CirculationType circ_test(g, lcap, ucap, supply);
kpeter@585
    83
  const CirculationType& const_circ_test = circ_test;
kpeter@585
    84
   
kpeter@585
    85
  circ_test
alpar@611
    86
    .lowerMap(lcap)
alpar@611
    87
    .upperMap(ucap)
alpar@611
    88
    .supplyMap(supply)
kpeter@585
    89
    .flowMap(flow);
kpeter@689
    90
  
kpeter@689
    91
  const CirculationType::Elevator& elev = const_circ_test.elevator();
kpeter@689
    92
  circ_test.elevator(const_cast<CirculationType::Elevator&>(elev));
kpeter@689
    93
  CirculationType::Tolerance tol = const_circ_test.tolerance();
kpeter@689
    94
  circ_test.tolerance(tol);
kpeter@403
    95
kpeter@403
    96
  circ_test.init();
kpeter@403
    97
  circ_test.greedyInit();
kpeter@403
    98
  circ_test.start();
kpeter@403
    99
  circ_test.run();
kpeter@403
   100
kpeter@585
   101
  v = const_circ_test.flow(a);
kpeter@585
   102
  const FlowMap& fm = const_circ_test.flowMap();
kpeter@585
   103
  b = const_circ_test.barrier(n);
kpeter@585
   104
  const_circ_test.barrierMap(bar);
kpeter@585
   105
  
kpeter@585
   106
  ignore_unused_variable_warning(fm);
kpeter@403
   107
}
kpeter@403
   108
kpeter@403
   109
template <class G, class LM, class UM, class DM>
kpeter@403
   110
void checkCirculation(const G& g, const LM& lm, const UM& um,
kpeter@403
   111
                      const DM& dm, bool find)
kpeter@403
   112
{
kpeter@403
   113
  Circulation<G, LM, UM, DM> circ(g, lm, um, dm);
kpeter@403
   114
  bool ret = circ.run();
kpeter@403
   115
  if (find) {
kpeter@403
   116
    check(ret, "A feasible solution should have been found.");
kpeter@403
   117
    check(circ.checkFlow(), "The found flow is corrupt.");
kpeter@403
   118
    check(!circ.checkBarrier(), "A barrier should not have been found.");
kpeter@403
   119
  } else {
kpeter@403
   120
    check(!ret, "A feasible solution should not have been found.");
kpeter@403
   121
    check(circ.checkBarrier(), "The found barrier is corrupt.");
kpeter@403
   122
  }
kpeter@403
   123
}
alpar@400
   124
alpar@400
   125
int main (int, char*[])
alpar@400
   126
{
kpeter@403
   127
  typedef ListDigraph Digraph;
kpeter@403
   128
  DIGRAPH_TYPEDEFS(Digraph);
alpar@400
   129
kpeter@403
   130
  Digraph g;
kpeter@403
   131
  IntArcMap lo(g), up(g);
kpeter@403
   132
  IntNodeMap delta(g, 0);
kpeter@403
   133
  Node s, t;
alpar@400
   134
kpeter@403
   135
  std::istringstream input(test_lgf);
kpeter@403
   136
  DigraphReader<Digraph>(g,input).
kpeter@403
   137
    arcMap("lcap", lo).
kpeter@403
   138
    arcMap("ucap", up).
kpeter@403
   139
    node("source",s).
kpeter@403
   140
    node("sink",t).
kpeter@403
   141
    run();
alpar@400
   142
kpeter@403
   143
  delta[s] = 7; delta[t] = -7;
kpeter@403
   144
  checkCirculation(g, lo, up, delta, true);
alpar@400
   145
kpeter@403
   146
  delta[s] = 13; delta[t] = -13;
kpeter@403
   147
  checkCirculation(g, lo, up, delta, true);
kpeter@403
   148
kpeter@403
   149
  delta[s] = 6; delta[t] = -6;
kpeter@403
   150
  checkCirculation(g, lo, up, delta, false);
kpeter@403
   151
kpeter@403
   152
  delta[s] = 14; delta[t] = -14;
kpeter@403
   153
  checkCirculation(g, lo, up, delta, false);
kpeter@403
   154
kpeter@403
   155
  delta[s] = 7; delta[t] = -13;
kpeter@403
   156
  checkCirculation(g, lo, up, delta, true);
kpeter@403
   157
kpeter@403
   158
  delta[s] = 5; delta[t] = -15;
kpeter@403
   159
  checkCirculation(g, lo, up, delta, true);
kpeter@403
   160
kpeter@403
   161
  delta[s] = 10; delta[t] = -11;
kpeter@403
   162
  checkCirculation(g, lo, up, delta, true);
kpeter@403
   163
kpeter@403
   164
  delta[s] = 11; delta[t] = -10;
kpeter@403
   165
  checkCirculation(g, lo, up, delta, false);
kpeter@403
   166
kpeter@403
   167
  return 0;
alpar@400
   168
}