| 315 | } |
| 316 | |
| 317 | bool HEkkDualRow::chooseFinalWorkGroupQuad() { |
| 318 | const double Td = ekk_instance_.options_->dual_feasibility_tolerance; |
| 319 | HighsInt fullCount = workCount; |
| 320 | workCount = 0; |
| 321 | double totalChange = kInitialTotalChange; |
| 322 | double selectTheta = workTheta; |
| 323 | const double totalDelta = fabs(workDelta); |
| 324 | workGroup.clear(); |
| 325 | workGroup.push_back(0); |
| 326 | HighsInt prev_workCount = workCount; |
| 327 | double prev_remainTheta = kInitialRemainTheta; |
| 328 | double prev_selectTheta = selectTheta; |
| 329 | |
| 330 | while (selectTheta < kMaxSelectTheta) { |
| 331 | double remainTheta = kInitialRemainTheta; |
| 332 | for (HighsInt i = workCount; i < fullCount; i++) { |
| 333 | HighsInt iCol = workData[i].first; |
| 334 | double value = workData[i].second; |
| 335 | double dual = workMove[iCol] * workDual[iCol]; |
| 336 | // Tight satisfy |
| 337 | if (dual <= selectTheta * value) { |
| 338 | swap(workData[workCount++], workData[i]); |
| 339 | totalChange += value * (workRange[iCol]); |
| 340 | } else if (dual + Td < remainTheta * value) { |
| 341 | remainTheta = (dual + Td) / value; |
| 342 | } |
| 343 | } |
| 344 | workGroup.push_back(workCount); |
| 345 | |
| 346 | // Update selectTheta with the value of remainTheta; |
| 347 | selectTheta = remainTheta; |
| 348 | // Check for no change in this loop - to prevent infinite loop |
| 349 | if ((workCount == prev_workCount) && (prev_selectTheta == selectTheta) && |
| 350 | (prev_remainTheta == remainTheta)) { |
| 351 | HighsInt num_var = |
| 352 | ekk_instance_.lp_.num_col_ + ekk_instance_.lp_.num_row_; |
| 353 | debugDualChuzcFailQuad0(*ekk_instance_.options_, workCount, workData, |
| 354 | num_var, workDual, selectTheta, remainTheta, |
| 355 | true); |
| 356 | return false; |
| 357 | } |
| 358 | // Record the initial values of workCount, remainTheta and selectTheta for |
| 359 | // the next pass through the loop - to check for infinite loop condition |
| 360 | prev_workCount = workCount; |
| 361 | prev_remainTheta = remainTheta; |
| 362 | prev_selectTheta = selectTheta; |
| 363 | if (totalChange >= totalDelta || workCount == fullCount) break; |
| 364 | } |
| 365 | // Check that at least one group has been identified |
| 366 | if ((HighsInt)workGroup.size() <= 1) { |
| 367 | HighsInt num_var = ekk_instance_.lp_.num_col_ + ekk_instance_.lp_.num_row_; |
| 368 | debugDualChuzcFailQuad1(*ekk_instance_.options_, workCount, workData, |
| 369 | num_var, workDual, selectTheta, true); |
| 370 | return false; |
| 371 | } |
| 372 | return true; |
| 373 | } |
| 374 |
nothing calls this directly
no test coverage detected