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

Go to the documentation of this file.
00001 /* $Id: branchExprDiv.cpp 141 2009-06-03 04:19:19Z pbelotti $ */
00002 /*
00003  * Name:    branchExprDiv.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: select branch for divisions
00006  *
00007  * (C) Carnegie-Mellon University, 2006-08.
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 #include "exprDiv.hpp"
00012 #include "exprMul.hpp"
00013 #include "CouenneBranchingObject.hpp"
00014 #include "CouenneObject.hpp"
00015 
00016 
00019 CouNumber exprDiv::selectBranch (const CouenneObject *obj, 
00020                                  const OsiBranchingInformation *info,
00021                                  expression *&var,
00022                                  double * &brpts, 
00023                                  double * &brDist, // distance of current LP
00024                                                    // point to new convexifications
00025                                  int &way) {
00026 
00027   if (brDist) {free (brDist); brDist = NULL;} // clear it, computeMulBrDist will fill it
00028 
00029   int xi = arglist_ [0]        -> Index (),
00030       yi = arglist_ [1]        -> Index (),
00031       wi = obj -> Reference () -> Index ();
00032 
00033   assert ((xi >= 0) && (yi >= 0) && (wi >= 0));
00034 
00035   // choosing branching variable and point is difficult, use
00036   // proportion in bound intervals
00037 
00038   CouNumber yl = info -> lower_    [yi], 
00039             yu = info -> upper_    [yi],
00040             y0 = info -> solution_ [yi];
00041 
00042   // if [yl,yu] contains 0, create two nodes
00043 
00044   if ((yl < -COUENNE_EPS) && 
00045       (yu >  COUENNE_EPS)) {
00046 
00047     var = arglist_ [1];
00048     brpts  = (double *) realloc (brpts,  sizeof (double));
00049 
00050     *brpts = 0.;
00051 
00052     way = (y0 > *brpts) ? TWO_RIGHT : TWO_LEFT;
00053 
00054     brDist = computeMulBrDist (info, wi, yi, xi, yi, brpts);
00055 
00056     return CoinMin (brDist [0], brDist [1]);
00057     /*return ((fabs (y0) < COUENNE_EPS) ? 1. :
00058             fabs (info -> solution_ [xi] / y0 - 
00059             info -> solution_ [wi]));*/
00060   }
00061 
00062   // From now on, [yl,yu] may be unlimited in one sense only, and
00063   // interval does not contain 0.
00064   //
00065   // As convexification is still carried out by applying McCormick
00066   // rules to x=w*y (where original operator is w=x/y), try to get
00067   // closer to a situation where both y and w are bounded, if
00068   // necessary by branching on w.
00069   //
00070   // Branch first on y if unbounded, and then on w. As a result of
00071   // bound tightening, if both y and w are bounded, x will be, too.
00072 
00073   if ((yl < -COUENNE_INFINITY) || // and yu < 0
00074       (yu >  COUENNE_INFINITY)) { // and yl > 0
00075 
00076     var = arglist_ [1];
00077     brpts = (double *) realloc (brpts, sizeof (CouNumber));
00078 
00079     // if y0 close to bounds, branch away from it
00080     if      (fabs (y0-yl) < COUENNE_NEAR_BOUND) *brpts = y0 + 1. + yl*10.;
00081     else if (fabs (y0-yu) < COUENNE_NEAR_BOUND) *brpts = y0 - 1. + yu*10.;
00082     else                                        *brpts = y0;
00083 
00084     way = (y0 > 0.) ? TWO_LEFT : TWO_RIGHT;
00085 
00086     brDist = computeMulBrDist (info, wi, yi, xi, yi, brpts);
00087 
00088     return CoinMin (brDist [0], brDist [1]);
00089 
00090     //return ((fabs (y0) < COUENNE_EPS) ? 1. : 
00091     //fabs (info -> solution_ [xi] / y0 - info -> solution_ [wi]));
00092   }
00093 
00094   // y is bounded, and y0 nonzero; if w is unbounded, bound w first as
00095   // x will be too.
00096 
00097   CouNumber wl = info -> lower_    [wi], 
00098             wu = info -> upper_    [wi],
00099             w0 = info -> solution_ [wi],
00100             x0 = info -> solution_ [xi];
00101 
00102   // w unbounded in >= one direction ///////////////////////////////////////
00103 
00104   if ((wl < -COUENNE_INFINITY) || 
00105       (wu >  COUENNE_INFINITY)) {
00106 
00107     var = obj -> Reference ();
00108 
00109     if ((wl < -COUENNE_INFINITY) &&
00110         (wu >  COUENNE_INFINITY)) { // unbounded in two directions
00111 
00112       CouNumber 
00113         wreal = x0 / y0, 
00114         wmin  = w0, 
00115         wmax  = wreal; // assume (x0,y0,w0) is below w=x/y
00116 
00117       if (wreal < w0) { // but swap if (x0,y0,w0) is above w=x/y
00118         wmin = wreal;
00119         wmax = w0;
00120       }
00121 
00122       brpts = (double *) realloc (brpts, sizeof (CouNumber));
00123       *brpts = wreal;
00124       way = (w0 < wreal) ? TWO_LEFT : TWO_RIGHT;
00125 
00126       brDist = computeMulBrDist (info, wi, yi, xi, wi, brpts);
00127       return CoinMin (brDist [0], brDist [1]);
00128 
00129     } else {
00130 
00131       // unbounded in one direction only, use two way branching
00132 
00133       brpts = (double *) realloc (brpts, sizeof (CouNumber));
00134 
00135       // if y0 close to bounds, branch away from it
00136       if      (fabs (w0-wl) < COUENNE_NEAR_BOUND) *brpts = w0 + 1 + wl*10;
00137       else if (fabs (w0-wu) < COUENNE_NEAR_BOUND) *brpts = w0 - 1 + wu*10;
00138       else                                        *brpts = w0;
00139 
00140       way = (wl < - COUENNE_INFINITY) ? TWO_RIGHT : TWO_LEFT;
00141 
00142       brDist = computeMulBrDist (info, wi, yi, xi, wi, brpts);
00143       return CoinMin (brDist [0], brDist [1]);
00144     }
00145     //return ((fabs (y0) < COUENNE_EPS) ? 1. : fabs (x0/y0 - w0));
00146   }
00147 
00148   // w and y are bounded (and so is x). Choose between x, y, z
00149   // depending on intervals first and then to vicinity to midpoint
00150   CouNumber 
00151     xl = info -> lower_ [xi],
00152     xu = info -> upper_ [xi],
00153     dx = xu-xl,
00154     dy = yu-yl,
00155     dw = wu-wl;
00156 
00157   brpts = (double *) realloc (brpts, sizeof (CouNumber));
00158 
00159   // Check largest interval and choose branch variable accordingly.
00160   // Branching point depends on where the current point is, but for
00161   // now just focus on the width of the intervals
00162 
00163   way = TWO_RAND;
00164 
00165   if (dx > dy)
00166     if (dx > dw) {var = arglist_[0];      *brpts = (xl+xu)/2.; /*return fabs (x0-y0*w0);*/}
00167     else         {var = obj->Reference(); *brpts = (wl+wu)/2.; /*return fabs (w0-x0/y0);*/}
00168   else
00169     if (dy > dw) {var = arglist_[1];      *brpts = (yl+yu)/2.; /*return fabs (y0-x0/w0);*/}
00170     else         {var = obj->Reference(); *brpts = (wl+wu)/2.; /*return fabs (w0-x0/y0);*/}
00171 
00172   brDist = computeMulBrDist (info, wi, yi, xi, var -> Index (), brpts);
00173   return CoinMin (brDist [0], brDist [1]);
00174 }

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