| 155 | } |
| 156 | |
| 157 | void getUnscaledInfeasibilities(const HighsOptions& options, |
| 158 | const HighsScale& scale, |
| 159 | const SimplexBasis& basis, |
| 160 | const HighsSimplexInfo& info, |
| 161 | HighsInfo& highs_info) { |
| 162 | const double primal_feasibility_tolerance = |
| 163 | options.primal_feasibility_tolerance; |
| 164 | const double dual_feasibility_tolerance = options.dual_feasibility_tolerance; |
| 165 | |
| 166 | HighsInt& num_primal_infeasibilities = highs_info.num_primal_infeasibilities; |
| 167 | double& max_primal_infeasibility = highs_info.max_primal_infeasibility; |
| 168 | double& sum_primal_infeasibilities = highs_info.sum_primal_infeasibilities; |
| 169 | HighsInt& num_dual_infeasibilities = highs_info.num_dual_infeasibilities; |
| 170 | double& max_dual_infeasibility = highs_info.max_dual_infeasibility; |
| 171 | double& sum_dual_infeasibilities = highs_info.sum_dual_infeasibilities; |
| 172 | |
| 173 | // Zero the counts of unscaled primal and dual infeasibilities |
| 174 | num_primal_infeasibilities = 0; |
| 175 | max_primal_infeasibility = 0; |
| 176 | sum_primal_infeasibilities = 0; |
| 177 | num_dual_infeasibilities = 0; |
| 178 | max_dual_infeasibility = 0; |
| 179 | sum_dual_infeasibilities = 0; |
| 180 | |
| 181 | double scale_mu = 1.0; |
| 182 | assert(int(scale.col.size()) == scale.num_col); |
| 183 | assert(int(scale.row.size()) == scale.num_row); |
| 184 | for (HighsInt iVar = 0; iVar < scale.num_col + scale.num_row; iVar++) { |
| 185 | // Look at the dual infeasibilities of nonbasic variables |
| 186 | if (basis.nonbasicFlag_[iVar] == kNonbasicFlagFalse) continue; |
| 187 | // No dual infeasibility for fixed rows and columns |
| 188 | if (info.workLower_[iVar] == info.workUpper_[iVar]) continue; |
| 189 | bool col = iVar < scale.num_col; |
| 190 | HighsInt iCol = 0; |
| 191 | HighsInt iRow = 0; |
| 192 | if (col) { |
| 193 | iCol = iVar; |
| 194 | assert(int(scale.col.size()) > iCol); |
| 195 | scale_mu = 1 / (scale.col[iCol] / scale.cost); |
| 196 | } else { |
| 197 | iRow = iVar - scale.num_col; |
| 198 | assert(int(scale.row.size()) > iRow); |
| 199 | scale_mu = scale.row[iRow] * scale.cost; |
| 200 | } |
| 201 | const double dual = info.workDual_[iVar]; |
| 202 | const double lower = info.workLower_[iVar]; |
| 203 | const double upper = info.workUpper_[iVar]; |
| 204 | const double unscaled_dual = dual * scale_mu; |
| 205 | |
| 206 | double dual_infeasibility; |
| 207 | if (highs_isInfinity(-lower) && highs_isInfinity(upper)) { |
| 208 | // Free: any nonzero dual value is infeasible |
| 209 | dual_infeasibility = fabs(unscaled_dual); |
| 210 | } else { |
| 211 | // Not fixed: any dual infeasibility is given by value signed by |
| 212 | // nonbasicMove. This assumes that nonbasicMove=0 for fixed |
| 213 | // variables |
| 214 | dual_infeasibility = -basis.nonbasicMove_[iVar] * unscaled_dual; |
no test coverage detected