exprGroup.cpp
Go to the documentation of this file.
1 /* $Id: exprGroup.cpp 1273 2019-02-23 17:29:55Z stefan $
2  *
3  * Name: exprGroup.cpp
4  * Author: Pietro Belotti
5  * Purpose: implementation of some methods for exprGroup
6  *
7  * (C) Carnegie-Mellon University, 2006-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CouenneExprConst.hpp"
12 #include "CouenneExprVar.hpp"
13 #include "CouenneExprGroup.hpp"
14 #include "CouenneExprClone.hpp"
15 #include "CouenneExprMul.hpp"
16 #include "CouenneDepGraph.hpp"
17 #include "CouenneProblem.hpp"
18 
19 #include <cassert>
20 
21 using namespace Couenne;
22 
23 namespace Couenne {
24 class Domain;
25 }
26 
27 // eliminates elements with zero coefficients
28 void cleanZeros (std::vector <std::pair <exprVar *, CouNumber> > &lcoeff) {
29 
30  std::vector <std::pair <exprVar *, CouNumber> >::iterator i = lcoeff.begin ();
31 
32  int ind = 0;
33  size_t size = lcoeff.size ();
34 
35  while (size-- > 0) {
36  if (i -> second == 0.) { // or equivalently, i -> second == -0.
37  lcoeff.erase (i);
38  i = lcoeff.begin () + ind;
39  } else {
40  ++i;
41  ++ind;
42  }
43  }
44 }
45 
46 
47 
51  std::vector <std::pair <exprVar *, CouNumber> > &lcoeff,
52  expression **al,
53  int n) {
54  size_t nl = lcoeff.size ();
55  expression *ret = NULL;
56 
58 
59  // a constant
60  if ((n==0) && (nl==0))
61  ret = new exprConst (c0); // a constant auxiliary? FIX!
62 
63  else if ((n==0) && (fabs (c0) < COUENNE_EPS) && (nl==1)) { // a linear monomial, cx
64 
65  if (fabs (lcoeff[0]. second - 1) < COUENNE_EPS)
66  ret = new exprClone (lcoeff[0]. first);
67  else ret = new exprMul (new exprConst (lcoeff[0]. second), new exprClone (lcoeff[0]. first));
68 
69  } else ret = new exprGroup (c0, lcoeff, al, n);
70 
71  return ret;
72 }
73 
74 
77  std::vector <std::pair <exprVar *, CouNumber> > &lcoeff,
78  expression **al,
79  int n):
80  exprSum (al, n),
81  lcoeff_ (lcoeff),
82  c0_ (c0) {
83 
85 }
86 
87 
90  exprSum (src.clonearglist (d), src.nargs_),
91  c0_ (src.c0_) {
92 
93  for (lincoeff::iterator i = src.lcoeff_.begin (); i != src.lcoeff_.end (); ++i)
94 
95  lcoeff_ . push_back (std::pair <exprVar *, CouNumber>
96  //(dynamic_cast <exprVar *> (i -> first -> clone (d)), i -> second));
97  (new exprVar (i -> first -> Index (), d), i -> second));
98 }
99 
100 
103 
104  for (lincoeff::iterator i = lcoeff_.begin (); i != lcoeff_.end (); ++i) {
105  enum expr_type code = i -> first -> code ();
106  if ((code == COU_EXPRLBOUND) ||
107  (code == COU_EXPRUBOUND))
108  delete i -> first;
109  }
110 }
111 
112 
114 void exprGroup::print (std::ostream &out, bool descend) const {
115 
116  //if (code () == COU_EXPRGROUP)
117  if (lcoeff_.size () > 0)
118  out << '(';
119 
120  bool nzNL = nargs_ && ((nargs_ > 1) ||
121  ((*arglist_) -> Type () != CONST) ||
122  (fabs ((*arglist_) -> Value ()) > COUENNE_EPS));
123 
124  if (nzNL)
125  exprSum::print (out, descend);
126 
127  if (c0_ > 0.) {if (nzNL) out << '+'; out << c0_;}
128  else if (c0_ < - 0.) out << c0_;
129 
130  for (size_t n = lcoeff_.size (), i=0; n--; i++) {
131 
132  CouNumber coeff = lcoeff_ [i]. second;
133 
134  if (coeff > 0.) { if (i || (c0_ != 0.) || nzNL) out << '+'; if (coeff != 1.) out << coeff << "*";}
135  else if (coeff < - 0.) { out << '-'; if (coeff != -1.) out << -coeff << "*";}
136 
137  lcoeff_ [i]. first -> print (out, descend);
138  if (!((i + 1) % MAX_ARG_LINE) && n)
139  out << std::endl;
140  }
141 
142  //if (code () == COU_EXPRGROUP)
143  if (lcoeff_.size () > 0)
144  out << ')';
145 }
146 
147 
150 
151  expression **arglist = new expression * [nargs_ + 1];
152 
153  CouNumber totlin=0;
154 
155  for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
156  if (el -> first -> Index () == index)
157  totlin += el -> second;
158 
159  int nargs = 0;
160 
161  if (fabs (totlin) > COUENNE_EPS)
162  arglist [nargs++] = new exprConst (totlin);
163 
164  for (int i = 0; i < nargs_; i++)
165  if (arglist_ [i] -> dependsOn (&index, 1))
166  arglist [nargs++] = arglist_ [i] -> differentiate (index);
167 
168  if ((nargs == 0) ||
169  ((nargs == 1) && (fabs (totlin) > COUENNE_EPS))) {
170  delete [] arglist;
171  return new exprConst (totlin);
172  }
173  else return new exprSum (arglist, nargs);
174 }
175 
176 
179 
180  int
181  nllin = exprSum::Linearity (), // linearity of nonlinear part
182  llin = (lcoeff_.size () == 0) ? // linear part
183  ((fabs (c0_) < COUENNE_EPS) ? ZERO : CONSTANT) :
184  LINEAR;
185 
186  return (llin > nllin) ? llin : nllin;
187 }
188 
189 
192 
193  // !!! why?
194 
195  //int sum = exprSum::compare (e);
196 
197  //if (sum != 0)
198  //return sum;
199 
200  if (c0_ < e.c0_ - COUENNE_EPS) return -1;
201  if (c0_ > e.c0_ + COUENNE_EPS) return 1;
202 
203  if (lcoeff_.size () < e.lcoeff_.size ()) return -1;
204  if (lcoeff_.size () > e.lcoeff_.size ()) return 1;
205 
206  for (lincoeff::iterator
207  el1 = lcoeff_.begin (),
208  el2 = e.lcoeff_.begin ();
209  el1 != lcoeff_.end ();
210  ++el1, ++el2) {
211 
212  int
213  ind1 = el1 -> first -> Index (),
214  ind2 = el2 -> first -> Index ();
215 
216  CouNumber
217  coe1 = el1 -> second,
218  coe2 = el2 -> second;
219 
220  if (ind1 < ind2) return -1;
221  if (ind1 > ind2) return 1;
222 
223  if (coe1 < coe2 - COUENNE_EPS) return -1;
224  if (coe1 > coe2 + COUENNE_EPS) return 1;
225  }
226 
227  return 0;
228 }
229 
230 
232 
234 
235  int maxrank = exprOp::rank ();
236 
237  if (maxrank < 0)
238  maxrank = 0;
239 
240  for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
241 
242  int r = el -> first -> rank ();
243  if (r > maxrank)
244  maxrank = r;
245  }
246 
247  return maxrank;
248 }
249 
250 
252 void exprGroup::fillDepSet (std::set <DepNode *, compNode> *dep, DepGraph *g) {
253 
254  exprOp::fillDepSet (dep, g);
255 
256  for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
257  dep -> insert (g -> lookup (el -> first -> Index ()));
258 }
259 
260 
263 int exprGroup::DepList (std::set <int> &deplist,
264  enum dig_type type) {
265 
266  int deps = exprOp::DepList (deplist, type);
267 
268  for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
269 
270  /*printf ("before [");
271  el -> first -> print ();
272  printf ("]: {");
273  for (std::set <int>::iterator i=deplist.begin (); i != deplist.end(); ++i)
274  printf ("%d ", *i);*/
275 
276  deps += el -> first -> DepList (deplist, type);
277 
278  /*printf ("}, after: {");
279  for (std::set <int>::iterator i=deplist.begin (); i != deplist.end(); ++i)
280  printf ("%d ", *i);
281  printf ("}\n");*/
282  }
283 
284  return deps;
285 }
286 
287 
290 
291  if (!(::isInteger (c0_)) ||
292  !(exprOp::isInteger ()))
293  return false;
294 
295  for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
296 
297  CouNumber coe = el -> second;
298 
299  bool
300  intCoe = ::isInteger (coe),
301  intVar = el -> first -> isInteger ();
302 
303  if (intCoe && intVar)
304  continue;
305 
306  CouNumber
307  lb = el -> first -> lb (),
308  ub = el -> first -> ub ();
309 
310  // check var fixed and product is integer
311  if ((fabs (lb - ub) < COUENNE_EPS) &&
312  (::isInteger (lb * coe) ||
313  (intCoe && ::isInteger (lb))))
314  continue;
315 
316  return false;
317  }
318 
319  return true;
320 }
321 
322 
325 
326  exprOp::replace (x, w);
327 
328  int
329  xind = x -> Index (),
330  wind = w -> Index ();
331 
332  // find occurrences of x and w in vector of variabls
333 
334  lincoeff::iterator x_occur = lcoeff_.begin ();
335 
336  // Do not assume index vector is sorted in ascending order
337  // w.r.t. (*iterator) -> first () -> Index()
338  while ((x_occur != lcoeff_.end ()) &&
339  (x_occur -> first -> Index () != xind))
340  ++x_occur;
341 
342  if (x_occur == lcoeff_ .end ()) // not found, bail out
343  return;
344 
345  if (xind == wind)
346  x_occur -> first = w;
347  else { // replacing two variables, not the features of one
348 
349  lincoeff::iterator w_occur = lcoeff_.begin ();
350 
351  // Do not assume index vector is sorted in ascending order
352  // w.r.t. (*iterator) -> first () -> Index()
353  while ((w_occur != lcoeff_.end ()) &&
354  (w_occur -> first -> Index () != wind))
355  ++w_occur;
356 
357  if (w_occur == lcoeff_ . end ()) // not found w, simply substitute
358  x_occur -> first = w;
359  else {
360  if ((w_occur -> second += x_occur -> second) == 0.) { // add coefficients
361  lcoeff_.erase (w_occur); // if they cancel out, delete w as well
362 
363  // under Microsoft, x_occur may have been invalidated by removing w_occur from lcoeff_, so we search for it again
364  for( x_occur = lcoeff_.begin (); x_occur -> first -> Index () != xind; ++x_occur )
365  assert(x_occur != lcoeff_ .end ()); // it was found before, so it should be still found
366  }
367  lcoeff_.erase (x_occur); // delete entry of x
368  }
369  }
370 }
371 
372 
376 
377  CouNumber retval = 0;
378 
379  for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
380  retval += el -> second * el -> second;
381 
382  return sqrt (retval);
383 }
384 
385 
388 
389  for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
390 
391  exprVar *var = el -> first;
392 
393  if (((var -> Type () == VAR) ||
394  (var -> Type () == AUX)) &&
395  (var -> Original () != p -> Var (var -> Index ()))) {
396 
397  expression *trash = var;
398  el -> first = p -> Var (var -> Index ());
399  delete trash;
400  }
401  }
402 }
403 
404 
407  exprOp::simplify ();
408  //if (lcoeff_. size () <= 0) // this is just a constant
409  //return new exprConst (c0_);
410  //else
411  return NULL;
412 }
413 
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: exprGroup.cpp:263
virtual void print(std::ostream &out=std::cout, bool=false) const
I/O.
Definition: exprOp.cpp:42
virtual int dependsOn(int *ind, int n, enum dig_type type=STOP_AT_AUX)
dependence on variable set: return cardinality of subset of the set of indices in first argument whic...
Definition: expression.cpp:172
virtual ~exprGroup()
Destructor – needed to clear bounds.
Definition: exprGroup.cpp:102
virtual void fillDepSet(std::set< DepNode *, compNode > *, DepGraph *)
update dependence set with index of this variable
Definition: exprGroup.cpp:252
virtual int Linearity()
get a measure of &quot;how linear&quot; the expression is:
Definition: exprGroup.cpp:178
class Group, with constant, linear and nonlinear terms:
virtual CouNumber gradientNorm(const double *x)
return l-2 norm of gradient at given point
Definition: exprGroup.cpp:375
#define MAX_ARG_LINE
virtual bool isInteger()
is this expression integer?
Definition: exprGroup.cpp:289
virtual void print(std::ostream &=std::cout, bool=false) const
Print expression to iostream.
Definition: exprGroup.cpp:114
virtual bool isInteger()
is this expression integer?
Definition: exprOp.cpp:188
virtual void replace(exprVar *x, exprVar *w)
replace variable x with new (aux) w
Definition: exprGroup.cpp:324
exprSum(expression **=NULL, int=0)
Constructors, destructor.
Definition: exprSum.cpp:20
lincoeff & lcoeff() const
return linear term coefficients
CouNumber c0_
constant term
virtual expression * simplify()
simplification
Definition: exprGroup.cpp:406
virtual int rank()
used in rank-based branching variable choice
Definition: exprGroup.cpp:233
constant-type operator
void cleanZeros(std::vector< std::pair< exprVar *, CouNumber > > &lcoeff)
Definition: exprGroup.cpp:28
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
static expression * genExprGroup(CouNumber, lincoeff &, expression **=NULL, int=0)
Generalized (static) constructor: check parameters and return a constant, a single variable...
Definition: exprGroup.cpp:50
exprGroup(CouNumber, lincoeff &, expression **=NULL, int=0)
Constructor.
virtual enum expr_type code()
code for comparisons
void fint fint fint real fint real real real real real real real real real * e
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)
fint end
lincoeff lcoeff_
coefficients and indices of the linear term
Class for MINLP problems with symbolic information.
expression clone (points to another expression)
#define COUENNE_EPS
void fint fint fint real fint real real real real real real real * r
virtual expression * simplify()
simplification
Definition: exprOp.cpp:243
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)
virtual int compare(exprGroup &)
only compare with people of the same kind
Definition: exprGroup.cpp:191
Dependence graph.
dig_type
type of digging when filling the dependence list
variable-type operator
expr_type
code returned by the method expression::code()
void fint fint fint real fint real real real real real real * g
Expression base class.
virtual expression * differentiate(int index)
differentiation
Definition: exprGroup.cpp:149
virtual void replace(exprVar *, exprVar *)
replace variable with other
Definition: exprOp.cpp:159
virtual void fillDepSet(std::set< DepNode *, compNode > *dep, DepGraph *g)
fill in dependence structure update dependence set with index of this variable
void fint fint fint real fint real real real real real real real real * w
virtual void realign(const CouenneProblem *p)
redirect variables to proper variable vector
Definition: exprGroup.cpp:387
void fint * n
virtual CouNumber Value() const
value (empty)
virtual const expression * Original() const
If this is an exprClone of a exprClone of an expr???, point to the original expr??? instead of an exprClone – improve computing efficiency.
virtual int Linearity()
Get a measure of &quot;how linear&quot; the expression is:
Definition: exprSum.cpp:147
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
class for multiplications,