gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Small implementation improvements in MCF algorithms (#180) - Handle max() as infinite value (not only infinity()). - Better GEQ handling in CapacityScaling. - Skip the unnecessary saturating operations in the first phase in CapacityScaling. - Use vector<char> instead of vector<bool> and vector<int> if it is possible and it proved to be usually faster.
0 2 0
default
2 files changed with 61 insertions and 50 deletions:
↑ Collapse diff ↑
Ignore white space 12 line context
... ...
@@ -130,13 +130,13 @@
130 130
  
131 131
  private:
132 132

	
133 133
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
134 134

	
135 135
    typedef std::vector<int> IntVector;
136
    typedef std::vector<bool> BoolVector;
136
    typedef std::vector<char> BoolVector;
137 137
    typedef std::vector<Value> ValueVector;
138 138
    typedef std::vector<Cost> CostVector;
139 139

	
140 140
  private:
141 141

	
142 142
    // Data related to the underlying digraph
... ...
@@ -193,12 +193,13 @@
193 193
    // potentials according to the found distance labels.
194 194
    class ResidualDijkstra
195 195
    {
196 196
    private:
197 197

	
198 198
      int _node_num;
199
      bool _geq;
199 200
      const IntVector &_first_out;
200 201
      const IntVector &_target;
201 202
      const CostVector &_cost;
202 203
      const ValueVector &_res_cap;
203 204
      const ValueVector &_excess;
204 205
      CostVector &_pi;
... ...
@@ -207,16 +208,16 @@
207 208
      IntVector _proc_nodes;
208 209
      CostVector _dist;
209 210
      
210 211
    public:
211 212

	
212 213
      ResidualDijkstra(CapacityScaling& cs) :
213
        _node_num(cs._node_num), _first_out(cs._first_out), 
214
        _target(cs._target), _cost(cs._cost), _res_cap(cs._res_cap),
215
        _excess(cs._excess), _pi(cs._pi), _pred(cs._pred),
216
        _dist(cs._node_num)
214
        _node_num(cs._node_num), _geq(cs._sum_supply < 0),
215
        _first_out(cs._first_out), _target(cs._target), _cost(cs._cost),
216
        _res_cap(cs._res_cap), _excess(cs._excess), _pi(cs._pi),
217
        _pred(cs._pred), _dist(cs._node_num)
217 218
      {}
218 219

	
219 220
      int run(int s, Value delta = 1) {
220 221
        RangeMap<int> heap_cross_ref(_node_num, Heap::PRE_HEAP);
221 222
        Heap heap(heap_cross_ref);
222 223
        heap.push(s, 0);
... ...
@@ -229,13 +230,14 @@
229 230
          Cost d = heap.prio() + _pi[u], dn;
230 231
          _dist[u] = heap.prio();
231 232
          _proc_nodes.push_back(u);
232 233
          heap.pop();
233 234

	
234 235
          // Traverse outgoing residual arcs
235
          for (int a = _first_out[u]; a != _first_out[u+1]; ++a) {
236
          int last_out = _geq ? _first_out[u+1] : _first_out[u+1] - 1;
237
          for (int a = _first_out[u]; a != last_out; ++a) {
236 238
            if (_res_cap[a] < delta) continue;
237 239
            v = _target[a];
238 240
            switch (heap.state(v)) {
239 241
              case Heap::PRE_HEAP:
240 242
                heap.push(v, d + _cost[a] - _pi[v]);
241 243
                _pred[v] = a;
... ...
@@ -684,28 +686,31 @@
684 686
      _sum_supply = 0;
685 687
      for (int i = 0; i != _root; ++i) {
686 688
        _sum_supply += _supply[i];
687 689
      }
688 690
      if (_sum_supply > 0) return INFEASIBLE;
689 691
      
690
      // Initialize maps
692
      // Initialize vectors
691 693
      for (int i = 0; i != _root; ++i) {
692 694
        _pi[i] = 0;
693 695
        _excess[i] = _supply[i];
694 696
      }
695 697

	
696 698
      // Remove non-zero lower bounds
699
      const Value MAX = std::numeric_limits<Value>::max();
700
      int last_out;
697 701
      if (_have_lower) {
698 702
        for (int i = 0; i != _root; ++i) {
699
          for (int j = _first_out[i]; j != _first_out[i+1]; ++j) {
703
          last_out = _first_out[i+1];
704
          for (int j = _first_out[i]; j != last_out; ++j) {
700 705
            if (_forward[j]) {
701 706
              Value c = _lower[j];
702 707
              if (c >= 0) {
703
                _res_cap[j] = _upper[j] < INF ? _upper[j] - c : INF;
708
                _res_cap[j] = _upper[j] < MAX ? _upper[j] - c : INF;
704 709
              } else {
705
                _res_cap[j] = _upper[j] < INF + c ? _upper[j] - c : INF;
710
                _res_cap[j] = _upper[j] < MAX + c ? _upper[j] - c : INF;
706 711
              }
707 712
              _excess[i] -= c;
708 713
              _excess[_target[j]] += c;
709 714
            } else {
710 715
              _res_cap[j] = 0;
711 716
            }
... ...
@@ -715,58 +720,57 @@
715 720
        for (int j = 0; j != _res_arc_num; ++j) {
716 721
          _res_cap[j] = _forward[j] ? _upper[j] : 0;
717 722
        }
718 723
      }
719 724

	
720 725
      // Handle negative costs
721
      for (int u = 0; u != _root; ++u) {
722
        for (int a = _first_out[u]; a != _first_out[u+1]; ++a) {
723
          Value rc = _res_cap[a];
724
          if (_cost[a] < 0 && rc > 0) {
725
            if (rc == INF) return UNBOUNDED;
726
            _excess[u] -= rc;
727
            _excess[_target[a]] += rc;
728
            _res_cap[a] = 0;
729
            _res_cap[_reverse[a]] += rc;
726
      for (int i = 0; i != _root; ++i) {
727
        last_out = _first_out[i+1] - 1;
728
        for (int j = _first_out[i]; j != last_out; ++j) {
729
          Value rc = _res_cap[j];
730
          if (_cost[j] < 0 && rc > 0) {
731
            if (rc >= MAX) return UNBOUNDED;
732
            _excess[i] -= rc;
733
            _excess[_target[j]] += rc;
734
            _res_cap[j] = 0;
735
            _res_cap[_reverse[j]] += rc;
730 736
          }
731 737
        }
732 738
      }
733 739
      
734 740
      // Handle GEQ supply type
735 741
      if (_sum_supply < 0) {
736 742
        _pi[_root] = 0;
737 743
        _excess[_root] = -_sum_supply;
738 744
        for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
739
          int u = _target[a];
740
          if (_excess[u] < 0) {
741
            _res_cap[a] = -_excess[u] + 1;
742
          } else {
743
            _res_cap[a] = 1;
744
          }
745
          _res_cap[_reverse[a]] = 0;
745
          int ra = _reverse[a];
746
          _res_cap[a] = -_sum_supply + 1;
747
          _res_cap[ra] = 0;
746 748
          _cost[a] = 0;
747
          _cost[_reverse[a]] = 0;
749
          _cost[ra] = 0;
748 750
        }
749 751
      } else {
750 752
        _pi[_root] = 0;
751 753
        _excess[_root] = 0;
752 754
        for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
755
          int ra = _reverse[a];
753 756
          _res_cap[a] = 1;
754
          _res_cap[_reverse[a]] = 0;
757
          _res_cap[ra] = 0;
755 758
          _cost[a] = 0;
756
          _cost[_reverse[a]] = 0;
759
          _cost[ra] = 0;
757 760
        }
758 761
      }
759 762

	
760 763
      // Initialize delta value
761 764
      if (_factor > 1) {
762 765
        // With scaling
763 766
        Value max_sup = 0, max_dem = 0;
764 767
        for (int i = 0; i != _node_num; ++i) {
765
          if ( _excess[i] > max_sup) max_sup =  _excess[i];
766
          if (-_excess[i] > max_dem) max_dem = -_excess[i];
768
          Value ex = _excess[i];
769
          if ( ex > max_sup) max_sup =  ex;
770
          if (-ex > max_dem) max_dem = -ex;
767 771
        }
768 772
        Value max_cap = 0;
769 773
        for (int j = 0; j != _res_arc_num; ++j) {
770 774
          if (_res_cap[j] > max_cap) max_cap = _res_cap[j];
771 775
        }
772 776
        max_sup = std::min(std::min(max_sup, max_dem), max_cap);
... ...
@@ -786,13 +790,14 @@
786 790
        pt = startWithScaling();
787 791
      else
788 792
        pt = startWithoutScaling();
789 793

	
790 794
      // Handle non-zero lower bounds
791 795
      if (_have_lower) {
792
        for (int j = 0; j != _res_arc_num - _node_num + 1; ++j) {
796
        int limit = _first_out[_root];
797
        for (int j = 0; j != limit; ++j) {
793 798
          if (!_forward[j]) _res_cap[j] += _lower[j];
794 799
        }
795 800
      }
796 801

	
797 802
      // Shift potentials if necessary
798 803
      Cost pr = _pi[_root];
... ...
@@ -809,14 +814,17 @@
809 814
    ProblemType startWithScaling() {
810 815
      // Perform capacity scaling phases
811 816
      int s, t;
812 817
      ResidualDijkstra _dijkstra(*this);
813 818
      while (true) {
814 819
        // Saturate all arcs not satisfying the optimality condition
820
        int last_out;
815 821
        for (int u = 0; u != _node_num; ++u) {
816
          for (int a = _first_out[u]; a != _first_out[u+1]; ++a) {
822
          last_out = _sum_supply < 0 ?
823
            _first_out[u+1] : _first_out[u+1] - 1;
824
          for (int a = _first_out[u]; a != last_out; ++a) {
817 825
            int v = _target[a];
818 826
            Cost c = _cost[a] + _pi[u] - _pi[v];
819 827
            Value rc = _res_cap[a];
820 828
            if (c < 0 && rc >= _delta) {
821 829
              _excess[u] -= rc;
822 830
              _excess[v] += rc;
... ...
@@ -827,14 +835,15 @@
827 835
        }
828 836

	
829 837
        // Find excess nodes and deficit nodes
830 838
        _excess_nodes.clear();
831 839
        _deficit_nodes.clear();
832 840
        for (int u = 0; u != _node_num; ++u) {
833
          if (_excess[u] >=  _delta) _excess_nodes.push_back(u);
834
          if (_excess[u] <= -_delta) _deficit_nodes.push_back(u);
841
          Value ex = _excess[u];
842
          if (ex >=  _delta) _excess_nodes.push_back(u);
843
          if (ex <= -_delta) _deficit_nodes.push_back(u);
835 844
        }
836 845
        int next_node = 0, next_def_node = 0;
837 846

	
838 847
        // Find augmenting shortest paths
839 848
        while (next_node < int(_excess_nodes.size())) {
840 849
          // Check deficit nodes
Ignore white space 12 line context
... ...
@@ -161,13 +161,13 @@
161 161
    
162 162
  private:
163 163

	
164 164
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
165 165

	
166 166
    typedef std::vector<int> IntVector;
167
    typedef std::vector<bool> BoolVector;
167
    typedef std::vector<char> CharVector;
168 168
    typedef std::vector<Value> ValueVector;
169 169
    typedef std::vector<Cost> CostVector;
170 170

	
171 171
    // State constants for arcs
172 172
    enum ArcStateEnum {
173 173
      STATE_UPPER = -1,
... ...
@@ -209,21 +209,23 @@
209 209
    IntVector _pred;
210 210
    IntVector _thread;
211 211
    IntVector _rev_thread;
212 212
    IntVector _succ_num;
213 213
    IntVector _last_succ;
214 214
    IntVector _dirty_revs;
215
    BoolVector _forward;
216
    IntVector _state;
215
    CharVector _forward;
216
    CharVector _state;
217 217
    int _root;
218 218

	
219 219
    // Temporary data used in the current pivot iteration
220 220
    int in_arc, join, u_in, v_in, u_out, v_out;
221 221
    int first, second, right, last;
222 222
    int stem, par_stem, new_stem;
223 223
    Value delta;
224
    
225
    const Value MAX;
224 226

	
225 227
  public:
226 228
  
227 229
    /// \brief Constant for infinite upper bounds (capacities).
228 230
    ///
229 231
    /// Constant for infinite upper bounds (capacities).
... ...
@@ -239,13 +241,13 @@
239 241
    private:
240 242

	
241 243
      // References to the NetworkSimplex class
242 244
      const IntVector  &_source;
243 245
      const IntVector  &_target;
244 246
      const CostVector &_cost;
245
      const IntVector  &_state;
247
      const CharVector &_state;
246 248
      const CostVector &_pi;
247 249
      int &_in_arc;
248 250
      int _search_arc_num;
249 251

	
250 252
      // Pivot rule data
251 253
      int _next_arc;
... ...
@@ -291,13 +293,13 @@
291 293
    private:
292 294

	
293 295
      // References to the NetworkSimplex class
294 296
      const IntVector  &_source;
295 297
      const IntVector  &_target;
296 298
      const CostVector &_cost;
297
      const IntVector  &_state;
299
      const CharVector &_state;
298 300
      const CostVector &_pi;
299 301
      int &_in_arc;
300 302
      int _search_arc_num;
301 303

	
302 304
    public:
303 305

	
... ...
@@ -330,13 +332,13 @@
330 332
    private:
331 333

	
332 334
      // References to the NetworkSimplex class
333 335
      const IntVector  &_source;
334 336
      const IntVector  &_target;
335 337
      const CostVector &_cost;
336
      const IntVector  &_state;
338
      const CharVector &_state;
337 339
      const CostVector &_pi;
338 340
      int &_in_arc;
339 341
      int _search_arc_num;
340 342

	
341 343
      // Pivot rule data
342 344
      int _block_size;
... ...
@@ -403,13 +405,13 @@
403 405
    private:
404 406

	
405 407
      // References to the NetworkSimplex class
406 408
      const IntVector  &_source;
407 409
      const IntVector  &_target;
408 410
      const CostVector &_cost;
409
      const IntVector  &_state;
411
      const CharVector &_state;
410 412
      const CostVector &_pi;
411 413
      int &_in_arc;
412 414
      int _search_arc_num;
413 415

	
414 416
      // Pivot rule data
415 417
      IntVector _candidates;
... ...
@@ -506,13 +508,13 @@
506 508
    private:
507 509

	
508 510
      // References to the NetworkSimplex class
509 511
      const IntVector  &_source;
510 512
      const IntVector  &_target;
511 513
      const CostVector &_cost;
512
      const IntVector  &_state;
514
      const CharVector &_state;
513 515
      const CostVector &_pi;
514 516
      int &_in_arc;
515 517
      int _search_arc_num;
516 518

	
517 519
      // Pivot rule data
518 520
      int _block_size, _head_length, _curr_length;
... ...
@@ -628,15 +630,15 @@
628 630
    /// \param arc_mixing Indicate if the arcs have to be stored in a
629 631
    /// mixed order in the internal data structure. 
630 632
    /// In special cases, it could lead to better overall performance,
631 633
    /// but it is usually slower. Therefore it is disabled by default.
632 634
    NetworkSimplex(const GR& graph, bool arc_mixing = false) :
633 635
      _graph(graph), _node_id(graph), _arc_id(graph),
636
      MAX(std::numeric_limits<Value>::max()),
634 637
      INF(std::numeric_limits<Value>::has_infinity ?
635
          std::numeric_limits<Value>::infinity() :
636
          std::numeric_limits<Value>::max())
638
          std::numeric_limits<Value>::infinity() : MAX)
637 639
    {
638 640
      // Check the value types
639 641
      LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
640 642
        "The flow type of NetworkSimplex must be signed");
641 643
      LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
642 644
        "The cost type of NetworkSimplex must be signed");
... ...
@@ -1017,15 +1019,15 @@
1017 1019

	
1018 1020
      // Remove non-zero lower bounds
1019 1021
      if (_have_lower) {
1020 1022
        for (int i = 0; i != _arc_num; ++i) {
1021 1023
          Value c = _lower[i];
1022 1024
          if (c >= 0) {
1023
            _cap[i] = _upper[i] < INF ? _upper[i] - c : INF;
1025
            _cap[i] = _upper[i] < MAX ? _upper[i] - c : INF;
1024 1026
          } else {
1025
            _cap[i] = _upper[i] < INF + c ? _upper[i] - c : INF;
1027
            _cap[i] = _upper[i] < MAX + c ? _upper[i] - c : INF;
1026 1028
          }
1027 1029
          _supply[_source[i]] -= c;
1028 1030
          _supply[_target[i]] += c;
1029 1031
        }
1030 1032
      } else {
1031 1033
        for (int i = 0; i != _arc_num; ++i) {
... ...
@@ -1211,24 +1213,24 @@
1211 1213
      int e;
1212 1214

	
1213 1215
      // Search the cycle along the path form the first node to the root
1214 1216
      for (int u = first; u != join; u = _parent[u]) {
1215 1217
        e = _pred[u];
1216 1218
        d = _forward[u] ?
1217
          _flow[e] : (_cap[e] == INF ? INF : _cap[e] - _flow[e]);
1219
          _flow[e] : (_cap[e] >= MAX ? INF : _cap[e] - _flow[e]);
1218 1220
        if (d < delta) {
1219 1221
          delta = d;
1220 1222
          u_out = u;
1221 1223
          result = 1;
1222 1224
        }
1223 1225
      }
1224 1226
      // Search the cycle along the path form the second node to the root
1225 1227
      for (int u = second; u != join; u = _parent[u]) {
1226 1228
        e = _pred[u];
1227 1229
        d = _forward[u] ? 
1228
          (_cap[e] == INF ? INF : _cap[e] - _flow[e]) : _flow[e];
1230
          (_cap[e] >= MAX ? INF : _cap[e] - _flow[e]) : _flow[e];
1229 1231
        if (d <= delta) {
1230 1232
          delta = d;
1231 1233
          u_out = u;
1232 1234
          result = 2;
1233 1235
        }
1234 1236
      }
... ...
@@ -1421,13 +1423,13 @@
1421 1423
      PivotRuleImpl pivot(*this);
1422 1424

	
1423 1425
      // Execute the Network Simplex algorithm
1424 1426
      while (pivot.findEnteringArc()) {
1425 1427
        findJoinNode();
1426 1428
        bool change = findLeavingArc();
1427
        if (delta >= INF) return UNBOUNDED;
1429
        if (delta >= MAX) return UNBOUNDED;
1428 1430
        changeFlow(change);
1429 1431
        if (change) {
1430 1432
          updateTreeStructure();
1431 1433
          updatePotential();
1432 1434
        }
1433 1435
      }
0 comments (0 inline)