gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Add a parameter to control arc mixing in NS (#298)
0 1 0
default
1 file changed with 24 insertions and 9 deletions:
↑ Collapse diff ↑
Ignore white space 384 line context
... ...
@@ -436,434 +436,449 @@
436 436
                                     std::sqrt(double(_search_arc_num))),
437 437
                                 MIN_LIST_LENGTH );
438 438
        _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
439 439
                                 MIN_MINOR_LIMIT );
440 440
        _curr_length = _minor_count = 0;
441 441
        _candidates.resize(_list_length);
442 442
      }
443 443

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

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

	
500 500
    }; //class CandidateListPivotRule
501 501

	
502 502

	
503 503
    // Implementation of the Altering Candidate List pivot rule
504 504
    class AlteringListPivotRule
505 505
    {
506 506
    private:
507 507

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

	
517 517
      // Pivot rule data
518 518
      int _block_size, _head_length, _curr_length;
519 519
      int _next_arc;
520 520
      IntVector _candidates;
521 521
      CostVector _cand_cost;
522 522

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

	
535 535
      SortFunc _sort_func;
536 536

	
537 537
    public:
538 538

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

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

	
561 561
      // Find next entering arc
562 562
      bool findEnteringArc() {
563 563
        // Check the current candidate list
564 564
        int e;
565 565
        for (int i = 0; i < _curr_length; ++i) {
566 566
          e = _candidates[i];
567 567
          _cand_cost[e] = _state[e] *
568 568
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
569 569
          if (_cand_cost[e] >= 0) {
570 570
            _candidates[i--] = _candidates[--_curr_length];
571 571
          }
572 572
        }
573 573

	
574 574
        // Extend the list
575 575
        int cnt = _block_size;
576 576
        int limit = _head_length;
577 577

	
578 578
        for (e = _next_arc; e < _search_arc_num; ++e) {
579 579
          _cand_cost[e] = _state[e] *
580 580
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
581 581
          if (_cand_cost[e] < 0) {
582 582
            _candidates[_curr_length++] = e;
583 583
          }
584 584
          if (--cnt == 0) {
585 585
            if (_curr_length > limit) goto search_end;
586 586
            limit = 0;
587 587
            cnt = _block_size;
588 588
          }
589 589
        }
590 590
        for (e = 0; e < _next_arc; ++e) {
591 591
          _cand_cost[e] = _state[e] *
592 592
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
593 593
          if (_cand_cost[e] < 0) {
594 594
            _candidates[_curr_length++] = e;
595 595
          }
596 596
          if (--cnt == 0) {
597 597
            if (_curr_length > limit) goto search_end;
598 598
            limit = 0;
599 599
            cnt = _block_size;
600 600
          }
601 601
        }
602 602
        if (_curr_length == 0) return false;
603 603
        
604 604
      search_end:
605 605

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

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

	
619 619
    }; //class AlteringListPivotRule
620 620

	
621 621
  public:
622 622

	
623 623
    /// \brief Constructor.
624 624
    ///
625 625
    /// The constructor of the class.
626 626
    ///
627 627
    /// \param graph The digraph the algorithm runs on.
628
    NetworkSimplex(const GR& graph) :
628
    /// \param arc_mixing Indicate if the arcs have to be stored in a
629
    /// mixed order in the internal data structure. 
630
    /// In special cases, it could lead to better overall performance,
631
    /// but it is usually slower. Therefore it is disabled by default.
632
    NetworkSimplex(const GR& graph, bool arc_mixing = false) :
629 633
      _graph(graph), _node_id(graph), _arc_id(graph),
630 634
      INF(std::numeric_limits<Value>::has_infinity ?
631 635
          std::numeric_limits<Value>::infinity() :
632 636
          std::numeric_limits<Value>::max())
633 637
    {
634 638
      // Check the value types
635 639
      LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
636 640
        "The flow type of NetworkSimplex must be signed");
637 641
      LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
638 642
        "The cost type of NetworkSimplex must be signed");
639 643
        
640 644
      // Resize vectors
641 645
      _node_num = countNodes(_graph);
642 646
      _arc_num = countArcs(_graph);
643 647
      int all_node_num = _node_num + 1;
644 648
      int max_arc_num = _arc_num + 2 * _node_num;
645 649

	
646 650
      _source.resize(max_arc_num);
647 651
      _target.resize(max_arc_num);
648 652

	
649 653
      _lower.resize(_arc_num);
650 654
      _upper.resize(_arc_num);
651 655
      _cap.resize(max_arc_num);
652 656
      _cost.resize(max_arc_num);
653 657
      _supply.resize(all_node_num);
654 658
      _flow.resize(max_arc_num);
655 659
      _pi.resize(all_node_num);
656 660

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

	
666
      // Copy the graph (store the arcs in a mixed order)
670
      // Copy the graph
667 671
      int i = 0;
668 672
      for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
669 673
        _node_id[n] = i;
670 674
      }
