gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Improve the tree update process and a pivot rule (#391) and make some parts of the code clearer using better names
0 1 0
default
1 file changed with 111 insertions and 96 deletions:
↑ Collapse diff ↑
Show white space 48 line context
... ...
@@ -145,133 +145,134 @@
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 167
    typedef std::vector<Value> ValueVector;
168 168
    typedef std::vector<Cost> CostVector;
169
    typedef std::vector<char> BoolVector;
170
    // Note: vector<char> is used instead of vector<bool> for efficiency reasons
169
    typedef std::vector<signed char> CharVector;
170
    // Note: vector<signed char> is used instead of vector<ArcState> and 
171
    // vector<ArcDirection> for efficiency reasons
171 172

	
172 173
    // State constants for arcs
173 174
    enum ArcState {
174 175
      STATE_UPPER = -1,
175 176
      STATE_TREE  =  0,
176 177
      STATE_LOWER =  1
177 178
    };
178 179

	
179
    typedef std::vector<signed char> StateVector;
180
    // Note: vector<signed char> is used instead of vector<ArcState> for
181
    // efficiency reasons
180
    // Direction constants for tree arcs
181
    enum ArcDirection {
182
      DIR_DOWN = -1,
183
      DIR_UP   =  1
184
    };
182 185

	
183 186
  private:
184 187

	
185 188
    // Data related to the underlying digraph
186 189
    const GR &_graph;
187 190
    int _node_num;
188 191
    int _arc_num;
189 192
    int _all_arc_num;
190 193
    int _search_arc_num;
191 194

	
192 195
    // Parameters of the problem
193 196
    bool _have_lower;
194 197
    SupplyType _stype;
195 198
    Value _sum_supply;
196 199

	
197 200
    // Data structures for storing the digraph
198 201
    IntNodeMap _node_id;
199 202
    IntArcMap _arc_id;
200 203
    IntVector _source;
201 204
    IntVector _target;
202 205
    bool _arc_mixing;
203 206

	
204 207
    // Node and arc data
205 208
    ValueVector _lower;
206 209
    ValueVector _upper;
207 210
    ValueVector _cap;
208 211
    CostVector _cost;
209 212
    ValueVector _supply;
210 213
    ValueVector _flow;
211 214
    CostVector _pi;
212 215

	
213 216
    // Data for storing the spanning tree structure
214 217
    IntVector _parent;
215 218
    IntVector _pred;
216 219
    IntVector _thread;
217 220
    IntVector _rev_thread;
218 221
    IntVector _succ_num;
219 222
    IntVector _last_succ;
223
    CharVector _pred_dir;
224
    CharVector _state;
220 225
    IntVector _dirty_revs;
221
    BoolVector _forward;
222
    StateVector _state;
223 226
    int _root;
224 227

	
225 228
    // Temporary data used in the current pivot iteration
226 229
    int in_arc, join, u_in, v_in, u_out, v_out;
227
    int first, second, right, last;
228
    int stem, par_stem, new_stem;
229 230
    Value delta;
230 231

	
231 232
    const Value MAX;
232 233

	
233 234
  public:
234 235

	
235 236
    /// \brief Constant for infinite upper bounds (capacities).
236 237
    ///
237 238
    /// Constant for infinite upper bounds (capacities).
238 239
    /// It is \c std::numeric_limits<Value>::infinity() if available,
239 240
    /// \c std::numeric_limits<Value>::max() otherwise.
240 241
    const Value INF;
241 242

	
242 243
  private:
243 244

	
244 245
    // Implementation of the First Eligible pivot rule
245 246
    class FirstEligiblePivotRule
246 247
    {
247 248
    private:
248 249

	
249 250
      // References to the NetworkSimplex class
250 251
      const IntVector  &_source;
251 252
      const IntVector  &_target;
252 253
      const CostVector &_cost;
253
      const StateVector &_state;
254
      const CharVector &_state;
254 255
      const CostVector &_pi;
255 256
      int &_in_arc;
256 257
      int _search_arc_num;
257 258

	
258 259
      // Pivot rule data
259 260
      int _next_arc;
260 261

	
261 262
    public:
262 263

	
263 264
      // Constructor
264 265
      FirstEligiblePivotRule(NetworkSimplex &ns) :
265 266
        _source(ns._source), _target(ns._target),
266 267
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
267 268
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
268 269
        _next_arc(0)
269 270
      {}
270 271

	
271 272
      // Find next entering arc
272 273
      bool findEnteringArc() {
273 274
        Cost c;
274 275
        for (int e = _next_arc; e != _search_arc_num; ++e) {
275 276
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
276 277
          if (c < 0) {
277 278
            _in_arc = e;
... ...
@@ -281,88 +282,88 @@
281 282
        }
282 283
        for (int e = 0; e != _next_arc; ++e) {
283 284
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
284 285
          if (c < 0) {
285 286
            _in_arc = e;
286 287
            _next_arc = e + 1;
287 288
            return true;
288 289
          }
289 290
        }
290 291
        return false;
291 292
      }
292 293

	
293 294
    }; //class FirstEligiblePivotRule
294 295

	
295 296

	
296 297
    // Implementation of the Best Eligible pivot rule
297 298
    class BestEligiblePivotRule
298 299
    {
299 300
    private:
300 301

	
301 302
      // References to the NetworkSimplex class
302 303
      const IntVector  &_source;
303 304
      const IntVector  &_target;
304 305
      const CostVector &_cost;
305
      const StateVector &_state;
306
      const CharVector &_state;
306 307
      const CostVector &_pi;
307 308
      int &_in_arc;
308 309
      int _search_arc_num;
309 310

	
310 311
    public:
311 312

	
312 313
      // Constructor
313 314
      BestEligiblePivotRule(NetworkSimplex &ns) :
314 315
        _source(ns._source), _target(ns._target),
315 316
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
316 317
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num)
317 318
      {}
318 319

	
319 320
      // Find next entering arc
320 321
      bool findEnteringArc() {
321 322
        Cost c, min = 0;
322 323
        for (int e = 0; e != _search_arc_num; ++e) {
323 324
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
324 325
          if (c < min) {
325 326
            min = c;
326 327
            _in_arc = e;
327 328
          }
328 329
        }
329 330
        return min < 0;
330 331
      }
331 332

	
332 333
    }; //class BestEligiblePivotRule
333 334

	
334 335

	
335 336
    // Implementation of the Block Search pivot rule
336 337
    class BlockSearchPivotRule
337 338
    {
338 339
    private:
339 340

	
340 341
      // References to the NetworkSimplex class
341 342
      const IntVector  &_source;
342 343
      const IntVector  &_target;
343 344
      const CostVector &_cost;
344
      const StateVector &_state;
345
      const CharVector &_state;
345 346
      const CostVector &_pi;
346 347
      int &_in_arc;
347 348
      int _search_arc_num;
348 349

	
349 350
      // Pivot rule data
350 351
      int _block_size;
351 352
      int _next_arc;
352 353

	
353 354
    public:
354 355

	
355 356
      // Constructor
356 357
      BlockSearchPivotRule(NetworkSimplex &ns) :
357 358
        _source(ns._source), _target(ns._target),
358 359
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
359 360
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
360 361
        _next_arc(0)
361 362
      {
362 363
        // The main parameters of the pivot rule
363 364
        const double BLOCK_SIZE_FACTOR = 1.0;
364 365
        const int MIN_BLOCK_SIZE = 10;
365 366

	
366 367
        _block_size = std::max( int(BLOCK_SIZE_FACTOR *
367 368
                                    std::sqrt(double(_search_arc_num))),
368 369
                                MIN_BLOCK_SIZE );
... ...
@@ -393,49 +394,49 @@
393 394
          if (--cnt == 0) {
394 395
            if (min < 0) goto search_end;
395 396
            cnt = _block_size;
396 397
          }
397 398
        }
398 399
        if (min >= 0) return false;
399 400

	
400 401
      search_end:
401 402
        _next_arc = e;
402 403
        return true;
403 404
      }
404 405

	
405 406
    }; //class BlockSearchPivotRule
