/home/coin/SVN-release/OS-2.2.0/Couenne/src/expression/operators/exprGroup.cpp

Go to the documentation of this file.
00001 /* $Id: exprGroup.cpp 320 2010-03-26 19:12:20Z stefan $ */
00002 /*
00003  * Name:    exprGroup.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: implementation of some methods for exprGroup
00006  *
00007  * (C) Carnegie-Mellon University, 2006-09.
00008  * This file is licensed under the Common Public License (CPL)
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 // eliminates elements with zero coefficients
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   // a constant
00057   if ((n==0) && (nl==0))
00058     ret = new exprConst (c0); // a constant auxiliary? FIX!
00059 
00060   else if ((n==0) && (fabs (c0) < COUENNE_EPS) && (nl==1)) { // a linear monomial, cx
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                          //(dynamic_cast <exprVar *> (i -> first -> clone (d)), i -> second));
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   //if (code () == COU_EXPRGROUP)
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     //else continue;
00133 
00134     lcoeff_ [i]. first -> print (out, descend);
00135     if (!((i + 1) % MAX_ARG_LINE))
00136         out << std::endl;
00137   }
00138 
00139   //if (code () == COU_EXPRGROUP)
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 (),    // linearity of nonlinear part
00179     llin  = (lcoeff_.size () == 0) ?  //              linear part
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   // !!! why?
00191 
00192   //int sum = exprSum::compare (e);
00193 
00194   //if (sum != 0) 
00195   //return sum;
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     // check var fixed and product is integer
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   // find occurrences of x and w in vector of variabls
00317 
00318   lincoeff::iterator x_occur = lcoeff_.begin ();
00319 
00320   // Do not assume index vector is sorted in ascending order
00321   // w.r.t. (*iterator) -> first () -> Index()
00322   while ((x_occur != lcoeff_.end ()) && 
00323          (x_occur -> first -> Index () != xind))
00324     ++x_occur;
00325 
00326   if (x_occur == lcoeff_ .end ()) // not found, bail out
00327     return;
00328 
00329   if (xind == wind)
00330     x_occur -> first = w;
00331   else { // replacing two variables, not the features of one
00332 
00333     lincoeff::iterator w_occur = lcoeff_.begin ();
00334 
00335     // Do not assume index vector is sorted in ascending order
00336     // w.r.t. (*iterator) -> first () -> Index()
00337     while ((w_occur != lcoeff_.end ()) &&
00338            (w_occur -> first -> Index () != wind))
00339       ++w_occur;
00340 
00341     if (w_occur == lcoeff_ . end ()) // not found w, simply substitute 
00342       x_occur -> first = w;
00343     else {
00344                 if ((w_occur -> second += x_occur -> second) == 0.) { // add coefficients
00345         lcoeff_.erase (w_occur);                // if they cancel out, delete w as well
00346 
00347         // under Microsoft, x_occur may have been invalidated by removing w_occur from lcoeff_, so we search for it again
00348         for( x_occur = lcoeff_.begin (); x_occur -> first -> Index () != xind; ++x_occur )
00349                 assert(x_occur != lcoeff_ .end ()); // it was found before, so it should be still found
00350         }
00351       lcoeff_.erase   (x_occur);                // delete entry of x
00352     }
00353   }
00354 }
00355 
00356 
00359 CouNumber exprGroup::gradientNorm (const double *x) {
00360 
00361   CouNumber retval = 0;
00362 
00363   for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
00364     retval += el -> second * el -> second;
00365 
00366   return sqrt (retval);
00367 }
00368 
00369 
00371 void exprGroup::realign (const CouenneProblem *p) {
00372 
00373   for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00374 
00375     exprVar *var = el -> first;
00376 
00377     if (((var -> Type () == VAR) ||  
00378          (var -> Type () == AUX)) &&
00379         (var -> Original () != p -> Var (var -> Index ()))) {
00380 
00381       expression *trash = var;
00382       el -> first = p -> Var (var -> Index ());
00383       delete trash;
00384     }
00385   }
00386 }
00387 
00388 
00390 expression *exprGroup::simplify () {
00391   exprOp::simplify (); 
00392   //if (lcoeff_. size () <= 0) // this is just a constant
00393   //return new exprConst (c0_);
00394   //else
00395   return NULL;
00396 }
00397 

Generated on Thu Aug 5 03:02:57 2010 by  doxygen 1.4.7