671
      int k = std::max(int(std::sqrt(double(_arc_num))), 10);
672
      i = 0;
673
      for (ArcIt a(_graph); a != INVALID; ++a) {
674
        _arc_id[a] = i;
675
        _source[i] = _node_id[_graph.source(a)];
676
        _target[i] = _node_id[_graph.target(a)];
677
        if ((i += k) >= _arc_num) i = (i % k) + 1;
675
      if (arc_mixing) {
676
        // Store the arcs in a mixed order
677
        int k = std::max(int(std::sqrt(double(_arc_num))), 10);
678
        int i = 0, j = 0;
679
        for (ArcIt a(_graph); a != INVALID; ++a) {
680
          _arc_id[a] = i;
681
          _source[i] = _node_id[_graph.source(a)];
682
          _target[i] = _node_id[_graph.target(a)];
683
          if ((i += k) >= _arc_num) i = ++j;
684
        }
685
      } else {
686
        // Store the arcs in the original order
687
        int i = 0;
688
        for (ArcIt a(_graph); a != INVALID; ++a, ++i) {
689
          _arc_id[a] = i;
690
          _source[i] = _node_id[_graph.source(a)];
691
          _target[i] = _node_id[_graph.target(a)];
692
        }
678 693
      }
679 694
      
680 695
      // Initialize maps
681 696
      for (int i = 0; i != _node_num; ++i) {
682 697
        _supply[i] = 0;
683 698
      }
684 699
      for (int i = 0; i != _arc_num; ++i) {
685 700
        _lower[i] = 0;
686 701
        _upper[i] = INF;
687 702
        _cost[i] = 1;
688 703
      }
689 704
      _have_lower = false;
690 705
      _stype = GEQ;
691 706
    }
692 707

	
693 708
    /// \name Parameters
694 709
    /// The parameters of the algorithm can be specified using these
695 710
    /// functions.
696 711

	
697 712
    /// @{
698 713

	
699 714
    /// \brief Set the lower bounds on the arcs.
700 715
    ///
701 716
    /// This function sets the lower bounds on the arcs.
702 717
    /// If it is not used before calling \ref run(), the lower bounds
703 718
    /// will be set to zero on all arcs.
704 719
    ///
705 720
    /// \param map An arc map storing the lower bounds.
706 721
    /// Its \c Value type must be convertible to the \c Value type
707 722
    /// of the algorithm.
708 723
    ///
709 724
    /// \return <tt>(*this)</tt>
710 725
    template <typename LowerMap>
711 726
    NetworkSimplex& lowerMap(const LowerMap& map) {
712 727
      _have_lower = true;
713 728
      for (ArcIt a(_graph); a != INVALID; ++a) {
714 729
        _lower[_arc_id[a]] = map[a];
715 730
      }
716 731
      return *this;
717 732
    }
718 733

	
719 734
    /// \brief Set the upper bounds (capacities) on the arcs.
720 735
    ///
721 736
    /// This function sets the upper bounds (capacities) on the arcs.
722 737
    /// If it is not used before calling \ref run(), the upper bounds
723 738
    /// will be set to \ref INF on all arcs (i.e. the flow value will be
724 739
    /// unbounded from above on each arc).
725 740
    ///
726 741
    /// \param map An arc map storing the upper bounds.
727 742
    /// Its \c Value type must be convertible to the \c Value type
728 743
    /// of the algorithm.
729 744
    ///
730 745
    /// \return <tt>(*this)</tt>
731 746
    template<typename UpperMap>
732 747
    NetworkSimplex& upperMap(const UpperMap& map) {
733 748
      for (ArcIt a(_graph); a != INVALID; ++a) {
734 749
        _upper[_arc_id[a]] = map[a];
735 750
      }
736 751
      return *this;
737 752
    }
738 753

	
739 754
    /// \brief Set the costs of the arcs.
740 755
    ///
741 756
    /// This function sets the costs of the arcs.
742 757
    /// If it is not used before calling \ref run(), the costs
743 758
    /// will be set to \c 1 on all arcs.
744 759
    ///
745 760
    /// \param map An arc map storing the costs.
746 761
    /// Its \c Value type must be convertible to the \c Cost type
747 762
    /// of the algorithm.
748 763
    ///
749 764
    /// \return <tt>(*this)</tt>
750 765
    template<typename CostMap>
751 766
    NetworkSimplex& costMap(const CostMap& map) {
752 767
      for (ArcIt a(_graph); a != INVALID; ++a) {
753 768
        _cost[_arc_id[a]] = map[a];
754 769
      }
755 770
      return *this;
756 771
    }
757 772

	
758 773
    /// \brief Set the supply values of the nodes.
759 774
    ///
760 775
    /// This function sets the supply values of the nodes.
761 776
    /// If neither this function nor \ref stSupply() is used before
762 777
    /// calling \ref run(), the supply of each node will be set to zero.
763 778
    /// (It makes sense only if non-zero lower bounds are given.)
764 779
    ///
765 780
    /// \param map A node map storing the supply values.
