19 #include "OsiClpSolverInterface.hpp"
21 #include "CbcModel.hpp"
22 #include "CbcStrategy.hpp"
25 #include "OsiCpxSolverInterface.hpp"
27 #define CHECK_CPX_STAT(a,b) if(b) throw CoinError("Error in CPLEX call",__FILE__,a);
39 bool reassignLpsolver):
41 nlp_(b.nonlinearSolver()),
48 leaveSiUnchanged_(leaveSiUnchanged),
49 reassignLpsolver_(reassignLpsolver),
53 currentNodeNumber_(-1)
57 b.
options()->GetIntegerValue(
"oa_log_level",logLevel,b.
prefix());
69 b.
options()->GetEnumValue(
"add_only_violated_oa", ivalue,b.
prefix());
71 b.
options()->GetEnumValue(
"oa_cuts_scope", ivalue,b.
prefix());
78 CglCutGenerator(other),
93 timeBegin_ = CoinCpuTime();
99 addOnlyViolated_(false),
100 cbcCutoffIncrement_(1
e-06),
101 cbcIntegerTolerance_(1
e-05),
104 maxLocalSearchTime_(3600),
107 logFrequency_(1000.),
120 global_(other.global_),
121 addOnlyViolated_(other.addOnlyViolated_),
122 cbcCutoffIncrement_(other.cbcCutoffIncrement_),
123 cbcIntegerTolerance_(other.cbcIntegerTolerance_),
124 gap_tol_(other.gap_tol_),
125 maxLocalSearch_(other.maxLocalSearch_),
126 maxLocalSearchTime_(other.maxLocalSearchTime_),
127 subMilpLogLevel_(other.subMilpLogLevel_),
128 maxSols_(other.maxSols_),
129 logFrequency_(other.logFrequency_),
139 (OsiSolverInterface * si,
146 initialNumberRows_(-1),
151 deleteSolver_(
false),
157 initialNumberRows_ = numrows_;
159 warm_ = si->getWarmStart();
161 colLower_ =
new double[numcols_];
162 colUpper_ =
new double[numcols_];
163 CoinCopyN(si->getColLower(), numcols_ , colLower_);
164 CoinCopyN(si->getColUpper(), numcols_ , colUpper_);
167 si->getDblParam(OsiDualObjectiveLimit, cutoff_);
168 si->messageHandler()->setLogLevel(0);
169 if (resolve) si->resolve();
174 (
const OsiSolverInterface & si):
176 initialNumberRows_(-1),
191 if (warm_)
delete warm_;
192 if (colLower_)
delete [] colLower_;
193 if (colUpper_)
delete [] colUpper_;
194 if (deleteSolver_)
delete si_;
200 if (initialNumberRows_ >= 0) {
201 int nRowsToDelete = si_->getNumRows() - initialNumberRows_;
202 int * rowsToDelete =
new int[nRowsToDelete];
203 for (
int i = 0 ; i < nRowsToDelete ; i++) {
204 rowsToDelete[i] = i + initialNumberRows_;
206 si_->deleteRows(nRowsToDelete, rowsToDelete);
207 delete [] rowsToDelete;
208 numrows_ = si_->getNumRows() ;
212 si_->setColLower(colLower_);
216 si_->setColUpper(colUpper_);
219 if (cutoff_<COIN_DBL_MAX) {
220 si_->setDblParam(OsiDualObjectiveLimit, cutoff_);
224 if (si_->setWarmStart(warm_)==
false) {
225 throw CoinError(
"Fail restoring the warm start at the end of procedure",
226 "restore",
"OaDecompositionBase::SaveSolverState") ;
235 int logLevel =
handler_->logLevel();
244 const CglTreeInfo
info) {
246 throw CoinError(
"Error in cut generator for outer approximation no NLP ipopt assigned",
"generateCuts",
"OaDecompositionBase");
250 BabInfo * babInfo =
dynamic_cast<BabInfo *
> (si.getAuxiliaryInfo());
252 assert(babInfo->
babPtr());
254 CglTreeInfo info_copy =
info;
255 const CbcNode * node = babInfo->
babPtr()->
model().currentNode();
256 info_copy.level = (node == NULL) ? 0 : babInfo->
babPtr()->
model().currentNode()->depth();
259 if (!babInfo->mipFeasible())
263 const double *colsol = si.getColSolution();
272 OsiBranchingInformation brInfo(
nlp_,
false);
273 brInfo.solution_ = colsol;
280 int nodeNumber = babInfo->
babPtr()->
model().getNodeCount();
283 printf(
"OA decomposition recalled from the same node!\n");
286 for(
int i = 0 ; i < numCuts ; i++){
288 if(
savedCuts_.rowCut(i).violated(colsol) > 0.){
290 printf(
"A violated saved cut has been found\n");
292 savedCuts_.rowCut(i).setEffectiveness(9.99e99);
312 si.getDblParam(OsiDualObjectiveLimit, cutoff);
326 double milpBound =
performOa(cs, *lpManip, babInfo, cutoff, info_copy);
329 babInfo->
babPtr()->
model().setSolutionCount (numSols_ - 1);
334 if (milpBound>-1e100)
338 babInfo->setMipBound(milpBound);
355 numrows_ = si_->getNumRows();
356 numcols_ = si_->getNumCols();
357 siColLower_ = si_->getColLower();
358 siColUpper_ = si_->getColUpper();
366 bool return_value =
false;
374 debug_.checkInteger(*
nlp_,std::cerr);
388 double * lpSolution =
new double[numcols + 1];
391 babInfo->setSolution(lpSolution,
392 numcols + 1, lpSolution[numcols]);
393 delete [] lpSolution;
398 (*handler_)<<
"Unsolved NLP... exit"<<CoinMessageEol;
416 OaDecompositionBase::OaDebug::checkInteger(
const OsiSolverInterface &nlp,
417 std::ostream & os)
const {
418 const double * colsol = nlp.getColSolution();
419 int numcols = nlp.getNumCols();
420 for (
int i = 0 ; i < numcols ; i++) {
421 if (nlp.isInteger(i)) {
422 if (fabs(colsol[i]) - floor(colsol[i] + 0.5) >
424 std::cerr<<
"Integer infeasible point (should not be), integer infeasibility for variable "<<i
425 <<
" is, "<<fabs(colsol[i] - floor(colsol[i] + 0.5))<<std::endl;
434 OaDecompositionBase::OaDebug::printEndOfProcedureDebugMessage(
const OsiCuts &cs,
440 std::ostream & os)
const{
441 std::cout<<
"------------------------------------------------------------------"
443 std::cout<<
"OA procedure finished"<<std::endl;
444 std::cout<<
"Generated "<<cs.sizeRowCuts()<<std::endl;
446 std::cout <<
"Found NLP-integer feasible solution of value : "<<solValue<<std::endl;
447 std::cout<<
"Current MILP lower bound is : "<<milpBound<<std::endl;
448 std::cout<<
"-------------------------------------------------------------------"<<std::endl;
449 std::cout<<
"Stopped because : isInteger "<<isInteger<<
", feasible "<<feasible<<std::endl<<std::endl;
OaDecompositionBase(BabSetupBase &b, bool leaveSiUnchanged, bool reassignLpsolver)
New usefull constructor.
int maxSols_
maximum number of solutions
Small class to manipulatee various things in an OsiSolverInterface and restore them.
virtual bool isAbandoned() const
Are there a numerical difficulties?
OsiCuts savedCuts_
Saved cuts: in some cases when using OA to check feasible solution algorithm may loop because Cbc rem...
virtual const double * getColLower() const
Get pointer to array[getNumCols()] of column lower bounds.
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real fint fint fint fint * info
void passInMessageHandler(CoinMessageHandler *handler)
bool reassignLpsolver_
Do we need to reassign the lp solver with Cbc.
bool addOnlyViolated_
Add only violated OA inequalities.
virtual void generateCuts(const OsiSolverInterface &si, OsiCuts &cs, const CglTreeInfo info=CglTreeInfo())
Standard cut generation methods.
OsiSolverInterface * lp_
A linear solver.
void setLogLevel(int level)
virtual bool doLocalSearch(BabInfo *babInfo) const =0
virutal method to decide if local search is performed
double cbcIntegerTolerance_
integer tolerance (has to be the same as Cbc's)
virtual int getNumCols() const
Get number of columns.
virtual bool isProvenOptimal() const
Is optimality proven?
void restore()
Restore solver.
virtual double getObjValue() const
Get objective function value (can't use default)
OsiObject ** objects_
Some objects the feasiblitiy of which to verify.
bool global_
Add cuts as global.
solverManip(OsiSolverInterface *si, bool saveNumRows=true, bool saveBasis=true, bool saveBounds=false, bool saveCutoff=false, bool resolve=true)
Constructor.
CoinMessageHandler * handler_
messages handler.
double gap_tol_
setting for gap tolerance.
int nObjects_
Number of objects.*/.
virtual const double * getColSolution() const
Get pointer to array[getNumCols()] of primal solution vector.
void fint fint fint real fint real real real real real real real real real * e
~solverManip()
Destructor.
virtual void setColUpper(int elementIndex, double elementValue)
Set a single column upper bound.
A class to have all elements necessary to setup a branch-and-bound.
double timeBegin_
time of construction
void setupMipSolver(BabSetupBase &b, const std::string &prefix)
virtual ~OaDecompositionBase()
Destructor.
Parameters parameters_
Parameters.
int currentNodeNumber_
Store the current node number.
int numSols_
number of solutions found by OA_decomposition.
double cbcCutoffIncrement_
cutoff min increase (has to be intialized trhough Cbc)
void getCached()
Number of columns.
virtual bool isIterationLimitReached() const
Iteration limit reached?
int nSolve_
Number of nlp solved done.
int subMilpLogLevel_
sub milp log level.
Bab * babPtr()
Pointer to the branch-and-bound algorithm (to access CbcModel).
virtual int getIterationCount() const
Get how many iterations it took to solve the problem (whatever "iteration" mean to the solver...
bool leaveSiUnchanged_
Wether or not we should remove cuts at the end of the procedure.
double logFrequency_
Frequency of log.
CoinMessages messages_
Messages for OA.
virtual double performOa(OsiCuts &cs, solverManip &lpManip, BabInfo *babInfo, double &, const CglTreeInfo &info) const =0
virtual method which performs the OA algorithm by modifying lp and nlp.
virtual const double * getColUpper() const
Get pointer to array[getNumCols()] of column upper bounds.
BabSetupBase * s_
Pointer to setup.
Output messages for Outer approximation cutting planes.
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
void setObjects(OsiObject **objects, int nObjects)
Set objects.
Base class for OA algorithms.
Parameters for algorithm.
virtual void setColLower(int elementIndex, double elementValue)
Set a single column lower bound.
bool integerFeasible(OsiSolverInterface &si, const OsiBranchingInformation &info, double integer_tolerance, OsiObject **objects, int nObjects)
Check for integer feasibility of a solution return 1 if it is.
OsiTMINLPInterface * nlp_
Pointer to nlp interface.
Parameters()
Constructor with default values.
const char * prefix() const
Get prefix to use for options.
const CbcModel & model() const
Get cbc model used to solve.
Bonmin class for passing info between components of branch-and-cuts.
CbcStrategy * strategy_
Strategy to apply when using Cbc as MILP sub-solver.
bool post_nlp_solve(BabInfo *babInfo, double cutoff) const
Solve the nlp and do output.
bool isInteger(CouNumber x)
is this number integer?