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