/home/coin/SVN-release/OS-2.4.2/Couenne/src/branch/operators/branchExprInv.cpp

Go to the documentation of this file.
00001 /* $Id: branchExprInv.cpp 708 2011-06-23 14:04:59Z pbelotti $
00002  *
00003  * Name:    branchExprInv.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: return branch selection for 1/x
00006  *
00007  * (C) Carnegie-Mellon University, 2006-07.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CoinHelperFunctions.hpp"
00012 
00013 #include "CouenneExprInv.hpp"
00014 #include "CouenneObject.hpp"
00015 #include "CouenneBranchingObject.hpp"
00016 #include "CouenneProjections.hpp"
00017 #include "CouenneFunTriplets.hpp"
00018 
00019 using namespace Couenne;
00020 
00022 CouNumber negPowSelectBranch (const CouenneObject *obj, 
00023                               const OsiBranchingInformation *info,
00024                               double * &brpts,  
00025                               double * &brDist, // distance of current LP
00026                                                 // point to new convexifications
00027                               int &way,
00028                               CouNumber k,
00029                               CouNumber x0, CouNumber y0, 
00030                               CouNumber l,  CouNumber u) {
00031 
00032   brDist = (double *) realloc (brDist, 2 * sizeof (double));
00033   brpts  = (double *) realloc (brpts, sizeof (CouNumber));
00034 
00035   // two cases: inside or outside the curves (there are two branches
00036   // of the hyperbola).
00037   //
00038   // Inside: the distance depends on the projection of the current
00039   // point onto the would-be upper envelopes, which forces us to look
00040   // at it numerically. If both bounds are infinite, create a ThreeWay
00041   // branch.
00042   //
00043   // Outside: it suffices to project the current point on the line
00044   // (i.e. to get the closest point on the line) to get the maxi-min
00045   // displacement.
00046   //
00047   // As for all monotonous functions, after choosing *brpts it is
00048   // equivalent to choose w's or x's index as ind, as the implied- and
00049   // propagated bounds will do the rest.
00050 
00051   if ((l < -COUENNE_EPS) && (u > COUENNE_EPS)) { // handle discontinuity
00052 
00053     // no matter if the (negative) exponent is odd or even, we better
00054     // branch on 0 lest we have no good convexification (especially
00055     // with odd exponent)
00056 
00057     *brpts = 0.;
00058     way = TWO_RAND;
00059 
00060     // Closest branch of the hyperbola is on the same side of y+x=0 as
00061     // (x0,y0) => need only one powNewton
00062 
00063     if (fabs (x0) < COUENNE_EPS)
00064       x0 = (x0 <= -0.) ? -COUENNE_EPS : COUENNE_EPS;
00065 
00066     CouNumber xp, xx0 = x0, yy0 = y0, exponent = k;
00067 
00068     // invert dependent and independent if
00069     if (((x0+y0 < 0.) && (x0 > 0.)) ||  // in lower half of fourth orthant, or
00070         ((x0+y0 > 0.) && (x0 < 0.))) {  // in upper half of second orthant
00071 
00072       exponent = 1. / k;
00073       xx0 = y0;
00074       yy0 = x0;
00075     }
00076 
00077     powertriplet pt (exponent);
00078 
00079     xp = (xx0 >= 0) ? 
00080        powNewton  (xx0,  yy0, &pt) : 
00081       -powNewton (-xx0, -yy0, &pt);
00082 
00083     CouNumber diff = x0 - xp;
00084     y0 -= safe_pow (xp, 1. / k);
00085 
00086     brDist [0] = sqrt (diff*diff + y0*y0); // exact distance
00087     brDist [1] = CoinMax (fabs (x0), 1.);
00088 
00089     if (x0 > 0.) {
00090       double swap = brDist [0];
00091       brDist [0] = brDist [1];
00092       brDist [1] = swap;
00093     }
00094 
00095     return CoinMin (brDist [0], brDist [1]);
00096   }
00097 
00098   int intk = 0;
00099 
00100   bool
00101     isInt    =            fabs (k    - (double) (intk = COUENNE_round (k)))    < COUENNE_EPS,
00102     isInvInt = !isInt && (fabs (1./k - (double) (intk = COUENNE_round (1./k))) < COUENNE_EPS);
00103 
00104   // case 2: bound interval does not contain zero. Look if inside or
00105   // outside of belly (refer to branchExprExp.cpp)
00106 
00107   if (((x0 >=  0.) &&                           (y0 <  safe_pow  (x0,k)))  ||    // x0>0, or
00108       ((x0 <= -0.) &&                                                            // x0<0, and
00109        (((isInt &&               !(intk % 2) && (y0 <  safe_pow  (x0,k)))) ||    // integer, even
00110         (((isInt || isInvInt) &&  (intk % 2) && (y0 > -safe_pow (-x0,k))))))) {  // (inv)integer, odd
00111 
00112     // Inside. Branch on closest point on curve, computed with a
00113     // Newton method
00114 
00115     way = (u < -0.) ? TWO_RIGHT : TWO_LEFT; // explore finite interval first
00116 
00117     powertriplet pt (k);
00118 
00119     *brpts = obj -> midInterval ((x0 >= 0.) ? 
00120                                   powNewton ( x0,  y0, &pt) : 
00121                                  -powNewton (-x0, -y0, &pt), l, u, info);
00122 
00123     CouNumber dy = y0 - safe_pow (*brpts >= 0 ? *brpts : - *brpts, 1. / k);
00124     x0 -= *brpts;
00125     return (brDist [0] = brDist [1] = sqrt (x0*x0 + dy*dy)); // distance is exact
00126   }
00127 
00128   // Inside, (x0^k) * y0 >= 1. Two cases: /////////////////////////////////////////////////
00129  
00130   // 1) bounds are infinite both horizontally and vertically
00131   // (i.e. [-inf,0] or [0,inf]) --> as for exprExp, pick point on
00132   // diagonal from current to curve, to be sure current will be cut by
00133   // branching rule
00134 
00135   if (((l <   COUENNE_EPS) && (u >   COUENNE_INFINITY)) || 
00136       ((u > - COUENNE_EPS) && (l < - COUENNE_INFINITY))) {
00137 
00138     /* brpts = (double *) realloc (brpts, 2 * sizeof (double));
00139     way = THREE_CENTER; // focus on central convexification first
00140     brpts [0] = x0;      // draw vertical   from (x0,y0) south (north) to curve y=1/x
00141     brpts [1] = 1. / y0; //      horizontal              west  (east)
00142     CouNumber a = fabs (y0 - 1 / x0), // sides of a triangle with (x0,y0)
00143               b = fabs (x0 - 1 / y0), // as one of the vertices
00144               c = a * cos (atan (a/b)); */
00145 
00146     //brpts = (double *) realloc (brpts, sizeof (double));
00147 
00148     //if (x0 > COUENNE_EPS) 
00149     *brpts = 0.5 * (fabs (x0) + pow (fabs (y0), 1./k));
00150 
00151     if (x0 < 0.) {
00152       *brpts = - *brpts;
00153       brDist [0] = fabs (fabs (y0) - safe_pow (fabs (x0), k));
00154       brDist [1] = *brpts - x0;
00155     } else {
00156       brDist [0] = x0 - *brpts;
00157       brDist [1] = fabs (y0 - safe_pow (x0, k));
00158     }
00159 
00160     //else 
00161     //*brpts = 0.5 * (x0 + pow (y0, 1./k));
00162 
00163     // follow South-East diagonal to find point on curve
00164     // so that current point is surely cut 
00165     //*brpts = 0.5 * (x0 + log (y0)); 
00166     //way = TWO_RAND;
00167     way = (x0 > *brpts) ? TWO_RIGHT : TWO_LEFT;
00168 
00169     return CoinMin (brDist [0], brDist [1]);
00170     //x0 - pow (fabs (y0), 1./k), y0 - pow (x0,k));
00171     //return CoinMin (a, CoinMin (b, c)); // distance is exact
00172   }
00173 
00174   // 2) at least one of them is finite
00175 
00176   if (l < - COUENNE_INFINITY) { // u << -0
00177 
00178     way = TWO_RIGHT;
00179     *brpts = obj -> midInterval (x0, l, u, info);
00180 
00181     return CoinMin (brDist [0] = y0 - safe_pow (*brpts, 1. / k), 
00182                     brDist [1] = projectSeg (x0, y0, l, safe_pow (l, k), 
00183                                              *brpts, safe_pow (*brpts, k), -1)); // distance is exact
00184   }
00185 
00186   if (u > COUENNE_INFINITY) { // l >> +0
00187 
00188     way = TWO_LEFT;
00189     *brpts = obj -> midInterval (x0, l, u, info);
00190 
00191     return CoinMin (brDist [1] = y0 - safe_pow (*brpts, 1. / k), 
00192                     brDist [0] = projectSeg (x0, y0, l, safe_pow (l, k), 
00193                                              *brpts, safe_pow (*brpts, k), +1)); // distance is exact
00194   }
00195 
00196   // last case: nice finite interval and limited curve
00197 
00198   powertriplet ft (k);
00199   *brpts = obj -> getBrPoint (&ft, x0, l, u, info);
00200 
00201   /*  // TODO: check if it works with all exponents
00202   if (u > l + COUENNE_EPS) {
00203 
00204     powertriplet ft (k);
00205     *brpts = maxHeight (&ft, l, u); // min area
00206 
00207     // *brpts = safe_pow ((safe_pow (u,k) - safe_pow (l,k)) / (k * (u-l)), 1/(k-1));
00208     // if (u < 0)
00209     // *brpts = - *brpts;
00210   }
00211   else *brpts = midInterval (x0, l, u, info);*/
00212 
00213   way = TWO_RAND;
00214 
00215   x0 -= *brpts;
00216   y0 -= safe_pow (*brpts, k);
00217 
00218   brDist [0] = projectSeg (x0,y0, l,      safe_pow (l,      k), *brpts, safe_pow (*brpts, k), 0);
00219   brDist [1] = projectSeg (x0,y0, *brpts, safe_pow (*brpts, k), u,      safe_pow (u,      k), 0);
00220 
00221   return CoinMin (brDist [0], brDist [1]);//sqrt (x0*x0 + y0*y0); // distance is exact
00222 }
00223 
00224 
00225 
00228 
00229 CouNumber exprInv::selectBranch (const CouenneObject *obj, 
00230                                  const OsiBranchingInformation *info,
00231                                  expression *&var,
00232                                  double * &brpts, 
00233                                  double * &brDist, // distance of current LP
00234                                                    // point to new convexifications
00235                                  int &way) {
00236 
00237   var = argument_;
00238 
00239   int
00240     ind = argument_           -> Index (),
00241     wi  = obj -> Reference () -> Index ();
00242 
00243   assert ((ind >= 0) && (wi >= 0));
00244 
00245   CouNumber y0 = info -> solution_ [wi],
00246             x0 = info -> solution_ [ind],
00247             l  = info -> lower_    [ind],
00248             u  = info -> upper_    [ind];
00249 
00250   return negPowSelectBranch (obj, info, brpts, brDist, way, -1, x0, y0, l,  u);
00251 }

Generated on Wed Nov 30 03:03:58 2011 by  doxygen 1.4.7