//############################################################################# bfSol* MibSHeuristic::getBilevelSolution(const double * sol, double origLower) { /* Find a bilevel feasible solution by solving the LL problem for a fixed UL solution, given by the UL portion of sol */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); OsiSolverInterface * lSolver = model->bS_->setUpModel(oSolver, true, sol); //double uObjSense(model->getSolver()->getObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double etol(etol_); int tCols(uCols + lCols); int i(0); if(0){ lSolver->writeLp("bilevelsolver"); std::cout << "Original Lower-level Solution Value: " << origLower << std::endl; for(i = 0; i < lCols; i++){ std::cout << "lowsol[" << i << "]: " << sol[lColIndices[i]] << std::endl; } } if(0){ dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("max_active_nodes", 1); } lSolver->branchAndBound(); if(lSolver->isProvenOptimal()){ double objVal(0.0); double lowerObj(lSolver->getObjValue()); double * colsol = new double[tCols]; for(i = 0; i < uCols; i++){ colsol[uColIndices[i]] = sol[uColIndices[i]]; } if(0){ std::cout << "candidate lower solution value: " << origLower << std::endl; std::cout << "actual lower solution value: " << lowerObj << std::endl; } if(fabs(origLower - lowerObj) < etol){ //original solution was bilevel feasible if(0) std::cout << "Original solution was bilevel feasible:" << std::endl; for(i = 0; i < lCols; i++){ if(0){ std::cout << "lowerportion[" << i << "]: " << sol[lColIndices[i]] << std::endl; } colsol[lColIndices[i]] = sol[lColIndices[i]]; } } else{ if(0){ std::cout << "Not bilevel feasible." << std::endl; } for(i = 0; i < lCols; i++){ if(0){ std::cout << "newportion[" << i << "]: " << lSolver->getColSolution()[i] << std::endl; } colsol[lColIndices[i]] = lSolver->getColSolution()[i]; } } for(i = 0; i < tCols; i++) objVal += colsol[i] * oSolver->getObjCoefficients()[i]; bfSol * bfsol = new bfSol(objVal, colsol); delete lSolver; return bfsol; } else{ delete lSolver; return NULL; } }
//############################################################################# void MibSHeuristic::lowerObjHeuristic() { /* optimize wrt to lower-level objective over current feasible lp feasible region */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); //OsiSolverInterface * hSolver = new OsiCbcSolverInterface(); OsiSolverInterface* hSolver = new OsiSymSolverInterface(); double objSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); //int tCols(lCols + uCols); int tCols(oSolver->getNumCols()); //assert(tCols == oSolver->getNumCols()); hSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); int j(0); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) hSolver->setInteger(j); } double * nObjCoeffs = new double[tCols]; int i(0), index(0); CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < lCols; i++){ index = lColIndices[i]; nObjCoeffs[index] = lObjCoeffs[i]; } //MibS objective sense is the opposite of OSI's! hSolver->setObjSense(objSense); hSolver->setObjective(nObjCoeffs); //double cutoff(model->getCutoff()); double cutoff(model->getKnowledgeBroker()->getIncumbentValue()); if(model->getNumSolutions()){ CoinPackedVector objCon; //double rhs(cutoff * objSense); //double smlTol(1.0); double rhs(cutoff); for(i = 0; i < tCols; i++){ objCon.insert(i, oSolver->getObjCoefficients()[i] * oSolver->getObjSense()); } hSolver->addRow(objCon, - hSolver->getInfinity(), rhs); } if(0) hSolver->writeLp("lobjheurstic"); if(0){ dynamic_cast<OsiCbcSolverInterface *> (hSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("max_active_nodes", 1); } hSolver->branchAndBound(); if(hSolver->isProvenOptimal()){ double upperObjVal(0.0); /*****************NEW ******************/ MibSSolution *mibSol = NULL; OsiSolverInterface * lSolver = model->bS_->setUpModel(hSolver, true); if(0){ lSolver->writeLp("tmp"); } if(0){ dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("max_active_nodes", 1); } lSolver->branchAndBound(); if (lSolver->isProvenOptimal()){ const double * sol = hSolver->getColSolution(); double objVal(lSolver->getObjValue() * objSense); double etol(etol_); double lowerObj = getLowerObj(sol, objSense); double * optUpperSolutionOrd = new double[uCols]; double * optLowerSolutionOrd = new double[lCols]; CoinZeroN(optUpperSolutionOrd, uCols); CoinZeroN(optLowerSolutionOrd, lCols); if(fabs(objVal - lowerObj) < etol){ /** Current solution is bilevel feasible **/ for(i = 0; i < tCols; i++) upperObjVal += hSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i]; mibSol = new MibSSolution(hSolver->getNumCols(), hSolver->getColSolution(), upperObjVal, model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } else{ /* solution is not bilevel feasible, create one that is */ const double * uSol = hSolver->getColSolution(); const double * lSol = lSolver->getColSolution(); int numElements(hSolver->getNumCols()); int i(0), pos(0), index(0); double * lpSolution = new double[numElements]; double upperObj(0.0); //FIXME: problem is still here. indices may be wrong. //also is all this necessary, or can we just paste together uSol and lSol? //this may be an old comment for(i = 0; i < numElements; i++){ pos = model->bS_->binarySearch(0, lCols - 1, i, lColIndices); if(pos < 0){ pos = model->bS_->binarySearch(0, uCols - 1, i, uColIndices); if (pos >= 0){ optUpperSolutionOrd[pos] = uSol[i]; } } else{ optLowerSolutionOrd[pos] = lSol[pos]; } } for(i = 0; i < uCols; i++){ index = uColIndices[i]; lpSolution[index] = optUpperSolutionOrd[i]; upperObj += optUpperSolutionOrd[i] * oSolver->getObjCoefficients()[index]; } for(i = 0; i < lCols; i++){ index = lColIndices[i]; lpSolution[index] = optLowerSolutionOrd[i]; upperObj += optLowerSolutionOrd[i] * oSolver->getObjCoefficients()[index]; } if(model->checkUpperFeasibility(lpSolution)){ mibSol = new MibSSolution(hSolver->getNumCols(), lpSolution, upperObj * oSolver->getObjSense(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } delete [] lpSolution; } } delete lSolver; } delete hSolver; }
//############################################################################# mcSol MibSHeuristic::solveSubproblem(double beta) { /* optimize wrt to weighted upper-level objective over current feasible lp feasible region */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); //OsiSolverInterface * sSolver = new OsiCbcSolverInterface(); OsiSolverInterface* sSolver = new OsiSymSolverInterface(); //sSolver = oSolver->clone(); //OsiSolverInterface * sSolver = tmpSolver; //OsiSolverInterface * tmpSolver = new OsiSolverInterface(oSolver); double uObjSense(oSolver->getObjSense()); double lObjSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); const double * uObjCoeffs = oSolver->getObjCoefficients(); double etol(etol_); int tCols(uCols + lCols); assert(tCols == oSolver->getNumCols()); sSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); int j(0); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) sSolver->setInteger(j); } double * nObjCoeffs = new double[tCols]; int i(0), index(0); CoinZeroN(nObjCoeffs, tCols); /* Multiply the UL columns of the UL objective by beta */ for(i = 0; i < uCols; i++){ index = uColIndices[i]; if(fabs(uObjCoeffs[index]) > etol) nObjCoeffs[index] = beta * uObjCoeffs[index] * uObjSense; else nObjCoeffs[index] = 0.0; } /* Multiply the LL columns of the UL objective by beta */ for(i = 0; i < lCols; i++){ index = lColIndices[i]; if(fabs(uObjCoeffs[index]) > etol) nObjCoeffs[index] = beta* uObjCoeffs[index] * uObjSense; else nObjCoeffs[index] = 0.0; } /* Add the LL columns of the LL objective multiplied by (1 - beta) */ for(i = 0; i < lCols; i++){ index = lColIndices[i]; if(fabs(lObjCoeffs[i]) > etol) nObjCoeffs[index] += (1 - beta) * lObjCoeffs[i] * lObjSense; } sSolver->setObjective(nObjCoeffs); //int i(0); if(0){ for(i = 0; i < sSolver->getNumCols(); i++){ std::cout << "betaobj " << sSolver->getObjCoefficients()[i] << std::endl; } } if(0){ sSolver->writeLp("afterbeta"); //sSolver->writeMps("afterbeta"); } if(0){ for(i = 0; i < sSolver->getNumCols(); i++){ std::cout << "obj " << sSolver->getObjCoefficients()[i] << std::endl; std::cout << "upper " << sSolver->getColUpper()[i] << std::endl; std::cout << "lower " << sSolver->getColLower()[i] << std::endl; } } if(0){ dynamic_cast<OsiCbcSolverInterface *> (sSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("max_active_nodes", 1); } //dynamic_cast<OsiSymSolverInterface *> (sSolver)->branchAndBound(); sSolver->branchAndBound(); if(sSolver->isProvenOptimal()){ if(0){ std::cout << "writing lp file." << std::endl; sSolver->writeLp("afterbeta"); //sSolver->writeMps("afterbeta"); } double upperObjVal(0.0); double lowerObjVal(0.0); for(i = 0; i < tCols; i++){ upperObjVal += sSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i]; if(0){ std::cout << "sSolver->getColSolution()[" << i << "] :" << sSolver->getColSolution()[i] << std::endl; } } lowerObjVal = getLowerObj(sSolver->getColSolution(), lObjSense); if(beta == 1.0){ /* fix upper-level objective to current value and reoptimize wrt to lower-level objective */ //OsiSolverInterface * nSolver = new OsiCbcSolverInterface(); OsiSolverInterface * nSolver = new OsiSymSolverInterface(); nSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) nSolver->setInteger(j); } CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < lCols; i++){ index = lColIndices[i]; nObjCoeffs[index] = lObjCoeffs[i] * lObjSense; } nSolver->setObjective(nObjCoeffs); CoinPackedVector objCon; for(i = 0; i < tCols; i++){ objCon.insert(i, uObjCoeffs[i] * uObjSense); } nSolver->addRow(objCon, upperObjVal, upperObjVal); nSolver->writeLp("beta1"); if(0){ dynamic_cast<OsiCbcSolverInterface *> (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("max_active_nodes", 1); } nSolver->branchAndBound(); double * colsol = new double[tCols]; if(nSolver->isProvenOptimal()){ lowerObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } else{ //just take the current solution lowerObjVal = sSolver->getObjValue(); CoinCopyN(sSolver->getColSolution(), tCols, colsol); } delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; delete nSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } else if(beta == 0.0){ /* fix lower-level objective to current value and reoptimize wrt to upper-level objective */ //OsiSolverInterface * nSolver = new OsiCbcSolverInterface(); OsiSolverInterface * nSolver = new OsiSymSolverInterface(); nSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) nSolver->setInteger(j); } CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < tCols; i++) nObjCoeffs[i] = uObjCoeffs[i] * uObjSense; nSolver->setObjective(nObjCoeffs); CoinPackedVector objCon; for(i = 0; i < lCols; i++){ index = lColIndices[i]; objCon.insert(index, lObjCoeffs[i] * lObjSense); } nSolver->addRow(objCon, lowerObjVal, lowerObjVal); if(0){ dynamic_cast<OsiCbcSolverInterface *> (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("max_active_nodes", 1); } if(0) nSolver->writeLp("nSolver"); nSolver->branchAndBound(); double * colsol = new double[tCols]; if(nSolver->isProvenOptimal()){ upperObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } else{ upperObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; delete nSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } else{ //no optimality cut needed here. all solutions are supported. double * colsol = new double[tCols]; CoinCopyN(sSolver->getColSolution(), tCols, colsol); delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } } else{ //FIXME:SHOULD JUST TAKE THIS OUT. DELETE sSolver and remove it from above nObjCoeffs = 0; delete[] nObjCoeffs; delete sSolver; std::cout << "Subproblem is not proven optimal." << std::endl; //return NULL; //abort(); } }
//############################################################################# void MibSHeuristic::objCutHeuristic() { /* Solve the LP relaxation with the new constraint d^2 y <= d^y* */ MibSModel * model = MibSModel_; //OsiSolverInterface * oSolver = model->origLpSolver_; OsiSolverInterface * oSolver = model->getSolver(); //OsiSolverInterface * hSolver = new OsiCbcSolverInterface(); OsiSolverInterface * hSolver = new OsiSymSolverInterface(); double objSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int tCols(lCols + uCols); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); hSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); int j(0); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) hSolver->setInteger(j); } double * optLowerSolutionOrd = model->bS_->optLowerSolutionOrd_; CoinPackedVector objCon; int i(0), index(0); double rhs(0.0); for(i = 0; i < lCols; i++){ index = lColIndices[i]; objCon.insert(index, lObjCoeffs[i] * objSense); //should this be ordered? and should lObjCoeffs by at index? //rhs += optLowerSolutionOrd_[i] * lObjCoeffs[i] * objSense; rhs += optLowerSolutionOrd[i] * lObjCoeffs[i] * objSense; } //Hmm, I think this was wrong before...? // hSolver->addRow(objCon, - hSolver->getInfinity(), rhs); hSolver->addRow(objCon, rhs, hSolver->getInfinity()); /* optimize w.r.t. to the UL objective with the new row */ if(0){ dynamic_cast<OsiCbcSolverInterface *> (hSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("max_active_nodes", 1); } hSolver->branchAndBound(); if(0) hSolver->writeLp("objcutheuristic"); if(hSolver->isProvenOptimal()){ MibSSolution *mibSol = NULL; OsiSolverInterface * lSolver = model->bS_->setUpModel(hSolver, true); if(0){ dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("max_active_nodes", 1); } lSolver->branchAndBound(); const double * sol = hSolver->getColSolution(); double objVal(lSolver->getObjValue() * objSense); double etol(etol_); double lowerObj = getLowerObj(sol, objSense); double * optUpperSolutionOrd = new double[uCols]; double * optLowerSolutionOrd = new double[lCols]; CoinZeroN(optUpperSolutionOrd, uCols); CoinZeroN(optLowerSolutionOrd, lCols); if(fabs(objVal - lowerObj) < etol){ /** Current solution is bilevel feasible **/ mibSol = new MibSSolution(hSolver->getNumCols(), hSolver->getColSolution(), hSolver->getObjValue(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } else{ /* solution is not bilevel feasible, create one that is */ const double * uSol = hSolver->getColSolution(); const double * lSol = lSolver->getColSolution(); //int numElements(lSolver->getNumCols()); int numElements(hSolver->getNumCols()); int i(0), pos(0), index(0); double * lpSolution = new double[numElements]; double upperObj(0.0); //FIXME: problem is still here. indices may be wrong. //also is all this necessary, or can we just paste together uSol and lSol? for(i = 0; i < numElements; i++){ //index = indices[i]; pos = model->bS_->binarySearch(0, lCols - 1, i, lColIndices); if(pos < 0){ pos = model->bS_->binarySearch(0, uCols - 1, i, uColIndices); //optUpperSolutionOrd[pos] = values[i]; //optUpperSolutionOrd[pos] = uSol[pos]; if (pos >= 0){ optUpperSolutionOrd[pos] = uSol[i]; } } else{ //optLowerSolutionOrd[pos] = lSol[i]; optLowerSolutionOrd[pos] = lSol[pos]; } } for(i = 0; i < uCols; i++){ index = uColIndices[i]; lpSolution[index] = optUpperSolutionOrd[i]; upperObj += optUpperSolutionOrd[i] * hSolver->getObjCoefficients()[index]; } for(i = 0; i < lCols; i++){ index = lColIndices[i]; lpSolution[index] = optLowerSolutionOrd[i]; upperObj += optLowerSolutionOrd[i] * hSolver->getObjCoefficients()[index]; } if(model->checkUpperFeasibility(lpSolution)){ mibSol = new MibSSolution(hSolver->getNumCols(), lpSolution, upperObj * hSolver->getObjSense(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } delete [] lpSolution; } delete lSolver; } delete hSolver; }
//############################################################################# void MibSBilevel::checkBilevelFeasiblity(bool isRoot) { int cutStrategy = model_->MibSPar_->entry(MibSParams::cutStrategy); bool warmStartLL = model_->MibSPar_->entry(MibSParams::warmStartLL); int maxThreadsLL = model_->MibSPar_->entry(MibSParams::maxThreadsLL); int whichCutsLL = model_->MibSPar_->entry(MibSParams::whichCutsLL); int probType = model_->MibSPar_->entry(MibSParams::bilevelProblemType); std::string feasCheckSolver = model_->MibSPar_->entry(MibSParams::feasCheckSolver); if (warmStartLL && (feasCheckSolver == "SYMPHONY") && solver_){ solver_ = setUpModel(model_->getSolver(), false); }else{ if (solver_){ delete solver_; } solver_ = setUpModel(model_->getSolver(), true); } OsiSolverInterface *lSolver = solver_; //CoinWarmStart * ws = getWarmStart(); //if (ws != NULL){ // lSolver->setWarmStart(ws); //} //delete ws; if(1) lSolver->writeLp("lowerlevel"); if (feasCheckSolver == "Cbc"){ dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); }else if (feasCheckSolver == "SYMPHONY"){ //dynamic_cast<OsiSymSolverInterface *> // (lSolver)->setSymParam("prep_level", -1); sym_environment *env = dynamic_cast<OsiSymSolverInterface *> (lSolver)->getSymphonyEnvironment(); if (warmStartLL){ sym_set_int_param(env, "keep_warm_start", TRUE); if (probType == 1){ //Interdiction sym_set_int_param(env, "should_use_rel_br", FALSE); sym_set_int_param(env, "use_hot_starts", FALSE); sym_set_int_param(env, "should_warmstart_node", TRUE); sym_set_int_param(env, "sensitivity_analysis", TRUE); sym_set_int_param(env, "sensitivity_bounds", TRUE); sym_set_int_param(env, "set_obj_upper_lim", FALSE); } } //Always uncomment for debugging!! sym_set_int_param(env, "do_primal_heuristic", FALSE); sym_set_int_param(env, "verbosity", -2); sym_set_int_param(env, "prep_level", -1); sym_set_int_param(env, "max_active_nodes", maxThreadsLL); sym_set_int_param(env, "tighten_root_bounds", FALSE); sym_set_int_param(env, "max_sp_size", 100); sym_set_int_param(env, "do_reduced_cost_fixing", FALSE); if (whichCutsLL == 0){ sym_set_int_param(env, "generate_cgl_cuts", FALSE); }else{ sym_set_int_param(env, "generate_cgl_gomory_cuts", GENERATE_DEFAULT); } if (whichCutsLL == 1){ sym_set_int_param(env, "generate_cgl_knapsack_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_probing_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_clique_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_twomir_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_flowcover_cuts", DO_NOT_GENERATE); } }else if (feasCheckSolver == "CPLEX"){ #ifdef USE_CPLEX lSolver->setHintParam(OsiDoReducePrint); lSolver->messageHandler()->setLogLevel(0); CPXENVptr cpxEnv = dynamic_cast<OsiCpxSolverInterface*>(lSolver)->getEnvironmentPtr(); assert(cpxEnv); CPXsetintparam(cpxEnv, CPX_PARAM_SCRIND, CPX_OFF); CPXsetintparam(cpxEnv, CPX_PARAM_THREADS, maxThreadsLL); #endif } if (warmStartLL && feasCheckSolver == "SYMPHONY"){ lSolver->resolve(); setWarmStart(lSolver->getWarmStart()); }else{ lSolver->branchAndBound(); } const double * sol = model_->solver()->getColSolution(); double objVal(lSolver->getObjValue() * model_->getLowerObjSense()); MibSTreeNode * node = static_cast<MibSTreeNode *>(model_->activeNode_); MibSTreeNode * parent = static_cast<MibSTreeNode *>(model_->activeNode_->getParent()); if((!node->isBoundSet()) && (node->getIndex() != 0)){ double parentBound = parent->getLowerUB(); node->setLowerUB(parentBound); node->setIsBoundSet(true); } if(objVal > node->getLowerUB()){ node->setLowerUB(objVal); node->setIsBoundSet(true); } double etol(model_->etol_); double lowerObj = getLowerObj(sol, model_->getLowerObjSense()); int lN(model_->lowerDim_); // lower-level dimension int uN(model_->upperDim_); // lower-level dimension if(!optLowerSolution_) optLowerSolution_ = new double[lN]; if(!optLowerSolutionOrd_) optLowerSolutionOrd_ = new double[lN]; CoinZeroN(optLowerSolution_, lN); CoinZeroN(optLowerSolutionOrd_, lN); int * lowerColInd = model_->getLowerColInd(); int * upperColInd = model_->getUpperColInd(); int index(0); if(0){ std::cout << "objVal: " << objVal << std::endl; std::cout << "lowerObj: " << lowerObj << std::endl; } if(fabs(objVal - lowerObj) < etol){ /** Current solution is bilevel feasible **/ const double * values = lSolver->getColSolution(); int lN(model_->getLowerDim()); int i(0); // May want to take out this update and keep current - both optimal // changed this 7/1 to allow for continuous vars /* for(i = 0; i < lN; i++){ lowerSolution_[i] = (double) floor(values[i] + 0.5); } */ for(i = 0; i < lN; i++){ if(lSolver->isInteger(i)) lowerSolution_[i] = (double) floor(values[i] + 0.5); else lowerSolution_[i] = (double) values[i]; } isBilevelFeasible_ = true; useBilevelBranching_ = false; }else if (lSolver->isProvenOptimal()){ /** Current solution is not bilevel feasible, but we may still have a solution **/ //std::cout << "Solution is not bilevel feasible." << std::endl; const double * values = lSolver->getColSolution(); int lN(model_->getLowerDim()); int i(0); //added this 7/1 to store y* for val func cut for(i = 0; i < lN; i++){ if(lSolver->isInteger(i)) optLowerSolution_[i] = (double) floor(values[i] + 0.5); else optLowerSolution_[i] = (double) values[i]; } int numCols = model_->solver()->getNumCols(); int pos(0); #if 1 for(i = 0; i < numCols; i++){ if ((pos = model_->bS_->binarySearch(0, lN - 1, i, lowerColInd)) >= 0){ optLowerSolutionOrd_[pos] = optLowerSolution_[pos]; } } #else double upperObj(0); double * newSolution = new double[numCols]; const double * upperObjCoeffs = model_->solver()->getObjCoefficients(); for(i = 0; i < numCols; i++){ pos = model_->bS_->binarySearch(0, lN - 1, i, lowerColInd); if(pos < 0){ pos = model_->bS_->binarySearch(0, uN - 1, i, upperColInd); newSolution[i] = sol[i]; } else{ newSolution[i] = optLowerSolution_[pos]; optLowerSolutionOrd_[pos] = optLowerSolution_[pos]; } upperObj += newSolution[i] * upperObjCoeffs[i]; } if(model_->checkUpperFeasibility(newSolution)){ MibSSolution *mibsSol = new MibSSolution(numCols, newSolution, upperObj, model_); model_->storeSolution(BlisSolutionTypeHeuristic, mibsSol); } delete [] newSolution; #endif /* run a heuristic to find a better feasible solution */ heuristic_->findHeuristicSolutions(); isBilevelFeasible_ = false; if(cutStrategy != 1) useBilevelBranching_ = true; } //delete lSolver; }