00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <set>
00013
00014 #include "CoinHelperFunctions.hpp"
00015 #include "exprQuad.hpp"
00016
00017
00018
00019
00020
00026 struct compVar {
00027 inline bool operator () (exprVar* e0, exprVar* e1) const
00028 {return (e0 -> Index () < e1 -> Index ());}
00029 };
00030
00031
00032
00035
00036 bool exprQuad::impliedBound (int wind, CouNumber *l, CouNumber *u, t_chg_bounds *chg) {
00037
00038
00039
00040
00041
00042
00043
00044 #ifdef DEBUG
00045 printf ("################ implied bounds: [%g,%g], ", l [wind], u [wind]);
00046 print (); printf ("\n");
00047 #endif
00048
00049
00050
00051
00052 std::set <exprVar *, compVar> indexSet;
00053
00054
00055 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
00056 indexSet.insert (el -> first);
00057
00058
00059 for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00060
00061 indexSet.insert (row -> first);
00062
00063 for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col)
00064 indexSet.insert (col -> first);
00065 }
00066
00067
00068
00069
00070 CouNumber qMin, qMax;
00071
00072 int indInfLo = -1, indInfUp = -1;
00073
00074
00075 expression *qlb, *qub;
00076 exprSum::getBounds (qlb, qub);
00077 qMin = (*qlb) (); delete qlb;
00078 qMax = (*qub) (); delete qub;
00079
00080
00081 if (qMin < -COUENNE_INFINITY) indInfLo = -2;
00082 if (qMax > COUENNE_INFINITY) indInfUp = -2;
00083
00084 if ((indInfLo == -2) &&
00085 (indInfUp == -2))
00086 return false;
00087
00088 #ifdef DEBUG
00089 printf ("1st phase... inf=(%d,%d) q=[%g,%g].\n", indInfLo, indInfUp, qMin, qMax);
00090 for (std::set <int>:: iterator iter = indexSet.begin ();
00091 iter != indexSet.end (); ++iter)
00092 printf ("%4d [%+6g %+6g]\n", *iter, l [iter -> Index ()], u [iter -> Index ()]);
00093 #endif
00094
00095
00096
00097 computeQuadFiniteBound (qMin, qMax, l, u, indInfLo, indInfUp);
00098
00099
00100
00101
00102
00103 qMin += c0_;
00104 qMax += c0_;
00105
00106 if (((indInfLo == -2) && (indInfUp == -2)) ||
00107 ((indInfLo == -1) && (indInfUp == -1) &&
00108 (qMin > l [wind]) && (qMax < u [wind])))
00109 return false;
00110
00111 #ifdef DEBUG
00112 printf ("2nd phase... inf=(%d,%d) q=[%g,%g].\n", indInfLo, indInfUp, qMin, qMax);
00113 #endif
00114
00116
00117
00118
00119
00120 int
00121 minindex = (*(indexSet.begin ())) -> Index (),
00122 maxindex = (*(indexSet.rbegin ())) -> Index (),
00123 nvars = maxindex - minindex + 1;
00124
00125 CouNumber
00126 *linCoeMin = new CouNumber [nvars],
00127 *linCoeMax = new CouNumber [nvars],
00128 *qii = new CouNumber [nvars],
00129 *bCutLb = new CouNumber [nvars],
00130 *bCutUb = new CouNumber [nvars];
00131
00132
00133 CoinFillN (linCoeMin, nvars, 0.);
00134 CoinFillN (linCoeMax, nvars, 0.);
00135 CoinFillN (qii, nvars, 0.);
00136 CoinFillN (bCutLb, nvars, 0.);
00137 CoinFillN (bCutUb, nvars, 0.);
00138
00139
00140 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00141
00142
00143 int ind = el -> first -> Index ();
00144
00145 CouNumber
00146 coe = el -> second,
00147 li = l [ind],
00148 ui = u [ind];
00149
00150 ind -= minindex;
00151
00152 linCoeMin [ind] += coe;
00153 linCoeMax [ind] += coe;
00154
00155 if (coe > 0) {
00156 if (li > -COUENNE_INFINITY) bCutLb [ind] += coe * li;
00157 if (ui < COUENNE_INFINITY) bCutUb [ind] += coe * ui;
00158 } else {
00159 if (ui < COUENNE_INFINITY) bCutLb [ind] += coe * ui;
00160 if (li > -COUENNE_INFINITY) bCutUb [ind] += coe * li;
00161 }
00162 }
00163
00164 #ifdef DEBUG
00165 printf ("linear filling (%d,%d): -----------------------\n", minindex, maxindex);
00166 for (std::set <int>:: iterator iter = indexSet.begin ();
00167 iter != indexSet.end (); ++iter)
00168 printf ("%4d [%+6g %+6g] [%+6g %+6g]\n", iter -> Index (),
00169 linCoeMin [iter -> Index () - minindex], linCoeMax [iter -> Index () - minindex],
00170 bCutLb [iter -> Index () - minindex], bCutUb [iter -> Index () - minindex]);
00171 #endif
00172
00173
00174 for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00175
00176 for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00177
00178 int
00179 qi = row -> first -> Index (),
00180 qj = col -> first -> Index ();
00181
00182 CouNumber coe = col -> second,
00183 li = l [qi], lj = l [qj],
00184 ui = u [qi], uj = u [qj];
00185
00186 if (qi == qj) {
00187
00188 qi -= minindex;
00189
00190 qii [qi] = coe;
00191
00192 CouNumber
00193 maxbUb = CoinMax (fabs (li), fabs (ui)),
00194 maxbLb = (li >= 0) ? (li) : (ui <= 0) ? (ui) : 0;
00195
00196 if (maxbUb > COUENNE_INFINITY) maxbUb = 0;
00197
00198 maxbUb *= maxbUb * coe;
00199 maxbLb *= maxbLb * coe;
00200
00201 if (coe > 0) {
00202 bCutUb [qi] += maxbUb;
00203 bCutLb [qi] += maxbLb;
00204 } else {
00205 bCutUb [qi] += maxbLb;
00206 bCutLb [qi] += maxbUb;
00207 }
00208 } else {
00209
00210 coe *= 2;
00211
00212 CouNumber *b1, *b2;
00213
00214 if (coe > 0) {b1 = l; b2 = u;}
00215 else {b1 = u; b2 = l;}
00216
00217 b1 += minindex;
00218 b2 += minindex;
00219
00220 qi -= minindex;
00221 qj -= minindex;
00222
00223 linCoeMin [qi] += coe * b1 [qj];
00224 linCoeMin [qj] += coe * b1 [qi];
00225
00226 linCoeMax [qi] += coe * b2 [qj];
00227 linCoeMax [qj] += coe * b2 [qi];
00228
00229 CouNumber
00230 addLo = CoinMin (CoinMin (li*lj, ui*uj),
00231 CoinMin (ui*lj, li*uj)),
00232 addUp = CoinMax (CoinMax (li*lj, ui*uj),
00233 CoinMax (ui*lj, li*uj));
00234
00235 if (addLo < -COUENNE_INFINITY) addLo = 0;
00236 if (addUp > COUENNE_INFINITY) addUp = 0;
00237
00238 addLo *= coe;
00239 addUp *= coe;
00240
00241 if (coe > 0) {
00242 bCutLb [qi] += addLo; bCutUb [qi] += addUp;
00243 bCutLb [qj] += addLo; bCutUb [qj] += addUp;
00244 } else {
00245 bCutLb [qi] += addUp; bCutUb [qi] += addLo;
00246 bCutLb [qj] += addUp; bCutUb [qj] += addLo;
00247 }
00248 }
00249 }
00250 }
00251
00252 #ifdef DEBUG
00253 printf ("quad filling: -----------------------\n");
00254 for (std::set <int>:: iterator iter = indexSet.begin ();
00255 iter != indexSet.end (); ++iter)
00256 printf ("%4d [%+6g %+6g] [%+6g %+6g]\n", *iter,
00257 linCoeMin [iter -> Index () - minindex], linCoeMax [iter -> Index () - minindex],
00258 bCutLb [iter -> Index () - minindex], bCutUb [iter -> Index () - minindex]);
00259 #endif
00260
00261
00262
00263
00264 bool one_updated = false;
00265
00266 for (std::set <exprVar *, compVar>:: iterator iter = indexSet.begin ();
00267 iter != indexSet.end (); ++iter) {
00268
00269 bool
00270 updatedL = false,
00271 updatedU = false;
00272
00273 int ind = (*iter) -> Index (),
00274 indn = ind - minindex;
00275
00276 CouNumber
00277 al = linCoeMin [indn],
00278 au = linCoeMax [indn],
00279 q = qii [indn];
00280
00281 #ifdef DEBUG
00282 CouNumber
00283 ol = l [ind],
00284 ou = u [ind];
00285 #endif
00286
00287 if (fabs (q) < COUENNE_EPS) {
00288
00289 if ((al > 0) || (au < 0)) {
00290
00291
00292
00293
00294
00295
00296
00297
00298 CouNumber
00299 l_b = l [wind] - qMax + bCutUb [indn],
00300 u_b = u [wind] - qMin + bCutLb [indn];
00301
00302 if (al > 0) {
00303
00304 if ((indInfUp == -1) || (indInfUp == ind))
00305 updatedL = updateBound (-1, l + ind, (l_b) / ((l_b < 0) ? al : au)) || updatedL;
00306 if ((indInfLo == -1) || (indInfLo == ind))
00307 updatedU = updateBound (+1, u + ind, (u_b) / ((u_b < 0) ? au : al)) || updatedU;
00308
00309 #ifdef DEBUG
00310 if (l [ind] > ol) printf ("0. l%d: %g --> %g\n", ind, ol, l [ind]);
00311 if (u [ind] < ou) printf ("0. u%d: %g --> %g\n", ind, ou, u [ind]);
00312 #endif
00313 } else {
00314
00315 if ((indInfLo == -1) || (indInfLo == ind))
00316 updatedL = updateBound (-1, l + ind, (u_b) / ((u_b < 0) ? al : au)) || updatedL;
00317 if ((indInfUp == -1) || (indInfUp == ind))
00318 updatedU = updateBound (+1, u + ind, (l_b) / ((l_b < 0) ? au : al)) || updatedU;
00319
00320 #ifdef DEBUG
00321 if (l [ind] > ol) printf ("1. l%d: %g --> %g\n", ind, ol, l [ind]);
00322 if (u [ind] < ou) printf ("1. u%d: %g --> %g\n", ind, ou, u [ind]);
00323 #endif
00324 }
00325 }
00326
00327 } else if (q > 0) {
00328
00329
00330
00331 if ((indInfLo != -1) &&
00332 (indInfLo != ind))
00333 continue;
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 CouNumber
00350 deltaSecond = 4 * q * (qMin - bCutLb [indn] - u [wind]),
00351 deltaUp = au*au - deltaSecond,
00352 deltaLo = al*al - deltaSecond;
00353
00354
00355
00356 if ((deltaUp >= 0) &&
00357 (deltaLo >= 0)) {
00358
00359 updatedL = updateBound (-1, l + ind, (- au - sqrt (deltaUp)) / (2*q)) || updatedL;
00360 updatedU = updateBound (+1, u + ind, (- al + sqrt (deltaLo)) / (2*q)) || updatedU;
00361
00362 #ifdef DEBUG
00363 if (l [ind] > ol) printf ("2. l%d: %g --> %g\n", ind, ol, l [ind]);
00364 if (u [ind] < ou) printf ("2. u%d: %g --> %g\n", ind, ou, u [ind]);
00365 #endif
00366
00367 } else if (deltaUp >= 0) {
00368
00369 updatedL = updateBound (-1, l + ind, (- au - sqrt (deltaUp)) / (2*q)) || updatedL;
00370 updatedU = updateBound (+1, u + ind, (- au + sqrt (deltaUp)) / (2*q)) || updatedU;
00371
00372
00373 #ifdef DEBUG
00374 if (l [ind] > ol) printf ("3. l%d: %g --> %g\n", ind, ol, l [ind]);
00375 if (u [ind] < ou) printf ("3. u%d: %g --> %g\n", ind, ou, u [ind]);
00376 #endif
00377
00378 } else if (deltaLo >= 0) {
00379
00380 updatedL = updateBound (-1, l + ind, (- al - sqrt (deltaLo)) / (2*q)) || updatedL;
00381 updatedU = updateBound (+1, u + ind, (- al + sqrt (deltaLo)) / (2*q)) || updatedU;
00382
00383
00384 #ifdef DEBUG
00385 if (l [ind] > ol) printf ("4. l%d: %g --> %g\n", ind, ol, l [ind]);
00386 if (u [ind] < ou) printf ("4. u%d: %g --> %g\n", ind, ou, u [ind]);
00387 #endif
00388
00389 } else {
00390
00391 updatedL = updateBound (-1, l+ind, +1) || updatedL;
00392 updatedU = updateBound (+1, u+ind, -1) || updatedU;
00393
00394 #ifdef DEBUG
00395 printf ("5. infeasible!\n");
00396 #endif
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 } else {
00410
00411
00412
00413
00414
00415 if ((indInfUp != -1) &&
00416 (indInfUp != ind))
00417 continue;
00418
00419 CouNumber
00420 deltaSecond = 4 * q * (qMax - bCutUb [indn] - l [wind]),
00421 deltaUp = au*au - deltaSecond,
00422 deltaLo = al*al - deltaSecond;
00423
00424
00425
00426 if ((deltaUp >= 0) &&
00427 (deltaLo >= 0)) {
00428
00429 updatedL = updateBound (-1, l + ind, (al - sqrt (deltaLo)) / (-2*q)) || updatedL;
00430 updatedU = updateBound (+1, u + ind, (au + sqrt (deltaUp)) / (-2*q)) || updatedU;
00431
00432 #ifdef DEBUG
00433 if (l [ind] > ol) printf ("6. l%d: %g --> %g\n", ind, ol, l [ind]);
00434 if (u [ind] < ou) printf ("6. u%d: %g --> %g\n", ind, ou, u [ind]);
00435 #endif
00436 } else if (deltaUp >= 0) {
00437
00438 updatedL = updateBound (-1, l + ind, (au - sqrt (deltaUp)) / (-2*q)) || updatedU;
00439 updatedU = updateBound (+1, u + ind, (au + sqrt (deltaUp)) / (-2*q)) || updatedL;
00440
00441
00442 #ifdef DEBUG
00443 if (l [ind] > ol) printf ("7. l%d: %g --> %g\n", ind, ol, l [ind]);
00444 if (u [ind] < ou) printf ("7. u%d: %g --> %g\n", ind, ou, u [ind]);
00445 #endif
00446
00447 } else if (deltaLo >= 0) {
00448
00449 updatedL = updateBound (-1, l + ind, (al - sqrt (deltaLo)) / (-2*q)) || updatedL;
00450 updatedU = updateBound (+1, u + ind, (al + sqrt (deltaLo)) / (-2*q)) || updatedU;
00451
00452 #ifdef DEBUG
00453 if (l [ind] > ol) printf ("8. l%d: %g --> %g\n", ind, ol, l [ind]);
00454 if (u [ind] < ou) printf ("8. u%d: %g --> %g\n", ind, ou, u [ind]);
00455 #endif
00456
00457 } else {
00458
00459 updatedL = updateBound (-1, l+ind, +1) || updatedL;
00460 updatedU = updateBound (+1, u+ind, -1) || updatedU;
00461
00462 #ifdef DEBUG
00463 printf ("9. infeasible\n");
00464 #endif
00465 }
00466 }
00467
00468
00469
00470 if (updatedL) {
00471 one_updated = true;
00472 chg [ind].setLower(t_chg_bounds::CHANGED);
00473 if ((*iter) -> isInteger ())
00474 l [ind] = ceil (l [ind] - COUENNE_EPS);
00475 }
00476
00477 if (updatedU) {
00478 one_updated = true;
00479 chg [ind].setUpper(t_chg_bounds::CHANGED);
00480 if ((*iter) -> isInteger ())
00481 u [ind] = floor (u [ind] + COUENNE_EPS);
00482 }
00483 }
00484
00485 delete [] linCoeMin;
00486 delete [] linCoeMax;
00487 delete [] qii;
00488 delete [] bCutLb;
00489 delete [] bCutUb;
00490
00491 return one_updated;
00492 }