conv-exprInv.cpp
Go to the documentation of this file.
1 /* $Id: conv-exprInv.cpp 1248 2018-03-18 17:54:11Z pbelotti $
2  *
3  * Name: conv-exprInv.cpp
4  * Author: Pietro Belotti
5  * Purpose: convexification and bounding methods for the inverse operator
6  *
7  * (C) Carnegie-Mellon University, 2006-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CouenneCutGenerator.hpp"
12 
13 #include "CouenneTypes.hpp"
14 
15 #include "CouenneExprVar.hpp"
16 #include "CouenneExprInv.hpp"
17 #include "CouenneExprClone.hpp"
18 #include "CouenneExprConst.hpp"
19 #include "CouenneExprMin.hpp"
20 #include "CouenneExprOpp.hpp"
21 #include "CouenneExprDiv.hpp"
22 #include "CouenneExprSum.hpp"
23 #include "CouenneExprMul.hpp"
24 #include "CouenneExprPow.hpp"
25 
26 #include "CouenneProblem.hpp"
27 
28 using namespace Couenne;
29 
30 // compute upper- and lower bounds of the expression w = 1/f(x) given
31 // bounds of f(x)
32 
34 
35  expression *lba, *uba;
36  argument_ -> getBounds (lba, uba);
37 
38  expression **all = new expression * [6];
39  all [0] = new exprConst (0.); all [1] = new exprConst (- COUENNE_INFINITY); // l<0<u
40  all [2] = new exprOpp (lba); all [3] = new exprInv (uba); // 0<l<u
41  all [4] = new exprClone (uba); all [5] = new exprInv (new exprClone (uba)); // l<u<0
42 
43  lb = new exprMin (all, 6);
44 
45  expression **alu = new expression * [6];
46  alu [0] = new exprConst (0.); alu [1] = new exprConst (COUENNE_INFINITY); // l<0<u
47  alu [2] = new exprClone (all [2]); alu [3] = new exprInv (new exprClone (lba)); // 0<l<u
48  alu [4] = new exprClone (uba); alu [5] = new exprInv (new exprClone (lba)); // l<u<0
49 
50  ub = new exprMin (alu, 6);
51 }
52 
53 
54 // compute VALUE of lower and upper bound of expression
56 
57  register CouNumber lba, uba;
58 
59  argument_ -> getBounds (lba, uba);
60 
61  if ((uba < -COUENNE_EPS) || (lba > COUENNE_EPS)) {
62  lb = 1./uba;
63  ub = 1./lba;
64  } else {
65  lb = -COUENNE_INFINITY;
66  ub = COUENNE_INFINITY;
67  }
68 }
69 
70 
71 #define MIN_DENOMINATOR 1e-6
72 
73 // generate convexification cut for constraint w = 1/x
74 
75 void exprInv::generateCuts (expression *aux, //const OsiSolverInterface &si,
76  OsiCuts &cs, const CouenneCutGenerator *cg,
77  t_chg_bounds *chg, int wind,
78  CouNumber lbw, CouNumber ubw) {
79 
80  // TODO: if a<=w<=b, c<=x<=d, there is a diamond enclosing the whole
81  // convexification
82 
83  CouNumber l, u;
84  argument_ -> getBounds (l, u);
85 
86  if ((l < - COUENNE_EPS) && (u > COUENNE_EPS)) // there is no convexification
87  return;
88 
89  int wi = aux -> Index (),
90  xi = argument_ -> Index ();
91 
92  bool cL = !chg || (cg -> isFirst ()) || (chg [xi].lower() != t_chg_bounds::UNCHANGED);
93  bool cR = !chg || (cg -> isFirst ()) || (chg [xi].upper() != t_chg_bounds::UNCHANGED);
94 
95  // special case: l and u are very close, replace function with
96  // linear term
97 
98  enum auxSign sign = cg -> Problem () -> Var (wi) -> sign ();
99 
100  if (fabs (u - l) < COUENNE_EPS) {
101 
102  CouNumber x0 = 0.5 * (u+l);
103  if (cL || cR)
104  cg -> createCut (cs, 2/x0, sign, wi, 1., xi, 1/(x0*x0));
105  return;
106  }
107 
108  // upper segment (or lower if x<0)
109 
110  if (cL || cR) {
111  // bounding box is within ]0,+inf[
112  if ((l> COUENNE_EPS) && (u< COU_MAX_COEFF) && sign != expression::AUX_GEQ) cg -> createCut (cs, 1/l+1/u, -1, wi,1., xi,1/(l*u));
113  if ((u<-COUENNE_EPS) && (l>-COU_MAX_COEFF) && sign != expression::AUX_LEQ) cg -> createCut (cs, 1/l+1/u, +1, wi,1., xi,1/(l*u));
114  // bounding box is within ]-inf,0[
115  }
116 
117  // choose sampling points.
118 
119  // if unbounded, use a rule of thumb
120  int ns = cg -> nSamples ();
121  if (l < - COUENNE_INFINITY) l = ns * (u-1); // (-infinity, u] where u < 0
122  else if (u > COUENNE_INFINITY) u = ns * (l+1); // [l, +infinity) where l > 0
123 
124  // make bounds nonzero
125  if (fabs (l) < COUENNE_EPS) l = (l<0) ? - MIN_DENOMINATOR : MIN_DENOMINATOR;
126  if (fabs (u) < COUENNE_EPS) u = (u<0) ? - MIN_DENOMINATOR : MIN_DENOMINATOR;
127 
128  // bound
129  if ((l > 0 && sign != expression::AUX_LEQ) ||
130  (sign != expression::AUX_GEQ))
131  cg -> addEnvelope
132  (cs, (l > 0) ? +1 : -1,
133  inv, oppInvSqr, wi, xi,
134  (cg -> isFirst ()) ? // is this first call?
135  // place it somewhere in the interval (we don't care)
136  ((l > COUENNE_EPS) ? l : u) :
137  // otherwise, replace it where it gives deepest cut
138  powNewton ((*argument_) (), (*aux) (), inv, oppInvSqr, inv_dblprime),
139  l, u, chg);
140 }
Cut Generator for linear convexifications.
CouNumber powNewton(CouNumber xc, CouNumber yc, unary_function f, unary_function fp, unary_function fpp)
find proper tangent point to add deepest tangent cut
Definition: powNewton.cpp:29
class opposite,
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
exprInv(expression *al)
Constructors, destructor.
CouNumber oppInvSqr(register CouNumber x)
derivative of inv (x)
CouNumber inv_dblprime(register CouNumber x)
inv_dblprime, second derivative of inv (x)
expression * argument_
single argument taken by this expression
CouNumber inv(register CouNumber arg)
the operator itself
constant-type operator
#define MIN_DENOMINATOR
ULong * x0
Definition: OSdtoa.cpp:1776
virtual int Index() const
Return index of variable (only valid for exprVar and exprAux)
auxSign
&quot;sign&quot; of the constraint defining an auxiliary.
fint ns
#define COU_MAX_COEFF
expression clone (points to another expression)
#define COUENNE_EPS
double CouNumber
main number type in Couenne
void generateCuts(expression *w, OsiCuts &cs, const CouenneCutGenerator *cg, t_chg_bounds *=NULL, int=-1, CouNumber=-COUENNE_INFINITY, CouNumber=COUENNE_INFINITY)
generate equality between *this and *w
void getBounds(expression *&, expression *&)
Get lower and upper bound of an expression (if any)
#define COUENNE_INFINITY
Expression base class.