/home/coin/SVN-release/OS-2.4.2/Couenne/src/branch/operators/branchExprQuad.cpp

Go to the documentation of this file.
00001 /* $Id: branchExprQuad.cpp 708 2011-06-23 14:04:59Z pbelotti $
00002  *
00003  * Name:    branchExprQuad.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: return branch data for quadratic forms
00006  *
00007  * (C) Carnegie-Mellon University, 2007-10.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CoinHelperFunctions.hpp"
00012 
00013 #include "CouenneExprQuad.hpp"
00014 #include "CouenneObject.hpp"
00015 #include "CouenneBranchingObject.hpp"
00016 
00017 using namespace Couenne;
00018 
00019 //#define DEBUG
00020 
00023 CouNumber exprQuad::selectBranch (const CouenneObject *obj, 
00024                                   const OsiBranchingInformation *info,
00025                                   expression *&var, 
00026                                   double * &brpts, 
00027                                   double * &brDist, // distance of current LP
00028                                                     // point to new convexifications
00029                                   int &way) {
00030   int ind = -1;
00031 
00032   // use a combination of eigenvectors and bounds
00033 
00034   CouNumber delta = (*(obj -> Reference ())) () - (*this) ();
00035 
00036   /*printf ("infeasibility: ");
00037   obj -> Reference () -> print (); 
00038   printf (" [%g=%g] := ", 
00039           (*(obj -> Reference ())) (), info -> solution_ [obj -> Reference () -> Index ()]);
00040           print (); printf (" [%g]\n", (*this) ());*/
00041 
00042   brpts  = (double *) realloc (brpts,    sizeof (double));
00043   brDist = (double *) realloc (brDist, 2*sizeof (double));
00044 
00045   way = TWO_RAND;
00046 
00047   // depending on where the current point is w.r.t. the curve,
00048   // branching is done on the eigenvector corresponding to the minimum
00049   // or maximum eigenvalue
00050 
00051   std::vector <std::pair <CouNumber, 
00052     std::vector <std::pair <exprVar *, CouNumber> > > >::iterator         fi = eigen_.begin ();
00053 
00054   std::vector <std::pair <CouNumber, 
00055     std::vector <std::pair <exprVar *, CouNumber> > > >::reverse_iterator ri = eigen_.rbegin ();
00056 
00057   CouNumber max_span = -COUENNE_INFINITY;
00058 
00059   bool changed_sign = false;
00060 
00062 
00063   for (;(((delta < 0.) && (fi != eigen_. end  ())) || // && (fi -> first < 0.) ||
00064          ((delta > 0.) && (ri != eigen_. rend ())));  // && (ri -> first > 0.));
00065        ++fi, ++ri) {
00066 
00067     std::vector <std::pair <exprVar *, CouNumber> > &ev = 
00068       (delta < 0.) ? fi -> second : ri -> second;
00069 
00070     if (((delta < 0.) && (fi -> first > 0.)) ||
00071         ((delta > 0.) && (ri -> first < 0.))) {
00072 
00073       if (max_span > 0.) break; // if found a variable already, return
00074       changed_sign = true;      // otherwise, keep in mind we are on
00075                                 // the wrong eigenvalues' sign
00076     }
00077 
00078     for (std::vector <std::pair <exprVar *, CouNumber> >::iterator j = ev.begin ();
00079          j != ev.end (); ++j) {
00080 
00081       int index = j -> first -> Index ();
00082 
00083       CouNumber 
00084         lb = info -> lower_ [index],
00085         ub = info -> upper_ [index];
00086 
00087       // only accept variable if not fixed
00088       if (fabs (ub-lb) > COUENNE_EPS) {
00089 
00090           // no variable was found but the eigenvalue is already
00091           // positive (negative)
00092           //      changed_sign &&
00093           //      (max_span < 0.))
00094 
00095         CouNumber span = -1;
00096 
00097         if ((lb < -COUENNE_INFINITY) ||
00098             (ub >  COUENNE_INFINITY) ||
00099             ((span = (ub-lb) * fabs (j -> second)) > max_span + COUENNE_EPS)) {
00100 
00101           ind = index;
00102           var = j -> first;
00103 
00104           *brpts = obj -> midInterval (info -> solution_ [index], lb, ub, info);
00105 
00106           if (changed_sign) 
00107             break;
00108 
00109           if (span >= 0) max_span = span; // finite, keep searching
00110           else break;                     // span unbounded, stop searching
00111         }
00112       }
00113     }
00114   }
00115 
00116   if ((eigen_.size () == 0) // if no eigenvalue has been computed yet
00117       || (ind < 0)) {       // or no index was found, pick largest interval
00118 
00119     CouNumber max_span = -COUENNE_INFINITY;
00120 
00121     for (std::map <exprVar *, std::pair <CouNumber, CouNumber> >::iterator i = bounds_. begin ();
00122          i != bounds_. end (); ++i) {
00123 
00124       CouNumber
00125         lb = i -> second.first,
00126         ub = i -> second.second,
00127         span = ub - lb;
00128 
00129       if ((span > COUENNE_EPS) && 
00130           (span > max_span)) {
00131 
00132         var = i -> first;
00133         ind = var -> Index ();
00134       }
00135     }
00136 
00137     if (ind < 0) {
00138 
00139       var = obj -> Reference ();
00140       ind = var -> Index ();
00141 
00142       *brpts = obj -> midInterval (info -> solution_ [ind],
00143                                    info -> lower_ [ind],
00144                                    info -> upper_ [ind], info);
00145     }
00146     else *brpts = obj -> midInterval (info -> solution_ [ind], 
00147                                       info -> lower_ [ind],
00148                                       info -> upper_ [ind], info);        
00149     //return fabs (delta);
00150   }
00151 
00152   return (brDist [0] = brDist [1] = fabs (delta));
00153 }

Generated on Wed Nov 30 03:03:58 2011 by  doxygen 1.4.7