CouenneThreeWayBranchObj.cpp
Go to the documentation of this file.
1 /* $Id: CouenneThreeWayBranchObj.cpp 694 2011-06-18 20:13:17Z stefan $
2  *
3  * Name: CouenneThreeWayBranchObj.cpp
4  * Authors: Pietro Belotti, Carnegie Mellon University
5  * Purpose: Branching object for auxiliary variables
6  *
7  * (C) Carnegie-Mellon University, 2006-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CoinHelperFunctions.hpp"
12 #include "CouenneObject.hpp"
15 
16 using namespace Ipopt;
17 using namespace Couenne;
18 
21 CouenneThreeWayBranchObj::CouenneThreeWayBranchObj (JnlstPtr jnlst,
22  expression *brVar,
23  CouNumber lcrop,
24  CouNumber rcrop,
25  int way
26  //bool isint
27  ):
28  brVar_ (brVar),
29  lcrop_ (lcrop),
30  rcrop_ (rcrop),
31  jnlst_ (jnlst) {
32 
33  numberBranches_ = 3;
34 
35  // if none of these three, set to 0 and do code below
36  firstBranch_ = (way == THREE_LEFT) ? 0 :
37  (way == THREE_CENTER) ? 1 :
38  (way == THREE_RIGHT) ? 2 : 0;
39 
40  if (way == THREE_RAND) { // pick first branch randomly
41  CouNumber rnd = 3. * CoinDrand48 ();
42  firstBranch_ = (rnd < 1.) ? 0 : (rnd < 2.) ? 1: 2;
43  }
44 }
45 
46 
53 double CouenneThreeWayBranchObj::branch (OsiSolverInterface * solver) {
54 
55  // -1 if "<= a" node
56  // way = 0 if "[a,b]" node
57  // 1 if ">= b" node
58 
59  int way = 0;
60 
61  switch (branchIndex_) {
62  // if first offspring, let firstBranch_ decide who's first
63  case 0: way = firstBranch_; break;
64  case 1: way = (firstBranch_ == 0) ? 1 : 0; break;
65  case 2: way = (firstBranch_ == 2) ? 1 : 2; break;
66  default: jnlst_->Printf(J_WARNING, J_BRANCHING,
67  "Warning, branchIndex_ has a strange value (%d)\n", branchIndex_);
68  }
69 
70  // set lower or upper bound (round if this variable is integer)
71 
72  int index = brVar_ -> Index ();
73  bool integer = brVar_ -> isInteger ();
74 
75  CouNumber
76  l = solver -> getColLower () [index],
77  u = solver -> getColUpper () [index];
78 
79  if (lcrop_ < l) lcrop_ = l;
80  if (rcrop_ > u) rcrop_ = u;
81 
82  switch (--way) { // from {0,1,2} to {-1,0,1}
83 
84  case -1: solver -> setColUpper (index, integer ? floor (lcrop_) : lcrop_); break; // left
85  case 0: solver -> setColLower (index, integer ? ceil (lcrop_) : lcrop_);
86  solver -> setColUpper (index, integer ? floor (rcrop_) : rcrop_); break; // central
87  case 1: solver -> setColLower (index, integer ? ceil (rcrop_) : rcrop_); break; // right
88  default: jnlst_->Printf(J_WARNING, J_BRANCHING, "Couenne: branching on nonsense way %d\n", way);
89  }
90 
91  // TODO: apply bound tightening
92 
93  if (jnlst_->ProduceOutput(J_DETAILED, J_BRANCHING)) {
94  switch (way) {
95  case -1: jnlst_->Printf(J_DETAILED, J_BRANCHING,
96  "#3# Branch: x%d <= %g\n", index, lcrop_); break; // left
97  case 0: jnlst_->Printf(J_DETAILED, J_BRANCHING,
98  "#3# Branch: %g <= x%d <= %g\n", lcrop_, index, rcrop_); break; // center
99  case 1: jnlst_->Printf(J_DETAILED, J_BRANCHING,
100  "#3# Branch: x%d >= %g\n", index, rcrop_); break; // right
101  default: jnlst_->Printf(J_DETAILED, J_BRANCHING, "Couenne: branching on nonsense way %d\n", way);
102  }
103  }
104 
105  branchIndex_++;
106 
107  return 0.; // estimated change in objective function
108 }
virtual double branch(OsiSolverInterface *solver=NULL)
Execute the actions required to branch, as specified by the current state of the branching object...
int firstBranch_
First branch to be performed: 0 is left, 1 is central, 2 is right.
JnlstPtr jnlst_
True if the associated variable is integer.
const Ipopt::EJournalCategory J_BRANCHING(Ipopt::J_USER1)
double CouNumber
main number type in Couenne
Expression base class.
expression * brVar_
The variable this branching object refers to.
bool isInteger(CouNumber x)
is this number integer?