/home/coin/SVN-release/OS-2.4.1/Couenne/src/bound_tightening/obbt.cpp

Go to the documentation of this file.
00001 /* $Id: obbt.cpp 698 2011-06-20 13:36:43Z pbelotti $
00002  *
00003  * Name:    obbt.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: Optimality-Based Bound Tightening
00006  *
00007  * (C) Carnegie-Mellon University, 2006-10.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CoinHelperFunctions.hpp"
00012 #include "CglCutGenerator.hpp"
00013 #include "OsiClpSolverInterface.hpp"
00014 
00015 #include "CouenneExpression.hpp"
00016 #include "CouenneExprVar.hpp"
00017 #include "CouenneCutGenerator.hpp"
00018 #include "CouenneProblem.hpp"
00019 #include "CouenneInfeasCut.hpp"
00020 
00021 using namespace Ipopt;
00022 using namespace Couenne;
00023 
00024 #define THRESH_OBBT_AUX 50 // if more than this originals, don't do OBBT on auxs
00025 #define OBBT_EPS 1e-3
00026 #define MAX_OBBT_LP_ITERATION 100
00027 #define MAX_OBBT_ATTEMPTS 1 // number of OBBT iterations at root node
00028                             // -- fixed at one as for some instance it
00029                             // doesn't seem to do anything after first run
00030 
00031 // minimum #bound changed in obbt to generate further cuts
00032 #define THRES_NBD_CHANGED 1
00033 
00034 // maximum number of obbt iterations
00035 #define MAX_OBBT_ITER 1
00036 
00037 // defined in generateCuts.cpp
00038 void sparse2dense (int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged);
00039 
00040 
00041 // OBBT for one sense (max/min) and one class of variables (orig/aux)
00042 int CouenneProblem::call_iter (OsiSolverInterface *csi, 
00043                                t_chg_bounds *chg_bds, 
00044                                const CoinWarmStart *warmstart, 
00045                                Bonmin::BabInfo *babInfo,
00046                                double *objcoe,
00047                                enum nodeType type,
00048                                int sense) const {
00049 
00050   int ncols   = csi -> getNumCols (),
00051       nimprov = 0;
00052 
00053   for (int ii=0; ii<ncols; ii++) {
00054 
00055     if (CoinCpuTime () > maxCpuTime_)
00056       break;
00057 
00058     int i = evalOrder (ii);
00059 
00060     enum expression::auxSign aSign = Var (i) -> sign ();
00061 
00062     if ((Var (i) -> Type () == type)     &&
00063         (Var (i) -> Multiplicity () > 0) &&
00064         ((type == VAR)                               || 
00065          (aSign  == expression::AUX_EQ) ||
00066          ((aSign == expression::AUX_LEQ) && (sense > 0)) ||
00067          ((aSign == expression::AUX_GEQ) && (sense < 0)))) {
00068 
00069       int ni = obbt_iter (csi, chg_bds, warmstart, babInfo, objcoe, sense, i);
00070 
00071 //       {
00072 //      // ToDo: Pipe all output through journalist
00073 //      Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING, 
00074 //                      "  bounds after obbt step  =====================\n  ");
00075 //      int j=0;
00076 //      for (int i=0; i < nVars (); i++) 
00077 //        if (variables_ [i] -> Multiplicity () > 0) {
00078 //          Jnlst()->Printf(J_VECTOR, J_BOUNDTIGHTENING,
00079 //                          "x_%03d [%+10g %+10g] ", i, 
00080 //                          domain_. lb (i),
00081 //                          domain_. ub (i));
00082 //          if (!(++j % 6)) Jnlst()->Printf(J_VECTOR, J_BOUNDTIGHTENING,"\n  ");
00083 //        }
00084 //      if (j % 6) Jnlst()->Printf(J_VECTOR, J_BOUNDTIGHTENING,"\n");
00085 //       }
00086 
00087       if (ni < 0) return ni;
00088       nimprov += ni;
00089     }
00090   }
00091 
00092   return nimprov;
00093 }
00094 
00095 
00097 
00098 int CouenneProblem::obbtInner (OsiSolverInterface *csi,
00099                                OsiCuts &cs,
00100                                t_chg_bounds *chg_bds,
00101                                Bonmin::BabInfo * babInfo) const {
00102 
00103   // set large bounds to infinity (as per suggestion by JJF)
00104 
00105   int ncols = csi -> getNumCols ();
00106   const double *lb = csi -> getColLower (),
00107                *ub = csi -> getColUpper ();
00108 
00109   double inf = csi -> getInfinity ();
00110 
00111   for (int i=ncols; i--;) {
00112     if (lb [i] < - COUENNE_INFINITY) csi -> setColLower (i, -inf);
00113     if (ub [i] >   COUENNE_INFINITY) csi -> setColUpper (i,  inf);
00114   }
00115 
00116   //  csi -> setHintParam (OsiDoDualInResolve, false);
00117 
00118   // setup cloned interface for later use
00119   csi -> setObjSense (1); // minimization
00120   csi -> setIntParam (OsiMaxNumIteration, MAX_OBBT_LP_ITERATION);
00121   csi -> applyCuts (cs);   // apply all (row+column) cuts to formulation
00122   csi -> initialSolve ();
00123 
00124   const CoinWarmStart *warmstart = csi -> getWarmStart ();
00125 
00126   // improve each bound
00127 
00128   double *objcoe = (double *) malloc (ncols * sizeof (double));
00129 
00130   // set obj function coefficients to zero
00131   for (int i=ncols; i--;)
00132     *objcoe++ = 0.;
00133   objcoe -= ncols;
00134 
00135   csi -> setObjective (objcoe);
00136   csi -> setObjSense (1);        // minimization
00137 
00138   int nimprov = 0;
00139  
00140   const int Infeasible = 1;
00141 
00142   try {
00143 
00144     int ni;
00145 
00146     if ((ni = call_iter (csi, chg_bds, warmstart, babInfo, objcoe, VAR,  1)) < 0) throw Infeasible;
00147     nimprov += ni;
00148 
00149     if ((ni = call_iter (csi, chg_bds, warmstart, babInfo, objcoe, VAR, -1)) < 0) throw Infeasible;
00150     nimprov += ni;
00151 
00152     if (nVars () < THRESH_OBBT_AUX) {
00153 
00154       if ((ni = call_iter (csi, chg_bds, warmstart, babInfo, objcoe, AUX,  1)) < 0) throw Infeasible;
00155       nimprov += ni;
00156 
00157       if ((ni = call_iter (csi, chg_bds, warmstart, babInfo, objcoe, AUX, -1)) < 0) throw Infeasible;
00158       nimprov += ni;
00159     }
00160   }
00161 
00162   catch (int exception) {
00163 
00164     if (exception == Infeasible)
00165       nimprov = -1;
00166   }
00167 
00168   free (objcoe);
00169   delete warmstart;
00170 
00171   return (nimprov);
00172 }
00173 
00174 
00175 // Optimality based bound tightening -- main loop
00176 int CouenneProblem::obbt (const CouenneCutGenerator *cg,
00177                           const OsiSolverInterface &si,
00178                           OsiCuts &cs,
00179                           const CglTreeInfo &info,
00180                           Bonmin::BabInfo * babInfo,
00181                           t_chg_bounds *chg_bds) {
00182 
00183   // TODO: set up list of hopeless variables and do different OBBT
00184   // saving lps
00185 
00186   // Check if cs contains only one cut and if it is of the form 1 <=
00187   // x0 <= -1. That means a previous cut generator has determined that
00188   // this node is infeasible and we shouldn't take the pain of running
00189   // this CGL.
00190 
00191   if (isWiped (cs) || info.pass >= MAX_OBBT_ATTEMPTS)
00192     return 0;
00193 
00194   int nTotImproved = 0;
00195 
00196   // Do OBBT if:
00197   if (doOBBT_ &&                        // flag is checked, AND
00198       ((logObbtLev_ != 0) ||               // (parameter is nonzero OR
00199        (info.level == 0)) &&               //  we are at root node), AND
00200       (info.pass == 0) &&               // at first round of cuts, AND 
00201       ((logObbtLev_ < 0) ||               // (logObbtLev = -1, OR
00202        (info.level <= logObbtLev_) ||     //  depth is lower than COU_OBBT_CUTOFF_LEVEL, OR
00203                                           //  probability inversely proportional to the level)
00204        (CoinDrand48 () < pow (2., (double) logObbtLev_ - (info.level + 1))))) {
00205 
00206     if ((info.level <= 0 && !(info.inTree)) || 
00207         jnlst_ -> ProduceOutput (J_STRONGWARNING, J_COUENNE))  {
00208 
00209       jnlst_ -> Printf (J_ERROR, J_COUENNE, "Optimality Based BT: "); 
00210       //nVars () > THRESH_OBBT_AUX ? nOrigVars_ : nVars (), info.pass); 
00211       fflush (stdout);
00212     }
00213 
00214     jnlst_ -> Printf (J_ITERSUMMARY, J_BOUNDTIGHTENING, "----- OBBT\n");
00215 
00216     // TODO: why check info.pass==0? Why not more than one pass? It
00217     // should be anyway checked that info.level be >= 0 as <0 means
00218     // first call at root node
00219 
00220     OsiSolverInterface *csi = si.clone (true);
00221 
00222     csi -> messageHandler () -> setLogLevel (0);
00223     //dynamic_cast <CouenneSolverInterface<T> *> 
00224 
00225     OsiClpSolverInterface *clpcsi = dynamic_cast <OsiClpSolverInterface *> (csi);
00226 
00227     if (clpcsi)
00228       clpcsi -> setupForRepeatedUse ();
00229     //csi -> doingResolve () = false;
00230 
00231     //csi -> setHintParam (OsiDoDualInResolve, false);
00232 
00233     int nImprov, nIter = 0;
00234 
00235     bool notImproved = false;
00236 
00237     while (!notImproved && 
00238            (nIter++ < MAX_OBBT_ITER) &&
00239            ((nImprov = obbtInner (csi, cs, chg_bds, babInfo)) > 0) &&
00240            (CoinCpuTime () < maxCpuTime_)) {
00241 
00242       int nchanged, *changed = NULL;
00243 
00245       sparse2dense (nVars (), chg_bds, changed, nchanged);
00246       cg -> genColCuts (*csi, cs, nchanged, changed);
00247 
00248       nTotImproved += nImprov;
00249 
00250       if ((nIter < MAX_OBBT_ITER) && 
00251           (nImprov >= THRES_NBD_CHANGED)) {
00252 
00253         // only generate new row cuts if improvents are enough
00254         int nCurCuts = cs.sizeRowCuts ();
00255         cg -> genRowCuts (*csi, cs, nchanged, changed, chg_bds);
00256 
00257         if (nCurCuts == cs.sizeRowCuts ())
00258           notImproved = true; // repeat only if new cuts available
00259 
00260       } else notImproved = true;
00261 
00262       if (changed) 
00263         free (changed);
00264     }
00265 
00266     //csi -> doingResolve () = true;
00267 
00268     delete csi;
00269 
00270     if ((info.level <= 0 && !(info.inTree)) ||
00271         jnlst_ -> ProduceOutput (J_STRONGWARNING, J_COUENNE))
00272       jnlst_ -> Printf (J_ERROR, J_COUENNE, "%d improved bounds\n", nTotImproved);
00273 
00274     if (nImprov < 0) {
00275       jnlst_->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING, "  Couenne: infeasible node after OBBT\n");
00276       return -1;
00277     }
00278   }
00279 
00280   return 0;
00281 }

Generated on Thu Nov 10 03:05:42 2011 by  doxygen 1.4.7