00001
00002
00003
00004
00005
00006
00007
00008
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,
00026
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,
00040
00041 int &way) {
00042
00043
00044
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
00062
00063
00064
00065
00066
00067 if (x0 < l) x0 = l;
00068 else if (x0 > u) x0 = u;
00069
00070
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 - (issignpower_ ? COUENNE_sign(x0) * pow(fabs(x0), k) : pow (x0, k))));
00077 }
00078
00079 assert (!issignpower_ || k > 0);
00080
00081
00082 if (k<0) return negPowSelectBranch (obj, info, brpts, brDist, way, k, x0, y0, l, u);
00083
00084 brDist = (double *) realloc (brDist, 2 * sizeof (double));
00085
00086 int intk = 0;
00087
00088 bool isInt = fabs (k - (double) (intk = COUENNE_round (k))) < COUENNE_EPS,
00089 isInvInt = !isInt && (k != 0.) && fabs (1./k - (double) (intk = COUENNE_round (1./k))) < COUENNE_EPS;
00090
00091
00092
00093 if (isInt && !((1 == intk % 2) || issignpower_)) {
00094
00095 if ((l < - COUENNE_INFINITY) &&
00096 (u > COUENNE_INFINITY)) {
00097
00098 if (y0 < pow (x0, k)) {
00099
00100 brpts = (double *) realloc (brpts, sizeof (double));
00101 powertriplet pt (k);
00102 *brpts = powNewton (x0, y0, &pt);
00103
00104 way = (x0 > 0) ? TWO_RIGHT : TWO_LEFT;
00105
00106 x0 -= *brpts;
00107 y0 -= pow (*brpts, k);
00108
00109 return (brDist [0] = brDist [1] = sqrt (x0*x0 + y0*y0));
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 brpts = (double *) realloc (brpts, sizeof (double));
00134 *brpts = x0;
00135 way = TWO_RAND;
00136
00137 return (brDist [0] = brDist [1] = fabs (y0 - pow (x0,k)));
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 }
00155
00156
00157
00158 brpts = (double *) realloc (brpts, sizeof (double));
00159
00160 if (l < -COUENNE_INFINITY) {
00161
00162
00163 *brpts = obj -> midInterval (-safe_pow (y0, 1. / k, issignpower_), l, u, info);
00164 way = TWO_RIGHT;
00165
00166
00167
00168 return CoinMin (brDist [0] = x0 - *brpts,
00169 brDist [1] = projectSeg
00170 (x0, y0,
00171 *brpts, safe_pow (*brpts, k, issignpower_),
00172 u, safe_pow (u, k, issignpower_), -1));
00173 }
00174
00175 if (u > COUENNE_INFINITY) {
00176
00177
00178
00179 *brpts = obj -> midInterval (safe_pow (y0, 1. / k, issignpower_), l, u, info);
00180 way = TWO_LEFT;
00181
00182
00183
00184 return CoinMin (brDist [1] = *brpts - x0,
00185 brDist [0] = projectSeg
00186 (x0, y0,
00187 l, safe_pow (l, k, issignpower_),
00188 *brpts, safe_pow (*brpts, k, issignpower_), -1));
00189 }
00190
00191
00192
00193 powertriplet ft (k);
00194
00195 *brpts = obj -> getBrPoint (&ft, x0, l, u, info);
00196
00197 way = (x0 < *brpts) ? TWO_LEFT : TWO_RIGHT;
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 CouNumber retval =
00208 CoinMin (brDist [0] = projectSeg (x0, y0, l, safe_pow (l, k, issignpower_), *brpts, safe_pow (*brpts, k, issignpower_), 0),
00209 brDist [1] = projectSeg (x0, y0, *brpts, safe_pow (*brpts, k, issignpower_), u, safe_pow (u, k, issignpower_), 0));
00210
00211
00212
00213 return retval;
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 }
00224
00225
00226
00227 brpts = (double *) realloc (brpts, sizeof (double));
00228 *brpts = x0;
00229 CouNumber pow0 = issignpower_ ? COUENNE_sign(x0) * pow(fabs(x0), k) : pow (x0, k);
00230
00231
00232
00233 if ((isInt && (1 == intk % 2)) || issignpower_) {
00234
00235 way = (x0 > 0.) ? TWO_RIGHT : TWO_LEFT;
00236
00237 if (((l < - COUENNE_INFINITY) && (u > COUENNE_INFINITY)) ||
00238 ((l < - COUENNE_INFINITY) && (y0 < pow0)) ||
00239 ((u > COUENNE_INFINITY) && (y0 > pow0))) {
00240
00241 if (((y0 > 0) && (y0 < pow0)) ||
00242 ((y0 < 0) && (y0 > pow0))) {
00243
00244 *brpts = 0;
00245 return (brDist [0] = brDist [1] = fabs (pow0 - y0));
00246
00247 } else {
00248
00249 *brpts = COUENNE_sign(y0) * pow(fabs(y0), 1./k);
00250
00251 return (brDist [0] = brDist [1] = (y0 > 0) ?
00252 projectSeg (x0, y0, x0, CoinMax (pow0, 0.), *brpts, y0, 0) :
00253 projectSeg (x0, y0, x0, CoinMin (pow0, 0.), *brpts, y0, 0));
00254 }
00255 }
00256
00257
00258
00259
00260 powertriplet pt (k, issignpower_);
00261 *brpts = obj -> getBrPoint (&pt, x0, l, u, info);
00262
00263
00264
00265
00266 if (y0 < pow0)
00267 *brpts = -*brpts;
00268
00269 if (*brpts > x0) {
00270
00271 brDist [0] = y0 - safe_pow (*brpts, k, issignpower_);
00272 brDist [1] = sqrt (brDist [0] * brDist [0] + (x0 - *brpts) * (x0 - *brpts));
00273
00274 } else {
00275
00276 brDist [1] = y0 - safe_pow (*brpts, k, issignpower_);
00277 brDist [0] = sqrt (brDist [1] * brDist [1] + (x0 - *brpts) * (x0 - *brpts));
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 }
00290
00291
00292
00293 if (isInvInt && (intk % 2) && !issignpower_) {
00294
00295 way = (x0 > 0.) ? TWO_RIGHT : TWO_LEFT;
00296
00297 if (((l < - COUENNE_INFINITY) && (u > COUENNE_INFINITY)) ||
00298 ((l < - COUENNE_INFINITY) && (y0 < pow0)) ||
00299 ((u > COUENNE_INFINITY) && (y0 > pow0))) {
00300
00301 if (((x0 > 0.) && (y0 > pow0)) ||
00302 ((x0 < 0.) && (y0 < pow0))) {
00303
00304
00305
00306 *brpts = 0.;
00307 return (brDist [0] = brDist [1] = fabs (pow0 - y0));
00308
00309 } else {
00310
00311 *brpts = x0;
00312
00313
00314
00315 return (brDist [0] = brDist [1] = (x0 > 0) ?
00316 projectSeg (x0,y0,x0, pow0, CoinMax (0., pow (y0, 1./k)), y0, 0) :
00317 projectSeg (x0,y0,x0, pow0, CoinMin (0., pow (y0, 1./k)), y0, 0));
00318 }
00319 }
00320
00321
00322
00323
00324 powertriplet pt (k);
00325 *brpts = obj -> getBrPoint (&pt, x0, l, u, info);
00326
00327
00328
00329
00330 if (y0 > pow0) *brpts = -*brpts;
00331 else if (y0 < pow0) *brpts = -*brpts;
00332
00333 if (*brpts > x0) {
00334
00335 brDist [0] = y0 - safe_pow (*brpts, k);
00336 brDist [1] = sqrt (brDist [0] * brDist [0] + (x0 - *brpts) * (x0 - *brpts));
00337
00338 } else {
00339
00340 brDist [1] = y0 - safe_pow (*brpts, k);
00341 brDist [0] = sqrt (brDist [1] * brDist [1] + (x0 - *brpts) * (x0 - *brpts));
00342 }
00343
00344 return CoinMax (brDist [0], brDist [1]);
00345
00346
00347
00348
00349
00350
00351 }
00352
00353 if (k>1) {
00354
00355 if (y0 < pow0) {
00356
00357
00358 powertriplet pt (k, issignpower_);
00359 *brpts = powNewton (x0, y0, &pt);
00360
00361 way = TWO_LEFT;
00362
00363 x0 -= *brpts;
00364 y0 -= pow (*brpts, k);
00365
00366 return (brDist [0] = brDist [1] = sqrt (x0*x0 + y0*y0));
00367
00368 } else {
00369
00370
00371
00372
00373 if (obj -> Strategy () == CouenneObject::MID_INTERVAL) {
00374 assert (!issignpower_);
00375 *brpts = 0.5 * (x0 + pow (y0, 1. / k));
00376 } else {
00377 powertriplet pt (k, issignpower_);
00378 *brpts = obj -> getBrPoint (&pt, x0, l, u, info);
00379 }
00380
00381 way = TWO_LEFT;
00382
00383 if (l < 0. && !issignpower_) l = 0.;
00384
00385 CouNumber
00386 powbpt = issignpower_ ? COUENNE_sign(*brpts) * pow (fabs (*brpts), k) : pow (*brpts, k),
00387 projL = projectSeg (x0, y0, l, issignpower_ ? COUENNE_sign(u) * pow(fabs(u),k) : pow (l, k), *brpts, powbpt, -1);
00388
00389 return (brDist[0] = brDist[1] = (u > COUENNE_INFINITY) ?
00390 CoinMin (projL, *brpts - x0) :
00391 CoinMin (projL, projectSeg (x0,y0, *brpts, powbpt, u, pow(u,k), -1)));
00392 }
00393
00394 } else {
00395
00396 if (y0 < pow0) {
00397
00398
00399
00400
00401
00402 if (obj -> Strategy () == CouenneObject::MID_INTERVAL)
00403 *brpts = 0.5 * (x0 + pow (y0, 1. / k));
00404 else {
00405 powertriplet pt (k);
00406 *brpts = obj -> getBrPoint (&pt, x0, l, u, info);
00407 }
00408
00409
00410 way = TWO_LEFT;
00411
00412 if (l < 0 && !issignpower_) l = 0.;
00413
00414 CouNumber
00415 powbpt = pow (*brpts, k),
00416 projL = projectSeg (x0, y0, l, pow (l, k), *brpts, powbpt, +1);
00417
00418 return (brDist[0] = brDist[1] = (u > COUENNE_INFINITY) ?
00419 CoinMin (projL, powbpt - y0) :
00420 CoinMin (projL, projectSeg (x0, y0, *brpts, powbpt, u, pow (u,k), +1)));
00421
00422 } else {
00423
00424 powertriplet pt (k);
00425 *brpts = powNewton (x0, y0, &pt);
00426
00427 way = TWO_LEFT;
00428
00429 x0 -= *brpts;
00430 y0 -= pow (*brpts, k);
00431
00432 return (brDist [0] = brDist [1] = sqrt (x0*x0 + y0*y0));
00433 }
00434 }
00435
00436
00437
00438
00439 assert (false);
00440
00441 var = NULL;
00442 return 0.;
00443 }