766 781
    /// Its \c Value type must be convertible to the \c Value type
767 782
    /// of the algorithm.
768 783
    ///
769 784
    /// \return <tt>(*this)</tt>
770 785
    template<typename SupplyMap>
771 786
    NetworkSimplex& supplyMap(const SupplyMap& map) {
772 787
      for (NodeIt n(_graph); n != INVALID; ++n) {
773 788
        _supply[_node_id[n]] = map[n];
774 789
      }
775 790
      return *this;
776 791
    }
777 792

	
778 793
    /// \brief Set single source and target nodes and a supply value.
779 794
    ///
780 795
    /// This function sets a single source node and a single target node
781 796
    /// and the required flow value.
782 797
    /// If neither this function nor \ref supplyMap() is used before
783 798
    /// calling \ref run(), the supply of each node will be set to zero.
784 799
    /// (It makes sense only if non-zero lower bounds are given.)
785 800
    ///
786 801
    /// Using this function has the same effect as using \ref supplyMap()
787 802
    /// with such a map in which \c k is assigned to \c s, \c -k is
788 803
    /// assigned to \c t and all other nodes have zero supply value.
789 804
    ///
790 805
    /// \param s The source node.
791 806
    /// \param t The target node.
792 807
    /// \param k The required amount of flow from node \c s to node \c t
793 808
    /// (i.e. the supply of \c s and the demand of \c t).
794 809
    ///
795 810
    /// \return <tt>(*this)</tt>
796 811
    NetworkSimplex& stSupply(const Node& s, const Node& t, Value k) {
797 812
      for (int i = 0; i != _node_num; ++i) {
798 813
        _supply[i] = 0;
799 814
      }
800 815
      _supply[_node_id[s]] =  k;
801 816
      _supply[_node_id[t]] = -k;
802 817
      return *this;
803 818
    }
804 819
    
805 820
    /// \brief Set the type of the supply constraints.
806 821
    ///
807 822
    /// This function sets the type of the supply/demand constraints.
808 823
    /// If it is not used before calling \ref run(), the \ref GEQ supply
809 824
    /// type will be used.
810 825
    ///
811 826
    /// For more information see \ref SupplyType.
812 827
    ///
813 828
    /// \return <tt>(*this)</tt>
814 829
    NetworkSimplex& supplyType(SupplyType supply_type) {
815 830
      _stype = supply_type;
816 831
      return *this;
817 832
    }
818 833

	
819 834
    /// @}
820 835

	
821 836
    /// \name Execution Control
822 837
    /// The algorithm can be executed using \ref run().
823 838

	
824 839
    /// @{
825 840

	
826 841
    /// \brief Run the algorithm.
827 842
    ///
828 843
    /// This function runs the algorithm.
829 844
    /// The paramters can be specified using functions \ref lowerMap(),
830 845
    /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply(), 
831 846
    /// \ref supplyType().
832 847
    /// For example,
833 848
    /// \code
834 849
    ///   NetworkSimplex<ListDigraph> ns(graph);
835 850
    ///   ns.lowerMap(lower).upperMap(upper).costMap(cost)
836 851
    ///     .supplyMap(sup).run();
837 852
    /// \endcode
838 853
    ///
839 854
    /// This function can be called more than once. All the parameters
840 855
    /// that have been given are kept for the next call, unless
841 856
    /// \ref reset() is called, thus only the modified parameters
842 857
    /// have to be set again. See \ref reset() for examples.
843 858
    /// However the underlying digraph must not be modified after this
844 859
    /// class have been constructed, since it copies and extends the graph.
845 860
    ///
846 861
    /// \param pivot_rule The pivot rule that will be used during the
847 862
    /// algorithm. For more information see \ref PivotRule.
848 863
    ///
849 864
    /// \return \c INFEASIBLE if no feasible flow exists,
850 865
    /// \n \c OPTIMAL if the problem has optimal solution
851 866
    /// (i.e. it is feasible and bounded), and the algorithm has found
852 867
    /// optimal flow and node potentials (primal and dual solutions),
853 868
    /// \n \c UNBOUNDED if the objective function of the problem is
854 869
    /// unbounded, i.e. there is a directed cycle having negative total
855 870
    /// cost and infinite upper bound.
856 871
    ///
857 872
    /// \see ProblemType, PivotRule
858 873
    ProblemType run(PivotRule pivot_rule = BLOCK_SEARCH) {
859 874
      if (!init()) return INFEASIBLE;
860 875
      return start(pivot_rule);
861 876
    }
862 877

	
863 878
    /// \brief Reset all the parameters that have been given before.
864 879
    ///
865 880
    /// This function resets all the paramaters that have been given
866 881
    /// before using functions \ref lowerMap(), \ref upperMap(),
867 882
    /// \ref costMap(), \ref supplyMap(), \ref stSupply(), \ref supplyType().
868 883
    ///
869 884
    /// It is useful for multiple run() calls. If this function is not
0 comments (0 inline)