void* problem_convert_to_osi(Problem *p) { int i; double rowLb, rowUb; OsiSolverInterface *solver = new OsiClpSolverInterface(); CoinBuild cb; solver->setIntParam(OsiNameDiscipline, 2); solver->messageHandler()->setLogLevel(0); solver->setHintParam(OsiDoReducePrint,true,OsiHintTry); for(i = 0; i < p->numCols; i++) { solver->addCol(0, NULL, NULL, p->colLb[i], p->colUb[i], p->objCoef[i]); solver->setColName(i, p->colName[i]); if(p->colType[i] == CONTINUOUS) solver->setContinuous(i); else solver->setInteger(i); } for(i = 0; i < p->numRows; i++) { switch(p->rowSense[i]) { case 'E': rowLb = p->rhs[i]; rowUb = p->rhs[i]; break; case 'L': rowLb = -p->infty; rowUb = p->rhs[i]; break; case 'G': rowLb = p->rhs[i]; rowUb = p->infty; break; default: fprintf(stderr, "Error: invalid type of constraint!\n"); exit(EXIT_FAILURE); } cb.addRow(p->rowNElements[i], p->idxsByRow[i], p->coefsByRow[i], rowLb, rowUb); } solver->addRows(cb); for(i = 0; i < p->numRows; i++) solver->setRowName(i, p->rowName[i]); return solver; }
int pushCbcOsiLogLevel (CoinParam *param) { assert (param != 0) ; CbcOsiParam *osiParam = dynamic_cast<CbcOsiParam *>(param) ; assert (osiParam != 0) ; OsiSolverInterface *osi = osiParam->obj() ; assert(osi != 0) ; int lvl = param->intVal() ; /* Setup to return nonfatal/fatal error (1/-1) by default, so that all we need to do is correct to 0 (no error) if we're successful. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } /* Now try to do the right thing with a hint. Harder to say -- assume that log level 1 is `normal'. */ OsiHintStrength strength ; bool sense ; if (lvl < 1) { strength = OsiHintDo ; sense = true ; } else if (lvl == 1) { strength = OsiHintIgnore ; sense = true ; } else if (lvl == 2) { strength = OsiHintTry ; sense = false ; } else { strength = OsiHintDo ; sense = false ; } bool setOK = osi->setHintParam(OsiDoReducePrint, sense, strength) ; /* Recover the message handler and set the log level directly. */ CoinMessageHandler *hndl = osi->messageHandler() ; assert (hndl != 0) ; hndl->setLogLevel(lvl) ; if (setOK) { return (0) ; } else { return (retval) ; } }
ILPSolverCbc::ILPSolverCbc() { // CbcModel assumes ownership over solver and deletes it in its destructor. OsiSolverInterface* solver = new OsiClpSolverInterface(); // Output should come from CBC, not from CBCs solver. solver->messageHandler()->setLogLevel(0); solver->setHintParam(OsiDoReducePrint, 1); d_model.assignSolver(solver, true); set_default_parameters(this); }
OsiSolverInterface *setupSolvers () { /* Populate the vector of OsiSolverInterface objects. */ # ifdef COIN_HAS_CLP solvers["clp"] = new OsiClpSolverInterface ; # endif # ifdef COIN_HAS_CPX solvers["cpx"] = new OsiCpxSolverInterface ; # endif # ifdef COIN_HAS_DYLP solvers["dylp"] = new OsiDylpSolverInterface ; # endif # ifdef COIN_HAS_GLPK solvers["glpk"] = new OsiGlpkSolverInterface ; # endif # ifdef COIN_HAS_MSK solvers["msk"] = new OsiMskSolverInterface ; # endif # ifdef COIN_HAS_SPX solvers["spx"] = new OsiSpxSolverInterface ; # endif /* Set the standard default values in each solver. */ for (solverMapIter_t solverIter = solvers.begin() ; solverIter != solvers.end() ; solverIter++) { OsiSolverInterface *osi = solverIter->second ; osi->messageHandler()->setLogLevel(0) ; CbcOsiParamUtils::setOsiSolverInterfaceDefaults(osi) ; } /* If we don't have a default solver, we're deeply confused. */ OsiSolverInterface *dflt_solver = solvers[CBC_DEFAULT_SOLVER] ; if (dflt_solver) { std::cout << "Default solver is " << CBC_DEFAULT_SOLVER << std::endl ; } else { std::cerr << "No solvers!" << std::endl ; } return (dflt_solver) ; }
/** Returns a feasible solution to the MINLP * The heuristic constructs a MIP based approximating all univariate functions appearing in nonlinear constraints * The linear approximation is obtained by adding inner chords linking pairs of points until covering the range of each variable **/ int HeuristicInnerApproximation::solution(double &solutionValue, double *betterSolution) { if(model_->getNodeCount() || model_->getCurrentPassNumber() > 1) return 0; if ((model_->getNodeCount()%howOften_)!=0||model_->getCurrentPassNumber()>1) return 0; int returnCode = 0; // 0 means it didn't find a feasible solution Bonmin::OsiTMINLPInterface * nlp = NULL; if(setup_->getAlgorithm() == Bonmin::B_BB) nlp = dynamic_cast<Bonmin::OsiTMINLPInterface *>(model_->solver()->clone()); else nlp = dynamic_cast<Bonmin::OsiTMINLPInterface *>(setup_->nonlinearSolver()->clone()); Bonmin::TMINLP2TNLP* minlp = nlp->problem(); // set tolerances //double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); int numberColumns; int numberRows; int nnz_jac_g; int nnz_h_lag; Ipopt::TNLP::IndexStyleEnum index_style; minlp->get_nlp_info(numberColumns, numberRows, nnz_jac_g, nnz_h_lag, index_style); //const Bonmin::TMINLP::VariableType* variableType = minlp->var_types(); const double* x_sol = minlp->x_sol(); double* newSolution = new double [numberColumns]; memcpy(newSolution,x_sol,numberColumns*sizeof(double)); double* new_g_sol = new double [numberRows]; bool feasible = true; // load the problem to OSI #ifdef DEBUG_BON_HEURISTIC std::cout << "Loading the problem to OSI\n"; #endif OsiSolverInterface *si = mip_->solver(); // the MIP solver bool delete_si = false; if(si == NULL) { si = new OsiClpSolverInterface; mip_->setLpSolver(si); delete_si = true; } CoinMessageHandler * handler = model_->messageHandler()->clone(); si->passInMessageHandler(handler); si->messageHandler()->setLogLevel(2); #ifdef DEBUG_BON_HEURISTIC std::cout << "Loading problem into si\n"; #endif extractInnerApproximation(*nlp, *si, newSolution, true); // Call the function construncting the inner approximation description #ifdef DEBUG_BON_HEURISTIC std::cout << "problem loaded\n"; std::cout << "**** Running optimization ****\n"; #endif mip_->optimize(DBL_MAX, 2, time_limit_); // Optimize the MIP #ifdef DEBUG_BON_HEURISTIC std::cout << "Optimization finished\n"; #endif if(mip_->getLastSolution()) { // if the MIP solver returns a feasible solution const double* solution = mip_->getLastSolution(); std::copy(solution, solution + numberColumns, newSolution); } else feasible = false; if(delete_si) { delete si; } delete handler; #if 0 // Set to 1 if you need to test the feasibility of the returned solution const double* x_l = minlp->x_l(); const double* x_u = minlp->x_u(); const double* g_l = minlp->g_l(); const double* g_u = minlp->g_u(); double primalTolerance = 1.0e-6; Bonmin::vector<Ipopt::TNLP::LinearityType> constTypes(numberRows); minlp->get_constraints_linearity(numberRows, constTypes()); feasible = true; for (int iColumn=0;iColumn<numberColumns;iColumn++) { double value=newSolution[iColumn]; if(value - x_l[iColumn] < -1e-8|| value - x_u[iColumn] > 1e-8) { std::cout<<"Solution found infeasible because: "<<std::endl; std::cout<<"x_l["<<iColumn<<"]= "<<x_l[iColumn]<<" " <<"x_sol["<<iColumn<<"]= "<<value<<" " <<"x_u["<<iColumn<<"]= "<<x_u[iColumn]<<std::endl; feasible = false; break; } } minlp->eval_g(numberColumns, newSolution, true, numberRows, new_g_sol); for(int iRow=0; iRow<numberRows; iRow++) { if(new_g_sol[iRow]<g_l[iRow]-primalTolerance || new_g_sol[iRow]>g_u[iRow]+primalTolerance) { std::cout<<"It should be infeasible because: "<<std::endl; std::cout<<"g_l["<<iRow<<"]= "<<g_l[iRow]<<" " <<"g_sol["<<iRow<<"]= "<<new_g_sol[iRow]<<" " <<"g_u["<<iRow<<"]= "<<g_u[iRow]<<std::endl; std::cout<<"primalTolerance= "<<primalTolerance<<std::endl; if(constTypes[iRow] == Ipopt::TNLP::NON_LINEAR) std::cout<<"nonLinear constraint number "<<iRow<<std::endl; feasible = false; } } std::cout<<"Every thing is feasible"<<std::endl; #endif if(feasible) { double newSolutionValue; minlp->eval_f(numberColumns, newSolution, true, newSolutionValue); if(newSolutionValue < solutionValue) { memcpy(betterSolution,newSolution,numberColumns*sizeof(double)); solutionValue = newSolutionValue; returnCode = 1; } } delete [] newSolution; delete [] new_g_sol; delete nlp; #ifdef DEBUG_BON_HEURISTIC std::cout<<"Inner approximation returnCode = "<<returnCode<<std::endl; #endif return returnCode; }
void CglLandP::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo info ) { if ((info.pass == 0) && !info.inTree) { numrows_ = si.getNumRows(); } // scanExtraCuts(cs, si.getColSolution()); Parameters params = params_; params.rhsWeight = numrows_ + 2; handler_->message(CUT_GAP, messages_)<<info.pass<<si.getObjValue() <<CoinMessageEol; if (info.inTree) //put lower pivot limit { params.pivotLimit = std::min(params.pivotLimit, params.pivotLimitInTree); params.countMistakenRc = true; } if (params.timeLimit < 0) { params.pivotLimit = 0; } assert(si.basisIsAvailable()); #ifdef APPEND_ROW OsiSolverInterface * t_si = si.clone(); if (params.modularize) { int new_idx = si.getNumCols(); int v_idx[1] = {new_idx}; double v_val[1] = {-1}; CoinPackedVector v(1, v_idx, v_val, false); t_si->addCol(CoinPackedVector(), 0, 1, 0); t_si->setInteger(new_idx); t_si->addRow(v,0, 0); t_si->resolve(); } #else const OsiSolverInterface * t_si = &si; #endif cached_.getData(*t_si); CglLandPSimplex landpSi(*t_si, cached_, params, validator_); if (params.generateExtraCuts == CglLandP::AllViolatedMigs) { landpSi.genThisBasisMigs(cached_, params); } landpSi.setLogLevel(handler_->logLevel()); int nCut = 0; std::vector<int> indices; getSortedFractionalIndices(indices,cached_, params); #ifndef NDEBUG int numrows = si.getNumRows(); #endif #ifdef DO_STAT //Get informations on current optimum { OsiSolverInterface * gapTester = si.clone(); gapTester->resolve(); roundsStats_.analyseOptimalBasis(gapTester,info.pass, numrows_); delete gapTester; } #endif params_.timeLimit += CoinCpuTime(); CoinRelFltEq eq(1e-04); for (unsigned int i = 0; i < indices.size() && nCut < params.maxCutPerRound && nCut < cached_.nBasics_ ; i++) { //Check for time limit int iRow = indices[i]; assert(iRow < numrows); OsiRowCut cut; int code=1; OsiSolverInterface * ncSi = NULL; if (params.pivotLimit != 0) { ncSi = t_si->clone(); landpSi.setSi(ncSi); ncSi->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); ncSi->messageHandler()->setLogLevel(0); } int generated = 0; if (params.pivotLimit == 0) { generated = landpSi.generateMig(iRow, cut, params); } else { generated = landpSi.optimize(iRow, cut, cached_, params); if (params.generateExtraCuts == CglLandP::AllViolatedMigs) { landpSi.genThisBasisMigs(cached_, params); } landpSi.resetSolver(cached_.basis_); } code = 0; if (generated) code = validator_(cut, cached_.colsol_, si, params, originalColLower_, originalColUpper_); if (!generated || code) { if (params.pivotLimit !=0) { handler_->message(LAP_CUT_FAILED_DO_MIG, messages_)<<validator_.failureString(code)<<CoinMessageEol; landpSi.freeSi(); OsiSolverInterface * ncSi = t_si->clone(); landpSi.setSi(ncSi); params.pivotLimit = 0; if (landpSi.optimize(iRow, cut, cached_, params)) { code = validator_(cut, cached_.colsol_, si, params, originalColLower_, originalColUpper_); } params.pivotLimit = params_.pivotLimit; } } if (params.pivotLimit != 0) { landpSi.freeSi(); } if (code) { handler_->message(CUT_REJECTED, messages_)<< validator_.failureString(code)<<CoinMessageEol; } else { if (canLift_) { cut.setGloballyValid(true); } cs.insertIfNotDuplicate(cut, eq); //cs.insert(cut); { //std::cout<<"Violation "<<cut.violated(cached_.colsol_)<<std::endl; nCut++; } } } Cuts& extra = landpSi.extraCuts(); for (int i = 0 ; i < cached_.nNonBasics_; i++) { OsiRowCut * cut = extra.rowCut(i); if (cut == NULL) continue; int code = validator_(*cut, cached_.colsol_, si, params, originalColLower_, originalColUpper_); if (code) { handler_->message(LAP_CUT_FAILED_DO_MIG, messages_) <<validator_.failureString(code)<<CoinMessageEol; } else { cs.insertIfNotDuplicate(*cut, eq); { nCut++; } } delete cut; } landpSi.outPivInfo(nCut); params_.timeLimit -= CoinCpuTime(); cached_.clean(); #ifdef APPEND_ROW assert(t_si != &si); delete t_si; #endif }
/** Returns a feasible solution to the MINLP * The heuristic constructs a MIP based approximating all univariate functions appearing in nonlinear constraints * The linear approximation is obtained by adding inner chords linking pairs of points until covering the range of each variable **/ int HeuristicInnerApproximation::solution(double &solutionValue, double *betterSolution) { if(model_->getNodeCount() || model_->getCurrentPassNumber() > 1) return 0; if ((model_->getNodeCount()%howOften_)!=0||model_->getCurrentPassNumber()>1) return 0; int returnCode = 0; // 0 means it didn't find a feasible solution OsiTMINLPInterface * nlp = NULL; if(setup_->getAlgorithm() == B_BB) nlp = dynamic_cast<OsiTMINLPInterface *>(model_->solver()->clone()); else nlp = dynamic_cast<OsiTMINLPInterface *>(setup_->nonlinearSolver()->clone()); TMINLP2TNLP* minlp = nlp->problem(); // set tolerances double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); int numberColumns; int numberRows; int nnz_jac_g; int nnz_h_lag; Ipopt::TNLP::IndexStyleEnum index_style; minlp->get_nlp_info(numberColumns, numberRows, nnz_jac_g, nnz_h_lag, index_style); const Bonmin::TMINLP::VariableType* variableType = minlp->var_types(); const double* x_sol = minlp->x_sol(); double* newSolution = new double [numberColumns]; memcpy(newSolution,x_sol,numberColumns*sizeof(double)); double* new_g_sol = new double [numberRows]; bool feasible = true; // load the problem to OSI #ifdef DEBUG_BON_HEURISTIC cout << "Loading the problem to OSI\n"; #endif OsiSolverInterface *si = mip_->solver(); // the MIP solver bool delete_si = false; if(si == NULL) { si = new OsiClpSolverInterface; mip_->setLpSolver(si); delete_si = true; } CoinMessageHandler * handler = model_->messageHandler()->clone(); si->passInMessageHandler(handler); si->messageHandler()->setLogLevel(2); #ifdef DEBUG_BON_HEURISTIC cout << "Loading problem into si\n"; #endif extractInnerApproximation(*nlp, *si, newSolution, true); // Call the function construncting the inner approximation description #ifdef DEBUG_BON_HEURISTIC cout << "problem loaded\n"; cout << "**** Running optimization ****\n"; #endif mip_->optimize(DBL_MAX, 2, 180); // Optimize the MIP #ifdef DEBUG_BON_HEURISTIC cout << "Optimization finished\n"; #endif if(mip_->getLastSolution()) { // if the MIP solver returns a feasible solution const double* solution = mip_->getLastSolution(); for (size_t iLCol=0;iLCol<numberColumns;iLCol++) { newSolution[iLCol] = solution[iLCol]; } } else feasible = false; if(delete_si) { delete si; } delete handler; const double* x_l = minlp->x_l(); const double* x_u = minlp->x_u(); const double* g_l = minlp->g_l(); const double* g_u = minlp->g_u(); double primalTolerance = 1.0e-6; #if 1 if(feasible ) { std::vector<double> memLow(numberColumns); std::vector<double> memUpp(numberColumns); std::copy(minlp->x_l(), minlp->x_l() + numberColumns, memLow.begin()); std::copy(minlp->x_u(), minlp->x_u() + numberColumns, memUpp.begin()); // fix the integer variables and solve the NLP for (int iColumn=0;iColumn<numberColumns;iColumn++) { if (variableType[iColumn] != Bonmin::TMINLP::CONTINUOUS) { double value=floor(newSolution[iColumn]+0.5); minlp->SetVariableUpperBound(iColumn, value); minlp->SetVariableLowerBound(iColumn, value); } } if(feasible) { nlp->initialSolve(); if(minlp->optimization_status() != Ipopt::SUCCESS) { feasible = false; } memcpy(newSolution,minlp->x_sol(),numberColumns*sizeof(double)); } for (int iColumn=0;iColumn<numberColumns;iColumn++) { if (variableType[iColumn] != Bonmin::TMINLP::CONTINUOUS) { minlp->SetVariableUpperBound(iColumn, memUpp[iColumn]); minlp->SetVariableLowerBound(iColumn, memLow[iColumn]); } } } #endif #endif if(feasible) { double newSolutionValue; minlp->eval_f(numberColumns, newSolution, true, newSolutionValue); if(newSolutionValue < solutionValue) { memcpy(betterSolution,newSolution,numberColumns*sizeof(double)); solutionValue = newSolutionValue; returnCode = 1; } } delete [] newSolution; delete [] new_g_sol; delete nlp; #ifdef DEBUG_BON_HEURISTIC std::cout<<"Inner approximation returnCode = "<<returnCode<<std::endl; #endif return returnCode; }
//############################################################################# 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; }
OsiSolverInterface* cpropagation_preprocess(CPropagation *cp, int nindexes[]) { if(cp->varsToFix == 0) { /* printf("There are no variables to remove from the problem!\n"); */ return NULL; /* returns a pointer to original solver */ } const double *colLb = problem_vars_lower_bound(cp->problem), *colUb = problem_vars_upper_bound(cp->problem); const double *objCoef = problem_vars_obj_coefs(cp->problem); const char *ctype = problem_vars_type(cp->problem); double sumFixedObj = 0.0; /* stores the sum of objective coefficients of all variables fixed to 1 */ OsiSolverInterface *preProcSolver = new OsiClpSolverInterface(); preProcSolver->setIntParam(OsiNameDiscipline, 2); preProcSolver->messageHandler()->setLogLevel(0); preProcSolver->setHintParam(OsiDoReducePrint,true,OsiHintTry); //preProcSolver->setObjName(cp->solver->getObjName()); for(int i = 0, j = 0; i < problem_num_cols(cp->problem); i++) { nindexes[i] = -1; if(cp->isToFix[i] == UNFIXED) { preProcSolver->addCol(0, NULL, NULL, colLb[i], colUb[i], objCoef[i]); preProcSolver->setColName(j, problem_var_name(cp->problem, i)); if(problem_var_type(cp->problem, i) == CONTINUOUS) preProcSolver->setContinuous(j); else preProcSolver->setInteger(j); nindexes[i] = j++; } else if(cp->isToFix[i] == ACTIVATE) sumFixedObj += objCoef[i]; } if(fabs(sumFixedObj) > EPS) { /* adding a variable with cost equals to the sum of all coefficients of variables fixed to 1 */ preProcSolver->addCol(0, NULL, NULL, 1.0, 1.0, sumFixedObj); preProcSolver->setColName(preProcSolver->getNumCols()-1, "sumFixedObj"); preProcSolver->setInteger(preProcSolver->getNumCols()-1); } for(int idxRow = 0; idxRow < problem_num_rows(cp->problem); idxRow++) { const int nElements = problem_row_size(cp->problem, idxRow); const int *idxs = problem_row_idxs(cp->problem, idxRow); const double *coefs = problem_row_coefs(cp->problem, idxRow); vector< int > vidx; vidx.reserve(problem_num_cols(cp->problem)); vector< double > vcoef; vcoef.reserve(problem_num_cols(cp->problem)); double activeCoefs = 0.0; for(int i = 0; i < nElements; i++) { if(cp->isToFix[idxs[i]] == UNFIXED) { assert(nindexes[idxs[i]] >= 0 && nindexes[idxs[i]] < problem_num_cols(cp->problem)); vidx.push_back(nindexes[idxs[i]]); vcoef.push_back(coefs[i]); } else if(cp->isToFix[idxs[i]] == ACTIVATE) activeCoefs += coefs[i]; } if(!vidx.empty()) { double rlb, rub; const char sense = problem_row_sense(cp->problem, idxRow); if(sense == 'E') { rlb = problem_row_rhs(cp->problem, idxRow) - activeCoefs; rub = problem_row_rhs(cp->problem, idxRow) - activeCoefs; } else if(sense == 'L') { rlb = preProcSolver->getInfinity(); rub = problem_row_rhs(cp->problem, idxRow) - activeCoefs; } else if(sense == 'G') { rlb = problem_row_rhs(cp->problem, idxRow) - activeCoefs; rub = preProcSolver->getInfinity(); } else { fprintf(stderr, "Error: invalid type of constraint!\n"); exit(EXIT_FAILURE); } preProcSolver->addRow((int)vcoef.size(), &vidx[0], &vcoef[0], rlb, rub); preProcSolver->setRowName(idxRow, problem_row_name(cp->problem, idxRow)); } } return preProcSolver; }
int doBaCParam (CoinParam *param) { assert (param != 0) ; CbcGenParam *genParam = dynamic_cast<CbcGenParam *>(param) ; assert (genParam != 0) ; CbcGenCtlBlk *ctlBlk = genParam->obj() ; assert (ctlBlk != 0) ; CbcModel *model = ctlBlk->model_ ; assert (model != 0) ; /* Setup to return nonfatal/fatal error (1/-1) by default. */ int retval ; if (CoinParamUtils::isInteractive()) { retval = 1 ; } else { retval = -1 ; } ctlBlk->setBaBStatus(CbcGenCtlBlk::BACAbandon, CbcGenCtlBlk::BACmInvalid, CbcGenCtlBlk::BACwNotStarted, false, 0) ; /* We ain't gonna do squat without a good model. */ if (!ctlBlk->goodModel_) { std::cout << "** Current model not valid!" << std::endl ; return (retval) ; } /* Start the clock ticking. */ double time1 = CoinCpuTime() ; double time2 ; /* Create a clone of the model which we can modify with impunity. Extract the underlying solver for convenient access. */ CbcModel babModel(*model) ; OsiSolverInterface *babSolver = babModel.solver() ; assert (babSolver != 0) ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: initial babSolver is " << std::hex << babSolver << std::dec << ", log level " << babSolver->messageHandler()->logLevel() << "." << std::endl ; # endif /* Solve the root relaxation. Bail unless it solves to optimality. */ if (!solveRelaxation(&babModel)) { ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBareRoot) ; return (0) ; } # if COIN_CBC_VERBOSITY > 0 std::cout << "doBaCParam: initial relaxation z = " << babSolver->getObjValue() << "." << std::endl ; # endif /* Are we up for fixing variables based on reduced cost alone? */ if (ctlBlk->djFix_.action_ == true) { reducedCostHack(babSolver, ctlBlk->djFix_.threshold_) ; } /* Time to consider preprocessing. We'll do a bit of setup before getting to the meat of the issue. preIppSolver will hold a clone of the unpreprocessed constraint system. We'll need it when we postprocess. ippSolver holds the preprocessed constraint system. Again, we clone it and give the clone to babModel for B&C. Presumably we need an unmodified copy of the preprocessed system to do postprocessing, but the copy itself is hidden inside the preprocess object. */ OsiSolverInterface *preIppSolver = 0 ; CglPreProcess ippObj ; bool didIPP = false ; int numberChanged = 0 ; int numberOriginalColumns = babSolver->getNumCols() ; CbcGenCtlBlk::IPPControl ippAction = ctlBlk->getIPPAction() ; if (!(ippAction == CbcGenCtlBlk::IPPOff || ippAction == CbcGenCtlBlk::IPPStrategy)) { double timeLeft = babModel.getMaximumSeconds() ; preIppSolver = babSolver->clone() ; OsiSolverInterface *ippSolver ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: clone made prior to IPP is " << std::hex << preIppSolver << std::dec << ", log level " << preIppSolver->messageHandler()->logLevel() << "." << std::endl ; # endif preIppSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ; ippObj.messageHandler()->setLogLevel(babModel.logLevel()) ; CglProbing probingGen ; probingGen.setUsingObjective(true) ; probingGen.setMaxPass(3) ; probingGen.setMaxProbeRoot(preIppSolver->getNumCols()) ; probingGen.setMaxElements(100) ; probingGen.setMaxLookRoot(50) ; probingGen.setRowCuts(3) ; ippObj.addCutGenerator(&probingGen) ; /* For preProcessNonDefault, the 2nd parameter controls the conversion of clique and SOS constraints. 0 does nothing, -1 converts <= to ==, and 2 and 3 form SOS sets under strict and not-so-strict conditions, respectively. */ int convert = 0 ; if (ippAction == CbcGenCtlBlk::IPPEqual) { convert = -1 ; } else if (ippAction == CbcGenCtlBlk::IPPEqualAll) { convert = -2 ; } else if (ippAction == CbcGenCtlBlk::IPPSOS) { convert = 2 ; } else if (ippAction == CbcGenCtlBlk::IPPTrySOS) { convert = 3 ; } ippSolver = ippObj.preProcessNonDefault(*preIppSolver, convert, 10) ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver returned from IPP is " << std::hex << ippSolver << std::dec ; if (ippSolver) { std::cout << ", log level " << ippSolver->messageHandler()->logLevel() ; } std::cout << "." << std::endl ; # endif /* ippSolver == 0 is success of a sort --- integer preprocess has found the problem to be infeasible or unbounded. Need to think about how to indicate status. */ if (!ippSolver) { std::cout << "Integer preprocess says infeasible or unbounded" << std::endl ; delete preIppSolver ; ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPP) ; return (0) ; } # if COIN_CBC_VERBOSITY > 0 else { std::cout << "After integer preprocessing, model has " << ippSolver->getNumRows() << " rows, " << ippSolver->getNumCols() << " columns, and " << ippSolver->getNumElements() << " elements." << std::endl ; } # endif preIppSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; ippSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ; if (ippAction == CbcGenCtlBlk::IPPSave) { ippSolver->writeMps("presolved", "mps", 1.0) ; std::cout << "Integer preprocessed model written to `presolved.mps' " << "as minimisation problem." << std::endl ; } OsiSolverInterface *osiTmp = ippSolver->clone() ; babModel.assignSolver(osiTmp) ; babSolver = babModel.solver() ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: clone of IPP solver passed to babModel is " << std::hex << babSolver << std::dec << ", log level " << babSolver->messageHandler()->logLevel() << "." << std::endl ; # endif if (!solveRelaxation(&babModel)) { delete preIppSolver ; ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwIPPRelax) ; return (0) ; } # if COIN_CBC_VERBOSITY > 0 std::cout << "doBaCParam: presolved relaxation z = " << babSolver->getObjValue() << "." << std::endl ; # endif babModel.setMaximumSeconds(timeLeft - (CoinCpuTime() - time1)) ; didIPP = true ; } /* At this point, babModel and babSolver hold the constraint system we'll use for B&C (either the original system or the preprocessed system) and we have a solution to the lp relaxation. If we're using the COSTSTRATEGY option, set up priorities here and pass them to the babModel. */ if (ctlBlk->priorityAction_ != CbcGenCtlBlk::BPOff) { setupPriorities(&babModel, ctlBlk->priorityAction_) ; } /* Install heuristics and cutting planes. */ installHeuristics(ctlBlk, &babModel) ; installCutGenerators(ctlBlk, &babModel) ; /* Set up status print frequency for babModel. */ if (babModel.getNumCols() > 2000 || babModel.getNumRows() > 1500 || babModel.messageHandler()->logLevel() > 1) babModel.setPrintFrequency(100) ; /* If we've read in a known good solution for debugging, activate the row cut debugger. */ if (ctlBlk->debugSol_.values_) { if (ctlBlk->debugSol_.numCols_ == babModel.getNumCols()) { babSolver->activateRowCutDebugger(ctlBlk->debugSol_.values_) ; } else { std::cout << "doBaCParam: debug file has incorrect number of columns." << std::endl ; } } /* Set ratio-based integrality gap, if specified by user. */ if (ctlBlk->setByUser_[CbcCbcParam::GAPRATIO] == true) { double obj = babSolver->getObjValue() ; double gapRatio = babModel.getDblParam(CbcModel::CbcAllowableFractionGap) ; double gap = gapRatio * (1.0e-5 + fabs(obj)) ; babModel.setAllowableGap(gap) ; std::cout << "doBaCParam: Continuous objective = " << obj << ", so allowable gap set to " << gap << std::endl ; } /* A bit of mystery code. As best I can figure, setSpecialOptions(2) suppresses the removal of warm start information when checkSolution runs an lp to check a solution. John's comment, ``probably faster to use a basis to get integer solutions'' makes some sense in this context. Didn't try to track down moreMipOptions just yet. */ babModel.setSpecialOptions(babModel.specialOptions() | 2) ; /* { int ndx = whichParam(MOREMIPOPTIONS,numberParameters,parameters) ; int moreMipOptions = parameters[ndx].intValue() ; if (moreMipOptions >= 0) { printf("more mip options %d\n",moreMipOptions); babModel.setSearchStrategy(moreMipOptions); } } */ /* Begin the final run-up to branch-and-cut. Make sure that objects are set up in the solver. It's possible that whoever loaded the model into the solver also set up objects. But it's also entirely likely that none exist to this point (and interesting to note that IPP doesn't need to know anything about objects). */ setupObjects(babSolver, didIPP, &ippObj) ; /* Set the branching method. We can't do this until we establish objects, because the constructor will set up arrays based on the number of objects, and there's no provision to set this information after creation. Arguably not good --- it'd be nice to set this in the prototype model that's cloned for this routine. In CoinSolve, shadowPriceMode is handled with the TESTOSI option. */ OsiChooseStrong strong(babSolver) ; strong.setNumberBeforeTrusted(babModel.numberBeforeTrust()) ; strong.setNumberStrong(babModel.numberStrong()) ; strong.setShadowPriceMode(ctlBlk->chooseStrong_.shadowPriceMode_) ; CbcBranchDefaultDecision decision ; decision.setChooseMethod(strong) ; babModel.setBranchingMethod(decision) ; /* Here I've deleted a huge block of code that deals with external priorities, branch direction, pseudocosts, and solution. (PRIORITYIN) Also a block of code that generates C++ code. */ /* Set up strategy for branch-and-cut. Note that the integer code supplied to setupPreProcessing is *not* compatible with the IPPAction enum. But at least it's documented. See desiredPreProcess_ in CbcStrategyDefault. `1' is accidentally equivalent to IPPOn. */ if (ippAction == CbcGenCtlBlk::IPPStrategy) { CbcStrategyDefault strategy(true, 5, 5) ; strategy.setupPreProcessing(1) ; babModel.setStrategy(strategy) ; } /* Yes! At long last, we're ready for the big call. Do branch and cut. In general, the solver used to return the solution will not be the solver we passed in, so reset babSolver here. */ int statistics = (ctlBlk->printOpt_ > 0) ? ctlBlk->printOpt_ : 0 ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver at call to branchAndBound is " << std::hex << babModel.solver() << std::dec << ", log level " << babModel.solver()->messageHandler()->logLevel() << "." << std::endl ; # endif babModel.branchAndBound(statistics) ; babSolver = babModel.solver() ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver at return from branchAndBound is " << std::hex << babModel.solver() << std::dec << ", log level " << babModel.solver()->messageHandler()->logLevel() << "." << std::endl ; # endif /* Write out solution to preprocessed model. */ if (ctlBlk->debugCreate_ == "createAfterPre" && babModel.bestSolution()) { CbcGenParamUtils::saveSolution(babSolver, "debug.file") ; } /* Print some information about branch-and-cut. */ # if COIN_CBC_VERBOSITY > 0 std::cout << "Cuts at root node changed objective from " << babModel.getContinuousObjective() << " to " << babModel.rootObjectiveAfterCuts() << std::endl ; for (int iGen = 0 ; iGen < babModel.numberCutGenerators() ; iGen++) { CbcCutGenerator *generator = babModel.cutGenerator(iGen) ; std::cout << generator->cutGeneratorName() << " was tried " << generator->numberTimesEntered() << " times and created " << generator->numberCutsInTotal() << " cuts of which " << generator->numberCutsActive() << " were active after adding rounds of cuts" ; if (generator->timing()) { std::cout << " ( " << generator->timeInCutGenerator() << " seconds)" ; } std::cout << std::endl ; } # endif time2 = CoinCpuTime(); ctlBlk->totalTime_ += time2 - time1; /* If we performed integer preprocessing, time to back it out. */ if (ippAction != CbcGenCtlBlk::IPPOff) { # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver passed to IPP postprocess is " << std::hex << babSolver << std::dec << "." << std::endl ; # endif ippObj.postProcess(*babSolver); babModel.assignSolver(preIppSolver) ; babSolver = babModel.solver() ; # if CBC_TRACK_SOLVERS > 0 std::cout << "doBaCParam: solver in babModel after IPP postprocess is " << std::hex << babSolver << std::dec << "." << std::endl ; # endif } /* Write out postprocessed solution to debug file, if requested. */ if (ctlBlk->debugCreate_ == "create" && babModel.bestSolution()) { CbcGenParamUtils::saveSolution(babSolver, "debug.file") ; } /* If we have a good solution, detach the solver with the answer. Fill in the rest of the status information for the benefit of the wider world. */ bool keepAnswerSolver = false ; OsiSolverInterface *answerSolver = 0 ; if (babModel.bestSolution()) { babModel.setModelOwnsSolver(false) ; keepAnswerSolver = true ; answerSolver = babSolver ; } ctlBlk->setBaBStatus(&babModel, CbcGenCtlBlk::BACwBAC, keepAnswerSolver, answerSolver) ; /* And one last bit of information & statistics. */ ctlBlk->printBaBStatus() ; std::cout << " " ; if (keepAnswerSolver) { std::cout << "objective " << babModel.getObjValue() << "; " ; } std::cout << babModel.getNodeCount() << " nodes and " << babModel.getIterationCount() << " iterations - took " << time2 - time1 << " seconds" << std::endl ; return (0) ; }
int MilpRounding::solution(double &solutionValue, double *betterSolution) { if(model_->getCurrentPassNumber() > 1) return 0; if (model_->currentDepth() > 2 && (model_->getNodeCount()%howOften_)!=0) return 0; int returnCode = 0; // 0 means it didn't find a feasible solution OsiTMINLPInterface * nlp = NULL; if(setup_->getAlgorithm() == B_BB) nlp = dynamic_cast<OsiTMINLPInterface *>(model_->solver()->clone()); else nlp = dynamic_cast<OsiTMINLPInterface *>(setup_->nonlinearSolver()->clone()); TMINLP2TNLP* minlp = nlp->problem(); // set tolerances double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); //double primalTolerance = 1.0e-6; int n; int m; int nnz_jac_g; int nnz_h_lag; Ipopt::TNLP::IndexStyleEnum index_style; minlp->get_nlp_info(n, m, nnz_jac_g, nnz_h_lag, index_style); const Bonmin::TMINLP::VariableType* variableType = minlp->var_types(); const double* x_sol = minlp->x_sol(); const double* g_l = minlp->g_l(); const double* g_u = minlp->g_u(); const double * colsol = model_->solver()->getColSolution(); // Get information about the linear and nonlinear part of the instance TMINLP* tminlp = nlp->model(); vector<Ipopt::TNLP::LinearityType> c_lin(m); tminlp->get_constraints_linearity(m, c_lin()); vector<int> c_idx(m); int n_lin = 0; for (int i=0;i<m;i++) { if (c_lin[i]==Ipopt::TNLP::LINEAR) c_idx[i] = n_lin++; else c_idx[i] = -1; } // Get the structure of the jacobian vector<int> indexRow(nnz_jac_g); vector<int> indexCol(nnz_jac_g); minlp->eval_jac_g(n, x_sol, false, m, nnz_jac_g, indexRow(), indexCol(), 0); // get the jacobian values vector<double> jac_g(nnz_jac_g); minlp->eval_jac_g(n, x_sol, false, m, nnz_jac_g, NULL, NULL, jac_g()); // Sort the matrix to column ordered vector<int> sortedIndex(nnz_jac_g); CoinIotaN(sortedIndex(), nnz_jac_g, 0); MatComp c; c.iRow = indexRow(); c.jCol = indexCol(); std::sort(sortedIndex.begin(), sortedIndex.end(), c); vector<int> row (nnz_jac_g); vector<double> value (nnz_jac_g); vector<int> columnStart(n,0); vector<int> columnLength(n,0); int indexCorrection = (index_style == Ipopt::TNLP::C_STYLE) ? 0 : 1; int iniCol = -1; int nnz = 0; for(int i=0; i<nnz_jac_g; i++) { int thisIndexCol = indexCol[sortedIndex[i]]-indexCorrection; int thisIndexRow = c_idx[indexRow[sortedIndex[i]] - indexCorrection]; if(thisIndexCol != iniCol) { iniCol = thisIndexCol; columnStart[thisIndexCol] = nnz; columnLength[thisIndexCol] = 0; } if(thisIndexRow == -1) continue; columnLength[thisIndexCol]++; row[nnz] = thisIndexRow; value[nnz] = jac_g[i]; nnz++; } // Build the row lower and upper bounds vector<double> newRowLower(n_lin); vector<double> newRowUpper(n_lin); for(int i = 0 ; i < m ; i++){ if(c_idx[i] == -1) continue; newRowLower[c_idx[i]] = g_l[i]; newRowUpper[c_idx[i]] = g_u[i]; } // Get solution array for heuristic solution vector<double> newSolution(n); std::copy(x_sol, x_sol + n, newSolution.begin()); // Define the constraint matrix for MILP CoinPackedMatrix matrix(true,n_lin,n, nnz, value(), row(), columnStart(), columnLength()); // create objective function and columns lower and upper bounds for MILP // and create columns for matrix in MILP //double alpha = 0; double beta = 1; vector<double> objective(n); vector<int> idxIntegers; idxIntegers.reserve(n); for(int i = 0 ; i < n ; i++){ if(variableType[i] != Bonmin::TMINLP::CONTINUOUS){ idxIntegers.push_back(i); objective[i] = beta*(1 - 2*colsol[i]); } } #if 0 // Get dual multipliers and build gradient of the lagrangean const double * duals = nlp->getRowPrice() + 2 *n; vector<double> grad(n, 0); vector<int> indices(n, 0); tminlp->eval_grad_f(n, x_sol, false, grad()); for(int i = 0 ; i < m ; i++){ if(c_lin[i] == Ipopt::TNLP::LINEAR) continue; int nnz; tminlp->eval_grad_gi(n, x_sol, false, i, nnz, indices(), NULL); tminlp->eval_grad_gi(n, x_sol, false, i, nnz, NULL, grad()); for(int k = 0 ; k < nnz ; k++){ objective[indices[k]] += alpha *duals[i] * grad[k]; } } for(int i = 0 ; i < n ; i++){ if(variableType[i] != Bonmin::TMINLP::CONTINUOUS) objective[i] += alpha * grad[i]; //if(fabs(objective[i]) < 1e-4) objective[i] = 0; else objective[i] = 0; } std::copy(objective.begin(), objective.end(), std::ostream_iterator<double>(std::cout, " ")); std::cout<<std::endl; #endif // load the problem to OSI OsiSolverInterface *si = mip_->solver(); assert(si != NULL); CoinMessageHandler * handler = model_->messageHandler()->clone(); si->passInMessageHandler(handler); si->messageHandler()->setLogLevel(1); si->loadProblem(matrix, model_->solver()->getColLower(), model_->solver()->getColUpper(), objective(), newRowLower(), newRowUpper()); si->setInteger(idxIntegers(), static_cast<int>(idxIntegers.size())); si->applyCuts(noGoods); bool hasFractionnal = true; while(hasFractionnal){ mip_->optimize(DBL_MAX, 0, 60); hasFractionnal = false; #if 0 bool feasible = false; if(mip_->getLastSolution()) { const double* solution = mip_->getLastSolution(); std::copy(solution, solution + n, newSolution.begin()); feasible = true; } if(feasible) { // fix the integer variables and solve the NLP // also add no good cut CoinPackedVector v; double lb = 1; for (int iColumn=0;iColumn<n;iColumn++) { if (variableType[iColumn] != Bonmin::TMINLP::CONTINUOUS) { double value=newSolution[iColumn]; if (fabs(floor(value+0.5)-value)>integerTolerance) { #ifdef DEBUG_BON_HEURISTIC_DIVE_MIP cout<<"It should be infeasible because: "<<endl; cout<<"variable "<<iColumn<<" is not integer"<<endl; #endif feasible = false; break; } else { value=floor(newSolution[iColumn]+0.5); if(value > 0.5){ v.insert(iColumn, -1); lb -= value; } minlp->SetVariableUpperBound(iColumn, value); minlp->SetVariableLowerBound(iColumn, value); } } } } #endif } bool feasible = false; if(mip_->getLastSolution()) { const double* solution = mip_->getLastSolution(); std::copy(solution, solution + n, newSolution.begin()); feasible = true; delete handler; } if(feasible) { // fix the integer variables and solve the NLP // also add no good cut CoinPackedVector v; double lb = 1; for (int iColumn=0;iColumn<n;iColumn++) { if (variableType[iColumn] != Bonmin::TMINLP::CONTINUOUS) { double value=newSolution[iColumn]; if (fabs(floor(value+0.5)-value)>integerTolerance) { feasible = false; break; } else { value=floor(newSolution[iColumn]+0.5); if(value > 0.5){ v.insert(iColumn, -1); lb -= value; } minlp->SetVariableUpperBound(iColumn, value); minlp->SetVariableLowerBound(iColumn, value); } } } OsiRowCut c; c.setRow(v); c.setLb(lb); c.setUb(DBL_MAX); noGoods.insert(c); if(feasible) { nlp->initialSolve(); if(minlp->optimization_status() != Ipopt::SUCCESS) { feasible = false; } std::copy(x_sol,x_sol+n, newSolution.begin()); } } if(feasible) { double newSolutionValue; minlp->eval_f(n, newSolution(), true, newSolutionValue); if(newSolutionValue < solutionValue) { std::copy(newSolution.begin(), newSolution.end(), betterSolution); solutionValue = newSolutionValue; returnCode = 1; } } delete nlp; #ifdef DEBUG_BON_HEURISTIC_DIVE_MIP std::cout<<"DiveMIP returnCode = "<<returnCode<<std::endl; #endif return returnCode; }