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 96 line context
... ...
@@ -88,196 +88,198 @@
88 88
  template <typename GR, typename V, typename C, typename TR>
89 89
#else
90 90
  template < typename GR, typename V = int, typename C = V,
91 91
             typename TR = CapacityScalingDefaultTraits<GR, V, C> >
92 92
#endif
93 93
  class CapacityScaling
94 94
  {
95 95
  public:
96 96

	
97 97
    /// The type of the digraph
98 98
    typedef typename TR::Digraph Digraph;
99 99
    /// The type of the flow amounts, capacity bounds and supply values
100 100
    typedef typename TR::Value Value;
101 101
    /// The type of the arc costs
102 102
    typedef typename TR::Cost Cost;
103 103

	
104 104
    /// The type of the heap used for internal Dijkstra computations
105 105
    typedef typename TR::Heap Heap;
106 106

	
107 107
    /// The \ref CapacityScalingDefaultTraits "traits class" of the algorithm
108 108
    typedef TR Traits;
109 109

	
110 110
  public:
111 111

	
112 112
    /// \brief Problem type constants for the \c run() function.
113 113
    ///
114 114
    /// Enum type containing the problem type constants that can be
115 115
    /// returned by the \ref run() function of the algorithm.
116 116
    enum ProblemType {
117 117
      /// The problem has no feasible solution (flow).
118 118
      INFEASIBLE,
119 119
      /// The problem has optimal solution (i.e. it is feasible and
120 120
      /// bounded), and the algorithm has found optimal flow and node
121 121
      /// potentials (primal and dual solutions).
122 122
      OPTIMAL,
123 123
      /// The digraph contains an arc of negative cost and infinite
124 124
      /// upper bound. It means that the objective function is unbounded
125 125
      /// on that arc, however note that it could actually be bounded
126 126
      /// over the feasible flows, but this algroithm cannot handle
127 127
      /// these cases.
128 128
      UNBOUNDED
129 129
    };
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
143 143
    const GR &_graph;
144 144
    int _node_num;
145 145
    int _arc_num;
146 146
    int _res_arc_num;
147 147
    int _root;
148 148

	
149 149
    // Parameters of the problem
150 150
    bool _have_lower;
151 151
    Value _sum_supply;
152 152

	
153 153
    // Data structures for storing the digraph
154 154
    IntNodeMap _node_id;
155 155
    IntArcMap _arc_idf;
156 156
    IntArcMap _arc_idb;
157 157
    IntVector _first_out;
158 158
    BoolVector _forward;
159 159
    IntVector _source;
160 160
    IntVector _target;
161 161
    IntVector _reverse;
162 162

	
163 163
    // Node and arc data
164 164
    ValueVector _lower;
165 165
    ValueVector _upper;
166 166
    CostVector _cost;
167 167
    ValueVector _supply;
168 168

	
169 169
    ValueVector _res_cap;
170 170
    CostVector _pi;
171 171
    ValueVector _excess;
172 172
    IntVector _excess_nodes;
173 173
    IntVector _deficit_nodes;
174 174

	
175 175
    Value _delta;
176 176
    int _factor;
177 177
    IntVector _pred;
178 178

	
179 179
  public:
180 180
  
181 181
    /// \brief Constant for infinite upper bounds (capacities).
182 182
    ///
183 183
    /// Constant for infinite upper bounds (capacities).
184 184
    /// It is \c std::numeric_limits<Value>::infinity() if available,
185 185
    /// \c std::numeric_limits<Value>::max() otherwise.
186 186
    const Value INF;
187 187

	
188 188
  private:
189 189

	
190 190
    // Special implementation of the Dijkstra algorithm for finding
191 191
    // shortest paths in the residual network of the digraph with
192 192
    // respect to the reduced arc costs and modifying the node
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;
205 206
      IntVector &_pred;
206 207
      
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);
223 224
        _pred[s] = -1;
224 225
        _proc_nodes.clear();
225 226

	
226 227
        // Process nodes
227 228
        while (!heap.empty() && _excess[heap.top()] > -delta) {
228 229
          int u = heap.top(), v;
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;
242 244
                break;
243 245
              case Heap::IN_HEAP:
244 246
                dn = d + _cost[a] - _pi[v];
245 247
                if (dn < heap[v]) {
246 248
                  heap.decrease(v, dn);
247 249
                  _pred[v] = a;
248 250
                }
249 251
                break;
250 252
              case Heap::POST_HEAP:
251 253
                break;
252 254
            }
253 255
          }
254 256
        }
255 257
        if (heap.empty()) return -1;
256 258

	
257 259
        // Update potentials of processed nodes
258 260
        int t = heap.top();
