| 434 | } |
| 435 | |
| 436 | void HEkkDualRHS::createInfeasList(double columnDensity) { |
| 437 | HighsInt numRow = ekk_instance_.lp_.num_row_; |
| 438 | double* dwork = ekk_instance_.scattered_dual_edge_weight_.data(); |
| 439 | |
| 440 | // 1. Build the full list |
| 441 | fill_n(workMark.data(), numRow, 0); |
| 442 | workCount = 0; |
| 443 | workCutoff = 0; |
| 444 | for (HighsInt iRow = 0; iRow < numRow; iRow++) { |
| 445 | if (work_infeasibility[iRow]) { |
| 446 | workMark[iRow] = 1; |
| 447 | workIndex[workCount++] = iRow; |
| 448 | } |
| 449 | } |
| 450 | |
| 451 | // 2. See if it worth to try to go sparse |
| 452 | // (Many candidates, really sparse RHS) |
| 453 | std::vector<double>& edge_weight = ekk_instance_.dual_edge_weight_; |
| 454 | if (workCount > max(numRow * 0.01, 500.0) && columnDensity < 0.05) { |
| 455 | HighsInt icutoff = max(workCount * 0.001, 500.0); |
| 456 | double maxMerit = 0; |
| 457 | for (HighsInt iRow = 0, iPut = 0; iRow < numRow; iRow++) |
| 458 | if (workMark[iRow]) { |
| 459 | double myMerit = work_infeasibility[iRow] / edge_weight[iRow]; |
| 460 | if (maxMerit < myMerit) maxMerit = myMerit; |
| 461 | dwork[iPut++] = -myMerit; |
| 462 | } |
| 463 | nth_element(dwork, dwork + icutoff, dwork + workCount); |
| 464 | double cutMerit = -dwork[icutoff]; |
| 465 | workCutoff = min(maxMerit * 0.99999, cutMerit * 1.00001); |
| 466 | |
| 467 | // Create again |
| 468 | fill_n(workMark.data(), numRow, 0); |
| 469 | workCount = 0; |
| 470 | for (HighsInt iRow = 0; iRow < numRow; iRow++) { |
| 471 | if (work_infeasibility[iRow] >= edge_weight[iRow] * workCutoff) { |
| 472 | workIndex[workCount++] = iRow; |
| 473 | workMark[iRow] = 1; |
| 474 | } |
| 475 | } |
| 476 | |
| 477 | // Reduce by drop smaller |
| 478 | if (workCount > icutoff * 1.5) { |
| 479 | // Firstly take up "icutoff" number of elements |
| 480 | HighsInt fullCount = workCount; |
| 481 | workCount = icutoff; |
| 482 | for (HighsInt i = icutoff; i < fullCount; i++) { |
| 483 | HighsInt iRow = workIndex[i]; |
| 484 | if (work_infeasibility[iRow] > edge_weight[iRow] * cutMerit) { |
| 485 | workIndex[workCount++] = iRow; |
| 486 | } else { |
| 487 | workMark[iRow] = 0; |
| 488 | } |
| 489 | } |
| 490 | } |
| 491 | } |
| 492 | |
| 493 | // 3. If there are still too many candidates: disable them |
no test coverage detected