test/preflow_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Thu, 12 Nov 2009 23:26:13 +0100
changeset 806 fa6f37d7a25b
parent 585 65fbcf2f978a
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@389
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@389
     2
 *
alpar@389
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@389
     4
 *
alpar@440
     5
 * Copyright (C) 2003-2009
alpar@389
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@389
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@389
     8
 *
alpar@389
     9
 * Permission to use, modify and distribute this software is granted
alpar@389
    10
 * provided that this copyright notice appears in all copies. For
alpar@389
    11
 * precise terms see the accompanying LICENSE file.
alpar@389
    12
 *
alpar@389
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@389
    14
 * express or implied, and with no claim as to its suitability for any
alpar@389
    15
 * purpose.
alpar@389
    16
 *
alpar@389
    17
 */
alpar@389
    18
alpar@423
    19
#include <iostream>
alpar@389
    20
alpar@389
    21
#include "test_tools.h"
alpar@389
    22
#include <lemon/smart_graph.h>
alpar@389
    23
#include <lemon/preflow.h>
alpar@389
    24
#include <lemon/concepts/digraph.h>
alpar@389
    25
#include <lemon/concepts/maps.h>
alpar@389
    26
#include <lemon/lgf_reader.h>
kpeter@394
    27
#include <lemon/elevator.h>
alpar@389
    28
alpar@389
    29
using namespace lemon;
alpar@389
    30
alpar@423
    31
char test_lgf[] =
alpar@423
    32
  "@nodes\n"
alpar@423
    33
  "label\n"
alpar@423
    34
  "0\n"
alpar@423
    35
  "1\n"
alpar@423
    36
  "2\n"
alpar@423
    37
  "3\n"
alpar@423
    38
  "4\n"
alpar@423
    39
  "5\n"
alpar@423
    40
  "6\n"
alpar@423
    41
  "7\n"
alpar@423
    42
  "8\n"
alpar@423
    43
  "9\n"
alpar@423
    44
  "@arcs\n"
alpar@423
    45
  "    label capacity\n"
alpar@423
    46
  "0 1 0     20\n"
alpar@423
    47
  "0 2 1     0\n"
alpar@423
    48
  "1 1 2     3\n"
alpar@423
    49
  "1 2 3     8\n"
alpar@423
    50
  "1 3 4     8\n"
alpar@423
    51
  "2 5 5     5\n"
alpar@423
    52
  "3 2 6     5\n"
alpar@423
    53
  "3 5 7     5\n"
alpar@423
    54
  "3 6 8     5\n"
alpar@423
    55
  "4 3 9     3\n"
alpar@423
    56
  "5 7 10    3\n"
alpar@423
    57
  "5 6 11    10\n"
alpar@423
    58
  "5 8 12    10\n"
alpar@423
    59
  "6 8 13    8\n"
alpar@423
    60
  "8 9 14    20\n"
alpar@423
    61
  "8 1 15    5\n"
alpar@423
    62
  "9 5 16    5\n"
alpar@423
    63
  "@attributes\n"
alpar@423
    64
  "source 1\n"
alpar@423
    65
  "target 8\n";
alpar@423
    66
kpeter@394
    67
