00001
00002
00003
00004
00005
00006
00007
00008
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
00029
00030
00031 void exprPow::getBounds (expression *&lb, expression *&ub) {
00032
00033
00034
00035
00036 assert (arglist_ [0] -> Type () != CONST);
00037
00038
00039
00040
00041
00042 expression *lbbase, *ubbase;
00043 arglist_ [0] -> getBounds (lbbase, ubbase);
00044
00045
00046
00047 if (arglist_ [1] -> Type () == CONST) {
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
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 || issignpower_) && (rndexp > 0)) {
00068
00069
00070
00071
00072 lb = new exprPow (lbbase, new exprConst (expon), issignpower_);
00073 ub = new exprPow (ubbase, new exprConst (expon), issignpower_);
00074 }
00075 else {
00076
00077
00078 assert(!issignpower_);
00079
00080 expression **all = new expression * [6];
00081
00082 all [0] = new exprOpp (lbbase);
00083 all [2] = new exprConst (0.);
00084 all [4] = ubbase;
00085
00086 if (expon > 0)
00087 all [1] = new exprPow (new exprClone (lbbase), new exprConst (expon));
00088 else all [1] = new exprPow (new exprClone (ubbase), new exprConst (expon));
00089
00090
00091
00092 if (expon > COUENNE_EPS) all [3] = new exprConst (0.);
00093 else if (isInt || isInvInt) {
00094 if (rndexp % 2)
00095 all [3] = new exprConst (-COUENNE_INFINITY);
00096 else all [3] = new exprMin (new exprClone (all [1]),
00097 new exprPow (new exprClone (lbbase),
00098 new exprConst (expon)));
00099 }
00100 else all [3] = new exprClone (all [1]);
00101
00102
00103
00104 if (expon > COUENNE_EPS) {
00105 if (isInt && !(rndexp % 2))
00106 all [5] = new exprPow (new exprClone (ubbase), new exprConst (expon));
00107 else all [5] = new exprConst (0.);
00108 }
00109 else {
00110 if (isInt || isInvInt) {
00111 if (rndexp % 2)
00112 all [5] = new exprPow (new exprClone (ubbase), new exprConst (expon));
00113 else all [5] = new exprPow (new exprClone (lbbase), new exprConst (expon));
00114 }
00115 else all [5] = new exprConst (0.);
00116 }
00117
00118 lb = new exprMin (all, 6);
00119
00120
00121
00122 if (expon > 0) {
00123
00124
00125
00126
00127 ub = new exprMax (new exprPow (new exprClone (lbbase), new exprConst (expon)),
00128 new exprPow (new exprClone (ubbase), new exprConst (expon)));
00129
00130 } else {
00131
00132 expression **alu = new expression * [6];
00133
00134 alu [0] = new exprClone (all [0]);
00135 alu [2] = new exprConst (0.);
00136 alu [4] = new exprClone (ubbase);
00137
00138
00139
00140
00141
00142
00143
00144 alu [1] = new exprPow (new exprClone (lbbase), new exprConst (expon));
00145
00146
00147
00148
00149 alu [3] = new exprConst (COUENNE_INFINITY);
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 if (isInt || isInvInt)
00165 alu [5] = new exprPow (new exprClone (ubbase), new exprConst (expon));
00166 else alu [5] = new exprConst (COUENNE_INFINITY);
00167
00168
00169 ub = new exprMin (alu, 6);
00170 }
00171 }
00172 }
00173 else
00174 printf ("exprPow::getBounds(): Warning, exponent not constant\n");
00175
00176
00177
00178
00179
00180
00181
00182 }
00183
00184
00185
00186 void exprPow::getBounds (CouNumber &lb, CouNumber &ub) {
00187
00188 CouNumber lba, uba, k = (*(arglist_ [1])) ();
00189 arglist_ [0] -> getBounds (lba, uba);
00190 int intk;
00191
00192 bool
00193 isInt = fabs (k - (double) (intk = COUENNE_round (k))) < COUENNE_EPS,
00194 isInvInt = !isInt && fabs (1./k - (double) (intk = COUENNE_round (1./k))) < COUENNE_EPS;
00195
00196 if (!isInt && (!isInvInt || !(intk % 2 || issignpower_))) {
00197
00198
00199
00200 if (lba < 0.) lba = 0.;
00201 if (uba < 0.) uba = 0.;
00202 }
00203
00204 if (isInt && !(intk % 2 || issignpower_) && (k > 0)) {
00205
00206 if (uba < 0) {
00207 lb = safe_pow (-uba, k);
00208 ub = safe_pow (-lba, k);
00209 } else if (lba > 0) {
00210 lb = safe_pow (lba, k);
00211 ub = safe_pow (uba, k);
00212 } else {
00213 lb = 0;
00214 ub = safe_pow (CoinMax (-lba, uba), k);
00215 }
00216
00217 } else if (k > 0) {
00218
00219 lb = safe_pow (lba, k, issignpower_);
00220 ub = safe_pow (uba, k, issignpower_);
00221
00222 } else if (isInt && !(intk % 2 || issignpower_)) {
00223
00224 if (uba < 0) {
00225 lb = safe_pow (-lba, k);
00226 ub = safe_pow (-uba, k);
00227 } else if (lba > 0) {
00228 lb = safe_pow (uba, k);
00229 ub = safe_pow (lba, k);
00230 } else {
00231 lb = safe_pow (CoinMax (-lba, uba), k);
00232 ub = COUENNE_INFINITY;
00233 }
00234
00235 } else {
00236 assert(!issignpower_);
00237 if (uba < 0) {
00238 lb = safe_pow (uba, k);
00239 ub = safe_pow (lba, k);
00240 } else if (lba > 0) {
00241 lb = safe_pow (uba, k);
00242 ub = safe_pow (lba, k);
00243 } else {
00244 lb = -COIN_DBL_MAX;
00245 ub = COIN_DBL_MAX;
00246 }
00247 }
00248 }