/home/coin/SVN-release/OS-2.4.0/Couenne/src/convex/generateCuts.cpp

Go to the documentation of this file.
00001 /* $Id: generateCuts.cpp 736 2011-07-04 02:27:17Z pbelotti $
00002  *
00003  * Name:    generateCuts.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: the generateCuts() method of the convexification class CouenneCutGenerator
00006  *
00007  * (C) Carnegie-Mellon University, 2006-11.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "BonCbc.hpp"
00012 #include "BonBabInfos.hpp"
00013 #include "CglCutGenerator.hpp"
00014 
00015 #include "CouenneCutGenerator.hpp"
00016 #include "CouenneProblem.hpp"
00017 #include "CouenneProblemElem.hpp"
00018 #include "CouenneExprVar.hpp"
00019 #include "CouenneInfeasCut.hpp"
00020 
00021 #include "CouenneRecordBestSol.hpp"
00022 
00023 #ifdef COIN_HAS_NTY
00024 #include "Nauty.h"
00025 #endif
00026 
00027 using namespace Ipopt;
00028 
00029 namespace Couenne {
00030 
00031 #define Couenne_large_bound2 9.99e12
00032 
00033 // checks bad cuts against known optimum
00034 bool isOptimumCut (const CouNumber *opt, OsiCuts &cs, CouenneProblem *p);
00035 
00036 // set and lift bound for auxiliary variable associated with objective
00037 // function
00038 void fictitiousBound (OsiCuts &cs,
00039                       CouenneProblem *p, 
00040                       bool action) {     // true before convexifying, false afterwards
00041 
00042   // fictitious bound for initial unbounded lp relaxations
00043   const CouNumber large_tol = (Couenne_large_bound2 / 1e6);
00044 
00045   // set trivial dual bound to objective function, if there is none
00046 
00047   int ind_obj = p -> Obj (0) -> Body () -> Index ();
00048 
00049   if (ind_obj < 0) return;
00050 
00051   // we have a single variable objective function
00052 
00053   //int sense = -1; //(p -> Obj (0) -> Sense () == MINIMIZE) ? -1 : 1;
00054 
00055   if (action)
00056     //if (sense<0) 
00057       {if (p -> Lb (ind_obj) < - Couenne_large_bound2) p -> Lb (ind_obj) = - Couenne_large_bound2;}
00058   //else         {if (p -> Ub (ind_obj) >   large_bound2) p -> Ub (ind_obj) =   large_bound2;}
00059   else
00060     //if (sense>0) {if (fabs (p->Ub(ind_obj)-large_bound2)<large_tol) p->Ub(ind_obj)=COUENNE_INFINITY;}
00061     //else         
00062       {if (fabs (p->Lb(ind_obj)+Couenne_large_bound2)<large_tol) p->Lb(ind_obj) =-COUENNE_INFINITY;}
00063 }
00064 
00065 
00066 // translate changed bound sparse array into a dense one
00067 void sparse2dense (int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged) {
00068 
00069   // convert sparse chg_bds in something handier
00070 
00071   changed  = (int *) realloc (changed, ncols * sizeof (int));
00072   nchanged = 0;
00073 
00074   for (register int i=ncols, j=0; i--; j++, chg_bds++)
00075     if (chg_bds -> lower() != t_chg_bounds::UNCHANGED ||
00076         chg_bds -> upper() != t_chg_bounds::UNCHANGED ) {
00077       *changed++ = j;
00078       nchanged++;
00079     }
00080 
00081   changed -= nchanged;
00082   //changed = (int *) realloc (changed, nchanged * sizeof (int));
00083 }
00084 
00085 
00087 void updateBranchInfo (const OsiSolverInterface &si, CouenneProblem *p, 
00088                        t_chg_bounds *chg, const CglTreeInfo &info);
00089 
00091 
00092 void CouenneCutGenerator::generateCuts (const OsiSolverInterface &si,
00093                                         OsiCuts &cs, 
00094                                         const CglTreeInfo info) const {
00095 
00096   // check if out of time or if an infeasibility cut (iis of type 0)
00097   // was added as a result of, e.g., pruning on BT. If so, no need to
00098   // run this.
00099 
00100   if (isWiped (cs) || 
00101      (CoinCpuTime () > problem_ -> getMaxCpuTime ()))
00102     return;
00103 
00104 #ifdef FM_TRACE_OPTSOL
00105   double currCutOff = problem_->getCutOff();
00106   double bestVal = 1e50;
00107   CouenneRecordBestSol *rs = problem_->getRecordBestSol();
00108   if(rs->getHasSol()) {
00109     bestVal = rs->getVal(); 
00110   }
00111   if(currCutOff > bestVal) {
00112     //problem_ -> setCutOff (bestVal - 1e-6); // FIXME: don't add numerical constants
00113     problem_ -> setCutOff (bestVal);
00114     OsiColCut *objCut = new OsiColCut;
00115     int indObj = problem_->Obj(0)->Body()->Index();
00116     objCut->setUbs(1, &indObj, &bestVal);
00117     cs.insert(objCut);
00118     delete objCut;
00119   }
00120 #endif
00121 
00122 #ifdef FM_PRINT_INFO
00123   if((BabPtr_ != NULL) && (info.level >= 0) && (info.pass == 0) && 
00124      (BabPtr_->model().getNodeCount() > lastPrintLine)) {
00125     printLineInfo();
00126     lastPrintLine += 1;
00127   }
00128 #endif
00129 
00130   const int infeasible = 1;
00131 
00132   int nInitCuts = cs.sizeRowCuts ();
00133 
00134   CouNumber
00135     *&realOpt = problem_ -> bestSol (),
00136     *saveOptimum = realOpt;
00137 
00138   if (!firstcall_ && realOpt) { 
00139 
00140     // have a debug optimal solution. Check if current bounds
00141     // contain it, otherwise pretend it does not exist
00142 
00143     CouNumber *opt = realOpt;
00144 
00145     const CouNumber 
00146       *sol = si.getColSolution (),
00147       *lb  = si.getColLower (),
00148       *ub  = si.getColUpper ();
00149 
00150     int objind = problem_ -> Obj (0) -> Body () -> Index ();
00151 
00152     for (int j=0, i=problem_ -> nVars (); i--; j++, opt++, lb++, ub++)
00153       if ((j != objind) && 
00154           ((*opt < *lb - COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*lb)))) || 
00155            (*opt > *ub + COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*ub)))))) {
00156         
00157         jnlst_ -> Printf (J_VECTOR, J_CONVEXIFYING, 
00158                           "out of bounds, ignore x%d = %g [%g,%g] opt = %g\n", 
00159                           problem_ -> nVars () - i - 1, *sol, *lb, *ub, *opt);
00160 
00161         // optimal point is not in current bounding box,
00162         // pretend realOpt is NULL until we return from this procedure
00163         realOpt = NULL;
00164         break;
00165       }
00166   }
00167 
00168   /*static int count = 0;
00169   char fname [20];
00170   sprintf (fname, "relax_%d", count++);
00171   si.writeLp (fname);
00172   printf ("writing %s\n", fname);*/
00173 
00174   jnlst_ -> Printf (J_DETAILED, J_CONVEXIFYING,
00175                     "generateCuts: level = %d, pass = %d, intree = %d\n",
00176                     info.level, info.pass, info.inTree);
00177 
00178   Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (si.getAuxiliaryInfo ());
00179 
00180   if (babInfo)
00181     babInfo -> setFeasibleNode ();
00182 
00183   double now   = CoinCpuTime ();
00184   int    ncols = problem_ -> nVars ();
00185 
00186   // This vector contains variables whose bounds have changed due to
00187   // branching, reduced cost fixing, or bound tightening below. To be
00188   // used with malloc/realloc/free
00189 
00190   t_chg_bounds *chg_bds = new t_chg_bounds [ncols];
00191 
00192   /*for (int i=0; i < ncols; i++) 
00193     if (problem_ -> Var (i) -> Multiplicity () <= 0) {
00194       chg_bds [i].setLower (t_chg_bounds::UNCHANGED);
00195       chg_bds [i].setUpper (t_chg_bounds::UNCHANGED);
00196       }*/
00197 
00198   problem_ -> installCutOff (); // install upper bound
00199 
00200   if (firstcall_) {
00201 
00202     // First convexification //////////////////////////////////////
00203 
00204     // OsiSolverInterface is empty yet, no information can be obtained
00205     // on variables or bounds -- and none is needed since our
00206     // constructor populated *problem_ with variables and bounds. We
00207     // only need to update the auxiliary variables and bounds with
00208     // their current value.
00209 
00210     for (int i=0; i < ncols; i++) 
00211       if (problem_ -> Var (i) -> Multiplicity () > 0) {
00212         chg_bds [i].setLower (t_chg_bounds::CHANGED);
00213         chg_bds [i].setUpper (t_chg_bounds::CHANGED);
00214       }
00215 
00216     // start with FBBT, should take advantage of cutoff found by NLP
00217     // run AFTER initial FBBT...
00218     if (problem_ -> doFBBT () &&
00219         (! (problem_ -> boundTightening (chg_bds, babInfo))))
00220           jnlst_ -> Printf (J_STRONGWARNING, J_CONVEXIFYING,
00221             "Couenne: WARNING, first convexification is infeasible\n");
00222 
00223     // For each auxiliary variable replacing the original (nonlinear)
00224     // constraints, check if corresponding bounds are violated, and
00225     // add cut to cs
00226 
00227     int nnlc = problem_ -> nCons ();
00228 
00229     for (int i=0; i<nnlc; i++) {
00230 
00231       if (CoinCpuTime () > problem_ -> getMaxCpuTime ())
00232         break;
00233 
00234       // for each constraint
00235       CouenneConstraint *con = problem_ -> Con (i);
00236 
00237       // (which has an aux as its body)
00238       int index = con -> Body () -> Index ();
00239 
00240       if ((index >= 0) && 
00241           ((con -> Body () -> Type () == AUX) ||
00242            (con -> Body () -> Type () == VAR))) {
00243 
00244         // get the auxiliary that is at the lhs
00245         exprVar *conaux = problem_ -> Var (index);
00246 
00247         if (conaux &&
00248             (conaux -> Type () == AUX) &&
00249             (conaux -> Image ()) && 
00250             (conaux -> Image () -> Linearity () <= LINEAR)) {
00251 
00252           // reduce density of problem by adding w >= l rather than
00253           // ax + b >= l for any linear auxiliary defined as w := ax+b
00254 
00255           double 
00256             lb = (*(con -> Lb ())) (), 
00257             ub = (*(con -> Ub ())) ();
00258 
00259           OsiColCut newBound;
00260           if (lb > -COUENNE_INFINITY) newBound.setLbs (1, &index, &lb);
00261           if (ub <  COUENNE_INFINITY) newBound.setUbs (1, &index, &ub);
00262 
00263           cs.insert (newBound);
00264 
00265           // the auxiliary w of constraint w <= b is associated with a
00266           // linear expression w = ax: add constraint ax <= b
00267           /*conaux -> Image () -> generateCuts (conaux, si, cs, this, chg_bds, 
00268                                               conaux -> Index (), 
00269                                               (*(con -> Lb ())) (), 
00270                                               (*(con -> Ub ())) ());*/
00271 
00272           // take it from the list of the variables to be linearized
00273           // 
00274           // DO NOT decrease multiplicity. Even if it is a linear
00275           // term, its bounds can still be used in implied bounds
00276           //
00277           // Are we sure? That will happen only if its multiplicity is
00278           // nonzero, for otherwise this aux is only used here, and is
00279           // useless elsewhere
00280           //
00281           //conaux -> decreaseMult (); // !!!
00282         }
00283 
00284         // also, add constraint w <= b
00285 
00286         // not now, do it later
00287 
00288 //      // if there exists violation, add constraint
00289 //      CouNumber l = con -> Lb () -> Value (), 
00290 //                u = con -> Ub () -> Value ();
00291 
00292 //      // tighten bounds in Couenne's problem representation
00293 //      problem_ -> Lb (index) = CoinMax (l, problem_ -> Lb (index));
00294 //      problem_ -> Ub (index) = CoinMin (u, problem_ -> Ub (index));
00295 
00296       } else { // body is more than just a variable, but it should be
00297                // linear. If so, generate equivalent linear cut
00298 
00299         assert (false); // TODO
00300       }
00301     }
00302 
00303     if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) {
00304       if (cs.sizeRowCuts ()) {
00305         jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint row cuts\n",
00306                           cs.sizeRowCuts ());
00307         for (int i=0; i<cs.sizeRowCuts (); i++) 
00308           cs.rowCutPtr (i) -> print ();
00309       }
00310       if (cs.sizeColCuts ()) {
00311         jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint col cuts\n",
00312                           cs.sizeColCuts ());
00313         for (int i=0; i<cs.sizeColCuts (); i++) 
00314           cs.colCutPtr (i) -> print ();
00315       }
00316     }
00317   } else {
00318 
00319     // use new optimum as lower bound for variable associated w/objective
00320     int indobj = problem_ -> Obj (0) -> Body () -> Index ();
00321 
00322     // transmit solution from OsiSolverInterface to problem
00323     problem_ -> domain () -> push (&si, &cs);
00324 
00325     if (indobj >= 0) {
00326 
00327       // Use current value of objvalue's x as a lower bound for bound
00328       // tightening
00329       double lp_bound = problem_ -> domain () -> x (indobj);
00330 
00331       //if (problem_ -> Obj (0) -> Sense () == MINIMIZE) 
00332       {if (lp_bound > problem_ -> Lb (indobj)) problem_ -> Lb (indobj) = lp_bound;}
00333            //else {if (lp_bound < problem_ -> Ub (indobj)) problem_ -> Ub (indobj) = lp_bound;}
00334     }
00335 
00336     updateBranchInfo (si, problem_, chg_bds, info); // info.depth >= 0 || info.pass >= 0
00337   }
00338 
00339   // restore constraint bounds before tightening and cut generation
00340   for (int i = problem_ -> nCons (); i--;) {
00341 
00342     // for each constraint
00343     CouenneConstraint *con = problem_ -> Con (i);
00344 
00345     // (which has an aux as its body)
00346     int index = con -> Body () -> Index ();
00347 
00348     if ((index >= 0) && 
00349         ((con -> Body () -> Type () == AUX) ||
00350          (con -> Body () -> Type () == VAR))) {
00351 
00352       // if there exists violation, add constraint
00353       CouNumber 
00354         l = con -> Lb () -> Value (),   
00355         u = con -> Ub () -> Value ();
00356 
00357       // tighten bounds in Couenne's problem representation
00358       problem_ -> Lb (index) = CoinMax (l, problem_ -> Lb (index));
00359       problem_ -> Ub (index) = CoinMin (u, problem_ -> Ub (index));
00360     }
00361   }
00362 
00363   problem_ -> installCutOff (); // install upper bound
00364 
00365   fictitiousBound (cs, problem_, false); // install finite lower bound, if currently -inf
00366 
00367   int *changed = NULL, nchanged;
00368 
00369   // Bound tightening ///////////////////////////////////////////
00370 
00371   // do bound tightening only at first pass of cutting plane in a node
00372   // of BB tree (info.pass == 0) or if first call (creation of RLT,
00373   // info.pass == -1)
00374 
00375   try {
00376 
00377     // Before bound tightening, compute symmetry group. After bound
00378     // tightening is done, we can apply further tightening using orbit
00379     // information.
00380 
00381 #ifdef COIN_HAS_NTY
00382     //    ChangeBounds (psi -> getColLower (),  
00383     //            psi -> getColUpper (), 
00384     //            psi -> getNumCols ());
00385     if (problem_ -> orbitalBranching ())
00386       problem_ -> Compute_Symmetry ();
00387 #endif
00388 
00389     // Bound tightening ////////////////////////////////////
00390 
00391     /*printf ("== BT ================\n");
00392       for (int i = 0; i < problem_ -> nVars (); i++)
00393       if (problem_ -> Var (i) -> Multiplicity () > 0)
00394       printf ("%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
00395       problem_ -> X  (i), problem_ -> Lb (i), problem_ -> Ub (i));
00396       printf("=============================\n");*/
00397 
00398     // Reduced Cost BT -- to be done first to use rcost correctly
00399     if (!firstcall_  &&                         // have a linearization already
00400         problem_ -> doRCBT () &&                // authorized to do reduced cost tightening
00401         problem_ -> redCostBT (&si, chg_bds) && // some variables were tightened with reduced cost
00402         !(problem_ -> btCore (chg_bds)))        // in this case, do another round of FBBT
00403       throw infeasible;
00404 
00405     // FBBT
00406     if (problem_ -> doFBBT () && 
00407         //(info.pass <= 0) && // do it in subsequent rounds too
00408         (! (problem_ -> boundTightening (chg_bds, babInfo))))
00409       throw infeasible;
00410 
00411     // OBBT
00412     if (!firstcall_ && // no obbt if first call (there is no LP to work with)
00413         problem_ -> obbt (this, si, cs, info, babInfo, chg_bds) < 0)
00414       throw infeasible;
00415 
00416     // Bound tightening done /////////////////////////////
00417 
00418     if ((problem_ -> doFBBT () ||
00419          problem_ -> doOBBT () ||
00420          problem_ -> doABT  ()) &&
00421         (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING))) {
00422 
00423       jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== after bt =============\n");
00424       for (int i = 0; i < problem_ -> nVars (); i++)
00425         if (problem_ -> Var (i) -> Multiplicity () > 0)
00426           jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
00427                          problem_ -> X  (i), problem_ -> Lb (i), problem_ -> Ub (i));
00428       jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
00429     }
00430 
00431     // Use orbit info to tighten bounds
00432 
00433 #ifdef COIN_HAS_NTY
00434 
00435     // TODO: when independent bound tightener, can get original bounds
00436     // through si.getCol{Low,Upp}er()
00437 
00438     if (problem_ -> orbitalBranching () && !firstcall_) {
00439 
00440       CouNumber 
00441         *lb = problem_ -> Lb (),
00442         *ub = problem_ -> Ub ();
00443 
00444       std::vector<std::vector<int> > *new_orbits = problem_ -> getNtyInfo () -> getOrbits();
00445 
00446       for (int i=0, ii = problem_ -> getNtyInfo () -> getNumOrbits (); ii--; i++){
00447 
00448         CouNumber
00449           ll = -COUENNE_INFINITY,
00450           uu =  COUENNE_INFINITY; 
00451         
00452         std::vector <int> orbit = (*new_orbits)[i];
00453 
00454         if (orbit.size () <= 1)
00455           continue; // not much to do when only one variable in this orbit
00456 
00457         if (jnlst_ -> ProduceOutput (J_VECTOR, J_BOUNDTIGHTENING)) {
00458           printf ("orbit bounds: "); fflush (stdout);
00459           for(int j = 0; j < orbit.size (); j++) {
00460             printf ("x_%d [%g,%g] ", orbit[j], lb [orbit [j]], ub [orbit [j]]);
00461             fflush (stdout);
00462           }
00463           printf ("\n");
00464         }
00465 
00466         for (int j = 0; j < orbit.size (); j++) {
00467  
00468           int indOrb = orbit [j];
00469 
00470           if (indOrb < problem_ -> nVars ()) {
00471 
00472             if (lb [indOrb] > ll) ll = lb [indOrb];
00473             if (ub [indOrb] < uu) uu = ub [indOrb];
00474           }
00475         }
00476 
00477         jnlst_ -> Printf (J_VECTOR, J_BOUNDTIGHTENING, 
00478                           " --> new common lower bounds: [%g,--]\n", ll);
00479 
00480         for(int j = 0; j < orbit.size (); j++) {
00481 
00482           int indOrb = orbit [j];
00483 
00484           if (indOrb < problem_ -> nVars ()){
00485 
00486             lb [indOrb] = ll;
00487             ub [indOrb] = uu;
00488           }
00489         }
00490       }
00491 
00492       delete new_orbits;
00493     }
00494 
00495 #endif
00496 
00497     // Generate convexification cuts //////////////////////////////
00498 
00499     sparse2dense (ncols, chg_bds, changed, nchanged);
00500 
00501     double *nlpSol = NULL;
00502 
00503     //--------------------------------------------
00504 
00505     if (true) {
00506 
00507       if (babInfo) 
00508         nlpSol = const_cast <double *> (babInfo -> nlpSolution ());
00509 
00510       // Aggressive Bound Tightening ////////////////////////////////
00511 
00512       int logAbtLev = problem_ -> logAbtLev ();
00513 
00514       if (problem_ -> doABT () &&             // flag is checked, AND
00515           ((logAbtLev != 0) ||                // (parameter is nonzero OR
00516            (info.level == 0)) &&              //  we are at root node), AND
00517           (info.pass == 0) &&                 // at first round of cuts, AND 
00518           ((logAbtLev < 0) ||                 // (logAbtLev = -1, OR
00519            (info.level <= logAbtLev) ||       //  depth is lower than COU_OBBT_CUTOFF_LEVEL, OR
00520            (CoinDrand48 () <                  //  probability inversely proportional to the level)
00521             pow (2., (double) logAbtLev - (info.level + 1))))) {
00522 
00523         jnlst_ -> Printf(J_VECTOR, J_BOUNDTIGHTENING,"  performing ABT\n");
00524         if (! (problem_ -> aggressiveBT (nlp_, chg_bds, info, babInfo)))
00525           throw infeasible;
00526 
00527         sparse2dense (ncols, chg_bds, changed, nchanged);
00528       }
00529 
00530       // obtain solution just found by nlp solver
00531 
00532       // Auxiliaries should be correct. solution should be the one found
00533       // at the node even if not as good as the best known.
00534 
00535       // save violation flag and disregard it while adding cut at NLP
00536       // point (which are not violated by the current, NLP, solution)
00537       bool save_av = addviolated_;
00538       addviolated_ = false;
00539 
00540       // save values
00541       problem_ -> domain () -> push 
00542         (problem_ -> nVars (), 
00543          problem_ -> domain () -> x  (), 
00544          problem_ -> domain () -> lb (), 
00545          problem_ -> domain () -> ub (), false);
00546 
00547       // fill originals with nlp values
00548       if (nlpSol) {
00549         CoinCopyN (nlpSol, problem_ -> nOrigVars (), problem_ -> domain () -> x ());
00550       //problem_ -> initAuxs ();
00551 
00552       problem_ -> getAuxs (problem_ -> domain () -> x ());
00553       }
00554 
00555       if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
00556         jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on NLP =============\n");
00557         for (int i = 0; i < problem_ -> nVars (); i++)
00558           if (problem_ -> Var (i) -> Multiplicity () > 0)
00559             jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
00560                            problem_ -> X  (i),
00561                            problem_ -> Lb (i),
00562                            problem_ -> Ub (i));
00563         jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
00564       }
00565 
00566       problem_ -> domain () -> current () -> isNlp () = true;
00567       genRowCuts (si, cs, nchanged, changed, chg_bds);  // add cuts
00568 
00569       problem_ -> domain () -> pop (); // restore point
00570 
00571       addviolated_ = save_av;     // restore previous value
00572 
00573       //    if (!firstcall_) // keep solution if called from extractLinearRelaxation()
00574       if (babInfo) 
00575         babInfo -> setHasNlpSolution (false); // reset it after use //AW HERE
00576 
00577     } else {
00578 
00579       if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) {
00580         jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on LP =============\n");
00581         for (int i = 0; i < problem_ -> nVars (); i++)
00582           if (problem_ -> Var (i) -> Multiplicity () > 0)
00583             jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i,
00584                            problem_ -> X  (i),
00585                            problem_ -> Lb (i),
00586                            problem_ -> Ub (i));
00587         jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n");
00588       }
00589 
00590       genRowCuts (si, cs, nchanged, changed, chg_bds);
00591     }
00592 
00593     // change tightened bounds through OsiCuts
00594     if (nchanged)
00595       genColCuts (si, cs, nchanged, changed);
00596 
00597     if (firstcall_ && (cs.sizeRowCuts () >= 1))
00598       jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
00599                      "Couenne: %d initial row cuts\n", cs.sizeRowCuts ());
00600 
00601     if (realOpt && // this is a good time to check if we have cut the optimal solution
00602         isOptimumCut (realOpt, cs, problem_))
00603       jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING,
00604                      "Warning: Optimal solution was cut\n");
00605   }
00606 
00607   catch (int exception) {
00608 
00609     if ((exception == infeasible) && (!firstcall_)) {
00610 
00611       jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,
00612                         "Couenne: Infeasible node\n");
00613 
00614       WipeMakeInfeas (cs);
00615     }
00616 
00617     if (babInfo) // set infeasibility to true in order to skip NLP heuristic
00618       babInfo -> setInfeasibleNode ();
00619   }
00620 
00621   delete [] chg_bds;
00622 
00623   if (changed) 
00624     free (changed);
00625 
00626   if (firstcall_) {
00627 
00628     jnlst_ -> Printf (J_SUMMARY, J_CONVEXIFYING, 
00629                       "Couenne: %d cuts (%d row, %d col) for linearization\n", 
00630                       cs.sizeRowCuts () + cs.sizeColCuts (),
00631                       cs.sizeRowCuts (),  cs.sizeColCuts ());
00632 
00633     fictitiousBound (cs, problem_, true);
00634     firstcall_  = false;
00635     ntotalcuts_ = nrootcuts_ = cs.sizeRowCuts ();
00636 
00637   } else { 
00638 
00639     problem_ -> domain () -> pop ();
00640 
00641     ntotalcuts_ += (cs.sizeRowCuts () - nInitCuts);
00642 
00643     if (saveOptimum)
00644       realOpt = saveOptimum; // restore debug optimum
00645   }
00646 
00647   septime_ += CoinCpuTime () - now;
00648 
00649   if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) {
00650 
00651     if (cs.sizeColCuts ()) {
00652       jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne col cuts:\n");
00653       for (int i=0; i<cs.sizeColCuts (); i++) 
00654         cs.colCutPtr (i) -> print ();
00655     }
00656   }
00657 
00658   if (!(info.inTree)) 
00659     rootTime_ = CoinCpuTime ();
00660 }
00661 
00662 }

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