branchExprQuad.cpp
Go to the documentation of this file.
1 /* $Id: branchExprQuad.cpp 708 2011-06-23 14:04:59Z pbelotti $
2  *
3  * Name: branchExprQuad.cpp
4  * Author: Pietro Belotti
5  * Purpose: return branch data for quadratic forms
6  *
7  * (C) Carnegie-Mellon University, 2007-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CoinHelperFunctions.hpp"
12 
13 #include "CouenneExprQuad.hpp"
14 #include "CouenneObject.hpp"
16 
17 using namespace Couenne;
18 
19 //#define DEBUG
20 
24  const OsiBranchingInformation *info,
25  expression *&var,
26  double * &brpts,
27  double * &brDist, // distance of current LP
28  // point to new convexifications
29  int &way) {
30  int ind = -1;
31 
32  // use a combination of eigenvectors and bounds
33 
34  CouNumber delta = (*(obj -> Reference ())) () - (*this) ();
35 
36  /*printf ("infeasibility: ");
37  obj -> Reference () -> print ();
38  printf (" [%g=%g] := ",
39  (*(obj -> Reference ())) (), info -> solution_ [obj -> Reference () -> Index ()]);
40  print (); printf (" [%g]\n", (*this) ());*/
41 
42  brpts = (double *) realloc (brpts, sizeof (double));
43  brDist = (double *) realloc (brDist, 2*sizeof (double));
44 
45  way = TWO_RAND;
46 
47  // depending on where the current point is w.r.t. the curve,
48  // branching is done on the eigenvector corresponding to the minimum
49  // or maximum eigenvalue
50 
51  std::vector <std::pair <CouNumber,
52  std::vector <std::pair <exprVar *, CouNumber> > > >::iterator fi = eigen_.begin ();
53 
54  std::vector <std::pair <CouNumber,
55  std::vector <std::pair <exprVar *, CouNumber> > > >::reverse_iterator ri = eigen_.rbegin ();
56 
57  CouNumber max_span = -COUENNE_INFINITY;
58 
59  bool changed_sign = false;
60 
62 
63  for (;(((delta < 0.) && (fi != eigen_. end ())) || // && (fi -> first < 0.) ||
64  ((delta > 0.) && (ri != eigen_. rend ()))); // && (ri -> first > 0.));
65  ++fi, ++ri) {
66 
67  std::vector <std::pair <exprVar *, CouNumber> > &ev =
68  (delta < 0.) ? fi -> second : ri -> second;
69 
70  if (((delta < 0.) && (fi -> first > 0.)) ||
71  ((delta > 0.) && (ri -> first < 0.))) {
72 
73  if (max_span > 0.) break; // if found a variable already, return
74  changed_sign = true; // otherwise, keep in mind we are on
75  // the wrong eigenvalues' sign
76  }
77 
78  for (std::vector <std::pair <exprVar *, CouNumber> >::iterator j = ev.begin ();
79  j != ev.end (); ++j) {
80 
81  int index = j -> first -> Index ();
82 
83  CouNumber
84  lb = info -> lower_ [index],
85  ub = info -> upper_ [index];
86 
87  // only accept variable if not fixed
88  if (fabs (ub-lb) > COUENNE_EPS) {
89 
90  // no variable was found but the eigenvalue is already
91  // positive (negative)
92  // changed_sign &&
93  // (max_span < 0.))
94 
95  CouNumber span = -1;
96 
97  if ((lb < -COUENNE_INFINITY) ||
98  (ub > COUENNE_INFINITY) ||
99  ((span = (ub-lb) * fabs (j -> second)) > max_span + COUENNE_EPS)) {
100 
101  ind = index;
102  var = j -> first;
103 
104  *brpts = obj -> midInterval (info -> solution_ [index], lb, ub, info);
105 
106  if (changed_sign)
107  break;
108 
109  if (span >= 0) max_span = span; // finite, keep searching
110  else break; // span unbounded, stop searching
111  }
112  }
113  }
114  }
115 
116  if ((eigen_.size () == 0) // if no eigenvalue has been computed yet
117  || (ind < 0)) { // or no index was found, pick largest interval
118 
119  CouNumber max_span = -COUENNE_INFINITY;
120 
121  for (std::map <exprVar *, std::pair <CouNumber, CouNumber> >::iterator i = bounds_. begin ();
122  i != bounds_. end (); ++i) {
123 
124  CouNumber
125  lb = i -> second.first,
126  ub = i -> second.second,
127  span = ub - lb;
128 
129  if ((span > COUENNE_EPS) &&
130  (span > max_span)) {
131 
132  var = i -> first;
133  ind = var -> Index ();
134  }
135  }
136 
137  if (ind < 0) {
138 
139  var = obj -> Reference ();
140  ind = var -> Index ();
141 
142  *brpts = obj -> midInterval (info -> solution_ [ind],
143  info -> lower_ [ind],
144  info -> upper_ [ind], info);
145  }
146  else *brpts = obj -> midInterval (info -> solution_ [ind],
147  info -> lower_ [ind],
148  info -> upper_ [ind], info);
149  //return fabs (delta);
150  }
151 
152  return (brDist [0] = brDist [1] = fabs (delta));
153 }
virtual CouNumber selectBranch(const CouenneObject *obj, const OsiBranchingInformation *info, expression *&var, double *&brpts, double *&brDist, int &way)
Set up branching object by evaluating many branching points for each expression&#39;s arguments...
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real fint fint fint fint * info
OsiObject for auxiliary variables $w=f(x)$.
static char * j
Definition: OSdtoa.cpp:3622
virtual int Index() const
Return index of variable (only valid for exprVar and exprAux)
fint end
std::vector< std::pair< CouNumber, std::vector< std::pair< exprVar *, CouNumber > > > > eigen_
eigenvalues and eigenvectors
#define COUENNE_EPS
std::map< exprVar *, std::pair< CouNumber, CouNumber > > bounds_
current bounds (checked before re-computing eigenvalues/vectors)
double CouNumber
main number type in Couenne
#define COUENNE_INFINITY
variable-type operator
Expression base class.