exprOp.cpp
Go to the documentation of this file.
1 /* $Id: exprOp.cpp 1147 2015-05-04 14:01:51Z stefan $
2  *
3  * Name: exprOp.cpp
4  * Author: Pietro Belotti
5  * Purpose: methods for multivariate function class
6  *
7  * (C) Carnegie-Mellon University, 2006-08.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CouenneExpression.hpp"
12 #include "CouenneExprAux.hpp"
13 #include "CouenneExprClone.hpp"
14 #include "CouenneExprOp.hpp"
15 #include "CouenneExprGroup.hpp"
16 #include "CouenneExprQuad.hpp"
17 #include "CouenneExprConst.hpp"
18 #include "CouennePrecisions.hpp"
19 
20 #include <cstdio>
21 
22 using namespace Couenne;
23 
24 namespace Couenne {
25 class CouenneProblem;
26 class Domain;
27 }
28 
29 // General N-ary function destructor
31 
32  if (arglist_) {
33  for (expression **alist = arglist_; nargs_--; alist++)
34  if (*alist) delete (*alist);
35  delete [] arglist_;
36  }
37 }
38 
39 
40 // print expression
41 
42 void exprOp::print (std::ostream &out,
43  bool descend) const {
44 
45  if (printPos () == PRE)
46  out << printOp ();
47 
48  if (nargs_ > 1)
49  {out << "("; fflush (stdout);}
50  for (int i=0; i<nargs_; i++) {
51  if (arglist_ [i])
52  arglist_ [i] -> print (out, descend);
53  fflush (stdout);
54  if (i < nargs_ - 1) {
55  if (printPos () == INSIDE) out << printOp ();
56  else out << ",";
57  }
58  if (!((i + 1) % MAX_ARG_LINE))
59  out << std::endl;
60  fflush (stdout);
61  }
62  if (nargs_ > 1) {
63  out << ")";
64  fflush (stdout);
65  }
66 }
67 
68 
70 
72 
73  int c0 = code (),
74  c1 = e1. code ();
75 
76  if (c0 < c1) return -1;
77  if (c0 > c1) return 1;
78 
79  // have to compare arguments one by one
80  if (nargs_ < e1.nargs_) return -1;
81  if (nargs_ > e1.nargs_) return 1;
82 
83  // not an exprGroup, compare arguments
84  for (register int i = nargs_; i--;) {
85 
86  int res = arglist_ [i] -> compare (*(e1. ArgList () [i]));
87  if (res) return res;
88  }
89 
90  // last chance, this might be an exprGroup or derived
91  if ((c0 == COU_EXPRGROUP) ||
92  (c0 == COU_EXPRQUAD)) {
93 
94  exprGroup *ne0 = dynamic_cast <exprGroup *> (this),
95  *ne1 = dynamic_cast <exprGroup *> (&e1);
96 
97  int cg = ne0 -> compare (*ne1);
98 
99  if (cg) return cg; // exprGroup
100 
101  // last chance, the two are quadratic forms
102 
103  if (c0 == COU_EXPRQUAD) {
104 
105  exprQuad *ne0 = dynamic_cast <exprQuad *> (this),
106  *ne1 = dynamic_cast <exprQuad *> (&e1);
107 
108  return ne0 -> compare (*ne1);
109  }
110  }
111 
112  return 0;
113 }
114 
115 
117 
118 int exprOp::rank () {
119 
120  int maxrank = -1;
121 
122  for (expression **al = arglist_ + nargs_;
123  al-- > arglist_;) {
124  int r = (*al) -> rank ();
125  if (r > maxrank) maxrank = r;
126  }
127 
128  return (maxrank);
129 }
130 
131 
132 // Create standard formulation of this expression, by:
133 //
134 // - creating auxiliary w variables and corresponding expressions
135 // - returning linear counterpart as new constraint (to replace
136 // current one)
137 //
138 // For the base exprOp class we only do the first part (for argument
139 // list components only), and the calling class (Sum, Sub, Mul, Pow,
140 // and the like) will do the part for its own object
141 
143 
144  exprVar *subst;
145 
146  for (int i = 0; i < nargs_; ++i)
147  if ((subst = arglist_ [i] -> standardize (p))) {
148 
149  if ((subst -> Type () == VAR) ||
150  (subst -> Type () == AUX))
151  arglist_ [i] = new exprClone (subst);
152  else arglist_ [i] = subst; // possibly a constant, should be nothing else
153  }
154  return NULL;
155 }
156 
157 
160 
161  expression **al = arglist_;
162  int index = x -> Index ();
163 
164  for (register int i = nargs_; i--; al++)
165 
166  switch ((*al) -> Type ()) {
167 
168  case AUX:
169  case VAR:
170  if ((*al) -> Index () == index) {
171  delete *al;
172  *al = new exprClone (w);
173  }
174  break;
175 
176  case UNARY:
177  case N_ARY:
178  (*al) -> replace (x, w);
179  break;
180 
181  default:
182  break;
183  }
184 }
185 
186 
189 
190  for (int i = nargs_; i--;)
191 
192  if (!(arglist_ [i] -> isInteger ())) {
193 
194  // this argument is not integer: check if constant and integer
195 
196  CouNumber lb, ub;
197  arglist_ [i] -> getBounds (lb, ub);
198 
199  if ((fabs (lb - ub) > COUENNE_EPS) ||
200  !::isInteger (lb))
201  return false;
202  }
203 
204  return true;
205 }
206 
207 
210 int exprOp::DepList (std::set <int> &deplist,
211  enum dig_type type) {
212  int tot = 0;
213 
214  //printf (" exprop::deplist of %x: ", Original ()); print (); printf ("\n");
215 
216  for (int i = nargs_; i--;) {
217 
218  /*printf (" ");
219  arglist_ [i] -> print (); printf (": {");
220  for (std::set <int>::iterator j=deplist.begin(); j != deplist.end(); ++j)
221  printf ("%d ", *j);
222  printf ("} -> {");*/
223 
224  tot += arglist_ [i] -> DepList (deplist, type);
225 
226  /*for (std::set <int>::iterator j=deplist.begin(); j != deplist.end(); ++j)
227  printf ("%d ", *j);
228  printf ("}\n");*/
229  }
230 
231  return tot;
232 }
233 
236 
237  for (int i=0; i<nargs_; i++)
238  arglist_ [i] -> realign (p);
239 }
240 
241 
242 // simplify n-ary expression f (g_1(x), g_2(x)... g_n(x))
244 
245  // Simplify arguments g_1(x), g_2(x)... g_n(x) first
246  for (int i=0; i<nargs_; i++) {
247 
248  expression *subst;
249 
250  if ((subst = arglist_ [i] -> simplify ())) {
251 
252  delete arglist_ [i];
253  arglist_ [i] = subst;
254  }
255  }
256 
257  return NULL;
258 }
259 
260 
261 //
262 // shrink argument list
263 //
264 // used by + and * (for now), accepts a constant resulting from
265 // applying an operator to the constants in the list of (pointers to)
266 // function arguments contained in el. The constant is inserted in the
267 // list if the result is not equal to null_element or if there are
268 // other non-constant terms in the arglist.
269 //
270 // Example: f(x) + 3 + g(x) + 2 + 4
271 //
272 // el = {pf, NULL, pg, NULL, NULL}
273 // nargs = 5
274 // c = 3 + 2 + 4 = 9
275 // null_element = 0 (for sums)
276 //
277 // where pf and pg are pointers to expression containing f and g,
278 // resp.
279 //
280 // Result: el and nargs are changed to
281 //
282 // el = {pf, p9, pg}
283 // nargs = 3
284 //
285 // Another example: f(x) + 2 + g(x) + (-4) + 2
286 // Result:
287 // el = {pf, pg}
288 // nargs = 2
289 //
290 // Another example: f(x) * 3 * g(x) * 2
291 //
292 // el = {pf, NULL, pg, NULL}
293 // nargs = 4
294 // c = 3 * 2 = 6 != null_element = 1 (for multiplications)
295 // Result:
296 // el = {pf, p6, pg}
297 // nargs = 3
298 //
299 
301 
302  register int i=0, j=0;
303 
304  bool one_fun = false;
305 
306  // find first NULL spot (left by some constant)
307  while ((i < nargs_) && (arglist_ [i]))
308  i++;
309 
310  // no spots, leave
311  if (i==nargs_)
312  return 0;
313 
314  // check if there is at least one non-constant expression
315  for (register int k=nargs_; k--;)
316  if (arglist_ [k]) {
317  one_fun = true;
318  break;
319  }
320 
321  // add constant term if c is not null w.r.t. the operation or if it
322  // would be an empty operand list otherwise
323  if ((fabs (c - null_element) > COUENNE_EPS) || !one_fun)
324  arglist_ [i++] = new exprConst (c);
325 
326  j = i;
327 
328  // now shift back all operands to compress argument list
329  while (i < nargs_) {
330 
331  while ((i < nargs_) && !(arglist_ [i]))
332  i++;
333 
334  if (i < nargs_)
335  one_fun = true;
336 
337  while ((i < nargs_) && (arglist_ [i]))
338  arglist_ [j++] = arglist_ [i++];
339  }
340 
341  nargs_ = j;
342 
343  // only say shrinking simplified arg list if there is just the
344  // constant
345  return (nargs_ == 1);// && ((fabs (c - null_element) > COUENNE_EPS) || !one_fun));
346 }
virtual ~exprOp()
Destructor.
Definition: exprOp.cpp:30
virtual void print(std::ostream &out=std::cout, bool=false) const
I/O.
Definition: exprOp.cpp:42
class Group, with constant, linear and nonlinear terms:
#define MAX_ARG_LINE
int shrink_arglist(CouNumber, CouNumber)
compress argument list
Definition: exprOp.cpp:300
virtual bool isInteger()
is this expression integer?
Definition: exprOp.cpp:188
virtual exprAux * standardize(CouenneProblem *, bool addAux=true)
generate auxiliary variable
Definition: exprOp.cpp:142
virtual enum pos printPos() const
print position (PRE, INSIDE, POST)
virtual void realign(const CouenneProblem *p)
empty function to redirect variables to proper variable vector
Definition: exprOp.cpp:235
constant-type operator
Long e1
Definition: OSdtoa.cpp:1815
static char * j
Definition: OSdtoa.cpp:3622
virtual int DepList(std::set< int > &deplist, enum dig_type type=ORIG_ONLY)
fill in the set with all indices of variables appearing in the expression
Definition: exprOp.cpp:210
virtual int rank()
used in rank-based branching variable choice
Definition: exprOp.cpp:118
virtual enum nodeType Type() const
Node type.
virtual int Index() const
Return index of variable (only valid for exprVar and exprAux)
Class for MINLP problems with symbolic information.
void fint fint * k
expression clone (points to another expression)
#define COUENNE_EPS
void fint fint fint real fint real real real real real real real * r
virtual enum expr_type code()
return code to classify type of expression
virtual expression * simplify()
simplification
Definition: exprOp.cpp:243
expression ** ArgList() const
return argument list
expression ** arglist_
argument list is an array of pointers to other expressions
double CouNumber
main number type in Couenne
int nargs_
number of arguments (cardinality of arglist)
general n-ary operator-type expression: requires argument list.
virtual void getBounds(expression *&, expression *&)
Get lower and upper bound of an expression (if any)
Definition: expression.cpp:32
class exprQuad, with constant, linear and quadratic terms
Auxiliary variable.
dig_type
type of digging when filling the dependence list
virtual std::string printOp() const
print operator
variable-type operator
Expression base class.
virtual void replace(exprVar *, exprVar *)
replace variable with other
Definition: exprOp.cpp:159
void fint fint fint real fint real real real real real real real real * w
real c
virtual int compare(exprOp &)
compare with other generic exprOp
Definition: exprOp.cpp:71
Define a dynamic point+bounds, with a way to save and restore previous points+bounds through a LIFO s...
void fint fint fint real fint real * x