00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CoinHelperFunctions.hpp"
00012
00013 #include "CouenneExprInv.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 brDist = (double *) realloc (brDist, 2 * sizeof (double));
00033 brpts = (double *) realloc (brpts, sizeof (CouNumber));
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 if ((l < -COUENNE_EPS) && (u > COUENNE_EPS)) {
00052
00053
00054
00055
00056
00057 *brpts = 0.;
00058 way = TWO_RAND;
00059
00060
00061
00062
00063 if (fabs (x0) < COUENNE_EPS)
00064 x0 = (x0 <= -0.) ? -COUENNE_EPS : COUENNE_EPS;
00065
00066 CouNumber xp, xx0 = x0, yy0 = y0, exponent = k;
00067
00068
00069 if (((x0+y0 < 0.) && (x0 > 0.)) ||
00070 ((x0+y0 > 0.) && (x0 < 0.))) {
00071
00072 exponent = 1. / k;
00073 xx0 = y0;
00074 yy0 = x0;
00075 }
00076
00077 powertriplet pt (exponent);
00078
00079 xp = (xx0 >= 0) ?
00080 powNewton (xx0, yy0, &pt) :
00081 -powNewton (-xx0, -yy0, &pt);
00082
00083 CouNumber diff = x0 - xp;
00084 y0 -= safe_pow (xp, 1. / k);
00085
00086 brDist [0] = sqrt (diff*diff + y0*y0);
00087 brDist [1] = CoinMax (fabs (x0), 1.);
00088
00089 if (x0 > 0.) {
00090 double swap = brDist [0];
00091 brDist [0] = brDist [1];
00092 brDist [1] = swap;
00093 }
00094
00095 return CoinMin (brDist [0], brDist [1]);
00096 }
00097
00098 int intk = 0;
00099
00100 bool
00101 isInt = fabs (k - (double) (intk = COUENNE_round (k))) < COUENNE_EPS,
00102 isInvInt = !isInt && (fabs (1./k - (double) (intk = COUENNE_round (1./k))) < COUENNE_EPS);
00103
00104
00105
00106
00107 if (((x0 >= 0.) && (y0 < safe_pow (x0,k))) ||
00108 ((x0 <= -0.) &&
00109 (((isInt && !(intk % 2) && (y0 < safe_pow (x0,k)))) ||
00110 (((isInt || isInvInt) && (intk % 2) && (y0 > -safe_pow (-x0,k))))))) {
00111
00112
00113
00114
00115 way = (u < -0.) ? TWO_RIGHT : TWO_LEFT;
00116
00117 powertriplet pt (k);
00118
00119 *brpts = obj -> midInterval ((x0 >= 0.) ?
00120 powNewton ( x0, y0, &pt) :
00121 -powNewton (-x0, -y0, &pt), l, u, info);
00122
00123 CouNumber dy = y0 - safe_pow (*brpts >= 0 ? *brpts : - *brpts, 1. / k);
00124 x0 -= *brpts;
00125 return (brDist [0] = brDist [1] = sqrt (x0*x0 + dy*dy));
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135 if (((l < COUENNE_EPS) && (u > COUENNE_INFINITY)) ||
00136 ((u > - COUENNE_EPS) && (l < - COUENNE_INFINITY))) {
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 *brpts = 0.5 * (fabs (x0) + pow (fabs (y0), 1./k));
00150
00151 if (x0 < 0.) {
00152 *brpts = - *brpts;
00153 brDist [0] = fabs (fabs (y0) - safe_pow (fabs (x0), k));
00154 brDist [1] = *brpts - x0;
00155 } else {
00156 brDist [0] = x0 - *brpts;
00157 brDist [1] = fabs (y0 - safe_pow (x0, k));
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167 way = (x0 > *brpts) ? TWO_RIGHT : TWO_LEFT;
00168
00169 return CoinMin (brDist [0], brDist [1]);
00170
00171
00172 }
00173
00174
00175
00176 if (l < - COUENNE_INFINITY) {
00177
00178 way = TWO_RIGHT;
00179 *brpts = obj -> midInterval (x0, l, u, info);
00180
00181 return CoinMin (brDist [0] = y0 - safe_pow (*brpts, 1. / k),
00182 brDist [1] = projectSeg (x0, y0, l, safe_pow (l, k),
00183 *brpts, safe_pow (*brpts, k), -1));
00184 }
00185
00186 if (u > COUENNE_INFINITY) {
00187
00188 way = TWO_LEFT;
00189 *brpts = obj -> midInterval (x0, l, u, info);
00190
00191 return CoinMin (brDist [1] = y0 - safe_pow (*brpts, 1. / k),
00192 brDist [0] = projectSeg (x0, y0, l, safe_pow (l, k),
00193 *brpts, safe_pow (*brpts, k), +1));
00194 }
00195
00196
00197
00198 powertriplet ft (k);
00199 *brpts = obj -> getBrPoint (&ft, x0, l, u, info);
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 way = TWO_RAND;
00214
00215 x0 -= *brpts;
00216 y0 -= safe_pow (*brpts, k);
00217
00218 brDist [0] = projectSeg (x0,y0, l, safe_pow (l, k), *brpts, safe_pow (*brpts, k), 0);
00219 brDist [1] = projectSeg (x0,y0, *brpts, safe_pow (*brpts, k), u, safe_pow (u, k), 0);
00220
00221 return CoinMin (brDist [0], brDist [1]);
00222 }
00223
00224
00225
00228
00229 CouNumber exprInv::selectBranch (const CouenneObject *obj,
00230 const OsiBranchingInformation *info,
00231 expression *&var,
00232 double * &brpts,
00233 double * &brDist,
00234
00235 int &way) {
00236
00237 var = argument_;
00238
00239 int
00240 ind = argument_ -> Index (),
00241 wi = obj -> Reference () -> Index ();
00242
00243 assert ((ind >= 0) && (wi >= 0));
00244
00245 CouNumber y0 = info -> solution_ [wi],
00246 x0 = info -> solution_ [ind],
00247 l = info -> lower_ [ind],
00248 u = info -> upper_ [ind];
00249
00250 return negPowSelectBranch (obj, info, brpts, brDist, way, -1, x0, y0, l, u);
00251 }