/home/coin/SVN-release/OS-1.1.1/Bonmin/src/Algorithms/OaGenerators/BonOaDecBase.cpp

Go to the documentation of this file.
00001 // (C) Copyright International Business Machines (IBM) 2006
00002 // All Rights Reserved.
00003 // This code is published under the Common Public License.
00004 //
00005 // Authors :
00006 // P. Bonami, International Business Machines
00007 //
00008 // Date :  12/07/2006
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 //The following two are to interupt the solution of sub-mip through CTRL-C
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       //Change Cbc messages prefixes
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         //CpxModel = cpx_;
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       //CpxModel = NULL;
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         //         printf("xx %d at %g (bounds %g, %g)",i,value,nlp_->getColLower()[i],
00459         //                nlp_->getColUpper()[i]);
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) {//Variable branching object
00487         if (fabs(otherSol[colnum] - colsol[colnum]) > 100*integerTolerance_) {
00488           return true;
00489         }
00490       }
00491       else {//It is a sos branching object
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   //Install current active cuts into local solver
00518   int numberCutsToAdd = si.getNumRows();
00519   numberCutsToAdd -= numrows_;
00520   if (numberCutsToAdd > 0)//Have to install some cuts
00521   {
00522     CoinPackedVector * * addCuts = new CoinPackedVector *[numberCutsToAdd];
00523     for (int i = 0 ; i < numberCutsToAdd ; i++)
00524     {
00525       addCuts[i] = new CoinPackedVector;
00526     }
00527     //Get the current matrix and fill the addCuts
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) { //Oups some error
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   //Install basis in problem
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   //put the cutoff
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); // make sure not volume
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   // babInfo is used to communicate with the b-and-b solver (Cbc or Bcp).
00626   OsiBabSolver * babInfo = dynamic_cast<OsiBabSolver *> (si.getAuxiliaryInfo());
00627   if (babInfo)
00628     if (!babInfo->mipFeasible())
00629       return;
00630 
00631   //Get the continuous solution
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   //Check integer infeasibility
00641   bool isInteger = nlpManip.integerFeasible(brInfo);
00642 
00643   SubMipSolver * subMip = NULL;
00644 
00645   if (!isInteger) {
00646     if (doLocalSearch())//create sub mip solver.
00647     {
00648       subMip = new SubMipSolver(lp_, parameters_.strategy());
00649     }
00650     else {
00651       return;
00652     }
00653   }
00654 
00655 
00656   //If we are going to modify things copy current information to restore it in the end
00657 
00658 
00659   //get the current cutoff
00660   double cutoff;
00661   si.getDblParam(OsiDualObjectiveLimit, cutoff);
00662 
00663   // Save solvers state if needed
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   //Transmit the bound found by the milp
00688   {
00689     if (milpBound>-1e100)
00690     {
00691       // Also store into solver
00692       if (babInfo)
00693         babInfo->setMipBound(milpBound);
00694     }
00695   }  //Clean everything :
00696 
00697   //free subMip
00698   if (subMip!= NULL) {
00699     delete subMip;
00700     subMip = NULL;
00701   }
00702 
00703   //  Reset the two solvers
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       // Also pass it to solver
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 }/* End namespace Bonmin. */
00815 

Generated on Tue Sep 30 03:01:23 2008 by  doxygen 1.4.7