259 261
        Cost dt = heap.prio();
260 262
        for (int i = 0; i < int(_proc_nodes.size()); ++i) {
261 263
          _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - dt;
262 264
        }
263 265

	
264 266
        return t;
265 267
      }
266 268

	
267 269
    }; //class ResidualDijkstra
268 270

	
269 271
  public:
270 272

	
271 273
    /// \name Named Template Parameters
272 274
    /// @{
273 275

	
274 276
    template <typename T>
275 277
    struct SetHeapTraits : public Traits {
276 278
      typedef T Heap;
277 279
    };
278 280

	
279 281
    /// \brief \ref named-templ-param "Named parameter" for setting
280 282
    /// \c Heap type.
281 283
    ///
282 284
    /// \ref named-templ-param "Named parameter" for setting \c Heap
283 285
    /// type, which is used for internal Dijkstra computations.
... ...
@@ -642,241 +644,248 @@
642 644
    /// \pre \ref run() must be called before using this function.
643 645
    template <typename FlowMap>
644 646
    void flowMap(FlowMap &map) const {
645 647
      for (ArcIt a(_graph); a != INVALID; ++a) {
646 648
        map.set(a, _res_cap[_arc_idb[a]]);
647 649
      }
648 650
    }
649 651

	
650 652
    /// \brief Return the potential (dual value) of the given node.
651 653
    ///
652 654
    /// This function returns the potential (dual value) of the
653 655
    /// given node.
654 656
    ///
655 657
    /// \pre \ref run() must be called before using this function.
656 658
    Cost potential(const Node& n) const {
657 659
      return _pi[_node_id[n]];
658 660
    }
659 661

	
660 662
    /// \brief Return the potential map (the dual solution).
661 663
    ///
662 664
    /// This function copies the potential (dual value) of each node
663 665
    /// into the given map.
664 666
    /// The \c Cost type of the algorithm must be convertible to the
665 667
    /// \c Value type of the map.
666 668
    ///
667 669
    /// \pre \ref run() must be called before using this function.
668 670
    template <typename PotentialMap>
669 671
    void potentialMap(PotentialMap &map) const {
670 672
      for (NodeIt n(_graph); n != INVALID; ++n) {
671 673
        map.set(n, _pi[_node_id[n]]);
672 674
      }
673 675
    }
674 676

	
675 677
    /// @}
676 678

	
677 679
  private:
678 680

	
679 681
    // Initialize the algorithm
680 682
    ProblemType init() {
681 683
      if (_node_num == 0) return INFEASIBLE;
682 684

	
683 685
      // Check the sum of supply values
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
            }
712 717
          }
713 718
        }
714 719
      } else {
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);
773 777
        for (_delta = 1; 2 * _delta <= max_sup; _delta *= 2) ;
774 778
      } else {
775 779
        // Without scaling
776 780
        _delta = 1;
777 781
      }
778 782

	
779 783
      return OPTIMAL;
780 784
    }
781 785

	
782 786
    ProblemType start() {
783 787
      // Execute the algorithm
784 788
      ProblemType pt;
785 789
      if (_delta > 1)
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];
799 804
      if (_sum_supply < 0 || pr > 0) {
800 805
        for (int i = 0; i != _node_num; ++i) {
801 806
          _pi[i] -= pr;
802 807
        }        
803 808
      }
804 809
      
805 810
      return pt;
806 811
    }
807 812

	
808 813
    // Execute the capacity scaling algorithm
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;
823 831
              _res_cap[a] = 0;
824 832
              _res_cap[_reverse[a]] += rc;
825 833
            }
826 834
          }
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
841 850
          if (_delta > 1) {
842 851
            bool delta_deficit = false;
843 852
            for ( ; next_def_node < int(_deficit_nodes.size());
844 853
                    ++next_def_node ) {
845 854
              if (_excess[_deficit_nodes[next_def_node]] <= -_delta) {
846 855
                delta_deficit = true;
847 856
                break;
848 857
              }
849 858
            }
850 859
            if (!delta_deficit) break;
851 860
          }
852 861

	
853 862
          // Run Dijkstra in the residual network
854 863
          s = _excess_nodes[next_node];
855 864
          if ((t = _dijkstra.run(s, _delta)) == -1) {
856 865
            if (_delta > 1) {
857 866
              ++next_node;
858 867
              continue;
859 868
            }
860 869
            return INFEASIBLE;
861 870
          }
862 871

	
863 872
          // Augment along a shortest path from s to t
864 873
          Value d = std::min(_excess[s], -_excess[t]);
865 874
          int u = t;
866 875
          int a;