406 407

	
407 408

	
408 409
    // Implementation of the Candidate List pivot rule
409 410
    class CandidateListPivotRule
410 411
    {
411 412
    private:
412 413

	
413 414
      // References to the NetworkSimplex class
414 415
      const IntVector  &_source;
415 416
      const IntVector  &_target;
416 417
      const CostVector &_cost;
417
      const StateVector &_state;
418
      const CharVector &_state;
418 419
      const CostVector &_pi;
419 420
      int &_in_arc;
420 421
      int _search_arc_num;
421 422

	
422 423
      // Pivot rule data
423 424
      IntVector _candidates;
424 425
      int _list_length, _minor_limit;
425 426
      int _curr_length, _minor_count;
426 427
      int _next_arc;
427 428

	
428 429
    public:
429 430

	
430 431
      /// Constructor
431 432
      CandidateListPivotRule(NetworkSimplex &ns) :
432 433
        _source(ns._source), _target(ns._target),
433 434
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
434 435
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
435 436
        _next_arc(0)
436 437
      {
437 438
        // The main parameters of the pivot rule
438 439
        const double LIST_LENGTH_FACTOR = 0.25;
439 440
        const int MIN_LIST_LENGTH = 10;
440 441
        const double MINOR_LIMIT_FACTOR = 0.1;
441 442
        const int MIN_MINOR_LIMIT = 3;
... ...
@@ -496,49 +497,49 @@
496 497
            }
497 498
            if (_curr_length == _list_length) goto search_end;
498 499
          }
