gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Fixing presolver and basis handling (#255)
0 2 0
default
2 files changed with 60 insertions and 6 deletions:
↑ Collapse diff ↑
Ignore white space 96 line context
... ...
@@ -488,165 +488,198 @@
488 488
    glp_set_obj_coef(lp, i, obj_coef);
489 489
  }
490 490

	
491 491
  GlpkBase::Value GlpkBase::_getObjCoeff(int i) const {
492 492
    //i = 0 means the constant term (shift)
493 493
    return glp_get_obj_coef(lp, i);
494 494
  }
495 495

	
496 496
  void GlpkBase::_setSense(GlpkBase::Sense sense) {
497 497
    switch (sense) {
498 498
    case MIN:
499 499
      glp_set_obj_dir(lp, GLP_MIN);
500 500
      break;
501 501
    case MAX:
502 502
      glp_set_obj_dir(lp, GLP_MAX);
503 503
      break;
504 504
    }
505 505
  }
506 506

	
507 507
  GlpkBase::Sense GlpkBase::_getSense() const {
508 508
    switch(glp_get_obj_dir(lp)) {
509 509
    case GLP_MIN:
510 510
      return MIN;
511 511
    case GLP_MAX:
512 512
      return MAX;
513 513
    default:
514 514
      LEMON_ASSERT(false, "Wrong sense");
515 515
      return GlpkBase::Sense();
516 516
    }
517 517
  }
518 518

	
519 519
  void GlpkBase::_clear() {
520 520
    glp_erase_prob(lp);
521 521
    rows.clear();
522 522
    cols.clear();
523 523
  }
524 524

	
525 525
  void GlpkBase::freeEnv() {
526 526
    glp_free_env();
527 527
  }
528 528

	
529 529
  GlpkBase::FreeEnvHelper GlpkBase::freeEnvHelper;
530 530

	
531 531
  // GlpkLp members
532 532

	
533 533
  GlpkLp::GlpkLp()
534 534
    : LpBase(), LpSolver(), GlpkBase() {
535 535
    messageLevel(MESSAGE_NO_OUTPUT);
536
    presolver(false);
536 537
  }
537 538

	
538 539
  GlpkLp::GlpkLp(const GlpkLp& other)
539 540
    : LpBase(other), LpSolver(other), GlpkBase(other) {
540 541
    messageLevel(MESSAGE_NO_OUTPUT);
542
    presolver(false);
541 543
  }
542 544

	
543 545
  GlpkLp* GlpkLp::newSolver() const { return new GlpkLp; }
544 546
  GlpkLp* GlpkLp::cloneSolver() const { return new GlpkLp(*this); }
545 547

	
546 548
  const char* GlpkLp::_solverName() const { return "GlpkLp"; }
547 549

	
548 550
  void GlpkLp::_clear_temporals() {
549 551
    _primal_ray.clear();
550 552
    _dual_ray.clear();
551 553
  }
552 554

	
553 555
  GlpkLp::SolveExitStatus GlpkLp::_solve() {
554 556
    return solvePrimal();
555 557
  }
556 558

	
557 559
  GlpkLp::SolveExitStatus GlpkLp::solvePrimal() {
558 560
    _clear_temporals();
559 561

	
560 562
    glp_smcp smcp;
561 563
    glp_init_smcp(&smcp);
562 564

	
563 565
    switch (_message_level) {
564 566
    case MESSAGE_NO_OUTPUT:
565 567
      smcp.msg_lev = GLP_MSG_OFF;
566 568
      break;
567 569
    case MESSAGE_ERROR_MESSAGE:
568 570
      smcp.msg_lev = GLP_MSG_ERR;
569 571
      break;
570 572
    case MESSAGE_NORMAL_OUTPUT:
571 573
      smcp.msg_lev = GLP_MSG_ON;
572 574
      break;
573 575
    case MESSAGE_FULL_OUTPUT:
574 576
      smcp.msg_lev = GLP_MSG_ALL;
575 577
      break;
576 578
    }
579
    smcp.presolve = _presolve;
577 580

	
578
    if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
581
    // If the basis is not valid we get an error return value.
582
    // In this case we can try to create a new basis.
583
    switch (glp_simplex(lp, &smcp)) {
584
    case 0:
585
      break;
586
    case GLP_EBADB:
587
    case GLP_ESING:
588
    case GLP_ECOND:
589
      lpx_set_int_parm(lp, LPX_K_MSGLEV, smcp.msg_lev);
590
      glp_adv_basis(lp, 0);
591
      if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
592
      break;
593
    default:
594
      return UNSOLVED;
595
    }
596

	
579 597
    return SOLVED;
580 598
  }
