/home/coin/SVN-release/OS-2.4.1/Couenne/src/branch/operators/branchExprPow.cpp

Go to the documentation of this file.
00001 /* $Id: branchExprPow.cpp 708 2011-06-23 14:04:59Z pbelotti $
00002  *
00003  * Name:    branchExprPow.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: return branch gain and branch object for powers
00006  *
00007  * (C) Carnegie-Mellon University, 2006-11.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CoinHelperFunctions.hpp"
00012 
00013 #include "CouenneExprPow.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 
00035 CouNumber exprPow::selectBranch (const CouenneObject *obj,
00036                                  const OsiBranchingInformation *info,
00037                                  expression *&var,
00038                                  double * &brpts, 
00039                                  double * &brDist, // distance of current LP
00040                                                    // point to new convexifications
00041                                  int &way) {
00042 
00043   // return branching point and branching policies for an expression
00044   // of the form x^k
00045 
00046   var = arglist_ [0];
00047 
00048   int 
00049     ind = arglist_ [0]        -> Index (),
00050     wi  = obj -> Reference () -> Index ();
00051 
00052   assert ((ind >= 0) && (wi >= 0) && (arglist_ [1] -> Type () == CONST));
00053 
00054   double k = arglist_ [1] -> Value ();
00055 
00056   CouNumber y0 = info -> solution_ [wi],
00057             x0 = info -> solution_ [ind],
00058             l  = info -> lower_    [ind],
00059             u  = info -> upper_    [ind];
00060 
00061   /*printf ("selbra for "); print ();
00062   printf ("%g [%g,%g] -> %g [%g,%g]\n", 
00063           x0, l, u, y0, 
00064           info -> lower_    [wi],
00065           info -> upper_    [wi]);*/
00066 
00067   if      (x0 < l) x0 = l;
00068   else if (x0 > u) x0 = u;
00069 
00070   // bounds coincide (happens within setupList)
00071   if (fabs (u-l) < COUENNE_EPS) {
00072     brpts = (CouNumber *) realloc (brpts, sizeof (CouNumber));
00073     *brpts = 0.5*(l+u);
00074     way = TWO_RAND;
00075     brDist = (double *) realloc (brDist, 2 * sizeof (double));
00076     return (brDist [0] = brDist [1] = fabs (y0 - pow (x0, k)));
00077   }
00078 
00079   // case 1: k negative, resort to method similar to exprInv:: ///////////////////////////////
00080   if (k<0) return negPowSelectBranch (obj, info, brpts, brDist, way, k, x0, y0, l, u);
00081 
00082   brDist = (double *) realloc (brDist, 2 * sizeof (double));
00083 
00084   int intk = 0;
00085 
00086   bool isInt    =                        fabs (k    - (double) (intk = COUENNE_round (k)))    < COUENNE_EPS,
00087        isInvInt = !isInt && (k != 0.) && fabs (1./k - (double) (intk = COUENNE_round (1./k))) < COUENNE_EPS;
00088 
00089   // case 2: k is positive and even /////////////////////////////////////////////////////////
00090 
00091   if (isInt && !(intk % 2)) {
00092 
00093     if ((l < - COUENNE_INFINITY) && 
00094         (u >   COUENNE_INFINITY)) { // infinite bounds
00095 
00096       if (y0 < pow (x0, k)) { // good side
00097 
00098         brpts = (double *) realloc (brpts, sizeof (double));
00099         powertriplet pt (k);
00100         *brpts = powNewton (x0, y0, &pt);
00101 
00102         way = (x0 > 0) ? TWO_RIGHT : TWO_LEFT; // priority to same side as x0
00103 
00104         x0 -= *brpts;
00105         y0 -= pow (*brpts, k);
00106 
00107         return (brDist [0] = brDist [1] = sqrt (x0*x0 + y0*y0)); // exact distance
00108       }
00109 
00110       // on the bad side /////////////////////
00111 
00112       // TODO: restore when we can do three-way branching
00113 
00114       /*double xp = pow (y0, 1./k);
00115 
00116       brpts = (double *) realloc (brpts, 2 * sizeof (double));
00117       brpts [0] = 0.5 * (x0 - xp);
00118       brpts [1] = 0.5 * (x0 + xp);
00119 
00120       way = THREE_CENTER;
00121 
00122       return CoinMin (x0 - brpts [0], 
00123                       CoinMin (brpts [1] - x0, 
00124                                projectSeg (x0, y0, 
00125                                            brpts [0], pow (brpts [0], k),
00126                                            brpts [1], pow (brpts [1], k), -1)));*/
00127 
00128       // in the meantime, branch on current point (next branch won't
00129       // have unbounded x)
00130 
00131       brpts = (double *) realloc (brpts, sizeof (double));
00132       *brpts = x0;
00133       way = TWO_RAND;
00134 
00135       return (brDist [0] = brDist [1] = fabs (y0 - pow (x0,k)));
00136 
00137       // no bounds on x
00138       /*      double alpha = pow ((y0 + pow (x0, k))/2, 1./k),
00139              yroot = pow (y0, 1./k);
00140       brpts = (double *) realloc (brpts, 2 * sizeof (double));
00141       double lambdaL = (-x0 / yroot), lambdaR = 0;
00142       if (lambdaL < 0) {
00143         lambdaR = -lambdaL;
00144         lambdaL = 0;
00145       }
00146       CouNumber // approx distance
00147         b0 = brpts [0] = -alpha + lambdaL * (alpha - yroot),
00148         b1 = brpts [1] =  alpha + lambdaR * (yroot - alpha);
00149       way = THREE_CENTER;
00150       return CoinMin (projectSeg (x0, y0, b0, pow (b0, k), b1, pow (b1, k), -1), 
00151                       CoinMin (x0 - b0, b1 - x0));      */
00152     }
00153 
00154     // at least one bound is finite //////////////////////////////////////////////
00155 
00156     brpts = (double *) realloc (brpts, sizeof (double));
00157 
00158     if (l < -COUENNE_INFINITY) {
00159 
00160       // if y0 is huge, try to make it close to 0
00161       *brpts = obj -> midInterval (-safe_pow (y0, 1. / k), l, u, info);
00162       way = TWO_RIGHT;
00163 
00164       //printf ("  ----> brptPow %g\n", *brpts);
00165 
00166       return CoinMin (brDist [0] = x0 - *brpts, 
00167                       brDist [1] = projectSeg
00168                       (x0,     y0, 
00169                        *brpts, safe_pow (*brpts, k), 
00170                        u,      safe_pow (u, k), -1));
00171     }
00172 
00173     if (u >  COUENNE_INFINITY) {
00174 
00175       // if y0 is huge, try to make it close to 0
00176       //*brpts = CoinMin (safe_pow (y0, 1. / k), COU_MAX_COEFF / k);
00177       *brpts = obj -> midInterval (safe_pow (y0, 1. / k), l, u, info);
00178       way = TWO_LEFT;
00179 
00180       //printf ("  ----> brptPow %g\n", *brpts);
00181 
00182       return CoinMin (brDist [1] = *brpts - x0,
00183                       brDist [0] = projectSeg
00184                       (x0,     y0, 
00185                        l,      safe_pow (l, k),
00186                        *brpts, safe_pow (*brpts, k), -1));
00187     } 
00188 
00189     // both bounds are finite ///////////////////////////////////////////////
00190 
00191     powertriplet ft (k);
00192     //*brpts = maxHeight (&ft, x0, y0, l, u);
00193     *brpts = obj -> getBrPoint (&ft, x0, l, u, info);
00194 
00195     way = (x0 < *brpts) ? TWO_LEFT : TWO_RIGHT;
00196 
00197     //    w -> print (); printf (" := "); dynamic_cast <exprAux *> (w) -> Image () -> print ();
00198     /*print ();
00199     printf (" (%g,%g) [%g,%g] --> %g, distances = %g,%g\n",
00200             x0, y0, l, u, *brpts,
00201             projectSeg (x0, y0, l,      safe_pow (l,k), *brpts, safe_pow (*brpts,k), 0),
00202             projectSeg (x0, y0, *brpts, safe_pow (*brpts,k),      u, safe_pow (u,k), 0));*/
00203 
00204     // Min area  -- exact distance
00205     CouNumber retval = 
00206       CoinMin (brDist [0] = projectSeg (x0,y0, l,      safe_pow(l,k), *brpts, safe_pow(*brpts,k), 0),
00207                brDist [1] = projectSeg (x0,y0, *brpts, safe_pow(*brpts,k),      u, safe_pow(u,k), 0));
00208 
00209     //printf ("returning %.10e\n", retval);
00210 
00211     return retval;
00212 
00213     /*      brpts = (double *) realloc (brpts, sizeof (double));
00214      *brpts = midInterval (x0, l, u, info);
00215      way = 
00216      (l < - COUENNE_INFINITY) ? TWO_RIGHT : 
00217      (u >   COUENNE_INFINITY) ? TWO_LEFT  : TWO_RAND;
00218 
00219      return fabs (y0 - pow (x0, k)); // not an exact measure
00220     */
00221   }
00222 
00223   // from here on, we use two-way branch
00224 
00225   brpts = (double *) realloc (brpts, sizeof (double));
00226   *brpts = x0; // just in case none of the ifs below is satisfied...
00227   CouNumber pow0 = pow (x0, k);
00228 
00229   // case 3: k>1 and odd ////////////////////////////////////////////////////////////
00230 
00231   if (isInt && (intk % 2)) {
00232 
00233     way = (x0 > 0.) ? TWO_RIGHT : TWO_LEFT;
00234 
00235     if (((l < - COUENNE_INFINITY) && (u > COUENNE_INFINITY)) || // [-inf,+inf[
00236         ((l < - COUENNE_INFINITY) && (y0 < pow0))            ||
00237         ((u >   COUENNE_INFINITY) && (y0 > pow0))) {
00238 
00239       if (((y0 > 0) && (y0 < pow0)) ||  
00240           ((y0 < 0) && (y0 > pow0))) {
00241 
00242         *brpts = 0;
00243         return (brDist [0] = brDist [1] = fabs (pow0 - y0));
00244 
00245       } else {
00246 
00247         *brpts = pow (y0, 1./k);
00248 
00249         return (brDist [0] = brDist [1] = (y0 > 0) ? // approx distance
00250                 projectSeg (x0, y0, x0, CoinMax (pow0, 0.), *brpts, y0, 0) :
00251                 projectSeg (x0, y0, x0, CoinMin (pow0, 0.), *brpts, y0, 0));
00252       }
00253     }
00254 
00255     // otherwise, on the side of the current point the convexification
00256     // is bounded.
00257 
00258     powertriplet pt (k);
00259     *brpts = obj -> getBrPoint (&pt, x0, l, u, info);
00260 
00261     // in min-area and balanced strategy, point returned is
00262     // positive. Put the right sign
00263 
00264     if (y0 < pow0)
00265       *brpts = -*brpts;
00266 
00267     if (*brpts > x0) {
00268 
00269       brDist [0] = y0 - safe_pow (*brpts, k);
00270       brDist [1] = sqrt (brDist [0] * brDist [0] + (x0 - *brpts) * (x0 - *brpts));
00271 
00272     } else {
00273 
00274       brDist [1] = y0 - safe_pow (*brpts, k);
00275       brDist [0] = sqrt (brDist [1] * brDist [1] + (x0 - *brpts) * (x0 - *brpts));
00276     }
00277 
00278     // otherwise, the convexification is surely bounded.
00279     //
00280     // apply minarea
00281 
00282     /*if (u > l + COUENNE_EPS) {
00283       *brpts = safe_pow ((safe_pow (u, k) - safe_pow (l,k)) / (k* (u-l)), 1./(k-1.));
00284       if (u<0) 
00285         *brpts = -*brpts;
00286         }*/
00287   }
00288 
00289   // case 4: k positive, in ]0,1[ and 1/k is integer and odd ////////////////////////
00290 
00291   if (isInvInt && (intk % 2)) {
00292 
00293     way = (x0 > 0.) ? TWO_RIGHT : TWO_LEFT;
00294 
00295     if (((l < - COUENNE_INFINITY) && (u > COUENNE_INFINITY)) || // ]-inf,+inf[
00296         ((l < - COUENNE_INFINITY) && (y0 < pow0))            ||
00297         ((u >   COUENNE_INFINITY) && (y0 > pow0))) { 
00298 
00299       if (((x0 > 0.) && (y0 > pow0)) ||  
00300           ((x0 < 0.) && (y0 < pow0))) { // in the same orthant as the
00301                                         // curve (i.e. first or third
00302                                         // orthant)
00303 
00304         *brpts = 0.;
00305         return (brDist [0] = brDist [1] = fabs (pow0 - y0));
00306 
00307       } else {
00308 
00309         *brpts = x0; // safe for any x0 as (l != x0 != u)
00310 
00311         //*brpts = obj -> midInterval (x0, l, u, info);
00312 
00313         return (brDist [0] = brDist [1] = (x0 > 0) ? // approx distance
00314           projectSeg (x0,y0,x0, pow0, CoinMax (0., pow (y0, 1./k)), y0, 0) :
00315           projectSeg (x0,y0,x0, pow0, CoinMin (0., pow (y0, 1./k)), y0, 0));
00316       }
00317     }
00318 
00319     // otherwise, on the side of the current point the convexification
00320     // is bounded.
00321 
00322     powertriplet pt (k);
00323     *brpts = obj -> getBrPoint (&pt, x0, l, u, info);
00324 
00325     // in min-area and balanced strategy, point returned is
00326     // positive. Put the right sign
00327 
00328     if      (y0 > pow0) *brpts = -*brpts;
00329     else if (y0 < pow0) *brpts = -*brpts;
00330 
00331     if (*brpts > x0) {
00332 
00333       brDist [0] = y0 - safe_pow (*brpts, k);
00334       brDist [1] = sqrt (brDist [0] * brDist [0] + (x0 - *brpts) * (x0 - *brpts));
00335 
00336     } else {
00337 
00338       brDist [1] = y0 - safe_pow (*brpts, k);
00339       brDist [0] = sqrt (brDist [1] * brDist [1] + (x0 - *brpts) * (x0 - *brpts));
00340     }
00341 
00342     return CoinMax (brDist [0], brDist [1]);
00343 
00344     /*if (u > l + COUENNE_EPS) {
00345       *brpts = safe_pow ((safe_pow (u, k) - safe_pow (l,k)) / (k* (u-l)), 1./(k-1.));
00346       if (u<0) 
00347         *brpts = -*brpts;
00348     } else *brpts = 0.5*(l+u);*/
00349   }
00350 
00351   if (k>1) { // case 5: k>1, but not integer //////////////////////////////////////
00352 
00353     if (y0 < pow0) { // on the good side, i.e. out of the convex
00354                      // side. We don't care if u is infinity
00355 
00356       powertriplet pt (k);
00357       *brpts = powNewton (x0, y0, &pt);
00358 
00359       way = TWO_LEFT;
00360 
00361       x0 -= *brpts;
00362       y0 -= pow (*brpts, k);
00363 
00364       return (brDist [0] = brDist [1] = sqrt (x0*x0 + y0*y0));
00365 
00366     } else { // on the bad (concave) side, above curve
00367 
00368       // as a rule of thumb, take the x coordinate of the midpoint of
00369       // horizontal segment between current point and curve
00370 
00371       if (obj -> Strategy () == CouenneObject::MID_INTERVAL)
00372         *brpts = 0.5 * (x0 + pow (y0, 1. / k));
00373       else {
00374         powertriplet pt (k);
00375         *brpts = obj -> getBrPoint (&pt, x0, l, u, info);
00376       }
00377       
00378       way = TWO_LEFT;
00379 
00380       if (l < 0.) l = 0.;
00381 
00382       CouNumber 
00383         powbpt = pow (*brpts, k),
00384         projL  = projectSeg (x0, y0, l, pow (l, k), *brpts, powbpt, -1);
00385 
00386       return (brDist[0] = brDist[1] = (u > COUENNE_INFINITY) ? 
00387         CoinMin (projL, *brpts - x0) : 
00388         CoinMin (projL, projectSeg (x0,y0, *brpts,powbpt, u, pow(u,k), -1)));
00389     }
00390 
00391   } else { // case 6: 0<k<1 //////////////////////////////////////////////////////////////////
00392 
00393     if (y0 < pow0) { // on the bad side, below
00394 
00395       // same rule of thumb as above, take the x coordinate of the
00396       // midpoint of horizontal segment between current point and
00397       // curve
00398 
00399       if (obj -> Strategy () == CouenneObject::MID_INTERVAL)
00400         *brpts = 0.5 * (x0 + pow (y0, 1. / k));
00401       else {
00402         powertriplet pt (k);
00403         *brpts = obj -> getBrPoint (&pt, x0, l, u, info);
00404       }
00405 
00406       //*brpts = 0.5 * (x0 + pow (x0, 1. / k));
00407       way = TWO_LEFT;
00408 
00409       if (l < 0) l = 0;
00410 
00411       CouNumber 
00412         powbpt = pow (*brpts, k),
00413         projL  = projectSeg (x0, y0, l, pow (l, k), *brpts, powbpt, +1);
00414 
00415       return (brDist[0] = brDist[1] = (u > COUENNE_INFINITY) ? 
00416         CoinMin (projL, powbpt - y0) : 
00417         CoinMin (projL, projectSeg (x0, y0, *brpts, powbpt, u, pow (u,k), +1)));
00418 
00419     } else { // on the convex side. We don't care if u is infinite
00420 
00421       powertriplet pt (k);
00422       *brpts = powNewton (x0, y0, &pt);
00423 
00424       way = TWO_LEFT;
00425 
00426       x0 -= *brpts;
00427       y0 -= pow (*brpts, k);
00428 
00429       return (brDist [0] = brDist [1] = sqrt (x0*x0 + y0*y0));
00430     }
00431   }
00432 
00433   // failsafe: return null, so that CouenneObject picks the default
00434   // variable/branchingpoint for the expression
00435 
00436   assert (false);
00437 
00438   var = NULL;
00439   return 0.;
00440 }

Generated on Thu Nov 10 03:05:43 2011 by  doxygen 1.4.7