1 /* $Id$
2  *
3  * Name:    exprDiv.hpp
4  * Author:  Pietro Belotti
5  * Purpose: definition of divisions
6  *
7  * (C) Carnegie-Mellon University, 2006-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #ifndef COUENNE_EXPRDIV_HPP
12 #define COUENNE_EXPRDIV_HPP
13 
14 #include "CouenneExprOp.hpp"
15 #include "CouennePrecisions.hpp"
16 
17 namespace Couenne {
18 
19 #define BR_NEXT_ZERO 1e-3
20 #define BR_MULT      1e-3
21 
22 /// class for divisions, \f$ \frac{f(x)}{g(x)} \f$
23 
24 class exprDiv: public exprOp {
25 
26  public:
27 
28   /// Constructor
exprDiv(expression ** al,int n=2)29   exprDiv (expression **al, int n = 2):
30     exprOp (al, n) {} //< non-leaf expression, with argument list
31 
32   /// Constructor with two arguments given explicitly
exprDiv(expression * arg0,expression * arg1)33   exprDiv (expression *arg0, expression *arg1):
34     exprOp (arg0, arg1) {}
35 
36   /// Cloning method
clone(Domain * d=NULL) const37   expression *clone (Domain *d = NULL) const
38     {return new exprDiv (clonearglist (d), nargs_);}
39 
40   /// Print operator
printOp() const41   std::string printOp () const
42     {return "/";}
43 
44   /// Function for the evaluation of the expression
45   inline CouNumber operator () ();
46 
47   /// return l-2 norm of gradient at given point
48   CouNumber gradientNorm (const double *x);
49 
50   /// Differentiation
51   expression *differentiate (int index);
52 
53   /// Simplification
54   expression *simplify ();
55 
56   /// Get a measure of "how linear" the expression is (see CouenneTypes.h)
Linearity()57   inline int Linearity () {
58 
59     if (arglist_ [1] -> Type () == CONST)
60       return arglist_ [0] -> Linearity ();
61     else return NONLINEAR;
62   }
63 
64   /// Get lower and upper bound of an expression (if any)
65   void getBounds (expression *&lb, expression *&ub);
66 
67   /// Get value of lower and upper bound of an expression (if any)
68   void getBounds (CouNumber &lb, CouNumber &ub);
69 
70   /// Reduce expression in standard form, creating additional aux
71   /// variables (and constraints)
72   exprAux *standardize (CouenneProblem *p, bool addAux = true);
73 
74   /// Generate equality between *this and *w
75   void generateCuts (expression *w, //const OsiSolverInterface &si,
76 		     OsiCuts &cs, const CouenneCutGenerator *cg,
77 		     t_chg_bounds * = NULL, int = -1,
78 		     CouNumber = -COUENNE_INFINITY,
79 		     CouNumber =  COUENNE_INFINITY);
80 
81   /// Code for comparisons
code()82   virtual enum expr_type code () {return COU_EXPRDIV;}
83 
84   /// is this expression integer?
85   bool isInteger ();
86 
87   /// Implied bound processing
88   bool impliedBound (int, CouNumber *, CouNumber *, t_chg_bounds *, enum auxSign = expression::AUX_EQ);
89 
90   /// Set up branching object by evaluating many branching points for
91   /// each expression's arguments
92   virtual CouNumber selectBranch (const CouenneObject *obj,
93 				  const OsiBranchingInformation *info,
94 				  expression * &var,
95 				  double * &brpts,
96  				  double * &brDist, // distance of current LP
97 					  	    // point to new convexifications
98 				  int &way);
99 
100   /// compute $y^{lv}$ and  $y^{uv}$ for Violation Transfer algorithm
101   virtual void closestFeasible (expression *varind,
102 				expression *vardep,
103 				CouNumber &left,
104 				CouNumber &right) const;
105 
106   /// can this expression be further linearized or are we on its
107   /// concave ("bad") side
isCuttable(CouenneProblem * problem,int index) const108   virtual bool isCuttable (CouenneProblem *problem, int index) const
109   {return false;} // concave on both sides, as for products
110 };
111 
112 
113 /// Compute division
114 
operator ()()115 inline CouNumber exprDiv::operator () ()
116   {return ((*(*arglist_)) () / (*(arglist_ [1])) ());}
117 
118 
119 #define SAFE_COEFFICIENT 1e9
120 
121 /// check if bounding box is suitable for a multiplication/division
122 /// convexification constraint
123 
is_boundbox_regular(register CouNumber b1,register CouNumber b2)124 inline bool is_boundbox_regular (register CouNumber b1, register CouNumber b2) {
125 
126   // Why SAFE_COEFFICIENT and not COUENNE_INFINITY? Because
127   // OsiRowCut::set[LU]b do not work for values more than
128   // SAFE_COEFFICIENT and apparently makes the convexification
129   // infeasible.
130   return
131     (fabs (b1)    < SAFE_COEFFICIENT) &&
132     (fabs (b2)    < SAFE_COEFFICIENT) &&
133     (fabs (b1*b2) < SAFE_COEFFICIENT);
134     //    && ((fabs (b1) > COUENNE_EPS) || (fabs (b2) > COUENNE_EPS));
135 }
136 
137 }
138 
139 #endif
140