867 876
          if (d > _delta) {
868 877
            while ((a = _pred[u]) != -1) {
869 878
              if (_res_cap[a] < d) d = _res_cap[a];
870 879
              u = _source[a];
871 880
            }
872 881
          }
873 882
          u = t;
874 883
          while ((a = _pred[u]) != -1) {
875 884
            _res_cap[a] -= d;
876 885
            _res_cap[_reverse[a]] += d;
877 886
            u = _source[a];
878 887
          }
879 888
          _excess[s] -= d;
880 889
          _excess[t] += d;
881 890

	
882 891
          if (_excess[s] < _delta) ++next_node;
Ignore white space 96 line context
... ...
@@ -119,339 +119,341 @@
119 119
    /// \brief Constants for selecting the pivot rule.
120 120
    ///
121 121
    /// Enum type containing constants for selecting the pivot rule for
122 122
    /// the \ref run() function.
123 123
    ///
124 124
    /// \ref NetworkSimplex provides five different pivot rule
125 125
    /// implementations that significantly affect the running time
126 126
    /// of the algorithm.
127 127
    /// By default, \ref BLOCK_SEARCH "Block Search" is used, which
128 128
    /// proved to be the most efficient and the most robust on various
129 129
    /// test inputs according to our benchmark tests.
130 130
    /// However, another pivot rule can be selected using the \ref run()
131 131
    /// function with the proper parameter.
132 132
    enum PivotRule {
133 133

	
134 134
      /// The \e First \e Eligible pivot rule.
135 135
      /// The next eligible arc is selected in a wraparound fashion
136 136
      /// in every iteration.
137 137
      FIRST_ELIGIBLE,
138 138

	
139 139
      /// The \e Best \e Eligible pivot rule.
140 140
      /// The best eligible arc is selected in every iteration.
141 141
      BEST_ELIGIBLE,
142 142

	
143 143
      /// The \e Block \e Search pivot rule.
144 144
      /// A specified number of arcs are examined in every iteration
145 145
      /// in a wraparound fashion and the best eligible arc is selected
146 146
      /// from this block.
147 147
      BLOCK_SEARCH,
148 148

	
149 149
      /// The \e Candidate \e List pivot rule.
150 150
      /// In a major iteration a candidate list is built from eligible arcs
151 151
      /// in a wraparound fashion and in the following minor iterations
152 152
      /// the best eligible arc is selected from this list.
153 153
      CANDIDATE_LIST,
154 154

	
155 155
      /// The \e Altering \e Candidate \e List pivot rule.
156 156
      /// It is a modified version of the Candidate List method.
157 157
      /// It keeps only the several best eligible arcs from the former
158 158
      /// candidate list and extends this list in every iteration.
159 159
      ALTERING_LIST
160 160
    };
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,
174 174
      STATE_TREE  =  0,
175 175
      STATE_LOWER =  1
176 176
    };
177 177

	
178 178
  private:
179 179

	
180 180
    // Data related to the underlying digraph
181 181
    const GR &_graph;
182 182
    int _node_num;
183 183
    int _arc_num;
184 184
    int _all_arc_num;
185 185
    int _search_arc_num;
186 186

	
187 187
    // Parameters of the problem
188 188
    bool _have_lower;
189 189
    SupplyType _stype;
190 190
    Value _sum_supply;
191 191

	
192 192
    // Data structures for storing the digraph
193 193
    IntNodeMap _node_id;
194 194
    IntArcMap _arc_id;
195 195
    IntVector _source;
196 196
    IntVector _target;
197 197

	
198 198
    // Node and arc data
199 199
    ValueVector _lower;
200 200
    ValueVector _upper;
201 201
    ValueVector _cap;
202 202
    CostVector _cost;
203 203
    ValueVector _supply;
204 204
    ValueVector _flow;
205 205
    CostVector _pi;
206 206

	
207 207
    // Data for storing the spanning tree structure
208 208
    IntVector _parent;
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).
230 232
    /// It is \c std::numeric_limits<Value>::infinity() if available,
231 233
    /// \c std::numeric_limits<Value>::max() otherwise.
232 234
    const Value INF;
233 235

	
234 236
  private:
235 237

	
236 238
    // Implementation of the First Eligible pivot rule
237 239
    class FirstEligiblePivotRule
