gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
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.
0 3 0
default
3 files changed with 377 insertions and 93 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -319,11 +319,11 @@
319 319
a single source and a single target. Formally, there is a \f$G=(V,A)\f$
320
digraph, a \f$cap:A\rightarrow\mathbf{R}^+_0\f$ capacity function and
320
digraph, a \f$cap: A\rightarrow\mathbf{R}^+_0\f$ capacity function and
321 321
\f$s, t \in V\f$ source and target nodes.
322
A maximum flow is an \f$f:A\rightarrow\mathbf{R}^+_0\f$ solution of the
322
A maximum flow is an \f$f: A\rightarrow\mathbf{R}^+_0\f$ solution of the
323 323
following optimization problem.
324 324

	
325
\f[ \max\sum_{a\in\delta_{out}(s)}f(a) - \sum_{a\in\delta_{in}(s)}f(a) \f]
326
\f[ \sum_{a\in\delta_{out}(v)} f(a) = \sum_{a\in\delta_{in}(v)} f(a)
327
    \qquad \forall v\in V\setminus\{s,t\} \f]
328
\f[ 0 \leq f(a) \leq cap(a) \qquad \forall a\in A \f]
325
\f[ \max\sum_{sv\in A} f(sv) - \sum_{vs\in A} f(vs) \f]
326
\f[ \sum_{uv\in A} f(uv) = \sum_{vu\in A} f(vu)
327
    \quad \forall u\in V\setminus\{s,t\} \f]
328
\f[ 0 \leq f(uv) \leq cap(uv) \quad \forall uv\in A \f]
329 329

	
... ...
@@ -347,3 +347,3 @@
347 347

	
348
This group describes the algorithms for finding minimum cost flows and
348
This group contains the algorithms for finding minimum cost flows and
349 349
circulations.
... ...
@@ -352,26 +352,94 @@
352 352
minimum total cost from a set of supply nodes to a set of demand nodes
353
in a network with capacity constraints and arc costs.
353
in a network with capacity constraints (lower and upper bounds)
354
and arc costs.
354 355
Formally, let \f$G=(V,A)\f$ be a digraph,
355 356
\f$lower, upper: A\rightarrow\mathbf{Z}^+_0\f$ denote the lower and
356
upper bounds for the flow values on the arcs,
357
upper bounds for the flow values on the arcs, for which
358
\f$0 \leq lower(uv) \leq upper(uv)\f$ holds for all \f$uv\in A\f$.
357 359
\f$cost: A\rightarrow\mathbf{Z}^+_0\f$ denotes the cost per unit flow
358
on the arcs, and
359
\f$supply: V\rightarrow\mathbf{Z}\f$ denotes the supply/demand values
360
of the nodes.
361
A minimum cost flow is an \f$f:A\rightarrow\mathbf{R}^+_0\f$ solution of
362
the following optimization problem.
360
on the arcs, and \f$sup: V\rightarrow\mathbf{Z}\f$ denotes the
361
signed supply values of the nodes.
362
If \f$sup(u)>0\f$, then \f$u\f$ is a supply node with \f$sup(u)\f$
363
supply, if \f$sup(u)<0\f$, then \f$u\f$ is a demand node with
364
\f$-sup(u)\f$ demand.
365
A minimum cost flow is an \f$f: A\rightarrow\mathbf{Z}^+_0\f$ solution
366
of the following optimization problem.
363 367

	
364
\f[ \min\sum_{a\in A} f(a) cost(a) \f]
365
\f[ \sum_{a\in\delta_{out}(v)} f(a) - \sum_{a\in\delta_{in}(v)} f(a) =
366
    supply(v) \qquad \forall v\in V \f]
367
\f[ lower(a) \leq f(a) \leq upper(a) \qquad \forall a\in A \f]
368
\f[ \min\sum_{uv\in A} f(uv) \cdot cost(uv) \f]
369
\f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \geq
370
    sup(u) \quad \forall u\in V \f]
