From 797ee51011ec02d17204a19d9b18689def78256b Mon Sep 17 00:00:00 2001 From: Yu Date: Thu, 12 Oct 2023 08:53:54 -0400 Subject: [PATCH] skip the generation of Benders binary cut if the bigM problem is unbounded (#124) --- src/MibSCutGenerator.cpp | 45 +++++++++++++++++++++++----------------- src/MibSCutGenerator.hpp | 7 ++++--- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/MibSCutGenerator.cpp b/src/MibSCutGenerator.cpp index fbb16fb6..9b17e156 100644 --- a/src/MibSCutGenerator.cpp +++ b/src/MibSCutGenerator.cpp @@ -57,8 +57,8 @@ MibSCutGenerator::MibSCutGenerator(MibSModel *mibs) upper_ = 0.0; maximalCutCount_ = 0; numCalledBoundCut_ = -1; - isBigMIncObjSet_ = false; - bigMIncObj_ = 0.0; + isBigMBendBinSet_ = false; + bigMBendBin_ = 0.0; ImprovingDirectionICSolver_ = 0; } @@ -4805,9 +4805,7 @@ MibSCutGenerator::bendersBinaryCut(BcpsConstraintPool &conPool) (MibSParams::allowRemoveCut)); OsiSolverInterface *solver = localModel_->solver(); - int i; - int index(0); - int numCuts(0); + int i(0), index(0), numCuts(0); double cutub(0.0), cutlb(-solver->getInfinity()), bigM(0.0); double lObjVal(localModel_->bS_->objVal_); double etol(localModel_->etol_); @@ -4831,15 +4829,22 @@ MibSCutGenerator::bendersBinaryCut(BcpsConstraintPool &conPool) if ((useLinkingSolutionPool == PARAM_ON && bS->tagInSeenLinkingPool_ == MibSLinkingPoolTagIsNotSet) || (useLinkingSolutionPool != PARAM_ON && bS->isLowerSolved_ == false)){ - goto TERM_INCOBJ; + goto TERM_BENDBIN; } - if(!isBigMIncObjSet_){ - bigMIncObj_ = findBigMBendersBinaryCut(); - isBigMIncObjSet_ = true; + if(!isBigMBendBinSet_){ + isBigMBendBinSet_ = findBigMBendersBinaryCut(bigMBendBin_); + // YX: turn off the cut if bigM is not found + if(!isBigMBendBinSet_){ + std::cout << "Warning: an error occurred when solving the bigM problem; "; + std::cout << "Benders binary cut generator will be turned off."; + std::cout << std::endl; + localModel_->MibSPar_->setEntry(MibSParams::useBendersBinaryCut, PARAM_OFF); + goto TERM_BENDBIN; + } } - bigM = bigMIncObj_ - lObjVal + 1; + bigM = bigMBendBin_ - lObjVal + 1; for(i = 0; i < uN; i++){ index = upperColInd[i]; @@ -4872,15 +4877,15 @@ MibSCutGenerator::bendersBinaryCut(BcpsConstraintPool &conPool) assert(indexList.size() == valsList.size()); numCuts += addCut(conPool, cutlb, cutub, indexList, valsList, allowRemoveCut); - TERM_INCOBJ: + TERM_BENDBIN: return numCuts; } //############################################################################# -double -MibSCutGenerator::findBigMBendersBinaryCut() +bool +MibSCutGenerator::findBigMBendersBinaryCut(double &bigM) { std::string feasCheckSolver = @@ -4894,9 +4899,8 @@ MibSCutGenerator::findBigMBendersBinaryCut() OsiSolverInterface *oSolver = localModel_->solver(); - int i(0); - int intCnt(0), colIndex(0); - double bigM(0.0); + bool bigMFound(false); + int i(0), intCnt(0), colIndex(0); int colNum(localModel_->getNumOrigVars()); int lCols(localModel_->getLowerDim()); double lObjSense(localModel_->getLowerObjSense()); @@ -5004,17 +5008,20 @@ MibSCutGenerator::findBigMBendersBinaryCut() nSolver->branchAndBound(); if (nSolver->isProvenOptimal()){ - bigM = nSolver->getObjValue(); + bigM = nSolver->getObjValue(); + bigMFound = true; } else{ - assert(0); + // throw CoinError("BigM problem is unbounded (or other error occurs).", + // "findBigMBendersBinaryCut", "MibSCutGenerator"); + bigMFound = false; } delete nSolver; delete [] objCoeffs; delete [] integerVars; - return bigM; + return bigMFound; } //############################################################################# diff --git a/src/MibSCutGenerator.hpp b/src/MibSCutGenerator.hpp index dc2902c7..08328407 100644 --- a/src/MibSCutGenerator.hpp +++ b/src/MibSCutGenerator.hpp @@ -29,8 +29,8 @@ class MibSCutGenerator : public BlisConGenerator { int auxCount_; int maximalCutCount_; int numCalledBoundCut_; - bool isBigMIncObjSet_; - double bigMIncObj_; + bool isBigMBendBinSet_; + double bigMBendBin_; OsiSolverInterface * ImprovingDirectionICSolver_; std::vector leafNodeCutTmpHist_; @@ -161,7 +161,8 @@ class MibSCutGenerator : public BlisConGenerator { /** Add disjunctive cuts for binary upper-level variables (maximal sol) **/ int bendersBinaryCutMaximal(BcpsConstraintPool &conPool); - double findBigMBendersBinaryCut(); + /** Solve the big M problem for Benders binary cut **/ + bool findBigMBendersBinaryCut(double &bigM); /** Add disjunctive cuts for binary upper-level variables (current sol)**/ int weakBendersBinaryCutCurrent(BcpsConstraintPool &conPool);