238 240
    {
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;
252 254

	
253 255
    public:
254 256

	
255 257
      // Constructor
256 258
      FirstEligiblePivotRule(NetworkSimplex &ns) :
257 259
        _source(ns._source), _target(ns._target),
258 260
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
259 261
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
260 262
        _next_arc(0)
261 263
      {}
262 264

	
263 265
      // Find next entering arc
264 266
      bool findEnteringArc() {
265 267
        Cost c;
266 268
        for (int e = _next_arc; e < _search_arc_num; ++e) {
267 269
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
268 270
          if (c < 0) {
269 271
            _in_arc = e;
270 272
            _next_arc = e + 1;
271 273
            return true;
272 274
          }
273 275
        }
274 276
        for (int e = 0; e < _next_arc; ++e) {
275 277
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
276 278
          if (c < 0) {
277 279
            _in_arc = e;
278 280
            _next_arc = e + 1;
279 281
            return true;
280 282
          }
281 283
        }
282 284
        return false;
283 285
      }
284 286

	
285 287
    }; //class FirstEligiblePivotRule
286 288

	
287 289

	
288 290
    // Implementation of the Best Eligible pivot rule
289 291
    class BestEligiblePivotRule
290 292
    {
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

	
304 306
      // Constructor
305 307
      BestEligiblePivotRule(NetworkSimplex &ns) :
306 308
        _source(ns._source), _target(ns._target),
307 309
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
308 310
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num)
309 311
      {}
310 312

	
311 313
      // Find next entering arc
312 314
      bool findEnteringArc() {
313 315
        Cost c, min = 0;
314 316
        for (int e = 0; e < _search_arc_num; ++e) {
315 317
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
316 318
          if (c < min) {
317 319
            min = c;
318 320
            _in_arc = e;
319 321
          }
320 322
        }
321 323
        return min < 0;
322 324
      }
323 325

	
324 326
    }; //class BestEligiblePivotRule
325 327

	
326 328

	
327 329
    // Implementation of the Block Search pivot rule
328 330
    class BlockSearchPivotRule
329 331
    {
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;
343 345
      int _next_arc;
344 346

	
345 347
    public:
346 348

	
347 349
      // Constructor
348 350
      BlockSearchPivotRule(NetworkSimplex &ns) :
349 351
        _source(ns._source), _target(ns._target),
350 352
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
351 353
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
352 354
        _next_arc(0)
353 355
      {
354 356
        // The main parameters of the pivot rule
355 357
        const double BLOCK_SIZE_FACTOR = 0.5;
356 358
        const int MIN_BLOCK_SIZE = 10;
357 359

	
358 360
        _block_size = std::max( int(BLOCK_SIZE_FACTOR *
359 361
                                    std::sqrt(double(_search_arc_num))),
360 362
                                MIN_BLOCK_SIZE );
361 363
      }
362 364

	
363 365
      // Find next entering arc
364 366
      bool findEnteringArc() {
365 367
        Cost c, min = 0;
366 368
        int cnt = _block_size;
367 369
        int e;
368 370
        for (e = _next_arc; e < _search_arc_num; ++e) {
369 371
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
370 372
          if (c < min) {
371 373
            min = c;
372 374
            _in_arc = e;
373 375
          }
374 376
          if (--cnt == 0) {
375 377
            if (min < 0) goto search_end;
376 378
            cnt = _block_size;
377 379
          }
378 380
        }
379 381
        for (e = 0; e < _next_arc; ++e) {
380 382
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
381 383
          if (c < min) {
382 384
            min = c;
383 385
            _in_arc = e;
384 386
          }
385 387
          if (--cnt == 0) {
386 388
            if (min < 0) goto search_end;
387 389
            cnt = _block_size;
388 390
          }
389 391
        }
390 392
        if (min >= 0) return false;
391 393

	
392 394
      search_end:
393 395
        _next_arc = e;
394 396
        return true;
395 397
      }
396 398

	
397 399
    }; //class BlockSearchPivotRule
398 400

	
399 401

	
400 402
    // Implementation of the Candidate List pivot rule
401 403
    class CandidateListPivotRule
402 404
    {
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;
416 418
      int _list_length, _minor_limit;
417 419
      int _curr_length, _minor_count;
418 420
      int _next_arc;
419 421

	
420 422
    public:
421 423

	
422 424
      /// Constructor
423 425
      CandidateListPivotRule(NetworkSimplex &ns) :
424 426
        _source(ns._source), _target(ns._target),
425 427
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
426 428
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
427 429
        _next_arc(0)
428 430
      {
429 431
        // The main parameters of the pivot rule
430 432
        const double LIST_LENGTH_FACTOR = 0.25;
431 433
        const int MIN_LIST_LENGTH = 10;
432 434
        const double MINOR_LIMIT_FACTOR = 0.1;
433 435
        const int MIN_MINOR_LIMIT = 3;
434 436

	
435 437
        _list_length = std::max( int(LIST_LENGTH_FACTOR *
436 438
                                     std::sqrt(double(_search_arc_num))),
437 439
                                 MIN_LIST_LENGTH );
438 440
        _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
439 441
                                 MIN_MINOR_LIMIT );
440 442
        _curr_length = _minor_count = 0;
441 443
        _candidates.resize(_list_length);
442 444
      }
