00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneExprQuad.hpp"
00012 #include "CoinHelperFunctions.hpp"
00013
00014 using namespace Couenne;
00015
00016 void updateInf (CouNumber coe, CouNumber lb, CouNumber ub, int &indInf1, int &indInf2, int i) {
00017
00018 if (coe > 0) {
00019 if (lb < 0) indInf1 = (indInf1 == -1) ? i : -2;
00020 if (ub > 0) indInf2 = (indInf2 == -1) ? i : -2;
00021 } else {
00022 if (lb < 0) indInf2 = (indInf2 == -1) ? i : -2;
00023 if (ub > 0) indInf1 = (indInf1 == -1) ? i : -2;
00024 }
00025 }
00026
00027
00028
00029
00030 void exprQuad::computeQuadFiniteBound (CouNumber &qMin,
00031 CouNumber &qMax,
00032 CouNumber *l,
00033 CouNumber *u,
00034 int &indInfLo,
00035 int &indInfUp) {
00036
00037
00038
00039 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00040
00041 int ind = el -> first -> Index ();
00042
00043 CouNumber
00044 coe = el -> second,
00045 li = l [ind],
00046 ui = u [ind];
00047
00048 if (coe < 0) {
00049
00050 if (indInfLo > -2) {
00051 if (ui > COUENNE_INFINITY) indInfLo = (indInfLo == -1) ? ind : -2;
00052 else qMin += coe * ui;
00053 }
00054
00055 if (indInfUp > -2) {
00056 if (li < -COUENNE_INFINITY) indInfUp = (indInfUp == -1) ? ind : -2;
00057 else qMax += coe * li;
00058 }
00059 } else {
00060
00061 if (indInfLo > -2) {
00062 if (li < -COUENNE_INFINITY) indInfLo = (indInfLo == -1) ? ind : -2;
00063 else qMin += coe * li;
00064 }
00065
00066 if (indInfUp > -2) {
00067 if (ui > COUENNE_INFINITY) indInfUp = (indInfUp == -1) ? ind : -2;
00068 else qMax += coe * ui;
00069 }
00070 }
00071 }
00072
00073
00074
00075 for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00076
00077 int i = row -> first -> Index ();
00078
00079 for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00080
00081 int j = col -> first -> Index ();
00082
00083 CouNumber
00084 coe = col -> second,
00085 lbi = l [i],
00086 ubi = u [i];
00087
00088 if (i==j) {
00089
00090 CouNumber
00091 tmin = (ubi <= 0) ? (ubi * ubi) : (lbi >= 0) ? (lbi * lbi) : 0,
00092 tmax = CoinMax (lbi*lbi, ubi*ubi);
00093
00094 if (coe < 0) {
00095 qMax += coe * tmin;
00096 if (indInfLo > -2) {
00097 if (tmax > COUENNE_INFINITY) indInfLo = (indInfLo == -1) ? i : -2;
00098 else qMin += coe * tmax;
00099 }
00100 } else {
00101 qMin += coe * tmin;
00102 if (indInfUp > -2) {
00103 if (tmax > COUENNE_INFINITY) indInfUp = (indInfUp == -1) ? i : -2;
00104 else qMax += coe * tmax;
00105 }
00106 }
00107 } else {
00108
00109 CouNumber
00110 lbj = l [j],
00111 ubj = u [j];
00112
00113 coe *= 2;
00114
00115
00116
00117 if (lbi < -COUENNE_INFINITY) updateInf (coe, lbj, ubj, indInfUp, indInfLo, i);
00118 if (lbj < -COUENNE_INFINITY) updateInf (coe, lbi, ubi, indInfUp, indInfLo, j);
00119
00120 if (ubi > COUENNE_INFINITY) updateInf (coe, lbj, ubj, indInfLo, indInfUp, i);
00121 if (ubj > COUENNE_INFINITY) updateInf (coe, lbi, ubi, indInfLo, indInfUp, j);
00122
00123 CouNumber term,
00124 b1 = coe * lbi * lbj,
00125 b2 = coe * lbi * ubj,
00126 b3 = coe * ubi * lbj,
00127 b4 = coe * ubi * ubj;
00128
00129 if ((term = CoinMin (CoinMin (b1, b2), CoinMin (b3, b4))) > -COUENNE_INFINITY) qMin += term;
00130 if ((term = CoinMax (CoinMax (b1, b2), CoinMax (b3, b4))) < COUENNE_INFINITY) qMax += term;
00131 }
00132 }
00133 }
00134 }