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