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

Go to the documentation of this file.
00001 /* $Id: CouenneVarObject.cpp 259 2009-10-04 14:20:13Z 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-09.
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 #include "CoinHelperFunctions.hpp"
00012 
00013 #include "CouenneProblem.hpp"
00014 #include "CouenneVarObject.hpp"
00015 #include "CouenneBranchingObject.hpp"
00016 #include "CouenneComplObject.hpp"
00017 
00019 CouenneVarObject::CouenneVarObject (CouenneCutGenerator *c,
00020                                     CouenneProblem *p,
00021                                     exprVar *ref, 
00022                                     Bonmin::BabSetupBase *base, 
00023                                     JnlstPtr jnlst):
00024 
00025   // Do not set variable (expression).
00026   // This way, no expression-dependent strategy is chosen
00027   CouenneObject (c, p, ref, base, jnlst) {
00028 
00029   if (jnlst_ -> ProduceOutput (J_SUMMARY, J_BRANCHING)) {
00030     printf ("created Variable Object: "); 
00031     reference_ -> print (); 
00032     printf (" with %s strategy [clamp=%g, alpha=%g]\n", 
00033             (strategy_ == LP_CLAMPED)   ? "lp-clamped" : 
00034             (strategy_ == LP_CENTRAL)   ? "lp-central" : 
00035             (strategy_ == BALANCED)     ? "balanced"   : 
00036             (strategy_ == MIN_AREA)     ? "min-area"   : 
00037             (strategy_ == MID_INTERVAL) ? "mid-point"  : 
00038             (strategy_ == NO_BRANCH)    ? "no-branching (null infeasibility)" : 
00039                                           "no strategy",
00040             lp_clamp_, alpha_);
00041   }
00042 }
00043 
00044 
00046 OsiBranchingObject *CouenneVarObject::createBranch (OsiSolverInterface *si, 
00047                                                     const OsiBranchingInformation *info, 
00048                                                     int way) const {
00049 
00050   // The infeasibility on an (independent) variable x_i is given by
00051   // something more elaborate than |w-f(x)|, that is, a function of
00052   // all infeasibilities of all expressions which depend on x_i.
00053 
00054   problem_ -> domain () -> push 
00055     (problem_ -> nVars (),
00056      info -> solution_,
00057      info -> lower_,
00058      info -> upper_); // have to alloc+copy
00059 
00060   int bestWay;
00061   const CouenneObject *criticalObject = NULL; // should create the branchingObject
00062 
00063   CouNumber bestPt = computeBranchingPoint (info, bestWay, criticalObject);
00064 
00066 
00067   jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, ":::: creating branching on x_%d @%g [%g,%g]\n", 
00068           reference_ -> Index (), 
00069           info -> solution_ [reference_ -> Index ()],
00070           info -> lower_    [reference_ -> Index ()],
00071           info -> upper_    [reference_ -> Index ()]);
00072 
00073   OsiBranchingObject *brObj = criticalObject ? 
00074     criticalObject -> createBranch (si, info, way) :
00075     new CouenneBranchingObject (si, this, jnlst_, cutGen_, problem_, reference_, 
00076                                 way, bestPt, doFBBT_, doConvCuts_);
00077 
00078   problem_ -> domain () -> pop ();
00079 
00080   return brObj;
00081 }
00082 
00083 
00085 CouNumber CouenneVarObject::computeBranchingPoint(const OsiBranchingInformation *info,
00086                                                   int& bestWay,
00087                                                   const CouenneObject *&criticalObject) const {
00088   criticalObject = NULL;
00089 
00090   if (jnlst_ -> ProduceOutput (J_DETAILED, J_BRANCHING)) {
00091     printf ( "---------- computeBRPT for "); 
00092     reference_ -> print (); 
00093     printf (" [%g,%g]\n", 
00094             info -> lower_ [reference_ -> Index ()],
00095             info -> upper_ [reference_ -> Index ()]);
00096   }
00097 
00098   expression *brVar = NULL; // branching variable
00099 
00100   CouNumber
00101     brdistDn = 0.,
00102     brdistUp = 0.,
00103     bestPt   = 0.,
00104    *brPts    = NULL, // branching point(s)
00105    *brDist   = NULL, // distances from LP point to each new convexification
00106     maxdist = - COIN_DBL_MAX;
00107 
00108   bool chosen = false;
00109 
00110   bestWay = TWO_LEFT;
00111   int whichWay = TWO_LEFT,
00112     index = reference_ -> Index ();
00113 
00114   std::set <int> deplist = problem_ -> Dependence () [index];
00115 
00116   for (std::set <int>::iterator i = deplist.begin (); i != deplist.end (); ++i) {
00117 
00118     const CouenneObject *obj = problem_ -> Objects () [*i];
00119 
00120     CouNumber improv = 0.;
00121 
00122     assert (obj -> Reference ());
00123 
00124     if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00125       printf ("  ** "); 
00126       obj -> Reference () -> print (); 
00127       if (reference_ -> Image ()) {printf (" := "); obj -> Reference () -> Image () -> print ();}
00128       printf ("\n");
00129     }
00130 
00131     if (obj -> Reference ()) {
00132       if (obj -> Reference () -> Image ())
00133         improv = obj -> Reference () -> Image ()
00134           -> selectBranch (obj, info,                      // input parameters
00135                            brVar, brPts, brDist, whichWay); // result: who, where, distances, direction
00136       else {
00137         brVar = obj -> Reference ();
00138         brPts  = (double *) realloc (brPts, sizeof (double)); 
00139         brDist = (double *) realloc (brDist, 2 * sizeof (double)); 
00140 
00141         double point = info -> solution_ [obj -> Reference () -> Index ()];
00142 
00143         *brPts = point;
00144         improv = 0.;
00145 
00146         if (point > floor (point)) {improv =                  brDist [0] = point - floor (point);}
00147         if (point < ceil  (point)) {improv = CoinMin (improv, brDist [1] = ceil (point) - point);}
00148 
00149         point -= floor (point);
00150         whichWay = (point < 0.45) ? TWO_LEFT : (point > 0.55) ? TWO_RIGHT : TWO_RAND;
00151       }
00152     }
00153 
00154     if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00155       printf ("  --> "); 
00156       if (brVar) {
00157         brVar -> print (); 
00158         if (brPts) 
00159           printf (" at %g, improv %g <%g>, indices = %d,%d\n", 
00160                   *brPts, improv, maxdist, index, brVar -> Index ());
00161       }
00162     }
00163 
00164     if (brVar &&
00165         (brVar -> Index () == index) &&    // it's us!
00166         (fabs (improv) > maxdist) &&       // this branching seems to induce a higher improvement
00167         (fabs (*brPts) < COU_MAX_COEFF)) { // and branching pt is limited
00168 
00169       criticalObject = (problem_ -> Objects () [*i]); // set this object as the branch creator
00170 
00171       brdistDn = brDist [0];
00172       brdistUp = brDist [1];
00173       chosen = true;
00174       bestPt = *brPts;
00175       maxdist = improv;
00176       bestWay = whichWay;
00177     }
00178   }
00179 
00180   // no hits on this VarObject's variable, that is, this variable was
00181   // never chosen 
00182 
00183   if (!chosen) {
00184 
00185     bestPt = info -> solution_ [index];
00186     brVar  = reference_;
00187 
00188     CouNumber 
00189       l     = info -> lower_ [index], 
00190       u     = info -> upper_ [index],
00191       width = lp_clamp_ * (u-l);
00192 
00193     switch (strategy_) {
00194 
00195     case CouenneObject::LP_CLAMPED:
00196       bestPt = CoinMax (l + width, CoinMin (bestPt, u - width));
00197       break;
00198     case CouenneObject::LP_CENTRAL: 
00199       if ((bestPt < l + width) || (bestPt > u - width))
00200         bestPt = (l+u)/2;
00201       break;
00202     case CouenneObject::MID_INTERVAL: 
00203     default: 
00204       // all other cases (balanced, min-area)
00205       bestPt = midInterval (bestPt, l, u);
00206 
00207       if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00208         if (CoinMin (fabs (bestPt - l), fabs (bestPt - u)) < 1e-3) {
00209           printf ("computed failsafe %g [%g,%g] for ", bestPt, l,u);
00210           reference_ -> print (); printf ("\n");
00211         }
00212       }
00213       break;
00214     }
00215 
00216     brPts  = (double *) realloc (brPts, sizeof (double));
00217     *brPts = bestPt;
00218 
00219       if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00220         printf ("  ::: failsafe:  %g [%g,%g] for ", 
00221                 bestPt, info -> lower_ [index], info -> upper_ [index]); 
00222         reference_ -> print ();
00223         printf ("\n");
00224       }
00225 
00226   } else {
00227 
00228       if (jnlst_ -> ProduceOutput (J_MATRIX, J_BRANCHING)) {
00229         if (CoinMin (fabs (bestPt - info -> lower_ [index]), 
00230                      fabs (bestPt - info -> upper_ [index])) < 1e-3) {
00231           printf ("  computed %g [%g,%g] for ", 
00232                   bestPt, info -> lower_ [index], info -> upper_ [index]); 
00233           reference_ -> print ();
00234           printf ("\n");
00235         }
00236       }
00237   }
00238 
00239   if (pseudoMultType_ == PROJECTDIST) {
00240 
00241     if (chosen) {
00242       downEstimate_ = brdistDn;
00243       upEstimate_   = brdistUp;
00244     } 
00245     else downEstimate_ = upEstimate_ = 1.;
00246   }
00247 
00248   if (brPts)  free (brPts);
00249   if (brDist) free (brDist);
00250 
00251   return bestPt;
00252 }
00253 
00254 
00255 #define TOL 0.
00256 
00258 double CouenneVarObject::feasibleRegion (OsiSolverInterface *solver, 
00259                                          const OsiBranchingInformation *info) const {
00260   int index = reference_ -> Index ();
00261 
00262   assert (index >= 0);
00263 
00264   double val = info -> solution_ [index];
00265 
00266   // fix that variable to its current value
00267   solver -> setColLower (index, val-TOL);
00268   solver -> setColUpper (index, val+TOL);
00269 
00270   return 0.;
00271 }
00272 
00273 
00275 bool CouenneVarObject::isCuttable () const {
00276 
00277   const std::set <int>                &deplist = problem_ -> Dependence () [reference_ -> Index ()];
00278   const std::vector <CouenneObject *> &objects = problem_ -> Objects ();
00279 
00280   for (std::set <int>::const_iterator depvar = deplist. begin ();
00281        depvar != deplist. end (); ++depvar)
00282     if (!(objects [*depvar] -> isCuttable ()))
00283       return false;
00284 
00285   return (!(reference_ -> isInteger ()));
00286 }
00287 

Generated on Mon May 3 03:05:18 2010 by  doxygen 1.4.7