443 445

	
444 446
      /// Find next entering arc
445 447
      bool findEnteringArc() {
446 448
        Cost min, c;
447 449
        int e;
448 450
        if (_curr_length > 0 && _minor_count < _minor_limit) {
449 451
          // Minor iteration: select the best eligible arc from the
450 452
          // current candidate list
451 453
          ++_minor_count;
452 454
          min = 0;
453 455
          for (int i = 0; i < _curr_length; ++i) {
454 456
            e = _candidates[i];
455 457
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
456 458
            if (c < min) {
457 459
              min = c;
... ...
@@ -464,97 +466,97 @@
464 466
          if (min < 0) return true;
465 467
        }
466 468

	
467 469
        // Major iteration: build a new candidate list
468 470
        min = 0;
469 471
        _curr_length = 0;
470 472
        for (e = _next_arc; e < _search_arc_num; ++e) {
471 473
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
472 474
          if (c < 0) {
473 475
            _candidates[_curr_length++] = e;
474 476
            if (c < min) {
475 477
              min = c;
476 478
              _in_arc = e;
477 479
            }
478 480
            if (_curr_length == _list_length) goto search_end;
479 481
          }
480 482
        }
481 483
        for (e = 0; e < _next_arc; ++e) {
482 484
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
483 485
          if (c < 0) {
484 486
            _candidates[_curr_length++] = e;
485 487
            if (c < min) {
486 488
              min = c;
487 489
              _in_arc = e;
488 490
            }
489 491
            if (_curr_length == _list_length) goto search_end;
490 492
          }
491 493
        }
492 494
        if (_curr_length == 0) return false;
493 495
      
494 496
      search_end:        
495 497
        _minor_count = 1;
496 498
        _next_arc = e;
497 499
        return true;
498 500
      }
499 501

	
500 502
    }; //class CandidateListPivotRule
501 503

	
502 504

	
503 505
    // Implementation of the Altering Candidate List pivot rule
504 506
    class AlteringListPivotRule
505 507
    {
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;
519 521
      int _next_arc;
520 522
      IntVector _candidates;
521 523
      CostVector _cand_cost;
522 524

	
523 525
      // Functor class to compare arcs during sort of the candidate list
524 526
      class SortFunc
525 527
      {
526 528
      private:
527 529
        const CostVector &_map;
528 530
      public:
529 531
        SortFunc(const CostVector &map) : _map(map) {}
530 532
        bool operator()(int left, int right) {
531 533
          return _map[left] > _map[right];
532 534
        }
533 535
      };
534 536

	
535 537
      SortFunc _sort_func;
536 538

	
537 539
    public:
538 540

	
539 541
      // Constructor
540 542
      AlteringListPivotRule(NetworkSimplex &ns) :
541 543
        _source(ns._source), _target(ns._target),
542 544
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
543 545
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
544 546
        _next_arc(0), _cand_cost(ns._search_arc_num), _sort_func(_cand_cost)
545 547
      {
546 548
        // The main parameters of the pivot rule
547 549
        const double BLOCK_SIZE_FACTOR = 1.0;
548 550
        const int MIN_BLOCK_SIZE = 10;
549 551
        const double HEAD_LENGTH_FACTOR = 0.1;
550 552
        const int MIN_HEAD_LENGTH = 3;
551 553

	
552 554
        _block_size = std::max( int(BLOCK_SIZE_FACTOR *
553 555
                                    std::sqrt(double(_search_arc_num))),
554 556
                                MIN_BLOCK_SIZE );
555 557
        _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
556 558
                                 MIN_HEAD_LENGTH );
557 559
        _candidates.resize(_head_length + _block_size);
558 560
        _curr_length = 0;
559 561
      }
560 562

	
... ...
@@ -586,99 +588,99 @@
586 588
            limit = 0;
587 589
            cnt = _block_size;
588 590
          }
589 591
        }
590 592
        for (e = 0; e < _next_arc; ++e) {
591 593
          _cand_cost[e] = _state[e] *
592 594
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
593 595
          if (_cand_cost[e] < 0) {
594 596
            _candidates[_curr_length++] = e;
595 597
          }
596 598
          if (--cnt == 0) {
597 599
            if (_curr_length > limit) goto search_end;
598 600
            limit = 0;
599 601
            cnt = _block_size;
600 602
          }
601 603
        }
602 604
        if (_curr_length == 0) return false;
603 605
        
604 606
      search_end:
605 607

	
606 608
        // Make heap of the candidate list (approximating a partial sort)
