Repository navigation
Conversation
…and logging a warning if presolve generates small matrix values, and logging (and returning) error if presolve creates lare matrix entries
…P) and HPresolve.cpp (for both LP and MIP)
…for both LPs and MIPs
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## latest #3578 +/- ##
==========================================
+ Coverage 75.67% 75.77% +0.10%
==========================================
Files 461 461
Lines 113794 114093 +299
Branches 17909 17939 +30
==========================================
+ Hits 86108 86454 +346
+ Misses 27398 27351 -47
Partials 288 288 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Opt-Mucca
left a comment
There was a problem hiding this comment.
The changes look good to me!
For MIP: Isn't any coefficient smaller than small_matrix_value after presolve coming from a reduction that we in theory should have blocked (the same for LP)? Or have I misunderstood the
double sum = Avalue[pos] + val;
if (std::abs(sum) <= options->small_matrix_value) {
unlink(pos);
}
block in addToMatrix @fwesselm ? I guess we're doing some reduction that is adding a new term to the matrix with value < small_matrix_value without checking it first?
I don't mind us deleting these values in the LP relaxation for MIP until we find a not-incredibly-extreme instance that is negatively affected by this. In general I'd also still like to lower the small_matrix_value further.
I thought it was almost certainly the case that explicit zero, duplicates and large values couldn't be created by presolve, but I didn't know what restrictions there were on creating small values. Instinct tells me that this small value is the result of an elimination operation, so a new nonzero hasn't been created. The instance is small, so it shouldn't be hard to identify how it's created
OK, at some calm moment we should lower 'small_matrix_value' and do a full test. Perhaps, as discussed, switching to maximum value scaling may be necessary to stop them from being scaled up - as can happen with the current equilibrium scaling (in simplex). |
Description
The assert triggered in #3564, drew my attention to the handling of explicit zeros, small values, duplicate values and large values in the constraint matrix after presolve.
What's happening currently
lpsolverinstance inHighsLpRelaxation. It sounds as if this may compromise what's returned to the MIP solver, since solutions feasible in the LP solver may have small infeasibilities in the MIP solver.lpsolverinstance inHighsLpRelaxation. However, any duplicate values in the constraint matrix after presolve would be present in the rest of the MIP solver. However, the evidence of the debug check for LPs suggests that they aren't created by presolve.Note that the return for the call
isn't being checked! Any duplicates or large values trigger a
HighsStatus::kErrorreturn, and the LP isn't loaded. Any explicit zeros or small values are removed and trigger aHighsStatus::kWarningreturn. Clearly it would be very noticeable if the LP isn't loaded and subsequent solves involve an empty model.What's happening with this PR
After LP or MIP presolve, and currently guarded by
cost bool kCheckReducedMatrixwhich is currentlyfalse,HighsSparsematrix::assessExtremeValuesis used to determine whether there are any explicit zeros, small values, or large values in the constraint matrix. Zeros or large values lead to the presolve status being set to a new valueHighsPresolveStatus::kMatrixValueError, resulting in failure of the solver. Small nonzero values are retained, but a warning message is logged, and a warning status is returned.HighsSparsematrix::assessStructureis a sanity check that the structure (including explicit zeros and duplicates) of the constraint matrix is fine - as it should meThis shouldn't lead to any more failures - since explicit zeros, duplicates and large values appear not to be generated by - but maybe a test should be done, but I felt it should be switched off until @Opt-Mucca and @fwesselm have considered it.
Other changes
highs/mip/HighsMipSolver.cpp, as well as handling the newHighsPresolveStatus::kMatrixValueError, I've added code to handle exception or memory allocation errors in presolve that should have been added previously.assessMatrixhad been tightened up for the case when a partitioned matrix is passedWhat's not been done
Small nonzero values from presolve are still being zeroed when passing the presolved model to the
lpsolverinstance inHighsLpRelaxation. If you want the small values from presolve to be used when solving LP relaxations, thesmall_valueoption will have to be reduced. There's a clear trade-off between losing precision from presolve, and increasing the risk of numerical issues in the simplex solve.However, as it stands, all this PR does is fix #3564
Checklist
latestbranchRelated issue
Closes #3564