| 755 | } |
| 756 | |
| 757 | HighsStatus HEkk::undualize() { |
| 758 | if (!this->status_.is_dualized) return HighsStatus::kOk; |
| 759 | HighsInt dual_num_col = lp_.num_col_; |
| 760 | HighsInt primal_num_tot = original_num_col_ + original_num_row_; |
| 761 | // These two aren't used (yet) |
| 762 | // vector<double>& dual_work_dual = info_.workDual_; |
| 763 | // vector<double>& primal_work_value = info_.workValue_; |
| 764 | // Take copies of the nonbasic information for the dual LP, since |
| 765 | // its values will be over-written in constructing the corresponding |
| 766 | // data for the primal problem |
| 767 | vector<int8_t> dual_nonbasic_flag = basis_.nonbasicFlag_; |
| 768 | vector<int8_t> dual_nonbasic_move = basis_.nonbasicMove_; |
| 769 | vector<HighsInt>& primal_basic_index = basis_.basicIndex_; |
| 770 | vector<int8_t>& primal_nonbasic_flag = basis_.nonbasicFlag_; |
| 771 | vector<int8_t>& primal_nonbasic_move = basis_.nonbasicMove_; |
| 772 | basis_.nonbasicFlag_.assign(primal_num_tot, kIllegalFlagValue); |
| 773 | basis_.nonbasicMove_.assign(primal_num_tot, kIllegalMoveValue); |
| 774 | basis_.basicIndex_.resize(0); |
| 775 | // The number of dual rows is the number of primal columns, so all |
| 776 | // dual basic variables are nonbasic in the primal problem. |
| 777 | // |
| 778 | // If there are extra dual columns due to upper bounds on boxed |
| 779 | // primal variables/constraints, there will be an excess of dual |
| 780 | // nonbasic variables for the required primal basic variables. |
| 781 | // |
| 782 | // For each pair of dual variables associated with a boxed primal |
| 783 | // variable/constraint: |
| 784 | // |
| 785 | // * If one is basic then it yields a nonbasic primal variable, at |
| 786 | // a bound given by the basic dual |
| 787 | // |
| 788 | // * If both are nonbasic, then they yield a basic primal variable |
| 789 | // |
| 790 | // Keep track of the dual column added to handle upper bounds on |
| 791 | // boxed variables/constraints |
| 792 | HighsInt upper_bound_col = original_num_row_; |
| 793 | for (HighsInt iCol = 0; iCol < original_num_col_; iCol++) { |
| 794 | const double lower = original_col_lower_[iCol]; |
| 795 | const double upper = original_col_upper_[iCol]; |
| 796 | int8_t move = kIllegalMoveValue; |
| 797 | HighsInt dual_variable = dual_num_col + iCol; |
| 798 | bool dual_basic = dual_nonbasic_flag[dual_variable] == kNonbasicFlagFalse; |
| 799 | if (lower == upper) { |
| 800 | // Fixed |
| 801 | if (dual_basic) move = kNonbasicMoveZe; |
| 802 | } else if (!highs_isInfinity(-lower)) { |
| 803 | // Finite lower bound so boxed or lower |
| 804 | if (!highs_isInfinity(upper)) { |
| 805 | // Finite upper bound so boxed |
| 806 | if (dual_basic) { |
| 807 | // Primal variable is nonbasic at its lower bound |
| 808 | move = kNonbasicMoveUp; |
| 809 | } else { |
| 810 | // Look at the corresponding dual variable for the upper bound |
| 811 | dual_variable = upper_bound_col; |
| 812 | dual_basic = dual_nonbasic_flag[dual_variable] == kNonbasicFlagFalse; |
| 813 | if (dual_basic) { |
| 814 | // Primal variable is nonbasic at its upper bound |
no test coverage detected