/home/coin/SVN-release/OS-2.0.1/Couenne/src/branch/operators/branchExprLog.cpp

Go to the documentation of this file.
00001 /* $Id: branchExprLog.cpp 141 2009-06-03 04:19:19Z pbelotti $ */
00002 /*
00003  * Name:    branchExprLog.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: return branch gain and branch object for logarithms
00006  *
00007  * (C) Carnegie-Mellon University, 2006-08.
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 #include "CoinHelperFunctions.hpp"
00012 
00013 #include "exprLog.hpp"
00014 #include "CouenneObject.hpp"
00015 #include "CouenneBranchingObject.hpp"
00016 #include "projections.hpp"
00017 #include "funtriplets.hpp"
00018 
00019 
00020 #define SQ_COUENNE_EPS COUENNE_EPS * COUENNE_EPS
00021 
00024 CouNumber exprLog::selectBranch (const CouenneObject *obj, 
00025                                  const OsiBranchingInformation *info,
00026                                  expression *&var,
00027                                  double * &brpts, 
00028                                  double * &brDist, // distance of current LP
00029                                                    // point to new convexifications
00030                                  int &way) {
00031 
00032   brpts  = (double *) realloc (brpts,    sizeof (double));
00033   brDist = (double *) realloc (brDist, 2*sizeof (double));
00034 
00035   // quite similar to exprExp::selectBranch() (see branchExprExp.cpp)
00036   //
00037   // two cases: inside or outside the belly. 
00038   //
00039   // Inside: the distance depends on the projection of the current
00040   // point onto the would-be upper envelopes, which forces us to look
00041   // at it numerically. If both bounds are infinite, create a ThreeWay
00042   // branch.
00043   //
00044   // Outside: it suffices to project the current point on the line
00045   // (i.e. to get the closest point on the line) to get the maxi-min
00046   // displacement.
00047   //
00048   // As for all monotonous functions, after choosing *brpts it is
00049   // equivalent to choose w's or x's index as ind, as the implied- and
00050   // propagated bounds will do the rest.
00051 
00052   var = argument_;
00053 
00054   int
00055     ind = var -> Index (),
00056     wi  = obj -> Reference () -> Index ();
00057 
00058   assert ((ind >= 0) && (wi >= 0));
00059 
00060   CouNumber 
00061     y0 = info -> solution_ [wi],
00062     x0 = info -> solution_ [ind],
00063     l  = info -> lower_    [ind],
00064     u  = info -> upper_    [ind];
00065 
00066   if (u < COUENNE_EPS) { // strange case, return default branching rule
00067     var = NULL; 
00068     return 0.;
00069   }
00070 
00071   if (x0 < SQ_COUENNE_EPS) // very unlikely...
00072     x0 = SQ_COUENNE_EPS;
00073 
00074   if (y0 > log (x0)) { 
00075 
00076     // Outside -> branch on closest point on curve
00077 
00078     *brpts = obj -> midInterval (powNewton (x0, y0, log, inv, oppInvSqr), l, u);
00079 
00080     way = TWO_LEFT;
00081     CouNumber dy = y0 - log (*brpts);
00082     x0 -= *brpts;
00083 
00084     return (brDist [0] = brDist [1] = sqrt (x0*x0 + dy*dy)); // exact distance
00085   } 
00086 
00087   // Inside. Two cases: ////////////////////////////////////////////////////
00088  
00089   if ((l <= SQ_COUENNE_EPS) && 
00090       (u > COUENNE_INFINITY)) {
00091 
00092     // 1) curve is unlimited in both senses
00093 
00094     /*// restore when we can do three-way branching
00095       #if 0
00096       brpts = (double *) realloc (brpts, 2 * sizeof (double));
00097       way = THREE_CENTER; // focus on central convexification first
00098       brpts [0] = exp (y0); // draw horizontal from (x0,y0) east  to curve y=log(x)
00099       brpts [1] = x0;       //      vertical                north
00100       CouNumber a = x0 - exp (y0), // sides of a triangle with (x0,y0)
00101       b = log (x0) - y0; // as one of the vertices
00102 
00103       return a * cos (atan (a/b)); // exact distance
00104       #endif*/
00105 
00106     // follow South-East diagonal to find point on curve
00107     // so that current point is surely cut 
00108     brpts = (double *) realloc (brpts, sizeof (double));
00109     *brpts = 0.5 * (x0 + exp (y0));
00110     way = TWO_RAND;
00111 
00112     return CoinMin (brDist [0] = x0 - exp (y0), 
00113                     brDist [1] = log (x0) - y0);
00114   } 
00115 
00116   // 2) at least one of them is finite
00117 
00118   brpts = (double *) realloc (brpts, sizeof (double));
00119 
00120   if (l <= SQ_COUENNE_EPS) { // u is finite
00121 
00122     *brpts = obj -> midInterval (exp (y0), l, u);
00123     way = TWO_RIGHT;
00124 
00125     brDist [0] = x0 - *brpts;
00126     return (brDist [1] = projectSeg (x0, y0, *brpts, log (*brpts), u, log (u), +1)); // exact distance
00127     //    return CoinMin (x0 - exp (y0), log (x0) - y0);
00128   }
00129  
00130   if (u > COUENNE_INFINITY) { // l is far from zero
00131 
00132     *brpts = CoinMax (10*x0, obj -> midInterval (x0, l, u));
00133     way = TWO_LEFT;
00134 
00135     brDist [1] = log (*brpts) - y0;
00136 
00137     return (brDist [0] = projectSeg (x0, y0, l, log (l), *brpts, log (*brpts), +1)); // exact distance
00138     //return log (x0) - y0;
00139   } 
00140 
00141   // both are finite
00142  
00143   simpletriplet ft (log, inv, oppInvSqr, inv);
00144 
00145   *brpts = obj -> getBrPoint (&ft, x0, l, u);
00146 
00147   //  *brpts = midInterval (powNewton (x0, y0, log, inv, oppInvSqr), l, u); 
00148   // WRONG! Local minima may be at bounds
00149 
00150   // compute distance from current point to new convexification(s) and
00151   // to curve. If closer to curve, branch on current point
00152 
00153   way = TWO_RAND;
00154 
00155   // exact distance
00156   return CoinMin (brDist [0] = projectSeg (x0, y0, l, log (l), *brpts, log (*brpts),             +1),
00157                   brDist [1] = projectSeg (x0, y0,             *brpts, log (*brpts), u, log (u), +1));
00158 }

Generated on Thu Oct 8 03:02:56 2009 by  doxygen 1.4.7