| 2849 | } |
| 2850 | |
| 2851 | double HEkkDual::computeExactDualObjectiveValue(HVector& dual_col, |
| 2852 | HVector& dual_row) { |
| 2853 | const HighsLp& lp = ekk_instance_.lp_; |
| 2854 | const SimplexBasis& basis = ekk_instance_.basis_; |
| 2855 | const HighsSimplexInfo& info = ekk_instance_.info_; |
| 2856 | // Create a local buffer for the pi vector |
| 2857 | dual_col.setup(lp.num_row_); |
| 2858 | dual_col.clear(); |
| 2859 | for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) { |
| 2860 | HighsInt iVar = basis.basicIndex_[iRow]; |
| 2861 | if (iVar < lp.num_col_) { |
| 2862 | const double value = lp.col_cost_[iVar]; |
| 2863 | if (value) { |
| 2864 | dual_col.array[iRow] = value; |
| 2865 | dual_col.index[dual_col.count++] = iRow; |
| 2866 | } |
| 2867 | } |
| 2868 | } |
| 2869 | // Create a local buffer for the dual vector |
| 2870 | const HighsInt numTot = lp.num_col_ + lp.num_row_; |
| 2871 | dual_row.setup(lp.num_col_); |
| 2872 | dual_row.clear(); |
| 2873 | if (dual_col.count) { |
| 2874 | const bool quad_precision = false; |
| 2875 | const double expected_density = 1; |
| 2876 | simplex_nla->btran(dual_col, expected_density); |
| 2877 | lp.a_matrix_.priceByColumn(quad_precision, dual_row, dual_col); |
| 2878 | } |
| 2879 | // Compute dual infeasibilities |
| 2880 | ekk_instance_.computeSimplexDualInfeasible(); |
| 2881 | if (info.num_dual_infeasibilities > 0) |
| 2882 | highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kInfo, |
| 2883 | "When computing exact dual objective, the unperturbed costs " |
| 2884 | "yield num / max / sum dual " |
| 2885 | "infeasibilities = %d / %g / %g\n", |
| 2886 | (int)info.num_dual_infeasibilities, info.max_dual_infeasibility, |
| 2887 | info.sum_dual_infeasibilities); |
| 2888 | HighsCDouble dual_objective = lp.offset_; |
| 2889 | double norm_dual = 0; |
| 2890 | double norm_delta_dual = 0; |
| 2891 | for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) { |
| 2892 | if (!basis.nonbasicFlag_[iCol]) continue; |
| 2893 | double exact_dual = lp.col_cost_[iCol] - dual_row.array[iCol]; |
| 2894 | // The active value must be decided based on the exact dual. For a nonbasic |
| 2895 | // column the bound that must be used may flip due to cost perturbation |
| 2896 | // flipping the sign of its dual and for a basic variable we may need to add |
| 2897 | // to the dual objective using one of the bounds when its dual is not zero. |
| 2898 | double active_value; |
| 2899 | if (exact_dual > ekk_instance_.options_->small_matrix_value) |
| 2900 | active_value = lp.col_lower_[iCol]; |
| 2901 | else if (exact_dual < -ekk_instance_.options_->small_matrix_value) |
| 2902 | active_value = lp.col_upper_[iCol]; |
| 2903 | else |
| 2904 | active_value = info.workValue_[iCol]; |
| 2905 | |
| 2906 | // when the active value is infinite the dual objective lower bound is |
| 2907 | // -infinity |
| 2908 | if (highs_isInfinity(fabs(active_value))) return -kHighsInf; |
nothing calls this directly
no test coverage detected