/home/coin/SVN-release/OS-2.4.1/Couenne/src/convex/operators/conv-exprMul-reformulate.cpp

Go to the documentation of this file.
00001 /* $Id: conv-exprMul-reformulate.cpp 597 2011-06-02 10:09:33Z pbelotti $
00002  *
00003  * Name:    conv-exprMul-reformulate.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: utility methods to reformulate multiplications into bilinear and trilinear terms
00006  *
00007  * (C) Carnegie-Mellon University, 2006-10.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include <queue>
00012 
00013 #include "CouenneTypes.hpp"
00014 #include "CouenneExprMul.hpp"
00015 #include "CouenneExprTrilinear.hpp"
00016 #include "CouenneExprBMul.hpp"
00017 #include "CouenneExprConst.hpp"
00018 #include "CouenneExprPow.hpp"
00019 #include "CouenneExprAux.hpp"
00020 #include "CouenneExprClone.hpp"
00021 #include "CouenneProblem.hpp"
00022 
00023 using namespace Couenne;
00024 
00026 
00027 inline bool areSameVariables (expression *v1, expression *v2) {
00028 
00029   register int t1 = v1 -> Type (), t2;
00030   return (((t1 == VAR) || (t1 == AUX)) &&
00031           (((t2 = v2 -> Type ()) == VAR) || (t2 == AUX)) && 
00032           (v1 -> Index () == v2 -> Index ()));
00033 }
00034 
00035 
00037 
00038 exprAux *exprMul::standardize (CouenneProblem *p, bool addAux) {
00039 
00040   //printf ("standardizing exprMul (addaux=%d) ", addAux); fflush (stdout); print (); printf ("\n");
00041 
00042   CouNumber coeff = 1.;
00043   std::map <int, CouNumber> indCoe;
00044 
00045   p -> flattenMul (this, coeff, indCoe);
00046 
00047   int nArgs = 0;
00048 
00049   expression **arglist = new expression * [indCoe.size ()];
00050 
00051   for (std::map <int, CouNumber>::iterator i = indCoe.begin (); i != indCoe.end (); ++i)
00052     if (i -> second == 1.) arglist [nArgs++] = new exprClone (p                -> Var (i -> first));
00053     else                   arglist [nArgs++] = new exprPow   (new exprClone (p -> Var (i -> first)), new exprConst (i -> second));
00054 
00055   //while (nargs_--)
00056   //delete arglist_ [nargs_];
00057 
00058   //delete [] arglist_;
00059 
00060   arglist_ = arglist;
00061   nargs_ = (int) indCoe.size();
00062 
00063   //printf ("new mul [%d]: %g * ", nargs_, coeff); fflush (stdout); print (); printf (" -- ");
00064 
00065   exprOp::standardize (p);
00066 
00067   //printf ("standardized: "); fflush (stdout); print (); printf ("\n");
00068 
00069   if (nargs_ == 1) {
00070 
00071     if (coeff != 1.) {
00072 
00073       // leak: arglist_ should be deleted
00074 
00075       expression *simMul = new exprMul (new exprConst (coeff), new exprClone (arglist_ [0]));
00076       return (addAux ? (p -> addAuxiliary (simMul)) : new exprAux (simMul, p -> domain ()));
00077 
00078     } else {
00079 
00080       // quick fix for nvs08: expression x_0^.5 * x_0^3 is quite
00081       // unusual and is translated into an exprMul with a single
00082       // argument.
00083 
00084       exprAux *var = dynamic_cast <exprAux *> (arglist_ [0] -> Copy ());
00085       return var;
00086     }
00087   }
00088 
00089   //if (nargs_ == 1)  // TODO: what happens really?
00090       //return NULL;
00091   /* {
00092      exprAux *aux = arglist_ [0];
00093      arglist_ [0] = NULL;
00094      return aux;
00095      } */
00096 
00097   // enable this when binary products are available
00098 
00099 #if 0
00100   // check if it is a product of binary variables
00101   bool isBinProd = true;
00102   for (int i=nargs_; i--;) {
00103 
00104     expression *arg = arglist_ [i];
00105     if (arg -> isInteger ()) {
00106 
00107       CouNumber lb, ub;
00108       arg -> getBounds (lb, ub);
00109       if ((fabs (ceil  (lb - COUENNE_EPS))      > 0.) ||
00110           (fabs (floor (ub + COUENNE_EPS) - 1.) > 0.)) { // if not all conditions hold, 
00111         isBinProd = false;
00112         break;
00113       }
00114     } else {
00115       isBinProd = false;
00116       break;
00117     }
00118   }
00119 
00120   if (isBinProd) {
00121     //printf ("found a BinProd!\n");
00122   }
00123 #endif
00124 
00125   enum Couenne::TrilinDecompType type = p -> getTrilinDecompType ();
00126 
00127   if (nargs_ <= 2)
00128     type = Couenne::rAI;
00129 
00130   expression *retExpr;
00131 
00132   switch (type) {
00133 
00134   case Couenne::treeDecomp: {
00135 
00136     //printf ("trying treeDecomp on "); print (); printf ("\n");
00137 
00138     // A more hierarchical decomposition. Example:
00139     //
00140     // (x1 x2 x3 x4 x5 x6 x7 x8 x9 x10)
00141     //
00142     // becomes
00143     //
00144     // ((((x1 x2) (x3 x4)) ((x5 x6) (x7 x8))) (x9 x10))
00145     //
00146     // so that x1 .. x10 are the leaves of a binary tree whose
00147     // non-leaf nodes are auxiliaries
00148     //
00149     // use a queue to parse the leaf level first (by pushing all
00150     // original members) and push the newly added auxs into the queue
00151     // while extracting _pairs_ of elements
00152 
00153     std::queue <expression *> queue;
00154 
00155     for (int i=0; i<nargs_; i++)
00156       queue.push (arglist_ [i]);
00157 
00158     expression *aux;
00159 
00160     while (queue.size() > 1) {
00161 
00162       expression *arg1 = queue.front (); queue.pop ();
00163       expression *arg2 = queue.front (); queue.pop ();
00164 
00165       //printf ("Coupling "); arg1 -> print (); 
00166       //printf (" with "); arg2 -> print (); 
00167 
00168       if (areSameVariables (arg1, arg2)) aux = new exprPow (new exprClone (arg1), new exprConst (2.));
00169       else                               aux = new exprMul (new exprClone (arg1), new exprClone (arg2));
00170 
00171       //printf (" --> "); aux -> print (); printf ("\n"); 
00172 
00173       if (!(queue.empty ()))
00174         aux = p -> addAuxiliary (aux);
00175 
00176       queue.push (aux);
00177     }
00178 
00179     aux = queue.front (); queue.pop ();
00180 
00181     retExpr = aux; //(addAux ? (p -> addAuxiliary (aux)) : new exprAux (this, p -> domain ()));
00182   } break;
00183 
00184   // ----------------------------------------------------------------------------------------------
00185 
00186   case Couenne::tri_bi:
00187   case Couenne::bi_tri: { // the two cases are very similar
00188 
00189     //printf ("trying %s on ", type==tri_bi ? "tri+bi" : "bi+tri"); print (); printf (": "); fflush (stdout);
00190 
00191     // rAI-tre (ok, funny name, but you get the meaning): same as rAI,
00192     // but with trilinear terms. A product
00193     //
00194     // x1 x2 x3... xk
00195     //
00196     // is decomposed as
00197     //
00198     // (...((x1 x2 x3) x4 x5) x6 x7) ... ) x[k-1] xk)
00199 
00200     expression *aux = arglist_ [0];
00201 
00202     for (int i = 1; i < nargs_;) {
00203 
00204       if (i < nargs_ - 1 && ((type==tri_bi) || (i!=1))) { // this is the only point of departure between tri_bi and bi_tri
00205 
00206         // there are at least two remaining arguments: can create trilinear
00207         if (areSameVariables (aux, arglist_ [i])) {
00208 
00209           if (areSameVariables (aux, arglist_ [i+1]))  // this is a term (x_i x_i x_i)
00210 
00211             if (i == nargs_ - 2) aux =                    new exprPow (new exprClone (aux), new exprConst (3.));
00212             else                 aux = p -> addAuxiliary (new exprPow (new exprClone (aux), new exprConst (3.)));
00213 
00214           else {
00215 
00216             aux = p -> addAuxiliary (new exprPow (new exprClone (aux), new exprConst (2.)));
00217             //aux -> print (); printf (" (tri0) := "); fflush (stdout); aux -> Image () -> print (); printf ("; ");  fflush (stdout);
00218             if (i == nargs_ - 2) aux =                    new exprMul (new exprClone (aux), new exprClone (arglist_ [i+1]));
00219             else                 aux = p -> addAuxiliary (new exprMul (new exprClone (aux), new exprClone (arglist_ [i+1])));
00220           }
00221 
00222         } else 
00223           if (areSameVariables (aux, arglist_ [i+1])) {
00224 
00225             printf ("Couenne, exprTrilinear: bad ordering of factors in product, aborting\n");
00226             exit (-1);
00227 
00228           } else {
00229 
00230             aux = new exprTrilinear (new exprClone (aux), 
00231                                      new exprClone (arglist_ [i]),
00232                                      new exprClone (arglist_ [i+1]));
00233 
00234             if (i != nargs_ - 2) 
00235               aux = p -> addAuxiliary (aux);
00236           }
00237 
00238         //aux -> print (); if (i != nargs_ - 2) {printf (" (tri) := "); aux -> Image () -> print (); printf ("; "); fflush (stdout);}
00239 
00240         i += 2; // covered two variables
00241 
00242       } else {
00243 
00244         if (areSameVariables (aux, arglist_ [i])) aux = new exprPow (new exprClone (aux), new exprConst (2.));
00245         else                                      aux = new exprMul (new exprClone (aux), new exprClone (arglist_ [i]));
00246 
00247         if (i==1) // must be bi+tri
00248           aux = p -> addAuxiliary (aux); // necessary to introduce the auxiliary variable
00249 
00250         //aux -> print (); if (i==1) {printf (" (bi) := "); fflush (stdout); aux -> Image () -> print (); printf ("; "); fflush (stdout);}
00251 
00252         i++; // covered the last variable
00253       }
00254     }
00255 
00256     //printf ("\n");
00257 
00258     retExpr = aux; //(addAux ? (p -> addAuxiliary (aux)) : new exprAux (this, p -> domain ()));
00259   } break;
00260 
00261   // ----------------------------------------------------------------------------------------------
00262 
00263   case Couenne::rAI:
00264   default:
00265 
00266     //printf ("trying good ol' rAI on "); print (); printf ("\n");
00267 
00268     // rAI -- recursive Arithmetic Intervals (see Ryoo and Sahinidis,
00269     // JOGO 19 (2001):403-424):
00270     //
00271     // All multilinear expressions are decomposed as 
00272     //
00273     // (x_1 (x_2 (x_3... (x_{k-1} x_k))...)
00274 
00275     expression *aux = arglist_ [0];
00276 
00277     for (int i = 1; i < nargs_ - 1; i++)
00278       aux = (areSameVariables (aux, arglist_ [i])) ? 
00279         (p -> addAuxiliary (new exprPow (new exprClone (aux), new exprConst (2.)))) : 
00280         (p -> addAuxiliary (new exprMul (new exprClone (aux), new exprClone (arglist_ [i]))));
00281 
00282     if (areSameVariables (aux, arglist_ [nargs_ - 1])) 
00283       aux    = new exprPow (new exprClone (aux), new exprConst (2.));
00284     else aux = new exprMul (new exprClone (aux), new exprClone (arglist_ [nargs_ - 1]));
00285 
00286     retExpr = aux;
00287   }
00288 
00289   if (coeff != 1.) {
00290 
00291     retExpr = p -> addAuxiliary (retExpr);
00292     retExpr = new exprMul (new exprConst (coeff), new exprClone (retExpr));
00293   }
00294 
00295   return (addAux ? (p -> addAuxiliary (retExpr)) : new exprAux (retExpr, p -> domain ()));
00296 }

Generated on Thu Nov 10 03:05:43 2011 by  doxygen 1.4.7