499 500
        }
500 501
        if (_curr_length == 0) return false;
501 502

	
502 503
      search_end:
503 504
        _minor_count = 1;
504 505
        _next_arc = e;
505 506
        return true;
506 507
      }
507 508

	
508 509
    }; //class CandidateListPivotRule
509 510

	
510 511

	
511 512
    // Implementation of the Altering Candidate List pivot rule
512 513
    class AlteringListPivotRule
513 514
    {
514 515
    private:
515 516

	
516 517
      // References to the NetworkSimplex class
517 518
      const IntVector  &_source;
518 519
      const IntVector  &_target;
519 520
      const CostVector &_cost;
520
      const StateVector &_state;
521
      const CharVector &_state;
521 522
      const CostVector &_pi;
522 523
      int &_in_arc;
523 524
      int _search_arc_num;
524 525

	
525 526
      // Pivot rule data
526 527
      int _block_size, _head_length, _curr_length;
527 528
      int _next_arc;
528 529
      IntVector _candidates;
529 530
      CostVector _cand_cost;
530 531

	
531 532
      // Functor class to compare arcs during sort of the candidate list
532 533
      class SortFunc
533 534
      {
534 535
      private:
535 536
        const CostVector &_map;
536 537
      public:
537 538
        SortFunc(const CostVector &map) : _map(map) {}
538 539
        bool operator()(int left, int right) {
539 540
          return _map[left] > _map[right];
540 541
        }
541 542
      };
542 543

	
543 544
      SortFunc _sort_func;
544 545

	
... ...
@@ -549,65 +550,67 @@
549 550
        _source(ns._source), _target(ns._target),
550 551
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
551 552
        _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num),
552 553
        _next_arc(0), _cand_cost(ns._search_arc_num), _sort_func(_cand_cost)
553 554
      {
554 555
        // The main parameters of the pivot rule
555 556
        const double BLOCK_SIZE_FACTOR = 1.0;
556 557
        const int MIN_BLOCK_SIZE = 10;
557 558
        const double HEAD_LENGTH_FACTOR = 0.1;
558 559
        const int MIN_HEAD_LENGTH = 3;
559 560

	
560 561
        _block_size = std::max( int(BLOCK_SIZE_FACTOR *
561 562
                                    std::sqrt(double(_search_arc_num))),
562 563
                                MIN_BLOCK_SIZE );
563 564
        _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
564 565
                                 MIN_HEAD_LENGTH );
565 566
        _candidates.resize(_head_length + _block_size);
566 567
        _curr_length = 0;
567 568
      }
568 569

	
569 570
      // Find next entering arc