371
\f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A \f]
368 372

	
369
LEMON contains several algorithms for solving minimum cost flow problems:
370
 - \ref CycleCanceling Cycle-canceling algorithms.
371
 - \ref CapacityScaling Successive shortest path algorithm with optional
373
The sum of the supply values, i.e. \f$\sum_{u\in V} sup(u)\f$ must be
374
zero or negative in order to have a feasible solution (since the sum
375
of the expressions on the left-hand side of the inequalities is zero).
376
It means that the total demand must be greater or equal to the total
377
supply and all the supplies have to be carried out from the supply nodes,
378
but there could be demands that are not satisfied.
379
If \f$\sum_{u\in V} sup(u)\f$ is zero, then all the supply/demand
380
constraints have to be satisfied with equality, i.e. all demands
381
have to be satisfied and all supplies have to be used.
382

	
383
If you need the opposite inequalities in the supply/demand constraints
384
(i.e. the total demand is less than the total supply and all the demands
385
have to be satisfied while there could be supplies that are not used),
386
then you could easily transform the problem to the above form by reversing
387
the direction of the arcs and taking the negative of the supply values
388
(e.g. using \ref ReverseDigraph and \ref NegMap adaptors).
389
However \ref NetworkSimplex algorithm also supports this form directly
390
for the sake of convenience.
391

	
392
A feasible solution for this problem can be found using \ref Circulation.
393

	
394
Note that the above formulation is actually more general than the usual
395
definition of the minimum cost flow problem, in which strict equalities
396
are required in the supply/demand contraints, i.e.
397

	
398
\f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) =
399
    sup(u) \quad \forall u\in V. \f]
400

	
401
However if the sum of the supply values is zero, then these two problems
402
are equivalent. So if you need the equality form, you have to ensure this
403
additional contraint for the algorithms.
404

	
405
The dual solution of the minimum cost flow problem is represented by node 
406
potentials \f$\pi: V\rightarrow\mathbf{Z}\f$.
407
An \f$f: A\rightarrow\mathbf{Z}^+_0\f$ feasible solution of the problem
408
is optimal if and only if for some \f$\pi: V\rightarrow\mathbf{Z}\f$
409
node potentials the following \e complementary \e slackness optimality
410
conditions hold.
411

	
412
 - For all \f$uv\in A\f$ arcs:
413
   - if \f$cost^\pi(uv)>0\f$, then \f$f(uv)=lower(uv)\f$;
414
   - if \f$lower(uv)<f(uv)<upper(uv)\f$, then \f$cost^\pi(uv)=0\f$;
415
   - if \f$cost^\pi(uv)<0\f$, then \f$f(uv)=upper(uv)\f$.
416
 - For all \f$u\in V\f$:
417
   - if \f$\sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \neq sup(u)\f$,
418
     then \f$\pi(u)=0\f$.
419
 
420
Here \f$cost^\pi(uv)\f$ denotes the \e reduced \e cost of the arc
421
\f$uv\in A\f$ with respect to the node potentials \f$\pi\f$, i.e.
422
\f[ cost^\pi(uv) = cost(uv) + \pi(u) - \pi(v).\f]
423

	
424
All algorithms provide dual solution (node potentials) as well
425
if an optimal flow is found.
426

	
427
LEMON contains several algorithms for solving minimum cost flow problems.
428
 - \ref NetworkSimplex Primal Network Simplex algorithm with various
429
   pivot strategies.
430
 - \ref CostScaling Push-Relabel and Augment-Relabel algorithms based on
431
   cost scaling.
432
 - \ref CapacityScaling Successive Shortest %Path algorithm with optional
372 433
   capacity scaling.
373
 - \ref CostScaling Push-relabel and augment-relabel algorithms based on
374
   cost scaling.
375
 - \ref NetworkSimplex Primal network simplex algorithm with various
