gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Support real types + numerical stability fix in NS (#254) - Real types are supported by appropriate inicialization. - A feature of the XTI spanning tree structure is removed to ensure numerical stability (could cause problems using integer types). The node potentials are updated always on the lower subtree, in order to prevent overflow problems. The former method isn't notably faster during to our tests.
0 1 0
default
1 file changed with 27 insertions and 24 deletions:
↑ Collapse diff ↑
Ignore white space 96 line context
... ...
@@ -9,97 +9,98 @@
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_NETWORK_SIMPLEX_H
20 20
#define LEMON_NETWORK_SIMPLEX_H
21 21

	
22 22
/// \ingroup min_cost_flow
23 23
///
24 24
/// \file
25 25
/// \brief Network Simplex algorithm for finding a minimum cost flow.
26 26

	
27 27
#include <vector>
28 28
#include <limits>
29 29
#include <algorithm>
30 30

	
31 31
#include <lemon/core.h>
32 32
#include <lemon/math.h>
33 33

	
34 34
namespace lemon {
35 35

	
36 36
  /// \addtogroup min_cost_flow
37 37
  /// @{
38 38

	
39 39
  /// \brief Implementation of the primal Network Simplex algorithm
40 40
  /// for finding a \ref min_cost_flow "minimum cost flow".
41 41
  ///
42 42
  /// \ref NetworkSimplex implements the primal Network Simplex algorithm
43 43
  /// for finding a \ref min_cost_flow "minimum cost flow".
44 44
  /// This algorithm is a specialized version of the linear programming
45 45
  /// simplex method directly for the minimum cost flow problem.
46 46
  /// It is one of the most efficient solution methods.
47 47
  ///
48 48
  /// In general this class is the fastest implementation available
49 49
  /// in LEMON for the minimum cost flow problem.
50 50
  ///
51 51
  /// \tparam GR The digraph type the algorithm runs on.
52 52
  /// \tparam F The value type used for flow amounts, capacity bounds
53 53
  /// and supply values in the algorithm. By default it is \c int.
54 54
  /// \tparam C The value type used for costs and potentials in the
55 55
  /// algorithm. By default it is the same as \c F.
56 56
  ///
57
  /// \warning Both value types must be signed integer types.
57
  /// \warning Both value types must be signed and all input data must
58
  /// be integer.
58 59
  ///
59 60
  /// \note %NetworkSimplex provides five different pivot rule
60 61
  /// implementations. For more information see \ref PivotRule.
61 62
  template <typename GR, typename F = int, typename C = F>
62 63
  class NetworkSimplex
63 64
  {
64 65
  public:
65 66

	
66 67
    /// The flow type of the algorithm
67 68
    typedef F Flow;
68 69
    /// The cost type of the algorithm
69 70
    typedef C Cost;
70 71
    /// The type of the flow map
71 72
    typedef typename GR::template ArcMap<Flow> FlowMap;
72 73
    /// The type of the potential map
73 74
    typedef typename GR::template NodeMap<Cost> PotentialMap;
74 75

	
75 76
  public:
76 77

	
77 78
    /// \brief Enum type for selecting the pivot rule.
78 79
    ///
79 80
    /// Enum type for selecting the pivot rule for the \ref run()
80 81
    /// function.
81 82
    ///
82 83
    /// \ref NetworkSimplex provides five different pivot rule
83 84
    /// implementations that significantly affect the running time
84 85
    /// of the algorithm.
85 86
    /// By default \ref BLOCK_SEARCH "Block Search" is used, which
86 87
    /// proved to be the most efficient and the most robust on various
87 88
    /// test inputs according to our benchmark tests.
88 89
    /// However another pivot rule can be selected using the \ref run()
89 90
    /// function with the proper parameter.
90 91
    enum PivotRule {
91 92

	
92 93
      /// The First Eligible pivot rule.
93 94
      /// The next eligible arc is selected in a wraparound fashion
94 95
      /// in every iteration.
95 96
      FIRST_ELIGIBLE,
96 97

	
97 98
      /// The Best Eligible pivot rule.
98 99
      /// The best eligible arc is selected in every iteration.
99 100
      BEST_ELIGIBLE,
100 101

	
101 102
      /// The Block Search pivot rule.
102 103
      /// A specified number of arcs are examined in every iteration
103 104
      /// in a wraparound fashion and the best eligible arc is selected
104 105
      /// from this block.
105 106
      BLOCK_SEARCH,
... ...
@@ -999,163 +1000,177 @@
999 1000

	
1000 1001
      // Initialize node related data
1001 1002
      bool valid_supply = true;
1002 1003
      if (!_pstsup && !_psupply) {
1003 1004
        _pstsup = true;
1004 1005
        _psource = _ptarget = NodeIt(_graph);
1005 1006
        _pstflow = 0;
1006 1007
      }
1007 1008
      if (_psupply) {
1008 1009
        Flow sum = 0;
1009 1010
        int i = 0;
1010 1011
        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
1011 1012
          _node_id[n] = i;
1012 1013
          _supply[i] = (*_psupply)[n];
1013 1014
          sum += _supply[i];
1014 1015
        }
1015 1016
        valid_supply = (sum == 0);
1016 1017
      } else {
1017 1018
        int i = 0;
1018 1019
        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
1019 1020
          _node_id[n] = i;
1020 1021
          _supply[i] = 0;
1021 1022
        }
1022 1023
        _supply[_node_id[_psource]] =  _pstflow;
1023 1024
        _supply[_node_id[_ptarget]]   = -_pstflow;
1024 1025
      }
1025 1026
      if (!valid_supply) return false;
1026 1027

	
1027 1028
      // Set data for the artificial root node
1028 1029
      _root = _node_num;
1029 1030
      _parent[_root] = -1;
1030 1031
      _pred[_root] = -1;
1031 1032
      _thread[_root] = 0;
1032 1033
      _rev_thread[0] = _root;
1033 1034
      _succ_num[_root] = all_node_num;
1034 1035
      _last_succ[_root] = _root - 1;
1035 1036
      _supply[_root] = 0;
1036 1037
      _pi[_root] = 0;
1037 1038

	
1038 1039
      // Store the arcs in a mixed order
1039 1040
      int k = std::max(int(sqrt(_arc_num)), 10);
1040 1041
      int i = 0;
1041 1042
      for (ArcIt e(_graph); e != INVALID; ++e) {
1042 1043
        _arc_ref[i] = e;
1043 1044
        if ((i += k) >= _arc_num) i = (i % k) + 1;
1044 1045
      }
1045 1046

	
1046 1047
      // Initialize arc maps
1047
      Flow max_cap = std::numeric_limits<Flow>::max();
1048
      Cost max_cost = std::numeric_limits<Cost>::max() / 4;
1048
      Flow inf_cap =
1049
        std::numeric_limits<Flow>::has_infinity ?
1050
        std::numeric_limits<Flow>::infinity() :
1051
        std::numeric_limits<Flow>::max();
1049 1052
      if (_pupper && _pcost) {
1050 1053
        for (int i = 0; i != _arc_num; ++i) {
1051 1054
          Arc e = _arc_ref[i];
1052 1055
          _source[i] = _node_id[_graph.source(e)];
1053 1056
          _target[i] = _node_id[_graph.target(e)];
1054 1057
          _cap[i] = (*_pupper)[e];
1055 1058
          _cost[i] = (*_pcost)[e];
1056 1059
          _flow[i] = 0;
1057 1060
          _state[i] = STATE_LOWER;
1058 1061
        }
1059 1062
      } else {
1060 1063
        for (int i = 0; i != _arc_num; ++i) {
1061 1064
          Arc e = _arc_ref[i];
1062 1065
          _source[i] = _node_id[_graph.source(e)];
1063 1066
          _target[i] = _node_id[_graph.target(e)];
1064 1067
          _flow[i] = 0;
1065 1068
          _state[i] = STATE_LOWER;
1066 1069
        }
1067 1070
        if (_pupper) {
1068 1071
          for (int i = 0; i != _arc_num; ++i)
1069 1072
            _cap[i] = (*_pupper)[_arc_ref[i]];
1070 1073
        } else {
1071 1074
          for (int i = 0; i != _arc_num; ++i)
1072
            _cap[i] = max_cap;
1075
            _cap[i] = inf_cap;
1073 1076
        }
1074 1077
        if (_pcost) {
1075 1078
          for (int i = 0; i != _arc_num; ++i)
1076 1079
            _cost[i] = (*_pcost)[_arc_ref[i]];
1077 1080
        } else {
1078 1081
          for (int i = 0; i != _arc_num; ++i)
1079 1082
            _cost[i] = 1;
1080 1083
        }
1081 1084
      }
1085
      
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
      }
1082 1097

	
1083 1098
      // Remove non-zero lower bounds
1084 1099
      if (_plower) {
1085 1100
        for (int i = 0; i != _arc_num; ++i) {
1086 1101
          Flow c = (*_plower)[_arc_ref[i]];
1087 1102
          if (c != 0) {
1088 1103
            _cap[i] -= c;
1089 1104
            _supply[_source[i]] -= c;
1090 1105
            _supply[_target[i]] += c;
1091 1106
          }
1092 1107
        }
1093 1108
      }
1094 1109

	
1095 1110
      // Add artificial arcs and initialize the spanning tree data structure
1096 1111
      for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
1097 1112
        _thread[u] = u + 1;
1098 1113
        _rev_thread[u + 1] = u;
1099 1114
        _succ_num[u] = 1;
1100 1115
        _last_succ[u] = u;
1101 1116
        _parent[u] = _root;
1102 1117
        _pred[u] = e;
1103
        _cost[e] = max_cost;
1104
        _cap[e] = max_cap;
1118
        _cost[e] = art_cost;
1119
        _cap[e] = inf_cap;
1105 1120
        _state[e] = STATE_TREE;
1106 1121
        if (_supply[u] >= 0) {
1107 1122
          _flow[e] = _supply[u];
1108 1123
          _forward[u] = true;
1109
          _pi[u] = -max_cost;
1124
          _pi[u] = -art_cost;
1110 1125
        } else {
1111 1126
          _flow[e] = -_supply[u];
1112 1127
          _forward[u] = false;
1113
          _pi[u] = max_cost;
1128
          _pi[u] = art_cost;
1114 1129
        }
1115 1130
      }