void checkPreflowCompile()
alpar@389
    68
{
alpar@389
    69
  typedef int VType;
alpar@389
    70
  typedef concepts::Digraph Digraph;
alpar@389
    71
alpar@389
    72
  typedef Digraph::Node Node;
alpar@389
    73
  typedef Digraph::Arc Arc;
alpar@389
    74
  typedef concepts::ReadMap<Arc,VType> CapMap;
alpar@389
    75
  typedef concepts::ReadWriteMap<Arc,VType> FlowMap;
alpar@389
    76
  typedef concepts::WriteMap<Node,bool> CutMap;
alpar@389
    77
kpeter@394
    78
  typedef Elevator<Digraph, Digraph::Node> Elev;
kpeter@394
    79
  typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
kpeter@394
    80
alpar@389
    81
  Digraph g;
alpar@389
    82
  Node n;
alpar@389
    83
  Arc e;
alpar@389
    84
  CapMap cap;
alpar@389
    85
  FlowMap flow;
alpar@389
    86
  CutMap cut;
kpeter@585
    87
  VType v;
kpeter@585
    88
  bool b;
alpar@389
    89
kpeter@585
    90
  typedef Preflow<Digraph, CapMap>
kpeter@585
    91
            ::SetFlowMap<FlowMap>
kpeter@585
    92
            ::SetElevator<Elev>
kpeter@585
    93
            ::SetStandardElevator<LinkedElev>
kpeter@585
    94
            ::Create PreflowType;
kpeter@585
    95
  PreflowType preflow_test(g, cap, n, n);
kpeter@585
    96
  const PreflowType& const_preflow_test = preflow_test;
kpeter@689
    97
  
kpeter@689
    98
  const PreflowType::Elevator& elev = const_preflow_test.elevator();
kpeter@689
    99
  preflow_test.elevator(const_cast<PreflowType::Elevator&>(elev));
kpeter@689
   100
  PreflowType::Tolerance tol = const_preflow_test.tolerance();
kpeter@689
   101
  preflow_test.tolerance(tol);
alpar@389
   102
kpeter@585
   103
  preflow_test
kpeter@585
   104
    .capacityMap(cap)
kpeter@585
   105
    .flowMap(flow)
kpeter@585
   106
    .source(n)
kpeter@585
   107
    .target(n);
alpar@389
   108
alpar@389
   109
  preflow_test.init();
kpeter@392
   110
  preflow_test.init(cap);
alpar@389
   111
  preflow_test.startFirstPhase();
alpar@389
   112
  preflow_test.startSecondPhase();
alpar@389
   113
  preflow_test.run();
alpar@389
   114
  preflow_test.runMinCut();
alpar@389
   115
kpeter@585
   116
  v = const_preflow_test.flowValue();
kpeter@585
   117
  v = const_preflow_test.flow(e);
kpeter@585
   118
  const FlowMap& fm = const_preflow_test.flowMap();
kpeter@585
   119
  b = const_preflow_test.minCut(n);
kpeter@585
   120
  const_preflow_test.minCutMap(cut);
kpeter@585
   121
  
kpeter@585
   122
  ignore_unused_variable_warning(fm);
alpar@389
   123
}
alpar@389
   124
alpar@389
   125
int cutValue (const SmartDigraph& g,
alpar@389
   126
              const SmartDigraph::NodeMap<bool>& cut,
alpar@389
   127
              const SmartDigraph::ArcMap<int>& cap) {
alpar@389
   128
alpar@389
   129
  int c=0;
alpar@389
   130
  for(SmartDigraph::ArcIt e(g); e!=INVALID; ++e) {
alpar@389
   131
    if (cut[g.source(e)] && !cut[g.target(e)]) c+=cap[e];
alpar@389
   132
  }
alpar@389
   133
  return c;
alpar@389
   134
}
alpar@389
   135
alpar@389
   136
bool checkFlow(const SmartDigraph& g,
alpar@389
   137
               const SmartDigraph::ArcMap<int>& flow,
alpar@389
   138
               const SmartDigraph::ArcMap<int>& cap,
alpar@389
   139
               SmartDigraph::Node s, SmartDigraph::Node t) {
alpar@389
   140
alpar@389
   141
  for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
alpar@389
   142
    if (flow[e] < 0 || flow[e] > cap[e]) return false;
alpar@389
   143
  }
alpar@389
   144
alpar@389
   145
  for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
alpar@389
   146
    if (n == s || n == t) continue;
alpar@389
   147
    int sum = 0;
alpar@389
   148
    for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
alpar@389
   149
      sum += flow[e];
alpar@389
   150
    }
alpar@389
   151
    for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
alpar@389
   152
      sum -= flow[e];
alpar@389
   153
    }
alpar@389
   154
    if (sum != 0) return false;
alpar@389
   155
  }
alpar@389
   156
  return true;
alpar@389
   157
}
alpar@389
   158
alpar@389
   159
