BonChooseVariable.cpp
Go to the documentation of this file.
1 // Copyright (C) 2006, 2008 International Business Machines
2 // Corporation and others. All Rights Reserved.
3 
4 #include <climits>
5 #include "CoinPragma.hpp"
6 #include "BonChooseVariable.hpp"
7 #include "CoinTime.hpp"
8 #include "IpBlas.hpp"
9 #include "BonMsgUtils.hpp"
10 
11 // This couples Cbc code into Bonmin code...
12 #include "CbcModel.hpp"
13 
14 namespace Bonmin
15 {
16 
18  CoinMessages((int) BON_CHOOSE_MESSAGES_DUMMY_END)
19  {
20  strcpy(source_,"BON");
21  ADD_MSG(PS_COST_HISTORY,std_m,6,"%3d up %3d %.8e down %3d %.8e");
22  ADD_MSG(PS_COST_MULT,std_m, 6, "upMultiplier = %e downMultiplier = %e");
23  ADD_MSG(PS_COST_ESTIMATES, std_m, 6, "%3d value = %e upEstimate = %e downEstimate = %e infeas = %e value2 = %e");
25  "list_[%5d] = %5d, usefull_[%5d] = %.16e %.16e");
27  "list_[%3d] = %3d useful_[%3d] = %e");
29  "list2[%3d] = %3d useful2[%3d] = %e");
31  " Starting strong branching. Obj. val = %g\n");
33  " Var Value DownStat DownChange UpStat UpChange");
34  ADD_MSG(SB_RES, std_m, 5,
35  " %3d %3d %.6e %6s %.6e %6s %.6e");
36  ADD_MSG(BRANCH_VAR, std_m, 4, "Branched on variable %i, bestWhichWay: %i");
37  ADD_MSG(CHOSEN_VAR, std_m, 4," Choosing %d");
38  ADD_MSG(UPDATE_PS_COST, std_m, 4,"update %3d %3d %e %e %3d");
39  }
40  const std::string BonChooseVariable::CNAME = "BonChooseVariable";
41 
42  BonChooseVariable::BonChooseVariable(BabSetupBase &b, const OsiSolverInterface* solver):
43  OsiChooseVariable(solver),
44  results_(),
45  cbc_model_(NULL),
47  pseudoCosts_()
48  {
49  jnlst_ = b.journalist();
51 
52  handler_ = new CoinMessageHandler;
53 
54  options->GetIntegerValue("bb_log_level", bb_log_level_, b.prefix());
55  handler_->setLogLevel(bb_log_level_);
56  options->GetNumericValue("time_limit", time_limit_, b.prefix());
57  options->GetNumericValue("setup_pseudo_frac", setup_pseudo_frac_, b.prefix());
58  options->GetNumericValue("maxmin_crit_no_sol", maxmin_crit_no_sol_, b.prefix());
59  options->GetNumericValue("maxmin_crit_have_sol", maxmin_crit_have_sol_, b.prefix());
60  options->GetEnumValue("trust_strong_branching_for_pseudo_cost",trustStrongForPseudoCosts_ , b.prefix());
61  int sortCrit;
62  options->GetEnumValue("candidate_sort_criterion", sortCrit, b.prefix());
63 #ifndef OLD_USEFULLNESS
64  sortCrit_ = (CandidateSortCriterion) sortCrit;
65 #endif
66 
67  int numberObjects = solver_->numberObjects();
68  //std::cout<<"Number objects "<<numberObjects<<std::endl;
69  pseudoCosts_.initialize(numberObjects);
70  int numberBeforeTrusted = b.getIntParameter(BabSetupBase::MinReliability);
71  pseudoCosts_.setNumberBeforeTrusted(numberBeforeTrusted);
72 
73  setNumberStrong(b.getIntParameter(BabSetupBase::NumberStrong));
74 
76  if (!options->GetIntegerValue("number_before_trust_list", numberBeforeTrustedList_, b.prefix())) {
77  // default is to use the same value as for numberBeforeTrusted
78  numberBeforeTrustedList_ = numberBeforeTrusted;
79  }
80  options->GetIntegerValue("number_strong_branch_root", numberStrongRoot_, b.prefix());
81  options->GetIntegerValue("min_number_strong_branch", minNumberStrongBranch_, b.prefix());
82  options->GetIntegerValue("number_look_ahead", numberLookAhead_, b.prefix());
83 
84  start_time_ = CoinCpuTime();
85  }
86 
88  OsiChooseVariable(rhs),
89  results_(rhs.results_),
90  time_limit_(rhs.time_limit_),
91  start_time_(CoinCpuTime()),
92  cbc_model_(rhs.cbc_model_),
93  only_pseudo_when_trusted_(rhs.only_pseudo_when_trusted_),
94  maxmin_crit_no_sol_(rhs.maxmin_crit_no_sol_),
95  maxmin_crit_have_sol_(rhs.maxmin_crit_have_sol_),
96  setup_pseudo_frac_(rhs.setup_pseudo_frac_),
97  numberBeforeTrustedList_(rhs.numberBeforeTrustedList_),
98  numberStrongRoot_(rhs.numberStrongRoot_),
99 #ifndef OLD_USEFULLNESS
100  sortCrit_(rhs.sortCrit_),
101 #endif
102  numberLookAhead_(rhs.numberLookAhead_),
103  minNumberStrongBranch_(rhs.minNumberStrongBranch_),
104  pseudoCosts_(rhs.pseudoCosts_),
105  trustStrongForPseudoCosts_(rhs.trustStrongForPseudoCosts_)
106  {
107  jnlst_ = rhs.jnlst_;
108  handler_ = rhs.handler_->clone();
110  DBG_ASSERT(IsValid(jnlst_));
111  }
112 
115  {
116  if (this != &rhs) {
117  OsiChooseVariable::operator=(rhs);
118  delete handler_;
119  handler_ = rhs.handler_->clone();
120  jnlst_ = rhs.jnlst_;
122  cbc_model_ = rhs.cbc_model_;
129 #ifndef OLD_USEFULLNESS
130  sortCrit_ = rhs.sortCrit_;
131 #endif
136  results_ = rhs.results_;
137  }
138  return *this;
139  }
140 
141  OsiChooseVariable *
143  {
144  return new BonChooseVariable(*this);
145  }
146 
148  {
149  delete handler_;
150  }
151 
152  void
155  {
156  roptions->SetRegisteringCategory("Strong branching setup", RegisteredOptions::BonminCategory);
157  roptions->AddStringOption4("candidate_sort_criterion",
158  "Choice of the criterion to choose candidates in strong-branching",
159  "best-ps-cost",
160  "best-ps-cost","Sort by decreasing pseudo-cost",
161  "worst-ps-cost", "Sort by increasing pseudo-cost",
162  "most-fractional", "Sort by decreasing integer infeasibility",
163  "least-fractional", "Sort by increasing integer infeasibility","");
164 
165  roptions->setOptionExtraInfo("candidate_sort_criterion",63);
166 
167  roptions->AddBoundedNumberOption("setup_pseudo_frac", "Proportion of strong branching list that has to be taken from most-integer-infeasible list.",
168  0., false, 1., false, 0.5);
169  roptions->setOptionExtraInfo("setup_pseudo_frac",63);
170  roptions->AddBoundedNumberOption("maxmin_crit_no_sol", "Weight towards minimum in of lower and upper branching estimates when no solution has been found yet.",
171  0., false, 1., false, 0.7);
172  roptions->setOptionExtraInfo("maxmin_crit_no_sol",63);
173  roptions->AddBoundedNumberOption("maxmin_crit_have_sol", "Weight towards minimum in of lower and upper branching estimates when a solution has been found.",
174  0., false, 1., false, 0.1);
175  roptions->setOptionExtraInfo("maxmin_crit_have_sol",63);
176  roptions->AddLowerBoundedIntegerOption("number_before_trust_list",
177  "Set the number of branches on a variable before its pseudo costs are to be believed during setup of strong branching candidate list.",
178  -1, 0, "The default value is that of \"number_before_trust\"");
179  roptions->setOptionExtraInfo("number_before_trust_list",63);
180  roptions->AddLowerBoundedIntegerOption("number_strong_branch_root",
181  "Maximum number of variables considered for strong branching in root node.",
182  0, COIN_INT_MAX, "");
183  roptions->setOptionExtraInfo("number_strong_branch_root",63);
184 
185  roptions->AddLowerBoundedIntegerOption("min_number_strong_branch", "Sets minimum number of variables for strong branching (overriding trust)",
186  0, 0,"");
187  roptions->setOptionExtraInfo("min_number_strong_branch",63);
188  roptions->AddStringOption2("trust_strong_branching_for_pseudo_cost",
189  "Whether or not to trust strong branching results for updating pseudo costs.",
190  "yes",
191  "no","",
192  "yes","",
193  ""
194  );
195  roptions->setOptionExtraInfo("trust_strong_branching_for_pseudo_cost", 63);
196 
197  roptions->AddLowerBoundedIntegerOption("number_look_ahead", "Sets limit of look-ahead strong-branching trials",
198  0, 0,"");
199  roptions->setOptionExtraInfo("number_look_ahead", 31);
200  }
201 
202 
203  void
204  BonChooseVariable::computeMultipliers(double& upMult, double& downMult) const
205  {
206  const double* upTotalChange = pseudoCosts_.upTotalChange();
207  const double* downTotalChange = pseudoCosts_.downTotalChange();
208  const int* upNumber = pseudoCosts_.upNumber();
209  const int* downNumber = pseudoCosts_.downNumber();
210  double sumUp=0.0;
211  double numberUp=0.0;
212  double sumDown=0.0;
213  double numberDown=0.0;
214  for (int i=pseudoCosts_.numberObjects() - 1; i >= 0; --i) {
215  sumUp += upTotalChange[i];
216  numberUp += upNumber[i];
217  sumDown += downTotalChange[i];
218  numberDown += downNumber[i];
220  <<i<< upNumber[i]<< upTotalChange[i]
221  << downNumber[i]<< downTotalChange[i]<<CoinMessageEol;
222  }
223  upMult=(1.0+sumUp)/(1.0+numberUp);
224  downMult=(1.0+sumDown)/(1.0+numberDown);
225 
227  <<upMult<< downMult<<CoinMessageEol;
228  }
229 
230  double
231  BonChooseVariable::computeUsefulness(const double MAXMIN_CRITERION,
232  const double upMult, const double downMult,
233  const double value,
234  const OsiObject* object, int i,
235  double& value2) const
236  {
237 #ifdef OLD_USEFULLNESS
238  double sumUp = pseudoCosts_.upTotalChange()[i]+1.0e-30;
239  int numberUp = pseudoCosts_.upNumber()[i];
240  double sumDown = pseudoCosts_.downTotalChange()[i]+1.0e-30;
241  int numberDown = pseudoCosts_.downNumber()[i];
242  double upEst = object->upEstimate();
243  double downEst = object->downEstimate();
244  upEst = numberUp ? ((upEst*sumUp)/numberUp) : (upEst*upMult);
245  //if (numberUp<numberBeforeTrusted_)
246  // upEst *= (numberBeforeTrusted_+1.0)/(numberUp+1.0);
247  downEst = numberDown ? ((downEst*sumDown)/numberDown) : (downEst*downMult);
248  //if (numberDown<numberBeforeTrusted_)
249  // downEst *= (numberBeforeTrusted_+1.0)/(numberDown+1.0);
250  double useful = ( MAXMIN_CRITERION*CoinMin(upEst,downEst) +
251  (1.0-MAXMIN_CRITERION)*CoinMax(upEst,downEst) );
252  value2 = -COIN_DBL_MAX;
253  if (numberUp < numberBeforeTrustedList_ ||
254  numberDown < numberBeforeTrustedList_) {
255  value2 = value;
256  }
257 #else
258  // FIXME: Hanlding initialization correctly
259  int numberUp = pseudoCosts_.upNumber()[i];
260  int numberDown = pseudoCosts_.downNumber()[i];
261  if (sortCrit_ >= DecrPs && sortCrit_ <= IncrPs) {//Using pseudo costs
262  double sumUp = pseudoCosts_.upTotalChange()[i]+1.0e-30;
263  double sumDown = pseudoCosts_.downTotalChange()[i]+1.0e-30;
264  double upEst = object->upEstimate();
265  double downEst = object->downEstimate();
266  upEst = numberUp ? ((upEst*sumUp)/numberUp) : (upEst*upMult);
267  //if (numberUp<numberBeforeTrusted_)
268  // upEst *= (numberBeforeTrusted_+1.0)/(numberUp+1.0);
269  downEst = numberDown ? ((downEst*sumDown)/numberDown) : (downEst*downMult);
270  //if (numberDown<numberBeforeTrusted_)
271  // downEst *= (numberBeforeTrusted_+1.0)/(numberDown+1.0);
272  double useful = ( MAXMIN_CRITERION*CoinMin(upEst,downEst) +
273  (1.0-MAXMIN_CRITERION)*CoinMax(upEst,downEst) );
274  if (numberUp == 0 || numberDown == 0) {
275  if (value == 0.) useful = 0;
276  else if (MAXMIN_CRITERION >= 0.5)//Sort on max infeasibility
277  useful = CoinMin(upEst, downEst);
278  else {//Do min infeasibility
279  useful = CoinMax(upEst, downEst);
280  }
281  }
282  value2 = -COIN_DBL_MAX;
283  if (numberUp < numberBeforeTrustedList_ ||
284  numberDown < numberBeforeTrustedList_) {
285  value2 = value;
286  }
287 #endif
289  <<i<< useful<< upEst<< downEst<< value<< value2<< CoinMessageEol;
290  return useful;
291  }
292 #ifndef OLD_USEFULLNESS
293  else if (sortCrit_ >= DecrInfeas && sortCrit_ <= IncrInfeas) {//Just return infeasibility
294  double usefull = value;
295  value2 = value;
296  return usefull;
297  }
298  else {
299  throw CoinError("BonChooseVariable", "computeUsefullnee",
300  "Unknown criterion for soring candidates");
301  return COIN_DBL_MAX;
302  }
303  }
304 #endif
305 
306  int
307  BonChooseVariable::setupList ( OsiBranchingInformation *info, bool initialize)
308  {
309  if (numberBeforeTrustedList_ < 0) {
311  return OsiChooseVariable::setupList(info, initialize);
312  }
313  if (initialize) {
314  status_=-2;
315  delete [] goodSolution_;
316  bestObjectIndex_=-1;
317  numberStrongDone_=0;
318  numberStrongIterations_ = 0;
319  numberStrongFixed_ = 0;
320  goodSolution_ = NULL;
321  goodObjectiveValue_ = COIN_DBL_MAX;
323  }
324  else {
325  throw CoinError(CNAME,"setupList","Should not be called with initialize==false");
326  }
327  numberOnList_=0;
328  numberUnsatisfied_=0;
329  int numberObjects = solver_->numberObjects();
330  assert (numberObjects);
331  if (numberObjects>pseudoCosts_.numberObjects()) {
332  //std::cout<<"Number objects "<<numberObjects<<std::endl;
333  //AW : How could that ever happen?
334  //PB : It happens for instance when SOS constraints are added. They are added after the creation of this.
335  // assert(false && "Right now, all old content is deleted!");
336  // redo useful arrays
337  int saveNumberBeforeTrusted = pseudoCosts_.numberBeforeTrusted();
338  pseudoCosts_.initialize(numberObjects);
339  pseudoCosts_.setNumberBeforeTrusted(saveNumberBeforeTrusted);
340  }
341  double check = -COIN_DBL_MAX;
342  int checkIndex=0;
343  int bestPriority=COIN_INT_MAX;
344  int maximumStrong= CoinMin(CoinMax(numberStrong_,numberStrongRoot_),
345  numberObjects) ;
346  int putOther = numberObjects;
347  int i;
348  for (i=0;i<numberObjects;i++) {
349  list_[i]=-1;
350  useful_[i]=0.0;
351  }
352  // We make a second list for most fractional variables
353  int* list2 = NULL;
354  double* useful2 = NULL;
355  double check2 = -COIN_DBL_MAX;
356  int checkIndex2=0;
357  int max_most_fra = setup_pseudo_frac_ > 0. ? (int)floor(setup_pseudo_frac_*(double)maximumStrong): 0;
358  if (setup_pseudo_frac_ > 0.) {
359  max_most_fra = CoinMax(1, max_most_fra);
360  }
361  if (max_most_fra) {
362  list2 = new int[max_most_fra];
363  useful2 = new double[max_most_fra];
364  for (i=0;i<max_most_fra;i++) {
365  list2[i]=-1;
366  useful2[i]=0.0;
367  }
368  }
369 
370  OsiObject ** object = info->solver_->objects();
371  double upMultiplier, downMultiplier;
372  computeMultipliers(upMultiplier, downMultiplier);
373 
374  // Say feasible
375  bool feasible = true;
376  const double MAXMIN_CRITERION = maxminCrit(info);
377  for ( i=0;i<numberObjects;i++) {
378  int way;
379  double value = object[i]->infeasibility(info,way);
380  if (value>0.0) {
381  numberUnsatisfied_++;
382  if (value>=1e50) {
383  // infeasible
384  feasible=false;
385  break;
386  }
387  int priorityLevel = object[i]->priority();
388  // Better priority? Flush choices.
389  if (priorityLevel<bestPriority) {
390  for (int j=maximumStrong-1;j>=0;j--) {
391  if (list_[j]>=0) {
392  int iObject = list_[j];
393  list_[j]=-1;
394  useful_[j]=0.0;
395  list_[--putOther]=iObject;
396  }
397  }
398  maximumStrong = CoinMin(maximumStrong,putOther);
399  bestPriority = priorityLevel;
400  check=-COIN_DBL_MAX;
401  checkIndex=0;
402  check2=-COIN_DBL_MAX;
403  checkIndex2=0;
405  if (max_most_fra>0) {
406  for (int j=0;j<max_most_fra;j++) {
407  list2[j]=-1;
408  useful2[j]=0.0;
409  }
410  }
411  }
412  if (priorityLevel==bestPriority) {
413  // Modify value
414  double value2;
415  value = computeUsefulness(MAXMIN_CRITERION,
416  upMultiplier, downMultiplier, value,
417  object[i], i, value2);
418  if (value>check) {
419  //add to list
420  int iObject = list_[checkIndex];
421  if (iObject>=0) {
422  assert (list_[putOther-1]<0);
423  list_[--putOther]=iObject; // to end
424  }
425  list_[checkIndex]=i;
426  assert (checkIndex<putOther);
427  useful_[checkIndex]=value;
428  // find worst
429  check=COIN_DBL_MAX;
430  maximumStrong = CoinMin(maximumStrong,putOther);
431  for (int j=0;j<maximumStrong;j++) {
432  if (list_[j]>=0) {
433  if (useful_[j]<check) {
434  check=useful_[j];
435  checkIndex=j;
436  }
437  }
438  else {
439  check=0.0;
440  checkIndex = j;
441  break;
442  }
443  }
444  }
445  else {
446  // to end
447  assert (list_[putOther-1]<0);
448  list_[--putOther]=i;
449  maximumStrong = CoinMin(maximumStrong,putOther);
450  }
451  if (max_most_fra > 0 && value2>check2) {
452  // add to list of integer infeasibilities
454  list2[checkIndex2]=i;
455  useful2[checkIndex2]=value2;
456  // find worst
457  check2=COIN_DBL_MAX;
458  for (int j=0;j<max_most_fra;j++) {
459  if (list2[j]>=0) {
460  if (useful2[j]<check2) {
461  check2=useful2[j];
462  checkIndex2=j;
463  }
464  }
465  else {
466  check2=0.0;
467  checkIndex2 = j;
468  break;
469  }
470  }
471  }
472  }
473  else {
474  // worse priority
475  // to end
476  assert (list_[putOther-1]<0);
477  list_[--putOther]=i;
478  maximumStrong = CoinMin(maximumStrong,putOther);
479  }
480  }
481  }
482 #if 0
483  for (int i=0; i<maximumStrong; i++) {
484  int way;
486  <<list_[i]<<i<<useful_[i]<<object[list_[i]]->infeasibility(info,way)
487  <<CoinMessageEol;
488  }
489 #endif
490  // Get list
491  numberOnList_=0;
492  if (feasible) {
493  maximumStrong = CoinMin(maximumStrong,putOther);
494  for (i=0;i<maximumStrong;i++) {
495  if (list_[i]>=0) {
496 #ifdef OLD_USEFULLNESS
497  list_[numberOnList_]=list_[i];
498  useful_[numberOnList_++]=-useful_[i];
499 
500 #else
501  list_[numberOnList_]=list_[i];
502  if ((sortCrit_ & 1) == 0) {
503  useful_[numberOnList_++]=-useful_[i];
504  }
505  else useful_[numberOnList_++] = useful_[i];
506 #endif
507  message(CANDIDATE_LIST2)<<numberOnList_-1
508  <<list_[numberOnList_-1]<<numberOnList_-1<<useful_[numberOnList_-1]
509  <<CoinMessageEol;
510  }
511  }
512  if (numberOnList_) {
513  int tmp_on_list = 0;
514  if (max_most_fra > 0 && numberOnList_ >= maximumStrong) {
515  // If we want to force non-trusted in the list, give them huge
516  // weight here
518  for (i=0;i<max_most_fra;i++) {
519  if (list2[i]>=0) {
520  list2[number_not_trusted_] = list2[i];
521  useful2[number_not_trusted_++] = useful2[i];
524  <<useful2[number_not_trusted_-1]<<CoinMessageEol;
525  }
526  }
527  if (number_not_trusted_) {
528  CoinSort_2(list_,list_+numberOnList_,useful_);
529  CoinSort_2(list2,list2+number_not_trusted_,useful2);
530  int i1=0;
531  int i2=0;
532  for (i=0; i<numberObjects; i++) {
533  bool found1 = (list_[i1]==i);
534  bool found2 = (list2[i2]==i);
535  if (found1 && found2) {
536  useful_[i1] = -1e150*(1.+useful2[i2]);
537  list2[i2] = -1;
538  }
539  if (found1) i1++;
540  if (found2) i2++;
541  if (i2==max_most_fra) break;
542  }
543  for (i=0; i<number_not_trusted_; i++) {
544  if (list2[i] >= 0) {
545  list_[numberOnList_+tmp_on_list] = list2[i];
546  useful_[numberOnList_+tmp_on_list] = -1e150*(1.+useful2[i]);
547  tmp_on_list++;
548  }
549  }
550  }
551  }
552  // Sort
553  CoinSort_2(useful_,useful_+numberOnList_+tmp_on_list,list_);
554  // move others
555  i = numberOnList_;
556  for (;putOther<numberObjects;putOther++)
557  list_[i++]=list_[putOther];
558  assert (i==numberUnsatisfied_);
559  if (!CoinMax(numberStrong_,numberStrongRoot_))
560  numberOnList_=0;
561  }
562  }
563  else {
564  // not feasible
565  numberUnsatisfied_=-1;
566  }
567  // Get rid of any shadow prices info
568  info->defaultDual_ = -1.0; // switch off
569  delete [] info->usefulRegion_;
570  delete [] info->indexRegion_;
571  delete [] list2;
572  delete [] useful2;
573  int way;
574  if (bb_log_level_>3) {
575  //for (int i=0; i<Min(numberUnsatisfied_,numberStrong_); i++)
576  for (int i=0; i<numberOnList_; i++){
577  message(CANDIDATE_LIST)<<i<< list_[i]<< i<< useful_[i]
578  <<object[list_[i]]->infeasibility(info,way)
579  <<CoinMessageEol;
580  }
581  }
582  return numberUnsatisfied_;
583 
584  }
585 
586  /* Choose a variable
587  Returns -
588  -1 Node is infeasible
589  0 Normal termination - we have a candidate
590  1 All looks satisfied - no candidate
591  2 We can change the bound on a variable - but we also have a strong branching candidate
592  3 We can change the bound on a variable - but we have a non-strong branching candidate
593  4 We can change the bound on a variable - no other candidates
594  We can pick up branch from whichObject() and whichWay()
595  We can pick up a forced branch (can change bound) from whichForcedObject() and whichForcedWay()
596  If we have a solution then we can pick up from goodObjectiveValue() and goodSolution()
597  */
598  int
600  OsiSolverInterface * solver,
601  OsiBranchingInformation *info,
602  bool fixVariables)
603  {
604  // We assume here that chooseVariable is called once at the very
605  // beginning with fixVariables set to true. This is then the root
606  // node.
607  bool isRoot = isRootNode(info);
608  int numberStrong = numberStrong_;
609  if (isRoot) {
610  numberStrong = CoinMax(numberStrong_, numberStrongRoot_);
611  }
612  std::vector<double> save_sol;
613  if (bb_log_level_>=3) {
614  save_sol.resize(info->numberColumns_);
615  std::copy(info->solution_, info->solution_ + info->numberColumns_ , save_sol.begin());
616  }
617  if (numberUnsatisfied_) {
618  const double* upTotalChange = pseudoCosts_.upTotalChange();
619  const double* downTotalChange = pseudoCosts_.downTotalChange();
620  const int* upNumber = pseudoCosts_.upNumber();
621  const int* downNumber = pseudoCosts_.downNumber();
622  int numberBeforeTrusted = pseudoCosts_.numberBeforeTrusted();
623  int numberLeft = CoinMin(numberStrong -numberStrongDone_,numberUnsatisfied_);
624  results_.clear();
625  int returnCode=0;
626  bestObjectIndex_ = -1;
627  bestWhichWay_ = -1;
628  firstForcedObjectIndex_ = -1;
629  firstForcedWhichWay_ =-1;
630  double bestTrusted=-COIN_DBL_MAX;
631  for (int i=0;i<numberLeft;i++) {
632  int iObject = list_[i];
633  if (numberBeforeTrusted == 0||
635  (
637  ( !isRoot && (upNumber[iObject]<numberBeforeTrusted ||
638  downNumber[iObject]<numberBeforeTrusted ))||
639  ( isRoot && (!upNumber[iObject] && !downNumber[iObject])) ) {
640 
641  results_.push_back(HotInfo(solver, info,
642  solver->objects(), iObject));
643  }
644  else {
645  const OsiObject * obj = solver->object(iObject);
646  double upEstimate = (upTotalChange[iObject]*obj->upEstimate())/upNumber[iObject];
647  double downEstimate = (downTotalChange[iObject]*obj->downEstimate())/downNumber[iObject];
648  double MAXMIN_CRITERION = maxminCrit(info);
649  double value = MAXMIN_CRITERION*CoinMin(upEstimate,downEstimate) + (1.0-MAXMIN_CRITERION)*CoinMax(upEstimate,downEstimate);
650  if (value > bestTrusted) {
651  bestObjectIndex_=iObject;
652  bestWhichWay_ = upEstimate>downEstimate ? 0 : 1;
653  bestTrusted = value;
654  }
655  }
656  }
657  int numberFixed=0;
658  if (results_.size() > 0) {
659  returnCode = doStrongBranching(solver, info, (int)results_.size(), 1);
660  if (bb_log_level_>=3) {
661  OsiObject ** obj = solver->objects();
662  const char* stat_msg[] = {"NOTDON", "FEAS", "INFEAS", "NOFINI"};
663  message(SB_START)<<info->objectiveValue_<<CoinMessageEol;
664  message(SB_HEADER)<<CoinMessageEol;
665  for (unsigned int i = 0; i< results_.size(); i++) {
666  double up_change = results_[i].upChange();
667  double down_change = results_[i].downChange();
668  int up_status = results_[i].upStatus();
669  int down_status = results_[i].downStatus();
670  int icol = obj[results_[i].whichObject()]->columnNumber();
671  double val = save_sol[icol];
672  message(SB_RES)<<(int) i<<icol<<val<<stat_msg[down_status+1]<<down_change
673  <<stat_msg[up_status+1]<< up_change<< CoinMessageEol;
674  }
675  }
676  if (returnCode>=0&&returnCode<=2) {
677  if (returnCode) {
678  returnCode=4;
679  if (bestObjectIndex_>=0)
680  returnCode=3;
681  }
682  for (unsigned int i=0;i < results_.size();i++) {
683  int iObject = results_[i].whichObject();
684  double upEstimate;
685  if (results_[i].downStatus()== 2 || results_[i].upStatus()==2) {
686  //continue;
687  }
688  if (results_[i].upStatus()!=1) {
689  assert (results_[i].upStatus()>=0);
690  upEstimate = results_[i].upChange();
691  }
692  else {
693  // infeasible - just say expensive
694  if (info->cutoff_<1.0e50)
695  upEstimate = 2.0*(info->cutoff_-info->objectiveValue_);
696  else
697  upEstimate = 2.0*fabs(info->objectiveValue_);
698  if (firstForcedObjectIndex_ <0) {
699  // first fixed variable
700  firstForcedObjectIndex_ = iObject;
701  firstForcedWhichWay_ =0;
702  }
703  numberFixed++;
704  if (fixVariables) {
705  const OsiObject * obj = solver->object(iObject);
706  OsiBranchingObject * branch = obj->createBranch(solver,info,0);
707  branch->branch(solver);
708  delete branch;
709  }
710  }
711  double downEstimate;
712  if (results_[i].downStatus()!=1) {
713  assert (results_[i].downStatus()>=0);
714  downEstimate = results_[i].downChange();
715  }
716  else {
717  // infeasible - just say expensive
718  if (info->cutoff_<1.0e50)
719  downEstimate = 2.0*(info->cutoff_-info->objectiveValue_);
720  else
721  downEstimate = 2.0*fabs(info->objectiveValue_);
722  if (firstForcedObjectIndex_ <0) {
723  firstForcedObjectIndex_ = iObject;
724  firstForcedWhichWay_ =1;
725  }
726  numberFixed++;
727  if (fixVariables) {
728  const OsiObject * obj = solver->object(iObject);
729  OsiBranchingObject * branch = obj->createBranch(solver,info,1);
730  branch->branch(solver);
731  delete branch;
732  }
733  }
734  double MAXMIN_CRITERION = maxminCrit(info);
735  double value = MAXMIN_CRITERION*CoinMin(upEstimate,downEstimate) + (1.0-MAXMIN_CRITERION)*CoinMax(upEstimate,downEstimate);
736  if (value>bestTrusted) {
737  bestTrusted = value;
738  bestObjectIndex_ = iObject;
739  bestWhichWay_ = upEstimate>downEstimate ? 0 : 1;
740  // but override if there is a preferred way
741  const OsiObject * obj = solver->object(iObject);
742  if (obj->preferredWay()>=0&&obj->infeasibility())
743  bestWhichWay_ = obj->preferredWay();
744  if (returnCode)
745  returnCode=2;
746  }
747  }
748  }
749  else if (returnCode==3) {
750  // max time - just choose one
751  bestObjectIndex_ = list_[0];
752  bestWhichWay_ = 0;
753  returnCode=0;
754  }
755  }
756  else {
757  bestObjectIndex_=list_[0];
758  }
759  if ( bestObjectIndex_ >=0 ) {
760  OsiObject * obj = solver->objects()[bestObjectIndex_];
761  obj->setWhichWay(bestWhichWay_);
762  message(BRANCH_VAR)<<obj->columnNumber()<< bestWhichWay_
763  <<CoinMessageEol;
764  }
765  message(CHOSEN_VAR)<<bestObjectIndex_<<CoinMessageEol;
766  if (numberFixed==numberUnsatisfied_&&numberFixed)
767  returnCode=4;
768  return returnCode;
769  }
770  else {
771  return 1;
772  }
773  }
774 
775  /* This is a utility function which does strong branching on
776  a list of objects and stores the results in OsiHotInfo.objects.
777  On entry the object sequence is stored in the OsiHotInfo object
778  and maybe more.
779  It returns -
780  -1 - one branch was infeasible both ways
781  0 - all inspected - nothing can be fixed
782  1 - all inspected - some can be fixed (returnCriterion==0)
783  2 - may be returning early - one can be fixed (last one done) (returnCriterion==1)
784  3 - returning because max time
785  */
786  int
787  BonChooseVariable::doStrongBranching( OsiSolverInterface * solver,
788  OsiBranchingInformation *info,
789  int numberToDo, int returnCriterion)
790  {
791  // Prepare stuff for look-ahead heuristic
792  double bestLookAhead_ = -COIN_DBL_MAX;
793  int trialsSinceBest_ = 0;
794  bool isRoot = isRootNode(info);
795  // Might be faster to extend branch() to return bounds changed
796  double * saveLower = NULL;
797  double * saveUpper = NULL;
798  int numberColumns = solver->getNumCols();
799  solver->markHotStart();
800  const double * lower = info->lower_;
801  const double * upper = info->upper_;
802  saveLower = CoinCopyOfArray(info->lower_,numberColumns);
803  saveUpper = CoinCopyOfArray(info->upper_,numberColumns);
804  int returnCode=0;
805  double timeStart = CoinCpuTime();
806  int iDo = 0;
807  for (;iDo<numberToDo;iDo++) {
808  HotInfo * result = results_() + iDo;
809  // For now just 2 way
810  OsiBranchingObject * branch = result->branchingObject();
811  assert (branch->numberBranches()==2);
812  /*
813  Try the first direction. Each subsequent call to branch() performs the
814  specified branch and advances the branch object state to the next branch
815  alternative.)
816  */
817  OsiSolverInterface * thisSolver = solver;
818  if (branch->boundBranch()) {
819  // ordinary
820  branch->branch(solver);
821  // maybe we should check bounds for stupidities here?
822  solver->solveFromHotStart() ;
823 
824 
825  } else {
826  // adding cuts or something
827  thisSolver = solver->clone();
828  branch->branch(thisSolver);
829  // set hot start iterations
830  int limit;
831  thisSolver->getIntParam(OsiMaxNumIterationHotStart,limit);
832  thisSolver->setIntParam(OsiMaxNumIteration,limit);
833  thisSolver->resolve();
834  }
835  // can check if we got solution
836  // status is 0 finished, 1 infeasible and 2 unfinished and 3 is solution
837  int status0 = result->updateInformation(thisSolver,info,this);
838  if (status0==3) {
839  // new solution already saved
840  if (trustStrongForSolution_) {
841  info->cutoff_ = goodObjectiveValue_;
842  status0=0;
843  }
844  }
845  if(solver->getRowCutDebugger() && status0 == 1 ){
846  OsiTMINLPInterface * tminlp_solver = dynamic_cast<OsiTMINLPInterface *> (solver);
847  throw tminlp_solver->newUnsolvedError(1, tminlp_solver->problem(), "SB");
848  }
849  numberStrongIterations_ += thisSolver->getIterationCount();
850  if (solver!=thisSolver)
851  delete thisSolver;
852  // Restore bounds
853  for (int j=0;j<numberColumns;j++) {
854  if (saveLower[j] != lower[j])
855  solver->setColLower(j,saveLower[j]);
856  if (saveUpper[j] != upper[j])
857  solver->setColUpper(j,saveUpper[j]);
858  }
859  /*
860  Try the next direction
861  */
862  thisSolver = solver;
863  if (branch->boundBranch()) {
864  // ordinary
865  branch->branch(solver);
866  // maybe we should check bounds for stupidities here?
867  fflush(stdout);
868  solver->solveFromHotStart() ;
869  } else {
870  // adding cuts or something
871  thisSolver = solver->clone();
872  branch->branch(thisSolver);
873  // set hot start iterations
874  int limit;
875  thisSolver->getIntParam(OsiMaxNumIterationHotStart,limit);
876  thisSolver->setIntParam(OsiMaxNumIteration,limit);
877 
878 
879  thisSolver->resolve();
880  }
881  // can check if we got solution
882  // status is 0 finished, 1 infeasible and 2 unfinished and 3 is solution
883  int status1 = result->updateInformation(thisSolver,info,this);
884  numberStrongDone_++;
885  if (status1==3) {
886  // new solution already saved
887  if (trustStrongForSolution_) {
888  info->cutoff_ = goodObjectiveValue_;
889  status1=0;
890  }
891  }
892  if(solver->getRowCutDebugger() && status1 == 1){
893  OsiTMINLPInterface * tminlp_solver = dynamic_cast<OsiTMINLPInterface *> (solver);
894  throw tminlp_solver->newUnsolvedError(1, tminlp_solver->problem(), "SB");
895  }
896  numberStrongIterations_ += thisSolver->getIterationCount();
897  if (solver!=thisSolver)
898  delete thisSolver;
899  // Restore bounds
900  for (int j=0;j<numberColumns;j++) {
901  if (saveLower[j] != lower[j])
902  solver->setColLower(j,saveLower[j]);
903  if (saveUpper[j] != upper[j])
904  solver->setColUpper(j,saveUpper[j]);
905  }
906  /*
907  End of evaluation for this candidate variable. Possibilities are:
908  * Both sides below cutoff; this variable is a candidate for branching.
909  * Both sides infeasible or above the objective cutoff: no further action
910  here. Break from the evaluation loop and assume the node will be purged
911  by the caller.
912  * One side below cutoff: Install the branch (i.e., fix the variable). Possibly break
913  from the evaluation loop and assume the node will be reoptimised by the
914  caller.
915  */
916  if (status0==1&&status1==1) {
917  // infeasible
918  returnCode=-1;
919  //break; // exit loop
920  } else if (status0==1||status1==1) {
921  numberStrongFixed_++;
922  returnCode=1;
923  }
924  bool hitMaxTime = ( CoinCpuTime()-timeStart > info->timeRemaining_)
925  || ( CoinCpuTime() - start_time_ > time_limit_);
926  if (hitMaxTime) {
927  returnCode=3;
928  break;
929  }
930  // stop if look ahead heuristic tells us so
931  if (!isRoot && numberLookAhead_) {
932  assert(status0==0 && status1==0);
933  double upEstimate = result->upChange();
934  double downEstimate = result->downChange();
935  double MAXMIN_CRITERION = maxminCrit(info);
936  double value = MAXMIN_CRITERION*CoinMin(upEstimate,downEstimate) + (1.0-MAXMIN_CRITERION)*CoinMax(upEstimate,downEstimate);
937  if (value > bestLookAhead_) {
938  bestLookAhead_ = value;
939  trialsSinceBest_ = 0;
940  }
941  else {
942  trialsSinceBest_++;
943  if (trialsSinceBest_ >= numberLookAhead_) {
944  break;
945  }
946  }
947  }
948  }
949  if(iDo < numberToDo) iDo++;
950  assert(iDo <= (int) results_.size());
951  results_.resize(iDo);
952  delete [] saveLower;
953  delete [] saveUpper;
954  // Delete the snapshot
955  solver->unmarkHotStart();
956  return returnCode;
957  }
958 
959  bool BonChooseVariable::isRootNode(const OsiBranchingInformation *info) const
960  {
961  return info->depth_ == 0;
962  }
963 
964  double
965  BonChooseVariable::maxminCrit(const OsiBranchingInformation *info) const
966  {
967  double retval = maxmin_crit_no_sol_;
968  if (cbc_model_) {
969  // FIXME: should be replaced by info->stateOfSearch_
970  const int stateOfSearch = cbc_model_->stateOfSearch();
971  const int depth = info->depth_;
972  if (stateOfSearch>1 && depth>10) {
973  retval = maxmin_crit_have_sol_;
974  }
975  }
976  return retval;
977  }
978 
979 // Given a candidate fill in useful information e.g. estimates
980  void
981  BonChooseVariable::updateInformation(const OsiBranchingInformation *info,
982  int branch, OsiHotInfo * hotInfo)
983  {
984  if(!trustStrongForPseudoCosts_) return;
985  int index = hotInfo->whichObject();
986  assert (index<solver_->numberObjects());
987  const OsiObject * object = info->solver_->object(index);
988  assert (object->upEstimate()>0.0&&object->downEstimate()>0.0);
989  assert (branch<2);
990  double* upTotalChange = pseudoCosts_.upTotalChange();
991  double* downTotalChange = pseudoCosts_.downTotalChange();
992  int* upNumber = pseudoCosts_.upNumber();
993  int* downNumber = pseudoCosts_.downNumber();
994  if (branch) {
995  //if (hotInfo->upStatus()!=1)
996  // AW: Let's update the pseudo costs only if the strong branching
997  // problem was marked as "solved"
998  if (hotInfo->upStatus()==0) {
999  assert (hotInfo->upStatus()>=0);
1000  upTotalChange[index] += hotInfo->upChange()/object->upEstimate();
1001  upNumber[index]++;
1002  }
1003  else if (hotInfo->upStatus()==1) {
1004  // infeasible - just say expensive
1005  upNumber[index]++;
1006  if (info->cutoff_<1.0e50)
1007  upTotalChange[index] += 2.0*(info->cutoff_-info->objectiveValue_)/object->upEstimate();
1008  else
1009  upTotalChange[index] += 2.0*fabs(info->objectiveValue_)/object->upEstimate();
1010  }
1011  }
1012  else {
1013  if (hotInfo->downStatus()==0) {
1014  assert (hotInfo->downStatus()>=0);
1015  downTotalChange[index] += hotInfo->downChange()/object->downEstimate();
1016  downNumber[index]++;
1017  }
1018  else if (hotInfo->downStatus()==1) {
1019  downNumber[index]++;
1020  // infeasible - just say expensive
1021  if (info->cutoff_<1.0e50)
1022  downTotalChange[index] += 2.0*(info->cutoff_-info->objectiveValue_)/object->downEstimate();
1023  else
1024  downTotalChange[index] += 2.0*fabs(info->objectiveValue_)/object->downEstimate();
1025  }
1026  }
1027  }
1028 
1029 // Given a branch fill in useful information e.g. estimates
1030 void
1032  double changeInObjective, double changeInValue,
1033  int status)
1034 {
1035  if(cbc_model_ == NULL) return;
1036  assert (index<solver_->numberObjects());
1037  assert (branch<2);
1038 
1039  if(fabs(changeInValue) < 1e-6) return;
1040 
1041  double* upTotalChange = pseudoCosts_.upTotalChange();
1042  double* downTotalChange = pseudoCosts_.downTotalChange();
1043  int* upNumber = pseudoCosts_.upNumber();
1044  int* downNumber = pseudoCosts_.downNumber();
1045  message(UPDATE_PS_COST)<<index<< branch
1046  <<changeInObjective<<changeInValue<<status
1047  <<CoinMessageEol;
1048 
1049  if (branch) {
1050  if (status!=1) {
1051  assert (status>=0);
1052  upTotalChange[index] += changeInObjective/changeInValue;
1053  upNumber[index]++;
1054  } else {
1055  // infeasible - just say expensive
1056  upNumber[index]++;
1057  assert(cbc_model_); // Later, we need to get this information in a different way...
1058  double cutoff = cbc_model_->getCutoff();
1059  double objectiveValue = cbc_model_->getCurrentObjValue();
1060  if (cutoff<1.0e50)
1061  upTotalChange[index] += 2.0*(cutoff-objectiveValue)/changeInValue;
1062  else
1063  upTotalChange[index] += 2.0*fabs(objectiveValue)/changeInValue;
1064  }
1065  } else {
1066  if (status!=1) {
1067  assert (status>=0);
1068  downTotalChange[index] += changeInObjective/changeInValue;
1069  downNumber[index]++;
1070  } else {
1071  assert(cbc_model_);
1072  // infeasible - just say expensive
1073  downNumber[index]++;
1074  double cutoff = cbc_model_->getCutoff();
1075  double objectiveValue = cbc_model_->getCurrentObjValue();
1076  if (cutoff<1.0e50)
1077  downTotalChange[index] += 2.0*(cutoff-objectiveValue)/changeInValue;
1078  else
1079  downTotalChange[index] += 2.0*fabs(objectiveValue)/changeInValue;
1080  }
1081  }
1082 }
1083 
1084 
1085  HotInfo::HotInfo(): OsiHotInfo(), infeasibilities_(){
1086  }
1087 
1088  HotInfo::HotInfo( OsiSolverInterface * solver,
1089  const OsiBranchingInformation *info,
1090  const OsiObject * const * objects,
1091  int whichObject):
1092  OsiHotInfo(solver, info, objects, whichObject),
1093  infeasibilities_(){
1094  infeasibilities_.resize(branchingObject_->numberBranches());
1095  }
1096 
1097  HotInfo::HotInfo(const HotInfo& other): OsiHotInfo(other),
1098  infeasibilities_(other.infeasibilities_){
1099  }
1100 
1101  OsiHotInfo *
1102  HotInfo::clone() const {
1103  return new HotInfo(*this);
1104  }
1105 
1106  HotInfo &
1108  if(this != &rhs){
1109  OsiHotInfo::operator=(rhs);
1111  }
1112  return (*this);
1113  }
1114 
1116  }
1117 
1118  int
1119  HotInfo::updateInformation(const OsiSolverInterface * solver,
1120  const OsiBranchingInformation * info,
1121  OsiChooseVariable * choose){
1122  //printf("in HotInfo::updateInformation\n");
1123  int iBranch = branchingObject_->branchIndex()-1;
1124  double & infeasibility = infeasibilities_[iBranch] = 0.;
1125 
1126  OsiObject ** objects = solver->objects();
1127  int numObject = solver->numberObjects();
1128  for(int i = 0 ; i < numObject ; i++){
1129  infeasibility += objects[i]->checkInfeasibility(info);
1130  }
1131  int status = OsiHotInfo::updateInformation(solver, info, choose);
1132 #if 1
1133  if(!solver->isProvenPrimalInfeasible() && !solver->isProvenOptimal()){
1134  status = 2;
1135  statuses_[iBranch] = status;
1136  }
1137  else if(solver->isProvenPrimalInfeasible() && fabs(solver->getObjValue()) < 1e-06) {
1138  assert(solver->messageHandler() != NULL);
1139  *solver->messageHandler() << "Very small infeasibility: " << solver->getObjValue() << CoinMessageEol;
1140  status = 2;
1141  statuses_[iBranch] = status;
1142  }
1143 #endif
1144  return status;
1145  }
1146 
1147 }/* Ends Bonmin's namespace.*/
1148 
int getIntParameter(const IntParameter &p) const
Return value of integer parameter.
virtual OsiHotInfo * clone() const
Clone.
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
HotInfo()
Default constructor.
TNLPSolver::UnsolvedError * newUnsolvedError(int num, Ipopt::SmartPtr< TMINLP2TNLP > problem, std::string name)
virtual int setupList(OsiBranchingInformation *info, bool initialize)
Sets up strong list and clears all if initialize is true.
virtual ~BonChooseVariable()
Destructor.
virtual ~HotInfo()
Destructor.
double setup_pseudo_frac_
fraction of branching candidates that are not trusted yet
Ipopt::SmartPtr< Ipopt::Journalist > journalist()
Acces storage of Journalist for output.
This class chooses a variable to branch on.
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real fint fint fint fint * info
bool only_pseudo_when_trusted_
Flag indicating whether we don&#39;t want to mix strong branching and pseudo costs during the decision wh...
int trustStrongForPseudoCosts_
Wether or not to trust strong branching results for updating pseudo costs.
bool isRootNode(const OsiBranchingInformation *info) const
detecting if this is root node
const TMINLP2TNLP * problem() const
get pointer to the TMINLP2TNLP adapter
Ipopt::SmartPtr< Ipopt::Journalist > jnlst_
Holding on the a pointer to the journalist.
double maxmin_crit_no_sol_
maxmin weight in branching decision when no solution has been found yet
This is class provides an Osi interface for a Mixed Integer Linear Program expressed as a TMINLP (so ...
double computeUsefulness(const double MAXMIN_CRITERION, const double upMult, const double dowMult, const double value, const OsiObject *object, int i, double &value2) const
virtual void updateInformation(const OsiBranchingInformation *info, int branch, OsiHotInfo *hotInfo)
This is a utility function which does strong branching on a list of objects and stores the results in...
double maxminCrit(const OsiBranchingInformation *info) const
Helper functions for setupList and chooseVariable.
bool IsValid(const OSSmartPtr< U > &smart_ptr)
Definition: OSSmartPtr.hpp:465
int std_m(int n)
Definition: BonMsgUtils.hpp:10
Number of candidates for strong branching.
virtual OsiChooseVariable * clone() const
Clone.
double maxmin_crit_have_sol_
maxmin weight in branching decision when no solution has been found yet
static const std::string CNAME
Stores the class name for throwing errors.
int minNumberStrongBranch_
Always strong branch that many first candidate in the list regardless of numberTrusted.
vector< HotInfo > results_
Stores strong branching results.
static char * j
Definition: OSdtoa.cpp:3622
HotInfo & operator=(const HotInfo &rhs)
Assignment operator.
Minimum reliability before trust pseudo-costs.
CoinMessageHandler & message(Messages_Types type) const
void fint fint fint real fint real real real real real real real real real * e
#define OLD_USEFULLNESS
A class to have all elements necessary to setup a branch-and-bound.
int bb_log_level_
verbosity level
CoinMessageHandler * handler_
Message handler.
int number_not_trusted_
Number of variables put into the list because there were not trusted.
int numberLookAhead_
number of look-ahead strong-branching steps
static int
Definition: OSdtoa.cpp:2173
double time_limit_
Global time limit for algorithm.
CbcModel * cbc_model_
CbcModel, used to get status of search.
void computeMultipliers(double &upMult, double &downMult) const
int numberBeforeTrustedList_
number of times a branch has to happen so that it is trusted in setupList
vector< double > infeasibilities_
infeasibilities of children
#define ADD_MSG(Id, Type, Level, MSG)
Definition: BonMsgUtils.hpp:7
int updateInformation(const OsiSolverInterface *solver, const OsiBranchingInformation *info, OsiChooseVariable *choose)
Fill in some usefull information after a strong branching is done:
OsiPseudoCosts pseudoCosts_
Stores the pseudo costs.
BonChooseVariable()
Default Constructor, forbiden for some reason.
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
int numberStrongRoot_
number of strong branching points at root node
return b
Definition: OSdtoa.cpp:1719
virtual int doStrongBranching(OsiSolverInterface *solver, OsiBranchingInformation *info, int numberToDo, int returnCriterion)
This is a utility function which does strong branching on a list of objects and stores the results in...
const char * prefix() const
Get prefix to use for options.
BonChooseVariable & operator=(const BonChooseVariable &rhs)
Assignment operator.
virtual int chooseVariable(OsiSolverInterface *solver, OsiBranchingInformation *info, bool fixVariables)
Choose a variable Returns - -1 Node is infeasible 0 Normal termination - we have a candidate 1 All lo...
double start_time_
Starting time of algorithm.