test/preflow_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 877 141f9c0db4a3
parent 923 30d5f950aa5f
child 1008 d216e1c8b3fa
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
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@877
     5
 * Copyright (C) 2003-2010
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@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);
kpeter@585
   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);
alpar@877
   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@923
   159
void initFlowTest()
alpar@923
   160
{
alpar@923
   161
  DIGRAPH_TYPEDEFS(SmartDigraph);
alpar@923
   162
  
alpar@923
   163
  SmartDigraph g;
alpar@923
   164
  SmartDigraph::ArcMap<int> cap(g),iflow(g);
alpar@923
   165
  Node s=g.addNode(); Node t=g.addNode();
alpar@923
   166
  Node n1=g.addNode(); Node n2=g.addNode();
alpar@923
   167
  Arc a;
alpar@923
   168
  a=g.addArc(s,n1); cap[a]=20; iflow[a]=20;
alpar@923
   169
  a=g.addArc(n1,n2); cap[a]=10; iflow[a]=0;
alpar@923
   170
  a=g.addArc(n2,t); cap[a]=20; iflow[a]=0;
alpar@923
   171
alpar@923
   172
  Preflow<SmartDigraph> pre(g,cap,s,t);
alpar@923
   173
  pre.init(iflow);
alpar@923
   174
  pre.startFirstPhase();
alpar@923
   175
  check(pre.flowValue() == 10, "The incorrect max flow value.");
alpar@923
   176
  check(pre.minCut(s), "Wrong min cut (Node s).");
alpar@923
   177
  check(pre.minCut(n1), "Wrong min cut (Node n1).");
alpar@923
   178
  check(!pre.minCut(n2), "Wrong min cut (Node n2).");
alpar@923
   179
  check(!pre.minCut(t), "Wrong min cut (Node t).");
alpar@923
   180
}
alpar@923
   181
alpar@923
   182
alpar@389
   183
int main() {
alpar@389
   184
alpar@389
   185
  typedef SmartDigraph Digraph;
alpar@389
   186
alpar@389
   187
  typedef Digraph::Node Node;
alpar@389
   188
  typedef Digraph::NodeIt NodeIt;
alpar@389
   189
  typedef Digraph::ArcIt ArcIt;
alpar@389
   190
  typedef Digraph::ArcMap<int> CapMap;
alpar@389
   191
  typedef Digraph::ArcMap<int> FlowMap;
alpar@389
   192
  typedef Digraph::NodeMap<bool> CutMap;
alpar@389
   193
alpar@389
   194
  typedef Preflow<Digraph, CapMap> PType;
alpar@389
   195
alpar@389
   196
  Digraph g;
alpar@389
   197
  Node s, t;
alpar@389
   198
  CapMap cap(g);
alpar@423
   199
  std::istringstream input(test_lgf);
alpar@423
   200
  DigraphReader<Digraph>(g,input).
alpar@389
   201
    arcMap("capacity", cap).
alpar@389
   202
    node("source",s).
alpar@389
   203
    node("target",t).
alpar@389
   204
    run();
alpar@389
   205
alpar@389
   206
  PType preflow_test(g, cap, s, t);
alpar@389
   207
  preflow_test.run();
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_cut(g);
alpar@389
   213
  preflow_test.minCutMap(min_cut);
alpar@389
   214
  int min_cut_value=cutValue(g,min_cut,cap);
alpar@389
   215
alpar@389
   216
  check(preflow_test.flowValue() == min_cut_value,
alpar@389
   217
        "The max flow value is not equal to the three min cut values.");
alpar@389
   218
alpar@389
   219
  FlowMap flow(g);
alpar@389
   220
  for(ArcIt e(g); e!=INVALID; ++e) flow[e] = preflow_test.flowMap()[e];
alpar@389
   221
alpar@389
   222
  int flow_value=preflow_test.flowValue();
alpar@389
   223
alpar@389
   224
  for(ArcIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e];
kpeter@392
   225
  preflow_test.init(flow);
alpar@389
   226
  preflow_test.startFirstPhase();
alpar@389
   227
alpar@389
   228
  CutMap min_cut1(g);
alpar@389
   229
  preflow_test.minCutMap(min_cut1);
alpar@389
   230
  min_cut_value=cutValue(g,min_cut1,cap);
alpar@389
   231
alpar@389
   232
  check(preflow_test.flowValue() == min_cut_value &&
alpar@389
   233
        min_cut_value == 2*flow_value,
alpar@389
   234
        "The max flow value or the min cut value is wrong.");
alpar@389
   235
alpar@389
   236
  preflow_test.startSecondPhase();
alpar@389
   237
alpar@389
   238
  check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
alpar@389
   239
        "The flow is not feasible.");
alpar@389
   240
alpar@389
   241
  CutMap min_cut2(g);
alpar@389
   242
  preflow_test.minCutMap(min_cut2);
alpar@389
   243
  min_cut_value=cutValue(g,min_cut2,cap);
alpar@389
   244
alpar@389
   245
  check(preflow_test.flowValue() == min_cut_value &&
alpar@389
   246
        min_cut_value == 2*flow_value,
alpar@389
   247
        "The max flow value or the three min cut values were not doubled");
alpar@389
   248
alpar@389
   249
alpar@389
   250
  preflow_test.flowMap(flow);
alpar@389
   251
alpar@389
   252
  NodeIt tmp1(g,s);
alpar@389
   253
  ++tmp1;
alpar@389
   254
  if ( tmp1 != INVALID ) s=tmp1;
alpar@389
   255
alpar@389
   256
  NodeIt tmp2(g,t);
alpar@389
   257
  ++tmp2;
alpar@389
   258
  if ( tmp2 != INVALID ) t=tmp2;
alpar@389
   259
alpar@389
   260
  preflow_test.source(s);
alpar@389
   261
  preflow_test.target(t);
alpar@389
   262
alpar@389
   263
  preflow_test.run();
alpar@389
   264
alpar@389
   265
  CutMap min_cut3(g);
alpar@389
   266
  preflow_test.minCutMap(min_cut3);
alpar@389
   267
  min_cut_value=cutValue(g,min_cut3,cap);
alpar@389
   268
alpar@389
   269
alpar@389
   270
  check(preflow_test.flowValue() == min_cut_value,
alpar@389
   271
        "The max flow value or the three min cut values are incorrect.");
alpar@389
   272
alpar@923
   273
  initFlowTest();
alpar@923
   274
  
alpar@389
   275
  return 0;
alpar@389
   276
}