376
   pivot strategies.
434
 - \ref CancelAndTighten The Cancel and Tighten algorithm.
435
 - \ref CycleCanceling Cycle-Canceling algorithms.
436

	
437
Most of these implementations support the general inequality form of the
438
minimum cost flow problem, but CancelAndTighten and CycleCanceling
439
only support the equality form due to the primal method they use.
440

	
441
In general NetworkSimplex is the most efficient implementation,
442
but in special cases other algorithms could be faster.
443
For example, if the total supply and/or capacities are rather small,
444
CapacityScaling is usually the fastest algorithm (without effective scaling).
377 445
*/
Show white space 6 line context
... ...
@@ -32,2 +32,5 @@
32 32
#include <lemon/math.h>
33
#include <lemon/maps.h>
34
#include <lemon/circulation.h>
35
#include <lemon/adaptors.h>
33 36

	
... ...
@@ -49,2 +52,4 @@
49 52
  /// in LEMON for the minimum cost flow problem.
53
  /// Moreover it supports both direction of the supply/demand inequality
54
  /// constraints. For more information see \ref ProblemType.
50 55
  ///
... ...
@@ -60,3 +65,4 @@
60 65
  /// \note %NetworkSimplex provides five different pivot rule
61
  /// implementations. For more information see \ref PivotRule.
66
  /// implementations, from which the most efficient one is used
67
  /// by default. For more information see \ref PivotRule.
62 68
  template <typename GR, typename F = int, typename C = F>
... ...
@@ -70,2 +76,8 @@
70 76
    typedef C Cost;
77
#ifdef DOXYGEN
78
    /// The type of the flow map
79
    typedef GR::ArcMap<Flow> FlowMap;
80
    /// The type of the potential map
81
    typedef GR::NodeMap<Cost> PotentialMap;
82
#else
71 83
    /// The type of the flow map
... ...
@@ -74,2 +86,3 @@
74 86
    typedef typename GR::template NodeMap<Cost> PotentialMap;
87
#endif
75 88

	
... ...
@@ -119,2 +132,54 @@
119 132
    };
133
    
134
    /// \brief Enum type for selecting the problem type.
135
    ///
136
    /// Enum type for selecting the problem type, i.e. the direction of
137
    /// the inequalities in the supply/demand constraints of the
138
    /// \ref min_cost_flow "minimum cost flow problem".
139
    ///
140
    /// The default problem type is \c GEQ, since this form is supported
141
    /// by other minimum cost flow algorithms and the \ref Circulation
142
    /// algorithm as well.
143
    /// The \c LEQ problem type can be selected using the \ref problemType()
144
    /// function.
145
    ///
146
    /// Note that the equality form is a special case of both problem type.
147
    enum ProblemType {
148

	
149
      /// This option means that there are "<em>greater or equal</em>"
150
      /// constraints in the defintion, i.e. the exact formulation of the
151
      /// problem is the following.
152
      /**
153
          \f[ \min\sum_{uv\in A} f(uv) \cdot cost(uv) \f]
154
          \f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \geq
155
              sup(u) \quad \forall u\in V \f]
156
          \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A \f]
157
      */
158
      /// It means that the total demand must be greater or equal to the 
159
      /// total supply (i.e. \f$\sum_{u\in V} sup(u)\f$ must be zero or
160
      /// negative) and all the supplies have to be carried out from 
161
      /// the supply nodes, but there could be demands that are not 
162
      /// satisfied.
163
      GEQ,
164
      /// It is just an alias for the \c GEQ option.
165
      CARRY_SUPPLIES = GEQ,
166

	
167
      /// This option means that there are "<em>less or equal</em>"
168
      /// constraints in the defintion, i.e. the exact formulation of the
169
      /// problem is the following.
170
      /**
171
          \f[ \min\sum_{uv\in A} f(uv) \cdot cost(uv) \f]
172
          \f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \leq
173
              sup(u) \quad \forall u\in V \f]
174
          \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A \f]
175
      */
176
      /// It means that the total demand must be less or equal to the 
177
      /// total supply (i.e. \f$\sum_{u\in V} sup(u)\f$ must be zero or
178
      /// positive) and all the demands have to be satisfied, but there
179
      /// could be supplies that are not carried out from the supply
180
      /// nodes.
181
      LEQ,
182
      /// It is just an alias for the \c LEQ option.
183
      SATISFY_DEMANDS = LEQ
184
    };
