CouenneBab.cpp
Go to the documentation of this file.
1 /* $Id: CouenneBab.cpp 1009 2013-10-17 22:49:30Z pbelotti $
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"
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
44 static CbcModel * currentBranchModel = NULL; // pointer to the main b&b
45 extern Bonmin::OACutGenerator2 *currentOA; // pointer to the OA generator
46 extern CbcModel *OAModel; // pointer to the submip if using Cbc
47 
48 extern "C" {
49 
50  static bool interruptedOnce = false;
51 
52  static void couenne_signal_handler (int whichSignal) {
53 
54  if (interruptedOnce) {
55  std::cerr<<"[BREAK]"<<std::endl;
56  //abort ();
57  exit (-1);
58  } else
59  std::cerr<<"Ctrl+C detected, stopping Couenne..." << std::endl;
60 
61  if (currentBranchModel) currentBranchModel -> sayEventHappened(); // stop at next node
62  if (OAModel) OAModel -> sayEventHappened(); // stop at next node
63  if (currentOA) currentOA -> parameter ().maxLocalSearchTime_ = 0.; // stop OA
64 
65  interruptedOnce = true;
66  }
67 }
68 #endif
69 
70 using namespace Couenne;
71 using namespace Bonmin;
72 
74 CouenneBab::CouenneBab (): Bab (), problem_(NULL) {}
75 
78 
80 {problem_ = p;}
81 
82 
85 
86  double remaining_time = s.getDoubleParameter(Bonmin::BabSetupBase::MaxTime) + CoinCpuTime();
87 
88  /* Put a link to this into solver.*/
89  OsiBabSolver * babInfo = dynamic_cast<OsiBabSolver *>(s.continuousSolver()->getAuxiliaryInfo());
90  assert(babInfo);
91  Bonmin::BabInfo * bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(babInfo);
92 
93  if (bonBabInfoPtr == NULL) { //Replace with a Bonmin::babInfo
94  bonBabInfoPtr = new Bonmin::BabInfo(*babInfo);
95  s.continuousSolver()->setAuxiliaryInfo(bonBabInfoPtr);
96  delete bonBabInfoPtr;
97  bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(s.continuousSolver()->getAuxiliaryInfo());
98  }
99 
100  bonBabInfoPtr->setBabPtr(this);
101 
103  OsiSolverInterface * solver = s.continuousSolver()->clone();
104  delete modelHandler_;
105  modelHandler_ = s.continuousSolver()->messageHandler()->clone();
106  model_.passInMessageHandler(modelHandler_);
107  model_.assignSolver(solver, true);
108 
109  // s.continuousSolver() = model_.solver();
110  // if(s.continuousSolver()->objects()!=NULL){
111  // model_.addObjects(s.continuousSolver()->numberObjects(),s.continuousSolver()->objects());
112  // }
113 
115  if (specOpt) {
116  model_.setSpecialOptions(specOpt);
117  if (specOpt==16) {
121  model_.setStrategy(strat);
122  }
123  }
124 
127 
128  //Setup cutting plane methods
129  for (Bonmin::BabSetupBase::CuttingMethods::iterator i = s.cutGenerators().begin() ;
130  i != s.cutGenerators().end() ; i++) {
131 
132  Bonmin::OaDecompositionBase * oa = dynamic_cast<Bonmin::OaDecompositionBase *>(i->cgl);
133  if (oa && oa->reassignLpsolver())
134  oa->assignLpInterface(model_.solver());
135  model_.addCutGenerator(i->cgl,i->frequency,i->id.c_str(), i->normal,
136  i->atSolution);
137  if(i->always){
138  model_.cutGenerators()[model_.numberCutGenerators()-1]
139  ->setMustCallAgain(true);
140  }
141  }
142 
143  for (Bonmin::BabSetupBase::HeuristicMethods::iterator i = s.heuristics().begin() ;
144  i != s.heuristics().end() ; i++) {
145  CbcHeuristic * heu = i->heuristic;
146  heu->setModel(&model_);
147  model_.addHeuristic(heu, i->id.c_str());
148  }
149 
150  //need to record solver logLevel here
151  int logLevel = s.continuousSolver()->messageHandler()->logLevel();
152 
153  //Set true branch-and-bound parameters
155 
156  // Put back solver logLevel
157  model_.solver()->messageHandler()->setLogLevel(logLevel);
158 
160 
161  bool ChangedObject = false;
162  //Pass over user set branching priorities to Cbc
163  if (s.continuousSolver()->objects()==NULL) {
164  //assert (s.branchingMethod() == NULL);
165  const OsiTMINLPInterface * nlpSolver = s.nonlinearSolver();
166  //set priorities, prefered directions...
167  const int * priorities = nlpSolver->getPriorities();
168  const double * upPsCosts = nlpSolver->getUpPsCosts();
169  const double * downPsCosts = nlpSolver->getDownPsCosts();
170  const int * directions = nlpSolver->getBranchingDirections();
171  bool hasPseudo = (upPsCosts!=NULL);
172  model_.findIntegers(true,hasPseudo);
173  OsiObject ** simpleIntegerObjects = model_.objects();
174  int numberObjects = model_.numberObjects();
175  if (priorities != NULL || directions != NULL || hasPseudo) {
176  ChangedObject = true;
177  for (int i = 0 ; i < numberObjects ; i++) {
178  CbcObject * object = dynamic_cast<CbcObject *>
179  (simpleIntegerObjects[i]);
180  int iCol = object->columnNumber();
181  if (priorities)
182  object->setPriority(priorities[iCol]);
183  if (directions)
184  object->setPreferredWay(directions[iCol]);
185  if (upPsCosts) {
186  CbcSimpleIntegerPseudoCost * pscObject =
187  dynamic_cast<CbcSimpleIntegerPseudoCost*> (object);
188  pscObject->setUpPseudoCost(upPsCosts[iCol]);
189  pscObject->setDownPseudoCost(downPsCosts[iCol]);
190  }
191  }
192  }
193 
194 #if 1
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 
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 
309  CbcCompareObjective compare;
310  model_.setNodeComparison(compare);
311  }
313  CbcCompareDepth compare;
314  model_.setNodeComparison(compare);
315  }
317  CbcCompareDefault compare;
318  compare.setWeight(0.0);
319  model_.setNodeComparison(compare);
320  }
322  CbcCompareDefault compare;
323  model_.setNodeComparison(compare);
324  }
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 
336  //Do nothing this is the default of Cbc.
337  }
339  CbcDiver treeTraversal;
340  treeTraversal.initialize(s);
341  model_.passInTreeHandler(treeTraversal);
342  }
344  CbcProbedDiver treeTraversal;
345  treeTraversal.initialize(s);
346  model_.passInTreeHandler(treeTraversal);
347  }
349  CbcDfsDiver treeTraversal;
350  treeTraversal.initialize(s);
351  model_.passInTreeHandler(treeTraversal);
352  }
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 
369  model_.setNumberPenalties(8);
370 
371  model_.setDblParam(CbcModel::CbcMaximumSeconds, s.getDoubleParameter(Bonmin::BabSetupBase::MaxTime));
372 
374 
375  model_.setMaximumNumberIterations(s.getIntParameter(Bonmin::BabSetupBase::MaxIterations));
376 
378 
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;
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
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());
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 {
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);
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){
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_) {
626  }
627  else {
629  }
630  }
631  else if (model_.status() == 0) {
632  if(model_.isContinuousUnbounded()){
633  status = TMINLP::CONTINUOUS_UNBOUNDED;
635  }
636  else
637  if (bestSolution_) {
638  status = TMINLP::SUCCESS;
640  }
641  else {
642  status = TMINLP::INFEASIBLE;
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_) {
654  }
655  else {
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 
681 const 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 
691 double 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 }
int getIntParameter(const IntParameter &p) const
Return value of integer parameter.
Behavior of the algorithm in the case of a failure.
int nObjects_
number of objects.
Definition: BonCbc.hpp:124
double bestObj_
objValue of MIP
Definition: BonCbc.hpp:106
Max number of failures in a branch.
static bool interruptedOnce
Definition: CouenneBab.cpp:50
void initialize(BabSetupBase &b)
Initialize the method (get options)
Definition: BonDiver.cpp:440
Ipopt::SmartPtr< TMINLP > tminlp()
return pointer to tminlp_.
void setCbcModel(CbcModel *cbc_model)
Method for setting CbcModel, which is used to get statusOfSearch.
const vector< OsiObject * > & objects() const
Access to extra objects.
double getNewCutoffDecr()
Are there a numerical difficulties?
void setObjects(OsiObject **objects, int nObjects)
Set objects.
Depth First Search.
void initialize(BabSetupBase &b)
Initialize the method (get options)
Definition: BonDiver.cpp:750
const double * bestSolution() const
Get the best solution known to the problem (is optimal if MipStatus is FeasibleOptimal).
Definition: CouenneBab.cpp:681
int mipIterationCount_
get total number of iterations in last mip solved.
Definition: BonCbc.hpp:114
const double * getDownPsCosts() const
Get number of columns.
This class chooses a variable to branch on.
int num
Number of SOS constraints.
Definition: BonTMINLP.hpp:75
#define CUTOFF_TOL
Definition: CouenneBab.cpp:36
CoinMessageHandler * modelHandler_
Message handler for CbcModel.
Definition: BonCbc.hpp:118
MipStatuses mipStatus_
Status of the mip solved.
Definition: BonCbc.hpp:104
static void couenne_signal_handler(int whichSignal)
Definition: CouenneBab.cpp:52
const TMINLP2TNLP * problem() const
get pointer to the TMINLP2TNLP adapter
const double * getUpPsCosts() const
Get number of columns.
This is class provides an Osi interface for a Mixed Integer Linear Program expressed as a TMINLP (so ...
Stop if relative gap is less than this.
virtual const SosInfo * sosConstraints() const =0
int has_x_init()
xInit has been set?
Spetial option in particular for Cbc.
Same as DfsDiveFromBest, but after a prescribed number of integer solution are found switch to best-b...
virtual ~CouenneBab()
Destructor.
Definition: CouenneBab.cpp:77
There is a CbcObject in the model which is not understood by Bonmin.
Definition: BonExitCodes.hpp:9
void setComparisonBound(const CbcCompareBase &val)
Set comparison method when closing bound.
Definition: BonDiver.hpp:402
void initialize(BabSetupBase &b)
Initialize the method (get options)
Definition: BonDiver.cpp:184
double * bestSolution_
Stores the solution of MIP.
Definition: BonCbc.hpp:101
Number of candidates for strong branching.
CbcModel model_
CbcModel used to solve problem.
Definition: BonCbc.hpp:116
Class to store sos constraints for model.
Definition: BonTMINLP.hpp:72
double continuousRelaxation_
Continuous relaxation of the problem.
Definition: BonCbc.hpp:110
void generateCuts(const OsiSolverInterface &solver, OsiCuts &cs, const CglTreeInfo info=CglTreeInfo())
int numNodes_
Number of nodes enumerated.
Definition: BonCbc.hpp:112
const int * getBranchingDirections() const
get prefered branching directions
const std::vector< double > & bestSolution2() const
get the best solution computed with alternative objective function.
Definition: BonAuxInfos.hpp:71
virtual int getNumCols() const
Get number of columns.
void setup_global_time_limit(double time_limit)
Setup for a global time limit for solver.
const int * getPriorities() const
Get priorities on integer variables.
void setDiver(CbcDfsDiver *diver)
Set the dfs diver to use.
Definition: BonDiver.hpp:379
Dynamic strategy, see CbcBranchActual.hpp for explanations.
Minimum reliability before trust pseudo-costs.
From a TMINLP, this class adapts to another TMINLP where the original objective is transformed into a...
const Bonmin::TNLPSolver * solver() const
TreeTraversal treeTraversalMethod()
Method used to traverse tree.
virtual void replaceIntegers(OsiObject **objects, int numberObjects)
virtual callback function to eventually modify objects for integer variable (replace with user set)...
Definition: BonCbc.hpp:84
CbcModel * OAModel
Definition: BonCbc.cpp:36
Class to perform OA in its classical form.
int * starts
For 0 &lt;= i &lt; nums, start[i] gives the indice of indices and weights arrays at which the description o...
Definition: BonTMINLP.hpp:86
void assignLpInterface(OsiSolverInterface *si)
Assign an OsiTMINLPInterface.
A class to have all elements necessary to setup a branch-and-bound.
limit on number of integer feasible solution.
CouenneProblem * problem_
Definition: CouenneBab.hpp:46
virtual void finalize_solution(TMINLP::SolverReturn status, Ipopt::Index n, const Ipopt::Number *x, Ipopt::Number obj_value)=0
This method is called when the algorithm is complete so the TNLP can store/write the solution...
SolverReturn
Return statuses of algorithm.
Definition: BonTMINLP.hpp:64
virtual bool setWarmStart(const CoinWarmStart *warm, Ipopt::SmartPtr< TMINLP2TNLP > tnlp)=0
Set the warm start in the solver.
virtual void branchAndBound(Bonmin::BabSetupBase &s)
Carry out branch and bound.
Definition: CouenneBab.cpp:84
Problem has been proven to be infeasible.
Definition: BonCbc.hpp:24
bool hasContinuedOnAFailure()
Did we continue on a failure.
double bestObj() const
Return objective value of the bestSolution.
Definition: CouenneBab.cpp:691
A more elaborate diving class.
Definition: BonDiver.hpp:199
Class for MINLP problems with symbolic information.
static CbcModel * currentBranchModel
Definition: CouenneBab.cpp:44
OsiChooseVariable * branchingMethod()
branching method to use.
void fint fint fint fint fint fint fint fint fint fint real real real real real real real real * s
int * priorities
priorities of sos constraints.
Definition: BonTMINLP.hpp:79
double bestObj2() const
return objective value of the best solution computed with alternative objective function.
Definition: BonAuxInfos.hpp:77
Display information every logIntervval nodes.
char * types
Type of sos.
Definition: BonTMINLP.hpp:77
Max number of consecutive infeasible problem in a branch before fathoming.
dive from top node of the heap untill it gets to a leaf of the tree.
Bonmin::OACutGenerator2 * currentOA
Definition: BonCbc.cpp:35
void setProblem(CouenneProblem *p)
Definition: CouenneBab.cpp:79
Consider or not SOS constraints.
Log level for root relaxation.
NodeComparison & nodeComparisonMethod()
Method used to compare nodes.
double bestBound_
best known (lower) bound.
Definition: BonCbc.hpp:108
void setModel(Ipopt::SmartPtr< TMINLP > tminlp)
Set the model to be solved by interface.
void setBabPtr(Bab *babPtr)
Set pointer to the branch-and-bound algorithm (to access CbcModel).
Definition: BonBabInfos.hpp:38
Number of cut passes at nodes.
int * indices
indices of elements belonging to the SOS.
Definition: BonTMINLP.hpp:88
virtual CoinWarmStart * getWarmStart(Ipopt::SmartPtr< TMINLP2TNLP > tnlp) const =0
Get the warm start form the solver.
#define COUENNE_INFINITY
CouenneBab()
Constructor.
Definition: CouenneBab.cpp:74
We will throw this error when a problem is not solved.
An integer solution to the problem has been found.
Definition: BonCbc.hpp:25
OsiTMINLPInterface * nonlinearSolver()
Pointer to the non-linear solver used.
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
double getDoubleParameter(const DoubleParameter &p) const
Return value of double parameter.
No feasible solution to the problem is known.
Definition: BonCbc.hpp:27
Optimum solution has been found and its optimality proved.
Definition: BonCbc.hpp:23
OsiSolverInterface * continuousSolver()
Pointer to the continuous solver to use for relaxations.
Base class for OA algorithms.
HeuristicMethods & heuristics()
list of Heuristic methods to use.
dive from top node of the heap with more elaborate strategy (see options doc).
Eplore two kids before following on dive.
Number of cut passes at nodes.
Class to do probed diving in the tree.
Definition: BonDiver.hpp:108
void setComparisonDive(const CbcCompareBase &val)
Set comparison method when diving.
Definition: BonDiver.hpp:397
OsiObject ** objects_
OsiObjects of the model.
Definition: BonCbc.hpp:122
CuttingMethods & cutGenerators()
list of cutting planes methods to apply with their frequencies.
Class to do diving in the tree.
Definition: BonDiver.hpp:26
const CbcModel & model() const
Get cbc model used to solve.
Definition: BonCbc.hpp:87
Stop if absolute gap is less than this.
Best guessed integer solution is subtree below, based on pseudo costs.
Bonmin class for passing info between components of branch-and-cuts.
Definition: BonBabInfos.hpp:19
double * weights
weights of the elements of the SOS.
Definition: BonTMINLP.hpp:90