conv-exprDiv.cpp
Go to the documentation of this file.
1 /* $Id: conv-exprDiv.cpp 811 2012-02-01 19:21:41Z pbelotti $
2  *
3  * Name: conv-exprDiv.cpp
4  * Author: Pietro Belotti
5  * Purpose: standardization and convexification methods for divisions
6  *
7  * (C) Carnegie-Mellon University, 2006-11.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CouenneCutGenerator.hpp"
12 
13 #include "CouenneTypes.hpp"
14 #include "CouenneExpression.hpp"
15 #include "CouenneExprAux.hpp"
16 #include "CouenneExprOp.hpp"
17 #include "CouenneExprDiv.hpp"
18 #include "CouenneExprMul.hpp"
19 #include "CouenneProblem.hpp"
20 
21 using namespace Couenne;
22 
23 // Create standard formulation of this expression
25 
27  return (addAux ? (p -> addAuxiliary (this)) : new exprAux (this, p -> domain ()));
28 }
29 
30 
31 // generate convexification cut for constraint w = x/y
32 void exprDiv::generateCuts (expression *w, //const OsiSolverInterface &si,
33  OsiCuts &cs, const CouenneCutGenerator *cg,
34  t_chg_bounds *chg, int wind,
35  CouNumber lbw, CouNumber ubw) {
36  // compute y bounds
37 
38  CouNumber yl, yu;
39  arglist_ [1] -> getBounds (yl, yu);
40 
41  int xi = arglist_ [0] -> Index (),
42  yi = arglist_ [1] -> Index (),
43  wi = w -> Index ();
44 
45  bool cLW, cRW, cLY, cRY =
46  cLW = cRW = cLY = true;
47 
48  if (!(cg -> isFirst ()) && chg) {
49  cLW = (chg [wi].lower() != t_chg_bounds::UNCHANGED);
50  cRW = (chg [wi].upper() != t_chg_bounds::UNCHANGED);
51  cLY = (chg [yi].lower() != t_chg_bounds::UNCHANGED);
52  cRY = (chg [yi].upper() != t_chg_bounds::UNCHANGED);
53  }
54 
55  // no convexification for terms x/y where y=0 is internal to the
56  // bounding box
57 
58  if ((yl < -0.) &&
59  (yu > 0.)) return;
60 
61  CouNumber k;
62 
63  enum auxSign sign = cg -> Problem () -> Var (wi) -> sign ();
64 
65  // special case #1: y is almost constant (nonzero) --> y = k. We
66  // only need a single plane w >/</= x/k.
67  if ((fabs (yl-yu) < COUENNE_EPS) &&
68  ((fabs (k = ((yl+yu) / 2)) > COUENNE_EPS))) {
69  if (cLY || cRY)
70  cg -> createCut (cs, 0., sign, wi, 1., xi, -1./k);
71  return;
72  }
73 
74  CouNumber wl, wu;
75  w -> getBounds (wl, wu);
76 
77  if (lbw > wl) wl = lbw;
78  if (ubw < wu) wu = ubw;
79 
80  // special case #2: w is almost constant (nonzero) --> w = x/y = k. We
81  // only need a single plane x >/</= y*k.
82 
83  if ((fabs (wl-wu) < COUENNE_EPS) &&
84  ((k = fabs (wl+wu) / 2) > COUENNE_EPS) &&
85  // extra condition: either y's bounds are both pos or both neg,
86  // or this is an equality
87  ((sign==expression::AUX_EQ) || (yl > 0.) || (yu < 0.))) {
88 
89  if (cLW || cRW) {
90  if (sign==expression::AUX_EQ || (yl > 0.)) cg -> createCut (cs, 0., sign, yi, k, xi, -1.);
91  else cg -> createCut (cs, 0., sign, yi, -k, xi, 1.);
92  }
93 
94  return;
95  }
96 
97  CouNumber xl, xu;
98  arglist_ [0] -> getBounds (xl, xu);
99 
100  if ((fabs (xl-xu) < COUENNE_EPS) &&
101  (fabs (yl-yu) < COUENNE_EPS) &&
102  (fabs (wl-wu) < COUENNE_EPS))
103  return; // not much to do here...
104 
105  // same as product, just a change in coordinates
106 
107  //CouNumber *x = w -> domain () -> x ();
108  CouNumber *x = cg -> Problem () -> X ();
109 
110  bool
111  ineqFullOrthantF = (((sign == expression::AUX_LEQ) && (yl > 0.)) || ((sign == expression::AUX_GEQ) && (yu < -0.))),
112  ineqFullOrthantB = (((sign == expression::AUX_LEQ) && (yu < -0.)) || ((sign == expression::AUX_GEQ) && (yl > 0.)));
113 
114  unifiedProdCuts (cg, cs,
115  wi, x [wi], wl, wu,
116  yi, x [yi], yl, yu,
117  xi, x [xi],
118  ineqFullOrthantF ? -COIN_DBL_MAX : xl,
119  ineqFullOrthantB ? COIN_DBL_MAX : xu,
120  chg,
121  ineqFullOrthantF ? expression::AUX_GEQ :
122  ineqFullOrthantB ? expression::AUX_LEQ :
124 }
Cut Generator for linear convexifications.
void unifiedProdCuts(const CouenneCutGenerator *, OsiCuts &, int, CouNumber, CouNumber, CouNumber, int, CouNumber, CouNumber, CouNumber, int, CouNumber, CouNumber, CouNumber, t_chg_bounds *, enum expression::auxSign)
unified convexification of products and divisions
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
const char & lower() const
virtual exprAux * standardize(CouenneProblem *, bool addAux=true)
generate auxiliary variable
Definition: exprOp.cpp:142
const char & upper() const
void getBounds(expression *&lb, expression *&ub)
Get lower and upper bound of an expression (if any)
Definition: exprDiv.cpp:159
virtual int Index() const
Return index of variable (only valid for exprVar and exprAux)
auxSign
&quot;sign&quot; of the constraint defining an auxiliary.
Class for MINLP problems with symbolic information.
void fint fint * k
#define COUENNE_EPS
expression ** arglist_
argument list is an array of pointers to other expressions
double CouNumber
main number type in Couenne
Auxiliary variable.
Expression base class.
exprAux * standardize(CouenneProblem *p, bool addAux=true)
Reduce expression in standard form, creating additional aux variables (and constraints) ...
void fint fint fint real fint real real real real real real real real * w
void fint fint fint real fint real * x
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.