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

Go to the documentation of this file.
00001 /* $Id: constrStandardize.cpp 750 2011-08-05 12:02:43Z pbelotti $
00002  *
00003  * Name:    constrStandardize.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: standardization of constraints
00006  *
00007  * (C) Carnegie-Mellon University, 2007-11.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CoinHelperFunctions.hpp"
00012 
00013 #include "BonBabSetupBase.hpp"
00014 
00015 #include "CouenneProblemElem.hpp"
00016 #include "CouenneProblem.hpp"
00017 
00018 #include "CouenneExpression.hpp"
00019 #include "CouenneExprAux.hpp"
00020 #include "CouenneExprClone.hpp"
00021 #include "CouenneExprIVar.hpp"
00022 #include "CouenneDepGraph.hpp"
00023 
00024 using namespace Couenne;
00025 
00026 // replace a variable
00027 void replace (CouenneProblem *p, int wind, int xind);
00028 
00029 
00031 exprAux *CouenneConstraint::standardize (CouenneProblem *p) {
00032 
00033   // spot an auxiliary variable in constraint's body w - f(x) and move
00034   // the explicit w into the vector of auxiliary variables
00035   //
00036   // do it only if this is an equality constraint and there is at
00037   // least one variable that did not show up so far (need a problem
00038   // structure)
00039 
00040   if (p -> Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_REFORMULATE)) {
00041     printf ("Reformulating constraint: "); print ();
00042 
00043     printf (" ["); fflush (stdout); lb_ -> print ();
00044     printf (","); fflush (stdout);  ub_ -> print (); fflush (stdout);
00045     /*  printf ("] {with auxset = ");
00046         for (std::set <exprAux *, compExpr>::iterator i = p -> AuxSet () -> begin ();
00047         i != p -> AuxSet () -> end (); i++) {
00048         printf ("<"); (*i) -> print (); 
00049         printf (","); (*i) -> Image () -> print (); printf ("> ");
00050         }*/
00051     printf ("]\n");
00052   }
00053 
00054   // Auxiliaries used to be definable with a constraint f(x) + bw = c,
00055   // which implies w := (c - f(x)) / b. Semi-auxiliaries no longer
00056   // need the equality sign, but their sign will be determined by lb_
00057   // and ub_. Their values allow us to decide whether we should create
00058   // a (semi)auxiliary or not.
00059 
00060   CouNumber 
00061     rLb = (*lb_) (),
00062     rUb = (*ub_) ();
00063 
00064   std::string 
00065     use_auxcons,
00066     use_semiaux;
00067 
00068   p -> bonBase () -> options () -> GetStringValue ("use_auxcons", use_auxcons, "couenne.") ; 
00069   p -> bonBase () -> options () -> GetStringValue ("use_semiaux", use_semiaux, "couenne.") ; 
00070 
00071   if ((  use_auxcons == "yes") &&          // if aux generated by constraints are disabled, just bail out
00072       (((use_semiaux == "yes") &&          // otherwise, either we allow semi-auxs
00073         ((rLb < -COUENNE_INFINITY/2) ||    // (and either bound is infinite)
00074          (rUb >  COUENNE_INFINITY/2))) ||  //
00075        (fabs (rLb-rUb) <= COUENNE_EPS))) { // or there is an equality constraint
00076 
00077     enum expression::auxSign aSign = expression::AUX_EQ;
00078 
00079     if      (rLb < -COUENNE_INFINITY/2) aSign = expression::AUX_LEQ;
00080     else if (rUb >  COUENNE_INFINITY/2) aSign = expression::AUX_GEQ;
00081 
00082     CouNumber rhs = rLb >= -COUENNE_INFINITY/2 ? rLb : rUb;
00083 
00084     // this could be the definition of a (semi)-auxiliary
00085 
00086     expression *rest;
00087 
00088     // split w from f(x)
00089     int wind = p -> splitAux (rhs, body_, rest, p -> Commuted (), aSign);
00090 
00091     //printf ("REST [%d] [%g,%g]: ", wind, p -> Lb (wind), p -> Ub (wind)); rest -> print (); printf ("\n");
00092 
00093     if (wind >= 0) { // this IS the definition of an auxiliary variable w = f(x)
00094 
00095       // simplify expression (you never know)
00096 
00097       expression *restSimple = rest -> simplify ();
00098 
00099       if (restSimple) {
00100         delete rest;
00101         rest = restSimple;
00102       }
00103 
00104       // if this is a constraint of the form x=k, reset x's bounds and
00105       // do nothing else
00106 
00107       if (rest -> code () == COU_EXPRCONST) {
00108 
00109         CouNumber constRHS = rest -> Value ();
00110 
00111         if (aSign != expression::AUX_LEQ) p -> Var (wind) -> lb () = constRHS;
00112         if (aSign != expression::AUX_GEQ) p -> Var (wind) -> ub () = constRHS;
00113 
00114         delete rest;
00115         return NULL;
00116       }
00117 
00118       // Assign a new auxiliary variable (with the same index, "wind",
00119       // as the old original variable) to the expression contained in
00120       // "rest"
00121 
00122       p -> Commuted () [wind] = true;
00123 
00124       if (p -> Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_REFORMULATE)) {
00125         printf ("---> %d & ", wind); fflush (stdout);
00126         rest -> print (); printf ("[sign: %d]\n", aSign);
00127       }
00128 
00129       assert (p -> Var (wind) -> Type () == VAR);
00130 
00131       int xind = rest -> Index ();
00132 
00133       // check if constraint now reduces to w_k = x_h, and if so
00134       // replace all occurrences of x_k with x_h
00135 
00136       if ((xind >= 0) && (aSign == expression::AUX_EQ)) {
00137 
00138         // create new variable, it has to be integer if original variable was integer
00139         exprAux *w = new exprAux (new exprClone (p -> Var (xind)), wind, 1 + p -> Var (xind) -> rank (),
00140                                   p -> Var (wind) -> isInteger () ?
00141                                   exprAux::Integer : exprAux::Continuous,
00142                                   p -> domain (), aSign);
00143         p -> auxiliarize (w);
00144         w -> zeroMult ();
00145         
00146         replace (p, wind, xind);
00147 
00148         p -> auxiliarize (p -> Var (wind), p -> Var (xind));
00149         //p -> Var (wind) -> zeroMult (); // redundant variable is neutralized
00150 
00151       } else {
00152 
00153         // create new variable, it has to be integer if original variable was integer
00154         exprAux *w = new exprAux (rest, wind, 1 + rest -> rank (),
00155                                   ((p -> Var (wind) -> isInteger ()) || 
00156                                    (false && (rest -> isInteger ()) && (aSign == expression::AUX_EQ))) ? // FIXME!!!
00157                                   exprAux::Integer : exprAux::Continuous,
00158                                   p -> domain (), aSign);
00159 
00160 //      if (p -> Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_REFORMULATE)) {
00161 
00162 //        printf ("AuxSet:\n");
00163 //        for (std::set <exprAux *, compExpr>::iterator i = p -> AuxSet () -> begin ();
00164 //             i != p -> AuxSet () -> end (); ++i)
00165 //          if ((*i) -> Image () == NULL) {
00166 //            (*i) -> print (); printf (" does not have an image!!!\n");
00167 //          } else {
00168 //            printf ("-- "); (*i) -> print (); printf (" := ");
00169 //            (*i) -> Image () -> print (); printf ("\n");
00170 //          }
00171 //      }
00172 
00173         std::set <exprAux *, compExpr>::iterator i = p -> AuxSet () -> end ();
00174 
00175         if (aSign == expression::AUX_EQ)
00176           i = p -> AuxSet () -> find (w);
00177 
00178         // no such expression found in the set:
00179         if ((i == p -> AuxSet () -> end ()) || (aSign != expression::AUX_EQ)) {
00180 
00181           p -> AuxSet      () -> insert (w); // 1) beware of useless copies
00182           p -> getDepGraph () -> insert (w); // 2) introduce it in acyclic structure
00183 
00184           if (p -> Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_REFORMULATE)) {
00185             printf ("now replacing x [%d] with ", wind); fflush (stdout);
00186             w -> print (); printf (" := ");
00187             w -> Image () -> print (); printf ("\n");
00188           }
00189 
00190           // replace ALL occurrences of original variable (with index
00191           // wind) with newly created auxiliary
00192           p -> auxiliarize (w);
00193         } 
00194 
00195         else {
00196 
00197           if (p -> Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_REFORMULATE)) {
00198             printf ("found aux occurrence of "); fflush (stdout);
00199             w -> print (); printf (" := ");
00200             w -> Image () -> print (); printf (" ... ");
00201             (*i) -> print (); printf (" := ");
00202             (*i) -> Image () -> print (); printf ("\n");
00203           }
00204 
00205           // if this is an original variable and is competing with an
00206           // auxiliary variable, or at least this has a lower index,
00207           // we better replace it throughout and eliminate that
00208           // aux. See globallib/st_glmp_fp3 for an example where this
00209           // otherwise would be a bug (x_1 unlinked from x2-x3 and
00210           // leading to unbounded)
00211           
00212           int xind = (*i) -> Index (), iMax, iMin;
00213 
00214           if (xind < wind) {
00215             iMax = wind;
00216             iMin = xind;
00217           } else {
00218             iMax = xind;
00219             iMin = wind;
00220           }
00221 
00222           replace (p, iMax, iMin);
00223 
00224           p -> auxiliarize (p -> Var (iMax), p -> Var (iMin));
00225           p -> Var (iMax) -> zeroMult (); // redundant variable is neutralized
00226           p -> auxiliarize (w);
00227         }
00228       }
00229 
00230       return NULL;
00231     }
00232   }
00233 
00234   if (p -> Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_REFORMULATE))
00235     printf ("\nnormal\n-----------------\n");
00236 
00237   //body_ -> standardize (p, false); // TODO: check!
00238 
00239   //return NULL;
00240 
00241   return body_ -> standardize (p);
00242 }
00243 
00244 
00245 // Replace a variable ////////////////////////////////
00246 void replace (CouenneProblem *p, int wind, int xind) {
00247 
00248   exprVar 
00249     *varLeaves = p -> Variables () [wind],
00250     *varStays  = p -> Variables () [xind];
00251 
00252   // intersect features of the two variables (integrality, bounds)
00253 
00254   varStays -> lb () = varLeaves -> lb () = CoinMax (varStays -> lb (), varLeaves -> lb ());
00255   varStays -> ub () = varLeaves -> ub () = CoinMin (varStays -> ub (), varLeaves -> ub ());
00256 
00257   if (varStays  -> isInteger () ||
00258       varLeaves -> isInteger ()) {
00259 
00260     varStays -> lb () = ceil  (varStays -> lb ());
00261     varStays -> ub () = floor (varStays -> ub ());
00262 
00263     if (varStays -> Type () == AUX)
00264       varStays -> setInteger (true);
00265     else {
00266       //expression *old = varStays; // !!! leak
00267       p -> Variables () [xind] = varStays = new exprIVar (xind, p -> domain ());
00268       p -> auxiliarize (varStays); // replace it everywhere in the problem
00269       //delete old;
00270     }
00271   }
00272 }

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