/home/coin/SVN-release/OS-2.2.0/Bonmin/src/CbcBonmin/BonCbc.cpp

Go to the documentation of this file.
00001 // (C) Copyright International Business Machines Corporation 2007
00002 // All Rights Reserved.
00003 // This code is published under the Common Public License.
00004 //
00005 // Authors :
00006 // Pierre Bonami, International Business Machines Corporation
00007 //
00008 // Date : 04/19/2007
00009 
00010 
00011 #include "BonCbc.hpp"
00012 #include "BonOACutGenerator2.hpp"
00013 #include "BonCbcNlpStrategy.hpp"
00014 #include "BonBabInfos.hpp"
00015 #include "CbcModel.hpp"
00016 #include "CbcBranchActual.hpp"
00017 #include "CbcCutGenerator.hpp"
00018 #include "CbcCompareActual.hpp"
00019 
00020 #include "BonExitCodes.hpp"
00021 
00022 #include "BonChooseVariable.hpp"
00023 #include "BonGuessHeuristic.hpp"
00024 
00025 #include "BonDiver.hpp"
00026 #include "BonLinearCutsGenerator.hpp"
00027 #include "BonTMINLPLinObj.hpp"
00028 // sets cutoff a bit above real one, to avoid single-point feasible sets
00029 #define CUTOFF_TOL 1e-6
00030 
00031 // Code to enable user interuption
00032 static CbcModel * currentBranchModel = NULL; //pointer to the main b&b
00033 Bonmin::OACutGenerator2 * currentOA = NULL; //pointer to the OA generator
00034 CbcModel * OAModel; // pointer to the submip if using Cbc
00035 bool BonminAbortAll;
00036 
00037 #define SIGNAL
00038 #ifdef SIGNAL
00039 #include "CoinSignal.hpp"
00040 
00041 extern "C"
00042 {
00043 
00044   static bool BonminInteruptedOnce =false;
00045   static void signal_handler(int whichSignal) {
00046     if (BonminInteruptedOnce) {
00047       std::cerr<<"User forced interuption"<<std::endl;
00048       exit(0);
00049     }
00050     if (currentBranchModel!=NULL)
00051       currentBranchModel->setMaximumNodes(0); // stop at next node
00052     if (OAModel!=NULL)
00053       OAModel->setMaximumNodes(0); // stop at next node
00054     if (currentOA!=NULL)
00055       currentOA->parameter().maxLocalSearchTime_ = 0.; // stop OA
00056     BonminAbortAll = true;
00057     BonminInteruptedOnce = true;
00058     return;
00059   }
00060 }
00061 #endif
00062 
00063 namespace Bonmin
00064 {
00065 
00067   Bab::Bab():
00068       bestSolution_(NULL),
00069       mipStatus_(),
00070       bestObj_(1e200),
00071       bestBound_(-1e200),
00072       continuousRelaxation_(-COIN_DBL_MAX),
00073       numNodes_(0),
00074       mipIterationCount_(0),
00075       model_(),
00076       modelHandler_(NULL),
00077       objects_(0),
00078       nObjects_(0),
00079       usingCouenne_(false)
00080   {}
00081 
00083   Bab::~Bab()
00084   {
00085     if (bestSolution_) delete [] bestSolution_;
00086     bestSolution_ = NULL;
00087     for ( int i = 0 ; i < nObjects_ ; i++) {
00088       delete objects_[i];
00089     }
00090     delete [] objects_;
00091     delete modelHandler_;
00092   }
00093 
00095   void
00096   Bab::operator()(BabSetupBase & s)
00097   {
00098     branchAndBound(s);
00099   }
00100 
00102   void
00103   Bab::branchAndBound(BabSetupBase & s)
00104   {
00105     /* Put a link to this into solver.*/
00106     OsiBabSolver *  babInfo = dynamic_cast<OsiBabSolver *>(s.continuousSolver()->getAuxiliaryInfo());
00107     assert(babInfo);
00108     Bonmin::BabInfo *  bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(babInfo);
00109     if (bonBabInfoPtr == NULL) {//Replace with a Bonmin::babInfo
00110       bonBabInfoPtr = new Bonmin::BabInfo(*babInfo);
00111       s.continuousSolver()->setAuxiliaryInfo(bonBabInfoPtr);
00112       delete bonBabInfoPtr;
00113       bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(s.continuousSolver()->getAuxiliaryInfo());
00114     }
00115     bonBabInfoPtr->setBabPtr(this);
00116 
00117     s.nonlinearSolver()->solver()->setup_global_time_limit(s.getDoubleParameter(BabSetupBase::MaxTime));
00118     OsiSolverInterface * solver = s.continuousSolver()->clone();
00119     delete modelHandler_;
00120     modelHandler_ = s.continuousSolver()->messageHandler()->clone();
00121     model_.passInMessageHandler(modelHandler_);
00122     model_.assignSolver(solver, true);
00123 
00124 
00125     //  s.continuousSolver() = model_.solver();
00126     //   if(s.continuousSolver()->objects()!=NULL){
00127     //     model_.addObjects(s.continuousSolver()->numberObjects(),s.continuousSolver()->objects());
00128     //   }
00129 
00130     int specOpt = s.getIntParameter(BabSetupBase::SpecialOption);
00131     if (specOpt) {
00132       model_.setSpecialOptions(specOpt);
00133       if (specOpt==16) {
00134         CbcNlpStrategy strat(s.getIntParameter(BabSetupBase::MaxFailures), 
00135                              s.getIntParameter(BabSetupBase::MaxInfeasible), 
00136                              s.getIntParameter(BabSetupBase::FailureBehavior));
00137         model_.setStrategy(strat);
00138       }
00139     }
00140 
00141     model_.setMaximumCutPasses(s.getIntParameter(BabSetupBase::NumCutPasses));
00142     model_.setMaximumCutPassesAtRoot(s.getIntParameter(BabSetupBase::NumCutPassesAtRoot));
00143 
00144     //Setup cutting plane methods
00145     for (BabSetupBase::CuttingMethods::iterator i = s.cutGenerators().begin() ;
00146         i != s.cutGenerators().end() ; i++) {
00147 
00148       OaDecompositionBase * oa = dynamic_cast<OaDecompositionBase *>(i->cgl);
00149       if (oa && oa->reassignLpsolver())
00150         oa->assignLpInterface(model_.solver());
00151         model_.addCutGenerator(i->cgl,i->frequency,i->id.c_str(), i->normal,
00152                                i->atSolution);
00153     }
00154 
00155     for (BabSetupBase::HeuristicMethods::iterator i = s.heuristics().begin() ;
00156         i != s.heuristics().end() ; i++) {
00157       CbcHeuristic * heu = i->heuristic;
00158       heu->setModel(&model_);
00159       model_.addHeuristic(heu, i->id.c_str());
00160     }
00161 
00162 
00163     //need to record solver logLevel here
00164     int logLevel = s.continuousSolver()->messageHandler()->logLevel();
00165 
00166     //Set true branch-and-bound parameters
00167     model_.setLogLevel(s.getIntParameter(BabSetupBase::BabLogLevel));
00168 
00169     // Put back solver logLevel
00170     model_.solver()->messageHandler()->setLogLevel(logLevel);
00171 
00172     model_.setPrintFrequency(s.getIntParameter(BabSetupBase::BabLogInterval));
00173 
00174     bool ChangedObject = false;
00175     //Pass over user set branching priorities to Cbc
00176     if (s.continuousSolver()->objects()==NULL) {
00177       //assert (s.branchingMethod() == NULL);
00178       const OsiTMINLPInterface * nlpSolver = s.nonlinearSolver();
00179       //set priorities, prefered directions...
00180       const int * priorities = nlpSolver->getPriorities();
00181       const double * upPsCosts = nlpSolver->getUpPsCosts();
00182       const double * downPsCosts = nlpSolver->getDownPsCosts();
00183       const int * directions = nlpSolver->getBranchingDirections();
00184       bool hasPseudo = (upPsCosts!=NULL);
00185       model_.findIntegers(true,hasPseudo);
00186       OsiObject ** simpleIntegerObjects = model_.objects();
00187       int numberObjects = model_.numberObjects();
00188       if (priorities != NULL || directions != NULL || hasPseudo) {
00189         ChangedObject = true;
00190         for (int i = 0 ; i < numberObjects ; i++) {
00191           CbcObject * object = dynamic_cast<CbcObject *>
00192               (simpleIntegerObjects[i]);
00193           int iCol = object->columnNumber();
00194           if (priorities)
00195             object->setPriority(priorities[iCol]);
00196           if (directions)
00197             object->setPreferredWay(directions[iCol]);
00198           if (upPsCosts) {
00199             CbcSimpleIntegerPseudoCost * pscObject =
00200               dynamic_cast<CbcSimpleIntegerPseudoCost*> (object);
00201             pscObject->setUpPseudoCost(upPsCosts[iCol]);
00202             pscObject->setDownPseudoCost(downPsCosts[iCol]);
00203           }
00204         }
00205       }
00206 
00207 #if 1
00208       // Now pass user set Sos constraints (code inspired from CoinSolve.cpp)
00209       const TMINLP::SosInfo * sos = s.nonlinearSolver()->model()->sosConstraints();
00210       if (!s.getIntParameter(BabSetupBase::DisableSos) && sos && sos->num > 0) 
00211         //we have some sos constraints
00212       {
00213         const OsiTMINLPInterface * nlpSolver = s.nonlinearSolver();
00214         const int & numSos = sos->num;
00215        (*nlpSolver->messageHandler())<<"Adding "<<sos->num<<" sos constraints."
00216                                      <<CoinMessageEol;
00217 
00218         CbcObject ** objects = new CbcObject*[numSos];
00219         const int * starts = sos->starts;
00220         const int * indices = sos->indices;
00221         const char * types = sos->types;
00222         const double * weights = sos->weights;
00223         //verify if model has user set priorities
00224         bool hasPriorities = false;
00225         const int * varPriorities = nlpSolver->getPriorities();
00226         int numberObjects = model_.numberObjects();
00227         if (varPriorities)
00228         {
00229           for (int i = 0 ; i < numberObjects ; i++) {
00230             if (varPriorities[i]) {
00231               hasPriorities = true;
00232               break;
00233             }
00234           }
00235         }
00236         const int * sosPriorities = sos->priorities;
00237         if (sosPriorities)
00238         {
00239           for (int i = 0 ; i < numSos ; i++) {
00240             if (sosPriorities[i]) {
00241               hasPriorities = true;
00242               break;
00243             }
00244           }
00245         }
00246         for (int i = 0 ; i < numSos ; i++)
00247         {
00248           int start = starts[i];
00249           int length = starts[i + 1] - start;
00250           objects[i] = new CbcSOS(&model_, length, &indices[start],
00251               &weights[start], i, types[i]);
00252 
00253           objects[i]->setPriority(10);
00254           if (hasPriorities && sosPriorities && sosPriorities[i]) {
00255             objects[i]->setPriority(sosPriorities[i]);
00256           }
00257         }
00258         model_.addObjects(numSos, objects);
00259         for (int i = 0 ; i < numSos ; i++)
00260           delete objects[i];
00261         delete [] objects;
00262       }
00263 #endif
00264       //If Setup contains more objects add them to Cbc
00265       if (s.objects().size()) {
00266         CbcObject ** objects = new CbcObject *[s.objects().size()];
00267         for (unsigned int i = 0 ; i < s.objects().size() ; i++) {
00268           objects[i] = dynamic_cast<CbcObject *> (s.objects()[i]);
00269           assert(objects[i]);
00270           objects[i]->setModel(&model_);
00271         }
00272         model_.addObjects(s.objects().size(), objects);
00273         delete [] objects;
00274       }
00275 
00276       replaceIntegers(model_.objects(), model_.numberObjects());
00277     }
00278     else {//Pass in objects to Cbc
00279     // Redundant definition of default branching (as Default == User)
00280     assert (s.branchingMethod() != NULL);
00281 
00282     if (!usingCouenne_)
00283       model_.addObjects (s.continuousSolver()->numberObjects(),
00284                          s.continuousSolver()->objects());
00285     else {
00286       // add nonlinear and integer objects (need to add OsiSOS)
00287       int nco = s.continuousSolver () -> numberObjects ();
00288       OsiObject **objs = new OsiObject * [nco];
00289       for (int i=0; i<nco; i++) 
00290         objs [i] = s.continuousSolver () -> objects () [i];
00291       model_.addObjects (nco, objs);
00292       delete [] objs;
00293     }
00294 
00295     CbcBranchDefaultDecision branch;
00296     s.branchingMethod()->setSolver(model_.solver());
00297     BonChooseVariable * strong2 = dynamic_cast<BonChooseVariable *>(s.branchingMethod());
00298     if (strong2)
00299       strong2->setCbcModel(&model_);
00300     branch.setChooseMethod(*s.branchingMethod());
00301 
00302     model_.setBranchingMethod(&branch);
00303         // prevent duplicating object when copying in CbcModel.cpp
00304         model_.solver()->deleteObjects();
00305     }
00306 
00307     model_.setDblParam(CbcModel::CbcCutoffIncrement, s.getDoubleParameter(BabSetupBase::CutoffDecr));
00308 
00309     model_.setCutoff(s.getDoubleParameter(BabSetupBase::Cutoff) + CUTOFF_TOL);
00310 
00311     model_.setDblParam(CbcModel::CbcAllowableGap, s.getDoubleParameter(BabSetupBase::AllowableGap));
00312     model_.setDblParam(CbcModel::CbcAllowableFractionGap, s.getDoubleParameter(BabSetupBase::AllowableFractionGap));
00313 
00314     // Definition of node selection strategy
00315 
00316     if (s.nodeComparisonMethod()==BabSetupBase::bestBound) {
00317       CbcCompareObjective compare;
00318       model_.setNodeComparison(compare);
00319     }
00320     else if (s.nodeComparisonMethod()==BabSetupBase::DFS) {
00321       CbcCompareDepth compare;
00322       model_.setNodeComparison(compare);
00323     }
00324     else if (s.nodeComparisonMethod()==BabSetupBase::BFS) {
00325       CbcCompareDefault compare;
00326       compare.setWeight(0.0);
00327       model_.setNodeComparison(compare);
00328     }
00329     else if (s.nodeComparisonMethod()==BabSetupBase::dynamic) {
00330       CbcCompareDefault compare;
00331       model_.setNodeComparison(compare);
00332     }
00333     else if (s.nodeComparisonMethod()==BabSetupBase::bestGuess) {
00334       // Right now, this is a mess.  We need a separation of the
00335       // pseudo costs from the ChooseVariable method
00336       CbcCompareEstimate compare;
00337       model_.setNodeComparison(compare);
00338       GuessHeuristic * guessHeu = new GuessHeuristic(model_);
00339       model_.addHeuristic(guessHeu);
00340       delete guessHeu;
00341     }
00342 
00343     if (s.treeTraversalMethod() == BabSetupBase::HeapOnly) {
00344       //Do nothing this is the default of Cbc.
00345     }
00346     else if (s.treeTraversalMethod() == BabSetupBase::DiveFromBest) {
00347       CbcDiver treeTraversal;
00348       treeTraversal.initialize(s);
00349       model_.passInTreeHandler(treeTraversal);
00350     }
00351     else if (s.treeTraversalMethod() == BabSetupBase::ProbedDive) {
00352       CbcProbedDiver treeTraversal;
00353       treeTraversal.initialize(s);
00354       model_.passInTreeHandler(treeTraversal);
00355     }
00356     else if (s.treeTraversalMethod() == BabSetupBase::DfsDiveFromBest) {
00357       CbcDfsDiver treeTraversal;
00358       treeTraversal.initialize(s);
00359       model_.passInTreeHandler(treeTraversal);
00360     }
00361     else if (s.treeTraversalMethod() == BabSetupBase::DfsDiveDynamic) {
00362       CbcDfsDiver treeTraversal;
00363       treeTraversal.initialize(s);
00364       model_.passInTreeHandler(treeTraversal);
00365 
00366       DiverCompare compare;
00367       compare.setComparisonDive(*model_.nodeComparison());
00368       compare.setComparisonBound(CbcCompareObjective());
00369       CbcDfsDiver * dfs = dynamic_cast<CbcDfsDiver *> (model_.tree());
00370       assert(dfs);
00371       compare.setDiver(dfs);
00372       model_.setNodeComparison(compare);
00373     }
00374 
00375     model_.setNumberStrong(s.getIntParameter(BabSetupBase::NumberStrong));
00376 
00377     model_.setNumberBeforeTrust(s.getIntParameter(BabSetupBase::MinReliability));
00378     model_.setNumberPenalties(8);
00379 
00380     model_.setDblParam(CbcModel::CbcMaximumSeconds, s.getDoubleParameter(BabSetupBase::MaxTime));
00381 
00382     model_.setMaximumNodes(s.getIntParameter(BabSetupBase::MaxNodes));
00383 
00384     model_.setMaximumNumberIterations(s.getIntParameter(BabSetupBase::MaxIterations));
00385 
00386     model_.setMaximumSolutions(s.getIntParameter(BabSetupBase::MaxSolutions));
00387 
00388     model_.setIntegerTolerance(s.getDoubleParameter(BabSetupBase::IntTol));
00389 
00390 
00391 
00392     //Get objects from model_ if it is not null means there are some sos constraints or non-integer branching object
00393     // pass them to cut generators.
00394     OsiObject ** objects = model_.objects();
00395     if (specOpt!=16 && objects) {
00396       int numberObjects = model_.numberObjects();
00397       if (objects_ != NULL) {
00398         for (int i = 0 ; i < nObjects_; i++)
00399           delete objects_[i];
00400       }
00401       delete [] objects_;
00402       objects_ = new OsiObject*[numberObjects];
00403       nObjects_ = numberObjects;
00404       for (int i = 0 ; i < numberObjects; i++) {
00405         OsiObject * obj = objects[i];
00406         CbcSimpleInteger * intObj = dynamic_cast<CbcSimpleInteger *> (obj);
00407         if (intObj) {
00408           objects_[i] = intObj->osiObject();
00409         }
00410         else {
00411           CbcSOS * sosObj = dynamic_cast<CbcSOS *>(obj);
00412           if (sosObj) objects_[i] = sosObj->osiObject(model_.solver());
00413           else {//Maybe an unsupported CbcObject
00414             CbcObject * cbcObj = dynamic_cast<CbcObject *>(obj);
00415             if (cbcObj) {
00416               std::cerr<<"Unsupported CbcObject appears in the code"<<std::endl;
00417               throw UNSUPPORTED_CBC_OBJECT;
00418             }
00419             else {//It has to be an OsiObject.
00420               objects_[i]=obj->clone();
00421             }
00422           }
00423         }
00424       }
00425       CbcCutGenerator ** gen = model_.cutGenerators();
00426       int numGen = model_.numberCutGenerators();
00427       for (int i = 0 ; i < numGen ; i++) {
00428         OaDecompositionBase * oa = dynamic_cast<OaDecompositionBase * >(gen[i]->generator());
00429         if (oa)//pass objects
00430           oa->setObjects(objects_,nObjects_);
00431       }
00432     }
00433 
00434 
00435     try {
00436     //Get the time and start.
00437     {
00438       OsiTMINLPInterface * tmpOsi = NULL;
00439       if(s.nonlinearSolver() == s.continuousSolver()){
00440         tmpOsi = dynamic_cast<OsiTMINLPInterface *> (model_.solver());
00441         tmpOsi->forceSolverOutput(s.getIntParameter(BabSetupBase::RootLogLevel)); 
00442       }
00443       model_.initialSolve();
00444       if(tmpOsi != NULL){
00445         tmpOsi->setSolverOutputToDefault(); 
00446       }
00447     }
00448 
00449     int ival;
00450     s.options()->GetEnumValue("enable_dynamic_nlp", ival, "bonmin.");
00451     if(s.nonlinearSolver() == s.continuousSolver() && ival)
00452     {
00453       if(!model_.solver()->isProvenOptimal() ){//Something went wrong check if objective is linear and alternate model
00454                                             // can be solved
00455         OsiTMINLPInterface * tmpOsi = dynamic_cast<OsiTMINLPInterface *> (model_.solver());
00456         TMINLPLinObj * tmp_tminlp = dynamic_cast<TMINLPLinObj *> (tmpOsi->model());
00457         tmpOsi->setModel(tmp_tminlp->tminlp());
00458         model_.initialSolve();
00459       } 
00460       else {
00461         LinearCutsGenerator cgl;
00462         cgl.initialize(s); 
00463         OsiCuts cuts;
00464         cgl.generateCuts(*model_.solver(), cuts);
00465         std::vector<OsiRowCut *> mycuts(cuts.sizeRowCuts());
00466         for(int i = 0 ; i < cuts.sizeRowCuts() ; i++){
00467           mycuts[i] = cuts.rowCutPtr(i);
00468         }
00469         model_.solver()->applyRowCuts(mycuts.size(), (const OsiRowCut **) &mycuts[0]);
00470       }
00471 
00472        //Added by Claudia
00473        OsiTMINLPInterface * nlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver());
00474        if(nlpSolver && nlpSolver->getNewCutoffDecr()!=COIN_DBL_MAX)
00475           model_.setDblParam(CbcModel::CbcCutoffIncrement, nlpSolver->getNewCutoffDecr());
00476 
00477     model_.solver()->resolve();
00478 
00479     }
00480 
00481     // for Couenne
00482     if (usingCouenne_)
00483       model_.passInSolverCharacteristics (bonBabInfoPtr);
00484 
00485     continuousRelaxation_ =model_.solver()->getObjValue();
00486     if (specOpt==16)//Set warm start point for Ipopt
00487     {
00488 #if 1
00489       const double * colsol = model_.solver()->getColSolution();
00490       const double * duals = model_.solver()->getRowPrice();
00491       model_.solver()->setColSolution(colsol);
00492       model_.solver()->setRowPrice(duals);
00493 #else
00494       OsiTMINLPInterface * tnlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver());
00495       CoinWarmStart * warm = tnlpSolver->solver()->getWarmStart(tnlpSolver->problem());
00496       tnlpSolver->solver()->setWarmStart(warm, tnlpSolver->problem());
00497       delete warm;
00498 #endif
00499     }
00500 
00501 #ifdef SIGNAL
00502     CoinSighandler_t saveSignal=SIG_DFL;
00503     // register signal handler
00504     saveSignal = signal(SIGINT,signal_handler);
00505 #endif
00506 
00507     currentBranchModel = &model_;
00508 
00509     // to get node parent info in Cbc, pass parameter 3.
00510     //model_.branchAndBound(3);
00511     model_.branchAndBound();
00512     }
00513     catch(TNLPSolver::UnsolvedError *E){
00514       s.nonlinearSolver()->model()->finalize_solution(TMINLP::MINLP_ERROR,
00515            0,
00516            NULL,
00517            DBL_MAX);
00518       throw E;
00519    
00520     }
00521     numNodes_ = model_.getNodeCount();
00522     bestObj_ = model_.getObjValue();
00523     bestBound_ = model_.getBestPossibleObjValue();
00524     mipIterationCount_ = model_.getIterationCount();
00525 
00526     bool hasFailed = false;
00527     if (specOpt==16)//Did we continue branching on a failure
00528     {
00529       CbcNlpStrategy * nlpStrategy = dynamic_cast<CbcNlpStrategy *>(model_.strategy());
00530       if (nlpStrategy)
00531         hasFailed = nlpStrategy->hasFailed();
00532       else
00533         throw -1;
00534     }
00535     else
00536       hasFailed = s.nonlinearSolver()->hasContinuedOnAFailure();
00537 
00538     // Output summarizing cut generators (taken from CbcSolver.cpp)
00539     // ToDo put into proper print level
00540 
00541     
00542 
00543     int numberGenerators = model_.numberCutGenerators();
00544     for (int iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
00545       CbcCutGenerator * generator = model_.cutGenerator(iGenerator);
00546       //CglStored * stored = dynamic_cast<CglStored*>(generator->generator());
00547        if (true&&!generator->numberCutsInTotal())
00548         continue;
00549        if(modelHandler_->logLevel() >= 1) {
00550         *modelHandler_ << generator->cutGeneratorName()
00551                 << "was tried" << generator->numberTimesEntered()
00552                 << "times and created" << generator->numberCutsInTotal()+generator->numberColumnCuts()
00553                 << "cuts of which" << generator->numberCutsActive()
00554                 << "were active after adding rounds of cuts";
00555          if (generator->timing()) {
00556                 char timebuf[20];
00557                 sprintf(timebuf, "(%.3fs)", generator->timeInCutGenerator());
00558                 *modelHandler_ << timebuf << CoinMessageEol;
00559          }
00560          else {
00561                 *modelHandler_ << CoinMessageEol;
00562          }
00563        }
00564     }
00565 
00566     if (hasFailed) {
00567         *model_.messageHandler()
00568       << "************************************************************" << CoinMessageEol
00569       << "WARNING : Optimization failed on an NLP during optimization"  << CoinMessageEol
00570       << "  (no optimal value found within tolerances)."  << CoinMessageEol
00571       << "  Optimization was not stopped because option"  << CoinMessageEol
00572       << "\"nlp_failure_behavior\" has been set to fathom but"  << CoinMessageEol
00573       << " beware that reported solution may not be optimal"  << CoinMessageEol
00574       << "************************************************************" << CoinMessageEol;
00575     }
00576     TMINLP::SolverReturn status = TMINLP::MINLP_ERROR;
00577 
00578     if (model_.numberObjects()==0) {
00579       if (bestSolution_)
00580         delete [] bestSolution_;
00581       OsiSolverInterface * solver = 
00582              (s.nonlinearSolver() == s.continuousSolver())? 
00583              model_.solver() : s.nonlinearSolver();
00584       bestSolution_ = new double[solver->getNumCols()];
00585       CoinCopyN(solver->getColSolution(), solver->getNumCols(),
00586           bestSolution_);
00587       bestObj_ = bestBound_ = solver->getObjValue();
00588     }
00589 
00590     if (bonBabInfoPtr->bestSolution2().size() > 0) {
00591       assert((int) bonBabInfoPtr->bestSolution2().size() == s.nonlinearSolver()->getNumCols());
00592       if (bestSolution_)
00593         delete [] bestSolution_;
00594       bestSolution_ = new double[s.nonlinearSolver()->getNumCols()];
00595       std::copy(bonBabInfoPtr->bestSolution2().begin(), bonBabInfoPtr->bestSolution2().end(),
00596           bestSolution_);
00597       bestObj_ = (bonBabInfoPtr->bestObj2());
00598        (*s.nonlinearSolver()->messageHandler())<<"\nReal objective function: "
00599                                             <<bestObj_<<CoinMessageEol;
00600     }
00601     else if (model_.bestSolution()) {
00602       if (bestSolution_)
00603         delete [] bestSolution_;
00604       bestSolution_ = new double[s.nonlinearSolver()->getNumCols()];
00605       CoinCopyN(model_.bestSolution(), s.nonlinearSolver()->getNumCols(), bestSolution_);
00606     }
00607     if (model_.status() == 0) {
00608       if(model_.isContinuousUnbounded()){
00609         status = TMINLP::CONTINUOUS_UNBOUNDED;
00610         mipStatus_ = UnboundedOrInfeasible;
00611       }
00612       else
00613       if (bestSolution_) {
00614         status = TMINLP::SUCCESS;
00615         mipStatus_ = FeasibleOptimal;
00616       }
00617       else {
00618         status = TMINLP::INFEASIBLE;
00619         mipStatus_ = ProvenInfeasible;
00620       }
00621     }
00622     else if (model_.status() == 1) {
00623       status = TMINLP::LIMIT_EXCEEDED;
00624       if (bestSolution_) {
00625         mipStatus_ = Feasible;
00626       }
00627       else {
00628         mipStatus_ = NoSolutionKnown;
00629       }
00630     }
00631     else if (model_.status()==2) {
00632       status = TMINLP::MINLP_ERROR;
00633     }
00634     s.nonlinearSolver()->model()->finalize_solution(status,
00635         s.nonlinearSolver()->getNumCols(),
00636         bestSolution_,
00637         bestObj_);
00638   }
00639 
00640 
00642   double
00643   Bab::bestBound()
00644   {
00645     if (mipStatus_ == FeasibleOptimal) return bestObj_;
00646     else if (mipStatus_ == ProvenInfeasible) return 1e200;
00647     else return bestBound_;
00648   }
00649 }

Generated on Thu Aug 5 03:02:54 2010 by  doxygen 1.4.7