test/preflow_test.cc
author Balazs Dezso <deba@inf.elte.hu>
Thu, 24 Jun 2010 09:27:53 +0200
changeset 891 bb70ad62c95f
parent 440 88ed40ad0d4f
child 689 86c49553fea5
child 923 30d5f950aa5f
permissions -rw-r--r--
Fix critical bug in preflow (#372)

The wrong transition between the bound decrease and highest active
heuristics caused the bug. The last node chosen in bound decrease mode
is used in the first iteration in highest active mode.
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;
alpar@389
    97
kpeter@585
    98
  preflow_test
kpeter@585
    99
    .capacityMap(cap)
kpeter@585
   100
    .flowMap(flow)
kpeter@585
   101
    .source(n)
kpeter@585
   102
    .target(n);
alpar@389
   103
alpar@389
   104
  preflow_test.init();
kpeter@392
   105
  preflow_test.init(cap);
alpar@389
   106
  preflow_test.startFirstPhase();
alpar@389
   107
  preflow_test.startSecondPhase();
alpar@389
   108
  preflow_test.run();
alpar@389
   109
  preflow_test.runMinCut();
alpar@389
   110
kpeter@585
   111
  v = const_preflow_test.flowValue();
kpeter@585
   112
  v = const_preflow_test.flow(e);
kpeter@585
   113
  const FlowMap& fm = const_preflow_test.flowMap();
kpeter@585
   114
  b = const_preflow_test.minCut(n);
kpeter@585
   115
  const_preflow_test.minCutMap(cut);
kpeter@585
   116
  
kpeter@585
   117
  ignore_unused_variable_warning(fm);
alpar@389
   118
}
alpar@389
   119
alpar@389
   120
int cutValue (const SmartDigraph& g,
alpar@389
   121
              const SmartDigraph::NodeMap<bool>& cut,
alpar@389
   122
              const SmartDigraph::ArcMap<int>& cap) {
alpar@389
   123
alpar@389
   124
  int c=0;
alpar@389
   125
  for(SmartDigraph::ArcIt e(g); e!=INVALID; ++e) {
alpar@389
   126
    if (cut[g.source(e)] && !cut[g.target(e)]) c+=cap[e];
alpar@389
   127
  }
alpar@389
   128
  return c;
alpar@389
   129
}
alpar@389
   130
alpar@389
   131
bool checkFlow(const SmartDigraph& g,
alpar@389
   132
               const SmartDigraph::ArcMap<int>& flow,
alpar@389
   133
               const SmartDigraph::ArcMap<int>& cap,
alpar@389
   134
               SmartDigraph::Node s, SmartDigraph::Node t) {
alpar@389
   135
alpar@389
   136
  for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
alpar@389
   137
    if (flow[e] < 0 || flow[e] > cap[e]) return false;
alpar@389
   138
  }
alpar@389
   139
alpar@389
   140
  for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
alpar@389
   141
    if (n == s || n == t) continue;
alpar@389
   142
    int sum = 0;
alpar@389
   143
    for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
alpar@389
   144
      sum += flow[e];
alpar@389
   145
    }
alpar@389
   146
    for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
alpar@389
   147
      sum -= flow[e];
alpar@389
   148
    }
alpar@389
   149
    if (sum != 0) return false;
alpar@389
   150
  }
alpar@389
   151
  return true;
alpar@389
   152
}
alpar@389
   153
alpar@389
   154
