00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "exprConst.hpp"
00012 #include "exprVar.hpp"
00013 #include "exprGroup.hpp"
00014 #include "exprClone.hpp"
00015 #include "exprMul.hpp"
00016 #include "depGraph.hpp"
00017 #include "CouenneProblem.hpp"
00018
00019 class Domain;
00020
00021
00022
00023 void cleanZeros (std::vector <std::pair <exprVar *, CouNumber> > &lcoeff) {
00024
00025 std::vector <std::pair <exprVar *, CouNumber> >::iterator i = lcoeff.begin ();
00026
00027 int
00028 ind = 0,
00029 size = lcoeff.size ();
00030
00031 while (size-- > 0) {
00032 if ((i -> second == 0.) ||
00033 (i -> second == -0.)) {
00034 lcoeff.erase (i);
00035 i = lcoeff.begin () + ind;
00036 } else {
00037 ++i;
00038 ++ind;
00039 }
00040 }
00041 }
00042
00043
00044
00047 expression *exprGroup::genExprGroup (CouNumber c0,
00048 std::vector <std::pair <exprVar *, CouNumber> > &lcoeff,
00049 expression **al,
00050 int n) {
00051 int nl = lcoeff.size ();
00052 expression *ret = NULL;
00053
00054 cleanZeros (lcoeff);
00055
00056
00057 if ((n==0) && (nl==0))
00058 ret = new exprConst (c0);
00059
00060 else if ((n==0) && (fabs (c0) < COUENNE_EPS) && (nl==1)) {
00061
00062 if (fabs (lcoeff[0]. second - 1) < COUENNE_EPS)
00063 ret = new exprClone (lcoeff[0]. first);
00064 else ret = new exprMul (new exprConst (lcoeff[0]. second), new exprClone (lcoeff[0]. first));
00065
00066 } else ret = new exprGroup (c0, lcoeff, al, n);
00067
00068 return ret;
00069 }
00070
00071
00073 exprGroup::exprGroup (CouNumber c0,
00074 std::vector <std::pair <exprVar *, CouNumber> > &lcoeff,
00075 expression **al,
00076 int n):
00077 exprSum (al, n),
00078 lcoeff_ (lcoeff),
00079 c0_ (c0) {
00080
00081 cleanZeros (lcoeff_);
00082 }
00083
00084
00086 exprGroup::exprGroup (const exprGroup &src, Domain *d):
00087 exprSum (src.clonearglist (d), src.nargs_),
00088 c0_ (src.c0_) {
00089
00090 for (lincoeff::iterator i = src.lcoeff_.begin (); i != src.lcoeff_.end (); ++i)
00091
00092 lcoeff_ . push_back (std::pair <exprVar *, CouNumber>
00093
00094 (new exprVar (i -> first -> Index (), d), i -> second));
00095 }
00096
00097
00099 exprGroup::~exprGroup () {
00100
00101 for (lincoeff::iterator i = lcoeff_.begin (); i != lcoeff_.end (); ++i) {
00102 enum expr_type code = i -> first -> code ();
00103 if ((code == COU_EXPRLBOUND) ||
00104 (code == COU_EXPRUBOUND))
00105 delete i -> first;
00106 }
00107 }
00108
00109
00111 void exprGroup::print (std::ostream &out, bool descend) const {
00112
00113
00114 if (lcoeff_.size () > 0)
00115 out << '(';
00116
00117 if (nargs_ && ((nargs_ > 1) ||
00118 ((*arglist_) -> Type () != CONST) ||
00119 (fabs ((*arglist_) -> Value ()) > COUENNE_EPS)))
00120 exprSum::print (out, descend);
00121
00122 if (c0_ > 0.) out << '+' << c0_;
00123 else if (c0_ < - 0.) out << c0_;
00124
00125 for (int n = lcoeff_.size (), i=0; n--; i++) {
00126
00127 CouNumber coeff = lcoeff_ [i]. second;
00128 out << ' ';
00129
00130 if (coeff > 0.) out << '+' << coeff << "*";
00131 else if (coeff < - 0.) out << coeff << "*";
00132
00133
00134 lcoeff_ [i]. first -> print (out, descend);
00135 if (!((i + 1) % MAX_ARG_LINE))
00136 out << std::endl;
00137 }
00138
00139
00140 if (lcoeff_.size () > 0)
00141 out << ')';
00142 }
00143
00144
00146 expression *exprGroup::differentiate (int index) {
00147
00148 expression **arglist = new expression * [nargs_ + 1];
00149
00150 CouNumber totlin=0;
00151
00152 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
00153 if (el -> first -> Index () == index)
00154 totlin += el -> second;
00155
00156 int nargs = 0;
00157
00158 if (fabs (totlin) > COUENNE_EPS)
00159 arglist [nargs++] = new exprConst (totlin);
00160
00161 for (int i = 0; i < nargs_; i++)
00162 if (arglist_ [i] -> dependsOn (&index, 1))
00163 arglist [nargs++] = arglist_ [i] -> differentiate (index);
00164
00165 if ((nargs == 0) ||
00166 (nargs == 1) && (fabs (totlin) > COUENNE_EPS)) {
00167 delete [] arglist;
00168 return new exprConst (totlin);
00169 }
00170 else return new exprSum (arglist, nargs);
00171 }
00172
00173
00175 int exprGroup::Linearity () {
00176
00177 int
00178 nllin = exprSum::Linearity (),
00179 llin = (lcoeff_.size () == 0) ?
00180 ((fabs (c0_) < COUENNE_EPS) ? ZERO : CONSTANT) :
00181 LINEAR;
00182
00183 return (llin > nllin) ? llin : nllin;
00184 }
00185
00186
00188 int exprGroup::compare (exprGroup &e) {
00189
00190
00191
00192
00193
00194
00195
00196
00197 if (c0_ < e.c0_ - COUENNE_EPS) return -1;
00198 if (c0_ > e.c0_ + COUENNE_EPS) return 1;
00199
00200 if (lcoeff_.size () < e.lcoeff_.size ()) return -1;
00201 if (lcoeff_.size () > e.lcoeff_.size ()) return 1;
00202
00203 for (lincoeff::iterator
00204 el1 = lcoeff_.begin (),
00205 el2 = e.lcoeff_.begin ();
00206 el1 != lcoeff_.end ();
00207 ++el1, ++el2) {
00208
00209 int
00210 ind1 = el1 -> first -> Index (),
00211 ind2 = el2 -> first -> Index ();
00212
00213 CouNumber
00214 coe1 = el1 -> second,
00215 coe2 = el2 -> second;
00216
00217 if (ind1 < ind2) return -1;
00218 if (ind1 > ind2) return 1;
00219
00220 if (coe1 < coe2 - COUENNE_EPS) return -1;
00221 if (coe1 > coe2 + COUENNE_EPS) return 1;
00222 }
00223
00224 return 0;
00225 }
00226
00227
00229
00230 int exprGroup::rank () {
00231
00232 int maxrank = exprOp::rank ();
00233
00234 if (maxrank < 0)
00235 maxrank = 0;
00236
00237 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00238
00239 int r = el -> first -> rank ();
00240 if (r > maxrank)
00241 maxrank = r;
00242 }
00243
00244 return maxrank;
00245 }
00246
00247
00249 void exprGroup::fillDepSet (std::set <DepNode *, compNode> *dep, DepGraph *g) {
00250
00251 exprOp::fillDepSet (dep, g);
00252
00253 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
00254 dep -> insert (g -> lookup (el -> first -> Index ()));
00255 }
00256
00257
00260 int exprGroup::DepList (std::set <int> &deplist,
00261 enum dig_type type) {
00262
00263 int deps = exprOp::DepList (deplist, type);
00264
00265 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
00266 deps += el -> first -> DepList (deplist, type);
00267
00268 return deps;
00269 }
00270
00271
00273 bool exprGroup::isInteger () {
00274
00275 if (!(::isInteger (c0_)) ||
00276 !(exprOp::isInteger ()))
00277 return false;
00278
00279 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00280
00281 CouNumber coe = el -> second;
00282
00283 bool
00284 intCoe = ::isInteger (coe),
00285 intVar = el -> first -> isInteger ();
00286
00287 if (intCoe && intVar)
00288 continue;
00289
00290 CouNumber
00291 lb = el -> first -> lb (),
00292 ub = el -> first -> ub ();
00293
00294
00295 if ((fabs (lb - ub) < COUENNE_EPS) &&
00296 (::isInteger (lb * coe) ||
00297 (intCoe && ::isInteger (lb))))
00298 continue;
00299
00300 return false;
00301 }
00302
00303 return true;
00304 }
00305
00306
00308 void exprGroup::replace (exprVar *x, exprVar *w) {
00309
00310 exprOp::replace (x, w);
00311
00312 int
00313 xind = x -> Index (),
00314 wind = w -> Index ();
00315
00316
00317
00318 lincoeff::iterator x_occur = lcoeff_.begin ();
00319
00320
00321
00322 while ((x_occur != lcoeff_.end ()) &&
00323 (x_occur -> first -> Index () != xind))
00324 ++x_occur;
00325
00326 if (x_occur == lcoeff_ .end ())
00327 return;
00328
00329 if (xind == wind)
00330 x_occur -> first = w;
00331 else {
00332
00333 lincoeff::iterator w_occur = lcoeff_.begin ();
00334
00335
00336
00337 while ((w_occur != lcoeff_.end ()) &&
00338 (w_occur -> first -> Index () != wind))
00339 ++w_occur;
00340
00341 if (w_occur == lcoeff_ . end ())
00342 x_occur -> first = w;
00343 else {
00344 if ((w_occur -> second += x_occur -> second) == 0.)
00345 lcoeff_.erase (w_occur);
00346 lcoeff_.erase (x_occur);
00347 }
00348 }
00349 }
00350
00351
00354 CouNumber exprGroup::gradientNorm (const double *x) {
00355
00356 CouNumber retval = 0;
00357
00358 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
00359 retval += el -> second * el -> second;
00360
00361 return sqrt (retval);
00362 }
00363
00364
00366 void exprGroup::realign (const CouenneProblem *p) {
00367
00368 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00369
00370 exprVar *var = el -> first;
00371
00372 if (((var -> Type () == VAR) ||
00373 (var -> Type () == AUX)) &&
00374 (var -> Original () != p -> Var (var -> Index ()))) {
00375
00376 expression *trash = var;
00377 el -> first = p -> Var (var -> Index ());
00378 delete trash;
00379 }
00380 }
00381 }
00382
00383
00385 expression *exprGroup::simplify () {
00386 exprOp::simplify ();
00387
00388
00389
00390 return NULL;
00391 }
00392