branchExprDiv.cpp
Go to the documentation of this file.
1 /* $Id: branchExprDiv.cpp 708 2011-06-23 14:04:59Z pbelotti $
2  *
3  * Name: branchExprDiv.cpp
4  * Author: Pietro Belotti
5  * Purpose: select branch for divisions
6  *
7  * (C) Carnegie-Mellon University, 2006-11.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CouenneExprDiv.hpp"
12 #include "CouenneExprMul.hpp"
14 #include "CouenneObject.hpp"
15 
16 using namespace Couenne;
17 
21  const OsiBranchingInformation *info,
22  expression *&var,
23  double * &brpts,
24  double * &brDist, // distance of current LP
25  // point to new convexifications
26  int &way) {
27 
28  if (brDist) {free (brDist); brDist = NULL;} // clear it, computeMulBrDist will fill it
29 
30  int xi = arglist_ [0] -> Index (),
31  yi = arglist_ [1] -> Index (),
32  wi = obj -> Reference () -> Index ();
33 
34  assert ((xi >= 0) && (yi >= 0) && (wi >= 0));
35 
36  brpts = (double *) realloc (brpts, sizeof (double));
37 
38  // choosing branching variable and point is difficult, use
39  // proportion in bound intervals
40 
41  CouNumber yl = info -> lower_ [yi],
42  yu = info -> upper_ [yi],
43  y0 = info -> solution_ [yi];
44 
45  // if [yl,yu] contains 0, create two nodes
46 
47  if ((yl < -COUENNE_EPS) &&
48  (yu > COUENNE_EPS)) {
49 
50  var = arglist_ [1];
51 
52  *brpts = 0.;
53 
54  way = (y0 > *brpts) ? TWO_RIGHT : TWO_LEFT;
55 
56  brDist = computeMulBrDist (info, wi, yi, xi, yi, brpts);
57 
58  return CoinMin (brDist [0], brDist [1]);
59  /*return ((fabs (y0) < COUENNE_EPS) ? 1. :
60  fabs (info -> solution_ [xi] / y0 -
61  info -> solution_ [wi]));*/
62  }
63 
64  // From now on, [yl,yu] may be unlimited in one sense only, and
65  // interval does not contain 0.
66  //
67  // As convexification is still carried out by applying McCormick
68  // rules to x=w*y (where original operator is w=x/y), try to get
69  // closer to a situation where both y and w are bounded, if
70  // necessary by branching on w.
71  //
72  // Branch first on y if unbounded, and then on w. As a result of
73  // bound tightening, if both y and w are bounded, x will be, too.
74 
75  if ((yl < -COUENNE_INFINITY) || // and yu < 0
76  (yu > COUENNE_INFINITY)) { // and yl > 0
77 
78  var = arglist_ [1];
79 
80  // if y0 close to bounds, branch away from it
81  if (fabs (y0-yl) < COUENNE_NEAR_BOUND) *brpts = y0 + 1. + yl*10.;
82  else if (fabs (y0-yu) < COUENNE_NEAR_BOUND) *brpts = y0 - 1. + yu*10.;
83  else *brpts = y0;
84 
85  way = (y0 > 0.) ? TWO_LEFT : TWO_RIGHT;
86 
87  brDist = computeMulBrDist (info, wi, yi, xi, yi, brpts);
88 
89  return CoinMin (brDist [0], brDist [1]);
90 
91  //return ((fabs (y0) < COUENNE_EPS) ? 1. :
92  //fabs (info -> solution_ [xi] / y0 - info -> solution_ [wi]));
93  }
94 
95  // y is bounded, and y0 nonzero; if w is unbounded, bound w first as
96  // x will be too.
97 
98  CouNumber wl = info -> lower_ [wi],
99  wu = info -> upper_ [wi],
100  w0 = info -> solution_ [wi],
101  x0 = info -> solution_ [xi];
102 
103  // w unbounded in >= one direction ///////////////////////////////////////
104 
105  if ((wl < -COUENNE_INFINITY) ||
106  (wu > COUENNE_INFINITY)) {
107 
108  var = obj -> Reference ();
109 
110  if ((wl < -COUENNE_INFINITY) &&
111  (wu > COUENNE_INFINITY)) { // unbounded in two directions
112 
113  CouNumber
114  wreal = x0 / y0,
115  wmin = w0,
116  wmax = wreal; // assume (x0,y0,w0) is below w=x/y
117 
118  if (wreal < w0) { // but swap if (x0,y0,w0) is above w=x/y
119  wmin = wreal;
120  wmax = w0;
121  }
122 
123  *brpts = wreal;
124  way = (w0 < wreal) ? TWO_LEFT : TWO_RIGHT;
125 
126  brDist = computeMulBrDist (info, wi, yi, xi, wi, brpts);
127  return CoinMin (brDist [0], brDist [1]);
128 
129  } else {
130 
131  // unbounded in one direction only, use two way branching
132 
133  // if y0 close to bounds, branch away from it
134  if (fabs (w0-wl) < COUENNE_NEAR_BOUND) *brpts = w0 + 1 + wl*10;
135  else if (fabs (w0-wu) < COUENNE_NEAR_BOUND) *brpts = w0 - 1 + wu*10;
136  else *brpts = w0;
137 
138  way = (wl < - COUENNE_INFINITY) ? TWO_RIGHT : TWO_LEFT;
139 
140  brDist = computeMulBrDist (info, wi, yi, xi, wi, brpts);
141  return CoinMin (brDist [0], brDist [1]);
142  }
143  //return ((fabs (y0) < COUENNE_EPS) ? 1. : fabs (x0/y0 - w0));
144  }
145 
146  // w and y are bounded (and so is x). Choose between x, y, z
147  // depending on intervals first and then to vicinity to midpoint
148  CouNumber
149  xl = info -> lower_ [xi],
150  xu = info -> upper_ [xi],
151  dx = xu-xl,
152  dy = yu-yl,
153  dw = wu-wl;
154 
155  // Check largest interval and choose branch variable accordingly.
156  // Branching point depends on where the current point is, but for
157  // now just focus on the width of the intervals
158 
159  way = TWO_RAND;
160 
161  if (dx > dy)
162  if (dx > dw) {var = arglist_[0]; *brpts = (xl+xu)/2.; /*return fabs (x0-y0*w0);*/}
163  else {var = obj->Reference(); *brpts = (wl+wu)/2.; /*return fabs (w0-x0/y0);*/}
164  else
165  if (dy > dw) {var = arglist_[1]; *brpts = (yl+yu)/2.; /*return fabs (y0-x0/w0);*/}
166  else {var = obj->Reference(); *brpts = (wl+wu)/2.; /*return fabs (w0-x0/y0);*/}
167 
168  brDist = computeMulBrDist (info, wi, yi, xi, var -> Index (), brpts);
169  return CoinMin (brDist [0], brDist [1]);
170 }
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
OsiObject for auxiliary variables $w=f(x)$.
virtual CouNumber selectBranch(const CouenneObject *obj, const OsiBranchingInformation *info, expression *&var, double *&brpts, double *&brDist, int &way)
Set up branching object by evaluating many branching points for each expression&#39;s arguments...
ULong * x0
Definition: OSdtoa.cpp:1776
virtual int Index() const
Return index of variable (only valid for exprVar and exprAux)
double * computeMulBrDist(const OsiBranchingInformation *info, int xi, int yi, int wi, int brind, double *brpt, int nPts)
compute distance from future convexifications in set with x,y,w bounded.
#define COUENNE_EPS
expression ** arglist_
argument list is an array of pointers to other expressions
double CouNumber
main number type in Couenne
#define COUENNE_INFINITY
exprVar * Reference() const
return reference auxiliary variable
Expression base class.
#define COUENNE_NEAR_BOUND