/home/coin/SVN-release/OS-2.4.0/Couenne/src/branch/CouenneBranchingObject.cpp

Go to the documentation of this file.
00001 /* $Id: CouenneBranchingObject.cpp 738 2011-07-10 17:38:58Z pbelotti $
00002  *
00003  * Name:    CouenneBranchingObject.cpp
00004  * Authors: Pierre Bonami, IBM Corp.
00005  *          Pietro Belotti, Carnegie Mellon University
00006  * Purpose: Branching object for auxiliary variables
00007  *
00008  * (C) Carnegie-Mellon University, 2006-11.
00009  * This file is licensed under the Eclipse Public License (EPL)
00010  */
00011 
00012 #include "CoinHelperFunctions.hpp"
00013 
00014 #include "OsiRowCut.hpp"
00015 
00016 #include "CouenneCutGenerator.hpp"
00017 
00018 #include "CouenneProblem.hpp"
00019 #include "CouenneProblemElem.hpp"
00020 #include "CouenneObject.hpp"
00021 #include "CouenneBranchingObject.hpp"
00022 
00023 using namespace Ipopt;
00024 using namespace Couenne;
00025 
00026 // translate changed bound sparse array into a dense one
00027 void sparse2dense (int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged);
00028 
00035 CouenneBranchingObject::CouenneBranchingObject (OsiSolverInterface *solver,
00036                                                 const OsiObject * originalObject,
00037                                                 JnlstPtr jnlst, 
00038                                                 CouenneCutGenerator *cutGen,
00039                                                 CouenneProblem *problem,
00040                                                 expression *var, 
00041                                                 int way, 
00042                                                 CouNumber brpoint, 
00043                                                 bool doFBBT, bool doConvCuts):
00044 
00045   OsiTwoWayBranchingObject (solver, originalObject, way, brpoint),
00046 
00047   cutGen_       (cutGen),
00048   problem_      (problem),
00049   variable_     (var),
00050   jnlst_        (jnlst),
00051   doFBBT_       (doFBBT),
00052   doConvCuts_   (doConvCuts),
00053   downEstimate_ (0.),
00054   upEstimate_   (0.),
00055   simulate_     (false) {
00056 
00057   // This two-way branching rule is only applied when both lower and
00058   // upper bound are finite. Otherwise, a CouenneThreeWayBranchObj is
00059   // used (see CouenneThreeWayBranchObj.hpp).
00060   //
00061   // The rule is as follows:
00062   //
00063   // - if x is well inside the interval (both bounds are infinite or
00064   // there is a difference of at least COU_NEAR_BOUND), set
00065   // value_ to x;
00066   //
00067   // - otherwise, try to get far from bounds by setting value_ to a
00068   // convex combination of current and midpoint
00069   //
00070   // TODO: consider branching value that maximizes distance from
00071   // current point (how?)
00072 
00073   CouNumber lb, ub;
00074 
00075   variable_ -> getBounds (lb, ub);
00076 
00077   // bounds may have tightened and may exclude value_ now, update it
00078 
00079   value_ = (fabs (brpoint) < large_bound) ? brpoint : (*variable_) ();
00080 
00081   if   (lb < -large_bound)
00082     if (ub >  large_bound) value_ = 0.;                                                   // ]-inf,+inf[
00083     else                   value_ = ((value_ < -COUENNE_EPS) ? (AGGR_MUL * (-1+value_)) : // ]-inf,u]
00084                                      (value_ >  COUENNE_EPS) ? 0. : -AGGR_MUL);
00085   else
00086     if (ub >  large_bound) value_ = ((value_ >  COUENNE_EPS) ? (AGGR_MUL *  (1+value_)) : // [l,+inf[
00087                                      (value_ < -COUENNE_EPS) ? 0. :  AGGR_MUL);
00088     else {                                                                                // [l,u]
00089       double margin = fabs (ub-lb) * closeToBounds;
00090       if      (value_ < lb + margin) value_ = lb + margin;
00091       else if (value_ > ub - margin) value_ = ub - margin;
00092     }
00093 
00094   jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, 
00095                     "Branch: x%-3d will branch on %g (cur. %g) [%g,%g]; firstBranch_ = %d\n", 
00096                     variable_ -> Index (), value_, (*variable_) (), lb, ub, firstBranch_);
00097 }
00098 
00099 
00107 double CouenneBranchingObject::branch (OsiSolverInterface * solver) {
00108 
00109   jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, 
00110                     "::branch: at %.20e\n", value_);
00111 
00112   // way = 0 if "<=" node, 
00113   //       1 if ">=" node
00114 
00115   int 
00116     way   = (!branchIndex_) ? firstBranch_ : !firstBranch_,
00117     index = variable_ -> Index ();
00118 
00119   bool 
00120     integer    = variable_ -> isInteger (),
00121     infeasible = false;
00122 
00123   CouNumber
00124     l      = solver -> getColLower () [index],
00125     u      = solver -> getColUpper () [index],
00126     brpt   = value_;
00127 
00128   if      (brpt < l) brpt = l;
00129   else if (brpt > u) brpt = u;
00130 
00131   // anticipate test on bounds w.r.t. test on integrality.
00132 
00133   if   (l <  -large_bound) {
00134     if (u <=  large_bound) // ]-inf,u]
00135       brpt = ((u < -COUENNE_EPS) ? CoinMax (CoinMax (brpt, .5 * (l+u)), AGGR_MUL * (-1. + brpt)) : 
00136               (u >  COUENNE_EPS) ? 0.                                                            : -AGGR_MUL);
00137     else brpt = 0.;
00138   } else
00139     if (u >  large_bound) // [l,+inf[
00140       brpt = ((l >  COUENNE_EPS) ? CoinMin (CoinMin (brpt, .5 * (l+u)), AGGR_MUL * ( 1. + brpt)) : 
00141               (l < -COUENNE_EPS) ? 0.                                                            :  AGGR_MUL);
00142     else {                // [l,u] (finite)
00143 
00144       CouNumber point = default_alpha * brpt + (1. - default_alpha) * (l + u) / 2.;
00145 
00146       if      ((point-l) / (u-l) < closeToBounds) brpt = l + (u-l) * closeToBounds;
00147       else if ((u-point) / (u-l) < closeToBounds) brpt = u + (l-u) * closeToBounds;
00148       else                                        brpt = point;
00149     }
00150 
00151   // If brpt is integer and the variable is constrained to be integer,
00152   // there will be a valid but weak branching. Modify brpt depending
00153   // on way and on the bounds on the variable, so that the usual
00154   // integer branching will be performed.
00155 
00156   if (integer && 
00157       ::isInteger (brpt)) {
00158 
00159     // Look at all possible cases (l,u are bounds, b is the branching
00160     // point. l,u,b all integer):
00161     //
00162     // 1) l <  b <  u: first branch on b +/- 1 depending on branch
00163     // direction, right branch on b;
00164     //
00165     // 2) l <= b <  u: LEFT branch on b, RIGHT branch on b+1
00166     // 
00167     // 3) l <  b <= u: LEFT branch on b-1, RIGHT branch on b
00168 
00169     // assert ((brpt - l > .5) || 
00170     //      (u - brpt > .5));
00171 
00172     if ((brpt - l > .5) &&
00173         (u - brpt > .5)) {// brpt is integer interior point of [l,u]
00174 
00175       if (!branchIndex_) { // if this is the first branch operation
00176         if (!way) brpt -= (1. - COUENNE_EPS);
00177         else      brpt += (1. - COUENNE_EPS);
00178       }
00179       else { // adjust brpt so that interval covers integer value
00180              // necessary for nvs13.nl 
00181         if (!way) brpt += COUENNE_EPS;
00182         else      brpt -= COUENNE_EPS;
00183       }
00184     } 
00185     else {
00186       if (u - brpt > .5) {
00187         if (way) {
00188           brpt += (1. - COUENNE_EPS);
00189         }
00190         else { // adjust brpt so that interval covers integer value
00191           brpt += COUENNE_EPS;
00192         }
00193       }
00194       else { 
00195         if (brpt - l > .5) {
00196           if (!way) {
00197             brpt -= (1. - COUENNE_EPS);
00198           }
00199           else { // adjust brpt so that interval covers integer value
00200             brpt -= COUENNE_EPS;
00201           }
00202         }
00203         else { // u == l == brpt; must still branch to fix variables in object
00204           // but one branch is infeasible
00205           if(way) {
00206             solver->setColLower(index, u+1); // infeasible
00207           }
00208         }
00209       }
00210     }
00211   }
00212 
00213   jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "Branching: x%-3d %c= %.20e\n", 
00214                     index, way ? '>' : '<', integer ? (way ? ceil (brpt) : floor (brpt)) : brpt);
00215 
00216   if (way) {
00217     if      (brpt < l)             jnlst_->Printf (J_STRONGWARNING, J_BRANCHING, "Nonsense up-br: [ %.8f ,(%.8f)] -> %.8f\n",l,u,value_);
00218     else if (brpt < l+COUENNE_EPS) jnlst_->Printf (J_STRONGWARNING, J_BRANCHING, "## WEAK  up-br: [ %.8f ,(%.8f)] -> %.8f\n",l,u,value_);
00219   } else {
00220     if      (brpt > u)             jnlst_->Printf (J_STRONGWARNING, J_BRANCHING, "Nonsense dn-br: [(%.8f), %.8f ] -> %.8f\n",l,u,value_);
00221     else if (brpt > u-COUENNE_EPS) jnlst_->Printf (J_STRONGWARNING, J_BRANCHING, "## WEAK  dn-br: [(%.8f), %.8f ] -> %.8f\n",l,u,value_);
00222   }
00223 
00224   /*
00225   double time = CoinCpuTime ();
00226   jnlst_ -> Printf (J_VECTOR, J_BRANCHING,"[vbctool] %02d:%02d:%02d.%02d_I x%d%c=%g_[%g,%g]\n",
00227                     (int) (floor(time) / 3600), 
00228                     (int) (floor(time) / 60) % 60, 
00229                     (int) floor(time) % 60, 
00230                     (int) ((time - floor (time)) * 100),
00231                     index, way ? '>' : '<', integer ? ((way ? ceil (brpt): floor (brpt))) : brpt,
00232                     solver -> getColLower () [index],
00233                     solver -> getColUpper () [index]);
00234   */
00235 
00236   t_chg_bounds *chg_bds = NULL;
00237 
00238   // Apply core branching decision (usually new variable bound)
00239 
00240   branchCore (solver, index, way, integer, brpt, chg_bds);
00241 
00242   //CouenneSolverInterface *couenneSolver = dynamic_cast <CouenneSolverInterface *> (solver);
00243   //CouenneProblem *p = cutGen_ -> Problem ();
00244   //couenneSolver -> CutGen () -> Problem ();
00245 
00246   int 
00247     nvars  = problem_ -> nVars (),
00248     objind = problem_ -> Obj (0) -> Body () -> Index ();
00249 
00250   //CouNumber &estimate = way ? upEstimate_ : downEstimate_;
00251   CouNumber estimate = 0.;//way ? upEstimate_ : downEstimate_;
00252 
00253   if ((doFBBT_ && problem_ -> doFBBT ()) ||
00254       (doConvCuts_ && simulate_ && cutGen_)) {
00255 
00256     problem_ -> domain () -> push (solver); // have to alloc+copy
00257 
00258     if (            doFBBT_ &&           // this branching object should do FBBT, and
00259         problem_ -> doFBBT ()) {         // problem allowed to do FBBT
00260 
00261       problem_ -> installCutOff ();
00262 
00263       if (!problem_ -> btCore (chg_bds)) // done FBBT and this branch is infeasible
00264         infeasible = true;               // ==> report it
00265 
00266       else {
00267 
00268         const double
00269           *lb = solver -> getColLower (),
00270           *ub = solver -> getColUpper ();
00271 
00272         //CouNumber newEst = problem_ -> Lb (objind) - lb [objind];
00273         estimate = CoinMax (0., problem_ -> Lb (objind) - lb [objind]);
00274 
00275         for (int i=0; i<nvars; i++) {
00276           if (problem_ -> Lb (i) > lb [i]) solver -> setColLower (i, problem_ -> Lb (i));
00277           if (problem_ -> Ub (i) < ub [i]) solver -> setColUpper (i, problem_ -> Ub (i));
00278         }
00279       }
00280     }
00281 
00282     if (!infeasible && doConvCuts_ && simulate_ && cutGen_) { 
00283 
00284       // generate convexification cuts before solving new node's LP
00285       int nchanged, *changed = NULL;
00286       OsiCuts cs;
00287 
00288       // sparsify structure with info on changed bounds and get convexification cuts
00289       sparse2dense (nvars, chg_bds, changed, nchanged);
00290       cutGen_ -> genRowCuts (*solver, cs, nchanged, changed, chg_bds);
00291       free (changed);
00292 
00293       solver -> applyCuts (cs);
00294     }
00295 
00296     //delete [] chg_bds;
00297 
00298     problem_ -> domain () -> pop ();
00299   }
00300 
00301   if (chg_bds) delete [] chg_bds;
00302 
00303   // next time do other branching
00304   branchIndex_++;
00305 
00306   return (infeasible ? COIN_DBL_MAX : estimate); // estimated change in objective function
00307 }

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