test/preflow_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 17 Apr 2009 18:04:36 +0200
changeset 656 e6927fe719e6
parent 442 ff48c2738fb2
child 632 65fbcf2f978a
permissions -rw-r--r--
Support >= and <= constraints in NetworkSimplex (#219, #234)

By default the same inequality constraints are supported as by
Circulation (the GEQ form), but the LEQ form can also be selected
using the problemType() function.

The documentation of the min. cost flow module is reworked and
extended with important notes and explanations about the different
variants of the problem and about the dual solution and optimality
conditions.
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;
alpar@404
    87
kpeter@409
    88
  Preflow<Digraph, CapMap>
kpeter@409
    89
    ::SetFlowMap<FlowMap>
kpeter@409
    90
    ::SetElevator<Elev>
kpeter@409
    91
    ::SetStandardElevator<LinkedElev>
kpeter@409
    92
    ::Create preflow_test(g,cap,n,n);
alpar@404
    93
alpar@404
    94
  preflow_test.capacityMap(cap);
alpar@404
    95
  flow = preflow_test.flowMap();
alpar@404
    96
  preflow_test.flowMap(flow);
alpar@404
    97
  preflow_test.source(n);
alpar@404
    98
  preflow_test.target(n);
alpar@404
    99
alpar@404
   100
  preflow_test.init();
kpeter@407
   101
  preflow_test.init(cap);
alpar@404
   102
  preflow_test.startFirstPhase();
alpar@404
   103
  preflow_test.startSecondPhase();
alpar@404
   104
  preflow_test.run();
alpar@404
   105
  preflow_test.runMinCut();
alpar@404
   106
alpar@404
   107
  preflow_test.flowValue();
alpar@404
   108
  preflow_test.minCut(n);
alpar@404
   109
  preflow_test.minCutMap(cut);
alpar@404
   110
  preflow_test.flow(e);
alpar@404
   111
alpar@404
   112
}
alpar@404
   113
alpar@404
   114
int cutValue (const SmartDigraph& g,
alpar@404
   115
              const SmartDigraph::NodeMap<bool>& cut,
alpar@404
   116
              const SmartDigraph::ArcMap<int>& cap) {
alpar@404
   117
alpar@404
   118
  int c=0;
alpar@404
   119
  for(SmartDigraph::ArcIt e(g); e!=INVALID; ++e) {
alpar@404
   120
    if (cut[g.source(e)] && !cut[g.target(e)]) c+=cap[e];
alpar@404
   121
  }
alpar@404
   122
  return c;
alpar@404
   123
}
alpar@404
   124
alpar@404
   125
bool checkFlow(const SmartDigraph& g,
alpar@404
   126
               const SmartDigraph::ArcMap<int>& flow,
alpar@404
   127
               const SmartDigraph::ArcMap<int>& cap,
alpar@404
   128
               SmartDigraph::Node s, SmartDigraph::Node t) {
alpar@404
   129
alpar@404
   130
  for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
alpar@404
   131
    if (flow[e] < 0 || flow[e] > cap[e]) return false;
alpar@404
   132
  }
alpar@404
   133
alpar@404
   134
  for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
alpar@404
   135
    if (n == s || n == t) continue;
alpar@404
   136
    int sum = 0;
alpar@404
   137
    for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
alpar@404
   138
      sum += flow[e];
alpar@404
   139
    }
alpar@404
   140
    for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
alpar@404
   141
      sum -= flow[e];
alpar@404
   142
    }
alpar@404
   143
    if (sum != 0) return false;
alpar@404
   144
  }
alpar@404
   145
  return true;
alpar@404
   146
}
alpar@404
   147
alpar@404
   148