120 185

	
... ...
@@ -157,2 +222,3 @@
157 222
    Flow _pstflow;
223
    ProblemType _ptype;
158 224

	
... ...
@@ -588,3 +654,3 @@
588 654
    ///
589
    /// Constructor.
655
    /// The constructor of the class.
590 656
    ///
... ...
@@ -594,3 +660,3 @@
594 660
      _plower(NULL), _pupper(NULL), _pcost(NULL),
595
      _psupply(NULL), _pstsup(false),
661
      _psupply(NULL), _pstsup(false), _ptype(GEQ),
596 662
      _flow_map(NULL), _potential_map(NULL),
... ...
@@ -613,2 +679,8 @@
613 679

	
680
    /// \name Parameters
681
    /// The parameters of the algorithm can be specified using these
682
    /// functions.
683

	
684
    /// @{
685

	
614 686
    /// \brief Set the lower bounds on the arcs.
... ...
@@ -762,2 +834,16 @@
762 834
    }
835
    
836
    /// \brief Set the problem type.
837
    ///
838
    /// This function sets the problem type for the algorithm.
839
    /// If it is not used before calling \ref run(), the \ref GEQ problem
840
    /// type will be used.
841
    ///
842
    /// For more information see \ref ProblemType.
843
    ///
844
    /// \return <tt>(*this)</tt>
845
    NetworkSimplex& problemType(ProblemType problem_type) {
846
      _ptype = problem_type;
847
      return *this;
848
    }
763 849

	
... ...
@@ -797,2 +883,4 @@
797 883
    }
884
    
885
    /// @}
798 886

	
... ...
@@ -806,6 +894,7 @@
806 894
    /// This function runs the algorithm.
807
    /// The paramters can be specified using \ref lowerMap(),
895
    /// The paramters can be specified using functions \ref lowerMap(),
808 896
    /// \ref upperMap(), \ref capacityMap(), \ref boundMaps(),
809
    /// \ref costMap(), \ref supplyMap() and \ref stSupply()
810
    /// functions. For example,
897
    /// \ref costMap(), \ref supplyMap(), \ref stSupply(), 
898
    /// \ref problemType(), \ref flowMap() and \ref potentialMap().
899
    /// For example,
811 900
    /// \code
... ...
@@ -832,5 +921,6 @@
832 921
    /// This function resets all the paramaters that have been given
833
    /// using \ref lowerMap(), \ref upperMap(), \ref capacityMap(),
834
    /// \ref boundMaps(), \ref costMap(), \ref supplyMap() and
835
    /// \ref stSupply() functions before.
922
    /// before using functions \ref lowerMap(), \ref upperMap(),
923
    /// \ref capacityMap(), \ref boundMaps(), \ref costMap(),
924
    /// \ref supplyMap(), \ref stSupply(), \ref problemType(), 
925
    /// \ref flowMap() and \ref potentialMap().
836 926
    ///
... ...
@@ -871,2 +961,10 @@
871 961
      _pstsup = false;
962
      _ptype = GEQ;
963
      if (_local_flow) delete _flow_map;
964
      if (_local_potential) delete _potential_map;
965
      _flow_map = NULL;
966
      _potential_map = NULL;
967
      _local_flow = false;
968
      _local_potential = false;
969

	
872 970
      return *this;
