source: trunk/Bonmin/src/CbcBonmin/BonCbc.cpp @ 1413

Last change on this file since 1413 was 1413, checked in by pbonami, 11 years ago

Fix for B-BB when problem is continuous

File size: 21.5 KB
Line 
1// (C) Copyright International Business Machines Corporation 2007
2// All Rights Reserved.
3// This code is published under the Common Public License.
4//
5// Authors :
6// Pierre Bonami, International Business Machines Corporation
7//
8// Date : 04/19/2007
9
10
11#include "BonCbc.hpp"
12#include "BonOACutGenerator2.hpp"
13#include "BonCbcNlpStrategy.hpp"
14#include "BonBabInfos.hpp"
15#include "CbcModel.hpp"
16#include "CbcBranchActual.hpp"
17#include "CbcCutGenerator.hpp"
18#include "CbcCompareActual.hpp"
19
20#include "BonExitCodes.hpp"
21
22#include "BonChooseVariable.hpp"
23#include "BonGuessHeuristic.hpp"
24
25#include "BonDiver.hpp"
26#include "BonLinearCutsGenerator.hpp"
27#include "BonTMINLPLinObj.hpp"
28// sets cutoff a bit above real one, to avoid single-point feasible sets
29#define CUTOFF_TOL 1e-6
30
31// Code to enable user interuption
32static CbcModel * currentBranchModel = NULL; //pointer to the main b&b
33Bonmin::OACutGenerator2 * currentOA = NULL; //pointer to the OA generator
34CbcModel * OAModel; // pointer to the submip if using Cbc
35bool BonminAbortAll;
36
37#define SIGNAL
38#ifdef SIGNAL
39#include "CoinSignal.hpp"
40
41extern "C"
42{
43
44  static bool BonminInteruptedOnce =false;
45  static void signal_handler(int whichSignal) {
46    if (BonminInteruptedOnce) {
47      std::cerr<<"User forced interuption"<<std::endl;
48      exit(0);
49    }
50    if (currentBranchModel!=NULL)
51      currentBranchModel->setMaximumNodes(0); // stop at next node
52    if (OAModel!=NULL)
53      OAModel->setMaximumNodes(0); // stop at next node
54    if (currentOA!=NULL)
55      currentOA->parameter().maxLocalSearchTime_ = 0.; // stop OA
56    BonminAbortAll = true;
57    BonminInteruptedOnce = true;
58    return;
59  }
60}
61#endif
62
63namespace Bonmin
64{
65
66  /** Constructor.*/
67  Bab::Bab():
68      bestSolution_(NULL),
69      mipStatus_(),
70      bestObj_(1e200),
71      bestBound_(-1e200),
72      continuousRelaxation_(-COIN_DBL_MAX),
73      numNodes_(0),
74      mipIterationCount_(0),
75      model_(),
76      modelHandler_(NULL),
77      objects_(0),
78      nObjects_(0),
79      usingCouenne_(false)
80  {}
81
82  /** Destructor.*/
83  Bab::~Bab()
84  {
85    if (bestSolution_) delete [] bestSolution_;
86    bestSolution_ = NULL;
87    for ( int i = 0 ; i < nObjects_ ; i++) {
88      delete objects_[i];
89    }
90    delete [] objects_;
91    delete modelHandler_;
92  }
93
94  /**operator() performs the branchAndBound*/
95  void
96  Bab::operator()(BabSetupBase & s)
97  {
98    branchAndBound(s);
99  }
100
101  /** Perform a branch-and-bound on given setup.*/
102  void
103  Bab::branchAndBound(BabSetupBase & s)
104  {
105    /* Put a link to this into solver.*/
106    OsiBabSolver *  babInfo = dynamic_cast<OsiBabSolver *>(s.continuousSolver()->getAuxiliaryInfo());
107    assert(babInfo);
108    Bonmin::BabInfo *  bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(babInfo);
109    if (bonBabInfoPtr == NULL) {//Replace with a Bonmin::babInfo
110      bonBabInfoPtr = new Bonmin::BabInfo(*babInfo);
111      s.continuousSolver()->setAuxiliaryInfo(bonBabInfoPtr);
112      delete bonBabInfoPtr;
113      bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(s.continuousSolver()->getAuxiliaryInfo());
114    }
115    bonBabInfoPtr->setBabPtr(this);
116
117    OsiSolverInterface * solver = s.continuousSolver()->clone();
118    delete modelHandler_;
119    modelHandler_ = s.continuousSolver()->messageHandler()->clone();
120    model_.passInMessageHandler(modelHandler_);
121    model_.assignSolver(solver, true);
122
123    //  s.continuousSolver() = model_.solver();
124    //   if(s.continuousSolver()->objects()!=NULL){
125    //     model_.addObjects(s.continuousSolver()->numberObjects(),s.continuousSolver()->objects());
126    //   }
127
128    int specOpt = s.getIntParameter(BabSetupBase::SpecialOption);
129    if (specOpt) {
130      model_.setSpecialOptions(specOpt);
131      if (specOpt==16) {
132        CbcNlpStrategy strat(s.getIntParameter(BabSetupBase::MaxFailures), 
133                             s.getIntParameter(BabSetupBase::MaxInfeasible), 
134                             s.getIntParameter(BabSetupBase::FailureBehavior));
135        model_.setStrategy(strat);
136      }
137    }
138
139    model_.setMaximumCutPasses(s.getIntParameter(BabSetupBase::NumCutPasses));
140    model_.setMaximumCutPassesAtRoot(s.getIntParameter(BabSetupBase::NumCutPassesAtRoot));
141
142    //Setup cutting plane methods
143    for (BabSetupBase::CuttingMethods::iterator i = s.cutGenerators().begin() ;
144        i != s.cutGenerators().end() ; i++) {
145
146      OaDecompositionBase * oa = dynamic_cast<OaDecompositionBase *>(i->cgl);
147      if (oa && oa->reassignLpsolver())
148        oa->assignLpInterface(model_.solver());
149        model_.addCutGenerator(i->cgl,i->frequency,i->id.c_str(), i->normal,
150                               i->atSolution);
151    }
152
153    for (BabSetupBase::HeuristicMethods::iterator i = s.heuristics().begin() ;
154        i != s.heuristics().end() ; i++) {
155      CbcHeuristic * heu = i->heuristic;
156      heu->setModel(&model_);
157      model_.addHeuristic(heu, i->id.c_str());
158    }
159
160
161    //need to record solver logLevel here
162    int logLevel = s.continuousSolver()->messageHandler()->logLevel();
163
164    //Set true branch-and-bound parameters
165    model_.setLogLevel(s.getIntParameter(BabSetupBase::BabLogLevel));
166
167    // Put back solver logLevel
168    model_.solver()->messageHandler()->setLogLevel(logLevel);
169
170    model_.setPrintFrequency(s.getIntParameter(BabSetupBase::BabLogInterval));
171
172    bool ChangedObject = false;
173    //Pass over user set branching priorities to Cbc
174    if (s.continuousSolver()->objects()==NULL) {
175      //assert (s.branchingMethod() == NULL);
176      const OsiTMINLPInterface * nlpSolver = s.nonlinearSolver();
177      //set priorities, prefered directions...
178      const int * priorities = nlpSolver->getPriorities();
179      const double * upPsCosts = nlpSolver->getUpPsCosts();
180      const double * downPsCosts = nlpSolver->getDownPsCosts();
181      const int * directions = nlpSolver->getBranchingDirections();
182      bool hasPseudo = (upPsCosts!=NULL);
183      model_.findIntegers(true,hasPseudo);
184      OsiObject ** simpleIntegerObjects = model_.objects();
185      int numberObjects = model_.numberObjects();
186      if (priorities != NULL || directions != NULL || hasPseudo) {
187        ChangedObject = true;
188        for (int i = 0 ; i < numberObjects ; i++) {
189          CbcObject * object = dynamic_cast<CbcObject *>
190              (simpleIntegerObjects[i]);
191          int iCol = object->columnNumber();
192          if (priorities)
193            object->setPriority(priorities[iCol]);
194          if (directions)
195            object->setPreferredWay(directions[iCol]);
196          if (upPsCosts) {
197            CbcSimpleIntegerPseudoCost * pscObject =
198              dynamic_cast<CbcSimpleIntegerPseudoCost*> (object);
199            pscObject->setUpPseudoCost(upPsCosts[iCol]);
200            pscObject->setDownPseudoCost(downPsCosts[iCol]);
201          }
202        }
203      }
204
205#if 1
206      // Now pass user set Sos constraints (code inspired from CoinSolve.cpp)
207      const TMINLP::SosInfo * sos = s.nonlinearSolver()->model()->sosConstraints();
208      if (!s.getIntParameter(BabSetupBase::DisableSos) && sos && sos->num > 0) 
209        //we have some sos constraints
210      {
211        const OsiTMINLPInterface * nlpSolver = s.nonlinearSolver();
212        const int & numSos = sos->num;
213       (*nlpSolver->messageHandler())<<"Adding "<<sos->num<<" sos constraints."
214                                     <<CoinMessageEol;
215
216        CbcObject ** objects = new CbcObject*[numSos];
217        const int * starts = sos->starts;
218        const int * indices = sos->indices;
219        const char * types = sos->types;
220        const double * weights = sos->weights;
221        //verify if model has user set priorities
222        bool hasPriorities = false;
223        const int * varPriorities = nlpSolver->getPriorities();
224        int numberObjects = model_.numberObjects();
225        if (varPriorities)
226        {
227          for (int i = 0 ; i < numberObjects ; i++) {
228            if (varPriorities[i]) {
229              hasPriorities = true;
230              break;
231            }
232          }
233        }
234        const int * sosPriorities = sos->priorities;
235        if (sosPriorities)
236        {
237          for (int i = 0 ; i < numSos ; i++) {
238            if (sosPriorities[i]) {
239              hasPriorities = true;
240              break;
241            }
242          }
243        }
244        for (int i = 0 ; i < numSos ; i++)
245        {
246          int start = starts[i];
247          int length = starts[i + 1] - start;
248          objects[i] = new CbcSOS(&model_, length, &indices[start],
249              &weights[start], i, types[i]);
250
251          objects[i]->setPriority(10);
252          if (hasPriorities && sosPriorities && sosPriorities[i]) {
253            objects[i]->setPriority(sosPriorities[i]);
254          }
255        }
256        model_.addObjects(numSos, objects);
257        for (int i = 0 ; i < numSos ; i++)
258          delete objects[i];
259        delete [] objects;
260      }
261#endif
262      //If Setup contains more objects add them to Cbc
263      if (s.objects().size()) {
264        CbcObject ** objects = new CbcObject *[s.objects().size()];
265        for (unsigned int i = 0 ; i < s.objects().size() ; i++) {
266          objects[i] = dynamic_cast<CbcObject *> (s.objects()[i]);
267          assert(objects[i]);
268          objects[i]->setModel(&model_);
269        }
270        model_.addObjects(s.objects().size(), objects);
271        delete [] objects;
272      }
273
274      replaceIntegers(model_.objects(), model_.numberObjects());
275    }
276    else {//Pass in objects to Cbc
277    // Redundant definition of default branching (as Default == User)
278    assert (s.branchingMethod() != NULL);
279
280    if (!usingCouenne_)
281      model_.addObjects (s.continuousSolver()->numberObjects(),
282                         s.continuousSolver()->objects());
283    else {
284      // add nonlinear and integer objects (need to add OsiSOS)
285      int nco = s.continuousSolver () -> numberObjects ();
286      OsiObject **objs = new OsiObject * [nco];
287      for (int i=0; i<nco; i++) 
288        objs [i] = s.continuousSolver () -> objects () [i];
289      model_.addObjects (nco, objs);
290      delete [] objs;
291    }
292
293    CbcBranchDefaultDecision branch;
294    s.branchingMethod()->setSolver(model_.solver());
295    BonChooseVariable * strong2 = dynamic_cast<BonChooseVariable *>(s.branchingMethod());
296    if (strong2)
297      strong2->setCbcModel(&model_);
298    branch.setChooseMethod(*s.branchingMethod());
299
300    model_.setBranchingMethod(&branch);
301        // prevent duplicating object when copying in CbcModel.cpp
302        model_.solver()->deleteObjects();
303    }
304
305    model_.setDblParam(CbcModel::CbcCutoffIncrement, s.getDoubleParameter(BabSetupBase::CutoffDecr));
306
307    model_.setCutoff(s.getDoubleParameter(BabSetupBase::Cutoff) + CUTOFF_TOL);
308
309    model_.setDblParam(CbcModel::CbcAllowableGap, s.getDoubleParameter(BabSetupBase::AllowableGap));
310    model_.setDblParam(CbcModel::CbcAllowableFractionGap, s.getDoubleParameter(BabSetupBase::AllowableFractionGap));
311
312    // Definition of node selection strategy
313
314    if (s.nodeComparisonMethod()==BabSetupBase::bestBound) {
315      CbcCompareObjective compare;
316      model_.setNodeComparison(compare);
317    }
318    else if (s.nodeComparisonMethod()==BabSetupBase::DFS) {
319      CbcCompareDepth compare;
320      model_.setNodeComparison(compare);
321    }
322    else if (s.nodeComparisonMethod()==BabSetupBase::BFS) {
323      CbcCompareDefault compare;
324      compare.setWeight(0.0);
325      model_.setNodeComparison(compare);
326    }
327    else if (s.nodeComparisonMethod()==BabSetupBase::dynamic) {
328      CbcCompareDefault compare;
329      model_.setNodeComparison(compare);
330    }
331    else if (s.nodeComparisonMethod()==BabSetupBase::bestGuess) {
332      // Right now, this is a mess.  We need a separation of the
333      // pseudo costs from the ChooseVariable method
334      CbcCompareEstimate compare;
335      model_.setNodeComparison(compare);
336      GuessHeuristic * guessHeu = new GuessHeuristic(model_);
337      model_.addHeuristic(guessHeu);
338      delete guessHeu;
339    }
340
341    if (s.treeTraversalMethod() == BabSetupBase::HeapOnly) {
342      //Do nothing this is the default of Cbc.
343    }
344    else if (s.treeTraversalMethod() == BabSetupBase::DiveFromBest) {
345      CbcDiver treeTraversal;
346      treeTraversal.initialize(s);
347      model_.passInTreeHandler(treeTraversal);
348    }
349    else if (s.treeTraversalMethod() == BabSetupBase::ProbedDive) {
350      CbcProbedDiver treeTraversal;
351      treeTraversal.initialize(s);
352      model_.passInTreeHandler(treeTraversal);
353    }
354    else if (s.treeTraversalMethod() == BabSetupBase::DfsDiveFromBest) {
355      CbcDfsDiver treeTraversal;
356      treeTraversal.initialize(s);
357      model_.passInTreeHandler(treeTraversal);
358    }
359    else if (s.treeTraversalMethod() == BabSetupBase::DfsDiveDynamic) {
360      CbcDfsDiver treeTraversal;
361      treeTraversal.initialize(s);
362      model_.passInTreeHandler(treeTraversal);
363
364      DiverCompare compare;
365      compare.setComparisonDive(*model_.nodeComparison());
366      compare.setComparisonBound(CbcCompareObjective());
367      CbcDfsDiver * dfs = dynamic_cast<CbcDfsDiver *> (model_.tree());
368      assert(dfs);
369      compare.setDiver(dfs);
370      model_.setNodeComparison(compare);
371    }
372
373    model_.setNumberStrong(s.getIntParameter(BabSetupBase::NumberStrong));
374
375    model_.setNumberBeforeTrust(s.getIntParameter(BabSetupBase::MinReliability));
376    model_.setNumberPenalties(8);
377
378    model_.setDblParam(CbcModel::CbcMaximumSeconds, s.getDoubleParameter(BabSetupBase::MaxTime));
379
380    model_.setMaximumNodes(s.getIntParameter(BabSetupBase::MaxNodes));
381
382    model_.setMaximumSolutions(s.getIntParameter(BabSetupBase::MaxSolutions));
383
384    model_.setIntegerTolerance(s.getDoubleParameter(BabSetupBase::IntTol));
385
386
387
388    //Get objects from model_ if it is not null means there are some sos constraints or non-integer branching object
389    // pass them to cut generators.
390    OsiObject ** objects = model_.objects();
391    if (specOpt!=16 && objects) {
392      int numberObjects = model_.numberObjects();
393      if (objects_ != NULL) {
394        for (int i = 0 ; i < nObjects_; i++)
395          delete objects_[i];
396      }
397      delete [] objects_;
398      objects_ = new OsiObject*[numberObjects];
399      nObjects_ = numberObjects;
400      for (int i = 0 ; i < numberObjects; i++) {
401        OsiObject * obj = objects[i];
402        CbcSimpleInteger * intObj = dynamic_cast<CbcSimpleInteger *> (obj);
403        if (intObj) {
404          objects_[i] = intObj->osiObject();
405        }
406        else {
407          CbcSOS * sosObj = dynamic_cast<CbcSOS *>(obj);
408          if (sosObj) objects_[i] = sosObj->osiObject(model_.solver());
409          else {//Maybe an unsupported CbcObject
410            CbcObject * cbcObj = dynamic_cast<CbcObject *>(obj);
411            if (cbcObj) {
412              std::cerr<<"Unsupported CbcObject appears in the code"<<std::endl;
413              throw UNSUPPORTED_CBC_OBJECT;
414            }
415            else {//It has to be an OsiObject.
416              objects_[i]=obj->clone();
417            }
418          }
419        }
420      }
421      CbcCutGenerator ** gen = model_.cutGenerators();
422      int numGen = model_.numberCutGenerators();
423      for (int i = 0 ; i < numGen ; i++) {
424        OaDecompositionBase * oa = dynamic_cast<OaDecompositionBase * >(gen[i]->generator());
425        if (oa)//pass objects
426          oa->setObjects(objects_,nObjects_);
427      }
428    }
429
430
431    try {
432    //Get the time and start.
433    model_.initialSolve();
434
435
436    int ival;
437    s.options()->GetEnumValue("enable_dynamic_nlp", ival, "bonmin.");
438    if(s.nonlinearSolver() == s.continuousSolver() && ival)
439    {
440      if(!model_.solver()->isProvenOptimal() ){//Something went wrong check if objective is linear and alternate model
441                                            // can be solved
442        OsiTMINLPInterface * tmpOsi = dynamic_cast<OsiTMINLPInterface *> (model_.solver());
443        TMINLPLinObj * tmp_tminlp = dynamic_cast<TMINLPLinObj *> (tmpOsi->model());
444        tmpOsi->setModel(tmp_tminlp->tminlp());
445        model_.initialSolve();
446      } 
447      else {
448        LinearCutsGenerator cgl;
449        cgl.initialize(s); 
450        OsiCuts cuts;
451        cgl.generateCuts(*model_.solver(), cuts);
452        std::vector<OsiRowCut *> mycuts(cuts.sizeRowCuts());
453        for(int i = 0 ; i < cuts.sizeRowCuts() ; i++){
454          mycuts[i] = cuts.rowCutPtr(i);
455        }
456        model_.solver()->applyRowCuts(mycuts.size(), (const OsiRowCut **) &mycuts[0]);
457      }
458    }
459
460    model_.solver()->resolve();
461
462    // for Couenne
463    if (usingCouenne_)
464      model_.passInSolverCharacteristics (bonBabInfoPtr);
465
466    continuousRelaxation_ =model_.solver()->getObjValue();
467    if (specOpt==16)//Set warm start point for Ipopt
468    {
469#if 1
470      const double * colsol = model_.solver()->getColSolution();
471      const double * duals = model_.solver()->getRowPrice();
472      model_.solver()->setColSolution(colsol);
473      model_.solver()->setRowPrice(duals);
474#else
475      OsiTMINLPInterface * tnlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver());
476      CoinWarmStart * warm = tnlpSolver->solver()->getWarmStart(tnlpSolver->problem());
477      tnlpSolver->solver()->setWarmStart(warm, tnlpSolver->problem());
478      delete warm;
479#endif
480    }
481
482#ifdef SIGNAL
483    CoinSighandler_t saveSignal=SIG_DFL;
484    // register signal handler
485    saveSignal = signal(SIGINT,signal_handler);
486#endif
487
488    currentBranchModel = &model_;
489
490    // to get node parent info in Cbc, pass parameter 3.
491    //model_.branchAndBound(3);
492    model_.branchAndBound();
493    }
494    catch(TNLPSolver::UnsolvedError *E){
495      s.nonlinearSolver()->model()->finalize_solution(TMINLP::MINLP_ERROR,
496           0,
497           NULL,
498           DBL_MAX);
499      throw E;
500   
501    }
502    numNodes_ = model_.getNodeCount();
503    bestObj_ = model_.getObjValue();
504    bestBound_ = model_.getBestPossibleObjValue();
505    mipIterationCount_ = model_.getIterationCount();
506
507    bool hasFailed = false;
508    if (specOpt==16)//Did we continue branching on a failure
509    {
510      CbcNlpStrategy * nlpStrategy = dynamic_cast<CbcNlpStrategy *>(model_.strategy());
511      if (nlpStrategy)
512        hasFailed = nlpStrategy->hasFailed();
513      else
514        throw -1;
515    }
516    else
517      hasFailed = s.nonlinearSolver()->hasContinuedOnAFailure();
518
519    // Output summarizing cut generators (taken from CbcSolver.cpp)
520    // ToDo put into proper print level
521
522   
523
524    int numberGenerators = model_.numberCutGenerators();
525    for (int iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
526      CbcCutGenerator * generator = model_.cutGenerator(iGenerator);
527      //CglStored * stored = dynamic_cast<CglStored*>(generator->generator());
528       if (true&&!generator->numberCutsInTotal())
529        continue;
530       if(modelHandler_->logLevel() >= 1) {
531        *modelHandler_ << generator->cutGeneratorName()
532                << "was tried" << generator->numberTimesEntered()
533                << "times and created" << generator->numberCutsInTotal()+generator->numberColumnCuts()
534                << "cuts of which" << generator->numberCutsActive()
535                << "were active after adding rounds of cuts";
536         if (generator->timing()) {
537                char timebuf[20];
538                sprintf(timebuf, "(%.3fs)", generator->timeInCutGenerator());
539                *modelHandler_ << timebuf << CoinMessageEol;
540         }
541         else {
542                *modelHandler_ << CoinMessageEol;
543         }
544       }
545    }
546
547    if (hasFailed) {
548        *model_.messageHandler()
549      << "************************************************************" << CoinMessageEol
550      << "WARNING : Optimization failed on an NLP during optimization"  << CoinMessageEol
551      << "  (no optimal value found within tolerances)."  << CoinMessageEol
552      << "  Optimization was not stopped because option"  << CoinMessageEol
553      << "\"nlp_failure_behavior\" has been set to fathom but"  << CoinMessageEol
554      << " beware that reported solution may not be optimal"  << CoinMessageEol
555      << "************************************************************" << CoinMessageEol;
556    }
557    TMINLP::SolverReturn status = TMINLP::MINLP_ERROR;
558
559    if (model_.numberObjects()==0) {
560      if (bestSolution_)
561        delete [] bestSolution_;
562      OsiSolverInterface * solver = 
563             (s.nonlinearSolver() == s.continuousSolver())? 
564             model_.solver() : s.nonlinearSolver();
565      bestSolution_ = new double[solver->getNumCols()];
566      CoinCopyN(solver->getColSolution(), solver->getNumCols(),
567          bestSolution_);
568      bestObj_ = bestBound_ = solver->getObjValue();
569    }
570
571    if (bonBabInfoPtr->bestSolution2().size() > 0) {
572      assert((int) bonBabInfoPtr->bestSolution2().size() == s.nonlinearSolver()->getNumCols());
573      if (bestSolution_)
574        delete [] bestSolution_;
575      bestSolution_ = new double[s.nonlinearSolver()->getNumCols()];
576      std::copy(bonBabInfoPtr->bestSolution2().begin(), bonBabInfoPtr->bestSolution2().end(),
577          bestSolution_);
578      bestObj_ = (bonBabInfoPtr->bestObj2());
579       (*s.nonlinearSolver()->messageHandler())<<"\nReal objective function: "
580                                            <<bestObj_<<CoinMessageEol;
581    }
582    else if (model_.bestSolution()) {
583      if (bestSolution_)
584        delete [] bestSolution_;
585      bestSolution_ = new double[s.nonlinearSolver()->getNumCols()];
586      CoinCopyN(model_.bestSolution(), s.nonlinearSolver()->getNumCols(), bestSolution_);
587    }
588    if (model_.status() == 0) {
589      if (bestSolution_) {
590        status = TMINLP::SUCCESS;
591        mipStatus_ = FeasibleOptimal;
592      }
593      else {
594        status = TMINLP::INFEASIBLE;
595        mipStatus_ = ProvenInfeasible;
596      }
597    }
598    else if (model_.status() == 1) {
599      status = TMINLP::LIMIT_EXCEEDED;
600      if (bestSolution_) {
601        mipStatus_ = Feasible;
602      }
603      else {
604        mipStatus_ = NoSolutionKnown;
605      }
606    }
607    else if (model_.status()==2) {
608      status = TMINLP::MINLP_ERROR;
609    }
610    s.nonlinearSolver()->model()->finalize_solution(status,
611        s.nonlinearSolver()->getNumCols(),
612        bestSolution_,
613        bestObj_);
614  }
615
616
617  /** return the best known lower bound on the objective value*/
618  double
619  Bab::bestBound()
620  {
621    if (mipStatus_ == FeasibleOptimal) return bestObj_;
622    else if (mipStatus_ == ProvenInfeasible) return 1e200;
623    else return bestBound_;
624  }
625}
Note: See TracBrowser for help on using the repository browser.