| 431 | } |
| 432 | |
| 433 | bool HEkkDualRow::chooseFinalWorkGroupHeap() { |
| 434 | const double Td = ekk_instance_.options_->dual_feasibility_tolerance; |
| 435 | HighsInt fullCount = alt_workCount; |
| 436 | double totalChange = kInitialTotalChange; |
| 437 | double selectTheta = workTheta; |
| 438 | const double totalDelta = fabs(workDelta); |
| 439 | HighsInt heap_num_en = 0; |
| 440 | std::vector<HighsInt> heap_i; |
| 441 | std::vector<double> heap_v; |
| 442 | heap_i.resize(fullCount + 1); |
| 443 | heap_v.resize(fullCount + 1); |
| 444 | for (HighsInt i = 0; i < fullCount; i++) { |
| 445 | HighsInt iCol = original_workData[i].first; |
| 446 | double value = original_workData[i].second; |
| 447 | double dual = workMove[iCol] * workDual[iCol]; |
| 448 | double ratio = dual / value; |
| 449 | if (ratio < kMaxSelectTheta) { |
| 450 | heap_num_en++; |
| 451 | heap_i[heap_num_en] = i; |
| 452 | heap_v[heap_num_en] = ratio; |
| 453 | } |
| 454 | } |
| 455 | maxheapsort(heap_v.data(), heap_i.data(), heap_num_en); |
| 456 | |
| 457 | alt_workCount = 0; |
| 458 | alt_workGroup.clear(); |
| 459 | alt_workGroup.push_back(alt_workCount); |
| 460 | if (heap_num_en <= 0) { |
| 461 | HighsInt num_var = ekk_instance_.lp_.num_col_ + ekk_instance_.lp_.num_row_; |
| 462 | // No entries in heap = > failure |
| 463 | debugDualChuzcFailHeap(*ekk_instance_.options_, alt_workCount, |
| 464 | original_workData, num_var, workDual, selectTheta, |
| 465 | true); |
| 466 | return false; |
| 467 | } |
| 468 | HighsInt this_group_first_entry = alt_workCount; |
| 469 | sorted_workData.resize(heap_num_en); |
| 470 | for (HighsInt en = 1; en <= heap_num_en; en++) { |
| 471 | HighsInt i = heap_i[en]; |
| 472 | HighsInt iCol = original_workData[i].first; |
| 473 | double value = original_workData[i].second; |
| 474 | double dual = workMove[iCol] * workDual[iCol]; |
| 475 | if (dual > selectTheta * value) { |
| 476 | // Breakpoint is in the next group, so record the pointer to its |
| 477 | // first entry |
| 478 | alt_workGroup.push_back(alt_workCount); |
| 479 | this_group_first_entry = alt_workCount; |
| 480 | selectTheta = (dual + Td) / value; |
| 481 | // End loop if all permitted groups have been identified |
| 482 | if (totalChange >= totalDelta) break; |
| 483 | } |
| 484 | // Store the breakpoint |
| 485 | sorted_workData[alt_workCount].first = iCol; |
| 486 | sorted_workData[alt_workCount].second = value; |
| 487 | totalChange += value * (workRange[iCol]); |
| 488 | alt_workCount++; |
| 489 | } |
| 490 | if (alt_workCount > this_group_first_entry) |
nothing calls this directly
no test coverage detected