... ...
@@ -1002,2 +1100,3 @@
1002 1100
      bool valid_supply = true;
1101
      Flow sum_supply = 0;
1003 1102
      if (!_pstsup && !_psupply) {
... ...
@@ -1008,3 +1107,2 @@
1008 1107
      if (_psupply) {
1009
        Flow sum = 0;
1010 1108
        int i = 0;
... ...
@@ -1013,5 +1111,6 @@
1013 1111
          _supply[i] = (*_psupply)[n];
1014
          sum += _supply[i];
1112
          sum_supply += _supply[i];
1015 1113
        }
1016
        valid_supply = (sum == 0);
1114
        valid_supply = (_ptype == GEQ && sum_supply <= 0) ||
1115
                       (_ptype == LEQ && sum_supply >= 0);
1017 1116
      } else {
... ...
@@ -1023,3 +1122,3 @@
1023 1122
        _supply[_node_id[_psource]] =  _pstflow;
1024
        _supply[_node_id[_ptarget]]   = -_pstflow;
1123
        _supply[_node_id[_ptarget]] = -_pstflow;
1025 1124
      }
... ...
@@ -1027,2 +1126,87 @@
1027 1126

	
1127
      // Infinite capacity value
1128
      Flow inf_cap =
1129
        std::numeric_limits<Flow>::has_infinity ?
1130
        std::numeric_limits<Flow>::infinity() :
1131
        std::numeric_limits<Flow>::max();
1132

	
1133
      // Initialize artifical cost
1134
      Cost art_cost;
1135
      if (std::numeric_limits<Cost>::is_exact) {
1136
        art_cost = std::numeric_limits<Cost>::max() / 4 + 1;
1137
      } else {
1138
        art_cost = std::numeric_limits<Cost>::min();
1139
        for (int i = 0; i != _arc_num; ++i) {
1140
          if (_cost[i] > art_cost) art_cost = _cost[i];
1141
        }
1142
        art_cost = (art_cost + 1) * _node_num;
1143
      }
1144

	
1145
      // Run Circulation to check if a feasible solution exists
1146
      typedef ConstMap<Arc, Flow> ConstArcMap;
1147
      FlowNodeMap *csup = NULL;
1148
      bool local_csup = false;
1149
      if (_psupply) {
1150
        csup = _psupply;
1151
      } else {
1152
        csup = new FlowNodeMap(_graph, 0);
1153
        (*csup)[_psource] =  _pstflow;
1154
        (*csup)[_ptarget] = -_pstflow;
1155
        local_csup = true;
1156
      }
1157
      bool circ_result = false;