int main() {
alpar@389
   160
alpar@389
   161
  typedef SmartDigraph Digraph;
alpar@389
   162
alpar@389
   163
  typedef Digraph::Node Node;
alpar@389
   164
  typedef Digraph::NodeIt NodeIt;
alpar@389
   165
  typedef Digraph::ArcIt ArcIt;
alpar@389
   166
  typedef Digraph::ArcMap<int> CapMap;
alpar@389
   167
  typedef Digraph::ArcMap<int> FlowMap;
alpar@389
   168
  typedef Digraph::NodeMap<bool> CutMap;
alpar@389
   169
alpar@389
   170
  typedef Preflow<Digraph, CapMap> PType;
alpar@389
   171
alpar@389
   172
  Digraph g;
alpar@389
   173
  Node s, t;
alpar@389
   174
  CapMap cap(g);
alpar@423
   175
  std::istringstream input(test_lgf);
alpar@423
   176
  DigraphReader<Digraph>(g,input).
alpar@389
   177
    arcMap("capacity", cap).
alpar@389
   178
    node("source",s).
alpar@389
   179
    node("target",t).
alpar@389
   180
    run();
alpar@389
   181
alpar@389
   182
  PType preflow_test(g, cap, s, t);
alpar@389
   183
  preflow_test.run();
alpar@389
   184
alpar@389
   185
  check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
alpar@389
   186
        "The flow is not feasible.");
alpar@389
   187
alpar@389
   188
  CutMap min_cut(g);
alpar@389
   189
  preflow_test.minCutMap(min_cut);
alpar@389
   190
  int min_cut_value=cutValue(g,min_cut,cap);
alpar@389
   191
alpar@389
   192
  check(preflow_test.flowValue() == min_cut_value,
alpar@389
   193
        "The max flow value is not equal to the three min cut values.");
alpar@389
   194
alpar@389
   195
  FlowMap flow(g);
alpar@389
   196
  for(ArcIt e(g); e!=INVALID; ++e) flow[e] = preflow_test.flowMap()[e];
alpar@389
   197
alpar@389
   198
  int flow_value=preflow_test.flowValue();
alpar@389
   199
alpar@389
   200
  for(ArcIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e];
kpeter@392
   201
  preflow_test.init(flow);
alpar@389
   202
  preflow_test.startFirstPhase();
alpar@389
   203
alpar@389
   204
  CutMap min_cut1(g);
alpar@389
   205
  preflow_test.minCutMap(min_cut1);
alpar@389
   206
  min_cut_value=cutValue(g,min_cut1,cap);
alpar@389
   207
alpar@389
   208
  check(preflow_test.flowValue() == min_cut_value &&
alpar@389
   209
        min_cut_value == 2*flow_value,
alpar@389
   210
        "The max flow value or the min cut value is wrong.");
alpar@389
   211
alpar@389
   212
  preflow_test.startSecondPhase();
alpar@389
   213
alpar@389
   214
  check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
alpar@389
   215
        "The flow is not feasible.");
alpar@389
   216
alpar@389
   217
  CutMap min_cut2(g);
alpar@389
   218
  preflow_test.minCutMap(min_cut2);
alpar@389
   219
  min_cut_value=cutValue(g,min_cut2,cap);
alpar@389
   220
alpar@389
   221
  check(preflow_test.flowValue() == min_cut_value &&
alpar@389
   222
        min_cut_value == 2*flow_value,
alpar@389
   223
        "The max flow value or the three min cut values were not doubled");
alpar@389
   224
alpar@389
   225
alpar@389
   226
  preflow_test.flowMap(flow);
alpar@389
   227
alpar@389
   228
  NodeIt tmp1(g,s);
alpar@389
   229
  ++tmp1;
alpar@389
   230
  if ( tmp1 != INVALID ) s=tmp1;
alpar@389
   231
alpar@389
   232
  NodeIt tmp2(g,t);
alpar@389
   233
  ++tmp2;
alpar@389
   234
  if ( tmp2 != INVALID ) t=tmp2;
alpar@389
   235
alpar@389
   236
  preflow_test.source(s);
alpar@389
   237
  preflow_test.target(t);
alpar@389
   238
alpar@389
   239
  preflow_test.run();
alpar@389
   240
alpar@389
   241
  CutMap min_cut3(g);
alpar@389
   242
  preflow_test.minCutMap(min_cut3);
alpar@389
   243
  min_cut_value=cutValue(g,min_cut3,cap);
alpar@389
   244
alpar@389
   245
alpar@389
   246
  check(preflow_test.flowValue() == min_cut_value,
alpar@389
   247
        "The max flow value or the three min cut values are incorrect.");
alpar@389
   248
alpar@389
   249
  return 0;
alpar@389
   250
}