From e2bca528520a3f83070e233599e8d5dcd67c5efb Mon Sep 17 00:00:00 2001 From: Ted Ralphs Date: Tue, 29 Oct 2024 23:28:57 +0100 Subject: [PATCH 1/9] Adding parameters to allow more fine-grained control of cut generation --- src/MibSBilevel.cpp | 18 +++++-- src/MibSConstants.hpp | 22 +++++++++ src/MibSCutGenerator.cpp | 67 +++++++++++++++++++------ src/MibSModel.cpp | 102 ++++++++++++++++++++++++++++++--------- src/MibSParams.cpp | 31 +++++++----- src/MibSParams.hpp | 8 +-- 6 files changed, 191 insertions(+), 57 deletions(-) diff --git a/src/MibSBilevel.cpp b/src/MibSBilevel.cpp index bcd08cb7..d3ff9585 100644 --- a/src/MibSBilevel.cpp +++ b/src/MibSBilevel.cpp @@ -57,15 +57,19 @@ MibSBilevel::createBilevel(CoinPackedVector* sol, (model_->MibSPar_->entry(MibSParams::branchStrategy)); bool solveSecondLevelEveryIteration(model_->MibSPar_->entry - (MibSParams::solveSecondLevelEveryIteration) == PARAM_ON); + (MibSParams::solveSecondLevelEveryIteration) == PARAM_ON); + bool solveSecondLevelEveryIterationRoot(model_->MibSPar_->entry + (MibSParams::solveSecondLevelEveryIterationRoot) == PARAM_ON); bool solveSecondLevelWhenXYVarsInt(model_->MibSPar_->entry - (MibSParams::solveSecondLevelWhenXYVarsInt) == PARAM_ON); + (MibSParams::solveSecondLevelWhenXYVarsInt) == PARAM_ON); bool solveSecondLevelWhenXVarsInt(model_->MibSPar_->entry - (MibSParams::solveSecondLevelWhenXVarsInt) == PARAM_ON); + (MibSParams::solveSecondLevelWhenXVarsInt) == PARAM_ON); + bool solveSecondLevelWhenYVarsInt(model_->MibSPar_->entry + (MibSParams::solveSecondLevelWhenXVarsInt) == PARAM_ON); bool solveSecondLevelWhenLVarsInt(model_->MibSPar_->entry - (MibSParams::solveSecondLevelWhenLVarsInt) == PARAM_ON); + (MibSParams::solveSecondLevelWhenLVarsInt) == PARAM_ON); bool solveSecondLevelWhenLVarsFixed(model_->MibSPar_->entry - (MibSParams::solveSecondLevelWhenLVarsFixed) == PARAM_ON); + (MibSParams::solveSecondLevelWhenLVarsFixed) == PARAM_ON); int cutStrategy(model_->MibSPar_->entry (MibSParams::cutStrategy)); @@ -239,8 +243,11 @@ MibSBilevel::createBilevel(CoinPackedVector* sol, isLinkVarsFixed_) || (branchPar == MibSBranchingStrategyFractional && isIntegral_) || (solveSecondLevelEveryIteration) || + (solveSecondLevelEveryIterationRoot && + model_->activeNode_->getDepth() == 0) || (solveSecondLevelWhenXYVarsInt && isIntegral_) || (solveSecondLevelWhenXVarsInt && isUpperIntegral_) || + (solveSecondLevelWhenYVarsInt && isLowerIntegral_) || (solveSecondLevelWhenLVarsInt && isLinkVarsIntegral_) || (solveSecondLevelWhenLVarsFixed && isLinkVarsFixed_ )))){ storeSol = checkBilevelFeasibility(mibs->isRoot_); @@ -420,6 +427,7 @@ MibSBilevel::checkBilevelFeasibility(bool isRoot) }else{ startTimeVF = model_->broker_->subTreeTimer().getTime(); lSolver->branchAndBound(); + lSolver->writeLp("water"); model_->timerVF_ += model_->broker_->subTreeTimer().getTime() - startTimeVF; } diff --git a/src/MibSConstants.hpp b/src/MibSConstants.hpp index 05dd7104..fce58d31 100644 --- a/src/MibSConstants.hpp +++ b/src/MibSConstants.hpp @@ -98,6 +98,28 @@ enum MibSBilevelFreeSetTypeISIC{ //############################################################################# +enum MibSIDICGenStrategy{ + MibSIDICGenStrategyNotSet = -1, + MibSIDICGenStrategyAlways, + MibSIDICGenStrategyAlwaysRoot, + MibSIDICGenStrategyXYInt, + MibSIDICGenStrategyLInt, + MibSIDICGenStrategyYInt +}; + +//############################################################################# + +enum MibSISICGenStrategy{ + MibSISICGenStrategyNotSet = -1, + MibSISICGenStrategyAlways, + MibSISICGenStrategyAlwaysRoot, + MibSISICGenStrategyXYInt, + MibSISICGenStrategyLInt, + MibSISICGenStrategyYInt, +}; + +//############################################################################# + enum MibSRelaxTypeParamBoundCut{ MibSRelaxTypeParamBoundCutLP = 0, MibSRelaxTypeParamBoundCutMIP diff --git a/src/MibSCutGenerator.cpp b/src/MibSCutGenerator.cpp index ea80ddb8..d2327c42 100644 --- a/src/MibSCutGenerator.cpp +++ b/src/MibSCutGenerator.cpp @@ -5870,11 +5870,11 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) int useBendersBinaryCut = localModel_->MibSPar_->entry(MibSParams::useBendersBinaryCut); - int useFractionalCuts = - localModel_->MibSPar_->entry(MibSParams::useFractionalCuts); + int IDICGenStrategy = + localModel_->MibSPar_->entry(MibSParams::IDICGenStrategy); - int useFractionalCutsRootOnly = - localModel_->MibSPar_->entry(MibSParams::useFractionalCutsRootOnly); + int ISICGenStrategy = + localModel_->MibSPar_->entry(MibSParams::ISICGenStrategy); double relaxedObjVal = localModel_->bS_->getLowerObj( localModel_->solver()->getColSolution(), @@ -6012,14 +6012,25 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) numCuts += bendersInterdictionMultipleCuts(conPool); } } - if (useImprovingSolutionIC == PARAM_ON && ((haveSecondLevelSol && - relaxedObjVal > localModel_->bS_->objVal_ + localModel_->etol_) || - localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == 1)){ + if (useImprovingSolutionIC == PARAM_ON && + ((haveSecondLevelSol && + relaxedObjVal > localModel_->bS_->objVal_ + localModel_->etol_) || + (localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == + MibSBilevelFreeSetTypeISICWithNewLLSol && + ISICGenStrategy == MibSIDICGenStrategyLInt))){ cutType = MibSIntersectionCutImprovingSolution; numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); } - if (useFractionalCuts && useImprovingDirectionIC == PARAM_ON){ + if (useImprovingDirectionIC == PARAM_ON && + ((haveSecondLevelSol && + relaxedObjVal > localModel_->bS_->objVal_ + localModel_->etol_) || + (localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == + MibSBilevelFreeSetTypeISICWithNewLLSol && + (ISICGenStrategy == MibSIDICGenStrategyLInt || + ISICGenStrategy == MibSIDICGenStrategyAlways || + (ISICGenStrategy == MibSIDICGenStrategyAlwaysRoot && + localModel_->activeNode_->getDepth() == 0))))){ cutType = MibSIntersectionCutImprovingDirection; numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); } @@ -6044,17 +6055,43 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) //and should always be false (see BlisTreeNode.cpp) return (false); - }else if (bS->isLowerIntegral_ && - (useFractionalCuts || - (useFractionalCutsRootOnly && - localModel_->activeNode_->getDepth() == 0))){ - if (useImprovingDirectionIC == PARAM_ON){ + }else if (bS->isLowerIntegral_){ + if (useImprovingDirectionIC == PARAM_ON && + (IDICGenStrategy == MibSIDICGenStrategyAlways || + IDICGenStrategy == MibSIDICGenStrategyYInt || + (IDICGenStrategy == MibSIDICGenStrategyAlwaysRoot && + localModel_->activeNode_->getDepth() == 0))){ + cutType = MibSIntersectionCutImprovingDirection; + numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + } + if (useImprovingSolutionIC == PARAM_ON && + ((haveSecondLevelSol && + relaxedObjVal > localModel_->bS_->objVal_ + localModel_->etol_) || + (localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == + MibSBilevelFreeSetTypeISICWithNewLLSol && + (ISICGenStrategy == MibSIDICGenStrategyYInt || + ISICGenStrategy == MibSIDICGenStrategyAlways || + (ISICGenStrategy == MibSIDICGenStrategyAlwaysRoot && + localModel_->activeNode_->getDepth() == 0))))){ + cutType = MibSIntersectionCutImprovingSolution; + numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + } + }else{ + if (useImprovingDirectionIC == PARAM_ON && + (IDICGenStrategy == MibSIDICGenStrategyAlways || + (IDICGenStrategy == MibSIDICGenStrategyAlwaysRoot && + localModel_->activeNode_->getDepth() == 0))){ cutType = MibSIntersectionCutImprovingDirection; numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); } - if (useImprovingSolutionIC == PARAM_ON && ((haveSecondLevelSol && + if (useImprovingSolutionIC == PARAM_ON && + ((haveSecondLevelSol && relaxedObjVal > localModel_->bS_->objVal_ + localModel_->etol_) || - localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == 1)){ + (localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == + MibSBilevelFreeSetTypeISICWithNewLLSol && + (ISICGenStrategy == MibSIDICGenStrategyAlways || + (ISICGenStrategy == MibSIDICGenStrategyAlwaysRoot && + localModel_->activeNode_->getDepth() == 0))))){ cutType = MibSIntersectionCutImprovingSolution; numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); } diff --git a/src/MibSModel.cpp b/src/MibSModel.cpp index cda009e5..37cf3233 100644 --- a/src/MibSModel.cpp +++ b/src/MibSModel.cpp @@ -3933,7 +3933,10 @@ MibSModel::adjustParameters() } } if (MibSPar_->entry(MibSParams::useImprovingDirectionIC) == PARAM_ON){ - defaultCutIsOn = true; + defaultCutIsOn = true; + if (MibSPar_->entry(MibSParams::IDICGenStrategy) == MibSIDICGenStrategyNotSet){ + MibSPar()->setEntry(MibSParams::IDICGenStrategy, MibSIDICGenStrategyXYInt); + } } //Param: "MibS_useImprovingSolutionIC" @@ -3958,8 +3961,8 @@ MibSModel::adjustParameters() std::cout << std::endl; MibSPar()->setEntry(MibSParams::useImprovingSolutionIC, PARAM_OFF); } - if (MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == 1 && - isLowerObjInt_ == false){ + if (MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == + MibSBilevelFreeSetTypeISICWithNewLLSol && isLowerObjInt_ == false){ std::cout << "The improving solution intersection cut (type II) are " << "only valid for problems with integer lower-level " << "objective coefficients."; @@ -3967,6 +3970,27 @@ MibSModel::adjustParameters() MibSPar()->setEntry(MibSParams::useImprovingSolutionIC, PARAM_OFF); } } + if (MibSPar_->entry(MibSParams::useImprovingSolutionIC) == PARAM_ON){ + switch (MibSPar_->entry(MibSParams::ISICGenStrategy)) { + case MibSISICGenStrategyNotSet: + MibSPar()->setEntry(MibSParams::ISICGenStrategy, MibSISICGenStrategyXYInt); + case MibSISICGenStrategyXYInt: + MibSPar()->setEntry(MibSParams::solveSecondLevelWhenXYVarsInt, 1); + break; + case MibSISICGenStrategyLInt: + MibSPar()->setEntry(MibSParams::solveSecondLevelWhenLVarsInt, 1); + break; + case MibSISICGenStrategyYInt: + MibSPar()->setEntry(MibSParams::solveSecondLevelWhenYVarsInt, 1); + break; + case MibSISICGenStrategyAlways: + MibSPar()->setEntry(MibSParams::solveSecondLevelEveryIteration, 1); + break; + case MibSISICGenStrategyAlwaysRoot: + MibSPar()->setEntry(MibSParams::solveSecondLevelEveryIterationRoot, 1); + break; + } + } //Param: "MibS_useHyperCubeIC" if ((turnOffDefaultCuts == true) && @@ -4155,36 +4179,68 @@ MibSModel::printProblemInfo(){ if (MibSPar_->entry(MibSParams::useImprovingSolutionIC) == PARAM_ON){ if (MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == MibSBilevelFreeSetTypeISICWithLLOptSol){ - std::cout << "Improving solution intersection cut generator (Type I) is on." << std::endl; + std::cout << "Improving solution intersection cut generator " + << "(Type I) is on." << std::endl; }else{ - std::cout << "Improving solution intersection cut generator (Type II) is on." << std::endl; + std::cout << "Improving solution intersection cut generator " + << "(Type II) is on." << std::endl; } + switch (MibSPar_->entry(MibSParams::ISICGenStrategy)){ + case MibSISICGenStrategyLInt: + std::cout << "ISICs will be used to separate solutions " + << "with integer linking variables." << std::endl; + break; + case MibSISICGenStrategyYInt: + std::cout << "ISICs will be used to separate solutions " + << "with integer lower-level variables." << std::endl; + break; + case MibSISICGenStrategyXYInt: + std::cout << "ISICs will be used to separate only solutions " + << "that are fully integer." << std::endl; + break; + case MibSISICGenStrategyAlwaysRoot: + std::cout << "ISICs will be used to separate fractional solutions " + << "only in the root node." << std::endl; + break; + case MibSISICGenStrategyAlways: + std::cout << "ISICs will be used to separate all solutions." + << std::endl; + break; + } } if (MibSPar_->entry(MibSParams::useImprovingDirectionIC) == PARAM_ON){ - std::cout << "Improving direction intersection cut generator is on." << std::endl; + std::cout << "Improving direction intersection cut generator is on." + << std::endl; + switch (MibSPar_->entry(MibSParams::IDICGenStrategy)){ + case MibSIDICGenStrategyLInt: + std::cout << "IDICs will be used to separate solutions " + << "with integer linking variables." << std::endl; + break; + case MibSIDICGenStrategyYInt: + std::cout << "IDICs will be used to separate solutions " + << "with integer lower-level variables." << std::endl; + break; + case MibSIDICGenStrategyXYInt: + std::cout << "IDICs will be used to separate only solutions " + << "that are fully integer." << std::endl; + break; + case MibSIDICGenStrategyAlwaysRoot: + std::cout << "IDICs will be used to separate fractional solutions " + << "only in the root node." << std::endl; + break; + case MibSIDICGenStrategyAlways: + std::cout << "IDICs will be used to separate all solutions." + << std::endl; + break; + } } if (MibSPar_->entry(MibSParams::useHypercubeIC) == PARAM_ON){ - std::cout << "Hypercube intersection cut generator is on." << std::endl; + std::cout << "Hypercube intersection cut generator is on." + << std::endl; } - if (MibSPar_->entry(MibSParams::useImprovingSolutionIC) == PARAM_ON || - MibSPar_->entry(MibSParams::useImprovingDirectionIC) == PARAM_ON){ - - if (MibSPar_->entry(MibSParams::useFractionalCutsRootOnly) == 1){ - std::cout << "Fractional solutions will be seperated in the root node." << std::endl; - MibSPar_->setEntry(MibSParams::useFractionalCuts, 0); - } - if (MibSPar_->entry(MibSParams::useFractionalCuts) == 1){ - std::cout << "Fractional solutions will be separated using intersection cuts." - << std::endl; - }else{ - std::cout << "Only integer solutions will be separated using intersection cuts." - << std::endl; - } - } - if (MibSPar_->entry(MibSParams::solveSecondLevelEveryIteration) == PARAM_OFF && MibSPar_->entry(MibSParams::solveSecondLevelWhenXYVarsInt) == diff --git a/src/MibSParams.cpp b/src/MibSParams.cpp index a7710ff7..be07edf3 100644 --- a/src/MibSParams.cpp +++ b/src/MibSParams.cpp @@ -177,12 +177,21 @@ MibSParams::createKeywordList() { keys_.push_back(make_pair(std::string("MibS_useTypeIC"), AlpsParameter(AlpsIntPar, useImprovingSolutionIC))); + keys_.push_back(make_pair(std::string("MibS_ISICGenStrategy"), + AlpsParameter(AlpsIntPar, ISICGenStrategy))); + keys_.push_back(make_pair(std::string("MibS_useImprovingDirectionIC"), AlpsParameter(AlpsIntPar, useImprovingDirectionIC))); //legacy parameter name keys_.push_back(make_pair(std::string("MibS_useTypeWatermelon"), AlpsParameter(AlpsIntPar, useImprovingDirectionIC))); + keys_.push_back(make_pair(std::string("MibS_IDICGenStrategy"), + AlpsParameter(AlpsIntPar, IDICGenStrategy))); + + keys_.push_back(make_pair(std::string("MibS_useTypeWatermelon"), + AlpsParameter(AlpsIntPar, useImprovingDirectionIC))); + keys_.push_back(make_pair(std::string("MibS_useHypercubeIC"), AlpsParameter(AlpsIntPar, useHypercubeIC))); @@ -195,23 +204,23 @@ MibSParams::createKeywordList() { keys_.push_back(make_pair(std::string("MibS_bilevelFreeSetTypeISIC"), AlpsParameter(AlpsIntPar, bilevelFreeSetTypeISIC))); - keys_.push_back(make_pair(std::string("MibS_useFractionalCuts"), - AlpsParameter(AlpsIntPar, useFractionalCuts))); - - keys_.push_back(make_pair(std::string("MibS_useFractionalCutsRootOnly"), - AlpsParameter(AlpsIntPar, - useFractionalCutsRootOnly))); - //solve lower-level Parameters keys_.push_back(make_pair(std::string("MibS_solveSecondLevelEveryIteration"), AlpsParameter(AlpsIntPar, solveSecondLevelEveryIteration))); + keys_.push_back(make_pair(std::string("MibS_solveSecondLevelEveryIterationRoot"), + AlpsParameter(AlpsIntPar, + solveSecondLevelEveryIterationRoot))); + keys_.push_back(make_pair(std::string("MibS_solveSecondLevelWhenXYVarsInt"), AlpsParameter(AlpsIntPar, solveSecondLevelWhenXYVarsInt))); keys_.push_back(make_pair(std::string("MibS_solveSecondLevelWhenXVarsInt"), AlpsParameter(AlpsIntPar, solveSecondLevelWhenXVarsInt))); + keys_.push_back(make_pair(std::string("MibS_solveSecondLevelWhenYVarsInt"), + AlpsParameter(AlpsIntPar, solveSecondLevelWhenYVarsInt))); + keys_.push_back(make_pair(std::string("MibS_solveSecondLevelWhenLVarsInt"), AlpsParameter(AlpsIntPar, solveSecondLevelWhenLVarsInt))); @@ -384,18 +393,18 @@ MibSParams::setDefaultEntries() { setEntry(useHybridIC, PARAM_NOTSET); - setEntry(useFractionalCuts, 1); - - setEntry(useFractionalCutsRootOnly, 0); - setEntry(bilevelFreeSetTypeISIC, MibSBilevelFreeSetTypeISICWithLLOptSol); setEntry(solveSecondLevelEveryIteration, PARAM_OFF); + setEntry(solveSecondLevelEveryIterationRoot, PARAM_OFF); + setEntry(solveSecondLevelWhenXYVarsInt, PARAM_ON); setEntry(solveSecondLevelWhenXVarsInt, PARAM_OFF); + setEntry(solveSecondLevelWhenYVarsInt, PARAM_OFF); + setEntry(solveSecondLevelWhenLVarsInt, PARAM_OFF); setEntry(solveSecondLevelWhenLVarsFixed, PARAM_ON); diff --git a/src/MibSParams.hpp b/src/MibSParams.hpp index 9d168670..cf5a7d3c 100644 --- a/src/MibSParams.hpp +++ b/src/MibSParams.hpp @@ -71,16 +71,18 @@ class MibSParams : public AlpsParameterSet { useBendersInterdictionCut, bendersInterdictionCutType, useImprovingSolutionIC, + ISICGenStrategy, + bilevelFreeSetTypeISIC, useImprovingDirectionIC, + IDICGenStrategy, useHypercubeIC, useTenderIC, useHybridIC, - useFractionalCuts, - useFractionalCutsRootOnly, - bilevelFreeSetTypeISIC, solveSecondLevelEveryIteration, + solveSecondLevelEveryIterationRoot, solveSecondLevelWhenXYVarsInt, solveSecondLevelWhenXVarsInt, + solveSecondLevelWhenYVarsInt, solveSecondLevelWhenLVarsInt, solveSecondLevelWhenLVarsFixed, computeBestUBWhenXVarsInt, From 806e2b95a3e0a1d3bc384e6ee7e4beb64dd243fe Mon Sep 17 00:00:00 2001 From: Ted Ralphs Date: Wed, 30 Oct 2024 14:58:37 +0100 Subject: [PATCH 2/9] Fixing some obvious bugs --- src/MibSBilevel.cpp | 2 +- src/MibSCutGenerator.cpp | 34 +++++++++++++++------------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/MibSBilevel.cpp b/src/MibSBilevel.cpp index d3ff9585..64af56d1 100644 --- a/src/MibSBilevel.cpp +++ b/src/MibSBilevel.cpp @@ -427,7 +427,7 @@ MibSBilevel::checkBilevelFeasibility(bool isRoot) }else{ startTimeVF = model_->broker_->subTreeTimer().getTime(); lSolver->branchAndBound(); - lSolver->writeLp("water"); + //lSolver->writeLp("water"); model_->timerVF_ += model_->broker_->subTreeTimer().getTime() - startTimeVF; } diff --git a/src/MibSCutGenerator.cpp b/src/MibSCutGenerator.cpp index d2327c42..473f3819 100644 --- a/src/MibSCutGenerator.cpp +++ b/src/MibSCutGenerator.cpp @@ -828,7 +828,7 @@ MibSCutGenerator::findLowerLevelSolImprovingSolutionIC(double *uselessIneqs, double infinity(oSolver->getInfinity()); int i, j; int index(0), cntInt(0); - double lObjVal(0.0), value(0.0); + double lObjVal(0.0); int uCols(localModel_->getUpperDim()); int lCols(localModel_->getLowerDim()); int lRows(localModel_->getLowerRowNum()); @@ -6012,34 +6012,30 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) numCuts += bendersInterdictionMultipleCuts(conPool); } } - if (useImprovingSolutionIC == PARAM_ON && - ((haveSecondLevelSol && - relaxedObjVal > localModel_->bS_->objVal_ + localModel_->etol_) || - (localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == - MibSBilevelFreeSetTypeISICWithNewLLSol && - ISICGenStrategy == MibSIDICGenStrategyLInt))){ + if (useImprovingDirectionIC == PARAM_ON && + (IDICGenStrategy == MibSIDICGenStrategyLInt || + IDICGenStrategy == MibSIDICGenStrategyAlways || + (IDICGenStrategy == MibSIDICGenStrategyAlwaysRoot && + localModel_->activeNode_->getDepth() == 0))){ cutType = MibSIntersectionCutImprovingSolution; numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); } - - if (useImprovingDirectionIC == PARAM_ON && + if (useImprovingSolutionIC == PARAM_ON && ((haveSecondLevelSol && relaxedObjVal > localModel_->bS_->objVal_ + localModel_->etol_) || (localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == MibSBilevelFreeSetTypeISICWithNewLLSol && - (ISICGenStrategy == MibSIDICGenStrategyLInt || - ISICGenStrategy == MibSIDICGenStrategyAlways || - (ISICGenStrategy == MibSIDICGenStrategyAlwaysRoot && + (ISICGenStrategy == MibSISICGenStrategyLInt || + ISICGenStrategy == MibSISICGenStrategyAlways || + (ISICGenStrategy == MibSISICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))))){ cutType = MibSIntersectionCutImprovingDirection; numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); } - if (useHypercubeIC == PARAM_ON && haveSecondLevelSol){ cutType = MibSIntersectionCutHypercube; numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); } - if (localModel_->allUpperBin_){ //problem with binary UL variables and integer LL variables if (useGeneralizedNoGoodCut == PARAM_ON){ @@ -6057,8 +6053,8 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) }else if (bS->isLowerIntegral_){ if (useImprovingDirectionIC == PARAM_ON && - (IDICGenStrategy == MibSIDICGenStrategyAlways || - IDICGenStrategy == MibSIDICGenStrategyYInt || + (IDICGenStrategy == MibSIDICGenStrategyYInt || + IDICGenStrategy == MibSIDICGenStrategyAlways || (IDICGenStrategy == MibSIDICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))){ cutType = MibSIntersectionCutImprovingDirection; @@ -6069,9 +6065,9 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) relaxedObjVal > localModel_->bS_->objVal_ + localModel_->etol_) || (localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == MibSBilevelFreeSetTypeISICWithNewLLSol && - (ISICGenStrategy == MibSIDICGenStrategyYInt || - ISICGenStrategy == MibSIDICGenStrategyAlways || - (ISICGenStrategy == MibSIDICGenStrategyAlwaysRoot && + (ISICGenStrategy == MibSISICGenStrategyYInt || + ISICGenStrategy == MibSISICGenStrategyAlways || + (ISICGenStrategy == MibSISICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))))){ cutType = MibSIntersectionCutImprovingSolution; numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); From 3289751a898d2ac4197db57f7b5d74b10909df33 Mon Sep 17 00:00:00 2001 From: Ted Ralphs Date: Tue, 5 Nov 2024 10:50:15 +0100 Subject: [PATCH 3/9] Fixing small (but important) typo bug --- src/MibSCutGenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MibSCutGenerator.cpp b/src/MibSCutGenerator.cpp index 473f3819..6378ff88 100644 --- a/src/MibSCutGenerator.cpp +++ b/src/MibSCutGenerator.cpp @@ -6017,7 +6017,7 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) IDICGenStrategy == MibSIDICGenStrategyAlways || (IDICGenStrategy == MibSIDICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))){ - cutType = MibSIntersectionCutImprovingSolution; + cutType = MibSIntersectionCutImprovingDirection; numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); } if (useImprovingSolutionIC == PARAM_ON && @@ -6029,7 +6029,7 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) ISICGenStrategy == MibSISICGenStrategyAlways || (ISICGenStrategy == MibSISICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))))){ - cutType = MibSIntersectionCutImprovingDirection; + cutType = MibSIntersectionCutImprovingSolution; numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); } if (useHypercubeIC == PARAM_ON && haveSecondLevelSol){ From 6c1cc80057998cce960003abedbde1fb4629dd7b Mon Sep 17 00:00:00 2001 From: Ted Ralphs Date: Thu, 7 Nov 2024 16:49:27 +0100 Subject: [PATCH 4/9] Better printing of statistics and some bug fixes --- src/MibSCutGenerator.cpp | 124 ++++++++++++++++++++++++++++++--------- src/MibSModel.cpp | 32 +++++++++- src/MibSModel.hpp | 63 ++++++++++++++++++++ src/MibSParams.cpp | 4 ++ src/MibSSolution.cpp | 87 +++++++++++++++++++++++++-- 5 files changed, 273 insertions(+), 37 deletions(-) diff --git a/src/MibSCutGenerator.cpp b/src/MibSCutGenerator.cpp index 6378ff88..05ebded7 100644 --- a/src/MibSCutGenerator.cpp +++ b/src/MibSCutGenerator.cpp @@ -302,14 +302,13 @@ MibSCutGenerator::feasibilityCuts(BcpsConstraintPool &conPool) = localModel_->MibSPar_->entry(MibSParams::useValFuncCut); if(useIntegerNoGoodCut && !useValFuncCut){ - return bilevelFeasCut1(conPool) ? true : false; + return bilevelFeasCut1(conPool); } else if(!useIntegerNoGoodCut && useValFuncCut){ - return bilevelFeasCut2(conPool) ? true : false; + return bilevelFeasCut2(conPool); } else if(useIntegerNoGoodCut && useValFuncCut){ - return ((bilevelFeasCut1(conPool) ? true : false) || - (bilevelFeasCut2(conPool) ? true : false)); + return (bilevelFeasCut1(conPool) + bilevelFeasCut2(conPool)); } else{ //std::cout << "No MIBS Cuts generated" << std::endl; @@ -5886,6 +5885,8 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) (useLinkingSolutionPool != PARAM_ON && bS->isLowerSolved_ != false && bS->isProvenOptimal_ != false)); + + int returnVal(0); if ((useBoundCut) && (localModel_->boundingPass_ <= 1)){ @@ -5951,27 +5952,43 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) int bendersInterdictionCutType = localModel_->MibSPar_->entry(MibSParams::bendersInterdictionCutType); if(bendersInterdictionCutType == MibSBendersInterdictionCutTypeJustOneCut){ - numCuts += bendersInterdictionOneCut(conPool, + returnVal = bendersInterdictionOneCut(conPool, bS->optLowerSolutionOrd_); } else{ - numCuts += bendersInterdictionMultipleCuts(conPool); - } + returnVal = bendersInterdictionMultipleCuts(conPool); + } + numCuts += returnVal; + localModel_->counterBendersInterdict_ += returnVal; } if (useImprovingSolutionIC == PARAM_ON){ cutType = MibSIntersectionCutImprovingSolution; - numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + returnVal = intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + if (returnVal){ + localModel_->counterXYIntISIC_++; + }else{ + localModel_->counterXYIntISICFail_++; + } + numCuts += returnVal; } if (useImprovingDirectionIC == PARAM_ON){ cutType = MibSIntersectionCutImprovingDirection; - numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + returnVal = intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + if (returnVal){ + localModel_->counterXYIntIDIC_++; + }else{ + localModel_->counterXYIntIDICFail_++; + } + numCuts += returnVal; } if (useHypercubeIC == PARAM_ON){ cutType = MibSIntersectionCutHypercube; - numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + returnVal = intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + localModel_->counterHypercubeIC_ += returnVal; + numCuts += returnVal; } if (useTenderIC == PARAM_ON){ @@ -5985,15 +6002,21 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) } if (useGeneralizedNoGoodCut == PARAM_ON){ - numCuts += generalizedNoGoodCut(conPool); + returnVal = generalizedNoGoodCut(conPool); + localModel_->counterGeneralizedNoGood_ += returnVal; + numCuts += returnVal; } if (useBendersBinaryCut == PARAM_ON && relaxedObjVal > localModel_->bS_->objVal_ + localModel_->etol_){ - numCuts += bendersBinaryCut(conPool); + returnVal = bendersBinaryCut(conPool); + localModel_->counterBendersBinary_ += returnVal; + numCuts += returnVal; } - numCuts += feasibilityCuts(conPool) ? true : false; + returnVal = feasibilityCuts(conPool); + localModel_->counterBendersInterdict_ += returnVal; + numCuts += returnVal; //This return value indicates whether the relaxation needs to be re-solved //and should always be false (see BlisTreeNode.cpp) @@ -6005,12 +6028,13 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) int bendersInterdictionCutType = localModel_->MibSPar_->entry(MibSParams::bendersInterdictionCutType); if(bendersInterdictionCutType == MibSBendersInterdictionCutTypeJustOneCut){ - numCuts += bendersInterdictionOneCut(conPool, - bS->optLowerSolutionOrd_); + returnVal = bendersInterdictionOneCut(conPool, + bS->optLowerSolutionOrd_); + }else{ + returnVal = bendersInterdictionMultipleCuts(conPool); } - else{ - numCuts += bendersInterdictionMultipleCuts(conPool); - } + localModel_->counterBendersInterdict_ += returnVal; + numCuts += returnVal; } if (useImprovingDirectionIC == PARAM_ON && (IDICGenStrategy == MibSIDICGenStrategyLInt || @@ -6018,32 +6042,50 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) (IDICGenStrategy == MibSIDICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))){ cutType = MibSIntersectionCutImprovingDirection; - numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + returnVal = intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + if (returnVal){ + localModel_->counterLIntIDIC_++; + }else{ + localModel_->counterLIntIDICFail_++; + } + numCuts += returnVal; } if (useImprovingSolutionIC == PARAM_ON && ((haveSecondLevelSol && relaxedObjVal > localModel_->bS_->objVal_ + localModel_->etol_) || (localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == - MibSBilevelFreeSetTypeISICWithNewLLSol && + MibSBilevelFreeSetTypeISICWithNewLLSol)) && (ISICGenStrategy == MibSISICGenStrategyLInt || ISICGenStrategy == MibSISICGenStrategyAlways || (ISICGenStrategy == MibSISICGenStrategyAlwaysRoot && - localModel_->activeNode_->getDepth() == 0))))){ + localModel_->activeNode_->getDepth() == 0))){ cutType = MibSIntersectionCutImprovingSolution; - numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + returnVal = intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + if (returnVal){ + localModel_->counterLIntISIC_++; + }else{ + localModel_->counterLIntISICFail_++; + } + numCuts += returnVal; } if (useHypercubeIC == PARAM_ON && haveSecondLevelSol){ cutType = MibSIntersectionCutHypercube; - numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + returnVal = intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + localModel_->counterHypercubeIC_ += returnVal; + numCuts += returnVal; } if (localModel_->allUpperBin_){ //problem with binary UL variables and integer LL variables if (useGeneralizedNoGoodCut == PARAM_ON){ - numCuts += generalizedNoGoodCut(conPool); + returnVal = generalizedNoGoodCut(conPool); + localModel_->counterGeneralizedNoGood_ += returnVal; + numCuts += returnVal; } if (useBendersBinaryCut == PARAM_ON && relaxedObjVal > localModel_->bS_->objVal_ + localModel_->etol_){ - numCuts += bendersBinaryCut(conPool); + returnVal = bendersBinaryCut(conPool); + localModel_->counterBendersBinary_ += returnVal; + numCuts += returnVal; } } @@ -6058,7 +6100,13 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) (IDICGenStrategy == MibSIDICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))){ cutType = MibSIntersectionCutImprovingDirection; - numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + returnVal = intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + if (returnVal){ + localModel_->counterYIntIDIC_++; + }else{ + localModel_->counterYIntIDICFail_++; + } + numCuts += returnVal; } if (useImprovingSolutionIC == PARAM_ON && ((haveSecondLevelSol && @@ -6070,7 +6118,13 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) (ISICGenStrategy == MibSISICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))))){ cutType = MibSIntersectionCutImprovingSolution; - numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + returnVal = intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + if (returnVal){ + localModel_->counterYIntISIC_++; + }else{ + localModel_->counterYIntISICFail_++; + } + numCuts += returnVal; } }else{ if (useImprovingDirectionIC == PARAM_ON && @@ -6078,7 +6132,13 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) (IDICGenStrategy == MibSIDICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))){ cutType = MibSIntersectionCutImprovingDirection; - numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + returnVal = intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + if (returnVal){ + localModel_->counterFracIDIC_++; + }else{ + localModel_->counterFracIDICFail_++; + } + numCuts += returnVal; } if (useImprovingSolutionIC == PARAM_ON && ((haveSecondLevelSol && @@ -6089,7 +6149,13 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) (ISICGenStrategy == MibSIDICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))))){ cutType = MibSIntersectionCutImprovingSolution; - numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + returnVal = intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType); + if (returnVal){ + localModel_->counterFracISIC_++; + }else{ + localModel_->counterFracISICFail_++; + } + numCuts += returnVal; } } diff --git a/src/MibSModel.cpp b/src/MibSModel.cpp index 37cf3233..8326768f 100644 --- a/src/MibSModel.cpp +++ b/src/MibSModel.cpp @@ -143,6 +143,27 @@ MibSModel::initialize() objAlignment_ = 0; counterVF_ = 0; counterUB_ = 0; + counterXYIntIDIC_ = 0; + counterLIntIDIC_ = 0; + counterYIntIDIC_ = 0; + counterFracIDIC_ = 0; + counterXYIntIDICFail_ = 0; + counterLIntIDICFail_ = 0; + counterYIntIDICFail_ = 0; + counterFracIDICFail_ = 0; + counterXYIntISIC_ = 0; + counterLIntISIC_ = 0; + counterYIntISIC_ = 0; + counterFracISIC_ = 0; + counterXYIntISICFail_ = 0; + counterLIntISICFail_ = 0; + counterYIntISICFail_ = 0; + counterFracISICFail_ = 0; + counterBendersInterdict_ = 0; + counterHypercubeIC_ = 0; + counterGeneralizedNoGood_ = 0; + counterBendersBinary_ = 0; + counterIntegerNoGood_ = 0; timerVF_ = 0.0; timerUB_ = 0.0; countIteration_ = 0; @@ -3934,8 +3955,10 @@ MibSModel::adjustParameters() } if (MibSPar_->entry(MibSParams::useImprovingDirectionIC) == PARAM_ON){ defaultCutIsOn = true; - if (MibSPar_->entry(MibSParams::IDICGenStrategy) == MibSIDICGenStrategyNotSet){ - MibSPar()->setEntry(MibSParams::IDICGenStrategy, MibSIDICGenStrategyXYInt); + if (MibSPar_->entry(MibSParams::IDICGenStrategy) == + MibSIDICGenStrategyNotSet){ + MibSPar()->setEntry(MibSParams::IDICGenStrategy, + MibSIDICGenStrategyAlways); } } @@ -3948,7 +3971,10 @@ MibSModel::adjustParameters() paramValue = MibSPar_->entry(MibSParams::useImprovingSolutionIC); if (paramValue == PARAM_NOTSET){ - if (lowerRowSignsConsistent_ == false || upperRowSignsConsistent_ == false){ + if (lowerRowSignsConsistent_ == false || upperRowSignsConsistent_ == false || + isPureInteger_ == false || isLowerCoeffInt_ == false || + (MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == + MibSBilevelFreeSetTypeISICWithNewLLSol && isLowerObjInt_ == false)){ MibSPar()->setEntry(MibSParams::useImprovingSolutionIC, PARAM_OFF); }else{ MibSPar()->setEntry(MibSParams::useImprovingSolutionIC, PARAM_ON); diff --git a/src/MibSModel.hpp b/src/MibSModel.hpp index 6e764a4b..51067e0f 100644 --- a/src/MibSModel.hpp +++ b/src/MibSModel.hpp @@ -114,6 +114,69 @@ class MibSModel : public BlisModel { /** Number of (UB) solved **/ int counterUB_; + /** Number of IDICs generated when solution is fully integer **/ + int counterXYIntIDIC_; + + /** Number of IDICs generated when linking variables are integer **/ + int counterLIntIDIC_; + + /** Number of IDICs generated when lower-level is integer **/ + int counterYIntIDIC_; + + /** Number of IDICs generated when solutions is fractional **/ + int counterFracIDIC_; + + /** Number of IDIC fails when solution is fully integer **/ + int counterXYIntIDICFail_; + + /** Number of IDIC fails when linking variables are integer **/ + int counterLIntIDICFail_; + + /** Number of IDIC fails when lower-level is integer **/ + int counterYIntIDICFail_; + + /** Number of IDIC fails when solutions is fractional **/ + int counterFracIDICFail_; + + /** Number of ISICs generated when solution is fully integer **/ + int counterXYIntISIC_; + + /** Number of ISICs generated when linking variables are integer **/ + int counterLIntISIC_; + + /** Number of ISICs generated when lower-level is integer **/ + int counterYIntISIC_; + + /** Number of ISICs generated when solutions is fractional **/ + int counterFracISIC_; + + /** Number of ISIC fails when solution is fully integer **/ + int counterXYIntISICFail_; + + /** Number of ISIC fails when linking variables are integer **/ + int counterLIntISICFail_; + + /** Number of ISIC fails when lower-level is integer **/ + int counterYIntISICFail_; + + /** Number of ISIC fails when solutions is fractional**/ + int counterFracISICFail_; + + /** Number of Benders Interdiction cuts generated **/ + int counterBendersInterdict_; + + /** Number of Hypercube Intersection cuts generated **/ + int counterHypercubeIC_; + + /** Number of Generalized No Good cuts generated **/ + int counterGeneralizedNoGood_; + + /** Number of Benders Binary cuts generated **/ + int counterBendersBinary_; + + /** Number of Integer No Good cuts generated **/ + int counterIntegerNoGood_; + /** Time for solving (VF) **/ double timerVF_; diff --git a/src/MibSParams.cpp b/src/MibSParams.cpp index be07edf3..4c5359ae 100644 --- a/src/MibSParams.cpp +++ b/src/MibSParams.cpp @@ -385,8 +385,12 @@ MibSParams::setDefaultEntries() { setEntry(useImprovingSolutionIC, PARAM_NOTSET); + setEntry(ISICGenStrategy, MibSISICGenStrategyNotSet); + setEntry(useImprovingDirectionIC, PARAM_NOTSET); + setEntry(IDICGenStrategy, MibSIDICGenStrategyNotSet); + setEntry(useHypercubeIC, PARAM_NOTSET); setEntry(useTenderIC, PARAM_NOTSET); diff --git a/src/MibSSolution.cpp b/src/MibSSolution.cpp index 5914462d..fceb914e 100644 --- a/src/MibSSolution.cpp +++ b/src/MibSSolution.cpp @@ -166,11 +166,88 @@ MibSSolution::print(std::ostream& os) const } } - if(&os == &std::cout){ - std::cout << "Number of problems (VF) solved = " << localModel_->counterVF_ << std::endl; - std::cout << "Number of problems (UB) solved = " << localModel_->counterUB_ << std::endl; - std::cout << "Time for solving problem (VF) = " << localModel_->timerVF_ << std::endl; - std::cout << "Time for solving problem (UB) = " << localModel_->timerUB_ << std::endl; + int useBendersInterdictionCut = + localModel_->MibSPar_->entry(MibSParams::useBendersInterdictionCut); + int useImprovingSolutionIC = + localModel_->MibSPar_->entry(MibSParams::useImprovingSolutionIC); + int useImprovingDirectionIC = + localModel_->MibSPar_->entry(MibSParams::useImprovingDirectionIC); + int useHypercubeIC = + localModel_->MibSPar_->entry(MibSParams::useHypercubeIC); + int useGeneralizedNoGoodCut = + localModel_->MibSPar_->entry(MibSParams::useGeneralizedNoGoodCut); + int useBendersBinaryCut + = localModel_->MibSPar_->entry(MibSParams::useBendersBinaryCut); + int useIntegerNoGoodCut + = localModel_->MibSPar_->entry(MibSParams::useIntegerNoGoodCut); + + os << "Number of problems (VF) solved = " << localModel_->counterVF_ + << std::endl + << "Number of problems (UB) solved = " << localModel_->counterUB_ + << std::endl + << "Time for solving problem (VF) = " << localModel_->timerVF_ + << std::endl + << "Time for solving problem (UB) = " << localModel_->timerUB_ + << std::endl; + if (useBendersInterdictionCut){ + os << "Number of Benders Interdiction Cuts Generated: " + << localModel_->counterBendersInterdict_ << std::endl; + } + if (useHypercubeIC){ + os << "Number of Hypercube Intersection Cuts Generated: " + << localModel_->counterHypercubeIC_ << std::endl; + } + if (useGeneralizedNoGoodCut){ + os << "Number of Generalized No Good Cuts Generated: " + << localModel_->counterGeneralizedNoGood_ << std::endl; + } + if (useBendersBinaryCut){ + os << "Number of Benders Binary Cuts Generated: " + << localModel_->counterBendersBinary_ << std::endl; + } + if (useIntegerNoGoodCut){ + os << "Number of Integer No Good Cuts Generated: " + << localModel_->counterIntegerNoGood_ << std::endl; + } + if (useImprovingDirectionIC){ + os << "Number of IDICs Generated:" << std::endl + << " Full Int IDIC: " << localModel_->counterXYIntIDIC_ + << std::endl + << " Linking Int IDIC: " << localModel_->counterLIntIDIC_ + << std::endl + << " Second-level Int IDIC: " << localModel_->counterYIntIDIC_ + << std::endl + << " Fractional IDIC: " << localModel_->counterFracIDIC_ + << std::endl + << "Number of IDIC Generation Failures:" << std::endl + << " Full Int IDIC (Fail): " << localModel_->counterXYIntIDICFail_ + << std::endl + << " Linking Int IDIC (Fail): " << localModel_->counterLIntIDICFail_ + << std::endl + << " Second-level Int IDIC (Fail): " << localModel_->counterYIntIDICFail_ + << std::endl + << " Fractional IDIC (Fail): " << localModel_->counterFracIDICFail_ + << std::endl; + } + if (useImprovingSolutionIC){ + os << "Number of ISICs Generated:" << std::endl + << " Full Int ISIC: " << localModel_->counterXYIntISIC_ + << std::endl + << " Linking Int ISIC: " << localModel_->counterLIntISIC_ + << std::endl + << " Second-level Int ISIC: " << localModel_->counterYIntISIC_ + << std::endl + << " Fractional: " << localModel_->counterFracISIC_ + << std::endl + << "Number of ISIC Generation Failures:" << std::endl + << " Full Int ISIC (Fail): " << localModel_->counterXYIntISICFail_ + << std::endl + << " Linking Int ISIC (Fail): " << localModel_->counterLIntISICFail_ + << std::endl + << " Second-level Int ISIC (Fail): " << localModel_->counterYIntISICFail_ + << std::endl + << " Fractional ISIC (Fail): " << localModel_->counterFracISICFail_ + << std::endl; } } From 64a332de5cdf8f0a83b40ab935c57c8557a8d1a5 Mon Sep 17 00:00:00 2001 From: Ted Ralphs Date: Tue, 12 Nov 2024 23:29:10 +0100 Subject: [PATCH 5/9] Fixing small bug that prevented Type 1 ISICs from being generated when linking variables are not integer --- src/MibSBilevel.cpp | 4 ++-- src/MibSCutGenerator.cpp | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/MibSBilevel.cpp b/src/MibSBilevel.cpp index 64af56d1..a83d1103 100644 --- a/src/MibSBilevel.cpp +++ b/src/MibSBilevel.cpp @@ -65,7 +65,7 @@ MibSBilevel::createBilevel(CoinPackedVector* sol, bool solveSecondLevelWhenXVarsInt(model_->MibSPar_->entry (MibSParams::solveSecondLevelWhenXVarsInt) == PARAM_ON); bool solveSecondLevelWhenYVarsInt(model_->MibSPar_->entry - (MibSParams::solveSecondLevelWhenXVarsInt) == PARAM_ON); + (MibSParams::solveSecondLevelWhenYVarsInt) == PARAM_ON); bool solveSecondLevelWhenLVarsInt(model_->MibSPar_->entry (MibSParams::solveSecondLevelWhenLVarsInt) == PARAM_ON); bool solveSecondLevelWhenLVarsFixed(model_->MibSPar_->entry @@ -250,7 +250,7 @@ MibSBilevel::createBilevel(CoinPackedVector* sol, (solveSecondLevelWhenYVarsInt && isLowerIntegral_) || (solveSecondLevelWhenLVarsInt && isLinkVarsIntegral_) || (solveSecondLevelWhenLVarsFixed && isLinkVarsFixed_ )))){ - storeSol = checkBilevelFeasibility(mibs->isRoot_); + storeSol = checkBilevelFeasibility(mibs->isRoot_); } } diff --git a/src/MibSCutGenerator.cpp b/src/MibSCutGenerator.cpp index 05ebded7..60f2d70f 100644 --- a/src/MibSCutGenerator.cpp +++ b/src/MibSCutGenerator.cpp @@ -5880,9 +5880,11 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) localModel_->getLowerObjSense()); bool haveSecondLevelSol = ((useLinkingSolutionPool == PARAM_ON && + bS->isLinkVarsIntegral_ && bS->tagInSeenLinkingPool_ != MibSLinkingPoolTagIsNotSet && bS->tagInSeenLinkingPool_ != MibSLinkingPoolTagLowerIsInfeasible) || - (useLinkingSolutionPool != PARAM_ON && + ((useLinkingSolutionPool != PARAM_ON || + !bS->isLinkVarsIntegral_) && bS->isLowerSolved_ != false && bS->isProvenOptimal_ != false)); From 40cb40582f1be3607d336d391d900bef9af96426 Mon Sep 17 00:00:00 2001 From: Ted Ralphs Date: Sun, 17 Nov 2024 22:53:02 +0100 Subject: [PATCH 6/9] Small change to defaults --- src/MibSModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MibSModel.cpp b/src/MibSModel.cpp index 8326768f..4b5bab5b 100644 --- a/src/MibSModel.cpp +++ b/src/MibSModel.cpp @@ -3999,7 +3999,7 @@ MibSModel::adjustParameters() if (MibSPar_->entry(MibSParams::useImprovingSolutionIC) == PARAM_ON){ switch (MibSPar_->entry(MibSParams::ISICGenStrategy)) { case MibSISICGenStrategyNotSet: - MibSPar()->setEntry(MibSParams::ISICGenStrategy, MibSISICGenStrategyXYInt); + MibSPar()->setEntry(MibSParams::ISICGenStrategy, MibSISICGenStrategyLInt); case MibSISICGenStrategyXYInt: MibSPar()->setEntry(MibSParams::solveSecondLevelWhenXYVarsInt, 1); break; From 8518b880dd3bc0eddd95725a90e1b911a2c8a6a2 Mon Sep 17 00:00:00 2001 From: Ted Ralphs Date: Mon, 18 Nov 2024 13:59:10 +0100 Subject: [PATCH 7/9] Adding one more cut generation option --- src/MibSConstants.hpp | 4 +++- src/MibSModel.cpp | 12 ++++++++++++ src/MibSSolution.cpp | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/MibSConstants.hpp b/src/MibSConstants.hpp index fce58d31..6436a87c 100644 --- a/src/MibSConstants.hpp +++ b/src/MibSConstants.hpp @@ -104,7 +104,8 @@ enum MibSIDICGenStrategy{ MibSIDICGenStrategyAlwaysRoot, MibSIDICGenStrategyXYInt, MibSIDICGenStrategyLInt, - MibSIDICGenStrategyYInt + MibSIDICGenStrategyYInt, + MibSIDICGenStrategyYLInt }; //############################################################################# @@ -116,6 +117,7 @@ enum MibSISICGenStrategy{ MibSISICGenStrategyXYInt, MibSISICGenStrategyLInt, MibSISICGenStrategyYInt, + MibSISICGenStrategyYLInt, }; //############################################################################# diff --git a/src/MibSModel.cpp b/src/MibSModel.cpp index 4b5bab5b..01a60695 100644 --- a/src/MibSModel.cpp +++ b/src/MibSModel.cpp @@ -4009,6 +4009,10 @@ MibSModel::adjustParameters() case MibSISICGenStrategyYInt: MibSPar()->setEntry(MibSParams::solveSecondLevelWhenYVarsInt, 1); break; + case MibSISICGenStrategyYLInt: + MibSPar()->setEntry(MibSParams::solveSecondLevelWhenYVarsInt, 1); + MibSPar()->setEntry(MibSParams::solveSecondLevelWhenLVarsInt, 1); + break; case MibSISICGenStrategyAlways: MibSPar()->setEntry(MibSParams::solveSecondLevelEveryIteration, 1); break; @@ -4220,6 +4224,10 @@ MibSModel::printProblemInfo(){ std::cout << "ISICs will be used to separate solutions " << "with integer lower-level variables." << std::endl; break; + case MibSISICGenStrategyYLInt: + std::cout << "ISICs will be used to separate solutions " + << "with integer linking or lower-level variables." << std::endl; + break; case MibSISICGenStrategyXYInt: std::cout << "ISICs will be used to separate only solutions " << "that are fully integer." << std::endl; @@ -4247,6 +4255,10 @@ MibSModel::printProblemInfo(){ std::cout << "IDICs will be used to separate solutions " << "with integer lower-level variables." << std::endl; break; + case MibSIDICGenStrategyYLInt: + std::cout << "IDICs will be used to separate solutions " + << "with integer linking or lower-level variables." << std::endl; + break; case MibSIDICGenStrategyXYInt: std::cout << "IDICs will be used to separate only solutions " << "that are fully integer." << std::endl; diff --git a/src/MibSSolution.cpp b/src/MibSSolution.cpp index fceb914e..2ad7a540 100644 --- a/src/MibSSolution.cpp +++ b/src/MibSSolution.cpp @@ -237,7 +237,7 @@ MibSSolution::print(std::ostream& os) const << std::endl << " Second-level Int ISIC: " << localModel_->counterYIntISIC_ << std::endl - << " Fractional: " << localModel_->counterFracISIC_ + << " Fractional ISIC: " << localModel_->counterFracISIC_ << std::endl << "Number of ISIC Generation Failures:" << std::endl << " Full Int ISIC (Fail): " << localModel_->counterXYIntISICFail_ From 0b5f6a4b839fa8baa6ad7feaf1227c564864ac9e Mon Sep 17 00:00:00 2001 From: Ted Ralphs Date: Mon, 18 Nov 2024 15:31:38 +0100 Subject: [PATCH 8/9] Oops, forgot this --- src/MibSCutGenerator.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/MibSCutGenerator.cpp b/src/MibSCutGenerator.cpp index 60f2d70f..5fd3968d 100644 --- a/src/MibSCutGenerator.cpp +++ b/src/MibSCutGenerator.cpp @@ -6040,6 +6040,7 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) } if (useImprovingDirectionIC == PARAM_ON && (IDICGenStrategy == MibSIDICGenStrategyLInt || + IDICGenStrategy == MibSIDICGenStrategyYLInt || IDICGenStrategy == MibSIDICGenStrategyAlways || (IDICGenStrategy == MibSIDICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))){ @@ -6058,6 +6059,7 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) (localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == MibSBilevelFreeSetTypeISICWithNewLLSol)) && (ISICGenStrategy == MibSISICGenStrategyLInt || + ISICGenStrategy == MibSISICGenStrategyYLInt || ISICGenStrategy == MibSISICGenStrategyAlways || (ISICGenStrategy == MibSISICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))){ @@ -6098,6 +6100,7 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) }else if (bS->isLowerIntegral_){ if (useImprovingDirectionIC == PARAM_ON && (IDICGenStrategy == MibSIDICGenStrategyYInt || + IDICGenStrategy == MibSIDICGenStrategyYLInt || IDICGenStrategy == MibSIDICGenStrategyAlways || (IDICGenStrategy == MibSIDICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))){ @@ -6116,6 +6119,7 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool) (localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeISIC) == MibSBilevelFreeSetTypeISICWithNewLLSol && (ISICGenStrategy == MibSISICGenStrategyYInt || + ISICGenStrategy == MibSISICGenStrategyYLInt || ISICGenStrategy == MibSISICGenStrategyAlways || (ISICGenStrategy == MibSISICGenStrategyAlwaysRoot && localModel_->activeNode_->getDepth() == 0))))){ From fd90955dcda713d0e57ab49f8121934d1cf07092 Mon Sep 17 00:00:00 2001 From: Ted Ralphs Date: Wed, 20 Nov 2024 10:13:35 +0100 Subject: [PATCH 9/9] Fixing small bug with default parameter settings --- src/MibSModel.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MibSModel.cpp b/src/MibSModel.cpp index 01a60695..22c464b9 100644 --- a/src/MibSModel.cpp +++ b/src/MibSModel.cpp @@ -4000,12 +4000,12 @@ MibSModel::adjustParameters() switch (MibSPar_->entry(MibSParams::ISICGenStrategy)) { case MibSISICGenStrategyNotSet: MibSPar()->setEntry(MibSParams::ISICGenStrategy, MibSISICGenStrategyLInt); - case MibSISICGenStrategyXYInt: - MibSPar()->setEntry(MibSParams::solveSecondLevelWhenXYVarsInt, 1); - break; case MibSISICGenStrategyLInt: MibSPar()->setEntry(MibSParams::solveSecondLevelWhenLVarsInt, 1); break; + case MibSISICGenStrategyXYInt: + MibSPar()->setEntry(MibSParams::solveSecondLevelWhenXYVarsInt, 1); + break; case MibSISICGenStrategyYInt: MibSPar()->setEntry(MibSParams::solveSecondLevelWhenYVarsInt, 1); break;