607 609
        make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
608 610
                   _sort_func );
609 611

	
610 612
        // Pop the first element of the heap
611 613
        _in_arc = _candidates[0];
612 614
        _next_arc = e;
613 615
        pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
614 616
                  _sort_func );
615 617
        _curr_length = std::min(_head_length, _curr_length - 1);
616 618
        return true;
617 619
      }
618 620

	
619 621
    }; //class AlteringListPivotRule
620 622

	
621 623
  public:
622 624

	
623 625
    /// \brief Constructor.
624 626
    ///
625 627
    /// The constructor of the class.
626 628
    ///
627 629
    /// \param graph The digraph the algorithm runs on.
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");
643 645
        
644 646
      // Resize vectors
645 647
      _node_num = countNodes(_graph);
646 648
      _arc_num = countArcs(_graph);
647 649
      int all_node_num = _node_num + 1;
648 650
      int max_arc_num = _arc_num + 2 * _node_num;
649 651

	
650 652
      _source.resize(max_arc_num);
651 653
      _target.resize(max_arc_num);
652 654

	
653 655
      _lower.resize(_arc_num);
654 656
      _upper.resize(_arc_num);
655 657
      _cap.resize(max_arc_num);
656 658
      _cost.resize(max_arc_num);
657 659
      _supply.resize(all_node_num);
658 660
      _flow.resize(max_arc_num);
659 661
      _pi.resize(all_node_num);
660 662

	
661 663
      _parent.resize(all_node_num);
662 664
      _pred.resize(all_node_num);
663 665
      _forward.resize(all_node_num);
664 666
      _thread.resize(all_node_num);
665 667
      _rev_thread.resize(all_node_num);
666 668
      _succ_num.resize(all_node_num);
667 669
      _last_succ.resize(all_node_num);
668 670
      _state.resize(max_arc_num);
669 671

	
670 672
      // Copy the graph
671 673
      int i = 0;
672 674
      for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
673 675
        _node_id[n] = i;
674 676
      }
675 677
      if (arc_mixing) {
676 678
        // Store the arcs in a mixed order
677 679
        int k = std::max(int(std::sqrt(double(_arc_num))), 10);
678 680
        int i = 0, j = 0;
679 681
        for (ArcIt a(_graph); a != INVALID; ++a) {
680 682
          _arc_id[a] = i;
681 683
          _source[i] = _node_id[_graph.source(a)];
682 684
          _target[i] = _node_id[_graph.target(a)];
683 685
          if ((i += k) >= _arc_num) i = ++j;
684 686
        }
... ...
@@ -975,99 +977,99 @@
975 977
    }
976 978

	
977 979
    /// \brief Return the potential (dual value) of the given node.
978 980
    ///
979 981
    /// This function returns the potential (dual value) of the
980 982
    /// given node.
981 983
    ///
982 984
    /// \pre \ref run() must be called before using this function.
983 985
    Cost potential(const Node& n) const {
984 986
      return _pi[_node_id[n]];
985 987
    }
986 988

	
987 989
    /// \brief Return the potential map (the dual solution).
988 990
    ///
989 991
    /// This function copies the potential (dual value) of each node
990 992
    /// into the given map.
991 993
    /// The \c Cost type of the algorithm must be convertible to the
992 994
    /// \c Value type of the map.
993 995
    ///
994 996
    /// \pre \ref run() must be called before using this function.
995 997
    template <typename PotentialMap>
996 998
    void potentialMap(PotentialMap &map) const {
997 999
      for (NodeIt n(_graph); n != INVALID; ++n) {
998 1000
        map.set(n, _pi[_node_id[n]]);
999 1001
      }
1000 1002
    }
1001 1003

	
1002 1004
    /// @}
1003 1005

	
1004 1006
  private:
1005 1007

	
1006 1008
    // Initialize internal data structures
1007 1009
    bool init() {
1008 1010
      if (_node_num == 0) return false;
1009 1011

	
1010 1012
      // Check the sum of supply values
1011 1013
      _sum_supply = 0;
1012 1014
      for (int i = 0; i != _node_num; ++i) {
1013 1015
        _sum_supply += _supply[i];
1014 1016
      }
1015 1017
      if ( !((_stype == GEQ && _sum_supply <= 0) ||
1016 1018
             (_stype == LEQ && _sum_supply >= 0)) ) return false;
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) {
1032 1034
          _cap[i] = _upper[i];
1033 1035
        }
1034 1036
      }
1035 1037

	
1036 1038
      // Initialize artifical cost
1037 1039
      Cost ART_COST;
