Skip to content

Commit d8ff906

Browse files
authored
Merge pull request ERGO-Code#2337 from ERGO-Code/fix-2322
Add max scale factor for generated inequalities
2 parents 69f3c04 + 5c1a0d8 commit d8ff906

File tree

4 files changed

+31
-22
lines changed

4 files changed

+31
-22
lines changed

FEATURES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ Corrected docstrings for `Highs_getReducedRow`, motivated by [#2312](https://git
2222

2323
LP file reader no longer fails when there is no objective section. Fix is [#2316](https://github.com/ERGO-Code/HiGHS/pull/2316)), but this exposes code quality issue [#2318](https://github.com/ERGO-Code/HiGHS/issues/2318))
2424

25-
25+
Added a max scale factor (+1024) when scaling up coefficients in `preprocessBaseInequality` and `postprocessCut`. Fix is [#2337](https://github.com/ERGO-Code/HiGHS/pull/2337).
2626

highs/mip/HighsCutGeneration.cpp

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,25 @@ bool HighsCutGeneration::cmirCutGenerationHeuristic(double minEfficacy,
736736
return true;
737737
}
738738

739+
double HighsCutGeneration::scale(double val) {
740+
int expshift = 0;
741+
std::frexp(val, &expshift);
742+
expshift = -expshift;
743+
744+
// Don't scale the coefficients by more than +1024 (violations can increase)
745+
expshift = std::min(10, expshift);
746+
747+
// Scale rhs
748+
rhs = ldexp(rhs, expshift);
749+
750+
// Scale row
751+
for (HighsInt i = 0; i != rowlen; ++i)
752+
vals[i] = std::ldexp(vals[i], expshift);
753+
754+
// Return scaling factor
755+
return std::ldexp(1.0, expshift);
756+
}
757+
739758
bool HighsCutGeneration::postprocessCut() {
740759
// right hand sides slightly below zero are likely due to numerical errors and
741760
// can cause numerical troubles with scaling, so set them to zero
@@ -800,6 +819,8 @@ bool HighsCutGeneration::postprocessCut() {
800819
}
801820
}
802821

822+
if (rowlen == 0) return false;
823+
803824
if (integralSupport) {
804825
// integral support -> determine scale to make all coefficients integral
805826
double intscale =
@@ -865,25 +886,12 @@ bool HighsCutGeneration::postprocessCut() {
865886
for (HighsInt i = 0; i != rowlen; ++i)
866887
minAbsValue = std::min(std::abs(vals[i]), minAbsValue);
867888

868-
int expshift;
869-
std::frexp(minAbsValue - epsilon, &expshift);
870-
expshift = -expshift;
871-
872-
rhs = std::ldexp((double)rhs, expshift);
873-
874-
for (HighsInt i = 0; i != rowlen; ++i)
875-
vals[i] = std::ldexp(vals[i], expshift);
889+
scale(minAbsValue - epsilon);
876890
}
877891
} else {
878892
// the support is not integral, scale cut to have the largest coefficient
879893
// around 1.0
880-
int expshift;
881-
std::frexp(maxAbsValue - epsilon, &expshift);
882-
expshift = -expshift;
883-
rhs = std::ldexp((double)rhs, expshift);
884-
885-
for (HighsInt i = 0; i != rowlen; ++i)
886-
vals[i] = std::ldexp(vals[i], expshift);
894+
scale(maxAbsValue - epsilon);
887895
}
888896

889897
return true;
@@ -911,12 +919,7 @@ bool HighsCutGeneration::preprocessBaseInequality(bool& hasUnboundedInts,
911919
for (HighsInt i = 0; i < rowlen; ++i)
912920
maxAbsVal = std::max(std::abs(vals[i]), maxAbsVal);
913921

914-
int expshift = 0;
915-
std::frexp(maxAbsVal, &expshift);
916-
expshift = -expshift;
917-
initialScale = std::ldexp(1.0, expshift);
918-
rhs *= initialScale;
919-
for (HighsInt i = 0; i < rowlen; ++i) vals[i] = std::ldexp(vals[i], expshift);
922+
initialScale = scale(maxAbsVal);
920923

921924
isintegral.resize(rowlen);
922925
for (HighsInt i = 0; i != rowlen; ++i) {

highs/mip/HighsCutGeneration.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class HighsCutGeneration {
6565
bool cmirCutGenerationHeuristic(double minEfficacy,
6666
bool onlyInitialCMIRScale = false);
6767

68+
double scale(double val);
69+
6870
bool postprocessCut();
6971

7072
bool preprocessBaseInequality(bool& hasUnboundedInts, bool& hasGeneralInts,

highs/util/HighsCDouble.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ class HighsCDouble {
314314
}
315315

316316
friend HighsCDouble round(const HighsCDouble& x) { return floor(x + 0.5); }
317+
318+
friend HighsCDouble ldexp(const HighsCDouble& v, int exp) {
319+
return HighsCDouble(std::ldexp(v.hi, exp), std::ldexp(v.lo, exp));
320+
}
317321
};
318322

319323
#endif

0 commit comments

Comments
 (0)