1116 1131

	
1117 1132
      return true;
1118 1133
    }
1119 1134

	
1120 1135
    // Find the join node
1121 1136
    void findJoinNode() {
1122 1137
      int u = _source[in_arc];
1123 1138
      int v = _target[in_arc];
1124 1139
      while (u != v) {
1125 1140
        if (_succ_num[u] < _succ_num[v]) {
1126 1141
          u = _parent[u];
1127 1142
        } else {
1128 1143
          v = _parent[v];
1129 1144
        }
1130 1145
      }
1131 1146
      join = u;
1132 1147
    }
1133 1148

	
1134 1149
    // Find the leaving arc of the cycle and returns true if the
1135 1150
    // leaving arc is not the same as the entering arc
1136 1151
    bool findLeavingArc() {
1137 1152
      // Initialize first and second nodes according to the direction
1138 1153
      // of the cycle
1139 1154
      if (_state[in_arc] == STATE_LOWER) {
1140 1155
        first  = _source[in_arc];
1141 1156
        second = _target[in_arc];
1142 1157
      } else {
1143 1158
        first  = _target[in_arc];
1144 1159
        second = _source[in_arc];
1145 1160
      }
1146 1161
      delta = _cap[in_arc];
1147 1162
      int result = 0;
1148 1163
      Flow d;
1149 1164
      int e;
1150 1165

	
1151 1166
      // Search the cycle along the path form the first node to the root
1152 1167
      for (int u = first; u != join; u = _parent[u]) {
1153 1168
        e = _pred[u];
1154 1169
        d = _forward[u] ? _flow[e] : _cap[e] - _flow[e];
1155 1170
        if (d < delta) {
1156 1171
          delta = d;
1157 1172
          u_out = u;
1158 1173
          result = 1;
1159 1174
        }
1160 1175
      }
1161 1176
      // Search the cycle along the path form the second node to the root
... ...
@@ -1282,112 +1297,100 @@
1282 1297
      }
