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

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

Generated on Thu Nov 10 03:05:43 2011 by  doxygen 1.4.7