570 571
      bool findEnteringArc() {
571 572
        // Check the current candidate list
572 573
        int e;
574
        Cost c;
573 575
        for (int i = 0; i != _curr_length; ++i) {
574 576
          e = _candidates[i];
575
          _cand_cost[e] = _state[e] *
576
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
577
          if (_cand_cost[e] >= 0) {
577
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
578
          if (c < 0) {
579
            _cand_cost[e] = c;
580
          } else {
578 581
            _candidates[i--] = _candidates[--_curr_length];
579 582
          }
580 583
        }
581 584

	
582 585
        // Extend the list
583 586
        int cnt = _block_size;
584 587
        int limit = _head_length;
585 588

	
586 589
        for (e = _next_arc; e != _search_arc_num; ++e) {
587
          _cand_cost[e] = _state[e] *
588
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
589
          if (_cand_cost[e] < 0) {
590
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
591
          if (c < 0) {
592
            _cand_cost[e] = c;
590 593
            _candidates[_curr_length++] = e;
591 594
          }
592 595
          if (--cnt == 0) {
593 596
            if (_curr_length > limit) goto search_end;
594 597
            limit = 0;
595 598
            cnt = _block_size;
596 599
          }
597 600
        }
598 601
        for (e = 0; e != _next_arc; ++e) {
599 602
          _cand_cost[e] = _state[e] *
600 603
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
601 604
          if (_cand_cost[e] < 0) {
602 605
            _candidates[_curr_length++] = e;
603 606
          }
604 607
          if (--cnt == 0) {
605 608
            if (_curr_length > limit) goto search_end;
606 609
            limit = 0;
607 610
            cnt = _block_size;
608 611
          }
609 612
        }
610 613
        if (_curr_length == 0) return false;
611 614

	
612 615
      search_end:
613 616

	
... ...
@@ -892,49 +895,49 @@
892 895
    ///
893 896
    /// \return <tt>(*this)</tt>
894 897
    ///
895 898
    /// \see resetParams(), run()
896 899
    NetworkSimplex& reset() {
897 900
      // Resize vectors
898 901
      _node_num = countNodes(_graph);
899 902
      _arc_num = countArcs(_graph);
900 903
      int all_node_num = _node_num + 1;
901 904
      int max_arc_num = _arc_num + 2 * _node_num;
902 905

	
903 906
      _source.resize(max_arc_num);
904 907
      _target.resize(max_arc_num);
905 908

	
906 909
      _lower.resize(_arc_num);
907 910
      _upper.resize(_arc_num);
908 911
      _cap.resize(max_arc_num);
909 912
      _cost.resize(max_arc_num);
910 913
      _supply.resize(all_node_num);
911 914
      _flow.resize(max_arc_num);
912 915
      _pi.resize(all_node_num);
913 916

	
914 917
      _parent.resize(all_node_num);
915 918
      _pred.resize(all_node_num);
916
      _forward.resize(all_node_num);
919
      _pred_dir.resize(all_node_num);
917 920
      _thread.resize(all_node_num);
918 921
      _rev_thread.resize(all_node_num);
919 922
      _succ_num.resize(all_node_num);
920 923
      _last_succ.resize(all_node_num);
921 924
      _state.resize(max_arc_num);
922 925

	
923 926
      // Copy the graph
924 927
      int i = 0;
925 928
      for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
926 929
        _node_id[n] = i;
927 930
      }
928 931
      if (_arc_mixing) {
929 932
        // Store the arcs in a mixed order
930 933
        int k = std::max(int(std::sqrt(double(_arc_num))), 10);
931 934
        int i = 0, j = 0;
932 935
        for (ArcIt a(_graph); a != INVALID; ++a) {
933 936
          _arc_id[a] = i;
934 937
          _source[i] = _node_id[_graph.source(a)];
935 938
          _target[i] = _node_id[_graph.target(a)];
936 939
          if ((i += k) >= _arc_num) i = ++j;
937 940
        }
938 941
      } else {
939 942
        // Store the arcs in the original order
940 943
        int i = 0;
... ...
@@ -1095,363 +1098,375 @@
1095 1098
      _parent[_root] = -1;
1096 1099
      _pred[_root] = -1;
1097 1100
      _thread[_root] = 0;
1098 1101
      _rev_thread[0] = _root;
1099 1102
      _succ_num[_root] = _node_num + 1;
1100 1103
      _last_succ[_root] = _root - 1;
1101 1104
      _supply[_root] = -_sum_supply;
1102 1105
      _pi[_root] = 0;
1103 1106

	
1104 1107
      // Add artificial arcs and initialize the spanning tree data structure
1105 1108
      if (_sum_supply == 0) {
1106 1109
        // EQ supply constraints
1107 1110
        _search_arc_num = _arc_num;
1108 1111
        _all_arc_num = _arc_num + _node_num;
1109 1112
        for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
1110 1113
          _parent[u] = _root;
1111 1114
          _pred[u] = e;
1112 1115
          _thread[u] = u + 1;
1113 1116
          _rev_thread[u + 1] = u;
1114 1117
          _succ_num[u] = 1;
1115 1118
          _last_succ[u] = u;
1116 1119
          _cap[e] = INF;
1117 1120
          _state[e] = STATE_TREE;
1118 1121
          if (_supply[u] >= 0) {
1119
            _forward[u] = true;
1122
            _pred_dir[u] = DIR_UP;
1120 1123
            _pi[u] = 0;
1121 1124
            _source[e] = u;
1122 1125
            _target[e] = _root;
1123 1126
            _flow[e] = _supply[u];
1124 1127
            _cost[e] = 0;
1125 1128
          } else {
1126
            _forward[u] = false;
1129
            _pred_dir[u] = DIR_DOWN;
1127 1130
            _pi[u] = ART_COST;
1128 1131
            _source[e] = _root;
1129 1132
            _target[e] = u;
1130 1133
            _flow[e] = -_supply[u];
1131 1134
            _cost[e] = ART_COST;
1132 1135
          }
1133 1136
        }
1134 1137
      }
1135 1138
      else if (_sum_supply > 0) {
1136 1139
        // LEQ supply constraints
1137 1140
        _search_arc_num = _arc_num + _node_num;
1138 1141
        int f = _arc_num + _node_num;
1139 1142
        for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
1140 1143
          _parent[u] = _root;
1141 1144
          _thread[u] = u + 1;
1142 1145
          _rev_thread[u + 1] = u;
1143 1146
          _succ_num[u] = 1;
1144 1147
          _last_succ[u] = u;
1145 1148
          if (_supply[u] >= 0) {
1146
            _forward[u] = true;
1149
            _pred_dir[u] = DIR_UP;
1147 1150
            _pi[u] = 0;
1148 1151
            _pred[u] = e;
1149 1152
            _source[e] = u;
1150 1153
            _target[e] = _root;
1151 1154
            _cap[e] = INF;
1152 1155
            _flow[e] = _supply[u];
1153 1156
            _cost[e] = 0;
1154 1157
            _state[e] = STATE_TREE;
1155 1158
          } else {
1156
            _forward[u] = false;
1159
            _pred_dir[u] = DIR_DOWN;
1157 1160
            _pi[u] = ART_COST;
1158 1161
            _pred[u] = f;
1159 1162
            _source[f] = _root;
1160 1163
            _target[f] = u;
1161 1164
            _cap[f] = INF;
1162 1165
            _flow[f] = -_supply[u];
1163 1166
            _cost[f] = ART_COST;
1164 1167
            _state[f] = STATE_TREE;
1165 1168
            _source[e] = u;
1166 1169
            _target[e] = _root;
1167 1170
            _cap[e] = INF;
1168 1171
            _flow[e] = 0;
1169 1172
            _cost[e] = 0;
1170 1173
            _state[e] = STATE_LOWER;
1171 1174
            ++f;
1172 1175
          }
1173 1176
        }
1174 1177
        _all_arc_num = f;
1175 1178
      }
1176 1179
      else {
1177 1180
        // GEQ supply constraints
1178 1181
        _search_arc_num = _arc_num + _node_num;
1179 1182
        int f = _arc_num + _node_num;
1180 1183
        for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
1181 1184
          _parent[u] = _root;
1182 1185
          _thread[u] = u + 1;
1183 1186
          _rev_thread[u + 1] = u;
1184 1187
          _succ_num[u] = 1;
1185 1188
          _last_succ[u] = u;
1186 1189
          if (_supply[u] <= 0) {
1187
            _forward[u] = false;
1190
            _pred_dir[u] = DIR_DOWN;
1188 1191
            _pi[u] = 0;
1189 1192
            _pred[u] = e;
1190 1193
            _source[e] = _root;
1191 1194
            _target[e] = u;
1192 1195
            _cap[e] = INF;
1193 1196
            _flow[e] = -_supply[u];
1194 1197
            _cost[e] = 0;
1195 1198
            _state[e] = STATE_TREE;
1196 1199
          } else {
1197
            _forward[u] = true;
1200
            _pred_dir[u] = DIR_UP;
1198 1201
            _pi[u] = -ART_COST;
1199 1202
            _pred[u] = f;
1200 1203
            _source[f] = u;
1201 1204
            _target[f] = _root;
1202 1205
            _cap[f] = INF;
1203 1206
            _flow[f] = _supply[u];
1204 1207
            _state[f] = STATE_TREE;
1205 1208
            _cost[f] = ART_COST;
1206 1209
            _source[e] = _root;
1207 1210
            _target[e] = u;
1208 1211
            _cap[e] = INF;
1209 1212
            _flow[e] = 0;
1210 1213
            _cost[e] = 0;
1211 1214
            _state[e] = STATE_LOWER;
1212 1215
            ++f;
1213 1216
          }
1214 1217
        }
1215 1218
        _all_arc_num = f;
1216 1219
      }
1217 1220

	
1218 1221
      return true;
1219 1222
    }
