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

Go to the documentation of this file.
00001 /* $Id: CouenneBranchingObject.cpp 259 2009-10-04 14:20:13Z 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-09.
00009  * This file is licensed under the Common Public License (CPL)
00010  */
00011 
00012 #include "CoinHelperFunctions.hpp"
00013 
00014 #include "OsiRowCut.hpp"
00015 
00016 //#include "CouenneSolverInterface.hpp"
00017 #include "CouenneProblem.hpp"
00018 #include "CouenneObject.hpp"
00019 #include "CouenneBranchingObject.hpp"
00020 #include "CouenneCutGenerator.hpp"
00021 
00022 class CouenneCutGenerator;
00023 
00024 // translate changed bound sparse array into a dense one
00025 void sparse2dense (int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged);
00026 
00027 
00034 CouenneBranchingObject::CouenneBranchingObject (OsiSolverInterface *solver,
00035                                                 const OsiObject * originalObject,
00036                                                 JnlstPtr jnlst, 
00037                                                 CouenneCutGenerator *cutGen,
00038                                                 CouenneProblem *problem,
00039                                                 expression *var, 
00040                                                 int way, 
00041                                                 CouNumber brpoint, 
00042                                                 bool doFBBT, bool doConvCuts):
00043 
00044   OsiTwoWayBranchingObject (solver, originalObject, way, brpoint),
00045   cutGen_       (cutGen),
00046   problem_      (problem),
00047   variable_     (var),
00048   jnlst_        (jnlst),
00049   doFBBT_       (doFBBT),
00050   doConvCuts_   (doConvCuts),
00051   downEstimate_ (0.),
00052   upEstimate_   (0.),
00053   simulate_     (false) {
00054 
00055   // This two-way branching rule is only applied when both lower and
00056   // upper bound are finite. Otherwise, a CouenneThreeWayBranchObj is
00057   // used (see CouenneThreeWayBranchObj.hpp).
00058   //
00059   // The rule is as follows:
00060   //
00061   // - if x is well inside the interval (both bounds are infinite or
00062   // there is a difference of at least COU_NEAR_BOUND), set
00063   // value_ to x;
00064   //
00065   // - otherwise, try to get far from bounds by setting value_ to a
00066   // convex combination of current and midpoint
00067   //
00068   // TODO: consider branching value that maximizes distance from
00069   // current point (how?)
00070 
00071   value_ = (*variable_) ();
00072 
00073   if (fabs (brpoint) < COUENNE_INFINITY) 
00074     value_ = brpoint;
00075 
00076   CouNumber lb, ub;
00077   var -> getBounds (lb, ub);
00078 
00079   // do not branch too close to bounds
00080   if ((lb > -COUENNE_INFINITY) && (ub < COUENNE_INFINITY)) {
00081     if      ((value_ - lb) / (ub-lb) < closeToBounds) value_ = lb + (ub-lb) * closeToBounds;
00082     else if ((ub - value_) / (ub-lb) < closeToBounds) value_ = ub + (lb-ub) * closeToBounds;
00083   }
00084 
00085   jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, 
00086                     "Branch: x%-3d will branch on %g (cur. %g) [%g,%g]; firstBranch_ = %d\n", 
00087                     variable_ -> Index (), value_, (*variable_) (), lb, ub, firstBranch_);
00088 }
00089 
00090 
00098 double CouenneBranchingObject::branch (OsiSolverInterface * solver) {
00099 
00100   // way = 0 if "<=" node, 
00101   //       1 if ">=" node
00102 
00103   int 
00104     way   = (!branchIndex_) ? firstBranch_ : !firstBranch_,
00105     index = variable_ -> Index ();
00106 
00107   bool 
00108     integer    = variable_ -> isInteger (),
00109     infeasible = false;
00110 
00111   CouNumber
00112     l      = solver -> getColLower () [index],
00113     u      = solver -> getColUpper () [index],
00114     brpt   = value_;
00115 
00116   if (way) {
00117     if      (value_ < l)             
00118       jnlst_->Printf(J_STRONGWARNING, J_BRANCHING, "Nonsense up-br: [ %.8f ,(%.8f)] -> %.8f\n",l,u,value_);
00119     else if (value_ < l+COUENNE_EPS) 
00120       jnlst_->Printf(J_STRONGWARNING, J_BRANCHING, "## WEAK  up-br: [ %.8f ,(%.8f)] -> %.8f\n",l,u,value_);
00121   } else {
00122     if      (value_ > u)             
00123       jnlst_->Printf(J_STRONGWARNING, J_BRANCHING, "Nonsense dn-br: [(%.8f), %.8f ] -> %.8f\n",l,u,value_);
00124     else if (value_ > u+COUENNE_EPS) 
00125       jnlst_->Printf(J_STRONGWARNING, J_BRANCHING, "## WEAK  dn-br: [(%.8f), %.8f ] -> %.8f\n",l,u,value_);
00126   }
00127 
00128   if ((brpt < l) || (brpt > u))
00129     brpt = 0.5 * (l+u);
00130 
00131   jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "Branching: x%-3d %c= %g\n", 
00132                     //printf ("Branching: x%-3d %c= %g\n", 
00133                     index, way ? '>' : '<', integer ? (way ? ceil (brpt) : floor (brpt)) : brpt);
00134 
00135   /*
00136   double time = CoinCpuTime ();
00137   jnlst_ -> Printf (J_VECTOR, J_BRANCHING,"[vbctool] %02d:%02d:%02d.%02d_I x%d%c=%g_[%g,%g]\n",
00138                     (int) (floor(time) / 3600), 
00139                     (int) (floor(time) / 60) % 60, 
00140                     (int) floor(time) % 60, 
00141                     (int) ((time - floor (time)) * 100),
00142                     index, way ? '>' : '<', integer ? ((way ? ceil (brpt): floor (brpt))) : brpt,
00143                     solver -> getColLower () [index],
00144                     solver -> getColUpper () [index]);
00145   */
00146 
00147   if (!way) solver -> setColUpper (index, integer ? floor (brpt) : brpt); // down branch
00148   else      solver -> setColLower (index, integer ? ceil  (brpt) : brpt); // up   branch
00149 
00150   //CouenneSolverInterface *couenneSolver = dynamic_cast <CouenneSolverInterface *> (solver);
00151   //CouenneProblem *p = cutGen_ -> Problem ();
00152   //couenneSolver -> CutGen () -> Problem ();
00153 
00154   int 
00155     nvars  = problem_ -> nVars (),
00156     objind = problem_ -> Obj (0) -> Body () -> Index ();
00157 
00158   //CouNumber &estimate = way ? upEstimate_ : downEstimate_;
00159   CouNumber estimate = 0.;//way ? upEstimate_ : downEstimate_;
00160 
00161   if ((doFBBT_ && problem_ -> doFBBT ()) ||
00162       (doConvCuts_ && simulate_ && cutGen_)) {
00163 
00164     problem_ -> domain () -> push (nvars,
00165                                    solver -> getColSolution (), 
00166                                    solver -> getColLower    (), 
00167                                    solver -> getColUpper    ()); // have to alloc+copy
00168 
00169     t_chg_bounds *chg_bds = new t_chg_bounds [nvars];
00170 
00171     if (!way) chg_bds [index].setUpper (t_chg_bounds::CHANGED);
00172     else      chg_bds [index].setLower (t_chg_bounds::CHANGED);
00173 
00174     if (            doFBBT_ &&           // this branching object should do FBBT, and
00175         problem_ -> doFBBT ()) {         // problem allowed to do FBBT
00176 
00177       problem_ -> installCutOff ();
00178 
00179       if (!problem_ -> btCore (chg_bds)) // done FBBT and this branch is infeasible
00180         infeasible = true;        // ==> report it
00181       else {
00182 
00183         const double
00184           *lb = solver -> getColLower (),
00185           *ub = solver -> getColUpper ();
00186 
00187         //CouNumber newEst = problem_ -> Lb (objind) - lb [objind];
00188         estimate = CoinMax (0., problem_ -> Lb (objind) - lb [objind]);
00189 
00190         //if (newEst > estimate) 
00191         //estimate = newEst;
00192 
00193         for (int i=0; i<nvars; i++) {
00194           if (problem_ -> Lb (i) > lb [i]) solver -> setColLower (i, problem_ -> Lb (i));
00195           if (problem_ -> Ub (i) < ub [i]) solver -> setColUpper (i, problem_ -> Ub (i));
00196         }
00197       }
00198     }
00199 
00200     if (!infeasible && doConvCuts_ && simulate_ && cutGen_) { 
00201 
00202       // generate convexification cuts before solving new node's LP
00203       int nchanged, *changed = NULL;
00204       OsiCuts cs;
00205 
00206       // sparsify structure with info on changed bounds and get convexification cuts
00207       sparse2dense (nvars, chg_bds, changed, nchanged);
00208       cutGen_ -> genRowCuts (*solver, cs, nchanged, changed, chg_bds);
00209       free (changed);
00210 
00211       solver -> applyCuts (cs);
00212     }
00213 
00214     delete [] chg_bds;
00215 
00216     problem_ -> domain () -> pop ();
00217   }
00218 
00219   // next time do other branching
00220   branchIndex_++;
00221 
00222   return (infeasible ? COIN_DBL_MAX : estimate); // estimated change in objective function
00223 }

Generated on Thu Aug 5 03:02:56 2010 by  doxygen 1.4.7