| ... |
... |
@@ -440,261 +440,294 @@
|
| 440 |
440 |
break;
|
| 441 |
441 |
case GLP_LO:
|
| 442 |
442 |
case GLP_DB:
|
| 443 |
443 |
case GLP_FX:
|
| 444 |
444 |
if (lo == up)
|
| 445 |
445 |
glp_set_row_bnds(lp, i, GLP_FX, lo, up);
|
| 446 |
446 |
else
|
| 447 |
447 |
glp_set_row_bnds(lp, i, GLP_DB, lo, up);
|
| 448 |
448 |
break;
|
| 449 |
449 |
default:
|
| 450 |
450 |
break;
|
| 451 |
451 |
}
|
| 452 |
452 |
}
|
| 453 |
453 |
}
|
| 454 |
454 |
|
| 455 |
455 |
GlpkBase::Value GlpkBase::_getRowUpperBound(int i) const {
|
| 456 |
456 |
int b = glp_get_row_type(lp, i);
|
| 457 |
457 |
switch (b) {
|
| 458 |
458 |
case GLP_UP:
|
| 459 |
459 |
case GLP_DB:
|
| 460 |
460 |
case GLP_FX:
|
| 461 |
461 |
return glp_get_row_ub(lp, i);
|
| 462 |
462 |
default:
|
| 463 |
463 |
return INF;
|
| 464 |
464 |
}
|
| 465 |
465 |
}
|
| 466 |
466 |
|
| 467 |
467 |
void GlpkBase::_setObjCoeffs(ExprIterator b, ExprIterator e) {
|
| 468 |
468 |
for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
|
| 469 |
469 |
glp_set_obj_coef(lp, i, 0.0);
|
| 470 |
470 |
}
|
| 471 |
471 |
for (ExprIterator it = b; it != e; ++it) {
|
| 472 |
472 |
glp_set_obj_coef(lp, it->first, it->second);
|
| 473 |
473 |
}
|
| 474 |
474 |
}
|
| 475 |
475 |
|
| 476 |
476 |
void GlpkBase::_getObjCoeffs(InsertIterator b) const {
|
| 477 |
477 |
for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
|
| 478 |
478 |
Value val = glp_get_obj_coef(lp, i);
|
| 479 |
479 |
if (val != 0.0) {
|
| 480 |
480 |
*b = std::make_pair(i, val);
|
| 481 |
481 |
++b;
|
| 482 |
482 |
}
|
| 483 |
483 |
}
|
| 484 |
484 |
}
|
| 485 |
485 |
|
| 486 |
486 |
void GlpkBase::_setObjCoeff(int i, Value obj_coef) {
|
| 487 |
487 |
//i = 0 means the constant term (shift)
|
| 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();
|
| 653 |
686 |
}
|
| 654 |
687 |
}
|
| 655 |
688 |
|
| 656 |
689 |
GlpkLp::Value GlpkLp::_getPrimalRay(int i) const {
|
| 657 |
690 |
if (_primal_ray.empty()) {
|
| 658 |
691 |
int row_num = glp_get_num_rows(lp);
|
| 659 |
692 |
int col_num = glp_get_num_cols(lp);
|
| 660 |
693 |
|
| 661 |
694 |
_primal_ray.resize(col_num + 1, 0.0);
|
| 662 |
695 |
|
| 663 |
696 |
int index = glp_get_unbnd_ray(lp);
|
| 664 |
697 |
if (index != 0) {
|
| 665 |
698 |
// The primal ray is found in primal simplex second phase
|
| 666 |
699 |
LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
|
| 667 |
700 |
glp_get_col_stat(lp, index - row_num)) != GLP_BS,
|
| 668 |
701 |
"Wrong primal ray");
|
| 669 |
702 |
|
| 670 |
703 |
bool negate = glp_get_obj_dir(lp) == GLP_MAX;
|
| 671 |
704 |
|
| 672 |
705 |
if (index > row_num) {
|
| 673 |
706 |
_primal_ray[index - row_num] = 1.0;
|
| 674 |
707 |
if (glp_get_col_dual(lp, index - row_num) > 0) {
|
| 675 |
708 |
negate = !negate;
|
| 676 |
709 |
}
|
| 677 |
710 |
} else {
|
| 678 |
711 |
if (glp_get_row_dual(lp, index) > 0) {
|
| 679 |
712 |
negate = !negate;
|
| 680 |
713 |
}
|
| 681 |
714 |
}
|
| 682 |
715 |
|
| 683 |
716 |
std::vector<int> ray_indexes(row_num + 1);
|
| 684 |
717 |
std::vector<Value> ray_values(row_num + 1);
|
| 685 |
718 |
int ray_length = glp_eval_tab_col(lp, index, &ray_indexes.front(),
|
| 686 |
719 |
&ray_values.front());
|
| 687 |
720 |
|
| 688 |
721 |
for (int i = 1; i <= ray_length; ++i) {
|
| 689 |
722 |
if (ray_indexes[i] > row_num) {
|
| 690 |
723 |
_primal_ray[ray_indexes[i] - row_num] = ray_values[i];
|
| 691 |
724 |
}
|
| 692 |
725 |
}
|
| 693 |
726 |
|
| 694 |
727 |
if (negate) {
|
| 695 |
728 |
for (int i = 1; i <= col_num; ++i) {
|
| 696 |
729 |
_primal_ray[i] = - _primal_ray[i];
|
| 697 |
730 |
}
|
| 698 |
731 |
}
|
| 699 |
732 |
} else {
|
| 700 |
733 |
for (int i = 1; i <= col_num; ++i) {
|
| ... |
... |
@@ -726,233 +759,248 @@
|
| 726 |
759 |
idx = glp_get_col_bind(lp, index - row_num);
|
| 727 |
760 |
if (glp_get_col_prim(lp, index - row_num) >
|
| 728 |
761 |
glp_get_col_ub(lp, index - row_num)) {
|
| 729 |
762 |
negate = true;
|
| 730 |
763 |
}
|
| 731 |
764 |
} else {
|
| 732 |
765 |
idx = glp_get_row_bind(lp, index);
|
| 733 |
766 |
if (glp_get_row_prim(lp, index) > glp_get_row_ub(lp, index)) {
|
| 734 |
767 |
negate = true;
|
| 735 |
768 |
}
|
| 736 |
769 |
}
|
| 737 |
770 |
|
| 738 |
771 |
_dual_ray[idx] = negate ? - 1.0 : 1.0;
|
| 739 |
772 |
|
| 740 |
773 |
glp_btran(lp, &_dual_ray.front());
|
| 741 |
774 |
} else {
|
| 742 |
775 |
double eps = 1e-7;
|
| 743 |
776 |
// The dual ray is found in primal simplex first phase
|
| 744 |
777 |
// We assume that the glpk minimizes the slack to get feasible solution
|
| 745 |
778 |
for (int i = 1; i <= row_num; ++i) {
|
| 746 |
779 |
int index = glp_get_bhead(lp, i);
|
| 747 |
780 |
if (index <= row_num) {
|
| 748 |
781 |
double res = glp_get_row_prim(lp, index);
|
| 749 |
782 |
if (res > glp_get_row_ub(lp, index) + eps) {
|
| 750 |
783 |
_dual_ray[i] = -1;
|
| 751 |
784 |
} else if (res < glp_get_row_lb(lp, index) - eps) {
|
| 752 |
785 |
_dual_ray[i] = 1;
|
| 753 |
786 |
} else {
|
| 754 |
787 |
_dual_ray[i] = 0;
|
| 755 |
788 |
}
|
| 756 |
789 |
_dual_ray[i] *= glp_get_rii(lp, index);
|
| 757 |
790 |
} else {
|
| 758 |
791 |
double res = glp_get_col_prim(lp, index - row_num);
|
| 759 |
792 |
if (res > glp_get_col_ub(lp, index - row_num) + eps) {
|
| 760 |
793 |
_dual_ray[i] = -1;
|
| 761 |
794 |
} else if (res < glp_get_col_lb(lp, index - row_num) - eps) {
|
| 762 |
795 |
_dual_ray[i] = 1;
|
| 763 |
796 |
} else {
|
| 764 |
797 |
_dual_ray[i] = 0;
|
| 765 |
798 |
}
|
| 766 |
799 |
_dual_ray[i] /= glp_get_sjj(lp, index - row_num);
|
| 767 |
800 |
}
|
| 768 |
801 |
}
|
| 769 |
802 |
|
| 770 |
803 |
glp_btran(lp, &_dual_ray.front());
|
| 771 |
804 |
|
| 772 |
805 |
for (int i = 1; i <= row_num; ++i) {
|
| 773 |
806 |
_dual_ray[i] /= glp_get_rii(lp, i);
|
| 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 {
|
| 933 |
981 |
return UNDEFINED;
|
| 934 |
982 |
}
|
| 935 |
983 |
default:
|
| 936 |
984 |
LEMON_ASSERT(false, "Wrong problem type.");
|
| 937 |
985 |
return GlpkMip::ProblemType();
|
| 938 |
986 |
}
|
| 939 |
987 |
}
|
| 940 |
988 |
|
| 941 |
989 |
GlpkMip::Value GlpkMip::_getSol(int i) const {
|
| 942 |
990 |
return glp_mip_col_val(lp, i);
|
| 943 |
991 |
}
|
| 944 |
992 |
|
| 945 |
993 |
GlpkMip::Value GlpkMip::_getSolValue() const {
|
| 946 |
994 |
return glp_mip_obj_val(lp);
|
| 947 |
995 |
}
|
| 948 |
996 |
|
| 949 |
997 |
GlpkMip* GlpkMip::newSolver() const { return new GlpkMip; }
|
| 950 |
998 |
GlpkMip* GlpkMip::cloneSolver() const {return new GlpkMip(*this); }
|
| 951 |
999 |
|
| 952 |
1000 |
const char* GlpkMip::_solverName() const { return "GlpkMip"; }
|
| 953 |
1001 |
|
| 954 |
1002 |
void GlpkMip::messageLevel(MessageLevel m) {
|
| 955 |
1003 |
_message_level = m;
|
| 956 |
1004 |
}
|
| 957 |
1005 |
|
| 958 |
1006 |
} //END OF NAMESPACE LEMON
|