1158
      if (_ptype == GEQ || (_ptype == LEQ && sum_supply == 0)) {
1159
        // GEQ problem type
1160
        if (_plower) {
1161
          if (_pupper) {
1162
            Circulation<GR, FlowArcMap, FlowArcMap, FlowNodeMap>
1163
              circ(_graph, *_plower, *_pupper, *csup);
1164
            circ_result = circ.run();
1165
          } else {
1166
            Circulation<GR, FlowArcMap, ConstArcMap, FlowNodeMap>
1167
              circ(_graph, *_plower, ConstArcMap(inf_cap), *csup);
1168
            circ_result = circ.run();
1169
          }
1170
        } else {
1171
          if (_pupper) {
1172
            Circulation<GR, ConstArcMap, FlowArcMap, FlowNodeMap>
1173
              circ(_graph, ConstArcMap(0), *_pupper, *csup);
1174
            circ_result = circ.run();
1175
          } else {
1176
            Circulation<GR, ConstArcMap, ConstArcMap, FlowNodeMap>
1177
              circ(_graph, ConstArcMap(0), ConstArcMap(inf_cap), *csup);
1178
            circ_result = circ.run();
1179
          }
1180
        }
1181
      } else {
1182
        // LEQ problem type
1183
        typedef ReverseDigraph<const GR> RevGraph;
1184
        typedef NegMap<FlowNodeMap> NegNodeMap;
1185
        RevGraph rgraph(_graph);
1186
        NegNodeMap neg_csup(*csup);
1187
        if (_plower) {
1188
          if (_pupper) {
1189
            Circulation<RevGraph, FlowArcMap, FlowArcMap, NegNodeMap>
1190
              circ(rgraph, *_plower, *_pupper, neg_csup);
1191
            circ_result = circ.run();
1192
          } else {
1193
            Circulation<RevGraph, FlowArcMap, ConstArcMap, NegNodeMap>
1194
              circ(rgraph, *_plower, ConstArcMap(inf_cap), neg_csup);
1195
            circ_result = circ.run();
1196
          }
1197
        } else {
1198
          if (_pupper) {
1199
            Circulation<RevGraph, ConstArcMap, FlowArcMap, NegNodeMap>
1200
              circ(rgraph, ConstArcMap(0), *_pupper, neg_csup);
1201
            circ_result = circ.run();
1202
          } else {
1203
            Circulation<RevGraph, ConstArcMap, ConstArcMap, NegNodeMap>
1204
              circ(rgraph, ConstArcMap(0), ConstArcMap(inf_cap), neg_csup);
1205
            circ_result = circ.run();
1206
          }
1207
        }
1208
      }
1209
      if (local_csup) delete csup;
1210
      if (!circ_result) return false;
1211

	
1028 1212
      // Set data for the artificial root node
... ...
@@ -1035,4 +1219,8 @@
1035 1219
      _last_succ[_root] = _root - 1;
1036
      _supply[_root] = 0;
1037
      _pi[_root] = 0;
1220
      _supply[_root] = -sum_supply;
1221
      if (sum_supply < 0) {
1222
        _pi[_root] = -art_cost;
1223
      } else {
1224
        _pi[_root] = art_cost;
1225
      }
1038 1226

	
... ...
@@ -1047,6 +1235,2 @@
1047 1235
      // Initialize arc maps
1048
      Flow inf_cap =
1049
        std::numeric_limits<Flow>::has_infinity ?
1050
        std::numeric_limits<Flow>::infinity() :
1051
        std::numeric_limits<Flow>::max();
