bool MILPSolverCLP::solve(const bool & skipPresolve) { if (!solvedYet) { if (skipPresolve) { solvectl->setPresolveType(ClpSolve::presolveOff); } else { solvectl->setPresolveType(ClpSolve::presolveOn); } lp->setSolveOptions(*solvectl); lp->initialSolve(); solvedYet = true; } else { lp->resolve(); } if (!lp->isProvenOptimal()) { return false; } if (!hasIntegerVariables) { return true; } delete milp; milp = 0; //lp->setHintParam(OsiDoReducePrint,true,OsiHintTry); if (!milp) { milp = new CbcModel(*lp); //milp->solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); } CglProbing pg; pg.setUsingObjective(true); pg.setMaxPass(3); pg.setMaxProbe(100); pg.setMaxLook(50); pg.setRowCuts(3); milp->addCutGenerator(&pg,-1); milp->setLogLevel(0); milp->branchAndBound(); return (milp->isProvenOptimal()); }
/** Add milp cut generators according to options.*/ void CouenneSetup::addMilpCutGenerators () { enum extraInfo_ {CUTINFO_NONE, CUTINFO_MIG, CUTINFO_PROBING, CUTINFO_CLIQUE}; // extra data structure to avoid repeated code below struct cutInfo { const char *optname; CglCutGenerator *cglptr; const char *cglId; enum extraInfo_ extraInfo; } cutList [] = { {(const char*)"Gomory_cuts",new CglGomory, (const char*)"Mixed Integer Gomory",CUTINFO_MIG}, {(const char*)"probing_cuts",new CglProbing, (const char*) "Probing", CUTINFO_PROBING}, {(const char*)"mir_cuts",new CglMixedIntegerRounding2, (const char*) "Mixed Integer Rounding", CUTINFO_NONE}, {(const char*)"2mir_cuts", new CglTwomir, (const char*) "2-MIR", CUTINFO_NONE}, {(const char*)"cover_cuts", new CglKnapsackCover, (const char*) "Cover", CUTINFO_NONE}, {(const char*)"clique_cuts", new CglClique, (const char*) "Clique", CUTINFO_CLIQUE}, {(const char*)"lift_and_project_cuts",new CglLandP,(const char*)"Lift and Project",CUTINFO_NONE}, {(const char*)"reduce_split_cuts",new CglRedSplit,(const char*) "Reduce and Split",CUTINFO_NONE}, {(const char*)"flow_covers_cuts",new CglFlowCover,(const char*) "Flow cover cuts", CUTINFO_NONE}, {NULL, NULL, NULL, CUTINFO_NONE}}; int freq; for (int i=0; cutList [i]. optname; i++) { options_ -> GetIntegerValue (std::string (cutList [i]. optname), freq, "couenne."); if (!freq) { delete cutList [i].cglptr; continue; } CuttingMethod cg; cg.frequency = freq; cg.cgl = cutList [i].cglptr; cg.id = std::string (cutList [i]. cglId); cutGenerators_.push_back (cg); // options for particular cases switch (cutList [i].extraInfo) { case CUTINFO_MIG: { CglGomory *gc = dynamic_cast <CglGomory *> (cutList [i].cglptr); if (!gc) break; gc -> setLimitAtRoot(512); gc -> setLimit(50); } break; case CUTINFO_PROBING: { CglProbing *pc = dynamic_cast <CglProbing *> (cutList [i].cglptr); if (!pc) break; pc->setUsingObjective(1); pc->setMaxPass(3); pc->setMaxPassRoot(3); // Number of unsatisfied variables to look at pc->setMaxProbe(10); pc->setMaxProbeRoot(50); // How far to follow the consequences pc->setMaxLook(10); pc->setMaxLookRoot(50); pc->setMaxLookRoot(10); // Only look at rows with fewer than this number of elements pc->setMaxElements(200); pc->setRowCuts(3); } break; case CUTINFO_CLIQUE: { CglClique *clique = dynamic_cast <CglClique *> (cutList [i].cglptr); if (!clique) break; clique -> setStarCliqueReport(false); clique -> setRowCliqueReport(false); clique -> setMinViolation(0.1); } break; //case CUTINFO_NONE: default: break; } } double givenAllowFGap2 = 0.0; options_->GetNumericValue(std::string("allowable_fraction_gap"), givenAllowFGap2, "bonmin."); double upval = 1e50; #ifdef FM_UP_BND printf("CutOff value:\n"); scanf("%lf", &upval); #else /* not FM_UP_BND */ options_->GetNumericValue(std::string("art_cutoff"), upval, "bonmin."); #endif /* FM_UP_BND */ if(upval < 1e50) { double newCO = (1-givenAllowFGap2) * upval; couenneProb_->setCutOff(newCO); printf("CutOff set to %f\n", newCO); #ifdef FM_TRACE_OPTSOL if(couenneProb_->getRecordBestSol()->getHasSol()) { if(newCO < couenneProb_->getRecordBestSol()->getVal()) { couenneProb_->getRecordBestSol()->setVal(newCO); } } #endif } }