1 /* $Id$
2  *
3  * Name:    expression.hpp
4  * Author:  Pietro Belotti
5  * Purpose: definition of the class expression
6  *
7  * (C) Carnegie-Mellon University, 2006-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #ifndef COUENNE_EXPRESSION_HPP
12 #define COUENNE_EXPRESSION_HPP
13 
14 #include <iostream>
15 #include <set>
16 #include <vector>
17 
18 #include "CouennePrecisions.hpp"
19 #include "CouenneTypes.hpp"
20 
21 class OsiBranchingInformation;
22 class OsiSolverInterface;
23 class OsiCuts;
24 
25 namespace Couenne {
26 
27 class CouenneProblem;
28 class CouenneCutGenerator;
29 class CouenneObject;
30 
31 class exprAux;
32 class exprCopy;
33 class exprVar;
34 
35 class DepNode;
36 class DepGraph;
37 
38 class Domain;
39 
40 struct compNode;
41 
42 /// Expression base class
43 ///
44 /// An empty expression class with no type or operator() from which
45 /// all other expression classes (for constants, variables, and
46 /// operators) are derived.
47 
48 class expression {
49 
50  public:
51 
52   /// "sign" of the constraint defining an auxiliary. If the auxiliary
53   /// is defined as \f$w \le f(x)\f$, then it is LEQ. It is EQ and GEQ,
54   /// respectively, if it is defined with \f$=\f$ and  \f$\ge\f$.
55   enum auxSign {AUX_UNDEF=-2, AUX_LEQ=-1, AUX_EQ, AUX_GEQ};
56 
57   /// Constructor
expression()58   expression () {}
59 
60   /// Copy constructor. Pass pointer to variable vector when
61   /// generating new problem, whose set of variables is equivalent but
62   /// may be changed or whose value is independent.
expression(const expression & e,Domain * d=NULL)63   expression (const expression &e, Domain *d = NULL) {}
64 
65   /// Destructor
~expression()66   virtual ~expression () {}
67 
68   /// Cloning method
clone(Domain * d=NULL) const69   virtual expression *clone (Domain *d = NULL) const
70   {return NULL;}
71 
72   /// Return index of variable (only valid for exprVar and exprAux)
Index() const73   virtual inline int Index () const
74   {return -1;}
75 
76   /// return number of arguments (when applicable, that is, with N-ary functions)
nArgs() const77   virtual inline int nArgs () const
78   {return 0;}
79 
80   /// return arglist (when applicable, that is, with N-ary functions)
ArgList() const81   virtual inline expression **ArgList () const
82   {return NULL;}
83 
84   /// set arglist (used in deleting nodes without deleting children)
ArgList(expression ** al)85   virtual inline void ArgList (expression **al) {}
86 
87   /// return argument (when applicable, i.e., with univariate functions)
Argument() const88   virtual inline expression *Argument () const
89   {return NULL;}
90 
91   /// return pointer to argument (when applicable, i.e., with univariate functions)
ArgPtr()92   virtual inline expression **ArgPtr ()
93   {return NULL;}
94 
95   /// node type
Type() const96   virtual inline enum nodeType Type () const
97   {return EMPTY;}
98 
99   /// return pointer to corresponding expression (for auxiliary variables only)
Image() const100   virtual inline expression *Image () const
101   {return NULL;}
102 
103   /// set expression associated with this auxiliary variable (for
104   /// compatibility with exprAux)
Image(expression * image)105   virtual void Image (expression *image) {}
106 
107   /// value (empty)
Value() const108   virtual inline CouNumber Value () const
109   {return 0.;}
110 
111   /// If this is an exprClone of a exprClone of an expr???, point to
112   /// the original expr??? instead of an exprClone -- improve computing
113   /// efficiency. Only overloaded for exprClones/exprCopy, of course.
Original() const114   virtual inline const expression *Original () const
115   {return this;}
116 
117   /// print expression to iostream
print(std::ostream & s=std::cout,bool=false) const118   virtual void print (std::ostream &s  = std::cout,   /// output stream
119 		      bool             = false) const /// descend into auxiliaries' image?
120   {s << '?';}
121 
122   /// null function for evaluating the expression
123   virtual CouNumber operator () () = 0;
124 
125   /// return l-2 norm of gradient at given point
gradientNorm(const double * x)126   virtual inline CouNumber gradientNorm (const double *x)
127   {return 0.;}
128 
129   /// differentiation
130   virtual expression *differentiate (int);
131 
132   /// dependence on variable set: return cardinality of subset of the
133   /// set of indices in first argument which occur in expression.
134   virtual int dependsOn (int *ind, int n, enum dig_type type = STOP_AT_AUX);
135 
136   /// version with one index only
dependsOn(int singleton,enum dig_type type=STOP_AT_AUX)137   inline int dependsOn (int singleton, enum dig_type type = STOP_AT_AUX)
138   {return dependsOn (&singleton, 1, type);}
139 
140   /// fill std::set with indices of variables on which this expression
141   /// depends. Also deal with expressions that have no variable
142   /// pointers (exprGroup, exprQuad)
DepList(std::set<int> & deplist,enum dig_type type=ORIG_ONLY)143   virtual inline int DepList (std::set <int> &deplist,
144 			      enum dig_type   type = ORIG_ONLY)
145   {return 0;}
146 
147   /// simplify expression (useful for derivatives)
simplify()148   virtual inline expression *simplify ()
149   {return NULL;}
150 
151   /// get a measure of "how linear" the expression is (see CouenneTypes.h)
Linearity()152   virtual inline int Linearity ()
153   {return NONLINEAR;}
154 
155   /// is this expression defined as an integer?
isDefinedInteger()156   virtual inline bool isDefinedInteger ()
157   {return isInteger ();}
158 
159   /// is this expression integer?
isInteger()160   virtual inline bool isInteger ()
161   {return false;}
162 
163   /// Get lower and upper bound of an expression (if any)
164   virtual void getBounds (expression *&, expression *&);
165 
166   /// Get lower and upper bound of an expression (if any) -- real values
167   virtual void getBounds (CouNumber &, CouNumber &);
168 
169   /// Create standard form of this expression, by:
170   ///
171   /// - creating auxiliary w variables and corresponding expressions
172   /// - returning linear counterpart as new constraint (to replace
173   ///   current one)
174   ///
175   /// For the base exprOp class we only do the first part (for argument
176   /// list components only), and the calling class (Sum, Sub, Mul, Pow,
177   /// and the like) will do the part for its own object
178   ///
179   /// addAux is true if a new auxiliary variable should be added
180   /// associated with the standardized expression
standardize(CouenneProblem * p,bool addAux=true)181   virtual inline exprAux *standardize (CouenneProblem *p, bool addAux = true)
182   {return NULL;}
183 
184   /// generate convexification cut for constraint w = this
generateCuts(expression * w,OsiCuts & cs,const CouenneCutGenerator * cg,t_chg_bounds * chg=NULL,int wind=-1,CouNumber lb=-COUENNE_INFINITY,CouNumber ub=COUENNE_INFINITY)185   virtual void generateCuts (expression *w, //const OsiSolverInterface &si,
186 			     OsiCuts &cs, const CouenneCutGenerator *cg,
187 			     t_chg_bounds *chg = NULL, int wind = -1,
188 			     CouNumber lb = -COUENNE_INFINITY,
189 			     CouNumber ub =  COUENNE_INFINITY) {}
190 
191   /// return integer for comparing expressions (used to recognize
192   /// common expression)
code()193   virtual enum expr_type code ()
194   {return COU_EXPRESSION;}
195 
196   /// either CONVEX, CONCAVE, AFFINE, or NONCONVEX
convexity() const197   virtual enum convexity convexity () const
198   {return NONCONVEX;}
199 
200   /// compare expressions
201   virtual int compare (expression &);
202 
203   /// compare copies of expressions
204   virtual int compare (exprCopy   &);
205 
206   /// used in rank-based branching variable choice: original variables
207   /// have rank 1; auxiliary w=f(x) has rank r(w) = r(x)+1; finally,
208   /// auxiliary w=f(x1,x2...,xk) has rank r(w) = 1+max{r(xi):i=1..k}.
rank()209   virtual int rank ()
210   {return -1;} // return null rank
211 
212   /// does a backward implied bound processing on every expression,
213   /// including exprSums although already done by Clp (useful when
214   /// repeated within Couenne). Parameters are the index of the
215   /// (auxiliary) variable in question and the current lower/upper
216   /// bound. The method returns true if there has been a change on any
217   /// bound on the variables on which the expression depends.
impliedBound(int,CouNumber *,CouNumber *,t_chg_bounds *,enum auxSign=expression::AUX_EQ)218   virtual bool impliedBound (int, CouNumber *, CouNumber *, t_chg_bounds *, enum auxSign = expression::AUX_EQ)
219   {return false;}
220 
221   /// multiplicity of a variable
Multiplicity()222   virtual inline int Multiplicity ()
223   {return 1;}
224 
225   /// set up branching object by evaluating many branching points for
226   /// each expression's arguments. Return estimated improvement in
227   /// objective function
selectBranch(const CouenneObject * obj,const OsiBranchingInformation * info,expression * & var,double * & brpts,double * & brDist,int & way)228   virtual CouNumber selectBranch (const CouenneObject *obj,
229 				  const OsiBranchingInformation *info,
230 				  expression * &var,
231 				  double * &brpts,
232 				  double * &brDist, // distance of current LP
233 						    // point to new convexifications
234 				  int &way)
235   {var = NULL; return 0.;}
236 
237   /// replace expression with another
replace(exprVar *,exprVar *)238   virtual void replace (exprVar *, exprVar *) {}
239 
240   /// update dependence set with index of variables on which this
241   /// expression depends
fillDepSet(std::set<DepNode *,compNode> *,DepGraph *)242   virtual void fillDepSet (std::set <DepNode *, compNode> *, DepGraph *) {}
243 
244   /// empty function to update domain pointer
linkDomain(Domain * d)245   virtual void linkDomain (Domain *d) {}
246 
247   /// empty function to redirect variables to proper variable vector
realign(const CouenneProblem * p)248   virtual void realign (const CouenneProblem *p) {}
249 
250   /// indicating if function is monotonically increasing
isBijective() const251   virtual bool isBijective() const
252   {return false;}
253 
254   /// compute the inverse function
inverse(expression * vardep) const255   virtual CouNumber inverse (expression *vardep) const
256   {return -COUENNE_INFINITY;}
257 
258   /// closest feasible points in function in both directions
259   virtual void closestFeasible (expression *varind, expression *vardep,
260 				CouNumber& left, CouNumber& right) const;
261 
262   /// can this expression be further linearized or are we on its
263   /// concave ("bad") side
isCuttable(CouenneProblem * problem,int index) const264   virtual bool isCuttable (CouenneProblem *problem, int index) const
265   {return true;}
266 
267   /// return true if this is a copy of something (i.e. an exprCopy)
isaCopy() const268   virtual bool isaCopy () const
269   {return false;}
270 
271   /// return copy of this expression (only makes sense in exprCopy)
Copy() const272   virtual expression *Copy () const
273   {return NULL;}
274 };
275 
276 
277 /// updates maximum violation. Used with all impliedBound. Returns true
278 /// if a bound has been modified, false otherwise
updateBound(register int sign,register CouNumber * dst,register CouNumber src)279 inline bool updateBound (register int sign,
280 			 register CouNumber *dst,
281 			 register CouNumber src) {
282 
283   // meaning:
284   //
285   // if (*dst > src) && (sign > 0) --> dst down to src
286   // if (*dst < src) && (sign < 0) --> dst up   to src
287   //
288   // that is, sign > 0 means we are tightening an UPPER bound
289   //          sign < 0                            LOWER
290 
291   register double delta = (sign > 0) ? (*dst - src) : (src - *dst);
292 
293   if (delta > 0.) {
294     //printf ("%.12g --> %.12g\n", *dst, src);
295     *dst = src; // tighten
296     return (delta > COUENNE_EPS); // avoid returning true when improvement is negligible
297   }
298 
299   return false;
300 }
301 
302 
303 /// independent comparison
compareExpr(const void * e0,const void * e1)304 inline int compareExpr (const void *e0, const void *e1)
305 {return ((*(expression **) e0) -> compare (**(expression **)e1));}
306 
307 
308 /// is this number integer?
isInteger(CouNumber x)309 inline bool isInteger (CouNumber x)
310 {return (fabs (COUENNE_round (x) - x) < COUENNE_EPS_INT);}
311 
312 
313 /// get original expression (can't make it an expression method as I
314 /// need a non-const, what "this" would return)
getOriginal(expression * e)315 inline expression *getOriginal (expression *e) {
316 
317   if (e -> isaCopy ()) return getOriginal (e -> Copy ());
318   else return e;
319 }
320 
321 /// Macro to return already simplified expression without having to do
322 /// the if part every time simplify () is called
Simplified(expression * complicated)323 inline expression *Simplified (expression *complicated) {
324 
325   expression *simpler = complicated -> simplify ();
326 
327   if (simpler) {
328     delete complicated;
329     return simpler;
330   } else return complicated;
331 }
332 
333 }
334 
335 #endif
336