1283 1298
      _pred[u_in] = in_arc;
1284 1299
      _forward[u_in] = (u_in == _source[in_arc]);
1285 1300
      _succ_num[u_in] = old_succ_num;
1286 1301

	
1287 1302
      // Set limits for updating _last_succ form v_in and v_out
1288 1303
      // towards the root
1289 1304
      int up_limit_in = -1;
1290 1305
      int up_limit_out = -1;
1291 1306
      if (_last_succ[join] == v_in) {
1292 1307
        up_limit_out = join;
1293 1308
      } else {
1294 1309
        up_limit_in = join;
1295 1310
      }
1296 1311

	
1297 1312
      // Update _last_succ from v_in towards the root
1298 1313
      for (u = v_in; u != up_limit_in && _last_succ[u] == v_in;
1299 1314
           u = _parent[u]) {
1300 1315
        _last_succ[u] = _last_succ[u_out];
1301 1316
      }
1302 1317
      // Update _last_succ from v_out towards the root
1303 1318
      if (join != old_rev_thread && v_in != old_rev_thread) {
1304 1319
        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1305 1320
             u = _parent[u]) {
1306 1321
          _last_succ[u] = old_rev_thread;
1307 1322
        }
1308 1323
      } else {
1309 1324
        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1310 1325
             u = _parent[u]) {
1311 1326
          _last_succ[u] = _last_succ[u_out];
1312 1327
        }