581 599

	
582 600
  GlpkLp::SolveExitStatus GlpkLp::solveDual() {
583 601
    _clear_temporals();
584 602

	
585 603
    glp_smcp smcp;
586 604
    glp_init_smcp(&smcp);
587 605

	
588 606
    switch (_message_level) {
589 607
    case MESSAGE_NO_OUTPUT:
590 608
      smcp.msg_lev = GLP_MSG_OFF;
591 609
      break;
592 610
    case MESSAGE_ERROR_MESSAGE:
593 611
      smcp.msg_lev = GLP_MSG_ERR;
594 612
      break;
595 613
    case MESSAGE_NORMAL_OUTPUT:
596 614
      smcp.msg_lev = GLP_MSG_ON;
597 615
      break;
598 616
    case MESSAGE_FULL_OUTPUT:
599 617
      smcp.msg_lev = GLP_MSG_ALL;
600 618
      break;
601 619
    }
602 620
    smcp.meth = GLP_DUAL;
621
    smcp.presolve = _presolve;
603 622

	
604
    if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
623
    // If the basis is not valid we get an error return value.
624
    // In this case we can try to create a new basis.
625
    switch (glp_simplex(lp, &smcp)) {
626
    case 0:
627
      break;
628
    case GLP_EBADB:
629
    case GLP_ESING:
630
    case GLP_ECOND:
631
      lpx_set_int_parm(lp, LPX_K_MSGLEV, smcp.msg_lev);
632
      glp_adv_basis(lp, 0);
633
      if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
634
      break;
635
    default:
636
      return UNSOLVED;
637
    }
605 638
    return SOLVED;
606 639
  }
607 640

	
608 641
  GlpkLp::Value GlpkLp::_getPrimal(int i) const {
609 642
    return glp_get_col_prim(lp, i);
610 643
  }
611 644

	
612 645
  GlpkLp::Value GlpkLp::_getDual(int i) const {
613 646
    return glp_get_row_dual(lp, i);
614 647
  }
615 648

	
616 649
  GlpkLp::Value GlpkLp::_getPrimalValue() const {
617 650
    return glp_get_obj_val(lp);
618 651
  }
619 652

	
620 653
  GlpkLp::VarStatus GlpkLp::_getColStatus(int i) const {
621 654
    switch (glp_get_col_stat(lp, i)) {
622 655
    case GLP_BS:
623 656
      return BASIC;
624 657
    case GLP_UP:
625 658
      return UPPER;
626 659
    case GLP_LO:
627 660
      return LOWER;
628 661
    case GLP_NF:
629 662
      return FREE;
630 663
    case GLP_NS:
631 664
      return FIXED;
632 665
    default:
633 666
      LEMON_ASSERT(false, "Wrong column status");
634 667
      return GlpkLp::VarStatus();
635 668
    }
636 669
  }
637 670

	
638 671
  GlpkLp::VarStatus GlpkLp::_getRowStatus(int i) const {
639 672
    switch (glp_get_row_stat(lp, i)) {
640 673
    case GLP_BS:
641 674
      return BASIC;
642 675
    case GLP_UP:
643 676
      return UPPER;
644 677
    case GLP_LO:
645 678
      return LOWER;
646 679
    case GLP_NF:
647 680
      return FREE;
648 681
    case GLP_NS:
649 682
      return FIXED;
650 683
    default:
651 684
      LEMON_ASSERT(false, "Wrong row status");
652 685
      return GlpkLp::VarStatus();
... ...
@@ -774,159 +807,174 @@
774 807
        }
775 808
      }
776 809
    }
777 810
    return _dual_ray[i];
778 811
  }
779 812

	
780 813
  GlpkLp::ProblemType GlpkLp::_getPrimalType() const {
781 814
    if (glp_get_status(lp) == GLP_OPT)
782 815
      return OPTIMAL;
783 816
    switch (glp_get_prim_stat(lp)) {
784 817
    case GLP_UNDEF:
785 818
      return UNDEFINED;
786 819
    case GLP_FEAS:
787 820
    case GLP_INFEAS:
788 821
      if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
789 822
        return UNBOUNDED;
790 823
      } else {
791 824
        return UNDEFINED;
792 825
      }
793 826
    case GLP_NOFEAS:
794 827
      return INFEASIBLE;
795 828
    default:
796 829
      LEMON_ASSERT(false, "Wrong primal type");
797 830
      return  GlpkLp::ProblemType();
798 831
    }
799 832
  }
800 833

	
801 834
  GlpkLp::ProblemType GlpkLp::_getDualType() const {
802 835
    if (glp_get_status(lp) == GLP_OPT)
803 836
      return OPTIMAL;
804 837
    switch (glp_get_dual_stat(lp)) {
805 838
    case GLP_UNDEF:
806 839
      return UNDEFINED;
807 840
    case GLP_FEAS:
808 841
    case GLP_INFEAS:
809 842
      if (glp_get_prim_stat(lp) == GLP_NOFEAS) {
810 843
        return UNBOUNDED;
811 844
      } else {
812 845
        return UNDEFINED;
813 846
      }
814 847
    case GLP_NOFEAS:
815 848
      return INFEASIBLE;
816 849
    default:
817 850
      LEMON_ASSERT(false, "Wrong primal type");
818 851
      return  GlpkLp::ProblemType();
819 852
    }
820 853
  }
