/home/coin/SVN-release/OS-2.4.0/Couenne/src/convex/operators/conv-exprPow-getBounds.cpp

Go to the documentation of this file.
00001 /* $Id: conv-exprPow-getBounds.cpp 560 2011-04-17 10:01:15Z stefan $ 
00002  *
00003  * Name:    conv-exprPow-getBounds.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: method to get lower and upper bounds of a power x^y
00006  *
00007  * (C) Carnegie-Mellon University, 2006-09.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include <math.h>
00012 
00013 #include "CouenneTypes.hpp"
00014 #include "CouenneExprPow.hpp"
00015 #include "CouenneExprConst.hpp"
00016 #include "CouenneExprClone.hpp"
00017 #include "CouenneExprMax.hpp"
00018 #include "CouenneExprMin.hpp"
00019 #include "CouenneExprOpp.hpp"
00020 #include "CouennePrecisions.hpp"
00021 #include "CouenneProblem.hpp"
00022 
00023 #include "CoinHelperFunctions.hpp"
00024 #include "CoinFinite.hpp"
00025 
00026 using namespace Couenne;
00027 
00028 // compute expressions for lower and upper bounds of a power x^y,
00029 // based on the lower/upper bounds of x and y
00030 
00031 void exprPow::getBounds (expression *&lb, expression *&ub) {
00032 
00033   // We have a standardized expression of the form w = x^y, where x or
00034   // y could be constant. Let us study each case separately.
00035 
00036   assert (arglist_ [0] -> Type () != CONST);
00037 
00038   // x is not constant, so it has (possibly different) lower and
00039   // upper bounds. The expression is x^b, b constant (the case x^y
00040   // has been decomposed by simplify() into exp(y log x).
00041 
00042   expression *lbbase, *ubbase;
00043   arglist_ [0] -> getBounds (lbbase, ubbase);
00044 
00045   //    printf ("ubbase = "); ubbase -> print (std::cout); printf ("\n"); 
00046 
00047   if (arglist_ [1] -> Type () == CONST) { 
00048 
00049     // expression = x^b, b!=0. There are four cases:
00050     // 
00051     // 1) b   is integer and odd  (cube, x^5, etc)
00052     // 2) b   is integer and even (square, x^8, etc)
00053     // 3) 1/b is integer and odd  (cube root, x^(1/7), etc)
00054     // 4) 1/b is integer and even (square root, x^(1/4), etc)
00055     // 5) none of the above
00056     //
00057     // For all of these, need to check if the exponent is negative...
00058 
00059     CouNumber expon = arglist_ [1] -> Value ();
00060     int rndexp;
00061 
00062     bool isInt =  fabs (expon - (rndexp = COUENNE_round (expon))) < COUENNE_EPS,
00063       isInvInt = !isInt &&
00064       ((fabs (expon) > COUENNE_EPS) &&
00065        (fabs (1/expon - (rndexp = COUENNE_round (1/expon))) < COUENNE_EPS));
00066 
00067     if ((isInt || isInvInt) && (rndexp % 2) && (rndexp > 0)) { 
00068 
00069       // the exponent is integer (or inverse integer), odd and
00070       // positive, hence the function is monotone non decreasing
00071 
00072       lb = new exprPow (lbbase, new exprConst (expon));
00073       ub = new exprPow (ubbase, new exprConst (expon));
00074     } 
00075     else {
00076 
00077       // the exponent is either negative, integer even, or fractional
00078 
00079       expression **all = new expression * [6];
00080 
00081       all [0] = new exprOpp   (lbbase);
00082       all [2] = new exprConst (0.);
00083       all [4] = ubbase;
00084 
00085       if (expon > 0) 
00086         all    [1] = new exprPow (new exprClone (lbbase), new exprConst (expon));
00087       else all [1] = new exprPow (new exprClone (ubbase), new exprConst (expon));
00088 
00089       // all [3] is lower bound when lbbase <= 0 <= ubbase
00090 
00091       if (expon > COUENNE_EPS) all [3] = new exprConst (0.);
00092       else if (isInt || isInvInt) {
00093         if (rndexp % 2) 
00094           all [3] = new exprConst (-COUENNE_INFINITY);
00095         else all [3] = new exprMin (new exprClone (all [1]),
00096                                     new exprPow (new exprClone (lbbase), 
00097                                                  new exprConst (expon)));
00098       }
00099       else all [3] = new exprClone (all [1]);
00100 
00101       // all [5] is the lower bound value when lbbase <= ubbase <= 0
00102 
00103       if (expon > COUENNE_EPS) {
00104         if (isInt && !(rndexp % 2))
00105           all [5] = new exprPow (new exprClone (ubbase), new exprConst (expon));
00106         else all [5] = new exprConst (0.);
00107       }
00108       else {
00109         if (isInt || isInvInt) {
00110           if (rndexp % 2)
00111             all    [5] = new exprPow (new exprClone (ubbase), new exprConst (expon));
00112           else all [5] = new exprPow (new exprClone (lbbase), new exprConst (expon));
00113         }
00114         else all [5] = new exprConst (0.);
00115       }
00116 
00117       lb = new exprMin (all, 6);
00118 
00119       // And now the upper bound ///////////////////////////////////
00120 
00121       if (expon > 0) {
00122 
00123         // special case: upper bound depends to variable bounds only:
00124         // $max {lb^k, ub^k}$
00125 
00126         ub = new exprMax (new exprPow (new exprClone (lbbase), new exprConst (expon)),
00127                           new exprPow (new exprClone (ubbase), new exprConst (expon)));
00128 
00129       } else { // from this point on, expon < 0
00130 
00131         expression **alu = new expression * [6];
00132 
00133         alu [0] = new exprClone (all [0]);
00134         alu [2] = new exprConst (0.);
00135         alu [4] = new exprClone (ubbase);
00136 
00137         //if ((isInt || isInvInt) && !(rndexp % 2))
00138         //alu    [1] = new exprPow (new exprClone (ubbase), new exprConst (expon));
00139         //else 
00140 
00141         // if negative exponent and base has nonnegative lower bound,
00142         // the upper bound can only be lb^k
00143         alu [1] = new exprPow (new exprClone (lbbase), new exprConst (expon));
00144 
00145         // alu [3] is upper bound when lbbase <= 0 <= ubbase
00146 
00147         //if (expon < - COUENNE_EPS) 
00148         alu [3] = new exprConst (COUENNE_INFINITY);
00149         //else if (isInt && !(rndexp % 2))
00150         //alu [3] = new exprPow (new exprMax (new exprClone (lbbase), new exprClone (ubbase)),
00151         //new exprConst (expon));
00152         //else alu [3] = new exprPow (new exprClone (ubbase), new exprConst (expon));
00153 
00154         // alu [5] is the upper bound value when lbbase <= ubbase <= 0
00155 
00156         /*if (expon > COUENNE_EPS) {
00157 
00158           if (isInt && !(rndexp % 2)) 
00159             alu [5] = new exprPow (new exprClone(ubbase), new exprConst(expon));
00160           else alu [5] = new exprConst (0.);
00161         }
00162         else {*/
00163         if (isInt || isInvInt) 
00164           alu [5] = new exprPow (new exprClone (ubbase), new exprConst (expon));
00165         else alu [5] = new exprConst (COUENNE_INFINITY);
00166           //}
00167 
00168         ub = new exprMin (alu, 6);
00169       }
00170     }
00171   }
00172   else // should NOT happen, exponent is not constant...
00173     printf ("exprPow::getBounds(): Warning, exponent not constant\n");
00174 
00175   /*CouNumber l, u;
00176   arglist_ [0] -> getBounds (l,u);
00177 
00178   printf ("pow::bound: ["); 
00179   lb -> print (); printf ("=%g, ", (*lb) ());
00180   ub -> print (); printf ("=%g [%g,%g]\n", (*ub) (), l, u);*/
00181 }
00182 
00183 
00184 // get value of lower and upper bound for the expression
00185 void exprPow::getBounds (CouNumber &lb, CouNumber &ub) {
00186 
00187   CouNumber lba, uba, k = (*(arglist_ [1])) ();
00188   arglist_ [0] -> getBounds (lba, uba);
00189   int intk;
00190 
00191   bool 
00192     isInt    =           fabs (k    - (double) (intk = COUENNE_round (k)))    < COUENNE_EPS,
00193     isInvInt = !isInt && fabs (1./k - (double) (intk = COUENNE_round (1./k))) < COUENNE_EPS;
00194 
00195   if (!isInt && (!isInvInt || !(intk % 2))) {
00196 
00197     // if exponent is fractional or 1/even, the base better be nonnegative
00198 
00199     if (lba < 0.) lba = 0.;
00200     if (uba < 0.) uba = 0.;
00201   }
00202 
00203   if (isInt && !(intk % 2) && (k > 0)) { // x^{2h}
00204 
00205     if (uba < 0) {
00206       lb = safe_pow (-uba, k);
00207       ub = safe_pow (-lba, k);
00208     } else if (lba > 0) {
00209       lb = safe_pow (lba, k);
00210       ub = safe_pow (uba, k);
00211     } else {
00212       lb = 0;
00213       ub = safe_pow (CoinMax (-lba, uba), k);
00214     }
00215 
00216   } else if (k > 0) { // monotone increasing: x^{2h+1} with h integer, or x^h with h real
00217 
00218     lb = safe_pow (lba, k);
00219     ub = safe_pow (uba, k);
00220 
00221   } else if (isInt && !(intk % 2)) { // x^{-2h} or x^{-1/2h} with h integer
00222 
00223     if (uba < 0) {
00224       lb = safe_pow (-lba, k);
00225       ub = safe_pow (-uba, k);
00226     } else if (lba > 0) {
00227       lb = safe_pow (uba, k);
00228       ub = safe_pow (lba, k);
00229     } else {
00230       lb = safe_pow (CoinMax (-lba, uba), k);
00231       ub = COUENNE_INFINITY;
00232     }
00233 
00234   } else { // x^k, k<0
00235 
00236     if (uba < 0) {
00237       lb = safe_pow (uba, k);
00238       ub = safe_pow (lba, k);
00239     } else if (lba > 0) {
00240       lb = safe_pow (uba, k);
00241       ub = safe_pow (lba, k);
00242     } else {
00243       lb = -COIN_DBL_MAX; // !!! may not be reached
00244       ub =  COIN_DBL_MAX;
00245     }
00246   }
00247 }

Generated on Thu Sep 22 03:05:56 2011 by  doxygen 1.4.7