1313 1328
      }
1314 1329

	
1315 1330
      // Update _succ_num from v_in to join
1316 1331
      for (u = v_in; u != join; u = _parent[u]) {
1317 1332
        _succ_num[u] += old_succ_num;
1318 1333
      }
1319 1334
      // Update _succ_num from v_out to join
1320 1335
      for (u = v_out; u != join; u = _parent[u]) {
1321 1336
        _succ_num[u] -= old_succ_num;
1322 1337
      }
1323 1338
    }
1324 1339

	
1325 1340
    // Update potentials
1326 1341
    void updatePotential() {
1327 1342
      Cost sigma = _forward[u_in] ?
1328 1343
        _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
1329 1344
        _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
1330
      if (_succ_num[u_in] > _node_num / 2) {
1331
        // Update in the upper subtree (which contains the root)
1332
        int before = _rev_thread[u_in];
1333
        int after = _thread[_last_succ[u_in]];
1334
        _thread[before] = after;
1335
        _pi[_root] -= sigma;
1336
        for (int u = _thread[_root]; u != _root; u = _thread[u]) {
1337
          _pi[u] -= sigma;
1338
        }
1339
        _thread[before] = u_in;
1340
      } else {
1341
        // Update in the lower subtree (which has been moved)
1342
        int end = _thread[_last_succ[u_in]];
1343
        for (int u = u_in; u != end; u = _thread[u]) {
1344
          _pi[u] += sigma;
1345
        }
1345
      // Update potentials in the subtree, which has been moved
1346
      int end = _thread[_last_succ[u_in]];
1347
      for (int u = u_in; u != end; u = _thread[u]) {
1348
        _pi[u] += sigma;
1346 1349
      }
1347 1350
    }
1348 1351

	
1349 1352
    // Execute the algorithm
1350 1353
    bool start(PivotRule pivot_rule) {
1351 1354
      // Select the pivot rule implementation
1352 1355
      switch (pivot_rule) {
1353 1356
        case FIRST_ELIGIBLE:
1354 1357
          return start<FirstEligiblePivotRule>();
1355 1358
        case BEST_ELIGIBLE:
1356 1359
          return start<BestEligiblePivotRule>();
1357 1360
        case BLOCK_SEARCH:
1358 1361
          return start<BlockSearchPivotRule>();
1359 1362
        case CANDIDATE_LIST:
1360 1363
          return start<CandidateListPivotRule>();
1361 1364
        case ALTERING_LIST:
1362 1365
          return start<AlteringListPivotRule>();
1363 1366
      }
1364 1367
      return false;
1365 1368
    }
1366 1369

	
1367 1370
    template <typename PivotRuleImpl>
1368 1371
    bool start() {
1369 1372
      PivotRuleImpl pivot(*this);
1370 1373

	
1371 1374
      // Execute the Network Simplex algorithm
1372 1375
      while (pivot.findEnteringArc()) {
1373 1376
        findJoinNode();
1374 1377
        bool change = findLeavingArc();
1375 1378
        changeFlow(change);
1376 1379
        if (change) {
1377 1380
          updateTreeStructure();
1378 1381
          updatePotential();
1379 1382
        }
1380 1383
      }
1381 1384

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

	
1387 1390
      // Copy flow values to _flow_map
1388 1391
      if (_plower) {
1389 1392
        for (int i = 0; i != _arc_num; ++i) {
1390 1393
          Arc e = _arc_ref[i];
1391 1394
          _flow_map->set(e, (*_plower)[e] + _flow[i]);
1392 1395
        }
1393 1396
      } else {
0 comments (0 inline)