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