1052 1236
      if (_pupper && _pcost) {
... ...
@@ -1085,14 +1269,2 @@
1085 1269
      
1086
      // Initialize artifical cost
1087
      Cost art_cost;
1088
      if (std::numeric_limits<Cost>::is_exact) {
1089
        art_cost = std::numeric_limits<Cost>::max() / 4 + 1;
1090
      } else {
1091
        art_cost = std::numeric_limits<Cost>::min();
1092
        for (int i = 0; i != _arc_num; ++i) {
1093
          if (_cost[i] > art_cost) art_cost = _cost[i];
1094
        }
1095
        art_cost = (art_cost + 1) * _node_num;
1096
      }
1097

	
1098 1270
      // Remove non-zero lower bounds
... ...
@@ -1120,6 +1292,6 @@
1120 1292
        _state[e] = STATE_TREE;
1121
        if (_supply[u] >= 0) {
1293
        if (_supply[u] > 0 || (_supply[u] == 0 && sum_supply <= 0)) {
1122 1294
          _flow[e] = _supply[u];
1123 1295
          _forward[u] = true;
1124
          _pi[u] = -art_cost;
1296
          _pi[u] = -art_cost + _pi[_root];
1125 1297
        } else {
... ...
@@ -1127,3 +1299,3 @@
1127 1299
          _forward[u] = false;
1128
          _pi[u] = art_cost;
1300
          _pi[u] = art_cost + _pi[_root];
1129 1301
        }
... ...
@@ -1384,7 +1556,2 @@
1384 1556

	
1385
      // Check if the flow amount equals zero on all the artificial arcs
1386
      for (int e = _arc_num; e != _arc_num + _node_num; ++e) {
1387
        if (_flow[e] > 0) return false;
1388
      }
1389

	
1390 1557
      // Copy flow values to _flow_map
Ignore white space 6 line context
... ...
@@ -35,15 +35,15 @@
35 35
  "@nodes\n"
36
  "label  sup1 sup2 sup3\n"
37
  "    1    20   27    0\n"
38
  "    2    -4    0    0\n"
39
  "    3     0    0    0\n"
40
  "    4     0    0    0\n"
41
  "    5     9    0    0\n"
42
  "    6    -6    0    0\n"
43
  "    7     0    0    0\n"
44
  "    8     0    0    0\n"
45
  "    9     3    0    0\n"
46
  "   10    -2    0    0\n"
47
  "   11     0    0    0\n"
48
  "   12   -20  -27    0\n"
36
  "label  sup1 sup2 sup3 sup4 sup5\n"
37
  "    1    20   27    0   20   30\n"
38
  "    2    -4    0    0   -8   -3\n"
39
  "    3     0    0    0    0    0\n"
40
  "    4     0    0    0    0    0\n"
41
  "    5     9    0    0    6   11\n"
42
  "    6    -6    0    0   -5   -6\n"
43
  "    7     0    0    0    0    0\n"
44
  "    8     0    0    0    0    3\n"
45
  "    9     3    0    0    0    0\n"
46
  "   10    -2    0    0   -7   -2\n"
47
  "   11     0    0    0  -10    0\n"
48
  "   12   -20  -27    0  -30  -20\n"
49 49
  "\n"
... ...
@@ -78,2 +78,8 @@
78 78

	
79
enum ProblemType {
80
  EQ,
81
  GEQ,
82
  LEQ
83
};
84

	
79 85
// Check the interface of an MCF algorithm
... ...
@@ -99,13 +105,15 @@
99 105
             .stSupply(n, n, k)
106
             .flowMap(flow)
107
             .potentialMap(pot)
100 108
             .run();
109
      
110
      const MCF& const_mcf = mcf;
101 111

	
102
      const typename MCF::FlowMap &fm = mcf.flowMap();
103
      const typename MCF::PotentialMap &pm = mcf.potentialMap();
112
      const typename MCF::FlowMap &fm = const_mcf.flowMap();
113
      const typename MCF::PotentialMap &pm = const_mcf.potentialMap();
104 114

	
105
      v = mcf.totalCost();
106
      double x = mcf.template totalCost<double>();
107
      v = mcf.flow(a);
108
      v = mcf.potential(n);
109
      mcf.flowMap(flow);
110
      mcf.potentialMap(pot);
115
      v = const_mcf.totalCost();
116
      double x = const_mcf.template totalCost<double>();
117
      v = const_mcf.flow(a);
118
      v = const_mcf.potential(n);
111 119

	
... ...
@@ -144,3 +152,4 @@
144 152
bool checkFlow( const GR& gr, const LM& lower, const UM& upper,
145
                const SM& supply, const FM& flow )
153
                const SM& supply, const FM& flow,
154
                ProblemType type = EQ )
146 155
{
... ...
@@ -158,3 +167,6 @@
158 167
      sum -= flow[e];
159
    if (sum != supply[n]) return false;
168
    bool b = (type ==  EQ && sum == supply[n]) ||
169
             (type == GEQ && sum >= supply[n]) ||
170
             (type == LEQ && sum <= supply[n]);
171
    if (!b) return false;
160 172
  }
... ...
@@ -167,5 +179,6 @@
167 179
template < typename GR, typename LM, typename UM,
168
           typename CM, typename FM, typename PM >
180
           typename CM, typename SM, typename FM, typename PM >
169 181
bool checkPotential( const GR& gr, const LM& lower, const UM& upper,
170
                     const CM& cost, const FM& flow, const PM& pi )
182
                     const CM& cost, const SM& supply, const FM& flow, 
183
                     const PM& pi )