1038 1040
      if (std::numeric_limits<Cost>::is_exact) {
1039 1041
        ART_COST = std::numeric_limits<Cost>::max() / 2 + 1;
1040 1042
      } else {
1041 1043
        ART_COST = std::numeric_limits<Cost>::min();
1042 1044
        for (int i = 0; i != _arc_num; ++i) {
1043 1045
          if (_cost[i] > ART_COST) ART_COST = _cost[i];
1044 1046
        }
1045 1047
        ART_COST = (ART_COST + 1) * _node_num;
1046 1048
      }
1047 1049

	
1048 1050
      // Initialize arc maps
1049 1051
      for (int i = 0; i != _arc_num; ++i) {
1050 1052
        _flow[i] = 0;
1051 1053
        _state[i] = STATE_LOWER;
1052 1054
      }
1053 1055
      
1054 1056
      // Set data for the artificial root node
1055 1057
      _root = _node_num;
1056 1058
      _parent[_root] = -1;
1057 1059
      _pred[_root] = -1;
1058 1060
      _thread[_root] = 0;
1059 1061
      _rev_thread[0] = _root;
1060 1062
      _succ_num[_root] = _node_num + 1;
1061 1063
      _last_succ[_root] = _root - 1;
1062 1064
      _supply[_root] = -_sum_supply;
1063 1065
      _pi[_root] = 0;
1064 1066

	
1065 1067
      // Add artificial arcs and initialize the spanning tree data structure
1066 1068
      if (_sum_supply == 0) {
1067 1069
        // EQ supply constraints
1068 1070
        _search_arc_num = _arc_num;
1069 1071
        _all_arc_num = _arc_num + _node_num;
1070 1072
        for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
1071 1073
          _parent[u] = _root;
1072 1074
          _pred[u] = e;
1073 1075
          _thread[u] = u + 1;
... ...
@@ -1169,108 +1171,108 @@
1169 1171
            _cap[e] = INF;
1170 1172
            _flow[e] = 0;
1171 1173
            _cost[e] = 0;
1172 1174
            _state[e] = STATE_LOWER;
1173 1175
            ++f;
1174 1176
          }
1175 1177
        }
1176 1178
        _all_arc_num = f;
1177 1179
      }
1178 1180

	
1179 1181
      return true;
1180 1182
    }
1181 1183

	
1182 1184
    // Find the join node
1183 1185
    void findJoinNode() {
1184 1186
      int u = _source[in_arc];
1185 1187
      int v = _target[in_arc];
1186 1188
      while (u != v) {
1187 1189
        if (_succ_num[u] < _succ_num[v]) {
1188 1190
          u = _parent[u];
1189 1191
        } else {
1190 1192
          v = _parent[v];
1191 1193
        }
1192 1194
      }
1193 1195
      join = u;
1194 1196
    }
1195 1197

	
1196 1198
    // Find the leaving arc of the cycle and returns true if the
1197 1199
    // leaving arc is not the same as the entering arc
1198 1200
    bool findLeavingArc() {
1199 1201
      // Initialize first and second nodes according to the direction
1200 1202
      // of the cycle
1201 1203
      if (_state[in_arc] == STATE_LOWER) {
1202 1204
        first  = _source[in_arc];
1203 1205
        second = _target[in_arc];
1204 1206
      } else {
1205 1207
        first  = _target[in_arc];
1206 1208
        second = _source[in_arc];
1207 1209
      }
1208 1210
      delta = _cap[in_arc];
1209 1211
      int result = 0;
1210 1212
      Value d;
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
      }
1235 1237

	
1236 1238
      if (result == 1) {
1237 1239
        u_in = first;
1238 1240
        v_in = second;
1239 1241
      } else {
1240 1242
        u_in = second;
1241 1243
        v_in = first;
1242 1244
      }
1243 1245
      return result != 0;
1244 1246
    }
1245 1247

	
1246 1248
    // Change _flow and _state vectors
