/home/coin/SVN-release/OS-2.0.0/Couenne/src/standardize/standardize.cpp

Go to the documentation of this file.
00001 /*
00002  * $Id: standardize.cpp 154 2009-06-16 18:52:53Z pbelotti $
00003  *
00004  * Name:    standardize.cpp
00005  * Author:  Pietro Belotti
00006  * Purpose: standardize all expressions in a problem
00007  *
00008  * (C) Carnegie-Mellon University, 2006-09.
00009  * This file is licensed under the Common Public License (CPL)
00010  */
00011 
00012 #include <vector>
00013 
00014 #include "CoinHelperFunctions.hpp"
00015 
00016 #include "CouenneTypes.hpp"
00017 #include "expression.hpp"
00018 #include "exprIVar.hpp"
00019 #include "exprClone.hpp"
00020 #include "CouenneProblem.hpp"
00021 #include "CouenneProblemElem.hpp"
00022 #include "depGraph.hpp"
00023 
00024 //#define DEBUG
00025 
00027 
00028 bool CouenneProblem::standardize () {
00029 
00030 #ifdef DEBUG
00031   printf ("START: current point: %d vars -------------------\n", 
00032           domain_.current () -> Dimension ());
00033   for (int i=0; i<domain_.current () -> Dimension (); i++)
00034     printf ("%3d %20g [%20g %20g]\n", i, domain_.x (i), domain_.lb (i), domain_.ub (i));
00035 #endif
00036 
00037   bool retval = true;
00038 
00039   // create dependence graph to assign an order to the evaluation (and
00040   // bound propagation, and -- in reverse direction -- implied bounds)
00041   graph_ = new DepGraph;
00042 
00043   for (std::vector <exprVar *>::iterator i = variables_ . begin ();
00044        i != variables_ . end (); ++i)
00045     graph_ -> insert (*i);
00046 
00047   // allocate space in auxiliaries_ from commonexprs_
00048 
00049   int initVar = variables_ . size () - commonexprs_ . size ();
00050 
00051   // Defined variables ///////////////////////////////////////////
00052 
00053   // standardize initial aux variables (aka defined variables, aka
00054   // common expression)
00055 
00056 #ifdef DEBUG
00057   if (commonexprs_.size ()) printf ("%d common exprs, initVar = %d = %d - %d\n", 
00058                                     commonexprs_.size (), 
00059                                     initVar, 
00060                                     variables_ . size (), 
00061                                     commonexprs_ . size ());
00062 #endif
00063 
00064   for (std::vector <expression *>::iterator i = commonexprs_ . begin ();
00065        i != commonexprs_ . end (); ++i) {
00066 
00067 #ifdef DEBUG
00068     printf ("-- stdz common expr [%d] :=", initVar); fflush (stdout);
00069     (*i) -> print (); printf ("\n"); fflush (stdout);
00070 #endif
00071 
00072     exprAux *naux = (*i) -> standardize (this, false);
00073 
00074     expression *img = naux -> Image ();
00075 
00076     // trick to obtain same index as common expression: create exprAux
00077     // with index initVar and replace occurrences with address of
00078     // newly created exprAux through auxiliarize()
00079 
00080     exprAux *newvar = new exprAux (img, initVar, 1 + img -> rank (), exprAux::Unset, &domain_);
00081     //img -> isInteger () ? exprAux::Integer : exprAux::Continuous);
00082 
00083     auxiliarize (newvar); // takes care of putting newvar at right position in variables_
00084 
00085     graph_ -> insert (newvar);
00086     graph_ -> erase (naux);
00087 
00088     //variables_ . erase (variables_ . end () - 1);
00089 
00090 #ifdef DEBUG
00091     if (naux) {
00092       printf ("done: "); fflush (stdout);
00093       naux -> print ();
00094       printf (" := "); fflush (stdout);
00095       naux -> Image () -> print (); printf ("\n..."); fflush (stdout);
00096     } else if (*i) {
00097       (*i) -> print ();
00098       //printf (" := "); fflush (stdout);
00099       //aux -> Image () -> print (); 
00100       printf ("\n");
00101     } else printf ("[n]aux NULL!\n");
00102 #endif
00103 
00104     initVar++;
00105   }
00106 
00107   // OBJECTIVES //////////////////////////////////////////////////////////////////////////////
00108 
00109   for (std::vector <CouenneObjective *>::iterator i = objectives_.begin ();
00110        i != objectives_.end (); ++i) {
00111 
00112 #ifdef DEBUG
00113     printf ("Objective [code: %d]", (*i) -> Body () -> code ()); (*i) -> print ();
00114 #endif
00115 
00116     exprAux *aux = (*i) -> standardize (this);
00117 
00118 #ifdef DEBUG
00119     printf ("      --> "); (*i) -> print (); 
00120     if (aux) {printf (" -- aux is "); aux -> print (); printf ("\n");}
00121 #endif
00122 
00123     if (aux) {
00124       //delete ((*i) -> Body ());
00125       (*i) -> Body (new exprClone (aux));
00126     }
00127 
00128 #ifdef DEBUG
00129     printf ("      --> "); (*i) -> print (); printf ("...................\n");
00130 #endif
00131   }
00132 
00133   // commuted_ is an array with a flag for each original variable,
00134   // which is true at position i if initially original variable x_i
00135   // went auxiliary
00136 
00137   commuted_ = new bool [nVars ()];
00138   for (int i = nVars (); i--;)
00139     *commuted_++ = false;
00140   commuted_ -= nVars ();
00141 
00142   //  std::vector <CouenneConstraint *> con2;
00143   std::vector <std::vector <CouenneConstraint *>::iterator> iters2erase;
00144 
00145 
00146   // CONSTRAINTS /////////////////////////////////////////////////////////////////////////////
00147 
00148   for (std::vector <CouenneConstraint *>::iterator i = constraints_.begin (); 
00149        i != constraints_.end (); ++i) {
00150 
00151 #ifdef DEBUG
00152     printf ("############# Constraint "); 
00153     (*i) -> print ();
00154 #endif
00155 
00156     exprAux *aux = (*i) -> standardize (this);
00157 
00158 #ifdef DEBUG
00159     printf (" ==> [%d] ", aux ? (aux -> Index ()) : -1); 
00160     (*i) -> print ();
00161 #endif
00162 
00163     if (aux) { // save if standardized
00164       //delete ((*i) -> Body ());
00165       (*i) -> Body (new exprClone (aux));
00166       //      con2.push_back (*i);
00167     }
00168     else {
00169       CouNumber lb, ub;
00170       (*i) -> Body () -> getBounds (lb, ub);
00171       if ((((*((*i) -> Lb ())) ()) > ub) ||
00172           (((*((*i) -> Ub ())) ()) < lb)) {
00173         printf ("found infeasible constraint [%g,%g]\n", lb, ub);
00174         (*i) -> print ();
00175         retval = false;
00176       }
00177       iters2erase.push_back (i);
00178     }
00179 
00180     //(*i) -> Body () -> realign (this);
00181 
00182 #ifdef DEBUG
00183     printf (" --> ");
00184     (*i) -> print ();
00185     printf ("..............................................................\n");
00186     //print ();
00187 #endif
00188 
00189     /*printf ("=== "); fflush (stdout); 
00190     aux -> print (); printf (" := "); fflush (stdout);
00191     aux -> Image () -> print (); printf ("\n");*/
00192   }
00193 
00194   for (unsigned int i = iters2erase.size (); i--;)
00195     constraints_. erase (iters2erase [i]);
00196 
00197 #ifdef DEBUG 
00198   // Use with caution. Bounds on auxs are not defined yet, so valgrind complains
00199   printf ("done with standardization: (careful, bounds below can be nonsense)\n");
00200   print (); 
00201 #endif
00202 
00203   // Create evaluation order ////////////////////////////////////////////////////
00204 
00205   delete auxSet_;
00206 
00207   // reallocate space for enlarged set of variables
00208   domain_.current () -> resize (nVars ());
00209 
00210   //graph_ -> print ();
00211   graph_ -> createOrder ();
00212   //graph_ -> print ();
00213 
00214   assert (graph_ -> checkCycles () == false);
00215 
00216   // Fill numbering structure /////////////////////////////////////////////////
00217 
00218   int n = nVars ();
00219   numbering_ = new int [n];
00220   std::set <DepNode *, compNode> vertices = graph_ -> Vertices ();
00221 
00222   for (std::set <DepNode *, compNode>::iterator i = vertices.begin ();
00223        i != vertices.end (); ++i)
00224 
00225     numbering_ [(*i) -> Order ()] = (*i) -> Index (); 
00226 
00228 
00229   for (int i = 0; i < nVars (); i++) {
00230 
00231     int ord = numbering_ [i];
00232 
00233     if (variables_ [ord] -> Type () == AUX) {
00234 
00235       // initial auxiliary bounds are infinite (they are later changed
00236       // through branching)
00237 
00238       if (variables_ [ord] -> Index () >= nOrigVars_) { // and one that was not an original, originally...
00239 
00240         domain_.lb (ord) = -COIN_DBL_MAX;
00241         domain_.ub (ord) =  COIN_DBL_MAX;
00242       }
00243 
00244       //printf ("from "); variables_ [ord] -> Lb    () -> print (); 
00245 
00246       // tighten them with propagated bounds
00247       variables_ [ord] -> crossBounds ();
00248 
00249       //printf ("to "); variables_ [ord] -> Lb    () -> print (); printf (", now eval\n");
00250 
00251 #ifdef DEBUG
00252       printf (":::: %3d %10g [%10g, %10g]", 
00253               ord, domain_.x (ord), domain_.lb (ord), domain_.ub (ord));
00254 #endif
00255 
00256       // and evaluate them
00257       domain_.x  (ord) = (*(variables_ [ord] -> Image ())) ();
00258       domain_.lb (ord) = (*(variables_ [ord] -> Lb    ())) ();
00259       domain_.ub (ord) = (*(variables_ [ord] -> Ub    ())) ();
00260 
00261 #ifdef DEBUG
00262       printf (" --> %10g [%10g, %10g] [", 
00263               domain_.x (ord), domain_.lb (ord), domain_.ub (ord));
00264       variables_ [ord] -> Lb () -> print (); printf (",");
00265       variables_ [ord] -> Ub () -> print (); printf ("]\n");
00266 #endif
00267 
00268       bool integer = variables_ [ord] -> isInteger ();
00269 
00270       if (integer) {
00271         domain_.lb (ord) = ceil  (domain_.lb (ord) - COUENNE_EPS);
00272         domain_.ub (ord) = floor (domain_.ub (ord) + COUENNE_EPS);
00273       }
00274     }
00275   }
00276 
00277   // TODO: resolve duplicate index in exprQuad before restoring this
00278 
00279   std::string delete_redund;
00280   if (bonBase_)
00281     bonBase_ -> options () -> GetStringValue ("delete_redundant", delete_redund, "couenne."); 
00282   else
00283     delete_redund = "yes";
00284 
00285   if (delete_redund == "yes")
00286 
00287     // Look for auxiliaries of the form w:=x and replace each occurrence of w with x
00288     for (std::vector <exprVar *>::iterator i = variables_.begin (); 
00289        i != variables_.end (); ++i)
00290 
00291     if ((*i) -> Type () == AUX) {
00292 
00293       int type = (*i) -> Image () -> Type ();
00294 
00295       if ((type == VAR) || (type == AUX)) {
00296 
00297         // found w_k = x_h. 
00298         // 
00299         // Check if either is integer, the survivor will be integer too
00300         // Replace all occurrences of w_k with x_h
00301 
00302         /*printf ("redundancy: "); 
00303         (*i)             -> print (); printf (" := "); 
00304         (*i) -> Image () -> print (); printf ("\n");*/
00305 
00306         // use the info on the variable to be discarded: tighter
00307         // bounds and integrality that the replacement might not have.
00308 
00309         int 
00310           indStays  = (*i) -> Image () -> Index (), // index h
00311           indLeaves = (*i)             -> Index (); // index k
00312 
00313         if (indStays == indLeaves)  // very strange case, w_h = x_h
00314           continue;
00315 
00316         // do not swap! x_h could be in turn an auxiliary...
00317         //
00318         //if (indStays > indLeaves) 
00319         //{int swap = indStays; indStays = indLeaves; indLeaves = swap;} // swap
00320 
00321         exprVar 
00322           *varStays  = variables_ [indStays],
00323           *varLeaves = variables_ [indLeaves];
00324 
00325         // intersect features of the two variables (integrality, bounds)
00326 
00327         varStays -> lb () = varLeaves -> lb () = CoinMax (varStays -> lb (), varLeaves -> lb ());
00328         varStays -> ub () = varLeaves -> ub () = CoinMin (varStays -> ub (), varLeaves -> ub ());
00329 
00330         if (varStays  -> isInteger () ||
00331             varLeaves -> isInteger ()) {
00332 
00333           varStays -> lb () = ceil  (varStays -> lb ());
00334           varStays -> ub () = floor (varStays -> ub ());
00335 
00336           if (varStays -> Type () == AUX)
00337             varStays -> setInteger (true);
00338           else {
00339             //expression *old = varStays; // !!! leak
00340             variables_ [indStays] = varStays = new exprIVar (indStays, &domain_);
00341             auxiliarize (varStays); // replace it everywhere in the problem
00342             //delete old;
00343           }
00344         }
00345 
00346         auxiliarize (varLeaves, varStays); // now replace occurrences of w_k with x_h
00347 
00348         //if (varLeaves -> Index () >= nOrigVars_) // why check? It's not there anymore.
00349         varLeaves -> zeroMult (); // disable this variable
00350       }
00351     }
00352 
00358   for (int ii=0; ii < nVars (); ii++) {
00359 
00360     int i = numbering_ [ii];
00361 
00362     if ((Var (i) -> Multiplicity () > 0) &&
00363         (Var (i) -> Type () == AUX) &&
00364         (Var (i) -> Image () -> isInteger ()))
00365       Var (i) -> setInteger (true);
00366 
00367     //if (Var (i) -> Multiplicity () == 0)
00368     //Lb (i) = Ub (i) = 0.;
00369   }
00370 
00371   // TODO: re-compute ranks
00372 
00373   delete [] commuted_;  commuted_ = NULL;
00374   delete    graph_;     graph_    = NULL;
00375 
00376   return retval;
00377 }

Generated on Mon Aug 3 03:02:21 2009 by  doxygen 1.4.7