821 854

	
822
  void GlpkLp::presolver(bool b) {
823
    lpx_set_int_parm(lp, LPX_K_PRESOL, b ? 1 : 0);
855
  void GlpkLp::presolver(bool presolve) {
856
    _presolve = presolve;
824 857
  }
825 858

	
826 859
  void GlpkLp::messageLevel(MessageLevel m) {
827 860
    _message_level = m;
828 861
  }
829 862

	
830 863
  // GlpkMip members
831 864

	
832 865
  GlpkMip::GlpkMip()
833 866
    : LpBase(), MipSolver(), GlpkBase() {
834 867
    messageLevel(MESSAGE_NO_OUTPUT);
835 868
  }
836 869

	
837 870
  GlpkMip::GlpkMip(const GlpkMip& other)
838 871
    : LpBase(), MipSolver(), GlpkBase(other) {
839 872
    messageLevel(MESSAGE_NO_OUTPUT);
840 873
  }
841 874

	
842 875
  void GlpkMip::_setColType(int i, GlpkMip::ColTypes col_type) {
843 876
    switch (col_type) {
844 877
    case INTEGER:
845 878
      glp_set_col_kind(lp, i, GLP_IV);
846 879
      break;
847 880
    case REAL:
848 881
      glp_set_col_kind(lp, i, GLP_CV);
849 882
      break;
850 883
    }
851 884
  }
852 885

	
853 886
  GlpkMip::ColTypes GlpkMip::_getColType(int i) const {
854 887
    switch (glp_get_col_kind(lp, i)) {
855 888
    case GLP_IV:
856 889
    case GLP_BV:
857 890
      return INTEGER;
858 891
    default:
859 892
      return REAL;
860 893
    }
861 894

	
862 895
  }
863 896

	
864 897
  GlpkMip::SolveExitStatus GlpkMip::_solve() {
865 898
    glp_smcp smcp;
866 899
    glp_init_smcp(&smcp);
867 900

	
868 901
    switch (_message_level) {
869 902
    case MESSAGE_NO_OUTPUT:
870 903
      smcp.msg_lev = GLP_MSG_OFF;
871 904
      break;
872 905
    case MESSAGE_ERROR_MESSAGE:
873 906
      smcp.msg_lev = GLP_MSG_ERR;
874 907
      break;
875 908
    case MESSAGE_NORMAL_OUTPUT:
876 909
      smcp.msg_lev = GLP_MSG_ON;
877 910
      break;
878 911
    case MESSAGE_FULL_OUTPUT:
879 912
      smcp.msg_lev = GLP_MSG_ALL;
880 913
      break;
881 914
    }
882 915
    smcp.meth = GLP_DUAL;
883 916

	
884
    if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
917
    // If the basis is not valid we get an error return value.
918
    // In this case we can try to create a new basis.
919
    switch (glp_simplex(lp, &smcp)) {
920
    case 0:
921
      break;
922
    case GLP_EBADB:
923
    case GLP_ESING:
924
    case GLP_ECOND:
925
      lpx_set_int_parm(lp, LPX_K_MSGLEV, smcp.msg_lev);
926
      glp_adv_basis(lp, 0);
927
      if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
928
      break;
929
    default:
930
      return UNSOLVED;
931
    }
932

	
885 933
    if (glp_get_status(lp) != GLP_OPT) return SOLVED;
886 934

	
887 935
    glp_iocp iocp;
888 936
    glp_init_iocp(&iocp);
889 937

	
890 938
    switch (_message_level) {
891 939
    case MESSAGE_NO_OUTPUT:
892 940
      iocp.msg_lev = GLP_MSG_OFF;
893 941
      break;
894 942
    case MESSAGE_ERROR_MESSAGE:
895 943
      iocp.msg_lev = GLP_MSG_ERR;
896 944
      break;
897 945
    case MESSAGE_NORMAL_OUTPUT:
898 946
      iocp.msg_lev = GLP_MSG_ON;
899 947
      break;
900 948
    case MESSAGE_FULL_OUTPUT:
901 949
      iocp.msg_lev = GLP_MSG_ALL;
902 950
      break;
903 951
    }
904 952

	
905 953
    if (glp_intopt(lp, &iocp) != 0) return UNSOLVED;
906 954
    return SOLVED;
907 955
  }
908 956

	
909 957

	
910 958
  GlpkMip::ProblemType GlpkMip::_getType() const {
911 959
    switch (glp_get_status(lp)) {
912 960
    case GLP_OPT:
913 961
      switch (glp_mip_status(lp)) {
914 962
      case GLP_UNDEF:
915 963
        return UNDEFINED;
916 964
      case GLP_NOFEAS:
917 965
        return INFEASIBLE;
918 966
      case GLP_FEAS:
919 967
        return FEASIBLE;
920 968
      case GLP_OPT:
921 969
        return OPTIMAL;
922 970
      default:
923 971
        LEMON_ASSERT(false, "Wrong problem type.");
924 972
        return GlpkMip::ProblemType();
925 973
      }
926 974
    case GLP_NOFEAS:
927 975
      return INFEASIBLE;
928 976
    case GLP_INFEAS:
929 977
    case GLP_FEAS:
930 978
      if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
931 979
        return UNBOUNDED;
932 980
      } else {
Ignore white space 6 line context
... ...
@@ -133,102 +133,108 @@
133 133
  ///\ingroup lp_group
134 134
  class GlpkLp : public LpSolver, public GlpkBase {
135 135
  public:
136 136

	
137 137
    ///\e
138 138
    GlpkLp();
139 139
    ///\e
140 140
    GlpkLp(const GlpkLp&);
141 141

	
142 142
    ///\e
143 143
    virtual GlpkLp* cloneSolver() const;
144 144
    ///\e
145 145
    virtual GlpkLp* newSolver() const;
146 146

	
147 147
  private:
148 148

	
149 149
    mutable std::vector<double> _primal_ray;
150 150
    mutable std::vector<double> _dual_ray;
151 151

	
152 152
    void _clear_temporals();
153 153

	
154 154
  protected:
155 155

	
156 156
    virtual const char* _solverName() const;
157 157

	
158 158
    virtual SolveExitStatus _solve();
159 159
    virtual Value _getPrimal(int i) const;
160 160
    virtual Value _getDual(int i) const;
161 161

	
162 162
    virtual Value _getPrimalValue() const;
163 163

	
164 164
    virtual VarStatus _getColStatus(int i) const;
165 165
    virtual VarStatus _getRowStatus(int i) const;
166 166

	
167 167
    virtual Value _getPrimalRay(int i) const;
168 168
    virtual Value _getDualRay(int i) const;
169 169

	
170 170
    virtual ProblemType _getPrimalType() const;
171 171
    virtual ProblemType _getDualType() const;
172 172

	
173 173
  public:
174 174

	
175 175
    ///Solve with primal simplex
176 176
    SolveExitStatus solvePrimal();
177 177

	
178 178
    ///Solve with dual simplex
179 179
    SolveExitStatus solveDual();
180 180

	
181
  private:
182

	
183
    bool _presolve;
184

	
185
  public:
186

	
181 187
    ///Turns on or off the presolver
182 188

	
183 189
    ///Turns on (\c b is \c true) or off (\c b is \c false) the presolver
184 190
    ///
185 191
    ///The presolver is off by default.
186
    void presolver(bool b);
192
    void presolver(bool presolve);
187 193

	
188 194
    ///Enum for \c messageLevel() parameter
189 195
    enum MessageLevel {
190 196
      /// no output (default value)
191 197
      MESSAGE_NO_OUTPUT = 0,
192 198
      /// error messages only
193 199
      MESSAGE_ERROR_MESSAGE = 1,
194 200
      /// normal output
195 201
      MESSAGE_NORMAL_OUTPUT = 2,
196 202
      /// full output (includes informational messages)
197 203
      MESSAGE_FULL_OUTPUT = 3
198 204
    };
199 205

	
200 206
  private:
201 207

	
202 208
    MessageLevel _message_level;
203 209

	
204 210
  public:
205 211

	
206 212
    ///Set the verbosity of the messages
207 213

	
208 214
    ///Set the verbosity of the messages
209 215
    ///
210 216
    ///\param m is the level of the messages output by the solver routines.
211 217
    void messageLevel(MessageLevel m);
212 218
  };
213 219

	
214 220
  /// \brief Interface for the GLPK MIP solver
215 221
  ///
216 222
  /// This class implements an interface for the GLPK MIP solver.
217 223
  ///\ingroup lp_group
218 224
  class GlpkMip : public MipSolver, public GlpkBase {
219 225
  public:
220 226

	
221 227
    ///\e
222 228
    GlpkMip();
223 229
    ///\e
224 230
    GlpkMip(const GlpkMip&);
225 231

	
226 232
    virtual GlpkMip* cloneSolver() const;
227 233
    virtual GlpkMip* newSolver() const;
228 234

	
229 235
  protected:
230 236

	
231 237
    virtual const char* _solverName() const;
232 238

	
233 239
    virtual ColTypes _getColType(int col) const;
234 240
    virtual void _setColType(int col, ColTypes col_type);
0 comments (0 inline)