diff --git a/highs/mip/HighsCliqueTable.cpp b/highs/mip/HighsCliqueTable.cpp index bc10beaa4ad..2edf934ae5f 100644 --- a/highs/mip/HighsCliqueTable.cpp +++ b/highs/mip/HighsCliqueTable.cpp @@ -861,7 +861,7 @@ void HighsCliqueTable::extractCliques( for (HighsInt i = 0; i != nbin; ++i) { HighsInt bincol = inds[perm[i]]; HighsCDouble impliedub = HighsCDouble(rhs) - vals[perm[i]]; - if (implics.getNumVarBounds() >= implics.getMaxVarBounds()) break; + if (implics.tooManyVarBounds()) break; for (HighsInt j = nbin; j != ntotal; ++j) { HighsInt col = inds[perm[j]]; if (globaldom.isFixed(col)) continue; diff --git a/highs/mip/HighsImplications.cpp b/highs/mip/HighsImplications.cpp index 75e5d3abf80..405d579651b 100644 --- a/highs/mip/HighsImplications.cpp +++ b/highs/mip/HighsImplications.cpp @@ -395,7 +395,7 @@ void HighsImplications::addVUB(HighsInt col, HighsInt vubcol, double vubcoef, // assume that VUBs do not have infinite coefficients and infinite constant // terms since such VUBs effectively evaluate to NaN. assert(std::abs(vubcoef) != kHighsInf || std::abs(vubconstant) != kHighsInf); - if (numVarBounds >= maxVarBounds) return; + if (tooManyVarBounds()) return; VarBound vub{vubcoef, vubconstant}; @@ -424,7 +424,7 @@ void HighsImplications::addVLB(HighsInt col, HighsInt vlbcol, double vlbcoef, // assume that VLBs do not have infinite coefficients and infinite constant // terms since such VLBs effectively evaluate to NaN. assert(std::abs(vlbcoef) != kHighsInf || std::abs(vlbconstant) != kHighsInf); - if (numVarBounds >= maxVarBounds) return; + if (tooManyVarBounds()) return; VarBound vlb{vlbcoef, vlbconstant}; @@ -732,13 +732,9 @@ void HighsImplications::cleanupVarbounds(HighsInt col) { if (infeasible) return; }); - if (!delVbds.empty()) { - for (HighsInt vubCol : delVbds) { - vubs[col].erase(vubCol); - numVarBounds--; - } - delVbds.clear(); - } + for (HighsInt vubCol : delVbds) vubs[col].erase(vubCol); + numVarBounds -= delVbds.size(); + delVbds.clear(); vlbs[col].for_each([&](HighsInt vlbCol, VarBound& vlb) { bool redundant = false; @@ -748,10 +744,8 @@ void HighsImplications::cleanupVarbounds(HighsInt col) { if (infeasible) return; }); - for (HighsInt vlbCol : delVbds) { - vlbs[col].erase(vlbCol); - numVarBounds--; - } + for (HighsInt vlbCol : delVbds) vlbs[col].erase(vlbCol); + numVarBounds -= delVbds.size(); } void HighsImplications::cleanupVlb(HighsInt col, HighsInt vlbCol, diff --git a/highs/mip/HighsImplications.h b/highs/mip/HighsImplications.h index ded41709f7f..e35a39880ab 100644 --- a/highs/mip/HighsImplications.h +++ b/highs/mip/HighsImplications.h @@ -66,7 +66,7 @@ class HighsImplications { nextCleanupCall = mipsolver.numNonzero(); numImplications = 0; numVarBounds = 0; - maxVarBounds = 5000000 + 10 * numcol; + maxVarBounds = calcMaxVarBounds(numcol); } std::function @@ -89,12 +89,18 @@ class HighsImplications { vlbs.shrink_to_fit(); vlbs.resize(numcol); numVarBounds = 0; - maxVarBounds = 5000000 + 10 * numcol; + maxVarBounds = calcMaxVarBounds(numcol); nextCleanupCall = mipsolver.numNonzero(); } - HighsInt getNumImplications() const { return numImplications; } + constexpr static int64_t calcMaxVarBounds(HighsInt numcol) { + return int64_t{5000000} + 10 * static_cast(numcol); + }; + + HighsInt getNumImplications() const { + return static_cast(numImplications); + } const std::vector& getImplications(HighsInt col, bool val, bool& infeasible) { @@ -114,9 +120,7 @@ class HighsImplications { return implications[loc].computed; } - HighsInt getNumVarBounds() const { return numVarBounds; } - - HighsInt getMaxVarBounds() const { return maxVarBounds; } + bool tooManyVarBounds() const { return numVarBounds >= maxVarBounds; } void addVUB(HighsInt col, HighsInt vubcol, double vubcoef, double vubconstant); diff --git a/highs/mip/HighsPrimalHeuristics.cpp b/highs/mip/HighsPrimalHeuristics.cpp index dd393940fb8..57dbb01ab1d 100644 --- a/highs/mip/HighsPrimalHeuristics.cpp +++ b/highs/mip/HighsPrimalHeuristics.cpp @@ -319,7 +319,25 @@ void HighsPrimalHeuristics::rootReducedCost() { localdom.col_lower_, localdom.col_upper_, 500, // std::max(50, int(0.05 * // (mipsolver.mipdata_->num_leaves))), - 200 + mipsolver.mipdata_->num_nodes / 20, 12); + 200 + static_cast(mipsolver.mipdata_->num_nodes / 20), + 12); +} + +static double calcFixVal(double rootchange, double fracval, double cost) { + // reinforce direction of this solution away from root + // solution if the change is at least 0.4 + // otherwise take the direction where the objective gets worse + // if objective is zero round to nearest integer + if (rootchange >= 0.4) + return std::ceil(fracval); + else if (rootchange <= -0.4) + return std::floor(fracval); + else if (cost > 0.0) + return std::ceil(fracval); + else if (cost < 0.0) + return std::floor(fracval); + else + return std::floor(fracval + 0.5); } void HighsPrimalHeuristics::RENS(const std::vector& tmp) { @@ -434,25 +452,15 @@ void HighsPrimalHeuristics::RENS(const std::vector& tmp) { if (numBranched == 0) { auto getFixVal = [&](HighsInt col, double fracval) { - double fixval; - // reinforce direction of this solution away from root // solution if the change is at least 0.4 // otherwise take the direction where the objective gets worse // if objective is zero round to nearest integer - double rootchange = mipsolver.mipdata_->rootlpsol.empty() - ? 0.0 - : fracval - mipsolver.mipdata_->rootlpsol[col]; - if (rootchange >= 0.4) - fixval = std::ceil(fracval); - else if (rootchange <= -0.4) - fixval = std::floor(fracval); - else if (mipsolver.model_->col_cost_[col] > 0.0) - fixval = std::ceil(fracval); - else if (mipsolver.model_->col_cost_[col] < 0.0) - fixval = std::floor(fracval); - else - fixval = std::floor(fracval + 0.5); + double fixval = + calcFixVal(mipsolver.mipdata_->rootlpsol.empty() + ? 0.0 + : fracval - mipsolver.mipdata_->rootlpsol[col], + fracval, mipsolver.model_->col_cost_[col]); // make sure we do not set an infeasible domain fixval = std::min(localdom.col_upper_[col], fixval); fixval = std::max(localdom.col_lower_[col], fixval); @@ -671,17 +679,8 @@ void HighsPrimalHeuristics::RINS(const std::vector& relaxationsol) { // solution if the change is at least 0.4 // otherwise take the direction where the objective gets worse // if objective is zero round to nearest integer - double rootchange = fracval - mipsolver.mipdata_->rootlpsol[col]; - if (rootchange >= 0.4) - fixval = std::ceil(fracval); - else if (rootchange <= -0.4) - fixval = std::floor(fracval); - else if (mipsolver.model_->col_cost_[col] > 0.0) - fixval = std::ceil(fracval); - else if (mipsolver.model_->col_cost_[col] < 0.0) - fixval = std::floor(fracval); - else - fixval = std::floor(fracval + 0.5); + fixval = calcFixVal(fracval - mipsolver.mipdata_->rootlpsol[col], + fracval, mipsolver.model_->col_cost_[col]); } // make sure we do not set an infeasible domain fixval = std::min(localdom.col_upper_[col], fixval);