... |
... |
@@ -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 {
|