00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CoinHelperFunctions.hpp"
00012 #include "OsiClpSolverInterface.hpp"
00013 #include "OsiCuts.hpp"
00014 #include "CoinTime.hpp"
00015
00016 #include "CouenneFixPoint.hpp"
00017
00018 #include "CouenneProblem.hpp"
00019 #include "CouennePrecisions.hpp"
00020 #include "CouenneExprVar.hpp"
00021 #include "CouenneInfeasCut.hpp"
00022
00023 using namespace Ipopt;
00024 using namespace Couenne;
00025
00027
00028 void CouenneFixPoint::generateCuts (const OsiSolverInterface &si,
00029 OsiCuts &cs,
00030 const CglTreeInfo treeInfo)
00031 #if CGL_VERSION_MAJOR == 0 && CGL_VERSION_MINOR <= 57
00032 const
00033 #endif
00034 {
00035
00044
00045 if (firstCall_)
00046 firstCall_ = false;
00047 else
00048 if (!(problem_ -> fbbtReachedIterLimit ()))
00049 return;
00050
00051 if (isWiped (cs))
00052 return;
00053
00054
00055
00056 if (treeInfo.inTree &&
00057 treeInfo.level > 0 &&
00058 treeInfo.pass > 1)
00059 return;
00060
00061 double startTime = CoinCpuTime ();
00062
00063 int nInitTightened = nTightened_;
00064
00065 if (treeInfo.inTree &&
00066 treeInfo.level <= 0) {
00067
00068 problem_ -> Jnlst () -> Printf (J_ERROR, J_COUENNE, "Fixed Point FBBT: ");
00069 fflush (stdout);
00070 }
00071
00072
00073
00074 double now = CoinCpuTime ();
00075
00076 problem_ -> domain () -> push (&si, &cs);
00077
00078 double
00079 *oldLB = CoinCopyOfArray (problem_ -> Lb (), problem_ -> nVars ()),
00080 *oldUB = CoinCopyOfArray (problem_ -> Ub (), problem_ -> nVars ());
00081
00082 perfIndicator_. setOldBounds (problem_ -> Lb (), problem_ -> Ub ());
00083
00102
00103 OsiSolverInterface *fplp = NULL;
00104
00105 if (true) {
00106
00107
00108 fplp = new OsiClpSolverInterface;
00109 }
00110
00127
00129
00130 const CoinPackedMatrix *A = si. getMatrixByRow ();
00131
00132 const int
00133 n = si. getNumCols (),
00134 m = si. getNumRows (),
00135 nCuts = cs.sizeRowCuts (),
00136 *ind = A -> getIndices ();
00137
00138 const double
00139 *lb = problem_ -> Lb (),
00140 *ub = problem_ -> Ub (),
00141 *rlb = si. getRowLower (),
00142 *rub = si. getRowUpper (),
00143 *coe = A -> getElements ();
00144
00145 if (problem_ -> Jnlst () -> ProduceOutput (J_ERROR, J_BOUNDTIGHTENING))
00146 for (int i=0; i<n; i++)
00147 printf ("----------- x_%d in [%g,%g]\n", i, lb [i], ub [i]);
00148
00149
00150 fplp -> messageHandler () -> setLogLevel (0);
00151
00152
00153 for (int i=0; i<n; i++) {
00154 bool isActive = problem_ -> Var (i) -> Multiplicity () > 0;
00155 fplp -> addCol (0, NULL, NULL, lb [i], ub [i], isActive ? -1. : 0.);
00156 }
00157
00158 for (int i=0; i<n; i++) {
00159 bool isActive = problem_ -> Var (i) -> Multiplicity () > 0;
00160 fplp -> addCol (0, NULL, NULL, lb [i], ub [i], isActive ? +1. : 0.);
00161 }
00162
00163 if (extendedModel_) {
00164
00165 for (int j=0; j<m; j++) fplp -> addCol (0, NULL, NULL, rlb [j], COIN_DBL_MAX, 0.);
00166 for (int j=0; j<m; j++) fplp -> addCol (0, NULL, NULL, -COIN_DBL_MAX, rub [j], 0.);
00167 }
00168
00169
00170
00171 for (int j=0; j<m; j++) {
00172
00173 int nEl = A -> getVectorSize (j);
00174
00175 if (!nEl)
00176 continue;
00177
00178 if (problem_ -> Jnlst () -> ProduceOutput (J_ERROR, J_BOUNDTIGHTENING)) {
00179
00180 printf ("row %4d, %4d elements: ", j, nEl);
00181
00182 for (int i=0; i<nEl; i++) {
00183 printf ("%+g x%d ", coe [i], ind [i]);
00184 fflush (stdout);
00185 }
00186
00187 printf ("\n");
00188 }
00189
00190
00191
00192 if (extendedModel_ || rlb [j] > -COUENNE_INFINITY)
00193 for (int i=0; i<nEl; i++)
00194 createRow (-1, ind [i], n, fplp, ind, coe, rlb [j], nEl, extendedModel_, j, m + nCuts);
00195
00196 if (extendedModel_ || rub [j] < COUENNE_INFINITY)
00197 for (int i=0; i<nEl; i++)
00198 createRow (+1, ind [i], n, fplp, ind, coe, rub [j], nEl, extendedModel_, j, m + nCuts);
00199
00200
00201
00202 if (extendedModel_) {
00203 createRow (-1, 2*n + j, n, fplp, ind, coe, rlb [j], nEl, extendedModel_, j, m + nCuts);
00204 createRow (+1, 2*n + m + j, n, fplp, ind, coe, rub [j], nEl, extendedModel_, j, m + nCuts);
00205 }
00206
00207 ind += nEl;
00208 coe += nEl;
00209 }
00210
00211
00212
00213 for (int j = 0, jj = nCuts; jj--; j++) {
00214
00215
00216
00217 OsiRowCut *cut = cs.rowCutPtr (j);
00218
00219 const CoinPackedVector &row = cut -> row ();
00220
00221 const int
00222 nEl = row.getNumElements (),
00223 *ind = row.getIndices ();
00224
00225 const double *coe = row.getElements ();
00226
00227 if (extendedModel_) {
00228 fplp -> addCol (0, NULL, NULL, cut -> lb (), COIN_DBL_MAX, 0.);
00229 fplp -> addCol (0, NULL, NULL, -COIN_DBL_MAX, cut -> ub (), 0.);
00230 }
00231
00232 if (extendedModel_ || cut -> lb () > -COUENNE_INFINITY)
00233 for (int i=0; i<nEl; i++)
00234 createRow (-1, ind [i], n, fplp, ind, coe, cut -> lb (), nEl, extendedModel_, m + j, m + nCuts);
00235
00236 if (extendedModel_ || cut -> ub () < COUENNE_INFINITY)
00237 for (int i=0; i<nEl; i++)
00238 createRow (+1, ind [i], n, fplp, ind, coe, cut -> ub (), nEl, extendedModel_, m + j, m + nCuts);
00239
00240
00241
00242 if (extendedModel_) {
00243 createRow (-1, 2*n + j, n, fplp, ind, coe, cut -> lb (), nEl, extendedModel_, m + j, m + nCuts);
00244 createRow (+1, 2*n + m + nCuts + j, n, fplp, ind, coe, cut -> ub (), nEl, extendedModel_, m + j, m + nCuts);
00245 }
00246
00247 ind += nEl;
00248 coe += nEl;
00249 }
00250
00251
00252
00253 if (extendedModel_)
00254
00255 for (int j=0; j<m; j++) {
00256
00257 int ind [2] = {2*n + j, 2*n + m + j};
00258 double coe [2] = {1., -1.};
00259
00260 CoinPackedVector row (2, ind, coe);
00261 fplp -> addRow (row, -COIN_DBL_MAX, 0.);
00262 }
00263
00266
00267 fplp -> setObjSense (-1.);
00268
00269
00270
00271
00272
00273 fplp -> setIntParam (OsiMaxNumIteration, CoinMax (100, fplp -> getNumRows ()));
00274
00275
00276
00277
00278
00279
00280
00281 double one_norm = 0;
00282 bool one_inf_bd = false;
00283
00284 for (int i=0; i<n; ++i) {
00285
00286 if ((oldLB [i] < -COUENNE_INFINITY) ||
00287 (oldUB [i] > COUENNE_INFINITY)) {
00288 one_inf_bd = true;
00289 break;
00290 }
00291
00292 one_norm += (oldUB [i] - oldLB [i]);
00293 }
00294
00295 #define APPROX_USELESS .99
00296
00297
00298 if (!one_inf_bd)
00299 fplp -> setDblParam (OsiPrimalObjectiveLimit, APPROX_USELESS * one_norm);
00300
00301 fplp -> initialSolve ();
00302
00303
00304
00305
00306
00307
00308
00309 if (fplp -> isProvenDualInfeasible () &&
00310 !(fplp -> isProvenPrimalInfeasible ())) {
00311
00312 problem_ -> Jnlst () -> Printf (J_WARNING, J_BOUNDTIGHTENING, "FPLP unbounded: extra BT\n");
00313
00314 if (!(problem_ -> doFBBT ()) &&
00315 !(problem_ -> btCore (NULL)))
00316 WipeMakeInfeas (cs);
00317
00318
00319
00320 for (int i=0; i<n; i++) {
00321 fplp -> setColLower ( i, problem_ -> Lb (i));
00322 fplp -> setColLower (n+i, problem_ -> Lb (i));
00323 fplp -> setColUpper ( i, problem_ -> Ub (i));
00324 fplp -> setColUpper (n+i, problem_ -> Ub (i));
00325 }
00326
00327
00328
00329 fplp -> resolve ();
00330 }
00331
00332 const double
00333 *newLB = fplp -> getColSolution (),
00334 *newUB = newLB + n;
00335
00336 double infeasBounds [] = {1,-1};
00337
00338
00339
00340 if (fplp -> isProvenOptimal ()) {
00341
00342
00343
00344
00345
00346 int
00347 *indLB = new int [n],
00348 *indUB = new int [n],
00349 ntightenedL = 0,
00350 ntightenedU = 0;
00351
00352 double
00353 *valLB = new double [n],
00354 *valUB = new double [n];
00355
00356 for (int i=0; i<n; i++) {
00357
00358 if (problem_ -> Jnlst () -> ProduceOutput (J_ERROR, J_BOUNDTIGHTENING))
00359 printf ("x%d: [%g,%g] --> [%g,%g]\n", i,
00360 oldLB [i], oldUB [i],
00361 newLB [i], newUB [i]);
00362
00363 if (newLB [i] > oldLB [i] + COUENNE_EPS) {
00364
00365 indLB [ntightenedL] = i;
00366 valLB [ntightenedL++] = newLB [i];
00367
00368 ++nTightened_;
00369 }
00370
00371 if (newUB [i] < oldUB [i] - COUENNE_EPS) {
00372
00373 indUB [ntightenedU] = i;
00374 valUB [ntightenedU++] = newUB [i];
00375
00376 ++nTightened_;
00377 }
00378 }
00379
00380 if (ntightenedL || ntightenedU) {
00381
00382 OsiColCut newBound;
00383
00384 newBound.setLbs (ntightenedL, indLB, valLB);
00385 newBound.setUbs (ntightenedU, indUB, valUB);
00386
00387 cs.insert (newBound);
00388 }
00389
00390 delete [] indLB;
00391 delete [] indUB;
00392 delete [] valLB;
00393 delete [] valUB;
00394
00395 CPUtime_ += CoinCpuTime () - now;
00396
00397 if (treeInfo.inTree &&
00398 treeInfo.level <= 0)
00399 problem_ -> Jnlst () -> Printf (J_ERROR, J_COUENNE, "%d bounds tightened (%g seconds)\n",
00400 nTightened_ - nInitTightened, CoinCpuTime () - now);
00401
00402 } else if (fplp -> isProvenPrimalInfeasible ()) {
00403
00404 if (treeInfo.inTree &&
00405 treeInfo.level <= 0)
00406 problem_ -> Jnlst () -> Printf (J_ERROR, J_COUENNE, " FPLP infeasible.\n");
00407
00408 WipeMakeInfeas (cs);
00409
00410 newLB = infeasBounds;
00411 newUB = infeasBounds + 1;
00412
00413 } else {
00414
00415
00416
00417
00418 if (treeInfo.inTree &&
00419 treeInfo.level <= 0)
00420 problem_ -> Jnlst () -> Printf (J_ERROR, J_COUENNE, " FPLP inconclusive, won't be used.\n");
00421
00422 newLB = oldLB;
00423 newUB = oldUB;
00424 }
00425
00426
00427
00428 delete fplp;
00429
00430 perfIndicator_. update (newLB, newUB, treeInfo.level);
00431 perfIndicator_. addToTimer (CoinCpuTime () - startTime);
00432
00433 problem_ -> domain () -> pop ();
00434
00435 delete [] oldLB;
00436 delete [] oldUB;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 void CouenneFixPoint::createRow (int sign,
00457 int indexVar,
00458 int nVars,
00459 OsiSolverInterface *p,
00460 const int *indices,
00461 const double *coe,
00462 const double rhs,
00463 const int nEl,
00464 bool extMod,
00465 int indCon,
00466 int nCon) const {
00467
00569
00570
00571 if (problem_ -> Jnlst () -> ProduceOutput (J_ERROR, J_BOUNDTIGHTENING)) {
00572
00573 printf ("creating constraint from: ");
00574
00575 for (int i=0; i<nEl; i++)
00576 printf ("%+g x%d ", coe [i], indices [i]);
00577
00578 printf ("%c= %g for variable index %d: ", sign > 0 ? '<' : '>', rhs, indexVar);
00579 }
00580
00581 int nTerms = nEl;
00582
00583 if (extMod)
00584 nTerms++;
00585
00586 int *iInd = new int [nTerms];
00587 double *elem = new double [nTerms];
00588
00589
00590
00591 CoinCopyN (coe, nEl, elem);
00592
00593 if (extMod) {
00594 elem [nEl] = -1.;
00595 iInd [nEl] = 2*nVars + indCon + ((sign > 0) ? nCon : 0);
00596 }
00597
00598
00599
00600 for (int k=0; k<nEl; k++) {
00601
00602 int curInd = indices [k];
00603
00604 iInd [k] = curInd;
00605
00606
00607
00608 if (curInd == indexVar) {
00609 if (((sign > 0) && (coe [k] > 0.)) ||
00610 ((sign < 0) && (coe [k] < 0.)))
00611
00612 iInd [k] += nVars;
00613
00614 } else if (((coe [k] > 0.) && (sign < 0)) ||
00615 ((coe [k] < 0.) && (sign > 0)))
00616
00617 iInd [k] += nVars;
00618 }
00619
00620 CoinPackedVector vec (nTerms, iInd, elem);
00621
00622 double
00623 lb = sign > 0 ? -COIN_DBL_MAX : extMod ? 0. : rhs,
00624 ub = sign < 0 ? +COIN_DBL_MAX : extMod ? 0. : rhs;
00625
00626 p -> addRow (vec, lb, ub);
00627
00628
00629
00630 if (problem_ -> Jnlst () -> ProduceOutput (J_ERROR, J_BOUNDTIGHTENING)) {
00631
00632 for (int i=0; i<nEl; i++)
00633 printf ("%+g x%d ", elem [i], iInd [i]);
00634
00635 printf ("in [%g,%g]\n", lb, ub);
00636 }
00637
00638
00639
00640
00641
00642 delete [] iInd;
00643 delete [] elem;
00644 }