diff --git a/Testing/Temporary/CTestCostData.txt b/Testing/Temporary/CTestCostData.txt new file mode 100644 index 0000000000..ed97d539c0 --- /dev/null +++ b/Testing/Temporary/CTestCostData.txt @@ -0,0 +1 @@ +--- diff --git a/src/mip/HighsCliqueTable.cpp b/src/mip/HighsCliqueTable.cpp index e311add6f4..6ec99a843d 100644 --- a/src/mip/HighsCliqueTable.cpp +++ b/src/mip/HighsCliqueTable.cpp @@ -1900,7 +1900,7 @@ void HighsCliqueTable::cleanupFixed(HighsDomain& globaldom) { if (nfixings != oldnfixings) propagateAndCleanup(globaldom); } -HighsInt HighsCliqueTable::getNumImplications(HighsInt col) { +HighsInt HighsCliqueTable::getNumImplications(HighsInt col) const { // first count all cliques as one implication, so that cliques of size two // are accounted for already HighsInt i0 = CliqueVar(col, 0).index(); @@ -1919,7 +1919,7 @@ HighsInt HighsCliqueTable::getNumImplications(HighsInt col) { return numimplics; } -HighsInt HighsCliqueTable::getNumImplications(HighsInt col, bool val) { +HighsInt HighsCliqueTable::getNumImplications(HighsInt col, bool val) const { HighsInt iVal = CliqueVar(col, val).index(); // each size two clique is one implication diff --git a/src/mip/HighsCliqueTable.h b/src/mip/HighsCliqueTable.h index 002852dd4b..1ae2b30236 100644 --- a/src/mip/HighsCliqueTable.h +++ b/src/mip/HighsCliqueTable.h @@ -286,9 +286,9 @@ class HighsCliqueTable { void addImplications(HighsDomain& domain, HighsInt col, HighsInt val); - HighsInt getNumImplications(HighsInt col); + HighsInt getNumImplications(HighsInt col) const; - HighsInt getNumImplications(HighsInt col, bool val); + HighsInt getNumImplications(HighsInt col, bool val) const; void runCliqueMerging(HighsDomain& globaldomain); diff --git a/src/mip/HighsImplications.cpp b/src/mip/HighsImplications.cpp index 7e1c1d62bc..5c4fe9d064 100644 --- a/src/mip/HighsImplications.cpp +++ b/src/mip/HighsImplications.cpp @@ -344,7 +344,7 @@ bool HighsImplications::runProbing(HighsInt col, HighsInt& numReductions) { substitutions.push_back(substitution); colsubstituted[implcol] = true; ++numReductions; - } else { + } else if (mipsolver.mipdata_->workers.size() <= 1) { double lb = std::min(lbDown, lbUp); double ub = std::max(ubDown, ubUp); @@ -558,7 +558,9 @@ void HighsImplications::separateImpliedBounds( if (nextCleanupCall < 0) { // HighsInt oldNumEntries = // mipsolver.mipdata_->cliquetable.getNumEntries(); - mipsolver.mipdata_->cliquetable.runCliqueMerging(globaldomain); + if (mipsolver.mipdata_->workers.size() <= 1) + mipsolver.mipdata_->cliquetable.runCliqueMerging(globaldomain); + // printf("numEntries: %d, beforeMerging: %d\n", // mipsolver.mipdata_->cliquetable.getNumEntries(), oldNumEntries); nextCleanupCall = @@ -567,7 +569,8 @@ void HighsImplications::separateImpliedBounds( // printf("nextCleanupCall: %d\n", nextCleanupCall); } - mipsolver.mipdata_->cliquetable.numNeighbourhoodQueries = oldNumQueries; + if (mipsolver.mipdata_->workers.size() <= 1) + mipsolver.mipdata_->cliquetable.numNeighbourhoodQueries = oldNumQueries; } for (std::pair fracint : diff --git a/src/mip/HighsMipSolver.cpp b/src/mip/HighsMipSolver.cpp index ac82298d50..5ff49cf66e 100644 --- a/src/mip/HighsMipSolver.cpp +++ b/src/mip/HighsMipSolver.cpp @@ -349,6 +349,7 @@ void HighsMipSolver::run() { if (evaluate_node_result == HighsSearch::NodeResult::kSubOptimal) break; if (search.currentNodePruned()) { + // ig: do we update num_leaves here? ++mipdata_->num_leaves; search.flushStatistics(); } else { diff --git a/src/mip/HighsRedcostFixing.cpp b/src/mip/HighsRedcostFixing.cpp index 3da72c6d8d..16f52d7e87 100644 --- a/src/mip/HighsRedcostFixing.cpp +++ b/src/mip/HighsRedcostFixing.cpp @@ -150,27 +150,29 @@ void HighsRedcostFixing::propagateRedCost(const HighsMipSolver& mipsolver, false)) { bool addedConstraints = false; - HighsInt oldNumConflicts = - mipsolver.mipdata_->conflictPool.getNumConflicts(); - for (const HighsDomainChange& domchg : boundChanges) { - if (localdomain.isActive(domchg)) continue; - localdomain.conflictAnalyzeReconvergence( - domchg, inds.data(), vals.data(), inds.size(), rhs, - mipsolver.mipdata_->conflictPool); - } - addedConstraints = - mipsolver.mipdata_->conflictPool.getNumConflicts() != oldNumConflicts; - - if (addedConstraints) { - localdomain.propagate(); - if (localdomain.infeasible()) return; - - boundChanges.erase( - std::remove_if(boundChanges.begin(), boundChanges.end(), - [&](const HighsDomainChange& domchg) { - return localdomain.isActive(domchg); - }), - boundChanges.end()); + if (mipsolver.mipdata_->workers.size() <= 1) { + HighsInt oldNumConflicts = + mipsolver.mipdata_->conflictPool.getNumConflicts(); + for (const HighsDomainChange& domchg : boundChanges) { + if (localdomain.isActive(domchg)) continue; + localdomain.conflictAnalyzeReconvergence( + domchg, inds.data(), vals.data(), inds.size(), rhs, + mipsolver.mipdata_->conflictPool); + } + addedConstraints = + mipsolver.mipdata_->conflictPool.getNumConflicts() != oldNumConflicts; + + if (addedConstraints) { + localdomain.propagate(); + if (localdomain.infeasible()) return; + + boundChanges.erase( + std::remove_if(boundChanges.begin(), boundChanges.end(), + [&](const HighsDomainChange& domchg) { + return localdomain.isActive(domchg); + }), + boundChanges.end()); + } } if (!boundChanges.empty()) { diff --git a/src/mip/HighsSeparation.cpp b/src/mip/HighsSeparation.cpp index 1a9a3aeb0f..0203a19229 100644 --- a/src/mip/HighsSeparation.cpp +++ b/src/mip/HighsSeparation.cpp @@ -79,10 +79,12 @@ HighsInt HighsSeparation::separationRound(HighsDomain& propdomain, return numBoundChgs; }; - lp->getMipSolver().timer_.start(implBoundClock); - mipdata.implications.separateImpliedBounds(*lp, lp->getSolution().col_value, - mipdata.cutpool, mipdata.feastol); - lp->getMipSolver().timer_.stop(implBoundClock); + if (&propdomain == &mipdata.domain) { + lp->getMipSolver().timer_.start(implBoundClock); + mipdata.implications.separateImpliedBounds(*lp, lp->getSolution().col_value, + mipdata.cutpool, mipdata.feastol); + lp->getMipSolver().timer_.stop(implBoundClock); + } HighsInt ncuts = 0; HighsInt numboundchgs = propagateAndResolve(); @@ -91,10 +93,12 @@ HighsInt HighsSeparation::separationRound(HighsDomain& propdomain, else ncuts += numboundchgs; - lp->getMipSolver().timer_.start(cliqueClock); - mipdata.cliquetable.separateCliques(lp->getMipSolver(), sol.col_value, - mipdata.cutpool, mipdata.feastol); - lp->getMipSolver().timer_.stop(cliqueClock); + if (&propdomain == &mipdata.domain) { + lp->getMipSolver().timer_.start(cliqueClock); + mipdata.cliquetable.separateCliques(lp->getMipSolver(), sol.col_value, + mipdata.cutpool, mipdata.feastol); + lp->getMipSolver().timer_.stop(cliqueClock); + } numboundchgs = propagateAndResolve(); if (numboundchgs == -1) @@ -112,11 +116,13 @@ HighsInt HighsSeparation::separationRound(HighsDomain& propdomain, } HighsLpAggregator lpAggregator(*lp); - for (const std::unique_ptr& separator : separators) { - separator->run(*lp, lpAggregator, transLp, mipdata.cutpool); - if (mipdata.domain.infeasible()) { - status = HighsLpRelaxation::Status::kInfeasible; - return 0; + if (&propdomain == &mipdata.domain) { + for (const std::unique_ptr& separator : separators) { + separator->run(*lp, lpAggregator, transLp, mipdata.cutpool); + if (mipdata.domain.infeasible()) { + status = HighsLpRelaxation::Status::kInfeasible; + return 0; + } } } @@ -126,13 +132,17 @@ HighsInt HighsSeparation::separationRound(HighsDomain& propdomain, else ncuts += numboundchgs; - mipdata.cutpool.separate(sol.col_value, propdomain, cutset, mipdata.feastol); + if (&propdomain == &mipdata.domain) { + mipdata.cutpool.separate(sol.col_value, propdomain, cutset, mipdata.feastol); + } if (cutset.numCuts() > 0) { ncuts += cutset.numCuts(); lp->addCuts(cutset); status = lp->resolveLp(&propdomain); lp->performAging(true); + + // only for the master domain. if (&propdomain == &mipdata.domain && lp->unscaledDualFeasible(status)) { mipdata.redcostfixing.addRootRedcost( mipdata.mipsolver, lp->getSolution().col_dual, lp->getObjective()); diff --git a/src/mip/HighsTransformedLp.cpp b/src/mip/HighsTransformedLp.cpp index 703b377e09..b8aef9d737 100644 --- a/src/mip/HighsTransformedLp.cpp +++ b/src/mip/HighsTransformedLp.cpp @@ -34,7 +34,9 @@ HighsTransformedLp::HighsTransformedLp(const HighsLpRelaxation& lprelaxation, vectorsum.setDimension(numTransformedCol); for (HighsInt col : mipsolver.mipdata_->continuous_cols) { - mipsolver.mipdata_->implications.cleanupVarbounds(col); + if (mipsolver.mipdata_->workers.size() <= 1) + mipsolver.mipdata_->implications.cleanupVarbounds(col); + if (mipsolver.mipdata_->domain.infeasible()) return; if (mipsolver.mipdata_->domain.isFixed(col)) continue; @@ -63,7 +65,9 @@ HighsTransformedLp::HighsTransformedLp(const HighsLpRelaxation& lprelaxation, double bestub = mipsolver.mipdata_->domain.col_upper_[col]; double bestlb = mipsolver.mipdata_->domain.col_lower_[col]; - mipsolver.mipdata_->implications.cleanupVarbounds(col); + if (mipsolver.mipdata_->workers.size() <= 1) + mipsolver.mipdata_->implications.cleanupVarbounds(col); + if (mipsolver.mipdata_->domain.infeasible()) return; simpleUbDist[col] = bestub - lpSolution.col_value[col]; if (simpleUbDist[col] <= mipsolver.mipdata_->feastol) @@ -185,9 +189,10 @@ bool HighsTransformedLp::transform(std::vector& vals, bestVub[col].second.maxValue() > ub + mip.mipdata_->feastol) { bool redundant = false; bool infeasible = false; - mip.mipdata_->implications.cleanupVub(col, bestVub[col].first, - bestVub[col].second, ub, redundant, - infeasible, false); + if (mip.mipdata_->workers.size() <= 1) + mip.mipdata_->implications.cleanupVub(col, bestVub[col].first, + bestVub[col].second, ub, redundant, + infeasible, false); } // the code below uses the difference between the column upper and lower @@ -200,9 +205,11 @@ bool HighsTransformedLp::transform(std::vector& vals, bestVlb[col].second.minValue() < lb - mip.mipdata_->feastol) { bool redundant = false; bool infeasible = false; - mip.mipdata_->implications.cleanupVlb(col, bestVlb[col].first, - bestVlb[col].second, lb, redundant, - infeasible, false); + + if (mip.mipdata_->workers.size() <= 1) + mip.mipdata_->implications.cleanupVlb(col, bestVlb[col].first, + bestVlb[col].second, lb, redundant, + infeasible, false); } // store the old bound type so that we can restore it if the continuous