171 184
{
... ...
@@ -181,2 +194,12 @@
181 194
  }
195
  
196
  for (NodeIt n(gr); opt && n != INVALID; ++n) {
197
    typename SM::Value sum = 0;
198
    for (OutArcIt e(gr, n); e != INVALID; ++e)
199
      sum += flow[e];
200
    for (InArcIt e(gr, n); e != INVALID; ++e)
201
      sum -= flow[e];
202
    opt = (sum == supply[n]) || (pi[n] == 0);
203
  }
204
  
182 205
  return opt;
... ...
@@ -192,3 +215,4 @@
192 215
               bool result, typename CM::Value total,
193
               const std::string &test_id = "" )
216
               const std::string &test_id = "",
217
               ProblemType type = EQ )
194 218
{
... ...
@@ -196,6 +220,6 @@
196 220
  if (result) {
197
    check(checkFlow(gr, lower, upper, supply, mcf.flowMap()),
221
    check(checkFlow(gr, lower, upper, supply, mcf.flowMap(), type),
198 222
          "The flow is not feasible " + test_id);
199 223
    check(mcf.totalCost() == total, "The flow is not optimal " + test_id);
200
    check(checkPotential(gr, lower, upper, cost, mcf.flowMap(),
224
    check(checkPotential(gr, lower, upper, cost, supply, mcf.flowMap(),
201 225
                         mcf.potentialMap()),
... ...
@@ -228,3 +252,3 @@
228 252
  Digraph::ArcMap<int> c(gr), l1(gr), l2(gr), u(gr);
229
  Digraph::NodeMap<int> s1(gr), s2(gr), s3(gr);
253
  Digraph::NodeMap<int> s1(gr), s2(gr), s3(gr), s4(gr), s5(gr);
230 254
  ConstMap<Arc, int> cc(1), cu(std::numeric_limits<int>::max());
... ...
@@ -241,2 +265,4 @@
241 265
    .nodeMap("sup3", s3)
266
    .nodeMap("sup4", s4)
267
    .nodeMap("sup5", s5)
242 268
    .node("source", v)
... ...
@@ -249,2 +275,3 @@
249 275

	
276
    // Check the equality form
250 277
    mcf.upperMap(u).costMap(c);
... ...
@@ -269,2 +296,24 @@
269 296
             gr, l2, u, cc, s3, false,   0, "#A8");
297

	
298
    // Check the GEQ form
299
    mcf.reset().upperMap(u).costMap(c).supplyMap(s4);
300
    checkMcf(mcf, mcf.run(),
301
             gr, l1, u, c, s4, true,  3530, "#A9", GEQ);
302
    mcf.problemType(mcf.GEQ);
303
    checkMcf(mcf, mcf.lowerMap(l2).run(),
304
             gr, l2, u, c, s4, true,  4540, "#A10", GEQ);
305
    mcf.problemType(mcf.CARRY_SUPPLIES).supplyMap(s5);
306
    checkMcf(mcf, mcf.run(),
307
             gr, l2, u, c, s5, false,    0, "#A11", GEQ);
308

	
309
    // Check the LEQ form
310
    mcf.reset().problemType(mcf.LEQ);
311
    mcf.upperMap(u).costMap(c).supplyMap(s5);
312
    checkMcf(mcf, mcf.run(),
313
             gr, l1, u, c, s5, true,  5080, "#A12", LEQ);
314
    checkMcf(mcf, mcf.lowerMap(l2).run(),
315
             gr, l2, u, c, s5, true,  5930, "#A13", LEQ);
316
    mcf.problemType(mcf.SATISFY_DEMANDS).supplyMap(s4);
317
    checkMcf(mcf, mcf.run(),
318
             gr, l2, u, c, s4, false,    0, "#A14", LEQ);
270 319
  }
0 comments (0 inline)