/home/coin/SVN-release/OS-2.4.1/Couenne/src/branch/CouenneVarObject.cpp

Go to the documentation of this file.
00001 /* $Id: CouenneVarObject.cpp 708 2011-06-23 14:04:59Z pbelotti $
00002  *
00003  * Name:    CouenneVarObject.cpp
00004  * Authors: Pietro Belotti, Carnegie Mellon University
00005  * Purpose: Base object for variables (to be used in branching)
00006  *
00007  * (C) Carnegie-Mellon University, 2008-11.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CoinHelperFunctions.hpp"
00012 
00013 #include "BonBabSetupBase.hpp"
00014 
00015 #include "CouenneProblem.hpp"
00016 #include "CouenneVarObject.hpp"
00017 #include "CouenneBranchingObject.hpp"
00018 #include "CouenneComplObject.hpp"
00019 #include "CouenneProblemElem.hpp"
00020 
00021 using namespace Ipopt;
00022 using namespace Couenne;
00023 
00025 CouenneVarObject::CouenneVarObject (CouenneCutGenerator *c,
00026                                     CouenneProblem *p,
00027                                     exprVar *ref, 
00028                                     Bonmin::BabSetupBase *base, 
00029                                     JnlstPtr jnlst,
00030                                     int varSelection):
00031 
00032   // Do not set variable (expression).
00033   // This way, no expression-dependent strategy is chosen
00034   CouenneObject (c, p, ref, base, jnlst),
00035   varSelection_ (varSelection) {
00036 
00037   if (jnlst_ -> ProduceOutput (J_SUMMARY, J_BRANCHING)) {
00038     printf ("created Variable Object: "); 
00039     reference_ -> print (); 
00040     printf (" with %s strategy [clamp=%g, alpha=%g]\n", 
00041             (strategy_ == LP_CLAMPED)   ? "lp-clamped" : 
00042             (strategy_ == LP_CENTRAL)   ? "lp-central" : 
00043             (strategy_ == BALANCED)     ? "balanced"   : 
00044             (strategy_ == MIN_AREA)     ? "min-area"   : 
00045             (strategy_ == MID_INTERVAL) ? "mid-point"  : 
00046             (strategy_ == NO_BRANCH)    ? "no-branching (null infeasibility)" : 
00047                                           "no strategy",
00048             lp_clamp_, alpha_);
00049   }
00050 }
00051 
00052 
00054 OsiBranchingObject *CouenneVarObject::createBranch (OsiSolverInterface *si, 
00055                                                     const OsiBranchingInformation *info, 
00056                                                     int way) const {
00057 
00058   // Before anything, use the LP point if so instructed
00059 
00060   problem_ -> domain () -> push 
00061     (problem_ -> nVars (),
00062      info -> solution_,
00063      info -> lower_,
00064      info -> upper_, false); // don't have to alloc+copy
00065 
00066   OsiBranchingObject *obj = NULL;
00067 
00068   // For some obscure reason, this only seems to work if
00069   // strong/reliability branching is not used. I suppose it has to do
00070   // with omitted pseudocost multiplier update, or some other hidden
00071   // part of the code. 
00072 
00073   if ((varSelection_ == Bonmin::BabSetupBase::OSI_SIMPLE) && 
00074       ((strategy_ == CouenneObject::LP_CLAMPED) ||
00075        (strategy_ == CouenneObject::LP_CENTRAL) ||
00076        (strategy_ == CouenneObject::MID_INTERVAL))) {
00077 
00078     int indVar = reference_ -> Index ();
00079 
00080     CouNumber
00081       brpt  = info -> solution_ [indVar],
00082       l     = info -> lower_    [indVar],
00083       u     = info -> upper_    [indVar];
00084       
00085     // these vanilla assignments would drive Couenne crazy. If any of
00086     // the bounds is (in absolute value) above 1e20, branching values
00087     // can be detrimental for bound tightening and convexification
00088     // cuts, for instance.
00089 
00090     // Actually, even smaller values (such as 1e10) can trigger bad BB
00091     // tree development (see wall in test files, not globallib/wall)
00092 
00093 #define LARGE_VALUE 1e8
00094 
00095     if ((l < - LARGE_VALUE) && 
00096         (u >   LARGE_VALUE) &&
00097         (fabs (brpt) > LARGE_VALUE / 10))
00098       brpt = 0.;
00099 
00100     if (l < - COUENNE_INFINITY) l = -1. - 2 * fabs (brpt);
00101     if (u >   COUENNE_INFINITY) u = +1. + 2 * fabs (brpt);
00102 
00103     CouNumber width = lp_clamp_ * (u-l);
00104 
00105     switch (strategy_) {
00106 
00107     case CouenneObject::LP_CLAMPED:   brpt = CoinMax (l + width, CoinMin (brpt, u - width));        break;
00108     case CouenneObject::LP_CENTRAL:   if ((brpt < l + width) || 
00109                                           (brpt > u - width)) brpt = .5 * (l+u);                    break;
00110     case CouenneObject::MID_INTERVAL: brpt = midInterval (brpt, 
00111                                                           info -> lower_ [indVar], 
00112                                                           info -> upper_ [indVar], info);           break;
00113     default: assert (false); // this will never be used
00114     }
00115 
00116     obj = new CouenneBranchingObject (si, this, jnlst_, cutGen_, problem_, reference_, 
00117                                                           TWO_LEFT, brpt, doFBBT_, doConvCuts_);
00118   } else {
00119 
00120     // now deal with the more complicated branching selections
00121 
00122     // The infeasibility on an (independent) variable x_i is given by
00123     // something more elaborate than |w-f(x)|, that is, a function of
00124     // all infeasibilities of all expressions which depend on x_i.
00125 
00126     int bestWay;
00127     const CouenneObject *criticalObject = NULL; // should create the branchingObject
00128 
00129     CouNumber bestPt = computeBranchingPoint (info, bestWay, criticalObject);
00130 
00132 
00133     int indVar = reference_ -> Index ();
00134 
00135     jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, ":::: creating branching on x_%d @%g [%g,%g]\n", 
00136                       indVar, 
00137                       info -> solution_ [indVar],
00138                       info -> lower_    [indVar],
00139                       info -> upper_    [indVar]);
00140 
00141     obj = criticalObject ? 
00142       criticalObject -> createBranch (si, info, way) :
00143       new CouenneBranchingObject (si, this, jnlst_, cutGen_, problem_, reference_, 
00144                                   way, bestPt, doFBBT_, doConvCuts_);
00145   }
00146 
00147   problem_ -> domain () -> pop ();
00148 
00149   return obj;
00150 }
00151 
00152 
00154 CouNumber CouenneVarObject::computeBranchingPoint (const OsiBranchingInformation *info,
00155                                                    int& bestWay,
00156                                                    const CouenneObject *&criticalObject) const {
00157   criticalObject = NULL;
00158 
00159   if (jnlst_ -> ProduceOutput (J_DETAILED, J_BRANCHING)) {
00160     printf ( "---------- computeBRPT for "); 
00161     reference_ -> print (); 
00162     printf (" [%g,%g]\n", 
00163             info -> lower_ [reference_ -> Index ()],
00164             info -> upper_ [reference_ -> Index ()]);
00165   }
00166 
00167   expression *brVar = NULL; // branching variable
00168 
00169   CouNumber
00170     brdistDn = 0.,
00171     brdistUp = 0.,
00172     bestPt   = 0.,
00173    *brPts    = NULL, // branching point(s)
00174    *brDist   = NULL, // distances from LP point to each new convexification
00175     maxdist  = - COIN_DBL_MAX;
00176 
00177   bool chosen = false;
00178 
00179   bestWay = TWO_LEFT;
00180 
00181   int 
00182     whichWay = TWO_LEFT,
00183     index    = reference_ -> Index ();
00184 
00185   std::set <int> deplist = problem_ -> Dependence () [index];
00186 
00187   for (std::set <int>::iterator i = deplist.begin (); i != deplist.end (); ++i) {
00188 
00189     const CouenneObject *obj = problem_ -> Objects () [*i];
00190 
00191     CouNumber improv = 0.;
00192 
00193     assert (obj -> Reference ());
00194 
00195     if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00196       printf ("  dependence: "); 
00197       obj -> Reference () -> print (); 
00198       if (reference_ -> Image ()) {printf (" := "); obj -> Reference () -> Image () -> print ();}
00199       printf ("\n");
00200     }
00201 
00202     if (obj -> Reference ()) {
00203       if (obj -> Reference () -> Image ())
00204 
00205         improv = obj -> Reference () -> Image ()
00206           -> selectBranch (obj, info,                       // input parameters
00207                            brVar, brPts, brDist, whichWay); // result: who, where, distances, direction
00208       else {
00209 
00210         brVar = obj -> Reference ();
00211         brPts  = (double *) realloc (brPts,      sizeof (double)); 
00212         brDist = (double *) realloc (brDist, 2 * sizeof (double)); 
00213 
00214         double point = info -> solution_ [obj -> Reference () -> Index ()];
00215 
00216         *brPts = point;
00217         improv = 0.;
00218 
00219         if (point > floor (point)) {improv =                  brDist [0] = point - floor (point);}
00220         if (point < ceil  (point)) {improv = CoinMin (improv, brDist [1] = ceil (point) - point);}
00221 
00222         point -= floor (point);
00223         whichWay = (point < 0.45) ? TWO_LEFT : (point > 0.55) ? TWO_RIGHT : TWO_RAND;
00224       }
00225     }
00226 
00227     if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00228       printf ("  --> Branching on "); 
00229       if (brVar) {
00230         brVar -> print (); 
00231         if (brPts) 
00232           printf (" at %g, improv %g <%g>, indices = %d,%d\n", 
00233                   *brPts, improv, maxdist, index, brVar -> Index ());
00234       }
00235     }
00236 
00237     if (brVar &&
00238         (brVar -> Index () == index) &&    // it's us!
00239         (fabs (improv) > maxdist) &&       // this branching seems to induce a higher improvement
00240         (fabs (*brPts) < COU_MAX_COEFF)) { // and branching pt is limited
00241 
00242       criticalObject = (problem_ -> Objects () [*i]); // set this object as the branch creator
00243 
00244       brdistDn = brDist [0];
00245       brdistUp = brDist [1];
00246       chosen = true;
00247       bestPt = *brPts;
00248       maxdist = improv;
00249       bestWay = whichWay;
00250     }
00251   }
00252 
00253   // no hits on this VarObject's variable, that is, this variable was
00254   // never chosen 
00255 
00256   if (!chosen) {
00257 
00258     bestPt = info -> solution_ [index];
00259     brVar  = reference_;
00260 
00261     CouNumber 
00262       l     = info -> lower_ [index], 
00263       u     = info -> upper_ [index],
00264       width = lp_clamp_ * (u-l);
00265 
00266     switch (strategy_) {
00267 
00268     case CouenneObject::LP_CLAMPED:
00269       bestPt = CoinMax (l + width, CoinMin (bestPt, u - width));
00270       break;
00271 
00272     case CouenneObject::LP_CENTRAL: 
00273       if ((bestPt < l + width) || (bestPt > u - width))
00274         bestPt = (l+u)/2;
00275       break;
00276 
00277     case CouenneObject::MID_INTERVAL: 
00278 
00279     default: 
00280       // all other cases (balanced, min-area)
00281       bestPt = midInterval (bestPt, l, u, info);
00282 
00283       if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00284         if (CoinMin (fabs (bestPt - l), fabs (bestPt - u)) < 1e-3) {
00285           printf ("computed failsafe %g [%g,%g] for ", bestPt, l,u);
00286           reference_ -> print (); printf ("\n");
00287         }
00288       }
00289 
00290       break;
00291     }
00292 
00293     if ((l < - large_bound) && 
00294         (u >   large_bound) &&
00295         (fabs (bestPt) > large_bound))
00296       bestPt = 0.;
00297 
00298     brPts  = (double *) realloc (brPts, sizeof (double));
00299     *brPts = bestPt;
00300 
00301     if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00302       printf ("  ::: failsafe:  %g [%g,%g] for ", 
00303               bestPt, info -> lower_ [index], info -> upper_ [index]); 
00304       reference_ -> print ();
00305       printf ("\n");
00306     }
00307 
00308   } else {
00309 
00310     if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00311       if (CoinMin (fabs (bestPt - info -> lower_ [index]), 
00312                    fabs (bestPt - info -> upper_ [index])) < 1e-3) {
00313         printf ("  computed %g [%g,%g] for ", 
00314                 bestPt, info -> lower_ [index], info -> upper_ [index]); 
00315         reference_ -> print ();
00316         printf ("\n");
00317       }
00318     }
00319   }
00320 
00321   if (pseudoMultType_ == PROJECTDIST) {
00322 
00323     if (chosen) {
00324       downEstimate_ = brdistDn;
00325       upEstimate_   = brdistUp;
00326     } 
00327     else downEstimate_ = upEstimate_ = 1.;
00328   }
00329 
00330   if (brPts)  free (brPts);
00331   if (brDist) free (brDist);
00332 
00333   return bestPt;
00334 }
00335 
00336 
00337 #define TOL 0.
00338 
00340 double CouenneVarObject::feasibleRegion (OsiSolverInterface *solver, 
00341                                          const OsiBranchingInformation *info) const {
00342   int index = reference_ -> Index ();
00343 
00344   assert (index >= 0);
00345 
00346   double val = info -> solution_ [index];
00347 
00348   // fix that variable to its current value
00349   solver -> setColLower (index, val-TOL);
00350   solver -> setColUpper (index, val+TOL);
00351 
00352   return 0.;
00353 }
00354 
00355 
00357 bool CouenneVarObject::isCuttable () const {
00358 
00359   const std::set <int>                &deplist = problem_ -> Dependence () [reference_ -> Index ()];
00360   const std::vector <CouenneObject *> &objects = problem_ -> Objects ();
00361 
00362   for (std::set <int>::const_iterator depvar = deplist. begin ();
00363        depvar != deplist. end (); ++depvar)
00364     if (!(objects [*depvar] -> isCuttable ()))
00365       return false;
00366 
00367   return (!(reference_ -> isInteger ()));
00368 }
00369 

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