00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouennePrecisions.hpp"
00012 #include "CouenneProblem.hpp"
00013 #include "CouenneCutGenerator.hpp"
00014 #include "exprVar.hpp"
00015
00016
00017
00018
00019
00020 template <class T>
00021 int CouenneSolverInterface<T>::tightenBoundsCLP (int lightweight) {
00022
00023
00024
00025 int
00026 numberRows = T::getNumRows(),
00027 numberColumns = T::getNumCols(),
00028 iRow, iColumn;
00029
00030 const double * columnUpper = T::getColUpper();
00031 const double * columnLower = T::getColLower();
00032 const double * rowUpper = T::getRowUpper();
00033 const double * rowLower = T::getRowLower();
00034
00035
00036 const double * element = T::getMatrixByCol()->getElements();
00037 const int * row = T::getMatrixByCol()->getIndices();
00038 const CoinBigIndex * columnStart = T::getMatrixByCol()->getVectorStarts();
00039 const int * columnLength = T::getMatrixByCol()->getVectorLengths();
00040 const double *objective = T::getObjCoefficients() ;
00041
00042 double direction = T::getObjSense();
00043 double * down = new double [numberRows];
00044
00045 if (lightweight)
00046 return tightenBoundsCLP_Light (lightweight);
00047
00048
00049
00050 double * up = new double [numberRows];
00051 double * sum = new double [numberRows];
00052 int * type = new int [numberRows];
00053 CoinZeroN(down,numberRows);
00054 CoinZeroN(up,numberRows);
00055 CoinZeroN(sum,numberRows);
00056 CoinZeroN(type,numberRows);
00057 double infinity = T::getInfinity();
00058
00059 for (iColumn=0;iColumn<numberColumns;iColumn++) {
00060 CoinBigIndex start = columnStart[iColumn];
00061 CoinBigIndex end = start + columnLength[iColumn];
00062 double lower = columnLower[iColumn];
00063 double upper = columnUpper[iColumn];
00064 if (lower==upper) {
00065 for (CoinBigIndex j=start;j<end;j++) {
00066 int iRow = row[j];
00067 double value = element[j];
00068 sum[iRow]+=2.0*fabs(value*lower);
00069 if ((type[iRow]&1)==0)
00070 down[iRow] += value*lower;
00071 if ((type[iRow]&2)==0)
00072 up[iRow] += value*lower;
00073 }
00074 } else {
00075 for (CoinBigIndex j=start;j<end;j++) {
00076 int iRow = row[j];
00077 double value = element[j];
00078 if (value>0.0) {
00079 if ((type[iRow]&1)==0) {
00080 if (lower!=-infinity) {
00081 down[iRow] += value*lower;
00082 sum[iRow]+=fabs(value*lower);
00083 } else {
00084 type[iRow] |= 1;
00085 }
00086 }
00087 if ((type[iRow]&2)==0) {
00088 if (upper!=infinity) {
00089 up[iRow] += value*upper;
00090 sum[iRow]+=fabs(value*upper);
00091 } else {
00092 type[iRow] |= 2;
00093 }
00094 }
00095 } else {
00096 if ((type[iRow]&1)==0) {
00097 if (upper!=infinity) {
00098 down[iRow] += value*upper;
00099 sum[iRow]+=fabs(value*upper);
00100 } else {
00101 type[iRow] |= 1;
00102 }
00103 }
00104 if ((type[iRow]&2)==0) {
00105 if (lower!=-infinity) {
00106 up[iRow] += value*lower;
00107 sum[iRow]+=fabs(value*lower);
00108 } else {
00109 type[iRow] |= 2;
00110 }
00111 }
00112 }
00113 }
00114 }
00115 }
00116
00117 int nTightened = 0;
00118 double tolerance = 1.0e-6;
00119
00120 for (iRow=0;iRow<numberRows;iRow++) {
00121 if ((type[iRow]&1)!=0)
00122 down[iRow]=-infinity;
00123 if (down[iRow]>rowUpper[iRow]) {
00124 if (down[iRow]>rowUpper[iRow]+tolerance+1.0e-8*sum[iRow]) {
00125
00126 #ifdef COIN_DEVELOP
00127 printf("infeasible on row %d\n",iRow);
00128 #endif
00129 nTightened=-1;
00130 break;
00131 } else {
00132 down[iRow]=rowUpper[iRow];
00133 }
00134 }
00135 if ((type[iRow]&2)!=0)
00136 up[iRow]=infinity;
00137 if (up[iRow]<rowLower[iRow]) {
00138 if (up[iRow]<rowLower[iRow]-tolerance-1.0e-8*sum[iRow]) {
00139
00140 #ifdef COIN_DEVELOP
00141 printf("infeasible on row %d\n",iRow);
00142 #endif
00143 nTightened=-1;
00144 break;
00145 } else {
00146 up[iRow]=rowLower[iRow];
00147 }
00148 }
00149 }
00150
00151 if (nTightened)
00152 numberColumns = 0;
00153
00154 for (iColumn=0;iColumn<numberColumns;iColumn++) {
00155 double lower = columnLower[iColumn];
00156 double upper = columnUpper[iColumn];
00157 double gap = upper-lower;
00158
00159 if (!gap)
00160 continue;
00161
00162 int canGo=0;
00163
00164 CoinBigIndex
00165 start = columnStart [iColumn],
00166 end = start + columnLength [iColumn];
00167
00168 if (lower < -1.0e8 && upper > 1.0e8)
00169 continue;
00170
00171
00172
00173
00174
00175
00176 std::vector <exprVar *> &vars = cutgen_ -> Problem () -> Variables ();
00177
00178 {
00179 if (vars [iColumn] -> isInteger ()) {
00180
00181 if (lower < ceil (lower - COUENNE_EPS) - COUENNE_EPS) {
00182 #ifdef COIN_DEVELOP
00183 printf("increasing lower bound on %d from %e to %e\n",iColumn,
00184 lower,ceil(lower - COUENNE_EPS));
00185 #endif
00186 lower=ceil(lower - COUENNE_EPS);
00187 gap=upper-lower;
00188 T::setColLower(iColumn,lower);
00189 }
00190
00191 if (upper > floor(upper + COUENNE_EPS) + COUENNE_EPS) {
00192 #ifdef COIN_DEVELOP
00193 printf("decreasing upper bound on %d from %e to %e\n",iColumn,
00194 upper,floor(upper + COUENNE_EPS));
00195 #endif
00196 upper=floor(upper + COUENNE_EPS);
00197 gap=upper-lower;
00198 T::setColUpper(iColumn,upper);
00199 }
00200 }
00201
00202 double newLower=lower;
00203 double newUpper=upper;
00204
00205 for (CoinBigIndex j=start;j<end;j++) {
00206 int iRow = row[j];
00207 double value = element[j];
00208 if (value>0.0) {
00209 if ((type[iRow]&1)==0) {
00210
00211 if (down[iRow] + value*gap > rowUpper[iRow]+tolerance) {
00212 double newGap = (rowUpper[iRow]-down[iRow])/value;
00213
00214 newGap += 1.0e-10*sum[iRow];
00215 if (vars [iColumn] -> isInteger ())
00216 newGap = floor(newGap);
00217 if (lower+newGap<newUpper)
00218 newUpper=lower+newGap;
00219 }
00220 }
00221 if (down[iRow]<rowLower[iRow])
00222 canGo |=1;
00223 if ((type[iRow]&2)==0) {
00224
00225 if (up[iRow] - value*gap < rowLower[iRow]-tolerance) {
00226 double newGap = (up[iRow]-rowLower[iRow])/value;
00227
00228 newGap += 1.0e-10*sum[iRow];
00229 if (vars [iColumn] -> isInteger ())
00230 newGap = floor(newGap);
00231 if (upper-newGap>newLower)
00232 newLower=upper-newGap;
00233 }
00234 }
00235 if (up[iRow]>rowUpper[iRow])
00236 canGo |=2;
00237 } else {
00238 if ((type[iRow]&1)==0) {
00239
00240 if (down[iRow] - value*gap > rowUpper[iRow]+tolerance) {
00241 double newGap = -(rowUpper[iRow]-down[iRow])/value;
00242
00243 newGap += 1.0e-10*sum[iRow];
00244 if (vars [iColumn] -> isInteger ())
00245 newGap = floor(newGap);
00246 if (upper-newGap>newLower)
00247 newLower=upper-newGap;
00248 }
00249 }
00250 if (up[iRow]>rowUpper[iRow])
00251 canGo |=1;
00252 if ((type[iRow]&2)==0) {
00253
00254 if (up[iRow] + value*gap < rowLower[iRow]-tolerance) {
00255 double newGap = -(up[iRow]-rowLower[iRow])/value;
00256
00257 newGap += 1.0e-10*sum[iRow];
00258 if (vars [iColumn] -> isInteger ())
00259 newGap = floor(newGap);
00260 if (lower+newGap<newUpper)
00261 newUpper=lower+newGap;
00262 }
00263 }
00264 if (down[iRow]<rowLower[iRow])
00265 canGo |=2;
00266 }
00267 }
00268
00269 if (newUpper<upper || newLower>lower) {
00270 nTightened++;
00271 if (newLower>newUpper) {
00272
00273 #if COIN_DEVELOP>1
00274 printf("infeasible on column %d\n",iColumn);
00275 #endif
00276 nTightened=-1;
00277 break;
00278 } else {
00279 T::setColLower(iColumn,newLower);
00280 T::setColUpper(iColumn,newUpper);
00281 }
00282 for (CoinBigIndex j=start;j<end;j++) {
00283 int iRow = row[j];
00284 double value = element[j];
00285 if (value>0.0) {
00286 if ((type[iRow]&1)==0) down [iRow] += value*(newLower-lower);
00287 if ((type[iRow]&2)==0) up [iRow] += value*(newUpper-upper);
00288 } else {
00289 if ((type[iRow]&1)==0) down [iRow] += value*(newUpper-upper);
00290 if ((type[iRow]&2)==0) up [iRow] += value*(newLower-lower);
00291 }
00292 }
00293 } else {
00294
00295 if (canGo!=3) {
00296
00297 double objValue = direction*objective[iColumn];
00298
00299 if (objValue>=0.0&&(canGo&1)==0) {
00300 #if COIN_DEVELOP>2
00301 printf("dual fix down on column %d\n",iColumn);
00302 #endif
00303 nTightened++;
00304 T::setColUpper(iColumn,lower);
00305 } else if (objValue<=0.0 && (canGo&2)==0) {
00306 #if COIN_DEVELOP>2
00307 printf("dual fix up on column %d\n",iColumn);
00308 #endif
00309 nTightened++;
00310 T::setColLower(iColumn,upper);
00311 }
00312 }
00313 }
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 }
00360
00361 delete [] type;
00362 delete [] down;
00363 delete [] up;
00364 delete [] sum;
00365
00366 return nTightened;
00367 }
00368