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

Generated on Thu Oct 8 03:02:54 2009 by  doxygen 1.4.7