1220 1223

	
1221 1224
    // Find the join node
1222 1225
    void findJoinNode() {
1223 1226
      int u = _source[in_arc];
1224 1227
      int v = _target[in_arc];
1225 1228
      while (u != v) {
1226 1229
        if (_succ_num[u] < _succ_num[v]) {
1227 1230
          u = _parent[u];
1228 1231
        } else {
1229 1232
          v = _parent[v];
1230 1233
        }
1231 1234
      }
1232 1235
      join = u;
1233 1236
    }
1234 1237

	
1235 1238
    // Find the leaving arc of the cycle and returns true if the
1236 1239
    // leaving arc is not the same as the entering arc
1237 1240
    bool findLeavingArc() {
1238 1241
      // Initialize first and second nodes according to the direction
1239 1242
      // of the cycle
1243
      int first, second;
1240 1244
      if (_state[in_arc] == STATE_LOWER) {
1241 1245
        first  = _source[in_arc];
1242 1246
        second = _target[in_arc];
1243 1247
      } else {
1244 1248
        first  = _target[in_arc];
1245 1249
        second = _source[in_arc];
1246 1250
      }
1247 1251
      delta = _cap[in_arc];
1248 1252
      int result = 0;
1249
      Value d;
1253
      Value c, d;
1250 1254
      int e;
1251 1255

	
1252
      // Search the cycle along the path form the first node to the root
1256
      // Search the cycle form the first node to the join node
1253 1257
      for (int u = first; u != join; u = _parent[u]) {
1254 1258
        e = _pred[u];
1255
        d = _forward[u] ?
1256
          _flow[e] : (_cap[e] >= MAX ? INF : _cap[e] - _flow[e]);
1259
        d = _flow[e];
1260
        if (_pred_dir[u] == DIR_DOWN) {
1261
          c = _cap[e];
1262
          d = c >= MAX ? INF : c - d;
1263
        }
1257 1264
        if (d < delta) {
1258 1265
          delta = d;
1259 1266
          u_out = u;
1260 1267
          result = 1;
1261 1268
        }
1262 1269
      }
1263
      // Search the cycle along the path form the second node to the root
1270

	
1271
      // Search the cycle form the second node to the join node
1264 1272
      for (int u = second; u != join; u = _parent[u]) {
1265 1273
        e = _pred[u];
1266
        d = _forward[u] ?
1267
          (_cap[e] >= MAX ? INF : _cap[e] - _flow[e]) : _flow[e];
1274
        d = _flow[e];
1275
        if (_pred_dir[u] == DIR_UP) {
1276
          c = _cap[e];
1277
          d = c >= MAX ? INF : c - d;
1278
        }
1268 1279
        if (d <= delta) {
1269 1280
          delta = d;
1270 1281
          u_out = u;
1271 1282
          result = 2;
1272 1283
        }
1273 1284
      }
1274 1285

	
1275 1286
      if (result == 1) {
1276 1287
        u_in = first;
1277 1288
        v_in = second;
1278 1289
      } else {
1279 1290
        u_in = second;
1280 1291
        v_in = first;
1281 1292
      }
1282 1293
      return result != 0;
1283 1294
    }
