source: stable/0.4/Couenne/src/main/CouenneBab.cpp @ 855

Last change on this file since 855 was 855, checked in by stefan, 8 years ago

check also CouenneRecordBestSol::getHasSol() when deciding whether to pass cbc or own recorded solution (it seems possible that cbc found a solution, problem_ -> getRecordBestSol () is not NULL, but there is no solution recorded there)

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