14 #include "CbcModel.hpp"
15 #include "CbcStrategy.hpp"
16 #include "OsiAuxInfo.hpp"
17 #include "OsiClpSolverInterface.hpp"
21 #include "OsiCpxSolverInterface.hpp"
23 void throw_error(
const std::string &
s,
const std::string &
f,
const std::string &func){
24 throw CoinError(s,f,func);
26 #define CHECK_CPX_STAT(a,b) if(b) throw_error("Error in CPLEX call",__FILE__,a);
42 integerSolution_(NULL),
48 b.
options()->GetIntegerValue(
"milp_log_level", logLevel, prefix);
51 b.
options()->GetEnumValue(
"milp_solver",ivalue,prefix);
54 clp_ =
new OsiClpSolverInterface;
56 clp_->messageHandler()->setLogLevel(logLevel);
58 else if (ivalue == 1) {
61 clp_ =
new OsiClpSolverInterface;
63 clp_->messageHandler()->setLogLevel(logLevel);
65 else if (ivalue == 2) {
67 OsiCpxSolverInterface * cpxSolver =
new OsiCpxSolverInterface;
70 b.
options()->GetIntegerValue(
"number_cpx_threads",ivalue,prefix);
71 CPXsetintparam(cpxSolver->getEnvironmentPtr(), CPX_PARAM_THREADS, ivalue);
72 b.
options()->GetIntegerValue(
"cpx_parallel_strategy",ivalue,prefix);
73 CPXsetintparam(cpxSolver->getEnvironmentPtr(), CPX_PARAM_PARALLELMODE, ivalue);
76 cpx_->messageHandler()->setLogLevel(logLevel);
78 std::cerr <<
"You have set an option to use CPLEX as the milp\n"
79 <<
"subsolver in oa decomposition. However, apparently\n"
80 <<
"CPLEX is not configured to be used in bonmin.\n"
81 <<
"See the manual for configuring CPLEX\n";
86 b.
options()->GetEnumValue(
"milp_strategy",ivalue,prefix);
94 b.
options()->GetNumericValue(
"allowable_fraction_gap",
gap_tol_, prefix);
103 integerSolution_(NULL),
105 milp_strat_(copy.milp_strat_),
106 gap_tol_(copy.gap_tol_),
107 ownClp_(copy.ownClp_)
110 if(copy.
cpx_ != NULL){
111 cpx_ =
new OsiCpxSolverInterface(*copy.
cpx_);
113 CPXgetintparam(copy.
cpx_->getEnvironmentPtr(), CPX_PARAM_THREADS, &ival);
114 CPXsetintparam(
cpx_->getEnvironmentPtr(), CPX_PARAM_THREADS, ival);
115 CPXgetintparam(copy.
cpx_->getEnvironmentPtr(), CPX_PARAM_PARALLELMODE, &ival);
116 CPXsetintparam(
cpx_->getEnvironmentPtr(), CPX_PARAM_PARALLELMODE, ival);
119 if(copy.
clp_ != NULL){
145 cpx_->loadProblem(*lp->getMatrixByCol(), lp->getColLower(), lp->getColUpper(), lp->getObjCoefficients(), lp->getRowLower(), lp->getRowUpper());
146 int ncols = lp->getNumCols();
147 for(
int i = 0 ; i < ncols ; i++){
148 if(lp->isInteger(i) || lp->isBinary(i))
151 cpx_->setContinuous(i);
158 clp_ = (lp == NULL) ? NULL :
159 dynamic_cast<OsiClpSolverInterface *>(lp);
188 CbcStrategyDefault * strat_default = NULL;
190 strat_default =
new CbcStrategyDefault(1,5,5, loglevel);
191 strat_default->setupPreProcessing();
196 cbc.solver()->setAuxiliaryInfo(&empty);
199 strcpy(cbc.messagesPointer()->source_,
"OCbc");
201 cbc.setLogLevel(loglevel);
202 cbc.solver()->messageHandler()->setLogLevel(0);
205 cbc.setLogLevel(loglevel);
206 cbc.solver()->messageHandler()->setLogLevel(0);
207 cbc.setMaximumSeconds(max_time);
208 cbc.setMaximumSolutions(1);
209 cbc.setCutoff(cutoff);
212 cbc.branchAndBound();
213 lowBound_ = cbc.getBestPossibleObjValue();
215 if (cbc.isProvenOptimal() || cbc.isProvenInfeasible())
219 if (cbc.getSolutionCount()) {
231 if(strat_default != NULL){
232 delete strat_default;
238 throw CoinError(
"Unsuported solver, for local searches you should use clp or cplex",
239 "performLocalSearch",
240 "OaDecompositionBase::SubMipSolver");
242 cpx_->messageHandler()->setLogLevel(loglevel);
244 CPXENVptr env =
cpx_->getEnvironmentPtr();
245 CPXLPptr cpxlp =
cpx_->getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
246 CPXsetdblparam(env, CPX_PARAM_TILIM, max_time);
247 CPXsetintparam(env, CPX_PARAM_CLOCKTYPE, 1);
248 CPXsetdblparam(env, CPX_PARAM_EPINT, 1
e-08);
249 CPXsetdblparam(env, CPX_PARAM_CUTUP, cutoff);
250 CPXsetdblparam(env, CPX_PARAM_EPGAP,
gap_tol_);
252 double start_time = CoinCpuTime();
254 CPXsetintparam(env,CPX_PARAM_INTSOLLIM, 10);
255 CPXsetintparam(env,CPX_PARAM_NODELIM, 1000);
259 int status = CPXmipopt(env,cpxlp);
260 CHECK_CPX_STAT(
"mipopt",status)
263 status = CPXgetbestobjval(env, cpxlp, &
lowBound_);
264 CHECK_CPX_STAT(
"bestobjvalue",status)
266 int stat = CPXgetstat( env, cpxlp);
267 optimal_ = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_OPTIMAL) || (stat == CPXMIP_OPTIMAL_TOL) || (stat == CPXMIP_INForUNBD) ;
272 status = CPXsolninfo(env, cpxlp, NULL, &type, NULL, NULL);
273 CHECK_CPX_STAT(
"solninfo", status);
274 while(!
optimal_ && type == CPX_NO_SOLN && stat != CPXMIP_SOL_LIM && stat != CPXMIP_TIME_LIM_INFEAS
275 && stat != CPXMIP_TIME_LIM_FEAS && (CoinCpuTime() - start_time) <= max_time){
276 CPXsetintparam(env, CPX_PARAM_INTSOLLIM, 1);
277 CPXsetdblparam(env, CPX_PARAM_TILIM, max_time - CoinCpuTime() + start_time);
278 CPXsetintparam(env,CPX_PARAM_NODELIM, 2100000000);
279 status = CPXmipopt(env,cpxlp);
280 CHECK_CPX_STAT(
"mipopt",status)
282 stat = CPXgetstat( env, cpxlp);
283 optimal_ = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_OPTIMAL) || (stat == CPXMIP_OPTIMAL_TOL) || (stat == CPXMIP_INForUNBD) ;
287 bool infeasible = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_ABORT_INFEAS) || (stat == CPXMIP_TIME_LIM_INFEAS)
288 || (stat == CPXMIP_NODE_LIM_INFEAS) || (stat == CPXMIP_FAIL_INFEAS)
289 || (stat == CPXMIP_MEM_LIM_INFEAS) || (stat == CPXMIP_INForUNBD);
292 status = CPXgetbestobjval(env, cpxlp, &
lowBound_);
293 CHECK_CPX_STAT(
"getbestobjval",status)
301 CHECK_CPX_STAT(
"getmipx",status)
313 throw CoinError(
"Unsuported solver, for local searches you should use clp or cplex",
314 "performLocalSearch",
315 "OaDecompositionBase::SubMipSolver");
324 CbcStrategyDefault * strat_default =
dynamic_cast<CbcStrategyDefault *
>(
strategy_->clone());
325 assert(strat_default);
326 strat_default->setupPreProcessing();
330 cbc.solver()->setAuxiliaryInfo(&empty);
333 strcpy(cbc.messagesPointer()->source_,
"OCbc");
335 cbc.setLogLevel(loglevel);
336 cbc.solver()->messageHandler()->setLogLevel(0);
339 cbc.setLogLevel(loglevel);
340 cbc.solver()->messageHandler()->setLogLevel(0);
341 cbc.setMaximumSeconds(maxTime);
342 cbc.setCutoff(cutoff);
343 cbc.setDblParam( CbcModel::CbcAllowableFractionGap,
gap_tol_);
346 cbc.branchAndBound();
347 lowBound_ = cbc.getBestPossibleObjValue();
349 if (cbc.isProvenOptimal() || cbc.isProvenInfeasible())
353 if (cbc.getSolutionCount()) {
364 delete strat_default;
370 CPXENVptr env =
cpx_->getEnvironmentPtr();
371 CPXLPptr orig_lp =
cpx_->getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
374 CPXLPptr cpxlp = CPXcloneprob(env, orig_lp, &s);
379 cutoff = cutoff-fabs(cutoff)*
gap_tol_*0.2;
384 CPXsetdblparam(env, CPX_PARAM_TILIM, maxTime);
385 CPXsetintparam(env, CPX_PARAM_CLOCKTYPE, 1);
386 CPXsetdblparam(env, CPX_PARAM_CUTUP, cutoff);
387 CPXsetdblparam(env, CPX_PARAM_EPGAP, gap_tol);
388 CPXsetintparam( env, CPX_PARAM_PREIND, CPX_ON );
394 cpx_->messageHandler()->setLogLevel(loglevel);
396 int status = CPXmipopt(env,cpxlp);
397 CHECK_CPX_STAT(
"mipopt",status)
399 int stat = CPXgetstat( env, cpxlp);
400 bool infeasible = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_ABORT_INFEAS) || (stat == CPXMIP_TIME_LIM_INFEAS) || (stat == CPXMIP_NODE_LIM_INFEAS) || (stat == CPXMIP_FAIL_INFEAS)
401 || (stat == CPXMIP_MEM_LIM_INFEAS) || (stat == CPXMIP_INForUNBD);
402 optimal_ = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_OPTIMAL) || (stat == CPXMIP_OPTIMAL_TOL) || (stat == CPXMIP_INForUNBD);
405 status = CPXgetbestobjval(env, cpxlp, &
lowBound_);
406 CHECK_CPX_STAT(
"getbestobjval",status)
413 CHECK_CPX_STAT(
"getmipx",status)
421 CPXfreeprob(env, &cpxlp);
428 throw CoinError(
"Unsuported solver, for local searches you should use clp or cplex",
429 "performLocalSearch",
430 "OaDecompositionBase::SubMipSolver");
438 fprintf(stderr,
"Function optimize_with_lazy_constraints can only be used with CPLEX\n");
445 CPXENVptr env =
cpx_->getEnvironmentPtr();
446 CPXLPptr cpxlp =
cpx_->getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
450 int orig_nrows = CPXgetnumrows(env, cpxlp) - cs.sizeRowCuts();
452 CPXdelrows(env, cpxlp, orig_nrows, CPXgetnumrows(env, cpxlp) - 1);
454 int rcnt = cs.sizeRowCuts(), nzcnt = 0;
462 for(
int i =0 ; i < rcnt ; i++){
463 const OsiRowCut &
r = cs.rowCut(i);
464 const double lb = r.lb(), ub=r.ub();
469 else if (lb <= infty) {
479 nzcnt += r.row().getNumElements();
484 for(
int i =0 ; i < rcnt ; i++){
485 const OsiRowCut &
r = cs.rowCut(i);
486 const double * el = r.row().getElements();
487 const int *
id = r.row().getIndices();
488 int nz = r.row().getNumElements();
489 std::copy(el, el + nz, val() + beg[i]);
490 std::copy(
id,
id + nz, ind() + beg[i]);
493 CPXaddlazyconstraints(env, cpxlp, rcnt, nzcnt, rhs(), sense(), beg(), ind(), val(), NULL);
494 CPXsetintparam(env, CPX_PARAM_REDUCE, CPX_PREREDUCE_PRIMALONLY);
496 CPXsetdblparam(env, CPX_PARAM_TILIM, maxTime);
497 CPXsetintparam(env, CPX_PARAM_CLOCKTYPE, 1);
498 CPXsetdblparam(env, CPX_PARAM_CUTUP, cutoff);
499 CPXsetdblparam(env, CPX_PARAM_EPGAP,
gap_tol_);
500 cpx_->messageHandler()->setLogLevel(loglevel);
501 int status = CPXmipopt(env,cpxlp);
502 CHECK_CPX_STAT(
"mipopt",status)
504 int stat = CPXgetstat( env, cpxlp);
505 bool infeasible = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_ABORT_INFEAS) || (stat == CPXMIP_TIME_LIM_INFEAS) || (stat == CPXMIP_NODE_LIM_INFEAS) || (stat == CPXMIP_FAIL_INFEAS)
506 || (stat == CPXMIP_MEM_LIM_INFEAS) || (stat == CPXMIP_INForUNBD);
507 optimal_ = (stat == CPXMIP_INFEASIBLE) || (stat == CPXMIP_OPTIMAL) || (stat == CPXMIP_OPTIMAL_TOL) || (stat == CPXMIP_INForUNBD);
510 status = CPXgetbestobjval(env, cpxlp, &
lowBound_);
511 CHECK_CPX_STAT(
"getbestobjval",status)
518 CHECK_CPX_STAT(
"getmipx",status)
527 CPXfreelazyconstraints(env, cpxlp);
528 CPXaddrows(env, cpxlp, 0, rcnt, nzcnt, rhs(), sense(), beg(), ind(), val(), NULL, NULL);
534 throw CoinError(
"Unsuported solver, for local searches you should use clp or cplex",
535 "performLocalSearch",
536 "OaDecompositionBase::SubMipSolver");
545 strategy_ =
dynamic_cast<CbcStrategyDefault *
>(strategy->clone());
554 roptions->AddStringOption3(
"milp_solver",
555 "Choose the subsolver to solve MILP sub-problems in OA decompositions.",
557 "Cbc_D",
"Coin Branch and Cut with its default",
558 "Cbc_Par",
"Coin Branch and Cut with passed parameters",
560 " To use Cplex, a valid license is required and you should have compiled OsiCpx in COIN-OR (see Osi documentation).");
561 roptions->setOptionExtraInfo(
"milp_solver",64);
563 roptions->AddBoundedIntegerOption(
"cpx_parallel_strategy",
564 "Strategy of parallel search mode in CPLEX.",
566 "-1 = opportunistic, 0 = automatic, 1 = deterministic (refer to CPLEX documentation)"
568 roptions->setOptionExtraInfo(
"cpx_parallel_strategy",64);
570 roptions->AddLowerBoundedIntegerOption(
"number_cpx_threads",
571 "Set number of threads to use with cplex.",
573 "(refer to CPLEX documentation)"
575 roptions->setOptionExtraInfo(
"number_cpx_threads",64);
578 roptions->AddStringOption2(
"milp_strategy",
579 "Choose a strategy for MILPs.",
580 "solve_to_optimality",
581 "find_good_sol",
"Stop sub milps when a solution improving the incumbent is found",
582 "solve_to_optimality",
"Solve MILPs to optimality",
584 roptions->setOptionExtraInfo(
"milp_strategy",64);
587 roptions->AddBoundedIntegerOption(
"milp_log_level",
588 "specify MILP solver log level.",
590 "Set the level of output of the MILP subsolver in OA : "
591 "0 - none, 1 - minimal, 2 - normal low, 3 - normal high"
593 roptions->setOptionExtraInfo(
"milp_log_level",64);
bool ownClp_
say if owns copy of clp_.
void setStrategy(CbcStrategyDefault *strategy)
Assign a strategy.
int nodeCount_
number of nodes in last mip solved.
double * integerSolution_
Has an integer solution? then it is here.
double gap_tol_
setting for gap tolerance.
A class to setup default strategy for Cbc specifying which cut generators to use. ...
bool optimal_
Is optimality proven?
void fint fint fint real fint real real real real * f
void fint fint fint real fint real real real real real real real real real * e
A very simple class to provide a common interface for solving MIPs with Cplex and Cbc...
A class to have all elements necessary to setup a branch-and-bound.
MILP_solve_strategy milp_strat_
MILP search strategy.
void fint fint fint real fint real real real real real real real real real fint real fint * lp
OsiClpSolverInterface * clp_
If lp solver is clp (then have to use Cbc) (not owned).
void fint fint fint fint fint fint fint fint fint fint real real real real real real real real * s
double lowBound_
lower bound obtained
void fint fint fint real fint real real real real real real real * r
OsiSolverInterface * solver()
int iterationCount_
number of simplex iteration in last mip solved.
static const int infeasible
SubMipSolver(BabSetupBase &b, const std::string &prefix)
Constructor.
void find_good_sol(double cutoff, int loglevel, double maxTime)
update cutoff and perform a local search to a good solution.
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
Register options for that Oa based cut generation method.
void optimize(double cutoff, int loglevel, double maxTime)
update cutoff and optimize MIP.
void setLpSolver(OsiSolverInterface *lp)
Assign lp solver.
CbcStrategyDefault * strategy_
Strategy for solving sub mips with cbc.
void optimize_with_lazy_constraints(double cutoff, int loglevel, double maxTime, const OsiCuts &cs)
update cutoff, put OA constraints in cs as lazy constraints and optimize MIP.
OsiCpxSolverInterface * cpx_
If mip solver is cpx this is it (owned).