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

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

Generated on Thu Oct 8 03:02:56 2009 by  doxygen 1.4.7