100 /// |
100 /// |
101 /// Enum type containing constants for selecting the supply type, |
101 /// Enum type containing constants for selecting the supply type, |
102 /// i.e. the direction of the inequalities in the supply/demand |
102 /// i.e. the direction of the inequalities in the supply/demand |
103 /// constraints of the \ref min_cost_flow "minimum cost flow problem". |
103 /// constraints of the \ref min_cost_flow "minimum cost flow problem". |
104 /// |
104 /// |
105 /// The default supply type is \c GEQ, since this form is supported |
105 /// The default supply type is \c GEQ, the \c LEQ type can be |
106 /// by other minimum cost flow algorithms and the \ref Circulation |
106 /// selected using \ref supplyType(). |
107 /// algorithm, as well. |
107 /// The equality form is a special case of both supply types. |
108 /// The \c LEQ problem type can be selected using the \ref supplyType() |
|
109 /// function. |
|
110 /// |
|
111 /// Note that the equality form is a special case of both supply types. |
|
112 enum SupplyType { |
108 enum SupplyType { |
113 |
|
114 /// This option means that there are <em>"greater or equal"</em> |
109 /// This option means that there are <em>"greater or equal"</em> |
115 /// supply/demand constraints in the definition, i.e. the exact |
110 /// supply/demand constraints in the definition of the problem. |
116 /// formulation of the problem is the following. |
|
117 /** |
|
118 \f[ \min\sum_{uv\in A} f(uv) \cdot cost(uv) \f] |
|
119 \f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \geq |
|
120 sup(u) \quad \forall u\in V \f] |
|
121 \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A \f] |
|
122 */ |
|
123 /// It means that the total demand must be greater or equal to the |
|
124 /// total supply (i.e. \f$\sum_{u\in V} sup(u)\f$ must be zero or |
|
125 /// negative) and all the supplies have to be carried out from |
|
126 /// the supply nodes, but there could be demands that are not |
|
127 /// satisfied. |
|
128 GEQ, |
111 GEQ, |
129 /// It is just an alias for the \c GEQ option. |
|
130 CARRY_SUPPLIES = GEQ, |
|
131 |
|
132 /// This option means that there are <em>"less or equal"</em> |
112 /// This option means that there are <em>"less or equal"</em> |
133 /// supply/demand constraints in the definition, i.e. the exact |
113 /// supply/demand constraints in the definition of the problem. |
134 /// formulation of the problem is the following. |
114 LEQ |
135 /** |
|
136 \f[ \min\sum_{uv\in A} f(uv) \cdot cost(uv) \f] |
|
137 \f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \leq |
|
138 sup(u) \quad \forall u\in V \f] |
|
139 \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A \f] |
|
140 */ |
|
141 /// It means that the total demand must be less or equal to the |
|
142 /// total supply (i.e. \f$\sum_{u\in V} sup(u)\f$ must be zero or |
|
143 /// positive) and all the demands have to be satisfied, but there |
|
144 /// could be supplies that are not carried out from the supply |
|
145 /// nodes. |
|
146 LEQ, |
|
147 /// It is just an alias for the \c LEQ option. |
|
148 SATISFY_DEMANDS = LEQ |
|
149 }; |
115 }; |
150 |
116 |
151 /// \brief Constants for selecting the pivot rule. |
117 /// \brief Constants for selecting the pivot rule. |
152 /// |
118 /// |
153 /// Enum type containing constants for selecting the pivot rule for |
119 /// Enum type containing constants for selecting the pivot rule for |
275 const IntVector &_target; |
243 const IntVector &_target; |
276 const CostVector &_cost; |
244 const CostVector &_cost; |
277 const IntVector &_state; |
245 const IntVector &_state; |
278 const CostVector &_pi; |
246 const CostVector &_pi; |
279 int &_in_arc; |
247 int &_in_arc; |
280 int _arc_num; |
248 int _search_arc_num; |
281 |
249 |
282 // Pivot rule data |
250 // Pivot rule data |
283 int _next_arc; |
251 int _next_arc; |
284 |
252 |
285 public: |
253 public: |
286 |
254 |
287 // Constructor |
255 // Constructor |
288 FirstEligiblePivotRule(NetworkSimplex &ns) : |
256 FirstEligiblePivotRule(NetworkSimplex &ns) : |
289 _source(ns._source), _target(ns._target), |
257 _source(ns._source), _target(ns._target), |
290 _cost(ns._cost), _state(ns._state), _pi(ns._pi), |
258 _cost(ns._cost), _state(ns._state), _pi(ns._pi), |
291 _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0) |
259 _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num), |
|
260 _next_arc(0) |
292 {} |
261 {} |
293 |
262 |
294 // Find next entering arc |
263 // Find next entering arc |
295 bool findEnteringArc() { |
264 bool findEnteringArc() { |
296 Cost c; |
265 Cost c; |
297 for (int e = _next_arc; e < _arc_num; ++e) { |
266 for (int e = _next_arc; e < _search_arc_num; ++e) { |
298 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
267 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
299 if (c < 0) { |
268 if (c < 0) { |
300 _in_arc = e; |
269 _in_arc = e; |
301 _next_arc = e + 1; |
270 _next_arc = e + 1; |
302 return true; |
271 return true; |
326 const IntVector &_target; |
295 const IntVector &_target; |
327 const CostVector &_cost; |
296 const CostVector &_cost; |
328 const IntVector &_state; |
297 const IntVector &_state; |
329 const CostVector &_pi; |
298 const CostVector &_pi; |
330 int &_in_arc; |
299 int &_in_arc; |
331 int _arc_num; |
300 int _search_arc_num; |
332 |
301 |
333 public: |
302 public: |
334 |
303 |
335 // Constructor |
304 // Constructor |
336 BestEligiblePivotRule(NetworkSimplex &ns) : |
305 BestEligiblePivotRule(NetworkSimplex &ns) : |
337 _source(ns._source), _target(ns._target), |
306 _source(ns._source), _target(ns._target), |
338 _cost(ns._cost), _state(ns._state), _pi(ns._pi), |
307 _cost(ns._cost), _state(ns._state), _pi(ns._pi), |
339 _in_arc(ns.in_arc), _arc_num(ns._arc_num) |
308 _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num) |
340 {} |
309 {} |
341 |
310 |
342 // Find next entering arc |
311 // Find next entering arc |
343 bool findEnteringArc() { |
312 bool findEnteringArc() { |
344 Cost c, min = 0; |
313 Cost c, min = 0; |
345 for (int e = 0; e < _arc_num; ++e) { |
314 for (int e = 0; e < _search_arc_num; ++e) { |
346 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
315 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
347 if (c < min) { |
316 if (c < min) { |
348 min = c; |
317 min = c; |
349 _in_arc = e; |
318 _in_arc = e; |
350 } |
319 } |
377 |
346 |
378 // Constructor |
347 // Constructor |
379 BlockSearchPivotRule(NetworkSimplex &ns) : |
348 BlockSearchPivotRule(NetworkSimplex &ns) : |
380 _source(ns._source), _target(ns._target), |
349 _source(ns._source), _target(ns._target), |
381 _cost(ns._cost), _state(ns._state), _pi(ns._pi), |
350 _cost(ns._cost), _state(ns._state), _pi(ns._pi), |
382 _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0) |
351 _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num), |
|
352 _next_arc(0) |
383 { |
353 { |
384 // The main parameters of the pivot rule |
354 // The main parameters of the pivot rule |
385 const double BLOCK_SIZE_FACTOR = 2.0; |
355 const double BLOCK_SIZE_FACTOR = 0.5; |
386 const int MIN_BLOCK_SIZE = 10; |
356 const int MIN_BLOCK_SIZE = 10; |
387 |
357 |
388 _block_size = std::max( int(BLOCK_SIZE_FACTOR * |
358 _block_size = std::max( int(BLOCK_SIZE_FACTOR * |
389 std::sqrt(double(_arc_num))), |
359 std::sqrt(double(_search_arc_num))), |
390 MIN_BLOCK_SIZE ); |
360 MIN_BLOCK_SIZE ); |
391 } |
361 } |
392 |
362 |
393 // Find next entering arc |
363 // Find next entering arc |
394 bool findEnteringArc() { |
364 bool findEnteringArc() { |
395 Cost c, min = 0; |
365 Cost c, min = 0; |
396 int cnt = _block_size; |
366 int cnt = _block_size; |
397 int e, min_arc = _next_arc; |
367 int e, min_arc = _next_arc; |
398 for (e = _next_arc; e < _arc_num; ++e) { |
368 for (e = _next_arc; e < _search_arc_num; ++e) { |
399 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
369 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
400 if (c < min) { |
370 if (c < min) { |
401 min = c; |
371 min = c; |
402 min_arc = e; |
372 min_arc = e; |
403 } |
373 } |
438 const IntVector &_target; |
408 const IntVector &_target; |
439 const CostVector &_cost; |
409 const CostVector &_cost; |
440 const IntVector &_state; |
410 const IntVector &_state; |
441 const CostVector &_pi; |
411 const CostVector &_pi; |
442 int &_in_arc; |
412 int &_in_arc; |
443 int _arc_num; |
413 int _search_arc_num; |
444 |
414 |
445 // Pivot rule data |
415 // Pivot rule data |
446 IntVector _candidates; |
416 IntVector _candidates; |
447 int _list_length, _minor_limit; |
417 int _list_length, _minor_limit; |
448 int _curr_length, _minor_count; |
418 int _curr_length, _minor_count; |
452 |
422 |
453 /// Constructor |
423 /// Constructor |
454 CandidateListPivotRule(NetworkSimplex &ns) : |
424 CandidateListPivotRule(NetworkSimplex &ns) : |
455 _source(ns._source), _target(ns._target), |
425 _source(ns._source), _target(ns._target), |
456 _cost(ns._cost), _state(ns._state), _pi(ns._pi), |
426 _cost(ns._cost), _state(ns._state), _pi(ns._pi), |
457 _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0) |
427 _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num), |
|
428 _next_arc(0) |
458 { |
429 { |
459 // The main parameters of the pivot rule |
430 // The main parameters of the pivot rule |
460 const double LIST_LENGTH_FACTOR = 1.0; |
431 const double LIST_LENGTH_FACTOR = 1.0; |
461 const int MIN_LIST_LENGTH = 10; |
432 const int MIN_LIST_LENGTH = 10; |
462 const double MINOR_LIMIT_FACTOR = 0.1; |
433 const double MINOR_LIMIT_FACTOR = 0.1; |
463 const int MIN_MINOR_LIMIT = 3; |
434 const int MIN_MINOR_LIMIT = 3; |
464 |
435 |
465 _list_length = std::max( int(LIST_LENGTH_FACTOR * |
436 _list_length = std::max( int(LIST_LENGTH_FACTOR * |
466 std::sqrt(double(_arc_num))), |
437 std::sqrt(double(_search_arc_num))), |
467 MIN_LIST_LENGTH ); |
438 MIN_LIST_LENGTH ); |
468 _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length), |
439 _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length), |
469 MIN_MINOR_LIMIT ); |
440 MIN_MINOR_LIMIT ); |
470 _curr_length = _minor_count = 0; |
441 _curr_length = _minor_count = 0; |
471 _candidates.resize(_list_length); |
442 _candidates.resize(_list_length); |
544 const IntVector &_target; |
515 const IntVector &_target; |
545 const CostVector &_cost; |
516 const CostVector &_cost; |
546 const IntVector &_state; |
517 const IntVector &_state; |
547 const CostVector &_pi; |
518 const CostVector &_pi; |
548 int &_in_arc; |
519 int &_in_arc; |
549 int _arc_num; |
520 int _search_arc_num; |
550 |
521 |
551 // Pivot rule data |
522 // Pivot rule data |
552 int _block_size, _head_length, _curr_length; |
523 int _block_size, _head_length, _curr_length; |
553 int _next_arc; |
524 int _next_arc; |
554 IntVector _candidates; |
525 IntVector _candidates; |
572 |
543 |
573 // Constructor |
544 // Constructor |
574 AlteringListPivotRule(NetworkSimplex &ns) : |
545 AlteringListPivotRule(NetworkSimplex &ns) : |
575 _source(ns._source), _target(ns._target), |
546 _source(ns._source), _target(ns._target), |
576 _cost(ns._cost), _state(ns._state), _pi(ns._pi), |
547 _cost(ns._cost), _state(ns._state), _pi(ns._pi), |
577 _in_arc(ns.in_arc), _arc_num(ns._arc_num), |
548 _in_arc(ns.in_arc), _search_arc_num(ns._search_arc_num), |
578 _next_arc(0), _cand_cost(ns._arc_num), _sort_func(_cand_cost) |
549 _next_arc(0), _cand_cost(ns._search_arc_num), _sort_func(_cand_cost) |
579 { |
550 { |
580 // The main parameters of the pivot rule |
551 // The main parameters of the pivot rule |
581 const double BLOCK_SIZE_FACTOR = 1.5; |
552 const double BLOCK_SIZE_FACTOR = 1.5; |
582 const int MIN_BLOCK_SIZE = 10; |
553 const int MIN_BLOCK_SIZE = 10; |
583 const double HEAD_LENGTH_FACTOR = 0.1; |
554 const double HEAD_LENGTH_FACTOR = 0.1; |
584 const int MIN_HEAD_LENGTH = 3; |
555 const int MIN_HEAD_LENGTH = 3; |
585 |
556 |
586 _block_size = std::max( int(BLOCK_SIZE_FACTOR * |
557 _block_size = std::max( int(BLOCK_SIZE_FACTOR * |
587 std::sqrt(double(_arc_num))), |
558 std::sqrt(double(_search_arc_num))), |
588 MIN_BLOCK_SIZE ); |
559 MIN_BLOCK_SIZE ); |
589 _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size), |
560 _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size), |
590 MIN_HEAD_LENGTH ); |
561 MIN_HEAD_LENGTH ); |
591 _candidates.resize(_head_length + _block_size); |
562 _candidates.resize(_head_length + _block_size); |
592 _curr_length = 0; |
563 _curr_length = 0; |
608 // Extend the list |
579 // Extend the list |
609 int cnt = _block_size; |
580 int cnt = _block_size; |
610 int last_arc = 0; |
581 int last_arc = 0; |
611 int limit = _head_length; |
582 int limit = _head_length; |
612 |
583 |
613 for (int e = _next_arc; e < _arc_num; ++e) { |
584 for (int e = _next_arc; e < _search_arc_num; ++e) { |
614 _cand_cost[e] = _state[e] * |
585 _cand_cost[e] = _state[e] * |
615 (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
586 (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); |
616 if (_cand_cost[e] < 0) { |
587 if (_cand_cost[e] < 0) { |
617 _candidates[_curr_length++] = e; |
588 _candidates[_curr_length++] = e; |
618 last_arc = e; |
589 last_arc = e; |
676 |
647 |
677 // Resize vectors |
648 // Resize vectors |
678 _node_num = countNodes(_graph); |
649 _node_num = countNodes(_graph); |
679 _arc_num = countArcs(_graph); |
650 _arc_num = countArcs(_graph); |
680 int all_node_num = _node_num + 1; |
651 int all_node_num = _node_num + 1; |
681 int all_arc_num = _arc_num + _node_num; |
652 int max_arc_num = _arc_num + 2 * _node_num; |
682 |
653 |
683 _source.resize(all_arc_num); |
654 _source.resize(max_arc_num); |
684 _target.resize(all_arc_num); |
655 _target.resize(max_arc_num); |
685 |
656 |
686 _lower.resize(all_arc_num); |
657 _lower.resize(_arc_num); |
687 _upper.resize(all_arc_num); |
658 _upper.resize(_arc_num); |
688 _cap.resize(all_arc_num); |
659 _cap.resize(max_arc_num); |
689 _cost.resize(all_arc_num); |
660 _cost.resize(max_arc_num); |
690 _supply.resize(all_node_num); |
661 _supply.resize(all_node_num); |
691 _flow.resize(all_arc_num); |
662 _flow.resize(max_arc_num); |
692 _pi.resize(all_node_num); |
663 _pi.resize(all_node_num); |
693 |
664 |
694 _parent.resize(all_node_num); |
665 _parent.resize(all_node_num); |
695 _pred.resize(all_node_num); |
666 _pred.resize(all_node_num); |
696 _forward.resize(all_node_num); |
667 _forward.resize(all_node_num); |
697 _thread.resize(all_node_num); |
668 _thread.resize(all_node_num); |
698 _rev_thread.resize(all_node_num); |
669 _rev_thread.resize(all_node_num); |
699 _succ_num.resize(all_node_num); |
670 _succ_num.resize(all_node_num); |
700 _last_succ.resize(all_node_num); |
671 _last_succ.resize(all_node_num); |
701 _state.resize(all_arc_num); |
672 _state.resize(max_arc_num); |
702 |
673 |
703 // Copy the graph (store the arcs in a mixed order) |
674 // Copy the graph (store the arcs in a mixed order) |
704 int i = 0; |
675 int i = 0; |
705 for (NodeIt n(_graph); n != INVALID; ++n, ++i) { |
676 for (NodeIt n(_graph); n != INVALID; ++n, ++i) { |
706 _node_id[n] = i; |
677 _node_id[n] = i; |
1067 } |
1038 } |
1068 |
1039 |
1069 // Initialize artifical cost |
1040 // Initialize artifical cost |
1070 Cost ART_COST; |
1041 Cost ART_COST; |
1071 if (std::numeric_limits<Cost>::is_exact) { |
1042 if (std::numeric_limits<Cost>::is_exact) { |
1072 ART_COST = std::numeric_limits<Cost>::max() / 4 + 1; |
1043 ART_COST = std::numeric_limits<Cost>::max() / 2 + 1; |
1073 } else { |
1044 } else { |
1074 ART_COST = std::numeric_limits<Cost>::min(); |
1045 ART_COST = std::numeric_limits<Cost>::min(); |
1075 for (int i = 0; i != _arc_num; ++i) { |
1046 for (int i = 0; i != _arc_num; ++i) { |
1076 if (_cost[i] > ART_COST) ART_COST = _cost[i]; |
1047 if (_cost[i] > ART_COST) ART_COST = _cost[i]; |
1077 } |
1048 } |
1091 _thread[_root] = 0; |
1062 _thread[_root] = 0; |
1092 _rev_thread[0] = _root; |
1063 _rev_thread[0] = _root; |
1093 _succ_num[_root] = _node_num + 1; |
1064 _succ_num[_root] = _node_num + 1; |
1094 _last_succ[_root] = _root - 1; |
1065 _last_succ[_root] = _root - 1; |
1095 _supply[_root] = -_sum_supply; |
1066 _supply[_root] = -_sum_supply; |
1096 _pi[_root] = _sum_supply < 0 ? -ART_COST : ART_COST; |
1067 _pi[_root] = 0; |
1097 |
1068 |
1098 // Add artificial arcs and initialize the spanning tree data structure |
1069 // Add artificial arcs and initialize the spanning tree data structure |
1099 for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) { |
1070 if (_sum_supply == 0) { |
1100 _parent[u] = _root; |
1071 // EQ supply constraints |
1101 _pred[u] = e; |
1072 _search_arc_num = _arc_num; |
1102 _thread[u] = u + 1; |
1073 _all_arc_num = _arc_num + _node_num; |
1103 _rev_thread[u + 1] = u; |
1074 for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) { |
1104 _succ_num[u] = 1; |
1075 _parent[u] = _root; |
1105 _last_succ[u] = u; |
1076 _pred[u] = e; |
1106 _cost[e] = ART_COST; |
1077 _thread[u] = u + 1; |
1107 _cap[e] = INF; |
1078 _rev_thread[u + 1] = u; |
1108 _state[e] = STATE_TREE; |
1079 _succ_num[u] = 1; |
1109 if (_supply[u] > 0 || (_supply[u] == 0 && _sum_supply <= 0)) { |
1080 _last_succ[u] = u; |
1110 _flow[e] = _supply[u]; |
1081 _cap[e] = INF; |
1111 _forward[u] = true; |
1082 _state[e] = STATE_TREE; |
1112 _pi[u] = -ART_COST + _pi[_root]; |
1083 if (_supply[u] >= 0) { |
1113 } else { |
1084 _forward[u] = true; |
1114 _flow[e] = -_supply[u]; |
1085 _pi[u] = 0; |
1115 _forward[u] = false; |
1086 _source[e] = u; |
1116 _pi[u] = ART_COST + _pi[_root]; |
1087 _target[e] = _root; |
1117 } |
1088 _flow[e] = _supply[u]; |
|
1089 _cost[e] = 0; |
|
1090 } else { |
|
1091 _forward[u] = false; |
|
1092 _pi[u] = ART_COST; |
|
1093 _source[e] = _root; |
|
1094 _target[e] = u; |
|
1095 _flow[e] = -_supply[u]; |
|
1096 _cost[e] = ART_COST; |
|
1097 } |
|
1098 } |
|
1099 } |
|
1100 else if (_sum_supply > 0) { |
|
1101 // LEQ supply constraints |
|
1102 _search_arc_num = _arc_num + _node_num; |
|
1103 int f = _arc_num + _node_num; |
|
1104 for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) { |
|
1105 _parent[u] = _root; |
|
1106 _thread[u] = u + 1; |
|
1107 _rev_thread[u + 1] = u; |
|
1108 _succ_num[u] = 1; |
|
1109 _last_succ[u] = u; |
|
1110 if (_supply[u] >= 0) { |
|
1111 _forward[u] = true; |
|
1112 _pi[u] = 0; |
|
1113 _pred[u] = e; |
|
1114 _source[e] = u; |
|
1115 _target[e] = _root; |
|
1116 _cap[e] = INF; |
|
1117 _flow[e] = _supply[u]; |
|
1118 _cost[e] = 0; |
|
1119 _state[e] = STATE_TREE; |
|
1120 } else { |
|
1121 _forward[u] = false; |
|
1122 _pi[u] = ART_COST; |
|
1123 _pred[u] = f; |
|
1124 _source[f] = _root; |
|
1125 _target[f] = u; |
|
1126 _cap[f] = INF; |
|
1127 _flow[f] = -_supply[u]; |
|
1128 _cost[f] = ART_COST; |
|
1129 _state[f] = STATE_TREE; |
|
1130 _source[e] = u; |
|
1131 _target[e] = _root; |
|
1132 _cap[e] = INF; |
|
1133 _flow[e] = 0; |
|
1134 _cost[e] = 0; |
|
1135 _state[e] = STATE_LOWER; |
|
1136 ++f; |
|
1137 } |
|
1138 } |
|
1139 _all_arc_num = f; |
|
1140 } |
|
1141 else { |
|
1142 // GEQ supply constraints |
|
1143 _search_arc_num = _arc_num + _node_num; |
|
1144 int f = _arc_num + _node_num; |
|
1145 for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) { |
|
1146 _parent[u] = _root; |
|
1147 _thread[u] = u + 1; |
|
1148 _rev_thread[u + 1] = u; |
|
1149 _succ_num[u] = 1; |
|
1150 _last_succ[u] = u; |
|
1151 if (_supply[u] <= 0) { |
|
1152 _forward[u] = false; |
|
1153 _pi[u] = 0; |
|
1154 _pred[u] = e; |
|
1155 _source[e] = _root; |
|
1156 _target[e] = u; |
|
1157 _cap[e] = INF; |
|
1158 _flow[e] = -_supply[u]; |
|
1159 _cost[e] = 0; |
|
1160 _state[e] = STATE_TREE; |
|
1161 } else { |
|
1162 _forward[u] = true; |
|
1163 _pi[u] = -ART_COST; |
|
1164 _pred[u] = f; |
|
1165 _source[f] = u; |
|
1166 _target[f] = _root; |
|
1167 _cap[f] = INF; |
|
1168 _flow[f] = _supply[u]; |
|
1169 _state[f] = STATE_TREE; |
|
1170 _cost[f] = ART_COST; |
|
1171 _source[e] = _root; |
|
1172 _target[e] = u; |
|
1173 _cap[e] = INF; |
|
1174 _flow[e] = 0; |
|
1175 _cost[e] = 0; |
|
1176 _state[e] = STATE_LOWER; |
|
1177 ++f; |
|
1178 } |
|
1179 } |
|
1180 _all_arc_num = f; |
1118 } |
1181 } |
1119 |
1182 |
1120 return true; |
1183 return true; |
1121 } |
1184 } |
1122 |
1185 |
1372 updatePotential(); |
1435 updatePotential(); |
1373 } |
1436 } |
1374 } |
1437 } |
1375 |
1438 |
1376 // Check feasibility |
1439 // Check feasibility |
1377 if (_sum_supply < 0) { |
1440 for (int e = _search_arc_num; e != _all_arc_num; ++e) { |
1378 for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) { |
1441 if (_flow[e] != 0) return INFEASIBLE; |
1379 if (_supply[u] >= 0 && _flow[e] != 0) return INFEASIBLE; |
|
1380 } |
|
1381 } |
|
1382 else if (_sum_supply > 0) { |
|
1383 for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) { |
|
1384 if (_supply[u] <= 0 && _flow[e] != 0) return INFEASIBLE; |
|
1385 } |
|
1386 } |
|
1387 else { |
|
1388 for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) { |
|
1389 if (_flow[e] != 0) return INFEASIBLE; |
|
1390 } |
|
1391 } |
1442 } |
1392 |
1443 |
1393 // Transform the solution and the supply map to the original form |
1444 // Transform the solution and the supply map to the original form |
1394 if (_have_lower) { |
1445 if (_have_lower) { |
1395 for (int i = 0; i != _arc_num; ++i) { |
1446 for (int i = 0; i != _arc_num; ++i) { |
1399 _supply[_source[i]] += c; |
1450 _supply[_source[i]] += c; |
1400 _supply[_target[i]] -= c; |
1451 _supply[_target[i]] -= c; |
1401 } |
1452 } |
1402 } |
1453 } |
1403 } |
1454 } |
|
1455 |
|
1456 // Shift potentials to meet the requirements of the GEQ/LEQ type |
|
1457 // optimality conditions |
|
1458 if (_sum_supply == 0) { |
|
1459 if (_stype == GEQ) { |
|
1460 Cost max_pot = std::numeric_limits<Cost>::min(); |
|
1461 for (int i = 0; i != _node_num; ++i) { |
|
1462 if (_pi[i] > max_pot) max_pot = _pi[i]; |
|
1463 } |
|
1464 if (max_pot > 0) { |
|
1465 for (int i = 0; i != _node_num; ++i) |
|
1466 _pi[i] -= max_pot; |
|
1467 } |
|
1468 } else { |
|
1469 Cost min_pot = std::numeric_limits<Cost>::max(); |
|
1470 for (int i = 0; i != _node_num; ++i) { |
|
1471 if (_pi[i] < min_pot) min_pot = _pi[i]; |
|
1472 } |
|
1473 if (min_pot < 0) { |
|
1474 for (int i = 0; i != _node_num; ++i) |
|
1475 _pi[i] -= min_pot; |
|
1476 } |
|
1477 } |
|
1478 } |
1404 |
1479 |
1405 return OPTIMAL; |
1480 return OPTIMAL; |
1406 } |
1481 } |
1407 |
1482 |
1408 }; //class NetworkSimplex |
1483 }; //class NetworkSimplex |