00001
00002
00003
00004
00005
00006
00007
00008
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,
00024
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,
00038
00039 int &way) {
00040
00041
00042
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
00060
00061
00062
00063
00064
00065 if (x0 < l) x0 = l;
00066 else if (x0 > u) x0 = u;
00067
00068
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
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
00088
00089 if (isInt && !(intk % 2)) {
00090
00091 if ((l < - COUENNE_INFINITY) &&
00092 (u > COUENNE_INFINITY)) {
00093
00094 if (y0 < pow (x0, k)) {
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;
00101
00102 x0 -= *brpts;
00103 y0 -= pow (*brpts, k);
00104
00105 return (brDist [0] = brDist [1] = sqrt (x0*x0 + y0*y0));
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
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
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 }
00151
00152
00153
00154 brpts = (double *) realloc (brpts, sizeof (double));
00155
00156 if (l < -COUENNE_INFINITY) {
00157
00158
00159 *brpts = obj -> midInterval (-safe_pow (y0, 1. / k), l, u);
00160 way = TWO_RIGHT;
00161
00162
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
00174
00175 *brpts = obj -> midInterval (safe_pow (y0, 1. / k), l, u);
00176 way = TWO_LEFT;
00177
00178
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
00188
00189 powertriplet ft (k);
00190
00191 *brpts = obj -> getBrPoint (&ft, x0, l, u);
00192
00193 way = (x0 < *brpts) ? TWO_LEFT : TWO_RIGHT;
00194
00195
00196
00197
00198
00199
00200
00201
00202
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
00208
00209 return retval;
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 }
00220
00221
00222
00223 brpts = (double *) realloc (brpts, sizeof (double));
00224 *brpts = x0;
00225 CouNumber pow0 = pow (x0, k);
00226
00227
00228
00229 if (isInt && (intk % 2)) {
00230
00231 way = (x0 > 0.) ? TWO_RIGHT : TWO_LEFT;
00232
00233 if ((l < - COUENNE_INFINITY) && (u > COUENNE_INFINITY) ||
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) ?
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
00254
00255
00256 powertriplet pt (k);
00257 *brpts = obj -> getBrPoint (&pt, x0, l, u);
00258
00259
00260
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
00277
00278
00279
00280
00281
00282
00283
00284
00285 }
00286
00287
00288
00289
00290 if (isInvInt && (intk % 2)) {
00291
00292 way = (x0 > 0.) ? TWO_RIGHT : TWO_LEFT;
00293
00294 if ((l < - COUENNE_INFINITY) && (u > COUENNE_INFINITY) ||
00295 (l < - COUENNE_INFINITY) && (y0 < pow0) ||
00296 (u > COUENNE_INFINITY) && (y0 > pow0)){
00297
00298 if ((x0 > 0.) && (y0 > pow0) ||
00299 (x0 < 0.) && (y0 < pow0)) {
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) ?
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
00315
00316
00317 powertriplet pt (k);
00318 *brpts = obj -> getBrPoint (&pt, x0, l, u);
00319
00320
00321
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
00341
00342
00343
00344
00345 }
00346
00347 if (k>1) {
00348
00349 if (y0 < pow0) {
00350
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 {
00363
00364
00365
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 {
00388
00389 if (y0 < pow0) {
00390
00391
00392
00393
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
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 {
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
00430
00431
00432 assert (false);
00433
00434 var = NULL;
00435 return 0.;
00436 }