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

Go to the documentation of this file.
00001 /* $Id: constrStandardize.cpp 298 2010-02-13 14:16:56Z pbelotti $
00002  *
00003  * Name:    constrStandardize.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: standardization of constraints
00006  *
00007  * (C) Carnegie-Mellon University, 2007-10.
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 #include "CouenneProblemElem.hpp"
00012 #include "CouenneProblem.hpp"
00013 
00014 #include "exprAux.hpp"
00015 #include "exprIVar.hpp"
00016 #include "depGraph.hpp"
00017 
00018 //#define DEBUG
00019 
00020 // replace a variable
00021 void replace (CouenneProblem *p, int wind, int xind);
00022 
00023 
00025 exprAux *CouenneConstraint::standardize (CouenneProblem *p) {
00026 
00027   // spot an auxiliary variable in constraint's body w - f(x) and move
00028   // the explicit w into the vector of auxiliary variables
00029   //
00030   // do it only if this is an equality constraint and there is at
00031   // least one variable that did not show up so far (need a problem
00032   // structure)
00033 
00034 #ifdef DEBUG
00035   printf ("################################\nStandardizing constraint: "); print ();
00036 
00037   printf (" ["); fflush (stdout); lb_ -> print ();
00038   printf (","); fflush (stdout);  ub_ -> print (); fflush (stdout);
00039   /*  printf ("] {with auxset = ");
00040   for (std::set <exprAux *, compExpr>::iterator i = p -> AuxSet () -> begin ();
00041        i != p -> AuxSet () -> end (); i++) {
00042     printf ("<"); (*i) -> print (); 
00043     printf (","); (*i) -> Image () -> print (); printf ("> ");
00044     }*/
00045   printf ("]\n");
00046 #endif
00047 
00048   if (compareExpr (&lb_, &ub_) == 0) {
00049 
00050     // this is an equality constraint, and could be the definition of
00051     // an auxiliary
00052 
00053     expression *rest;
00054 
00055     // split w from f(x)
00056     int wind = p -> splitAux ((*lb_) (), body_, rest, p -> Commuted ());
00057 
00058     if (wind >= 0) { // this IS the definition of an auxiliary variable w = f(x)
00059 
00060       // first, simplify expression (you never know)
00061 
00062       expression *restSimple = rest -> simplify ();
00063 
00064       if (restSimple) {
00065         delete rest;
00066         rest = restSimple;
00067       }
00068 
00069       // second, if this is a constraint of the form x=k, reset x's
00070       // bounds and do nothing else
00071 
00072       if (rest -> code () == COU_EXPRCONST) {
00073 
00074         p -> Var (wind) -> lb () = 
00075         p -> Var (wind) -> ub () = rest -> Value ();
00076 
00077         delete rest;
00078         return NULL;
00079       }
00080 
00081       // now assign a new auxiliary variable (with the same index,
00082       // "wind", as the old original variable) to the expression
00083       // contained in "rest"
00084 
00085       p -> Commuted () [wind] = true;
00086 
00087 #ifdef DEBUG
00088       printf ("---> %d & ", wind); fflush (stdout);
00089       rest -> print (); printf ("\n");
00090 #endif
00091 
00092       assert (p -> Var (wind) -> Type () == VAR);
00093 
00094       // check if constraint now reduces to w_k = x_h, and if so
00095       // replace all occurrences of x_k with x_h
00096 
00097       int xind = rest -> Index ();
00098 
00099       if (xind >= 0) {
00100 
00101         replace (p, wind, xind);
00102 
00103         p -> auxiliarize (p -> Var (wind), p -> Var (xind));
00104         p -> Var (wind) -> zeroMult (); // redundant variable is neutralized
00105 
00106       } else {
00107 
00108         // create new variable, it has to be integer if original variable was integer
00109         exprAux *w = new exprAux (rest, wind, 1 + rest -> rank (),
00110                                   p -> Var (wind) -> isInteger () ? 
00111                                   exprAux::Integer : exprAux::Continuous,
00112                                   p -> domain ());
00113 
00114         std::set <exprAux *, compExpr>::iterator i = p -> AuxSet () -> find (w);
00115 
00116         // no such expression found in the set:
00117         if (i == p -> AuxSet () -> end ()) {
00118 
00119           p -> AuxSet      () -> insert (w); // 1) beware of useless copies
00120           p -> getDepGraph () -> insert (w); // 2) introduce it in acyclic structure
00121 
00122 #ifdef DEBUG
00123           printf ("now replacing x [%d] with ", wind); fflush (stdout);
00124           w -> print (); printf (" := ");
00125           w -> Image () -> print (); printf ("\n");
00126 #endif
00127 
00128           // replace ALL occurrences of original variable (with index
00129           // wind) with newly created auxiliary
00130           p -> auxiliarize (w);
00131         } 
00132 
00133 #ifdef DEBUG
00134         else {
00135           printf ("found aux occurrence of "); fflush (stdout);
00136           w -> print (); printf (" := ");
00137           w -> Image () -> print (); printf (" ... ");
00138           (*i) -> print (); printf (" := ");
00139           (*i) -> Image () -> print (); printf ("\n");
00140 
00141           // if this is an original variable and is competing with an
00142           // auxiliary variable, or at least this has a lower index,
00143           // we better replace it throughout and eliminate that
00144           // aux. See globallib/st_glmp_fp3 for an example where this
00145           // otherwise would be a bug (x_1 unlinked from x2-x3 and
00146           // leading to unbounded)
00147           
00148           int xind = (*i) -> Index (), iMax, iMin;
00149 
00150           if (xind < wind) {
00151             iMax = wind;
00152             iMin = xind;
00153           } else {
00154             iMax = xind;
00155             iMin = wind;
00156           }
00157 
00158           replace (p, iMax, iMin);
00159 
00160           p -> auxiliarize (p -> Var (iMax), p -> Var (iMin));
00161           p -> Var (iMax) -> zeroMult (); // redundant variable is neutralized
00162           p -> auxiliarize (w);
00163         }
00164 #endif
00165       }
00166 
00167       return NULL;
00168     }
00169   }
00170 
00171 #ifdef DEBUG
00172   printf ("\nnormal\n-----------------\n");
00173 #endif
00174 
00175   return body_ -> standardize (p);
00176 }
00177 
00178 
00179 // Replace a variable ////////////////////////////////
00180 void replace (CouenneProblem *p, int wind, int xind) {
00181 
00182   exprVar 
00183     *varLeaves = p -> Variables () [wind],
00184     *varStays  = p -> Variables () [xind];
00185 
00186   // intersect features of the two variables (integrality, bounds)
00187 
00188   varStays -> lb () = varLeaves -> lb () = CoinMax (varStays -> lb (), varLeaves -> lb ());
00189   varStays -> ub () = varLeaves -> ub () = CoinMin (varStays -> ub (), varLeaves -> ub ());
00190 
00191   if (varStays  -> isInteger () ||
00192       varLeaves -> isInteger ()) {
00193 
00194     varStays -> lb () = ceil  (varStays -> lb ());
00195     varStays -> ub () = floor (varStays -> ub ());
00196 
00197     if (varStays -> Type () == AUX)
00198       varStays -> setInteger (true);
00199     else {
00200       //expression *old = varStays; // !!! leak
00201       p -> Variables () [xind] = varStays = new exprIVar (xind, p -> domain ());
00202       p -> auxiliarize (varStays); // replace it everywhere in the problem
00203       //delete old;
00204     }
00205   }
00206 }

Generated on Tue Mar 30 03:04:38 2010 by  doxygen 1.4.7