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

Go to the documentation of this file.
00001 /* $Id: exprQuad.cpp 217 2009-07-08 17:02:07Z pbelotti $
00002  *
00003  * Name:    exprQuad.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: implementation of some methods for exprQuad
00006  *
00007  * (C) Carnegie-Mellon University, 2006-08.
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 #include "CoinHelperFunctions.hpp"
00012 #include "CouenneProblem.hpp"
00013 #include "exprConst.hpp"
00014 #include "exprQuad.hpp"
00015 #include "exprPow.hpp"
00016 #include "exprMul.hpp"
00017 #include "depGraph.hpp"
00018 #include "lqelems.hpp"
00019 
00020 class Domain;
00021 
00022 //#define DEBUG
00023 
00024 struct cmpVar {
00025   bool operator() (const exprVar* v1, const exprVar* v2) const
00026   {return (v1 -> Index () < v2 -> Index ());}
00027 };
00028 
00030 exprQuad::exprQuad (CouNumber c0,
00031                     std::vector <std::pair <exprVar *, CouNumber> > &lcoeff,
00032                     std::vector <quadElem> &qcoeff,
00033                     expression **al,
00034                     int n):
00035 
00036   exprGroup (c0, lcoeff, al, n) {
00037 
00038   nqterms_ = 0;
00039 
00040   typedef std::map <exprVar *, CouNumber, cmpVar> rowMap;
00041   typedef std::map <exprVar *, rowMap,    cmpVar> matrixMap;
00042 
00043   matrixMap qMap;
00044 
00045   for (std::vector <quadElem>::iterator qel = qcoeff.begin (); qel != qcoeff.end (); ++qel) {
00046 
00047     CouNumber coe = qel -> coeff ();
00048 
00049     exprVar
00050       *varI = qel -> varI (),
00051       *varJ = qel -> varJ ();
00052 
00053     if (varI -> Index () != varJ -> Index ()) {
00054 
00055       coe /= 2.;
00056 
00057       // pick smaller index as row reference
00058       if (varI -> Index () > varJ -> Index ()) {
00059 
00060         exprVar *swap = varJ;
00061         varJ = varI;
00062         varI = swap;
00063       }
00064     }
00065 
00066     matrixMap::iterator rowp = qMap.find (varI);
00067 
00068     if (rowp == qMap.end ()) { // add new row
00069 
00070       std::pair <exprVar *, CouNumber> newcell (varJ, coe);
00071       rowMap rmap;
00072       rmap.insert (newcell);
00073 
00074       std::pair <exprVar *, rowMap>    newrow  (varI, rmap);
00075       qMap.insert (newrow);
00076 
00077     } else { // insert element into row
00078 
00079       rowMap::iterator cell = rowp -> second.find (varJ);
00080 
00081       if (cell == rowp -> second.end ()) { // normal case, add entry
00082 
00083         std::pair <exprVar *, CouNumber> newcell (varJ, coe);
00084         rowp -> second.insert (newcell);
00085 
00086       } else { // strange, but add coefficient
00087 
00088         if (fabs (cell -> second += coe) < COUENNE_EPS)
00089           // eliminate element of map if null coefficient
00090           rowp -> second.erase (cell); 
00091       }
00092     }
00093   }
00094 
00095   // transform maps into vectors
00096 
00097   for (matrixMap::iterator row = qMap.begin (); row != qMap.end (); ++row) {
00098 
00099     sparseQcol line;
00100 
00101     // insert first element in bound map
00102     if (bounds_.find (row -> first) == bounds_.end ()) {
00103 
00104       std::pair <CouNumber, CouNumber> newbound (-DBL_MAX, DBL_MAX);
00105       std::pair <exprVar *, std::pair <CouNumber, CouNumber> > newvar (row -> first, newbound);
00106       bounds_.insert (newvar);
00107     }
00108 
00109     for (rowMap::iterator cell = row -> second.begin (); cell != row -> second.end (); ++cell) {
00110 
00111       line.push_back (std::pair <exprVar *, CouNumber> (*cell));
00112 
00113       // insert second element in bound map
00114       if (bounds_.find (cell -> first) == bounds_.end ()) {
00115 
00116         std::pair <CouNumber, CouNumber> newbound (-DBL_MAX, DBL_MAX);
00117         std::pair <exprVar *, std::pair <CouNumber, CouNumber> > newvar (cell -> first, newbound);
00118         bounds_.insert (newvar);
00119       }
00120     }
00121 
00122     matrix_.push_back (std::pair <exprVar *, sparseQcol> (row -> first, line));
00123     nqterms_ += line.size ();
00124   }
00125 }
00126 
00127 
00129 exprQuad::exprQuad (const exprQuad &src, Domain *d): 
00130   exprGroup (src, d),
00131   bounds_   (src.bounds_),
00132   nqterms_  (src.nqterms_) {
00133 
00134   for (sparseQ::iterator row = src.matrix_.begin (); row != src.matrix_ . end (); ++row) {  
00135 
00136     sparseQcol column;
00137 
00138     for (sparseQcol::iterator i = row -> second. begin (); i != row -> second. end (); ++i)
00139       column.push_back (std::pair <exprVar *, CouNumber> 
00140                         //(dynamic_cast <exprVar *> (i -> first -> clone (d)), i -> second));
00141                         (new exprVar (i -> first -> Index (), d), i -> second));
00142 
00143     matrix_.push_back (std::pair <exprVar *, sparseQcol> 
00144                        //dynamic_cast <exprVar *> (row -> first -> clone (d)), column));
00145                        (new exprVar (row -> first -> Index (), d), column));
00146   }
00147 
00149 
00150   std::vector 
00151     <std::pair <CouNumber, std::vector 
00152     <std::pair <exprVar *, CouNumber> > > >::iterator row;
00153 
00154   for (row = src.eigen_ . begin (); 
00155        row != src.eigen_ . end (); ++row) {  
00156 
00157     std::vector <std::pair <exprVar *, CouNumber> > eigVec;
00158 
00159     for (std::vector <std::pair <exprVar *, CouNumber> >::iterator 
00160            i = row -> second. begin (); 
00161          i != row -> second. end (); ++i)
00162       eigVec.push_back (std::pair <exprVar *, CouNumber> 
00163                         (dynamic_cast <exprVar *> (i -> first -> clone (d)), i -> second));
00164 
00165     eigen_.push_back (std::pair <CouNumber, std::vector 
00166                        <std::pair <exprVar *, CouNumber> > > (row -> first, eigVec));
00167   }
00168 }
00169 
00170 
00172 void exprQuad::print (std::ostream &out, bool descend) const {
00173 
00174   //if (code () == COU_EXPRQUAD)
00175   if (matrix_.size () > 0)
00176     out << '(';
00177 
00178   // print linear and nonquadratic part
00179   exprGroup::print (out, descend);
00180 
00181   int noperands = 0;
00182 
00183   for (int n = matrix_.size (), i=0; n--; i++) {
00184     //sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00185 
00186     int xind = matrix_ [i].first -> Index ();
00187     const sparseQcol row = matrix_ [i].second;
00188 
00189     for (int m = row.size (), j=0; m--; j++) {
00190       //sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00191 
00192       if (fabs (row [j]. second - 1.) > COUENNE_EPS) {
00193         if (fabs (row [j]. second + 1.) < COUENNE_EPS) out << "- ";
00194         else {
00195           if (row [j]. second > 0.) out << '+';
00196           out << row [j]. second << "*";
00197         }
00198       } else out << '+';
00199 
00200       if (row [j].first -> Index () == xind) {
00201         matrix_ [i]. first -> print (out, descend);
00202         out << "^2";
00203       } else {
00204         matrix_ [i]. first -> print (out, descend);
00205         out << '*';
00206         row [j]. first -> print (out, descend);
00207       }
00208 
00209       if (!((noperands + 1) % MAX_ARG_LINE))
00210         out << std::endl;
00211     }
00212   }
00213 
00214   //if (code () == COU_EXPRGROUP)
00215   if (matrix_.size () > 0)
00216     out << ')';
00217 }
00218 
00219 
00221 expression *exprQuad::differentiate (int index) {
00222 
00223   std::map <exprVar *, CouNumber> lmap;
00224 
00225   CouNumber c0 = 0;
00226 
00227   // derive linear part (obtain constant)
00228   for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
00229     c0 += el -> second;
00230 
00231   // derive quadratic part (obtain linear part)
00232   for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00233 
00234     int xind = row -> first -> Index ();
00235 
00236     for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00237 
00238       int yind = col -> first -> Index ();
00239 
00240       CouNumber coe = col -> second;
00241       exprVar *var = col -> first;
00242 
00243       if      (xind == index)
00244         if    (yind == index) {var = col -> first; coe *= 2;}
00245         else                   var = col -> first;
00246       else if (yind == index)  var = row -> first;
00247       else continue;
00248 
00249       std::map <exprVar *, CouNumber>::iterator i = lmap.find (var);
00250 
00251       if (i != lmap.end()) {
00252         if (fabs (i -> second += coe) < COUENNE_EPS)
00253           lmap.erase (i);
00254       } else {
00255         std::pair <exprVar *, CouNumber> npair (var, coe);
00256         lmap.insert (npair);
00257       }
00258     }
00259   }
00260 
00261   // derive nonlinear sum
00262   expression **arglist = new expression * [nargs_ + 1];
00263   int nargs = 0;
00264 
00265   for (int i = 0; i < nargs_; i++) 
00266     if (arglist_ [i] -> dependsOn (index))
00267       arglist [nargs++] = arglist_ [i] -> differentiate (index);
00268 
00269   // special cases
00270 
00271   // 1) no linear part
00272   if (lmap.empty ()) {
00273 
00274     // and no nonlinear part either
00275     if (!nargs) {
00276       delete arglist;
00277       return new exprConst (c0);
00278     }
00279 
00280     if (fabs (c0) > COUENNE_EPS)
00281       arglist [nargs++] = new exprConst (c0);
00282 
00283     return new exprSum (arglist, nargs);
00284   }
00285 
00286   lincoeff coe;
00287 
00288   for (std::map <exprVar *, CouNumber>::iterator i = lmap.begin (); i != lmap.end (); ++i)
00289     coe.push_back (std::pair <exprVar *, CouNumber> (i -> first, i -> second));
00290 
00291   return new exprGroup (c0, coe, arglist, nargs);
00292 }
00293 
00294 
00296 
00297 int exprQuad::compare (exprQuad &e) {
00298 
00299   int sum = exprGroup::compare (e);
00300 
00301   if (sum != 0) 
00302     return sum;
00303 
00304   if (matrix_.size() < e.matrix_.size()) return -1;
00305   if (matrix_.size() > e.matrix_.size()) return  1;
00306 
00307   for (sparseQ::iterator 
00308          row1 =   matrix_.begin (),
00309          row2 = e.matrix_.begin ();
00310        row1 != matrix_.end (); 
00311        ++row1, ++row2) {
00312 
00313     if (row1 -> first -> Index () < row2 -> first -> Index ()) return -1;
00314     if (row1 -> first -> Index () > row2 -> first -> Index ()) return  1;
00315 
00316     if (row1 -> second.size () < row2 -> second.size ()) return -1;
00317     if (row1 -> second.size () > row2 -> second.size ()) return  1;
00318 
00319     //    if (matrix_.size() > e.matrix_.size()) return  1;
00320     //    int xind = row -> first -> Index ();
00321     //    CouNumber x = (*(row -> first)) ();
00322 
00323     for (sparseQcol::iterator 
00324            col1 = row1 -> second.begin (),
00325            col2 = row2 -> second.begin ();
00326          col1 != row1 -> second.end (); 
00327          ++col1, ++col2) {
00328 
00329       if (col1 -> first -> Index () < col2 -> first -> Index ()) return -1;
00330       if (col1 -> first -> Index () > col2 -> first -> Index ()) return  1;
00331 
00332       if (col1 -> second < col2 -> second - COUENNE_EPS) return -1;
00333       if (col1 -> second > col2 -> second + COUENNE_EPS) return  1;
00334     }
00335   }
00336 
00337   return 0;
00338 }
00339 
00340 
00342 
00343 int exprQuad::rank () {
00344 
00345   int maxrank = exprGroup::rank ();
00346 
00347   if (maxrank < 0) 
00348     maxrank = 0;
00349 
00350   int r;
00351 
00352   for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00353 
00354     if ((r = row -> first -> rank ()) > maxrank) maxrank = r;
00355 
00356     for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col)
00357       if ((r = col -> first -> rank ()) > maxrank) maxrank = r;
00358   }
00359 
00360   return maxrank;
00361 }
00362 
00363 
00365 void exprQuad::fillDepSet (std::set <DepNode *, compNode> *dep, DepGraph *g) {
00366 
00367   exprGroup::fillDepSet (dep, g);
00368 
00369   for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00370 
00371     dep -> insert (g -> lookup (row -> first -> Index ()));
00372 
00373     for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col)
00374       dep -> insert (g -> lookup (col -> first -> Index ()));
00375   }
00376 }
00377 
00378 
00381 int exprQuad::DepList (std::set <int> &deplist, 
00382                        enum dig_type type) {
00383 
00384   int deps = exprGroup::DepList (deplist, type);
00385 
00386   for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00387     deps += row -> first -> DepList (deplist, type);
00388     for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col)
00389       deps += col -> first -> DepList (deplist, type);
00390   }
00391 
00392   return deps;
00393 }
00394 
00395 
00397 bool exprQuad::isInteger () {
00398 
00399   if (!(exprGroup::isInteger ()))
00400     return false;
00401 
00402   for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00403 
00404     bool intI = row -> first -> isInteger ();
00405 
00406     for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00407 
00408       CouNumber coe = col -> second;
00409 
00410       bool 
00411         intCoe = ::isInteger (coe),
00412         intJ   = row -> first -> isInteger ();
00413 
00414       if (intI && intJ && intCoe) 
00415         continue;
00416 
00417       if (!intCoe  // coefficient fractional, check all is fixed and product is integer
00418           && row -> first -> isFixed ()
00419           && col -> first -> isFixed ()
00420           && ::isInteger (coe * 
00421                           row -> first -> lb () * 
00422                           col -> first -> lb ()))
00423         continue;
00424 
00425       if (!intI && (row -> first -> isFixed ()) && ::isInteger ((*(row -> first)) ())) continue;
00426       if (!intJ && (col -> first -> isFixed ()) && ::isInteger ((*(col -> first)) ())) continue;
00427 
00428       //if (!intI && !intJ &&  intCoe) ; // check x y fixed int
00429       //if (!intI &&  intJ &&  intCoe) ; // check x   fixed int
00430       //if ( intI && !intJ &&  intCoe) ; // check   y fixed int
00431 
00432       return false;
00433     }
00434   }
00435 
00436   return true;
00437 }
00438 
00439 
00441 void exprQuad::replace (exprVar *x, exprVar *w) {
00442 
00443   exprGroup::replace (x, w);
00444   int xind = x -> Index ();
00445   int wind = w -> Index ();
00446 
00447   for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00448 
00449     exprVar * &vr = row -> first;
00450     if ((vr -> Index () == xind)) {
00451 
00452       //fprintf (stderr, "Didn't fix exprQuad::replace() yet");
00453       //exit (-1);
00454       vr = w;
00455     }
00456 
00457     for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00458 
00459       exprVar * &vc = col -> first;
00460       if ((vc -> Index () == wind)) {
00461 
00462         //fprintf (stderr, "Didn't fix exprQuad::replace() yet");
00463         //exit (-1);
00464         vc = w;
00465       }
00466     }
00467   }
00468 }
00469 
00470 
00472 void exprQuad::realign (const CouenneProblem *p) {
00473 
00474   for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00475 
00476     exprVar * &vr = row -> first;
00477     int indVar;
00478 
00479     // substitute variable representing this row with its newest version
00480 
00481     if (((vr -> Type () == VAR) ||
00482          (vr -> Type () == AUX)) &&
00483         (vr -> Original () != p -> Var (indVar = vr -> Index ()))) {
00484 
00485       expression *trash = vr;
00486       row -> first = p -> Var (indVar);
00487       delete trash;
00488     }
00489 
00490     // substitute each variable of this row with its newest version
00491 
00492     for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00493 
00494       exprVar * &vc = col -> first;
00495       int indVar;
00496 
00497       // substitute variable representing this row with its newest version
00498 
00499       if (((vc -> Type () == VAR) ||
00500            (vc -> Type () == AUX)) &&
00501           (vc -> Original () != p -> Var (indVar = vc -> Index ()))) {
00502 
00503         expression *trash = vc;
00504         col -> first = p -> Var (indVar);
00505         delete trash;
00506       }
00507     }
00508   }
00509 }
00510 
00511 
00513 void exprQuad::closestFeasible (expression *varind,
00514                                 expression *vardep, 
00515                                 CouNumber &left,
00516                                 CouNumber &right) const {
00517 
00518   fprintf (stderr, "exprQuad::closestFeasible() not available for VT\n");
00519   exit (-1);
00520 }
00521 
00522 
00524 CouNumber exprQuad::gradientNorm (const double *x) {
00525 
00526   CouNumber grad = 0.;
00527 
00528   for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00529 
00530     CouNumber gradEl = 0.;
00531     for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col)
00532       gradEl += col -> second * x [col -> first -> Index ()];
00533 
00534     grad += gradEl * gradEl;
00535   }
00536 
00537   return sqrt (grad);
00538 }
00539 
00541 expression *exprQuad::simplify () {
00542   exprOp::simplify (); 
00543   return NULL;
00544 }
00545 

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