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

Go to the documentation of this file.
00001 /* $Id: conv-exprGroup.cpp 490 2011-01-14 16:07:12Z pbelotti $
00002  *
00003  * Name:    conv-exprGroup.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: implementation of convexification methods for exprGroup
00006  *
00007  * (C) Carnegie-Mellon University, 2006-10.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "OsiRowCut.hpp"
00012 #include "OsiCuts.hpp"
00013 
00014 #include "CouenneCutGenerator.hpp"
00015 
00016 #include "CouenneExprGroup.hpp"
00017 #include "CouenneExprBound.hpp"
00018 #include "CouenneExprMul.hpp"
00019 
00020 #include "CouenneProblem.hpp"
00021 
00022 using namespace Couenne;
00023 
00025 void exprGroup::getBounds (expression *&lb, expression *&ub) {
00026 
00027   expression 
00028     **lbnl = new expression * [1], 
00029     **ubnl = new expression * [1];
00030 
00031   // TODO: do not aggregate members of exprSum
00032 
00033   // compute lower/upper bound of nonlinear part
00034   exprSum::getBounds (*lbnl, *ubnl);
00035 
00036   lincoeff 
00037     *coeL = new lincoeff,
00038     *coeU = new lincoeff;
00039 
00040   // derive linear part (obtain constant)
00041   for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00042 
00043     std::pair <exprVar *, CouNumber> pairL, pairU;
00044 
00045     CouNumber coeff = el -> second;
00046     int         ind = el -> first -> Index ();
00047 
00048     pairL .second = pairU .second = coeff;
00049 
00050     if (coeff < 0.) {
00051       pairL.first = new exprUpperBound (ind, el -> first -> domain ());
00052       pairU.first = new exprLowerBound (ind, el -> first -> domain ());
00053     } else {
00054       pairL.first = new exprLowerBound (ind, el -> first -> domain ());
00055       pairU.first = new exprUpperBound (ind, el -> first -> domain ());
00056     }
00057 
00058     coeL -> push_back (pairL);
00059     coeU -> push_back (pairU);
00060   }
00061 
00062   lb = new exprGroup (c0_, *coeL, lbnl, 1);
00063   ub = new exprGroup (c0_, *coeU, ubnl, 1);
00064 
00065   delete coeL;
00066   delete coeU;
00067 }
00068 
00069 
00070 // /// Get expressions of lower and upper bound of an expression (if any)
00071 // void exprGroup::getBounds (expression *&lb, expression *&ub) {
00072 
00073 //   expression *lbnl, *ubnl;
00074 
00075 //   // TODO: do not aggregate members of exprSum
00076 
00077 //   // compute lower/upper bound of nonlinear part
00078 //   exprSum::getBounds (lbnl, ubnl);
00079 
00080 //   // count linear and constant terms
00081 //   int nlin = lcoeff_.size();
00082 //   if (fabs (c0_) > COUENNE_EPS) nlin++;
00083 //   //  for (register int *ind = index_; *ind++>=0; nlin++);
00084 
00085 //   expression 
00086 //     **linall = new expression * [nlin + 1], // linear arglist for lower bound
00087 //     **linalu = new expression * [nlin + 1]; //                    upper
00088 
00089 //   // add constant to bounds
00090 //   if (fabs (c0_) > COUENNE_EPS) {
00091 //     *linall++ = new exprConst (c0_);
00092 //     *linalu++ = new exprConst (c0_);
00093 //   }
00094 
00095 //   // TODO: make it another exprGroup!
00096 
00097 //   // derive linear part (obtain constant)
00098 //   for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00099 
00100 //     //    c0 += el -> second;
00101 
00102 //     CouNumber coeff = el -> second;
00103 //     int         ind = el -> first -> Index ();
00104 
00105 //     expression *l = new exprLowerBound (ind, el -> first -> domain ()),
00106 //                *u = new exprUpperBound (ind, el -> first -> domain ());
00107 
00108 //     if (fabs (coeff - 1.) < COUENNE_EPS) {
00109 //       *linall++ = l;
00110 //       *linalu++ = u;
00111 //     } else {
00112 
00113 //       expression *c1 = new exprConst (coeff),
00114 //                  *c2 = new exprConst (coeff);
00115 
00116 //       if (coeff < 0) {
00117 //      *linall++ = new exprMul (c1, u);
00118 //      *linalu++ = new exprMul (c2, l);
00119 //       } else {
00120 //      *linall++ = new exprMul (c1, l);
00121 //      *linalu++ = new exprMul (c2, u);
00122 //       }
00123 //     }
00124 //   }
00125 
00126 //   *linall = lbnl;
00127 //   *linalu = ubnl;
00128 
00129 //   lb = new exprSum (linall - nlin, nlin + 1);
00130 //   ub = new exprSum (linalu - nlin, nlin + 1);
00131 // }
00132 
00133 
00134 
00136 void exprGroup::getBounds (CouNumber &lb, CouNumber &ub) {
00137 
00138   // compute lower/upper bound of nonlinear part
00139 
00140   exprSum::getBounds (lb, ub);
00141   /*{
00142     expression *le, *ue;
00143     getBounds (le, ue);
00144 
00145     lb = (*le) ();
00146     ub = (*ue) ();
00147 
00148     delete le;
00149     delete ue;
00150     }*/
00151 
00152   lb += c0_;
00153   ub += c0_;
00154 
00155   // derive linear part (obtain constant)
00156   for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00157 
00158     exprVar    *var = el -> first;
00159     CouNumber coeff = el -> second, vlb, vub;
00160 
00161     bool 
00162       inf_lb = false,
00163       inf_ub = false;
00164 
00165     if ((vlb = var -> lb ()) < -COUENNE_INFINITY) {
00166       if (coeff > 0) inf_lb = true;
00167       else           inf_ub = true;
00168     } else {
00169       if (coeff > 0) lb += vlb * coeff;
00170       else           ub += vlb * coeff;
00171     }
00172 
00173     if ((vub = var -> ub ()) >  COUENNE_INFINITY) {
00174       if (coeff > 0) inf_ub = true;
00175       else           inf_lb = true;
00176     } else {
00177       if (coeff > 0) ub += vub * coeff;
00178       else           lb += vub * coeff;
00179     }
00180 
00181     if (inf_lb)
00182       lb = -COUENNE_INFINITY;
00183 
00184     if (inf_ub) {
00185       ub =  COUENNE_INFINITY;
00186       if (inf_lb)
00187         break;
00188     }
00189 
00190     //if (inf_lb && inf_ub) break; // no need to keep computing...
00191   }
00192 }
00193 
00194 
00195 // generate equality between *this and *w
00196 void exprGroup::generateCuts (expression *w,
00197                               OsiCuts &cs, const CouenneCutGenerator *cg,
00198                               t_chg_bounds *chg, 
00199                               int wind, CouNumber lb, CouNumber ub) {
00200 
00201   // very similar to exprSum::generateCuts. First of all, this has
00202   // been standardized into a sum, so it only gets a cut in the
00203   // initial relaxation
00204   if (!(cg -> isFirst ()))
00205     return;
00206 
00207   // there is one linear term so far: -w
00208   int nterms = lcoeff_.size ();
00209 
00210   OsiRowCut *cut = new OsiRowCut;
00211 
00212   // If this aux is fixed, don't write 
00213   //
00214   // "- w + ax = -b" but just
00215   // 
00216   // "ax = -b+ w0" 
00217   //
00218   // with w0 its constant value
00219 
00220   CouNumber vlb, vub;
00221   w -> getBounds (vlb, vub);
00222   bool uselessAux = (vub < vlb + COUENNE_EPS);
00223 
00224   // TODO: generalize to sign!= ::EQ
00225 
00226   int displacement = (wind < 0 && !uselessAux) ? 1: 0;
00227 
00228   CouNumber *coeff = new CouNumber [nargs_ + nterms + displacement];
00229   int       *index = new int       [nargs_ + nterms + displacement];
00230 
00231   if (wind < 0 && !uselessAux) {
00232     // first, make room for aux variable
00233     coeff [0] = -1.; 
00234     index [0] = w -> Index ();
00235     lb = ub = 0;
00236   }
00237 
00238   if (uselessAux)
00239     lb = ub = vlb;
00240 
00241   lb -= c0_;
00242   ub -= c0_;
00243 
00244   // now add linear terms
00245   lincoeff::iterator el = lcoeff_.begin ();
00246 
00247   for (int i=0; el != lcoeff_.end (); ++el) 
00248 
00249     if (fabs (el -> second) > 1.0e-21) { 
00250       // why 1.0e-21? Look at CoinPackedMatrix.cpp:2237
00251 
00252       coeff [i   + displacement] = el -> second; 
00253       index [i++ + displacement] = el -> first -> Index ();
00254     }
00255 
00256   // scan arglist for (aux) variables and constants
00257   for (int i=0; i<nargs_; i++) {
00258 
00259     expression *curr = arglist_ [i];
00260 
00261     if (curr -> Type () == CONST) {// constant term in sum
00262       lb -= curr -> Value ();
00263       ub -= curr -> Value ();
00264     }
00265     else {                        // variable
00266       coeff [++nterms] = 1.; 
00267       index   [nterms] = curr -> Index ();
00268     }
00269   }
00270 
00271   cut -> setRow (nterms + displacement, index, coeff);
00272 
00273   delete [] index;
00274   delete [] coeff;
00275 
00276   enum auxSign sign = expression::AUX_EQ;
00277 
00278   if (wind < 0)
00279     sign = cg -> Problem () -> Var (w -> Index ()) -> sign ();
00280 
00281   if (lb > -COUENNE_INFINITY && (wind >= 0 || sign != expression::AUX_GEQ)) cut -> setLb (lb);
00282   if (ub <  COUENNE_INFINITY && (wind >= 0 || sign != expression::AUX_LEQ)) cut -> setUb (ub);
00283 
00284   cut -> setGloballyValid (); // added only once, it is global
00285   cs.insert (cut);
00286   delete cut;
00287 }

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