Skip to content

Commit

Permalink
Make it possible to separate fractional solutions and add parameter f…
Browse files Browse the repository at this point in the history
…or cut depth
  • Loading branch information
tkralphs authored and yuxies committed Jan 13, 2022
1 parent 6dbbfea commit ea4698f
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 69 deletions.
52 changes: 27 additions & 25 deletions src/MibSBilevel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,16 @@ MibSBilevel::createBilevel(CoinPackedVector* sol,
MibSBranchingStrategy branchPar = static_cast<MibSBranchingStrategy>
(model_->MibSPar_->entry(MibSParams::branchStrategy));

int solveSecondLevelWhenXYVarsInt(model_->MibSPar_->entry
(MibSParams::solveSecondLevelWhenXYVarsInt));
int solveSecondLevelWhenXVarsInt(model_->MibSPar_->entry
(MibSParams::solveSecondLevelWhenXVarsInt));
int solveSecondLevelWhenLVarsInt(model_->MibSPar_->entry
(MibSParams::solveSecondLevelWhenLVarsInt));
int solveSecondLevelWhenLVarsFixed(model_->MibSPar_->entry
(MibSParams::solveSecondLevelWhenLVarsFixed));
bool solveSecondLevelEveryIteration(model_->MibSPar_->entry
(MibSParams::solveSecondLevelEveryIteration) == PARAM_ON);
bool solveSecondLevelWhenXYVarsInt(model_->MibSPar_->entry
(MibSParams::solveSecondLevelWhenXYVarsInt) == PARAM_ON);
bool solveSecondLevelWhenXVarsInt(model_->MibSPar_->entry
(MibSParams::solveSecondLevelWhenXVarsInt) == PARAM_ON);
bool solveSecondLevelWhenLVarsInt(model_->MibSPar_->entry
(MibSParams::solveSecondLevelWhenLVarsInt) == PARAM_ON);
bool solveSecondLevelWhenLVarsFixed(model_->MibSPar_->entry
(MibSParams::solveSecondLevelWhenLVarsFixed) == PARAM_ON);
int cutStrategy(model_->MibSPar_->entry
(MibSParams::cutStrategy));

Expand Down Expand Up @@ -309,24 +311,24 @@ MibSBilevel::createBilevel(CoinPackedVector* sol,

//step 7
if(!shouldPrune_){
if(((tagInSeenLinkingPool_ == MibSLinkingPoolTagLowerIsFeasible)
|| (tagInSeenLinkingPool_ == MibSLinkingPoolTagUBIsSolved)) ||
((!isContainedInLinkingPool_) &&
(((branchPar == MibSBranchingStrategyLinking) &&
(isIntegral_) && (isLinkVarsFixed_)) ||
((branchPar == MibSBranchingStrategyFractional)
&& (isIntegral_)) ||
((solveSecondLevelWhenXYVarsInt == PARAM_ON) && (isIntegral_)) ||
((solveSecondLevelWhenXVarsInt == PARAM_ON) && (isUpperIntegral_)) ||
((solveSecondLevelWhenLVarsInt == PARAM_ON) && (isLinkVarsIntegral_)) ||
((solveSecondLevelWhenLVarsFixed == PARAM_ON) && (isLinkVarsFixed_ ))))){
if((tagInSeenLinkingPool_ == MibSLinkingPoolTagLowerIsFeasible ||
tagInSeenLinkingPool_ == MibSLinkingPoolTagUBIsSolved) ||
(!isContainedInLinkingPool_ &&
((branchPar == MibSBranchingStrategyLinking && isIntegral_ && isLinkVarsFixed_) ||
(branchPar == MibSBranchingStrategyFractional && isIntegral_) ||
(solveSecondLevelEveryIteration) ||
(solveSecondLevelWhenXYVarsInt && isIntegral_) ||
(solveSecondLevelWhenXVarsInt && isUpperIntegral_) ||
(solveSecondLevelWhenLVarsInt && isLinkVarsIntegral_) ||
(solveSecondLevelWhenLVarsFixed && isLinkVarsFixed_ )))){
#ifdef _OPENMPMIBS
storeSol = checkBilevelFeasiblityParallel(mibs->isRoot_);
#else
storeSol = checkBilevelFeasiblity(mibs->isRoot_);
#endif
}
}
}

if(cutStrategy == 1){
useBilevelBranching_ = false;
}
Expand Down Expand Up @@ -576,7 +578,7 @@ MibSBilevel::checkBilevelFeasiblity(bool isRoot)
if(!lSolver->isProvenOptimal()){
LPSolStatus_ = MibSLPSolStatusInfeasible;
isProvenOptimal_ = false;
if(useLinkingSolutionPool){
if(useLinkingSolutionPool && isLinkVarsIntegral_){
//step 10
//Adding x_L to set E
shouldStoreObjValues.push_back(0);
Expand Down Expand Up @@ -606,7 +608,7 @@ MibSBilevel::checkBilevelFeasiblity(bool isRoot)

const double * values = lSolver->getColSolution();

if(useLinkingSolutionPool){
if(useLinkingSolutionPool && isLinkVarsIntegral_){
begPos = i * truncLN;
if(shouldStoreSolution == true){
std::copy(values, values + lN, shouldStoreValuesLowerSol.begin() + begPos);
Expand Down Expand Up @@ -664,14 +666,14 @@ MibSBilevel::checkBilevelFeasiblity(bool isRoot)
}

//step 13
if(((!useLinkingSolutionPool) && (isProvenOptimal_)) ||
if(((!useLinkingSolutionPool || !isLinkVarsIntegral_) && (isProvenOptimal_)) ||
((tagInSeenLinkingPool_ == MibSLinkingPoolTagLowerIsFeasible) ||
(tagInSeenLinkingPool_ == MibSLinkingPoolTagUBIsSolved))){

//double *lowerSol = new double[lN];
//CoinFillN(lowerSol, lN, 0.0);

if(useLinkingSolutionPool){
if(useLinkingSolutionPool && isLinkVarsIntegral_){
//get optimal value of (VF) from solution pool
//model_->it = seenLinkingSolutions.find(linkSol);
//objVal = model_->it->second.lowerObjVal1;
Expand Down Expand Up @@ -978,7 +980,7 @@ MibSBilevel::checkBilevelFeasiblity(bool isRoot)
}
//step 22
//Adding x_L to set E
if(useLinkingSolutionPool){
if(useLinkingSolutionPool && isLinkVarsIntegral_){
addSolutionToSeenLinkingSolutionPool
(MibSLinkingPoolTagUBIsSolved, shouldStoreValuesUBSol,
shouldStoreObjValues);
Expand Down
20 changes: 14 additions & 6 deletions src/MibSCutGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1871,7 +1871,9 @@ MibSCutGenerator::storeBestSolHypercubeIC(const double* lpSol,

startTimeUB = localModel_->broker_->subTreeTimer().getTime();
UBSolver->branchAndBound();
localModel_->timerUB_ += localModel_->broker_->subTreeTimer().getTime() - startTimeUB;
//This time is being double-counted, since it is also included in cut
//generation
//localModel_->timerUB_ += localModel_->broker_->subTreeTimer().getTime() - startTimeUB;
localModel_->counterUB_ ++;

if(feasCheckSolver == "SYMPHONY"){
Expand Down Expand Up @@ -6320,9 +6322,6 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool)
int useIntersectionCutTypeWatermelon =
localModel_->MibSPar_->entry(MibSParams::useTypeWatermelon);

int useIntersectionCutTypeFractionalWatermelon =
localModel_->MibSPar_->entry(MibSParams::useTypeFractionalWatermelon);

int useIntersectionCutTypeHypercubeIC =
localModel_->MibSPar_->entry(MibSParams::useTypeHypercubeIC);

Expand All @@ -6341,6 +6340,9 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool)
bool useIncObjCut
= localModel_->MibSPar_->entry(MibSParams::useIncObjCut);

int useFractionalCuts =
localModel_->MibSPar_->entry(MibSParams::useFractionalCuts);

double relaxedObjVal = localModel_->bS_->getLowerObj(
localModel_->solver()->getColSolution(),
localModel_->getLowerObjSense(), 0);
Expand Down Expand Up @@ -6503,12 +6505,18 @@ MibSCutGenerator::generateConstraints(BcpsConstraintPool &conPool)

return (numCuts ? true : false);

}else {
}else if (useFractionalCuts){

if (useIntersectionCutTypeFractionalWatermelon == PARAM_ON){
if (useIntersectionCutTypeWatermelon == PARAM_ON){
cutType = MibSIntersectionCutTypeWatermelon;
numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType);
}
if (useIntersectionCutTypeIC == PARAM_ON && ((haveSecondLevelSol &&
relaxedObjVal > localModel_->bS_->objValVec_[0] + localModel_->etol_) ||
localModel_->MibSPar_->entry(MibSParams::bilevelFreeSetTypeIC) == 1)){
cutType = MibSIntersectionCutTypeIC;
numCuts += intersectionCuts(conPool, bS->optLowerSolutionOrd_, cutType);
}
}

//delete sol;
Expand Down
39 changes: 11 additions & 28 deletions src/MibSModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,13 @@ MibSModel::initialize()
void
MibSModel::readParameters(const int argnum, const char * const * arglist)
{
//std::cout << "Reading parameters ..." << std::endl;
AlpsPar_->readFromArglist(argnum, arglist);
setBlisParameters();

//std::cout << "Reading parameters ..." << std::endl;
AlpsPar_->readFromArglist(argnum, arglist);
BlisPar_->readFromArglist(argnum, arglist);
MibSPar_->readFromArglist(argnum, arglist);

setBlisParameters();
}

//#############################################################################
Expand Down Expand Up @@ -6805,26 +6806,6 @@ MibSModel::instanceStructure(const CoinPackedMatrix *newMatrix,
defaultCutIsOn = true;
}

//Param: "MibS_useTypeFractionalWatermelon"
paramValue = MibSPar_->entry(MibSParams::useTypeFractionalWatermelon);

if (paramValue == PARAM_NOTSET){
MibSPar()->setEntry(MibSParams::useTypeFractionalWatermelon, PARAM_OFF);
}else if (paramValue == PARAM_ON){
if ((isPureInteger_ == false) || (isLowerCoeffInt_ == false)){
std::cout << "The (fractional) watermelon cut is only valid for pure integer "
<< "problems with integer lower-level constraints matrix.";
std::cout << std::endl;
MibSPar()->setEntry(MibSParams::useTypeFractionalWatermelon, PARAM_OFF);
}
if (isLowerObjInt_ == false){
std::cout << "The (fractional) watermelon cut is only valid for problems "
<< "with integer lower-level objective coefficients.";
std::cout << std::endl;
MibSPar()->setEntry(MibSParams::useTypeFractionalWatermelon, PARAM_OFF);
}
}

//Param: "MibS_useTypeIC"
paramValue = MibSPar_->entry(MibSParams::useTypeIC);

Expand Down Expand Up @@ -6874,7 +6855,7 @@ MibSModel::instanceStructure(const CoinPackedMatrix *newMatrix,
((isPureInteger_ == false) ||
(isUpperCoeffInt_ == false) ||
(isLowerCoeffInt_ == false))){
std::cout << "The pure integer cut is only valid for pure integer"
std::cout << "The integer no-good cut is only valid for pure integer"
<< "problems with integer constraint matrices";
std::cout << std::endl;
MibSPar()->setEntry(MibSParams::usePureIntegerCut, PARAM_OFF);
Expand Down Expand Up @@ -6941,7 +6922,7 @@ MibSModel::instanceStructure(const CoinPackedMatrix *newMatrix,

if (MibSPar_->entry(MibSParams::useTypeIC) == PARAM_ON){
if (MibSPar_->entry(MibSParams::bilevelFreeSetTypeIC) ==
MibSBilevelFreeSetTypeICWithNewLLSol){
MibSBilevelFreeSetTypeICWithLLOptSol){
std::cout << "Intersection cut IC generator (Type I) is on." << std::endl;
}else{
std::cout << "Intersection cut IC generator (Type II) is on." << std::endl;
Expand All @@ -6950,16 +6931,17 @@ MibSModel::instanceStructure(const CoinPackedMatrix *newMatrix,
if (MibSPar_->entry(MibSParams::useTypeWatermelon) == PARAM_ON){
std::cout << "Watermelon IC generator is on." << std::endl;
}
if (MibSPar_->entry(MibSParams::useTypeFractionalWatermelon) == PARAM_ON){
std::cout << "Fractional watermelon IC generator is on." << std::endl;
}
if (MibSPar_->entry(MibSParams::useTypeHypercubeIC) == PARAM_ON){
std::cout << "Hypercube IC generator is on." << std::endl;
}
if (MibSPar_->entry(MibSParams::useFractionalCuts) == 1){
std::cout << "Fractional cuts will be generated.";
}
//}
}

//Setting parameters of solving (VF) and (UB)
int solveSecondLevelEveryIteration(MibSPar_->entry(MibSParams::solveSecondLevelEveryIteration));
int solveSecondLevelWhenXYVarsInt(MibSPar_->entry(MibSParams::solveSecondLevelWhenXYVarsInt));
int solveSecondLevelWhenXVarsInt(MibSPar_->entry(MibSParams::solveSecondLevelWhenXVarsInt));
int solveSecondLevelWhenLVarsInt(MibSPar_->entry(MibSParams::solveSecondLevelWhenLVarsInt));
Expand All @@ -6969,6 +6951,7 @@ MibSModel::instanceStructure(const CoinPackedMatrix *newMatrix,
int computeBestUBWhenLVarsFixed(MibSPar_->entry(MibSParams::computeBestUBWhenLVarsFixed));

if ((solveSecondLevelWhenXYVarsInt == PARAM_NOTSET) &&
(solveSecondLevelEveryIteration == PARAM_NOTSET) &&
(solveSecondLevelWhenXVarsInt == PARAM_NOTSET) &&
(solveSecondLevelWhenLVarsInt == PARAM_NOTSET) &&
(solveSecondLevelWhenLVarsFixed == PARAM_NOTSET) &&
Expand Down
20 changes: 15 additions & 5 deletions src/MibSParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,6 @@ MibSParams::createKeywordList() {
keys_.push_back(make_pair(std::string("MibS_useTypeWatermelon"),
AlpsParameter(AlpsIntPar, useTypeWatermelon)));

keys_.push_back(make_pair(std::string("MibS_useTypeFractionalWatermelon"),
AlpsParameter(AlpsIntPar, useTypeFractionalWatermelon)));

keys_.push_back(make_pair(std::string("MibS_useTypeHypercubeIC"),
AlpsParameter(AlpsIntPar, useTypeHypercubeIC)));

Expand All @@ -179,7 +176,13 @@ MibSParams::createKeywordList() {
keys_.push_back(make_pair(std::string("MibS_bilevelFreeSetTypeIC"),
AlpsParameter(AlpsIntPar, bilevelFreeSetTypeIC)));

keys_.push_back(make_pair(std::string("MibS_useFractionalCuts"),
AlpsParameter(AlpsIntPar, useFractionalCuts)));

//solve lower-level Parameters
keys_.push_back(make_pair(std::string("MibS_solveSecondLevelEveryIteration"),
AlpsParameter(AlpsIntPar, solveSecondLevelEveryIteration)));

keys_.push_back(make_pair(std::string("MibS_solveSecondLevelWhenXYVarsInt"),
AlpsParameter(AlpsIntPar, solveSecondLevelWhenXYVarsInt)));

Expand Down Expand Up @@ -232,6 +235,9 @@ MibSParams::createKeywordList() {
keys_.push_back(make_pair(std::string("MibS_maxActiveNodes"),
AlpsParameter(AlpsIntPar, maxActiveNodes)));

keys_.push_back(make_pair(std::string("MibS_maxCutDepth"),
AlpsParameter(AlpsIntPar, maxCutDepth)));

//parameters for stochastic and SAA
//this parameter should be set to false, when the problem is
//stochastic and A2 is not random.
Expand Down Expand Up @@ -420,16 +426,18 @@ MibSParams::setDefaultEntries() {

setEntry(useTypeWatermelon, PARAM_NOTSET);

setEntry(useTypeFractionalWatermelon, PARAM_NOTSET);

setEntry(useTypeHypercubeIC, PARAM_NOTSET);

setEntry(useTypeTenderIC, PARAM_NOTSET);

setEntry(useTypeHybridIC, PARAM_NOTSET);

setEntry(useFractionalCuts, 0);

setEntry(bilevelFreeSetTypeIC, MibSBilevelFreeSetTypeICNotSet);

setEntry(solveSecondLevelEveryIteration, PARAM_NOTSET);

setEntry(solveSecondLevelWhenXYVarsInt, PARAM_NOTSET);

setEntry(solveSecondLevelWhenXVarsInt, PARAM_NOTSET);
Expand Down Expand Up @@ -462,6 +470,8 @@ MibSParams::setDefaultEntries() {

setEntry(relaxTypeParamBoundCut, MibSRelaxTypeParamBoundCutLP);

setEntry(maxCutDepth, ALPS_INT_MAX);

setEntry(maxActiveNodes, 1);

setEntry(isA2Random, PARAM_NOTSET);
Expand Down
4 changes: 3 additions & 1 deletion src/MibSParams.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,12 @@ class MIBSLIB_EXPORT MibSParams : public AlpsParameterSet {
bendersCutType,
useTypeIC,
useTypeWatermelon,
useTypeFractionalWatermelon,
useTypeHypercubeIC,
useTypeTenderIC,
useTypeHybridIC,
useFractionalCuts,
bilevelFreeSetTypeIC,
solveSecondLevelEveryIteration,
solveSecondLevelWhenXYVarsInt,
solveSecondLevelWhenXVarsInt,
solveSecondLevelWhenLVarsInt,
Expand All @@ -95,6 +96,7 @@ class MIBSLIB_EXPORT MibSParams : public AlpsParameterSet {
boundCutFreq,
boundCutNodeLim,
relaxTypeParamBoundCut,
maxCutDepth,
maxActiveNodes,
isA2Random,
isSMPSFormat,
Expand Down
7 changes: 3 additions & 4 deletions src/MibSTreeNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,6 @@ MibSTreeNode::process(bool isRoot, bool rampUp)
int numAppliedCons = 0;
int cutStrategy;

// Only autmatic stategy has depth limit.
int maxConstraintDepth = 20;

int numPassesLeft = 0;
int bStatus = -1;

Expand Down Expand Up @@ -173,6 +170,8 @@ MibSTreeNode::process(bool isRoot, bool rampUp)
BlisParams * BlisPar = model->BlisPar();

int maxPass = BlisPar->entry(BlisParams::cutPass);
int maxConstraintDepth = mibsModel->MibSPar_->entry(MibSParams::maxCutDepth);

double tailOffTol = BlisPar->entry(BlisParams::tailOff);

MibSBranchingStrategy branchPar = static_cast<MibSBranchingStrategy>
Expand Down Expand Up @@ -244,7 +243,7 @@ MibSTreeNode::process(bool isRoot, bool rampUp)

assert(cutStrategy != BlisCutStrategyNotSet);

if (cutStrategy == BlisCutStrategyNone) {
if (cutStrategy == BlisCutStrategyNone || depth_ > maxConstraintDepth) {
genConsHere = false;
}
else if (cutStrategy == BlisCutStrategyRoot) {
Expand Down

0 comments on commit ea4698f

Please sign in to comment.