int main() {
alpar@389
   155
alpar@389
   156
  typedef SmartDigraph Digraph;
alpar@389
   157
alpar@389
   158
  typedef Digraph::Node Node;
alpar@389
   159
  typedef Digraph::NodeIt NodeIt;
alpar@389
   160
  typedef Digraph::ArcIt ArcIt;
alpar@389
   161
  typedef Digraph::ArcMap<int> CapMap;
alpar@389
   162
  typedef Digraph::ArcMap<int> FlowMap;
alpar@389
   163
  typedef Digraph::NodeMap<bool> CutMap;
alpar@389
   164
alpar@389
   165
  typedef Preflow<Digraph, CapMap> PType;
alpar@389
   166
alpar@389
   167
  Digraph g;
alpar@389
   168
  Node s, t;
alpar@389
   169
  CapMap cap(g);
alpar@423
   170
  std::istringstream input(test_lgf);
alpar@423
   171
  DigraphReader<Digraph>(g,input).
alpar@389
   172
    arcMap("capacity", cap).
alpar@389
   173
    node("source",s).
alpar@389
   174
    node("target",t).
alpar@389
   175
    run();
alpar@389
   176
alpar@389
   177
  PType preflow_test(g, cap, s, t);
alpar@389
   178
  preflow_test.run();
alpar@389
   179
alpar@389
   180
  check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
alpar@389
   181
        "The flow is not feasible.");
alpar@389
   182
alpar@389
   183
  CutMap min_cut(g);
alpar@389
   184
  preflow_test.minCutMap(min_cut);
alpar@389
   185
  int min_cut_value=cutValue(g,min_cut,cap);
alpar@389
   186
alpar@389
   187
  check(preflow_test.flowValue() == min_cut_value,
alpar@389
   188
        "The max flow value is not equal to the three min cut values.");
alpar@389
   189
alpar@389
   190
  FlowMap flow(g);
alpar@389
   191
  for(ArcIt e(g); e!=INVALID; ++e) flow[e] = preflow_test.flowMap()[e];
alpar@389
   192
alpar@389
   193
  int flow_value=preflow_test.flowValue();
alpar@389
   194
alpar@389
   195
  for(ArcIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e];
kpeter@392
   196
  preflow_test.init(flow);
alpar@389
   197
  preflow_test.startFirstPhase();
alpar@389
   198
alpar@389
   199
  CutMap min_cut1(g);
alpar@389
   200
  preflow_test.minCutMap(min_cut1);
alpar@389
   201
  min_cut_value=cutValue(g,min_cut1,cap);
alpar@389
   202
alpar@389
   203
  check(preflow_test.flowValue() == min_cut_value &&
alpar@389
   204
        min_cut_value == 2*flow_value,
alpar@389
   205
        "The max flow value or the min cut value is wrong.");
alpar@389
   206
alpar@389
   207
  preflow_test.startSecondPhase();
alpar@389
   208
alpar@389
   209
  check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
alpar@389
   210
        "The flow is not feasible.");
alpar@389
   211
alpar@389
   212
  CutMap min_cut2(g);
alpar@389
   213
  preflow_test.minCutMap(min_cut2);
alpar@389
   214
  min_cut_value=cutValue(g,min_cut2,cap);
alpar@389
   215
alpar@389
   216
  check(preflow_test.flowValue() == min_cut_value &&
alpar@389
   217
        min_cut_value == 2*flow_value,
alpar@389
   218
        "The max flow value or the three min cut values were not doubled");
alpar@389
   219
alpar@389
   220
alpar@389
   221
  preflow_test.flowMap(flow);
alpar@389
   222
alpar@389
   223
  NodeIt tmp1(g,s);
alpar@389
   224
  ++tmp1;
alpar@389
   225
  if ( tmp1 != INVALID ) s=tmp1;
alpar@389
   226
alpar@389
   227
  NodeIt tmp2(g,t);
alpar@389
   228
  ++tmp2;
alpar@389
   229
  if ( tmp2 != INVALID ) t=tmp2;
alpar@389
   230
alpar@389
   231
  preflow_test.source(s);
alpar@389
   232
  preflow_test.target(t);
alpar@389
   233
alpar@389
   234
  preflow_test.run();
alpar@389
   235
alpar@389
   236
  CutMap min_cut3(g);
alpar@389
   237
  preflow_test.minCutMap(min_cut3);
alpar@389
   238
  min_cut_value=cutValue(g,min_cut3,cap);
alpar@389
   239
alpar@389
   240
alpar@389
   241
  check(preflow_test.flowValue() == min_cut_value,
alpar@389
   242
        "The max flow value or the three min cut values are incorrect.");
alpar@389
   243
alpar@389
   244
  return 0;
alpar@389
   245
}