source: trunk/Couenne/src/main/CouenneBab.cpp @ 972

Last change on this file since 972 was 885, checked in by pbelotti, 8 years ago

updating to SCIP 3.0.0

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