00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <sstream>
00011
00012 #include "BonOaDecBase.hpp"
00013
00014
00015 #include "BonminConfig.h"
00016
00017 #include "OsiClpSolverInterface.hpp"
00018
00019 #include "CbcModel.hpp"
00020 #include "CbcStrategy.hpp"
00021 #ifdef COIN_HAS_CPX
00022 #include "OsiCpxSolverInterface.hpp"
00023 #endif
00024 #include "OsiAuxInfo.hpp"
00025
00026
00027 extern CbcModel * OAModel;
00028
00029 namespace Bonmin
00030 {
00031
00032 OaDecompositionBase::OaDecompositionBase
00033 (OsiTMINLPInterface * nlp,
00034 OsiSolverInterface * si,
00035 CbcStrategy * strategy,
00036 double cbcCutoffIncrement,
00037 double cbcIntegerTolerance,
00038 bool leaveSiUnchanged
00039 )
00040 :
00041 CglCutGenerator(),
00042 nlp_(nlp),
00043 nSolve_(0),
00044 lp_(si),
00045 objects_(NULL),
00046 nObjects_(0),
00047 nLocalSearch_(0),
00048 handler_(NULL),
00049 leaveSiUnchanged_(leaveSiUnchanged),
00050 reassignLpsolver_(false),
00051 timeBegin_(0),
00052 parameters_()
00053 {
00054 handler_ = new CoinMessageHandler();
00055 handler_ -> setLogLevel(2);
00056 messages_ = OaMessages();
00057 if (strategy)
00058 parameters_.setStrategy(*strategy);
00059 timeBegin_ = CoinCpuTime();
00060 parameters_.cbcCutoffIncrement_ = cbcCutoffIncrement;
00061 parameters_.cbcIntegerTolerance_ = cbcIntegerTolerance;
00062 }
00063 OaDecompositionBase::OaDecompositionBase(BabSetupBase &b, bool leaveSiUnchanged,
00064 bool reassignLpsolver):
00065 CglCutGenerator(),
00066 nlp_(b.nonlinearSolver()),
00067 lp_(b.continuousSolver()),
00068 objects_(NULL),
00069 nObjects_(0),
00070 nLocalSearch_(0),
00071 handler_(NULL),
00072 leaveSiUnchanged_(leaveSiUnchanged),
00073 reassignLpsolver_(reassignLpsolver),
00074 timeBegin_(0),
00075 parameters_()
00076 {
00077 handler_ = new CoinMessageHandler();
00078 int logLevel;
00079 b.options()->GetIntegerValue("oa_log_level",logLevel,"bonmin.");
00080 b.options()->GetNumericValue("oa_log_frequency",parameters_.logFrequency_,"bonmin.");
00081
00082 handler_ -> setLogLevel(logLevel);
00083
00084 messages_ = OaMessages();
00085 timeBegin_ = CoinCpuTime();
00086 b.options()->GetIntegerValue("milp_log_level",parameters_.subMilpLogLevel_,"bonmin.");
00087 b.options()->GetNumericValue("cutoff_decr",parameters_.cbcCutoffIncrement_,"bonmin.");
00088 b.options()->GetNumericValue("integer_tolerance",parameters_.cbcIntegerTolerance_,"bonmin.");
00089 int ivalue;
00090 b.options()->GetEnumValue("add_only_violated_oa", ivalue,"bonmin.");
00091 parameters_.addOnlyViolated_ = ivalue;
00092 b.options()->GetEnumValue("oa_cuts_scope", ivalue,"bonmin.");
00093 parameters_.global_ = ivalue;
00094 }
00095
00096 OaDecompositionBase::OaDecompositionBase
00097 (const OaDecompositionBase & other)
00098 :
00099 CglCutGenerator(other),
00100 nlp_(other.nlp_),
00101 lp_(other.lp_),
00102 objects_(other.objects_),
00103 nObjects_(other.nObjects_),
00104 nLocalSearch_(0),
00105 messages_(other.messages_),
00106 leaveSiUnchanged_(other.leaveSiUnchanged_),
00107 reassignLpsolver_(other.reassignLpsolver_),
00108 timeBegin_(0),
00109 parameters_(other.parameters_)
00110 {
00111 timeBegin_ = CoinCpuTime();
00112 handler_ = other.handler_->clone();
00113 }
00115 OaDecompositionBase::Parameters::Parameters():
00116 global_(true),
00117 addOnlyViolated_(false),
00118 cbcCutoffIncrement_(1e-06),
00119 cbcIntegerTolerance_(1e-05),
00120 localSearchNodeLimit_(0),
00121 maxLocalSearchPerNode_(0),
00122 maxLocalSearch_(0),
00123 maxLocalSearchTime_(3600),
00124 subMilpLogLevel_(0),
00125 logFrequency_(1000.),
00126 strategy_(NULL)
00127 {}
00128
00130 OaDecompositionBase::~OaDecompositionBase()
00131 {
00132 delete handler_;
00133 }
00134
00135
00137 OaDecompositionBase::Parameters::Parameters(const Parameters & other):
00138 global_(other.global_),
00139 addOnlyViolated_(other.addOnlyViolated_),
00140 cbcCutoffIncrement_(other.cbcCutoffIncrement_),
00141 cbcIntegerTolerance_(other.cbcIntegerTolerance_),
00142 localSearchNodeLimit_(other.localSearchNodeLimit_),
00143 maxLocalSearchPerNode_(other.maxLocalSearchPerNode_),
00144 maxLocalSearch_(other.maxLocalSearch_),
00145 maxLocalSearchTime_(other.maxLocalSearchTime_),
00146 subMilpLogLevel_(other.subMilpLogLevel_),
00147 logFrequency_(other.logFrequency_),
00148 strategy_(NULL)
00149 {
00150 if (other.strategy_)
00151 strategy_ = other.strategy_->clone();
00152 }
00153
00154
00156 OaDecompositionBase::SubMipSolver::SubMipSolver(OsiSolverInterface * lp,
00157 const CbcStrategy * strategy):
00158 lp_(lp),
00159 clp_(NULL),
00160 cpx_(NULL),
00161 cbc_(NULL),
00162 lowBound_(-COIN_DBL_MAX),
00163 optimal_(false),
00164 integerSolution_(NULL),
00165 strategy_(NULL)
00166 {
00167 clp_ = (lp_ == NULL)? NULL :
00168 dynamic_cast<OsiClpSolverInterface *>(lp_);
00169 #ifdef COIN_HAS_CPX
00170 cpx_ = (lp_ == NULL)? NULL :
00171 dynamic_cast<OsiCpxSolverInterface *>(lp_);
00172 #endif
00173 if (strategy) strategy_ = strategy->clone();
00174 }
00175 OaDecompositionBase::SubMipSolver::~SubMipSolver()
00176 {
00177 if (strategy_) delete strategy_;
00178 if (integerSolution_) delete [] integerSolution_;
00179 if (cbc_) delete cbc_;
00180 }
00181
00183 void
00184 OaDecompositionBase::SubMipSolver::setLpSolver(OsiSolverInterface * lp)
00185 {
00186 lp_ = lp;
00187 clp_ = (lp_ == NULL) ? NULL :
00188 dynamic_cast<OsiClpSolverInterface *>(lp_);
00189 #ifdef COIN_HAS_CPX
00190 cpx_ = (lp_ == NULL) ? NULL :
00191 dynamic_cast<OsiCpxSolverInterface *>(lp_);
00192 #endif
00193 lowBound_ = -COIN_DBL_MAX;
00194 optimal_ = false;
00195 if (integerSolution_) {
00196 delete [] integerSolution_;
00197 integerSolution_ = NULL;
00198 }
00199 }
00200
00201
00202
00203 void
00204 OaDecompositionBase::SubMipSolver::performLocalSearch(double cutoff, int loglevel, double maxTime,
00205 int maxNodes)
00206 {
00207 if (clp_) {
00208 if (!strategy_)
00209 strategy_ = new CbcStrategyDefault(1,0,0, loglevel);
00210
00211 OsiBabSolver empty;
00212 if (cbc_) delete cbc_;
00213 OAModel = cbc_ = new CbcModel(*clp_);
00214 cbc_->solver()->setAuxiliaryInfo(&empty);
00215
00216
00217 strcpy(cbc_->messagesPointer()->source_,"OaCbc");
00218
00219 cbc_->setLogLevel(loglevel);
00220 cbc_->solver()->messageHandler()->setLogLevel(0);
00221 clp_->resolve();
00222 cbc_->setStrategy(*strategy_);
00223 cbc_->setLogLevel(loglevel);
00224 cbc_->solver()->messageHandler()->setLogLevel(0);
00225 cbc_->setMaximumNodes(maxNodes);
00226 cbc_->setMaximumSeconds(maxTime);
00227 cbc_->setCutoff(cutoff);
00228
00229 cbc_->branchAndBound();
00230 OAModel = NULL;
00231 lowBound_ = cbc_->getBestPossibleObjValue();
00232
00233 if (cbc_->isProvenOptimal() || cbc_->isProvenInfeasible())
00234 optimal_ = true;
00235 else optimal_ = false;
00236
00237 if (cbc_->getSolutionCount()) {
00238 if (!integerSolution_)
00239 integerSolution_ = new double[lp_->getNumCols()];
00240 CoinCopyN(cbc_->bestSolution(), lp_->getNumCols(), integerSolution_);
00241 }
00242 else if (integerSolution_) {
00243 delete [] integerSolution_;
00244 integerSolution_ = NULL;
00245 }
00246 nodeCount_ = cbc_->getNodeCount();
00247 iterationCount_ = cbc_->getIterationCount();
00248 }
00249 else {
00250 lp_->messageHandler()->setLogLevel(loglevel);
00251 #ifdef COIN_HAS_CPX
00252 if (cpx_) {
00253 CPXENVptr env = cpx_->getEnvironmentPtr();
00254 CPXsetintparam(env, CPX_PARAM_NODELIM, maxNodes);
00255 CPXsetdblparam(env, CPX_PARAM_TILIM, maxTime);
00256 CPXsetdblparam(env, CPX_PARAM_CUTUP, cutoff);
00257
00258 }
00259 else
00260 #endif
00261 {
00262 throw CoinError("Unsuported solver, for local searches you should use clp or cplex",
00263 "performLocalSearch",
00264 "OaDecompositionBase::SubMipSolver");
00265 }
00266
00267 lp_->branchAndBound();
00268
00269 #ifdef COIN_HAS_CPX
00270 if (cpx_) {
00271
00272 CPXENVptr env = cpx_->getEnvironmentPtr();
00273 CPXLPptr cpxlp = cpx_->getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ALL);
00274
00275 int status = CPXgetbestobjval(env, cpxlp, &lowBound_);
00276 nodeCount_ = CPXgetnodecnt(env , cpxlp);
00277 iterationCount_ = CPXgetmipitcnt(env , cpxlp);
00278 if (status)
00279 throw CoinError("Error in getting some CPLEX information","OaDecompositionBase::SubMipSolver","performLocalSearch");
00280 }
00281 #endif
00282
00283 if (lp_->getFractionalIndices().size() == 0) {
00284 if (!integerSolution_)
00285 integerSolution_ = new double[lp_->getNumCols()];
00286 CoinCopyN(lp_->getColSolution(), lp_->getNumCols() , integerSolution_);
00287 }
00288 else if (integerSolution_) {
00289 delete [] integerSolution_;
00290 integerSolution_ = NULL;
00291 }
00292 }
00293 }
00294
00295 OaDecompositionBase::solverManip::solverManip
00296 (OsiSolverInterface * si,
00297 bool saveNumRows,
00298 bool saveBasis,
00299 bool saveBounds,
00300 bool saveCutoff,
00301 bool resolve):
00302 si_(si),
00303 initialNumberRows_(-1),
00304 colLower_(NULL),
00305 colUpper_(NULL),
00306 warm_(NULL),
00307 cutoff_(COIN_DBL_MAX),
00308 deleteSolver_(false),
00309 objects_(NULL),
00310 nObjects_(0),
00311 integerTolerance_(1e-08)
00312 {
00313 getCached();
00314 if (saveNumRows)
00315 initialNumberRows_ = numrows_;
00316 if (saveBasis)
00317 warm_ = si->getWarmStart();
00318 if (saveBounds) {
00319 colLower_ = new double[numcols_];
00320 colUpper_ = new double[numcols_];
00321 CoinCopyN(si->getColLower(), numcols_ , colLower_);
00322 CoinCopyN(si->getColUpper(), numcols_ , colUpper_);
00323 }
00324 if (saveCutoff)
00325 si->getDblParam(OsiDualObjectiveLimit, cutoff_);
00326 si->messageHandler()->setLogLevel(0);
00327 if (resolve) si->resolve();
00328 }
00329
00330
00331 OaDecompositionBase::solverManip::solverManip
00332 (const OsiSolverInterface & si):
00333 si_(NULL),
00334 initialNumberRows_(-1),
00335 colLower_(NULL),
00336 colUpper_(NULL),
00337 warm_(NULL),
00338 cutoff_(COIN_DBL_MAX),
00339 deleteSolver_(true),
00340 objects_(NULL),
00341 nObjects_(0),
00342 integerTolerance_(1e-08)
00343 {
00344 si_ = si.clone();
00345 getCached();
00346 }
00347
00348 OaDecompositionBase::solverManip::~solverManip()
00349 {
00350 if (warm_) delete warm_;
00351 if (colLower_) delete [] colLower_;
00352 if (colUpper_) delete [] colUpper_;
00353 if (deleteSolver_) delete si_;
00354 }
00355
00356 void
00357 OaDecompositionBase::solverManip::restore()
00358 {
00359 if (initialNumberRows_ >= 0) {
00360 int nRowsToDelete = numrows_ - initialNumberRows_;
00361 int * rowsToDelete = new int[nRowsToDelete];
00362 for (int i = 0 ; i < nRowsToDelete ; i++) {
00363 rowsToDelete[i] = i + initialNumberRows_;
00364 }
00365 si_->deleteRows(nRowsToDelete, rowsToDelete);
00366 delete [] rowsToDelete;
00367 numrows_ -= nRowsToDelete;
00368 }
00369
00370 if (colLower_) {
00371 si_->setColLower(colLower_);
00372 }
00373
00374 if (colUpper_) {
00375 si_->setColUpper(colUpper_);
00376 }
00377
00378 if (cutoff_<COIN_DBL_MAX) {
00379 si_->setDblParam(OsiDualObjectiveLimit, cutoff_);
00380 }
00381
00382 if (warm_) {
00383 if (si_->setWarmStart(warm_)==false) {
00384 throw CoinError("Fail restoring the warm start at the end of procedure",
00385 "restore","OaDecompositionBase::SaveSolverState") ;
00386 }
00387 }
00388 getCached();
00389 }
00390
00391 void
00392 OaDecompositionBase::passInMessageHandler(CoinMessageHandler * handler)
00393 {
00394 int logLevel = handler_->logLevel();
00395 delete handler_;
00396 handler_=handler->clone();
00397 handler_->setLogLevel(logLevel);
00398 }
00399
00401 bool
00402 OaDecompositionBase::solverManip::integerFeasible(const OsiBranchingInformation& info) const
00403 {
00404 if (objects_) {
00405 int dummy;
00406 for (int i = 0 ; i < nObjects_ ; i++) {
00407 if (objects_[i]->infeasibility(&info, dummy) > 0.0) return false;
00408 }
00409 }
00410 else {
00411 const double * sol = info.solution_;
00412 int numcols = si_->getNumCols();
00413 for (int i = 0 ; i < numcols ; i++) {
00414 if (si_->isInteger(i)) {
00415 if (fabs(sol[i] - floor(sol[i] + 0.5)) >
00416 integerTolerance_) {
00417 return false;
00418 }
00419 }
00420 }
00421 }
00422 return true;
00423 }
00424
00427 void
00428 OaDecompositionBase::solverManip::fixIntegers(const OsiBranchingInformation& info)
00429 {
00430 if (objects_) {
00431 for (int i = 0 ; i < nObjects_ ; i++) {
00432 if (objects_[i]->feasibleRegion(si_, &info));
00433 }
00434 }
00435 else {
00436 const double * colsol = info.solution_;
00437 for (int i = 0; i < numcols_; i++) {
00438 if (si_->isInteger(i)) {
00439 double value = colsol[i];
00440 if (fabs(value - floor(value+0.5)) > integerTolerance_) {
00441 std::stringstream stream;
00442 stream<<"Error not integer valued solution"<<std::endl;
00443 stream<<"---------------- x["<<i<<"] = "<<value<<std::endl;
00444 throw CoinError(stream.str(),"fixIntegers","OaDecompositionBase::solverManip");
00445 }
00446 value = floor(value+0.5);
00447 value = max(colLower_[i],value);
00448 value = min(value, colUpper_[i]);
00449
00450 if (fabs(value) > 1e10) {
00451 std::stringstream stream;
00452 stream<<"Can not fix variable in nlp because it has too big a value ("<<value
00453 <<") at optimium of LP relaxation. You should try running the problem with B-BB"<<std::endl;
00454 throw CoinError(stream.str(),
00455 "fixIntegers","OaDecompositionBase::solverManip") ;
00456 }
00457 #ifdef OA_DEBUG
00458
00459
00460 std::cout<<(int)value;
00461 #endif
00462 si_->setColLower(i,value);
00463 si_->setColUpper(i,value);
00464 }
00465 }
00466 #ifdef OA_DEBUG
00467 std::cout<<std::endl;
00468 #endif
00469 }
00470 }
00472 bool
00473 OaDecompositionBase::solverManip::isDifferentOnIntegers(const double * colsol)
00474 {
00475 return isDifferentOnIntegers(colsol, si_->getColSolution());
00476 }
00477
00479 bool
00480 OaDecompositionBase::solverManip::isDifferentOnIntegers(const double * colsol, const double *otherSol)
00481 {
00482 if (objects_) {
00483 for (int i = 0 ; i < nObjects_ ; i++) {
00484 OsiObject * obj = objects_[i];
00485 int colnum = obj->columnNumber();
00486 if (colnum >= 0) {
00487 if (fabs(otherSol[colnum] - colsol[colnum]) > 100*integerTolerance_) {
00488 return true;
00489 }
00490 }
00491 else {
00492 OsiSOS * sos = dynamic_cast<OsiSOS *>(obj);
00493 assert(sos);
00494 const int * members = sos->members();
00495 int end = sos->numberMembers();
00496 for (int k = 0 ; k < end ; k++) {
00497 if (fabs(otherSol[members[k]] - colsol[members[k]]) > 0.001) {
00498 return true;
00499 }
00500 }
00501 }
00502 }
00503 }
00504 else {
00505 for (int i = 0; i < numcols_ ; i++) {
00506 if (si_->isInteger(i) && fabs(otherSol[i] - colsol[i])>0.001)
00507 return true;
00508 }
00509 }
00510 return false;
00511 }
00512
00514 void
00515 OaDecompositionBase::solverManip::cloneOther(const OsiSolverInterface &si)
00516 {
00517
00518 int numberCutsToAdd = si.getNumRows();
00519 numberCutsToAdd -= numrows_;
00520 if (numberCutsToAdd > 0)
00521 {
00522 CoinPackedVector * * addCuts = new CoinPackedVector *[numberCutsToAdd];
00523 for (int i = 0 ; i < numberCutsToAdd ; i++)
00524 {
00525 addCuts[i] = new CoinPackedVector;
00526 }
00527
00528 const CoinPackedMatrix * mat = si.getMatrixByCol();
00529 const CoinBigIndex * start = mat->getVectorStarts();
00530 const int * length = mat->getVectorLengths();
00531 const double * elements = mat->getElements();
00532 const int * indices = mat->getIndices();
00533 for (int i = 0 ; i < numcols_ ; i++)
00534 for (int k = start[i] ; k < start[i] + length[i] ; k++)
00535 {
00536 if (indices[k] >= numrows_) {
00537 addCuts[ indices[k] - numrows_ ]->insert(i, elements[k]);
00538 }
00539 }
00540 si_->addRows(numberCutsToAdd, (const CoinPackedVectorBase * const *) addCuts, si.getRowLower() + numrows_,
00541 si.getRowUpper() + numrows_);
00542 for (int i = 0 ; i < numberCutsToAdd ; i++){
00543 delete addCuts[i];
00544 }
00545 delete [] addCuts;
00546 }
00547 else if (numberCutsToAdd < 0) {
00548 throw CoinError("Internal error number of cuts wrong",
00549 "generateCuts","OACutGenerator2");
00550 }
00551
00552 si_->setColLower(si.getColLower());
00553 si_->setColUpper(si.getColUpper());
00554
00555 CoinWarmStart * warm = si.getWarmStart();
00556 if (si_->setWarmStart(warm)==false) {
00557 delete warm;
00558 throw CoinError("Fail installing the warm start in the subproblem",
00559 "generateCuts","OACutGenerator2") ;
00560 }
00561 delete warm;
00562
00563 double cutoff;
00564 si.getDblParam(OsiDualObjectiveLimit, cutoff);
00565 si_->setDblParam(OsiDualObjectiveLimit, cutoff);
00566 si_->messageHandler()->setLogLevel(0);
00567 si_->resolve();
00568
00569 numrows_ = si.getNumRows();
00570 #ifdef OA_DEBUG
00571
00572 std::cout<<"Resolve with hotstart :"<<std::endl
00573 <<"number of iterations(should be 0) : "<<lp_->getIterationCount()<<std::endl
00574 <<"Objective value and diff to original : "<<lp_->getObjValue()<<", "
00575 <<fabs(si_->getObjValue() - si.getObjValue())<<std::endl;
00576 for (int i = 0 ; i <= numcols ; i++) {
00577 if (fabs(si.getColSolution()[i]-si_->getColSolution()[i])>1e-08) {
00578 std::cout<<"Diff between solution at node and solution with local solver : "<<fabs(si.getColSolution()[i]-lp_->getColSolution()[i])<<std::endl;
00579 }
00580 }
00581 #endif
00582
00583 }
00584
00585
00587 void
00588 OaDecompositionBase::solverManip::installCuts(const OsiCuts& cs, int numberCuts)
00589 {
00590 int numberCutsBefore = cs.sizeRowCuts() - numberCuts;
00591
00592 CoinWarmStartBasis * basis
00593 = dynamic_cast<CoinWarmStartBasis*>(si_->getWarmStart()) ;
00594 assert(basis != NULL);
00595 basis->resize(numrows_ + numberCuts,numcols_ + 1) ;
00596 for (int i = 0 ; i < numberCuts ; i++) {
00597 basis->setArtifStatus(numrows_ + i,
00598 CoinWarmStartBasis::basic) ;
00599 }
00600
00601 const OsiRowCut ** addCuts = new const OsiRowCut * [numberCuts] ;
00602 for (int i = 0 ; i < numberCuts ; i++) {
00603 addCuts[i] = &cs.rowCut(i + numberCutsBefore) ;
00604 }
00605 si_->applyRowCuts(numberCuts,addCuts) ;
00606 numrows_ += numberCuts;
00607 delete [] addCuts ;
00608 if (si_->setWarmStart(basis) == false) {
00609 delete basis;
00610 throw CoinError("Fail setWarmStart() after cut installation.",
00611 "generateCuts","OACutGenerator2") ;
00612 }
00613 delete basis;
00614 }
00615
00617 void
00618 OaDecompositionBase::generateCuts(const OsiSolverInterface &si, OsiCuts & cs,
00619 const CglTreeInfo info) const
00620 {
00621 if (nlp_ == NULL) {
00622 throw CoinError("Error in cut generator for outer approximation no NLP ipopt assigned", "generateCuts", "OaDecompositionBase");
00623 }
00624
00625
00626 OsiBabSolver * babInfo = dynamic_cast<OsiBabSolver *> (si.getAuxiliaryInfo());
00627 if (babInfo)
00628 if (!babInfo->mipFeasible())
00629 return;
00630
00631
00632 const double *colsol = si.getColSolution();
00633
00634
00635 solverManip nlpManip(nlp_, false, false, true, false, false);
00636 nlpManip.setIntegerTolerance(parameters_.cbcIntegerTolerance_);
00637 nlpManip.setObjects(objects_, nObjects_);
00638 OsiBranchingInformation brInfo(nlp_, false);
00639 brInfo.solution_ = colsol;
00640
00641 bool isInteger = nlpManip.integerFeasible(brInfo);
00642
00643 SubMipSolver * subMip = NULL;
00644
00645 if (!isInteger) {
00646 if (doLocalSearch())
00647 {
00648 subMip = new SubMipSolver(lp_, parameters_.strategy());
00649 }
00650 else {
00651 return;
00652 }
00653 }
00654
00655
00656
00657
00658
00659
00660 double cutoff;
00661 si.getDblParam(OsiDualObjectiveLimit, cutoff);
00662
00663
00664
00665 solverManip * lpManip = NULL;
00666 if (lp_ != NULL) {
00667 if (lp_!=&si) {
00668 lpManip = new solverManip(lp_, true, false, false, true, true);
00669 lpManip->cloneOther(si);
00670 }
00671 else {
00672 #if 0
00673 throw CoinError("Not allowed to modify si in a cutGenerator",
00674 "OACutGenerator2","generateCuts");
00675 #else
00676 lpManip = new solverManip(lp_, true, leaveSiUnchanged_, true, true);
00677 #endif
00678 }
00679 }
00680 else {
00681 lpManip = new solverManip(si);
00682 }
00683 lpManip->setObjects(objects_, nObjects_);
00684 lpManip->setIntegerTolerance(parameters_.cbcIntegerTolerance_);
00685 double milpBound = performOa(cs, nlpManip, *lpManip, subMip, babInfo, cutoff);
00686
00687
00688 {
00689 if (milpBound>-1e100)
00690 {
00691
00692 if (babInfo)
00693 babInfo->setMipBound(milpBound);
00694 }
00695 }
00696
00697
00698 if (subMip!= NULL) {
00699 delete subMip;
00700 subMip = NULL;
00701 }
00702
00703
00704 if (leaveSiUnchanged_)
00705 lpManip->restore();
00706 delete lpManip;
00707 nlpManip.restore();
00708 return;
00709 }
00710
00711 void
00712 OaDecompositionBase::solverManip::getCached()
00713 {
00714 numrows_ = si_->getNumRows();
00715 numcols_ = si_->getNumCols();
00716 siColLower_ = si_->getColLower();
00717 siColUpper_ = si_->getColUpper();
00718 }
00719
00720
00722 bool
00723 OaDecompositionBase::solveNlp(OsiBabSolver * babInfo, double cutoff) const
00724 {
00725 nSolve_++;
00726 nlp_->resolve();
00727 bool return_value = false;
00728 if (nlp_->isProvenOptimal()) {
00729 handler_->message(FEASIBLE_NLP, messages_)
00730 <<nlp_->getIterationCount()
00731 <<nlp_->getObjValue()<<CoinMessageEol;
00732
00733 #ifdef OA_DEBUG
00734 const double * colsol2 = nlp_->getColSolution();
00735 debug_.checkInteger(colsol2,numcols,std::cerr);
00736 #endif
00737
00738 if ((nlp_->getObjValue() < cutoff) ) {
00739 handler_->message(UPDATE_UB, messages_)
00740 <<nlp_->getObjValue()
00741 <<CoinCpuTime()-timeBegin_
00742 <<CoinMessageEol;
00743
00744 return_value = true;
00745
00746 if (babInfo) {
00747 int numcols = nlp_->getNumCols();
00748 double * lpSolution = new double[numcols + 1];
00749 CoinCopyN(nlp_->getColSolution(), numcols, lpSolution);
00750 lpSolution[numcols] = nlp_->getObjValue();
00751 babInfo->setSolution(lpSolution,
00752 numcols + 1, lpSolution[numcols]);
00753 delete [] lpSolution;
00754 }
00755 else {
00756 printf("No auxiliary info in nlp solve!\n");
00757 throw -1;
00758 }
00759 }
00760 }
00761 else if (nlp_->isAbandoned() || nlp_->isIterationLimitReached()) {
00762 (*handler_)<<"Unsolved NLP... exit"<<CoinMessageEol;
00763 }
00764 else {
00765 handler_->message(INFEASIBLE_NLP, messages_)
00766 <<nlp_->getIterationCount()
00767 <<CoinMessageEol;
00768 }
00769 return return_value;
00770 }
00771
00772
00773
00774 #ifdef OA_DEBUG
00775 bool
00776 OaDecompositionBase::OaDebug::checkInteger(const double * colsol, int numcols, ostream & os) const
00777 {
00778 for (int i = 0 ; i < numcols ; i++) {
00779 if (nlp_->isInteger(i)) {
00780 if (fabs(sol[i]) - floor(sol[i] + 0.5) >
00781 parameters_.cbcIntegerTolerance_) {
00782 std::cerr<<"Integer infeasible point (should not be), integer infeasibility for variable "<<i
00783 <<" is, "<<fabs(colsol2[i] - floor(colsol2[i] + 0.5))<<std::endl;
00784 }
00785 }
00786 return true;
00787 }
00788
00789 }
00790
00791 void
00792 OaDecompositionBase::OaDebug::printEndOfProcedureDebugMessage(const OsiCuts &cs,
00793 bool foundSolution,
00794 double milpBound,
00795 bool isInteger,
00796 bool feasible,
00797 std::ostream & os)
00798 {
00799 std::cout<<"------------------------------------------------------------------"
00800 <<std::endl;
00801 std::cout<<"OA procedure finished"<<std::endl;
00802 std::cout<<"Generated "<<cs.sizeRowCuts()<<std::endl;
00803 if (foundSolution)
00804 std::cout <<"Found NLP-integer feasible solution of value : "<<cutoff<<std::endl;
00805 std::cout<<"Current MILP lower bound is : "<<milpBound<<std::endl;
00806 std::cout<<"-------------------------------------------------------------------"<<std::endl;
00807 std::cout<<"Stopped because : isInteger "<<isInteger<<", feasible "<<feasible<<std::endl<<std::endl;
00808
00809 }
00810
00811
00812
00813 #endif
00814 }
00815