int main() {
alpar@404
   149
alpar@404
   150
  typedef SmartDigraph Digraph;
alpar@404
   151
alpar@404
   152
  typedef Digraph::Node Node;
alpar@404
   153
  typedef Digraph::NodeIt NodeIt;
alpar@404
   154
  typedef Digraph::ArcIt ArcIt;
alpar@404
   155
  typedef Digraph::ArcMap<int> CapMap;
alpar@404
   156
  typedef Digraph::ArcMap<int> FlowMap;
alpar@404
   157
  typedef Digraph::NodeMap<bool> CutMap;
alpar@404
   158
alpar@404
   159
  typedef Preflow<Digraph, CapMap> PType;
alpar@404
   160
alpar@404
   161
  Digraph g;
alpar@404
   162
  Node s, t;
alpar@404
   163
  CapMap cap(g);
alpar@442
   164
  std::istringstream input(test_lgf);
alpar@442
   165
  DigraphReader<Digraph>(g,input).
alpar@404
   166
    arcMap("capacity", cap).
alpar@404
   167
    node("source",s).
alpar@404
   168
    node("target",t).
alpar@404
   169
    run();
alpar@404
   170
alpar@404
   171
  PType preflow_test(g, cap, s, t);
alpar@404
   172
  preflow_test.run();
alpar@404
   173
alpar@404
   174
  check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
alpar@404
   175
        "The flow is not feasible.");
alpar@404
   176
alpar@404
   177
  CutMap min_cut(g);
alpar@404
   178
  preflow_test.minCutMap(min_cut);
alpar@404
   179
  int min_cut_value=cutValue(g,min_cut,cap);
alpar@404
   180
alpar@404
   181
  check(preflow_test.flowValue() == min_cut_value,
alpar@404
   182
        "The max flow value is not equal to the three min cut values.");
alpar@404
   183
alpar@404
   184
  FlowMap flow(g);
alpar@404
   185
  for(ArcIt e(g); e!=INVALID; ++e) flow[e] = preflow_test.flowMap()[e];
alpar@404
   186
alpar@404
   187
  int flow_value=preflow_test.flowValue();
alpar@404
   188
alpar@404
   189
  for(ArcIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e];
kpeter@407
   190
  preflow_test.init(flow);
alpar@404
   191
  preflow_test.startFirstPhase();
alpar@404
   192
alpar@404
   193
  CutMap min_cut1(g);
alpar@404
   194
  preflow_test.minCutMap(min_cut1);
alpar@404
   195
  min_cut_value=cutValue(g,min_cut1,cap);
alpar@404
   196
alpar@404
   197
  check(preflow_test.flowValue() == min_cut_value &&
alpar@404
   198
        min_cut_value == 2*flow_value,
alpar@404
   199
        "The max flow value or the min cut value is wrong.");
alpar@404
   200
alpar@404
   201
  preflow_test.startSecondPhase();
alpar@404
   202
alpar@404
   203
  check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
alpar@404
   204
        "The flow is not feasible.");
alpar@404
   205
alpar@404
   206
  CutMap min_cut2(g);
alpar@404
   207
  preflow_test.minCutMap(min_cut2);
alpar@404
   208
  min_cut_value=cutValue(g,min_cut2,cap);
alpar@404
   209
alpar@404
   210
  check(preflow_test.flowValue() == min_cut_value &&
alpar@404
   211
        min_cut_value == 2*flow_value,
alpar@404
   212
        "The max flow value or the three min cut values were not doubled");
alpar@404
   213
alpar@404
   214
alpar@404
   215
  preflow_test.flowMap(flow);
alpar@404
   216
alpar@404
   217
  NodeIt tmp1(g,s);
alpar@404
   218
  ++tmp1;
alpar@404
   219
  if ( tmp1 != INVALID ) s=tmp1;
alpar@404
   220
alpar@404
   221
  NodeIt tmp2(g,t);
alpar@404
   222
  ++tmp2;
alpar@404
   223
  if ( tmp2 != INVALID ) t=tmp2;
alpar@404
   224
alpar@404
   225
  preflow_test.source(s);
alpar@404
   226
  preflow_test.target(t);
alpar@404
   227
alpar@404
   228
  preflow_test.run();
alpar@404
   229
alpar@404
   230
  CutMap min_cut3(g);
alpar@404
   231
  preflow_test.minCutMap(min_cut3);
alpar@404
   232
  min_cut_value=cutValue(g,min_cut3,cap);
alpar@404
   233
alpar@404
   234
alpar@404
   235
  check(preflow_test.flowValue() == min_cut_value,
alpar@404
   236
        "The max flow value or the three min cut values are incorrect.");
alpar@404
   237
alpar@404
   238
  return 0;
alpar@404
   239
}