Skip to content

Commit a7033a1

Browse files
authored
Merge pull request #2671 from ERGO-Code/instantly-apply-implics
Apply implications when performing a bound change
2 parents 9accf88 + 66a5be3 commit a7033a1

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

highs/mip/HighsDomain.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2053,9 +2053,14 @@ void HighsDomain::changeBound(HighsDomainChange boundchg, Reason reason) {
20532053
domchgstack_.push_back(boundchg);
20542054
domchgreason_.push_back(reason);
20552055

2056-
if (binary && !infeasible_ && isFixed(boundchg.column))
2056+
if (binary && !infeasible_ && isFixed(boundchg.column)) {
20572057
mipsolver->mipdata_->cliquetable.addImplications(
20582058
*this, boundchg.column, col_lower_[boundchg.column] > 0.5);
2059+
if (!infeasible_) {
2060+
mipsolver->mipdata_->implications.applyImplications(
2061+
*this, boundchg.column, col_lower_[boundchg.column] > 0.5);
2062+
}
2063+
}
20592064
}
20602065

20612066
void HighsDomain::setDomainChangeStack(

highs/mip/HighsImplications.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,3 +829,44 @@ void HighsImplications::cleanupVub(HighsInt col, HighsInt vubCol,
829829
infeasible = mipsolver.mipdata_->domain.infeasible();
830830
}
831831
}
832+
833+
void HighsImplications::applyImplications(HighsDomain& domain,
834+
const HighsInt col,
835+
const HighsInt val) {
836+
assert(domain.isFixed(col));
837+
838+
auto checkImplication = [&](const HighsDomainChange& domchg) -> bool {
839+
assert(!domain.infeasible());
840+
if (domain.isFixed(domchg.column)) return false;
841+
const bool isint =
842+
domain.variableType(domchg.column) != HighsVarType::kContinuous;
843+
// Directly change bounds on all integer columns. Only change continuous
844+
// columns that fix the column, as changing their domains risks
845+
// suppressing further bound changes found in propagation, e.g.,
846+
// change [0, 100] -> [0, 50], propagation could tighten to [0, 48], but
847+
// such a tightening would not be applied due to min boundRange improvement.
848+
if (domchg.boundtype == HighsBoundType::kLower) {
849+
if ((!isint && domchg.boundval >
850+
domain.col_upper_[domchg.column] - domain.feastol()) ||
851+
(isint && domchg.boundval >
852+
domain.col_lower_[domchg.column] + domain.feastol())) {
853+
domain.changeBound(domchg, HighsDomain::Reason::cliqueTable(col, val));
854+
}
855+
} else {
856+
if ((!isint && domchg.boundval <
857+
domain.col_lower_[domchg.column] + domain.feastol()) ||
858+
(isint && domchg.boundval <
859+
domain.col_upper_[domchg.column] - domain.feastol())) {
860+
domain.changeBound(domchg, HighsDomain::Reason::cliqueTable(col, val));
861+
}
862+
}
863+
return domain.infeasible();
864+
};
865+
866+
HighsInt loc = 2 * col + val;
867+
if (implications[loc].computed) {
868+
for (HighsDomainChange& domchg : implications[loc].implics) {
869+
if (checkImplication(domchg)) break;
870+
}
871+
}
872+
}

highs/mip/HighsImplications.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ class HighsImplications {
179179
void cleanupVub(HighsInt col, HighsInt vubCol,
180180
HighsImplications::VarBound& vub, double ub, bool& redundant,
181181
bool& infeasible, bool allowBoundChanges = true) const;
182+
183+
void applyImplications(HighsDomain& domain, HighsInt col, HighsInt val);
182184
};
183185

184186
#endif

0 commit comments

Comments
 (0)