00001 /* $Id: computeMulBrDist.cpp 490 2011-01-14 16:07:12Z pbelotti $ 00002 * 00003 * Name: computeMulBrDist.cpp 00004 * Author: Pietro Belotti 00005 * Purpose: compute distance to new convexifications generated by branching on product 00006 * 00007 * (C) Carnegie-Mellon University, 2008-10. 00008 * This file is licensed under the Eclipse Public License (EPL) 00009 */ 00010 00011 #include "CouennePrecisions.hpp" 00012 #include "CouenneTypes.hpp" 00013 #include "CouenneObject.hpp" 00014 00015 #include "CouenneExprMul.hpp" 00016 #include "CouenneFunTriplets.hpp" 00017 #include "CouenneProjections.hpp" 00018 00019 namespace Couenne { 00020 00021 // compute distance from future convexifications in set \f$\{(x,y,w): 00022 // w = xy\}\f$ with x,y,w bounded 00023 double *computeMulBrDist (const OsiBranchingInformation *info, 00024 int xi, int yi, int wi, 00025 int brind, double *brpt, int nPts) { 00026 00027 // use rule of thumb to compute distance: fix two of the three 00028 // variables and compute distance between current LP point and curve 00029 // w=x/y (z is the branching variable, x or y) 00030 // 00031 // 1) fix x,y: distances are w - x/y and ||(w-x/y, z-zb)||_2 00032 // 2) fix x,w: y - x/w and ||(y-x/w, z-zb)||_2 00033 // 3) fix y,w: x - y*w and ||(x-y*w, z-zb)||_2 00034 00035 CouNumber 00036 x0 = info -> solution_ [xi], //xl = info -> lower_ [xi], xu = info -> upper_ [xi], 00037 y0 = info -> solution_ [yi], //yl = info -> lower_ [yi], yu = info -> upper_ [yi], 00038 w0 = info -> solution_ [wi]; //wl = info -> lower_ [wi], wu = info -> upper_ [wi]; 00039 00040 double *dist = (double *) malloc (2 * sizeof (double)); 00041 00042 // two main cases: 00043 // 00044 // 1) wi is the branching index: the bounding box is divided in two 00045 // by the rule w <= wb and w >= wb. Finding the distances from the 00046 // current point (x0,y0,w0) to the two semi-surfaces depends on 00047 // which side w0 stands. 00048 // 00049 // 2) xi or yi are the branching index: reduce to the problem of 00050 // finding the distance from a point (x0,y0,w0) to the same surface 00051 // within the (two) element of a partition of the bounding box. 00052 00053 00054 // case 1 //////////////////////////////////////////////////////////////////// 00055 // 00056 // Depending on whether 00057 // 00058 // a) w0 <=/>= wb 00059 // b) w0 <=/>= x0*y0 00060 // c) wb <=/>= 0 00061 // 00062 // there are eight (!) cases, each with a similar computation for 00063 // the two distances. We unify it below. 00064 00065 // [for now give a simplified version with rough distance computation] 00066 00067 if (brind == wi) { 00068 00069 // easy implementation: for own side, w0 - x0 y0; for other side, 00070 // horiz/vert distance to curve x0 w0 = wb 00071 00072 bool side = (((x0*y0 > *brpt) && (*brpt > 0)) || 00073 ((x0*y0 < *brpt) && (*brpt < 0))); 00074 00075 dist [side ? 1 : 0] = CoinMax 00076 (fabs (w0 - x0*y0), CoinMin 00077 ((fabs (y0) > COUENNE_EPS) ? fabs (x0 - *brpt / y0) : 0., 00078 (fabs (x0) > COUENNE_EPS) ? fabs (y0 - *brpt / x0) : 0.)); 00079 00080 dist [side ? 0 : 1] = fabs (w0 - x0*y0); 00081 } 00082 00083 // case 2 //////////////////////////////////////////////////////////////////// 00084 00085 else { 00086 00087 CouNumber diff = info -> solution_ [brind] - *brpt; 00088 bool side = (diff > 0.); 00089 00090 dist [side ? 0 : 1] = CoinMax (fabs (w0 - x0 * y0), fabs (diff)); 00091 dist [side ? 1 : 0] = fabs (w0 - x0 *y0); 00092 } 00093 00094 //dist [0] = dist [1] = 1; 00095 return dist; 00096 } 00097 00098 }