1247 1249
    void changeFlow(bool change) {
1248 1250
      // Augment along the cycle
1249 1251
      if (delta > 0) {
1250 1252
        Value val = _state[in_arc] * delta;
1251 1253
        _flow[in_arc] += val;
1252 1254
        for (int u = _source[in_arc]; u != join; u = _parent[u]) {
1253 1255
          _flow[_pred[u]] += _forward[u] ? -val : val;
1254 1256
        }
1255 1257
        for (int u = _target[in_arc]; u != join; u = _parent[u]) {
1256 1258
          _flow[_pred[u]] += _forward[u] ? val : -val;
1257 1259
        }
1258 1260
      }
1259 1261
      // Update the state of the entering and leaving arcs
1260 1262
      if (change) {
1261 1263
        _state[in_arc] = STATE_TREE;
1262 1264
        _state[_pred[u_out]] =
1263 1265
          (_flow[_pred[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
1264 1266
      } else {
1265 1267
        _state[in_arc] = -_state[in_arc];
1266 1268
      }
1267 1269
    }
1268 1270

	
1269 1271
    // Update the tree structure
1270 1272
    void updateTreeStructure() {
1271 1273
      int u, w;
1272 1274
      int old_rev_thread = _rev_thread[u_out];
1273 1275
      int old_succ_num = _succ_num[u_out];
1274 1276
      int old_last_succ = _last_succ[u_out];
1275 1277
      v_out = _parent[u_out];
1276 1278

	
... ...
@@ -1379,97 +1381,97 @@
1379 1381
      // Update _succ_num from v_in to join
1380 1382
      for (u = v_in; u != join; u = _parent[u]) {
1381 1383
        _succ_num[u] += old_succ_num;
1382 1384
      }
1383 1385
      // Update _succ_num from v_out to join
1384 1386
      for (u = v_out; u != join; u = _parent[u]) {
1385 1387
        _succ_num[u] -= old_succ_num;
1386 1388
      }
1387 1389
    }
1388 1390

	
1389 1391
    // Update potentials
1390 1392
    void updatePotential() {
1391 1393
      Cost sigma = _forward[u_in] ?
1392 1394
        _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
1393 1395
        _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
1394 1396
      // Update potentials in the subtree, which has been moved
1395 1397
      int end = _thread[_last_succ[u_in]];
1396 1398
      for (int u = u_in; u != end; u = _thread[u]) {
1397 1399
        _pi[u] += sigma;
1398 1400
      }
1399 1401
    }
1400 1402

	
1401 1403
    // Execute the algorithm
1402 1404
    ProblemType start(PivotRule pivot_rule) {
1403 1405
      // Select the pivot rule implementation
1404 1406
      switch (pivot_rule) {
1405 1407
        case FIRST_ELIGIBLE:
1406 1408
          return start<FirstEligiblePivotRule>();
1407 1409
        case BEST_ELIGIBLE:
1408 1410
          return start<BestEligiblePivotRule>();
1409 1411
        case BLOCK_SEARCH:
1410 1412
          return start<BlockSearchPivotRule>();
1411 1413
        case CANDIDATE_LIST:
1412 1414
          return start<CandidateListPivotRule>();
1413 1415
        case ALTERING_LIST:
1414 1416
          return start<AlteringListPivotRule>();
1415 1417
      }
1416 1418
      return INFEASIBLE; // avoid warning
1417 1419
    }
1418 1420

	
1419 1421
    template <typename PivotRuleImpl>
1420 1422
    ProblemType start() {
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
      }
1434 1436
      
1435 1437
      // Check feasibility
1436 1438
      for (int e = _search_arc_num; e != _all_arc_num; ++e) {
1437 1439
        if (_flow[e] != 0) return INFEASIBLE;
1438 1440
      }
1439 1441

	
1440 1442
      // Transform the solution and the supply map to the original form
1441 1443
      if (_have_lower) {
1442 1444
        for (int i = 0; i != _arc_num; ++i) {
1443 1445
          Value c = _lower[i];
1444 1446
          if (c != 0) {
1445 1447
            _flow[i] += c;
1446 1448
            _supply[_source[i]] += c;
1447 1449
            _supply[_target[i]] -= c;
1448 1450
          }
1449 1451
        }
1450 1452
      }
1451 1453
      
1452 1454
      // Shift potentials to meet the requirements of the GEQ/LEQ type
1453 1455
      // optimality conditions
1454 1456
      if (_sum_supply == 0) {
1455 1457
        if (_stype == GEQ) {
1456 1458
          Cost max_pot = std::numeric_limits<Cost>::min();
1457 1459
          for (int i = 0; i != _node_num; ++i) {
1458 1460
            if (_pi[i] > max_pot) max_pot = _pi[i];
1459 1461
          }
1460 1462
          if (max_pot > 0) {
1461 1463
            for (int i = 0; i != _node_num; ++i)
1462 1464
              _pi[i] -= max_pot;
1463 1465
          }
1464 1466
        } else {
1465 1467
          Cost min_pot = std::numeric_limits<Cost>::max();
1466 1468
          for (int i = 0; i != _node_num; ++i) {
1467 1469
            if (_pi[i] < min_pot) min_pot = _pi[i];
1468 1470
          }
1469 1471
          if (min_pot < 0) {
1470 1472
            for (int i = 0; i != _node_num; ++i)
1471 1473
              _pi[i] -= min_pot;
1472 1474
          }
1473 1475
        }
1474 1476
      }
1475 1477

	
0 comments (0 inline)