/home/coin/SVN-release/OS-2.4.0/Couenne/src/bound_tightening/twoImpliedBT/TwoImpliedGenCuts.cpp

Go to the documentation of this file.
00001 /* $Id: TwoImpliedGenCuts.cpp 732 2011-07-03 20:06:50Z pbelotti $
00002  *
00003  * Name:    TwoImpliedGenCuts.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: bound reduction using two inequalities from the LP relaxation
00006  * 
00007  * (C) Pietro Belotti, 2010.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include <set>
00012 #include <stdlib.h>
00013 
00014 #include "BonCbc.hpp"
00015 #include "BonBabInfos.hpp"
00016 #include "CoinHelperFunctions.hpp"
00017 #include "CoinPackedMatrix.hpp"
00018 #include "CglCutGenerator.hpp"
00019 #include "CoinTime.hpp"
00020 
00021 #include "CouenneTypes.hpp"
00022 #include "CouenneProblemElem.hpp"
00023 #include "CouenneTwoImplied.hpp"
00024 #include "CouenneExprVar.hpp"
00025 #include "CouennePrecisions.hpp"
00026 #include "CouenneProblem.hpp"
00027 #include "CouenneInfeasCut.hpp"
00028 #include "CouenneJournalist.hpp"
00029 
00030 using namespace Ipopt;
00031 
00032 // necessary to make updateBranchInfo visible
00033 namespace Couenne {
00034 
00036 void updateBranchInfo (const OsiSolverInterface &si, CouenneProblem *p, 
00037                        t_chg_bounds *chg, const CglTreeInfo &info);
00038 
00039 // do single pair of inequalities. Return < 0 if infeasible
00040 
00041 int combine (CouenneProblem *p,
00042              int n1, int n2, 
00043              const int *ind1, // indices
00044              const int *ind2, 
00045              double *sa1, // coeff (sparse array)
00046              double *sa2,
00047              const double *a1,  // coeff
00048              const double *a2, 
00049              double *clb, // variable bounds
00050              double *cub,
00051              double l1, // constraint bounds
00052              double l2,  
00053              double u1, 
00054              double u2, 
00055              bool *isInteger,
00056              int sign); // invert second constraint? -1: yes, +1: no
00057 
00059 void CouenneTwoImplied::generateCuts (const OsiSolverInterface &si, 
00060                                       OsiCuts &cs, 
00061                                       const CglTreeInfo info) const {
00062 
00063   // don't perform this is cs has been added an infeasible cut (a
00064   // result of some bound tightening procedure discovering an
00065   // infeasible node)
00066 
00067   if (isWiped (cs))
00068     return;
00069 
00070   double now = CoinCpuTime ();
00071 
00072   // a more elaborate scheme to avoid heavy use of this heavy procedure
00073 
00074   if ((depthStopSeparate_ >= 0 &&           // if -1, there is no limit on depth
00075        info.level > depthStopSeparate_)     // otherwise, check if too deep for adding these cuts
00076       ||
00077       (depthLevelling_ >= 0 &&              // chance to run this procedure
00078        info.level >= depthLevelling_ &&
00079        CoinDrand48 () > 1. / (2. + info.level - depthLevelling_)))
00080     return;
00081 
00082   if (info.level <= 0)
00083     jnlst_ -> Printf (J_ERROR, J_COUENNE, "TwoImpl-BT: "); fflush (stdout);
00084 
00085   // printf ("probexecute = %g. Level = %d, depthlevelling = %d, depthStop = %d, cond = %d\n", 
00086   //      1. / (2. + info.level - depthLevelling_),
00087   //      info.level,
00088   //      depthLevelling_, 
00089   //      depthStopSeparate_,
00090   //      (depthLevelling_ < 0 || info.level < depthLevelling_));
00091 
00092   // Update CouenneProblem's bounds using si's getCol{Low,Upp}er() and
00093   // cs's OsiColCuts
00094   problem_ -> domain () -> push (&si, &cs);
00095 
00096   static int nBadColMatWarnings = 0;
00097 
00098   std::set <std::pair <int, int> > pairs;
00099 
00106 
00109 
00110 #define USE_ROW
00111 
00112 #ifdef USE_ROW
00113 
00114   const CoinPackedMatrix *mat = si. getMatrixByRow ();
00115 
00116   int 
00117     m = mat -> getMajorDim (), // # rows
00118     n = mat -> getMinorDim (); // # cols
00119 
00120 #else
00121 
00122   const CoinPackedMatrix *mat = si. getMatrixByCol ();
00123 
00124   int 
00125     n = mat -> getMajorDim (), // # cols
00126     m = mat -> getMinorDim (); // # rows
00127 
00128 #endif
00129 
00130   const double
00131     *rlb = si.getRowLower (),
00132     *rub = si.getRowUpper ();
00133 
00134 #ifdef USE_ROW
00135 
00137 
00138   int 
00139      nnz   = mat -> getNumElements (), // # nonzeros
00140      nnzC  = 0,
00141     *sta   = new int [n+1],
00142      nCuts = cs.sizeRowCuts ();
00143 
00144   // Count nonzeros in cs
00145 
00146   for (int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
00147 
00148     const OsiRowCut        *cut     = cs. rowCutPtr (i);
00149     const CoinPackedVector &rowCoe  = cut -> row ();
00150 
00151     nnzC += rowCoe.getNumElements ();
00152   }
00153 
00154   int    *ind = new int    [nnz + nnzC];
00155   double *A   = new double [nnz + nnzC];
00156 
00158   {
00159     const double
00160       *rA   = mat -> getElements ();
00161 
00162     const int
00163       *rInd = mat -> getIndices      (),
00164       *rSta = mat -> getVectorStarts ();
00165 
00166     // copy rA, rInd, rSta into A, ind, sta
00167 
00168     CoinZeroN (sta, n+1);
00169 
00171 
00172     // pre-fill starting positions with cardinalities of each column
00173 
00174     for (int i=nnz; i--;)
00175       ++ (sta [1 + *rInd++]);
00176 
00177     // fill sta with nonzeros from cs's OsiRowCuts
00178 
00179     for (int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
00180 
00181       const OsiRowCut        *cut     = cs. rowCutPtr (i);
00182       const CoinPackedVector &rowCoe  = cut -> row ();
00183       const int              *indices = rowCoe.getIndices     ();
00184       int                     nnz     = rowCoe.getNumElements ();
00185       // Note: nnz redeclared here (no scoping problems)
00186 
00187       for (int i=nnz; i--;)
00188         ++ (sta [1 + *indices++]);
00189     }
00190 
00191     rInd -= nnz;
00192 
00194 
00195     // make sta cumulative
00196 
00197     for (int i=1; i<=n; i++)
00198       sta [i] += sta [i-1];
00199 
00200     // use space marked by sta to fill appropriate
00201     // indices/coefficients
00202 
00203     for (int i=0; i<m; i++) {
00204 
00205       // filling indices of row i
00206 
00207       int rowStart = rSta [i];
00208 
00209       for (int j = rowStart, jj = rSta [i+1] - rowStart; jj--; j++) {
00210 
00211         int &curSta = sta [rInd [j]];
00212 
00213         ind [curSta]   = i;
00214         A   [curSta++] = rA [j];
00215       }
00216       
00217       //printf ("\n");
00218     }
00219 
00220     // Add rowCuts from cs as well.
00221 
00222     for (int i=0, ii = cs. sizeRowCuts (); ii--; i++) {
00223 
00224       const OsiRowCut        *cut      = cs. rowCutPtr (i);
00225       //printf ("[cut] %4d [%g,%g]: ", m+i, cut -> lb (), cut -> ub ()); 
00226 
00227       const CoinPackedVector &rowCoe   = cut -> row ();
00228       const int              *indices  = rowCoe.getIndices  ();
00229       const double           *elements = rowCoe.getElements ();
00230       int                     nnz      = rowCoe.getNumElements ();
00231       // Note: nnz redeclared here (no scoping problems)
00232 
00233       for (int j=nnz; j--;) {
00234 
00235         //printf ("%+g x%d ", *elements, *indices); 
00236 
00237         int &curSta = sta [*indices++];
00238 
00239         ind [curSta]   = m+i;
00240         A   [curSta++] = *elements++;
00241       }
00242       //printf ("\n");
00243     }
00244 
00245     for (int i=n; --i;)
00246       sta [i] = sta [i-1];
00247 
00248     sta [0] = 0;
00249 
00250     //printf ("%d + %d = %d nonzeros\n", nnz, nnzC, nnz + nnzC);
00251   }
00252 
00253 #else
00254 
00255   const double
00256     *A   = mat -> getElements ();
00257 
00258   const int
00259     *ind = mat -> getIndices      (),
00260     *sta = mat -> getVectorStarts ();
00261 
00262 #endif
00263 
00266 
00267   bool *isInteger = new bool [n];
00268   for (int i=0, ii=n; ii--; i++)
00269     *isInteger++ = problem_ -> Var (i) -> isInteger ();
00270   isInteger -= n;
00271 
00272   // print out 
00273 
00274   // for (int i=0; i<n; i++) {
00275 
00276   //   printf ("x%04d - %5d -> %5d, %5d elements:", i, sta [i], sta [i+1], sta [i+1] - sta [i]);
00277   //   fflush (stdout);
00278 
00279   //   for (int j=0; j<sta [i+1] - sta [i]; j++) {
00280   //     printf ("(%d,%g) ", ind [sta [i] + j], A [sta [i] + j]);
00281   //     fflush (stdout);
00282   //   }
00283   //   printf ("\n");
00284   // }
00285 
00286   // For every column i, compare pairs of rows j and k with nonzero
00287   // coefficients.
00288   //
00289   // If the coefficients have the same sign and the inequalities are
00290   // both >= or both <=, skip this pair -- no tightening can come from
00291   // this pair (this doesn't mean that for another variable the
00292   // opposite may happen).
00293 
00294   double 
00295     *sa1 = new double [n], // contains dense representation of a1 i.e. lots of zeros
00296     *sa2 = new double [n]; //                                  a2
00297 
00298   CoinFillN (sa1, n, 0.);
00299   CoinFillN (sa2, n, 0.);
00300 
00301   for (int i=0; i<n; i++, sta++) {
00302 
00303     //printf ("x%d:\n", i);
00304 
00305     for   (int jj = *(sta+1) - *sta, j = *sta; jj--; j++)
00306       for (int kk = jj,              k = j+1;  kk--; k++) {
00307 
00308         if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
00309           break;
00310 
00311         register int 
00312           indj = ind [j],
00313           indk = ind [k];
00314 
00315         //printf ("  checking pair %d, %d\n", indj, indk);
00316 
00317         // should never happen, but if it does, just bail out
00318         if ((indj >= m + nCuts) || (indj < 0) ||
00319             (indk >= m + nCuts) || (indk < 0)) {
00320 
00321           if (nBadColMatWarnings++ < 1)
00322             //      jnlst_ -> Printf (J_STRONGWARNING, J_BOUNDTIGHTENING, " 
00323             printf ("\
00324   Couenne: warning, matrix by row has nonsense indices.\n\
00325   This separator will now return without (column) cuts.\n\
00326   NOTE: further such inconsistencies won't be reported.\n");
00327 
00328           delete [] sa1;
00329           delete [] sa2;
00330 
00331           delete [] sta;
00332           delete [] ind;
00333           delete [] A;
00334 
00335           delete [] isInteger;
00336 
00337           problem_ -> domain () -> pop ();
00338 
00339           totalTime_     += CoinCpuTime () - now;
00340           totalInitTime_ += CoinCpuTime () - now;
00341 
00342           return; 
00343         }
00344 
00345         double 
00346           prod = A [j] * A [k],
00347           rlbj, rubj, rlbk, rubk;
00348 
00349         if (indj>=m) {
00350           OsiRowCut *cut = cs.rowCutPtr (indj-m);
00351           rlbj = cut -> lb ();
00352           rubj = cut -> ub ();
00353         } else {
00354           rlbj = rlb [indj];
00355           rubj = rub [indj];
00356         }
00357 
00358         if (indk>=m) {
00359           OsiRowCut *cut = cs.rowCutPtr (indk-m);
00360           rlbk = cut -> lb ();
00361           rubk = cut -> ub ();
00362         } else {
00363           rlbk = rlb [indk];
00364           rubk = rub [indk];
00365         }
00366 
00367         if (prod > 0.) { // same sign -- skip unless finite lb1/ub2 OR
00368                          // finite ub1/lb2. This is to avoid a situation
00369                          // in which all coefficients in this pair
00370                          // have the same sign
00371 
00372           if (!(((rlbj > -COUENNE_INFINITY/10) && (rubk <  COUENNE_INFINITY/10)) || 
00373                 ((rubj <  COUENNE_INFINITY/10) && (rlbk > -COUENNE_INFINITY/10))))
00374 
00375             continue;
00376 
00377         } else
00378 
00379         if ((prod < 0.) && // opposite sign -- multiply second
00380                            // inequality by -1 and repeat
00381             !(((rlbj > -COUENNE_INFINITY/10) && (rlbk > -COUENNE_INFINITY/10)) || 
00382               ((rubj <  COUENNE_INFINITY/10) && (rubk <  COUENNE_INFINITY/10))))
00383 
00384           continue;
00385 
00386         pairs.insert (std::pair <int, int> (indj, indk));
00387       }
00388   }
00389 
00390   // pairs (h,k) are done. Now for each pair set new bounds, if possible ///////////////////////////
00391 
00392 #ifdef USE_ROW
00393   const CoinPackedMatrix *rowA = mat;
00394 #else
00395   const CoinPackedMatrix *rowA = si. getMatrixByRow ();
00396 #endif
00397 
00398   const double
00399     *rA  = rowA -> getElements ();
00400 
00401   // TODO: no need for copy, though we need it to compare to old problem's bounds
00402 
00403   double
00404     *clb = CoinCopyOfArray (problem_ -> Lb (), n),
00405     *cub = CoinCopyOfArray (problem_ -> Ub (), n),
00406     *oldLB = CoinCopyOfArray (problem_ -> Lb (), n),
00407     *oldUB = CoinCopyOfArray (problem_ -> Ub (), n);
00408 
00409   const int
00410     *rInd = rowA -> getIndices      (),
00411     *rSta = rowA -> getVectorStarts ();
00412 
00413   int 
00414     ntightened = 0,
00415     ntrials    = 0,
00416     nCurTightened;
00417 
00418   // info about LP problem: upper bound, dual bound
00419 
00420   Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (si.getAuxiliaryInfo ());
00421 
00422   int result = 0;
00423 
00424   // data structure for FBBT
00425 
00426   t_chg_bounds *chg_bds = new t_chg_bounds [n];
00427 
00428   // for (int i=0; i<n; i++) 
00429   //   if (problem_ -> Var (i) -> Multiplicity () <= 0) {
00430   //     chg_bds [i].setLower (t_chg_bounds::UNCHANGED);
00431   //     chg_bds [i].setUpper (t_chg_bounds::UNCHANGED);
00432   //   }
00433 
00434   // fills in chg_bds with changed bounds from previous BB node
00435 
00436   updateBranchInfo (si, problem_, chg_bds, info);
00437 
00438   // Comparing all pairs of inequalities is overkill if the comparison
00439   // has been done in a previous iteration: a pair of inequalities of
00440   // the old LP relaxation should be skipped unless some bounds have
00441   // been changed in at least one of the variables (of either
00442   // inequality). Moreover, all pairs of inequalities should be
00443   // considered where the first is from the LP relaxation and the
00444   // second is from the cuts added so far.
00445 
00446   // Repeat the scan as long as there is tightening and the bounding
00447   // box is nonempty.
00448 
00449   do {
00450 
00451     nCurTightened = 0;
00452 
00453     // scan all pairs. All are potential pairs of inequalities that
00454     // can give a better (combined) implied bound
00455 
00456     for (std::set <std::pair <int, int> >:: iterator p = pairs.begin (); p != pairs.end (); ++p) {
00457 
00458       if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
00459         break;
00460 
00461       // indices of the two inequalities
00462 
00463       int 
00464         h = p -> first,
00465         k = p -> second,
00466         n1, n2;
00467 
00468       double l1, u1, l2, u2;
00469 
00470       const double *a1, *a2;
00471 
00472       const int *ind1, *ind2;
00473 
00474       // set indices/counters depending on whether h or k are cuts or
00475       // inequalities
00476 
00477       if (h>=m) {
00478 
00479         const OsiRowCut *cut = cs.rowCutPtr (h-m);
00480         const CoinPackedVector &rowCoe  = cut -> row ();
00481 
00482         l1 = cut -> lb ();
00483         u1 = cut -> ub ();
00484         n1   = rowCoe. getNumElements ();
00485         ind1 = rowCoe. getIndices     ();
00486         a1   = rowCoe. getElements    ();
00487 
00488       } else {
00489 
00490         l1 = rlb [h];
00491         u1 = rub [h];
00492         n1 = rSta [h+1] - rSta [h];
00493         ind1 = rInd + rSta [h];
00494         a1 = rA + rSta [h];
00495       }
00496 
00498 
00499       if (k>=m) {
00500 
00501         OsiRowCut *cut = cs.rowCutPtr (k-m);
00502         const CoinPackedVector &rowCoe  = cut -> row ();
00503 
00504         l2 = cut -> lb ();
00505         u2 = cut -> ub ();
00506         n2   = rowCoe. getNumElements ();
00507         ind2 = rowCoe. getIndices     ();
00508         a2   = rowCoe. getElements    ();
00509 
00510       } else {
00511 
00512         l2 = rlb [k];
00513         u2 = rub [k];
00514         n2 = rSta [k+1] - rSta [k];
00515         ind2 = rInd + rSta [k];
00516         a2 = rA + rSta [k];
00517       }
00518 
00519       // If both indices are from the LP relaxation, only check if
00520       // there is at least one changed bound in the variables of one
00521       // (or both) of them
00522 
00523       if ((h < m) && (k < m) && !firstCall_) {
00524 
00525         bool new_bound = false;
00526 
00527         for (int i=n1; i--;) {
00528 
00529           t_chg_bounds &chg = chg_bds [ind1 [i]];
00530 
00531           if ((chg. lower () != t_chg_bounds::UNCHANGED) ||
00532               (chg. upper () != t_chg_bounds::UNCHANGED))
00533 
00534             new_bound = true;
00535         }
00536 
00537         if (!new_bound) 
00538           for (int i=n2; i--;) {
00539 
00540             t_chg_bounds &chg = chg_bds [ind2 [i]];
00541 
00542             if ((chg. lower () != t_chg_bounds::UNCHANGED) ||
00543                 (chg. upper () != t_chg_bounds::UNCHANGED))
00544 
00545               new_bound = true;
00546           }
00547 
00548         if (!new_bound) continue;
00549       }
00550 
00551       // fill in sa1 and sa2
00552 
00553       for (int i=n1; i--;) sa1 [ind1 [i]] = a1 [i];
00554       for (int i=n2; i--;) sa2 [ind2 [i]] = a2 [i];
00555 
00556       // A few cases here on the inequalities' bounds, which may
00557       // determine a change of sign in the second when combining the
00558       // two: for example, if we have -inf < ax < b and c < dx < +inf,
00559       // it makes sense to combine -inf < ax < b and -inf < - dx < -c
00560       // as the upper bound will create a finite convex combination.
00561 
00562       if ((u1 <   COUENNE_INFINITY && u2 <   COUENNE_INFINITY) ||
00563           (l1 > - COUENNE_INFINITY && l2 > - COUENNE_INFINITY))
00564 
00565         result = combine (problem_, n1, n2, ind1, ind2, sa1, sa2, a1, a2, clb, cub, l1, l2, u1, u2, isInteger, 1);
00566 
00567       if (result < 0)
00568         break;
00569 
00570       nCurTightened += result;
00571       result = 0;
00572 
00573       // fill in sa2 with opposite values
00574       for (int i=n2; i--;) 
00575         sa2 [ind2 [i]] = - a2 [i];
00576 
00577       if ((u1 <   COUENNE_INFINITY && l2 > - COUENNE_INFINITY) ||
00578           (l1 > - COUENNE_INFINITY && u2 <   COUENNE_INFINITY))
00579 
00580         // do NOT invert l2 and u2, this is done in combine
00581         result = combine (problem_, n1, n2, ind1, ind2, sa1, sa2, a1, a2, clb, cub, l1, l2, u1, u2, isInteger, -1);
00582 
00583       if (result < 0)
00584         break;
00585 
00586       nCurTightened += result;
00587 
00588       // clean sa1 and sa2
00589 
00590       for (int i=n1; i--;) sa1 [ind1 [i]] = 0.;
00591       for (int i=n2; i--;) sa2 [ind2 [i]] = 0.;
00592     }
00593 
00594     if (result < 0) 
00595       break;
00596 
00597     int objInd = problem_ -> Obj (0) -> Body () -> Index ();
00598 
00599     if (nCurTightened &&
00600         (objInd >= 0) && 
00601         babInfo && 
00602         babInfo -> babPtr ()) {
00603 
00604 #ifdef DEBUG
00605       printf ("FBBT\n");
00606 #endif
00607 
00608       CouNumber
00609         UB      = babInfo -> babPtr () -> model (). getObjValue(),
00610         LB      = babInfo -> babPtr () -> model (). getBestPossibleObjValue (),
00611         primal0 = problem_ -> Ub (objInd), 
00612         dual0   = problem_ -> Lb (objInd);
00613 
00614       // Do one round of BT
00615 
00616       if ((UB < COUENNE_INFINITY) && 
00617           (UB < primal0 - COUENNE_EPS)) { // update primal bound (MIP)
00618 
00619         problem_ -> Ub (objInd) = UB;
00620         chg_bds [objInd].setUpper (t_chg_bounds::CHANGED);
00621       }
00622 
00623       if ((LB > - COUENNE_INFINITY) && 
00624           (LB > dual0 + COUENNE_EPS)) { // update dual bound
00625         problem_ -> Lb (objInd) = LB;
00626         chg_bds [objInd].setLower (t_chg_bounds::CHANGED);
00627       }
00628 
00629       // change chg_bds for all new bounds stored in cs
00630 
00631       /*for (int i = cs. sizeColCuts (); i--;) {
00632 
00633         const CoinPackedVector
00634           &lbs = cs. colCutPtr (i) -> lbs (),
00635           &ubs = cs. colCutPtr (i) -> ubs ();
00636 
00637         // copy lbs
00638 
00639         const int *indices = lbs. getIndices ();
00640 
00641         for (int j = lbs. getNumElements (); j--; indices++)
00642           chg_bds [*indices].setLower (t_chg_bounds::CHANGED);
00643 
00644         // copy ubs
00645 
00646         indices = ubs. getIndices ();
00647 
00648         for (int j = ubs. getNumElements (); j--; indices++)
00649           chg_bds [*indices].setUpper (t_chg_bounds::CHANGED);
00650       }
00651       */
00652 
00653       if (!(problem_ -> btCore (chg_bds))) {
00654 
00655         //problem infeasible, add IIS of size 2
00656 
00657         result = -1;
00658         break;
00659 
00660       } else {
00661 
00662         // update tightened bounds from problem to clb
00663 
00664         for (int i=0; i<n; i++) {
00665 
00666           if (problem_ -> Lb (i) > clb [i] + COUENNE_EPS) clb [i] = problem_ -> Lb (i);
00667           if (problem_ -> Ub (i) < cub [i] - COUENNE_EPS) cub [i] = problem_ -> Ub (i);
00668         }
00669       }
00670     }
00671 
00672     ntightened += nCurTightened;
00673 
00674   } while (++ntrials < nMaxTrials_ && nCurTightened);
00675 
00676   totalInitTime_ += CoinCpuTime () - now;
00677 
00678   // check if bounds improved, in that case create OsiColCuts
00679 
00680   if (result >= 0 && ntightened) {
00681 
00682     // check old and new bounds
00683 
00684     int 
00685       *indLB = new int [n],
00686       *indUB = new int [n],
00687       ntightenedL = 0,
00688       ntightenedU = 0;
00689 
00690     double 
00691       *valLB = new double [n],
00692       *valUB = new double [n];
00693 
00694     for (int i=0; i<n; i++) {
00695 
00696       if (clb [i] > oldLB [i]) {
00697 
00698         if (problem_ -> bestSol () &&
00699             problem_ -> bestSol () [i] > oldLB [i] &&
00700             problem_ -> bestSol () [i] < clb   [i] - 1e-12) {
00701 
00702           jnlst_ -> Printf (J_ERROR, J_COUENNE, 
00703                             "Warning, twoImplBounds new LB cuts optimal solution: LB x_%d = %g --> %g, opt %g (diff: %g)\n",
00704                             i, oldLB [i], clb [i], problem_ -> bestSol () [i], clb [i] - problem_ -> bestSol () [i]);
00705 
00706         }
00707 
00708         //printf ("L %4d: %g -> %g\n", i, oldLB [i], clb [i]);
00709         indLB [ntightenedL]   = i;
00710         valLB [ntightenedL++] = clb [i];
00711       }
00712 
00713       if (cub [i] < oldUB [i]) {
00714 
00715         if (problem_ -> bestSol () &&
00716             problem_ -> bestSol () [i] < oldUB [i] &&
00717             problem_ -> bestSol () [i] > cub   [i] + 1e-12) {
00718 
00719           jnlst_ -> Printf (J_ERROR, J_COUENNE, 
00720                             "Warning, twoImplBounds new UB cuts optimal solution: UB x_%d = %g --> %g, opt %g (diff: %g)\n",
00721                             i, oldUB [i], cub [i], problem_ -> bestSol () [i], problem_ -> bestSol () [i] - cub [i]);
00722 
00723         }
00724 
00725         //printf ("U %4d: %g -> %g\n", i, oldUB [i], cub [i]);
00726         indUB [ntightenedU]   = i;
00727         valUB [ntightenedU++] = cub [i];
00728       }
00729     }
00730 
00731     if (ntightenedL || ntightenedU) {
00732 
00733       OsiColCut newBound;
00734 
00735       newBound.setLbs (ntightenedL, indLB, valLB);
00736       newBound.setUbs (ntightenedU, indUB, valUB);
00737 
00738       //newBound.print ();
00739 
00740       cs.insert (newBound);
00741     }
00742 
00743     delete [] indLB;
00744     delete [] indUB;
00745     delete [] valLB;
00746     delete [] valUB;
00747 
00748     ntightened = ntightenedL + ntightenedU;
00749   }
00750 
00751   else 
00752 
00753     if (result < 0)
00754       WipeMakeInfeas (cs);
00755 
00756   delete [] clb;
00757   delete [] cub;
00758   delete [] oldLB;
00759   delete [] oldUB;
00760   delete [] sa1;
00761   delete [] sa2; 
00762   delete [] chg_bds;
00763 
00764   delete [] isInteger;
00765 
00766   problem_ -> domain () -> pop ();
00767 
00768 #ifdef USE_ROW
00769   delete [] A;
00770   delete [] ind;
00771   delete [] (sta-n);
00772 #endif
00773 
00774   if (firstCall_)
00775     firstCall_ = false;
00776 
00777   totalTime_ += CoinCpuTime () - now;
00778 
00779   if (info.level <= 0)
00780     jnlst_ -> Printf (J_ERROR, J_COUENNE, "%d improved bounds\n", ntightened);
00781 }
00782 }

Generated on Thu Sep 22 03:05:55 2011 by  doxygen 1.4.7