211 _graph(graph), _lower(&lower), _capacity(graph), _orig_cost(cost), |
203 _graph(graph), _lower(&lower), _capacity(graph), _orig_cost(cost), |
212 _cost(graph), _supply(graph), _flow(NULL), _local_flow(false), |
204 _cost(graph), _supply(graph), _flow(NULL), _local_flow(false), |
213 _potential(NULL), _local_potential(false), _res_cost(_cost), |
205 _potential(NULL), _local_potential(false), _res_cost(_cost), |
214 _res_graph(NULL), _red_cost(NULL), _excess(graph, 0) |
206 _res_graph(NULL), _red_cost(NULL), _excess(graph, 0) |
215 { |
207 { |
216 // Removing non-zero lower bounds |
208 // Remove non-zero lower bounds |
217 _capacity = subMap(capacity, lower); |
209 _capacity = subMap(capacity, lower); |
218 Supply sum = 0; |
210 Supply sum = 0; |
219 for (NodeIt n(_graph); n != INVALID; ++n) { |
211 for (NodeIt n(_graph); n != INVALID; ++n) { |
220 Supply s = supply[n]; |
212 Supply s = supply[n]; |
221 for (InEdgeIt e(_graph, n); e != INVALID; ++e) |
213 for (InEdgeIt e(_graph, n); e != INVALID; ++e) |
272 _graph(graph), _lower(&lower), _capacity(graph), _orig_cost(cost), |
264 _graph(graph), _lower(&lower), _capacity(graph), _orig_cost(cost), |
273 _cost(graph), _supply(graph), _flow(NULL), _local_flow(false), |
265 _cost(graph), _supply(graph), _flow(NULL), _local_flow(false), |
274 _potential(NULL), _local_potential(false), _res_cost(_cost), |
266 _potential(NULL), _local_potential(false), _res_cost(_cost), |
275 _res_graph(NULL), _red_cost(NULL), _excess(graph, 0) |
267 _res_graph(NULL), _red_cost(NULL), _excess(graph, 0) |
276 { |
268 { |
277 // Removing nonzero lower bounds |
269 // Remove nonzero lower bounds |
278 _capacity = subMap(capacity, lower); |
270 _capacity = subMap(capacity, lower); |
279 for (NodeIt n(_graph); n != INVALID; ++n) { |
271 for (NodeIt n(_graph); n != INVALID; ++n) { |
280 Supply sum = 0; |
272 Supply sum = 0; |
281 if (n == s) sum = flow_value; |
273 if (n == s) sum = flow_value; |
282 if (n == t) sum = -flow_value; |
274 if (n == t) sum = -flow_value; |
445 } |
448 } |
446 |
449 |
447 _red_cost = new ReducedCostMap(_graph, _cost, *_potential); |
450 _red_cost = new ReducedCostMap(_graph, _cost, *_potential); |
448 _res_graph = new ResGraph(_graph, _capacity, *_flow); |
451 _res_graph = new ResGraph(_graph, _capacity, *_flow); |
449 |
452 |
450 // Initializing the scaled cost map and the epsilon parameter |
453 // Initialize the scaled cost map and the epsilon parameter |
451 Cost max_cost = 0; |
454 Cost max_cost = 0; |
452 int node_num = countNodes(_graph); |
455 int node_num = countNodes(_graph); |
453 for (EdgeIt e(_graph); e != INVALID; ++e) { |
456 for (EdgeIt e(_graph); e != INVALID; ++e) { |
454 _cost[e] = LCost(_orig_cost[e]) * node_num * ALPHA; |
457 _cost[e] = LCost(_orig_cost[e]) * node_num * _alpha; |
455 if (_orig_cost[e] > max_cost) max_cost = _orig_cost[e]; |
458 if (_orig_cost[e] > max_cost) max_cost = _orig_cost[e]; |
456 } |
459 } |
457 _epsilon = max_cost * node_num; |
460 _epsilon = max_cost * node_num; |
458 |
461 |
459 // Finding a feasible flow using Circulation |
462 // Find a feasible flow using Circulation |
460 Circulation< Graph, ConstMap<Edge, Capacity>, CapacityEdgeMap, |
463 Circulation< Graph, ConstMap<Edge, Capacity>, CapacityEdgeMap, |
461 SupplyMap > |
464 SupplyMap > |
462 circulation( _graph, constMap<Edge>(Capacity(0)), _capacity, |
465 circulation( _graph, constMap<Edge>(Capacity(0)), _capacity, |
463 _supply ); |
466 _supply ); |
464 return circulation.flowMap(*_flow).run(); |
467 return circulation.flowMap(*_flow).run(); |
465 } |
468 } |
466 |
469 |
467 |
470 /// Execute the algorithm performing partial augmentation and |
468 /// Execute the algorithm. |
471 /// relabel operations. |
469 bool start() { |
472 bool startPartialAugment() { |
|
473 // Paramters for heuristics |
|
474 const int BF_HEURISTIC_EPSILON_BOUND = 1000; |
|
475 const int BF_HEURISTIC_BOUND_FACTOR = 3; |
|
476 // Maximum augment path length |
|
477 const int MAX_PATH_LENGTH = 4; |
|
478 |
|
479 // Variables |
|
480 typename Graph::template NodeMap<Edge> pred_edge(_graph); |
|
481 typename Graph::template NodeMap<bool> forward(_graph); |
|
482 typename Graph::template NodeMap<OutEdgeIt> next_out(_graph); |
|
483 typename Graph::template NodeMap<InEdgeIt> next_in(_graph); |
|
484 typename Graph::template NodeMap<bool> next_dir(_graph); |
470 std::deque<Node> active_nodes; |
485 std::deque<Node> active_nodes; |
471 typename Graph::template NodeMap<bool> hyper(_graph, false); |
486 std::vector<Node> path_nodes; |
472 |
487 |
473 int node_num = countNodes(_graph); |
488 int node_num = countNodes(_graph); |
474 for ( ; _epsilon >= 1; _epsilon = _epsilon < ALPHA && _epsilon > 1 ? |
489 for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ? |
475 1 : _epsilon / ALPHA ) |
490 1 : _epsilon / _alpha ) |
476 { |
491 { |
477 // Performing price refinement heuristic using Bellman-Ford |
492 // "Early Termination" heuristic: use Bellman-Ford algorithm |
478 // algorithm |
493 // to check if the current flow is optimal |
479 if (_epsilon <= BF_HEURISTIC_EPSILON_BOUND) { |
494 if (_epsilon <= BF_HEURISTIC_EPSILON_BOUND) { |
480 typedef ShiftMap< ResidualCostMap<LargeCostMap> > ShiftCostMap; |
495 typedef ShiftMap< ResidualCostMap<LargeCostMap> > ShiftCostMap; |
481 ShiftCostMap shift_cost(_res_cost, _epsilon); |
496 ShiftCostMap shift_cost(_res_cost, 1); |
482 BellmanFord<ResGraph, ShiftCostMap> bf(*_res_graph, shift_cost); |
497 BellmanFord<ResGraph, ShiftCostMap> bf(*_res_graph, shift_cost); |
483 bf.init(0); |
498 bf.init(0); |
484 bool done = false; |
499 bool done = false; |
485 int K = int(BF_HEURISTIC_BOUND_FACTOR * sqrt(node_num)); |
500 int K = int(BF_HEURISTIC_BOUND_FACTOR * sqrt(node_num)); |
486 for (int i = 0; i < K && !done; ++i) |
501 for (int i = 0; i < K && !done; ++i) |
487 done = bf.processNextWeakRound(); |
502 done = bf.processNextWeakRound(); |
488 if (done) { |
503 if (done) break; |
489 for (NodeIt n(_graph); n != INVALID; ++n) |
504 } |
490 (*_potential)[n] = bf.dist(n); |
505 |
491 continue; |
506 // Saturate edges not satisfying the optimality condition |
492 } |
|
493 } |
|
494 |
|
495 // Saturating edges not satisfying the optimality condition |
|
496 Capacity delta; |
507 Capacity delta; |
497 for (EdgeIt e(_graph); e != INVALID; ++e) { |
508 for (EdgeIt e(_graph); e != INVALID; ++e) { |
498 if (_capacity[e] - (*_flow)[e] > 0 && (*_red_cost)[e] < 0) { |
509 if (_capacity[e] - (*_flow)[e] > 0 && (*_red_cost)[e] < 0) { |
499 delta = _capacity[e] - (*_flow)[e]; |
510 delta = _capacity[e] - (*_flow)[e]; |
500 _excess[_graph.source(e)] -= delta; |
511 _excess[_graph.source(e)] -= delta; |
506 _excess[_graph.source(e)] += (*_flow)[e]; |
517 _excess[_graph.source(e)] += (*_flow)[e]; |
507 (*_flow)[e] = 0; |
518 (*_flow)[e] = 0; |
508 } |
519 } |
509 } |
520 } |
510 |
521 |
511 // Finding active nodes (i.e. nodes with positive excess) |
522 // Find active nodes (i.e. nodes with positive excess) |
512 for (NodeIt n(_graph); n != INVALID; ++n) |
523 for (NodeIt n(_graph); n != INVALID; ++n) { |
513 if (_excess[n] > 0) active_nodes.push_back(n); |
524 if (_excess[n] > 0) active_nodes.push_back(n); |
514 |
525 } |
515 // Performing push and relabel operations |
526 |
|
527 // Initialize the next edge maps |
|
528 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
529 next_out[n] = OutEdgeIt(_graph, n); |
|
530 next_in[n] = InEdgeIt(_graph, n); |
|
531 next_dir[n] = true; |
|
532 } |
|
533 |
|
534 // Perform partial augment and relabel operations |
516 while (active_nodes.size() > 0) { |
535 while (active_nodes.size() > 0) { |
|
536 // Select an active node (FIFO selection) |
|
537 if (_excess[active_nodes[0]] <= 0) { |
|
538 active_nodes.pop_front(); |
|
539 continue; |
|
540 } |
|
541 Node start = active_nodes[0]; |
|
542 path_nodes.clear(); |
|
543 path_nodes.push_back(start); |
|
544 |
|
545 // Find an augmenting path from the start node |
|
546 Node u, tip = start; |
|
547 LCost min_red_cost; |
|
548 while ( _excess[tip] >= 0 && |
|
549 int(path_nodes.size()) <= MAX_PATH_LENGTH ) |
|
550 { |
|
551 if (next_dir[tip]) { |
|
552 for (OutEdgeIt e = next_out[tip]; e != INVALID; ++e) { |
|
553 if (_capacity[e] - (*_flow)[e] > 0 && (*_red_cost)[e] < 0) { |
|
554 u = _graph.target(e); |
|
555 pred_edge[u] = e; |
|
556 forward[u] = true; |
|
557 next_out[tip] = e; |
|
558 tip = u; |
|
559 path_nodes.push_back(tip); |
|
560 goto next_step; |
|
561 } |
|
562 } |
|
563 next_dir[tip] = false; |
|
564 } |
|
565 for (InEdgeIt e = next_in[tip]; e != INVALID; ++e) { |
|
566 if ((*_flow)[e] > 0 && -(*_red_cost)[e] < 0) { |
|
567 u = _graph.source(e); |
|
568 pred_edge[u] = e; |
|
569 forward[u] = false; |
|
570 next_in[tip] = e; |
|
571 tip = u; |
|
572 path_nodes.push_back(tip); |
|
573 goto next_step; |
|
574 } |
|
575 } |
|
576 |
|
577 // Relabel tip node |
|
578 min_red_cost = std::numeric_limits<LCost>::max() / 2; |
|
579 for (OutEdgeIt oe(_graph, tip); oe != INVALID; ++oe) { |
|
580 if ( _capacity[oe] - (*_flow)[oe] > 0 && |
|
581 (*_red_cost)[oe] < min_red_cost ) |
|
582 min_red_cost = (*_red_cost)[oe]; |
|
583 } |
|
584 for (InEdgeIt ie(_graph, tip); ie != INVALID; ++ie) { |
|
585 if ((*_flow)[ie] > 0 && -(*_red_cost)[ie] < min_red_cost) |
|
586 min_red_cost = -(*_red_cost)[ie]; |
|
587 } |
|
588 (*_potential)[tip] -= min_red_cost + _epsilon; |
|
589 |
|
590 // Reset the next edge maps |
|
591 next_out[tip] = OutEdgeIt(_graph, tip); |
|
592 next_in[tip] = InEdgeIt(_graph, tip); |
|
593 next_dir[tip] = true; |
|
594 |
|
595 // Step back |
|
596 if (tip != start) { |
|
597 path_nodes.pop_back(); |
|
598 tip = path_nodes[path_nodes.size()-1]; |
|
599 } |
|
600 |
|
601 next_step: |
|
602 continue; |
|
603 } |
|
604 |
|
605 // Augment along the found path (as much flow as possible) |
|
606 Capacity delta; |
|
607 for (int i = 1; i < int(path_nodes.size()); ++i) { |
|
608 u = path_nodes[i]; |
|
609 delta = forward[u] ? |
|
610 _capacity[pred_edge[u]] - (*_flow)[pred_edge[u]] : |
|
611 (*_flow)[pred_edge[u]]; |
|
612 delta = std::min(delta, _excess[path_nodes[i-1]]); |
|
613 (*_flow)[pred_edge[u]] += forward[u] ? delta : -delta; |
|
614 _excess[path_nodes[i-1]] -= delta; |
|
615 _excess[u] += delta; |
|
616 if (_excess[u] > 0 && _excess[u] <= delta) active_nodes.push_back(u); |
|
617 } |
|
618 } |
|
619 } |
|
620 |
|
621 // Compute node potentials for the original costs |
|
622 ResidualCostMap<CostMap> res_cost(_orig_cost); |
|
623 BellmanFord< ResGraph, ResidualCostMap<CostMap> > |
|
624 bf(*_res_graph, res_cost); |
|
625 bf.init(0); bf.start(); |
|
626 for (NodeIt n(_graph); n != INVALID; ++n) |
|
627 (*_potential)[n] = bf.dist(n); |
|
628 |
|
629 // Handle non-zero lower bounds |
|
630 if (_lower) { |
|
631 for (EdgeIt e(_graph); e != INVALID; ++e) |
|
632 (*_flow)[e] += (*_lower)[e]; |
|
633 } |
|
634 return true; |
|
635 } |
|
636 |
|
637 /// Execute the algorithm performing push and relabel operations. |
|
638 bool startPushRelabel() { |
|
639 // Paramters for heuristics |
|
640 const int BF_HEURISTIC_EPSILON_BOUND = 1000; |
|
641 const int BF_HEURISTIC_BOUND_FACTOR = 3; |
|
642 |
|
643 typename Graph::template NodeMap<bool> hyper(_graph, false); |
|
644 typename Graph::template NodeMap<Edge> pred_edge(_graph); |
|
645 typename Graph::template NodeMap<bool> forward(_graph); |
|
646 typename Graph::template NodeMap<OutEdgeIt> next_out(_graph); |
|
647 typename Graph::template NodeMap<InEdgeIt> next_in(_graph); |
|
648 typename Graph::template NodeMap<bool> next_dir(_graph); |
|
649 std::deque<Node> active_nodes; |
|
650 |
|
651 int node_num = countNodes(_graph); |
|
652 for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ? |
|
653 1 : _epsilon / _alpha ) |
|
654 { |
|
655 // "Early Termination" heuristic: use Bellman-Ford algorithm |
|
656 // to check if the current flow is optimal |
|
657 if (_epsilon <= BF_HEURISTIC_EPSILON_BOUND) { |
|
658 typedef ShiftMap< ResidualCostMap<LargeCostMap> > ShiftCostMap; |
|
659 ShiftCostMap shift_cost(_res_cost, 1); |
|
660 BellmanFord<ResGraph, ShiftCostMap> bf(*_res_graph, shift_cost); |
|
661 bf.init(0); |
|
662 bool done = false; |
|
663 int K = int(BF_HEURISTIC_BOUND_FACTOR * sqrt(node_num)); |
|
664 for (int i = 0; i < K && !done; ++i) |
|
665 done = bf.processNextWeakRound(); |
|
666 if (done) break; |
|
667 } |
|
668 |
|
669 // Saturate edges not satisfying the optimality condition |
|
670 Capacity delta; |
|
671 for (EdgeIt e(_graph); e != INVALID; ++e) { |
|
672 if (_capacity[e] - (*_flow)[e] > 0 && (*_red_cost)[e] < 0) { |
|
673 delta = _capacity[e] - (*_flow)[e]; |
|
674 _excess[_graph.source(e)] -= delta; |
|
675 _excess[_graph.target(e)] += delta; |
|
676 (*_flow)[e] = _capacity[e]; |
|
677 } |
|
678 if ((*_flow)[e] > 0 && -(*_red_cost)[e] < 0) { |
|
679 _excess[_graph.target(e)] -= (*_flow)[e]; |
|
680 _excess[_graph.source(e)] += (*_flow)[e]; |
|
681 (*_flow)[e] = 0; |
|
682 } |
|
683 } |
|
684 |
|
685 // Find active nodes (i.e. nodes with positive excess) |
|
686 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
687 if (_excess[n] > 0) active_nodes.push_back(n); |
|
688 } |
|
689 |
|
690 // Initialize the next edge maps |
|
691 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
692 next_out[n] = OutEdgeIt(_graph, n); |
|
693 next_in[n] = InEdgeIt(_graph, n); |
|
694 next_dir[n] = true; |
|
695 } |
|
696 |
|
697 // Perform push and relabel operations |
|
698 while (active_nodes.size() > 0) { |
|
699 // Select an active node (FIFO selection) |
517 Node n = active_nodes[0], t; |
700 Node n = active_nodes[0], t; |
518 bool relabel_enabled = true; |
701 bool relabel_enabled = true; |
519 |
702 |
520 // Performing push operations if there are admissible edges |
703 // Perform push operations if there are admissible edges |
521 if (_excess[n] > 0) { |
704 if (_excess[n] > 0 && next_dir[n]) { |
522 for (OutEdgeIt e(_graph, n); e != INVALID; ++e) { |
705 OutEdgeIt e = next_out[n]; |
|
706 for ( ; e != INVALID; ++e) { |
523 if (_capacity[e] - (*_flow)[e] > 0 && (*_red_cost)[e] < 0) { |
707 if (_capacity[e] - (*_flow)[e] > 0 && (*_red_cost)[e] < 0) { |
524 delta = _capacity[e] - (*_flow)[e] <= _excess[n] ? |
708 delta = std::min(_capacity[e] - (*_flow)[e], _excess[n]); |
525 _capacity[e] - (*_flow)[e] : _excess[n]; |
|
526 t = _graph.target(e); |
709 t = _graph.target(e); |
527 |
710 |
528 // Push-look-ahead heuristic |
711 // Push-look-ahead heuristic |
529 Capacity ahead = -_excess[t]; |
712 Capacity ahead = -_excess[t]; |
530 for (OutEdgeIt oe(_graph, t); oe != INVALID; ++oe) { |
713 for (OutEdgeIt oe(_graph, t); oe != INVALID; ++oe) { |
611 if ((*_flow)[ie] > 0 && -(*_red_cost)[ie] < min_red_cost) |
801 if ((*_flow)[ie] > 0 && -(*_red_cost)[ie] < min_red_cost) |
612 min_red_cost = -(*_red_cost)[ie]; |
802 min_red_cost = -(*_red_cost)[ie]; |
613 } |
803 } |
614 (*_potential)[n] -= min_red_cost + _epsilon; |
804 (*_potential)[n] -= min_red_cost + _epsilon; |
615 hyper[n] = false; |
805 hyper[n] = false; |
616 } |
806 |
617 |
807 // Reset the next edge maps |
618 // Removing active nodes with non-positive excess |
808 next_out[n] = OutEdgeIt(_graph, n); |
|
809 next_in[n] = InEdgeIt(_graph, n); |
|
810 next_dir[n] = true; |
|
811 } |
|
812 |
|
813 // Remove nodes that are not active nor hyper |
619 while ( active_nodes.size() > 0 && |
814 while ( active_nodes.size() > 0 && |
620 _excess[active_nodes[0]] <= 0 && |
815 _excess[active_nodes[0]] <= 0 && |
621 !hyper[active_nodes[0]] ) { |
816 !hyper[active_nodes[0]] ) { |
622 active_nodes.pop_front(); |
817 active_nodes.pop_front(); |
623 } |
818 } |
624 } |
819 } |
625 } |
820 } |
626 |
821 |
627 // Computing node potentials for the original costs |
822 // Compute node potentials for the original costs |
628 ResidualCostMap<CostMap> res_cost(_orig_cost); |
823 ResidualCostMap<CostMap> res_cost(_orig_cost); |
629 BellmanFord< ResGraph, ResidualCostMap<CostMap> > |
824 BellmanFord< ResGraph, ResidualCostMap<CostMap> > |
630 bf(*_res_graph, res_cost); |
825 bf(*_res_graph, res_cost); |
631 bf.init(0); bf.start(); |
826 bf.init(0); bf.start(); |
632 for (NodeIt n(_graph); n != INVALID; ++n) |
827 for (NodeIt n(_graph); n != INVALID; ++n) |
633 (*_potential)[n] = bf.dist(n); |
828 (*_potential)[n] = bf.dist(n); |
634 |
829 |
635 // Handling non-zero lower bounds |
830 // Handle non-zero lower bounds |
636 if (_lower) { |
831 if (_lower) { |
637 for (EdgeIt e(_graph); e != INVALID; ++e) |
832 for (EdgeIt e(_graph); e != INVALID; ++e) |
638 (*_flow)[e] += (*_lower)[e]; |
833 (*_flow)[e] += (*_lower)[e]; |
639 } |
834 } |
640 return true; |
835 return true; |