1284 1295

	
1285 1296
    // Change _flow and _state vectors
1286 1297
    void changeFlow(bool change) {
1287 1298
      // Augment along the cycle
1288 1299
      if (delta > 0) {
1289 1300
        Value val = _state[in_arc] * delta;
1290 1301
        _flow[in_arc] += val;
1291 1302
        for (int u = _source[in_arc]; u != join; u = _parent[u]) {
1292
          _flow[_pred[u]] += _forward[u] ? -val : val;
1303
          _flow[_pred[u]] -= _pred_dir[u] * val;
1293 1304
        }
1294 1305
        for (int u = _target[in_arc]; u != join; u = _parent[u]) {
1295
          _flow[_pred[u]] += _forward[u] ? val : -val;
1306
          _flow[_pred[u]] += _pred_dir[u] * val;
1296 1307
        }
1297 1308
      }
1298 1309
      // Update the state of the entering and leaving arcs
1299 1310
      if (change) {
1300 1311
        _state[in_arc] = STATE_TREE;
1301 1312
        _state[_pred[u_out]] =
1302 1313
          (_flow[_pred[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
1303 1314
      } else {
1304 1315
        _state[in_arc] = -_state[in_arc];
1305 1316
      }
1306 1317
    }
1307 1318

	
1308 1319
    // Update the tree structure
1309 1320
    void updateTreeStructure() {
1310
      int u, w;
1311 1321
      int old_rev_thread = _rev_thread[u_out];
1312 1322
      int old_succ_num = _succ_num[u_out];
1313 1323
      int old_last_succ = _last_succ[u_out];
1314 1324
      v_out = _parent[u_out];
1315 1325

	
1316
      u = _last_succ[u_in];  // the last successor of u_in
1317
      right = _thread[u];    // the node after it
1326
      // Check if u_in and u_out coincide
1327
      if (u_in == u_out) {
1328
        // Update _parent, _pred, _pred_dir
1329
        _parent[u_in] = v_in;
1330
        _pred[u_in] = in_arc;
1331
        _pred_dir[u_in] = u_in == _source[in_arc] ? DIR_UP : DIR_DOWN;
1318 1332

	
1333
        // Update _thread and _rev_thread
1334
        if (_thread[v_in] != u_out) {
1335
          int after = _thread[old_last_succ];
1336
          _thread[old_rev_thread] = after;
1337
          _rev_thread[after] = old_rev_thread;
1338
          after = _thread[v_in];
1339
          _thread[v_in] = u_out;
1340
          _rev_thread[u_out] = v_in;
1341
          _thread[old_last_succ] = after;
1342
          _rev_thread[after] = old_last_succ;
1343
        }
1344
      } else {
1319 1345
      // Handle the case when old_rev_thread equals to v_in
1320 1346
      // (it also means that join and v_out coincide)
1321
      if (old_rev_thread == v_in) {
1322
        last = _thread[_last_succ[u_out]];
1323
      } else {
1324
        last = _thread[v_in];
1325
      }
1347
        int thread_continue = old_rev_thread == v_in ?
1348
          _thread[old_last_succ] : _thread[v_in];
1326 1349

	
1327 1350
      // Update _thread and _parent along the stem nodes (i.e. the nodes
1328 1351
      // between u_in and u_out, whose parent have to be changed)
1329
      _thread[v_in] = stem = u_in;
1352
        int stem = u_in;              // the current stem node
1353
        int par_stem = v_in;          // the new parent of stem
1354
        int next_stem;                // the next stem node
1355
        int last = _last_succ[u_in];  // the last successor of stem
1356
        int before, after = _thread[last];
1357
        _thread[v_in] = u_in;
1330 1358
      _dirty_revs.clear();
1331 1359
      _dirty_revs.push_back(v_in);
1332
      par_stem = v_in;
1333 1360
      while (stem != u_out) {
1334 1361
        // Insert the next stem node into the thread list
1335
        new_stem = _parent[stem];
1336
        _thread[u] = new_stem;
1337
        _dirty_revs.push_back(u);
1362
          next_stem = _parent[stem];
1363
          _thread[last] = next_stem;
1364
          _dirty_revs.push_back(last);
1338 1365

	
1339 1366
        // Remove the subtree of stem from the thread list
1340
        w = _rev_thread[stem];
1341
        _thread[w] = right;
1342
        _rev_thread[right] = w;
1367
          before = _rev_thread[stem];
1368
          _thread[before] = after;
1369
          _rev_thread[after] = before;
1343 1370

	
1344 1371
        // Change the parent node and shift stem nodes
1345 1372
        _parent[stem] = par_stem;
1346 1373
        par_stem = stem;
1347
        stem = new_stem;
1374
          stem = next_stem;
1348 1375

	
1349
        // Update u and right
1350
        u = _last_succ[stem] == _last_succ[par_stem] ?
1376
          // Update last and after
1377
          last = _last_succ[stem] == _last_succ[par_stem] ?
1351 1378
          _rev_thread[par_stem] : _last_succ[stem];
1352
        right = _thread[u];
1379
          after = _thread[last];
1353 1380
      }
1354 1381
      _parent[u_out] = par_stem;
1355
      _thread[u] = last;
1356
      _rev_thread[last] = u;
1357
      _last_succ[u_out] = u;
1382
        _thread[last] = thread_continue;
1383
        _rev_thread[thread_continue] = last;
1384
        _last_succ[u_out] = last;
1358 1385

	
1359 1386
      // Remove the subtree of u_out from the thread list except for
1360 1387
      // the case when old_rev_thread equals to v_in
1361
      // (it also means that join and v_out coincide)
1362 1388
      if (old_rev_thread != v_in) {
1363
        _thread[old_rev_thread] = right;
1364
        _rev_thread[right] = old_rev_thread;
1389
          _thread[old_rev_thread] = after;
1390
          _rev_thread[after] = old_rev_thread;
1365 1391
      }
1366 1392

	
1367 1393
      // Update _rev_thread using the new _thread values
1368 1394
      for (int i = 0; i != int(_dirty_revs.size()); ++i) {
1369
        u = _dirty_revs[i];
1395
          int u = _dirty_revs[i];
1370 1396
        _rev_thread[_thread[u]] = u;
1371 1397
      }
1372 1398

	
1373
      // Update _pred, _forward, _last_succ and _succ_num for the
1399
        // Update _pred, _pred_dir, _last_succ and _succ_num for the
1374 1400
      // stem nodes from u_out to u_in
1375 1401
      int tmp_sc = 0, tmp_ls = _last_succ[u_out];
1376
      u = u_out;
1377
      while (u != u_in) {
1378
        w = _parent[u];
1379
        _pred[u] = _pred[w];
1380
        _forward[u] = !_forward[w];
1381
        tmp_sc += _succ_num[u] - _succ_num[w];
1402
        for (int u = u_out, p = _parent[u]; u != u_in; u = p, p = _parent[u]) {
1403
          _pred[u] = _pred[p];
1404
          _pred_dir[u] = -_pred_dir[p];
1405
          tmp_sc += _succ_num[u] - _succ_num[p];
1382 1406
        _succ_num[u] = tmp_sc;
1383
        _last_succ[w] = tmp_ls;
1384
        u = w;
1407
          _last_succ[p] = tmp_ls;
1385 1408
      }
1386 1409
      _pred[u_in] = in_arc;
1387
      _forward[u_in] = (u_in == _source[in_arc]);
1410
        _pred_dir[u_in] = u_in == _source[in_arc] ? DIR_UP : DIR_DOWN;
1388 1411
      _succ_num[u_in] = old_succ_num;
1389

	
1390
      // Set limits for updating _last_succ form v_in and v_out
1391
      // towards the root
1392
      int up_limit_in = -1;
1393
      int up_limit_out = -1;
1394
      if (_last_succ[join] == v_in) {
1395
        up_limit_out = join;
1396
      } else {
1397
        up_limit_in = join;
1398 1412
      }
1399 1413

	
1400 1414
      // Update _last_succ from v_in towards the root
1401
      for (u = v_in; u != up_limit_in && _last_succ[u] == v_in;
1402
           u = _parent[u]) {
1403
        _last_succ[u] = _last_succ[u_out];
1415
      int up_limit_out = _last_succ[join] == v_in ? join : -1;
1416
      int last_succ_out = _last_succ[u_out];
1417
      for (int u = v_in; u != -1 && _last_succ[u] == v_in; u = _parent[u]) {
1418
        _last_succ[u] = last_succ_out;
1404 1419
      }
1420

	
1405 1421
      // Update _last_succ from v_out towards the root
1406 1422
      if (join != old_rev_thread && v_in != old_rev_thread) {
1407
        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1423
        for (int u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1408 1424
             u = _parent[u]) {
1409 1425
          _last_succ[u] = old_rev_thread;
1410 1426
        }
1411
      } else {
1412
        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1427
      }
1428
      else if (last_succ_out != old_last_succ) {
1429
        for (int u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1413 1430
             u = _parent[u]) {
1414
          _last_succ[u] = _last_succ[u_out];
1431
          _last_succ[u] = last_succ_out;
1415 1432
        }
1416 1433
      }
1417 1434

	
1418 1435
      // Update _succ_num from v_in to join
1419
      for (u = v_in; u != join; u = _parent[u]) {
1436
      for (int u = v_in; u != join; u = _parent[u]) {
1420 1437
        _succ_num[u] += old_succ_num;
1421 1438
      }
1422 1439
      // Update _succ_num from v_out to join
1423
      for (u = v_out; u != join; u = _parent[u]) {
1440
      for (int u = v_out; u != join; u = _parent[u]) {
1424 1441
        _succ_num[u] -= old_succ_num;
1425 1442
      }
1426 1443
    }
1427 1444

	
1428
    // Update potentials
1445
    // Update potentials in the subtree that has been moved
1429 1446
    void updatePotential() {
1430
      Cost sigma = _forward[u_in] ?
1431
        _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
1432
        _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
1433
      // Update potentials in the subtree, which has been moved
1447
      Cost sigma = _pi[v_in] - _pi[u_in] -
1448
                   _pred_dir[u_in] * _cost[in_arc];
1434 1449
      int end = _thread[_last_succ[u_in]];
1435 1450
      for (int u = u_in; u != end; u = _thread[u]) {
1436 1451
        _pi[u] += sigma;
1437 1452
      }
1438 1453
    }
1439 1454

	
1440 1455
    // Heuristic initial pivots
1441 1456
    bool initialPivots() {
1442 1457
      Value curr, total = 0;
1443 1458
      std::vector<Node> supply_nodes, demand_nodes;
1444 1459
      for (NodeIt u(_graph); u != INVALID; ++u) {
1445 1460
        curr = _supply[_node_id[u]];
1446 1461
        if (curr > 0) {
1447 1462
          total += curr;
1448 1463
          supply_nodes.push_back(u);
1449 1464
        }
1450 1465
        else if (curr < 0) {
1451 1466
          demand_nodes.push_back(u);
1452 1467
        }
1453 1468
      }
1454 1469
      if (_sum_supply > 0) total -= _sum_supply;
1455 1470
      if (total <= 0) return true;
1456 1471

	
1457 1472
      IntVector arc_vector;
0 comments (0 inline)