source: trunk/Couenne/src/expression/exprOp.cpp @ 114

Last change on this file since 114 was 114, checked in by stefan, 13 years ago

for gcc 4.4

File size: 4.8 KB
Line 
1/*
2 * Name:    exprOp.cpp
3 * Author:  Pietro Belotti
4 * Purpose: methods for multivariate function class
5 *
6 * (C) Carnegie-Mellon University, 2006-08.
7 * This file is licensed under the Common Public License (CPL)
8 */
9
10#include "expression.hpp"
11#include "exprAux.hpp"
12#include "exprClone.hpp"
13#include "exprOp.hpp"
14#include "exprGroup.hpp"
15#include "exprQuad.hpp"
16
17#include <cstdio>
18
19class CouenneProblem;
20class Domain;
21
22
23// General N-ary function destructor
24exprOp::~exprOp () {
25
26  if (arglist_) {
27    for (expression **alist = arglist_; nargs_--; alist++)
28      if (*alist) delete (*alist);
29    delete [] arglist_;
30  }
31}
32
33
34// print expression
35
36void exprOp::print (std::ostream &out, 
37                    bool descend) const {
38 
39  if (printPos () == PRE)
40    out << printOp ();
41
42  if (nargs_ > 1)
43    {out << "("; fflush (stdout);}
44  for (int i=0; i<nargs_; i++) {
45    if (arglist_ [i])
46      arglist_ [i] -> print (out, descend); 
47    fflush (stdout);
48    if (i < nargs_ - 1) {
49      if (printPos () == INSIDE) out << printOp ();
50      else                       out << ",";
51    }
52    if (!((i + 1) % MAX_ARG_LINE))
53      out << std::endl;
54    fflush (stdout);
55  }
56  if (nargs_ > 1) {
57    out << ")";
58    fflush (stdout);
59  }
60}
61
62
63/// compare general n-ary expressions
64
65int exprOp::compare (exprOp &e1) {
66
67  int c0 =     code (),
68      c1 = e1. code ();
69
70  if (c0 < c1) return -1;
71  if (c0 > c1) return  1;
72
73  // have to compare arguments one by one
74  if (nargs_ < e1.nargs_) return -1;
75  if (nargs_ > e1.nargs_) return  1;
76
77  // not an exprGroup, compare arguments
78  for (register int i = nargs_; i--;) {
79
80    int res = arglist_ [i] -> compare (*(e1. ArgList () [i]));
81    if (res) return res;
82  }
83
84  // last chance, this might be an exprGroup or derived
85  if ((c0 == COU_EXPRGROUP) ||
86      (c0 == COU_EXPRQUAD)) {
87
88    exprGroup *ne0 = dynamic_cast <exprGroup *> (this),
89              *ne1 = dynamic_cast <exprGroup *> (&e1);
90
91    int cg = ne0 -> compare (*ne1);
92
93    if (cg) return cg; // exprGroup
94
95    // last chance, the two are quadratic forms
96
97    if (c0 == COU_EXPRQUAD) {
98
99      exprQuad *ne0 = dynamic_cast <exprQuad *> (this),
100               *ne1 = dynamic_cast <exprQuad *> (&e1);
101
102      return ne0 -> compare (*ne1);
103    }
104  }
105
106  return 0;
107}
108
109
110/// used in rank-based branching variable choice
111
112int exprOp::rank () {
113
114  int maxrank = -1;
115
116  for (expression **al = arglist_ + nargs_; 
117       al-- > arglist_;) {
118    int r = (*al) -> rank ();
119    if (r > maxrank) maxrank = r;
120  }
121
122  return (maxrank);
123}
124
125
126// Create standard formulation of this expression, by:
127//
128// - creating auxiliary w variables and corresponding expressions
129// - returning linear counterpart as new constraint (to replace
130//   current one)
131//
132// For the base exprOp class we only do the first part (for argument
133// list components only), and the calling class (Sum, Sub, Mul, Pow,
134// and the like) will do the part for its own object
135
136exprAux *exprOp::standardize (CouenneProblem *p, bool addAux) {
137
138  exprVar *subst;
139
140  for (int i = nargs_; i--;)
141    if ((subst = arglist_ [i] -> standardize (p))) {
142      if ((subst -> Type () == VAR) ||
143          (subst -> Type () == AUX))
144        arglist_ [i]    = new exprClone (subst);
145      else arglist_ [i] = subst;
146    }
147  return NULL;
148}
149
150
151/// replace variable x with new (aux) w
152void exprOp::replace (exprVar *x, exprVar *w) {
153
154  expression **al = arglist_;
155  int index = x -> Index ();
156
157  for (register int i = nargs_; i--; al++)
158
159    switch ((*al) -> Type ()) {
160
161    case AUX:
162    case VAR:
163      if ((*al) -> Index () == index) {
164        delete *al;
165        *al = new exprClone (w);
166      }
167      break;
168
169    case UNARY:
170    case N_ARY:
171      (*al) -> replace (x, w);
172      break;
173
174    default:
175      break;
176    }
177}
178
179
180/// is this expression integer?
181bool exprOp::isInteger () {
182
183  for (int i = nargs_; i--;)
184
185    if (!(arglist_ [i] -> isInteger ())) { 
186
187      // this argument is not integer: check if constant and integer
188
189      CouNumber lb, ub;
190      arglist_ [i] -> getBounds (lb, ub);
191
192      if ((fabs (lb - ub) > COUENNE_EPS) ||
193          !::isInteger (lb))
194        return false;
195    }
196
197  return true;
198}
199
200
201/// fill in the set with all indices of variables appearing in the
202/// expression
203int exprOp::DepList (std::set <int> &deplist, 
204                     enum dig_type type) {
205  int tot = 0;
206
207  //printf ("  exprop::deplist of "); print (); printf ("\n");
208
209  for (int i = nargs_; i--;) {
210
211    /*printf ("  ");
212    arglist_ [i] -> print (); printf (": {");
213    for (std::set <int>::iterator j=deplist.begin(); j != deplist.end(); ++j)
214      printf ("%d ", *j);
215      printf ("} -> {");*/
216
217    tot += arglist_ [i] -> DepList (deplist, type);
218
219    /*for (std::set <int>::iterator j=deplist.begin(); j != deplist.end(); ++j)
220      printf ("%d ", *j);
221      printf ("}\n");*/
222  }
223  return tot;
224}
225
226/// empty function to redirect variables to proper variable vector
227void exprOp::realign (const CouenneProblem *p) {
228
229  for (int i=0; i<nargs_; i++)
230    arglist_ [i] -> realign (p);
231}
Note: See TracBrowser for help on using the repository browser.