Skip to content

Commit

Permalink
Adding parameters to allow more fine-grained control of cut generation
Browse files Browse the repository at this point in the history
  • Loading branch information
tkralphs committed Oct 29, 2024
1 parent 4377871 commit e2bca52
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 57 deletions.
18 changes: 13 additions & 5 deletions src/MibSBilevel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -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_);
Expand Down Expand Up @@ -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;
}

Expand Down
22 changes: 22 additions & 0 deletions src/MibSConstants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
67 changes: 52 additions & 15 deletions src/MibSCutGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down
102 changes: 79 additions & 23 deletions src/MibSModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -3958,15 +3961,36 @@ 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.";
std::cout << std::endl;
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) &&
Expand Down Expand Up @@ -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) ==
Expand Down
31 changes: 20 additions & 11 deletions src/MibSParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)));

Expand All @@ -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)));

Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit e2bca52

Please sign in to comment.