branchExprInv.cpp
Go to the documentation of this file.
1 /* $Id: branchExprInv.cpp 940 2013-01-13 19:49:02Z pbelotti $
2  *
3  * Name: branchExprInv.cpp
4  * Author: Pietro Belotti
5  * Purpose: return branch selection for 1/x
6  *
7  * (C) Carnegie-Mellon University, 2006-07.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CoinHelperFunctions.hpp"
12 
13 #include "CouenneExprInv.hpp"
14 #include "CouenneObject.hpp"
16 #include "CouenneProjections.hpp"
17 #include "CouenneFunTriplets.hpp"
18 
19 using namespace Couenne;
20 
23  const OsiBranchingInformation *info,
24  double * &brpts,
25  double * &brDist, // distance of current LP
26  // point to new convexifications
27  int &way,
28  CouNumber k,
29  CouNumber x0, CouNumber y0,
30  CouNumber l, CouNumber u) {
31 
32  brDist = (double *) realloc (brDist, 2 * sizeof (double));
33  brpts = (double *) realloc (brpts, sizeof (CouNumber));
34 
35  // two cases: inside or outside the curves (there are two branches
36  // of the hyperbola).
37  //
38  // Inside: the distance depends on the projection of the current
39  // point onto the would-be upper envelopes, which forces us to look
40  // at it numerically. If both bounds are infinite, create a ThreeWay
41  // branch.
42  //
43  // Outside: it suffices to project the current point on the line
44  // (i.e. to get the closest point on the line) to get the maxi-min
45  // displacement.
46  //
47  // As for all monotonous functions, after choosing *brpts it is
48  // equivalent to choose w's or x's index as ind, as the implied- and
49  // propagated bounds will do the rest.
50 
51  if ((l < -COUENNE_EPS) && (u > COUENNE_EPS)) { // handle discontinuity
52 
53  // no matter if the (negative) exponent is odd or even, we better
54  // branch on 0 lest we have no good convexification (especially
55  // with odd exponent)
56 
57  *brpts = 0.;
58  way = TWO_RAND;
59 
60  // Closest branch of the hyperbola is on the same side of y+x=0 as
61  // (x0,y0) => need only one powNewton
62 
63  if (fabs (x0) < COUENNE_EPS)
64  x0 = (x0 <= -0.) ? -COUENNE_EPS : COUENNE_EPS;
65 
66  CouNumber xp, xx0 = x0, yy0 = y0, exponent = k;
67 
68  // invert dependent and independent if
69  if (((x0+y0 < 0.) && (x0 > 0.)) || // in lower half of fourth orthant, or
70  ((x0+y0 > 0.) && (x0 < 0.))) { // in upper half of second orthant
71 
72  exponent = 1. / k;
73  xx0 = y0;
74  yy0 = x0;
75  }
76 
77  powertriplet pt (exponent);
78 
79  xp = (xx0 >= 0) ?
80  powNewton (xx0, yy0, &pt) :
81  -powNewton (-xx0, -yy0, &pt);
82 
83  CouNumber diff = x0 - xp;
84  y0 -= safe_pow (xp, 1. / k);
85 
86  brDist [0] = sqrt (diff*diff + y0*y0); // exact distance
87  brDist [1] = CoinMax (fabs (x0), 1.);
88 
89  if (x0 > 0.) {
90  double swap = brDist [0];
91  brDist [0] = brDist [1];
92  brDist [1] = swap;
93  }
94 
95  return CoinMin (brDist [0], brDist [1]);
96  }
97 
98  int intk = 0;
99 
100  bool
101  isInt = fabs (k - (double) (intk = COUENNE_round (k))) < COUENNE_EPS,
102  isInvInt = !isInt && (fabs (1./k - (double) (intk = COUENNE_round (1./k))) < COUENNE_EPS);
103 
104  // case 2: bound interval does not contain zero. Look if inside or
105  // outside of belly (refer to branchExprExp.cpp)
106 
107  if (((x0 >= 0.) && (y0 < safe_pow (x0,k))) || // x0>0, or
108  ((x0 <= -0.) && // x0<0, and
109  (((isInt && !(intk % 2) && (y0 < safe_pow (x0,k)))) || // integer, even
110  (((isInt || isInvInt) && (intk % 2) && (y0 > -safe_pow (-x0,k))))))) { // (inv)integer, odd
111 
112  // Inside. Branch on closest point on curve, computed with a
113  // Newton method
114 
115  way = (u < -0.) ? TWO_RIGHT : TWO_LEFT; // explore finite interval first
116 
117  powertriplet pt (k);
118 
119  *brpts = obj -> midInterval ((x0 >= 0.) ?
120  powNewton ( x0, y0, &pt) :
121  -powNewton (-x0, -y0, &pt), l, u, info);
122 
123  CouNumber dy = y0 - safe_pow (*brpts >= 0 ? *brpts : - *brpts, 1. / k);
124  x0 -= *brpts;
125  return (brDist [0] = brDist [1] = sqrt (x0*x0 + dy*dy)); // distance is exact
126  }
127 
128  // Inside, (x0^k) * y0 >= 1. Two cases: /////////////////////////////////////////////////
129 
130  // 1) bounds are infinite both horizontally and vertically
131  // (i.e. [-inf,0] or [0,inf]) --> as for exprExp, pick point on
132  // diagonal from current to curve, to be sure current will be cut by
133  // branching rule
134 
135  if (((l < COUENNE_EPS) && (u > COUENNE_INFINITY)) ||
136  ((u > - COUENNE_EPS) && (l < - COUENNE_INFINITY))) {
137 
138  /* brpts = (double *) realloc (brpts, 2 * sizeof (double));
139  way = THREE_CENTER; // focus on central convexification first
140  brpts [0] = x0; // draw vertical from (x0,y0) south (north) to curve y=1/x
141  brpts [1] = 1. / y0; // horizontal west (east)
142  CouNumber a = fabs (y0 - 1 / x0), // sides of a triangle with (x0,y0)
143  b = fabs (x0 - 1 / y0), // as one of the vertices
144  c = a * cos (atan (a/b)); */
145 
146  //brpts = (double *) realloc (brpts, sizeof (double));
147 
148  //if (x0 > COUENNE_EPS)
149  *brpts = 0.5 * (fabs (x0) + pow (fabs (y0), 1./k));
150 
151  if (x0 < 0.) {
152  *brpts = - *brpts;
153  brDist [0] = fabs (fabs (y0) - safe_pow (fabs (x0), k));
154  brDist [1] = *brpts - x0;
155  } else {
156  brDist [0] = x0 - *brpts;
157  brDist [1] = fabs (y0 - safe_pow (x0, k));
158  }
159 
160  //else
161  //*brpts = 0.5 * (x0 + pow (y0, 1./k));
162 
163  // follow South-East diagonal to find point on curve
164  // so that current point is surely cut
165  //*brpts = 0.5 * (x0 + log (y0));
166  //way = TWO_RAND;
167  way = (x0 > *brpts) ? TWO_RIGHT : TWO_LEFT;
168 
169  return CoinMin (brDist [0], brDist [1]);
170  //x0 - pow (fabs (y0), 1./k), y0 - pow (x0,k));
171  //return CoinMin (a, CoinMin (b, c)); // distance is exact
172  }
173 
174  // 2) at least one of them is finite
175 
176  if (l < - COUENNE_INFINITY) { // u << -0
177 
178  way = TWO_RIGHT;
179  *brpts = obj -> midInterval (x0, l, u, info);
180 
181  return CoinMin (brDist [0] = y0 - safe_pow (*brpts, 1. / k),
182  brDist [1] = projectSeg (x0, y0, l, safe_pow (l, k),
183  *brpts, safe_pow (*brpts, k), -1)); // distance is exact
184  }
185 
186  if (u > COUENNE_INFINITY) { // l >> +0
187 
188  way = TWO_LEFT;
189  *brpts = obj -> midInterval (x0, l, u, info);
190 
191  return CoinMin (brDist [1] = y0 - safe_pow (*brpts, 1. / k),
192  brDist [0] = projectSeg (x0, y0, l, safe_pow (l, k),
193  *brpts, safe_pow (*brpts, k), +1)); // distance is exact
194  }
195 
196  // last case: nice finite interval and limited curve
197 
198  powertriplet ft (k);
199  *brpts = obj -> getBrPoint (&ft, x0, l, u, info);
200 
201  /* // TODO: check if it works with all exponents
202  if (u > l + COUENNE_EPS) {
203 
204  powertriplet ft (k);
205  *brpts = maxHeight (&ft, l, u); // min area
206 
207  // *brpts = safe_pow ((safe_pow (u,k) - safe_pow (l,k)) / (k * (u-l)), 1/(k-1));
208  // if (u < 0)
209  // *brpts = - *brpts;
210  }
211  else *brpts = midInterval (x0, l, u, info);*/
212 
213  way = TWO_RAND;
214 
215  x0 -= *brpts;
216  y0 -= safe_pow (*brpts, k);
217 
218  brDist [0] = projectSeg (x0,y0, l, safe_pow (l, k), *brpts, safe_pow (*brpts, k), 0);
219  brDist [1] = projectSeg (x0,y0, *brpts, safe_pow (*brpts, k), u, safe_pow (u, k), 0);
220 
221  return CoinMin (brDist [0], brDist [1]);//sqrt (x0*x0 + y0*y0); // distance is exact
222 }
223 
224 
225 
228 
230  const OsiBranchingInformation *info,
231  expression *&var,
232  double * &brpts,
233  double * &brDist, // distance of current LP
234  // point to new convexifications
235  int &way) {
236 
237  var = argument_;
238 
239  int
240  ind = argument_ -> Index (),
241  wi = obj -> Reference () -> Index ();
242 
243  assert ((ind >= 0) && (wi >= 0));
244 
245  CouNumber y0 = info -> solution_ [wi],
246  x0 = info -> solution_ [ind],
247  l = info -> lower_ [ind],
248  u = info -> upper_ [ind];
249 
250  return negPowSelectBranch (obj, info, brpts, brDist, way, -1, x0, y0, l, u);
251 }
#define COUENNE_round(x)
static Bigint * diff(Bigint *a, Bigint *b)
Definition: OSdtoa.cpp:1120
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)$.
CouNumber negPowSelectBranch(const CouenneObject *obj, const OsiBranchingInformation *info, double *&brpts, double *&brDist, int &way, CouNumber k, CouNumber x0, CouNumber y0, CouNumber l, CouNumber u)
generic approach for negative powers (commom with exprInv::selectBranch())
CouNumber powNewton(CouNumber xc, CouNumber yc, unary_function f, unary_function fp, unary_function fpp)
find proper tangent point to add deepest tangent cut
Definition: powNewton.cpp:29
expression * argument_
single argument taken by this expression
ULong * x0
Definition: OSdtoa.cpp:1776
virtual int Index() const
Return index of variable (only valid for exprVar and exprAux)
void fint fint * k
#define COUENNE_EPS
CouNumber projectSeg(CouNumber x0, CouNumber y0, CouNumber x1, CouNumber y1, CouNumber x2, CouNumber y2, int sign, CouNumber *xp=NULL, CouNumber *yp=NULL)
Compute projection of point (x0, y0) on the segment defined by two points (x1,y1), (x2, y2) – sign provided by parameter sign.
Definition: projections.cpp:78
double CouNumber
main number type in Couenne
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 ...
#define COUENNE_INFINITY
CouNumber safe_pow(CouNumber base, CouNumber exponent, bool signpower=false)
compute power and check for integer-and-odd inverse exponent
Expression base class.