/home/coin/SVN-release/OS-2.4.1/Couenne/src/expression/operators/bounds/exprBQuad.cpp

Go to the documentation of this file.
00001 /* $Id: exprBQuad.cpp 490 2011-01-14 16:07:12Z pbelotti $ */
00002 /*
00003  * Name:    exprBQuad.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: method to compute value of an expr?BQuad
00006  *
00007  * (C) Carnegie-Mellon University, 2006. 
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CoinHelperFunctions.hpp"
00012 #include "CouenneExprBQuad.hpp"
00013 
00014 using namespace Couenne;
00015 
00016 //#define DEBUG
00017 
00018 CouNumber exprQuad::computeQBound (int sign) {
00019 
00020   // 1) loose: disaggregated bound
00021   // 2) tighter: aggregate coefficient per variable
00022   // 3) tightest: solve (convex) QP on available alpha-convexification
00023 
00024   // 1) loose bound
00025   //
00026   // w = a0 + a'x + x'Qx means that its lower bound is
00027   //
00028   // w_l = a0 + a'_+ x_l + a'_- x_u + \sum_
00029 
00030 
00031   // 2) tighter bound -- TODO
00032   //
00033   // Compute lower (if sign == -1) or upper (sign == +1) bound of an
00034   // exprQuad based on the information obtained through
00035   // alpha-convexification, if any, or as follows:
00036   //
00037   // w = a0 + a'x + x'Qx = 
00038   //   = a0 + sum{i} [(a_i + sum {j>=i} q_ij * x_j) * x_i] =
00039   //   = a0 + sum{i} [                          z_i * x_i]
00040   // 
00041   // Thus, some bound on z_i can be computed and a bound on the whole
00042   // expression should be better than what can be obtained by summing
00043   // all bounds separately.
00044   //
00045   // Notice that the above computation is fast and may be better than
00046   // the convexification after some updates in the variable bounds
00047   // without updating the convexification. Notice also that the
00048   // direction can also be vertical, not only horizontal.
00049 
00050   CouNumber bound = c0_, term;
00051 
00052   // derive linear part (obtain constant)
00053   for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00054 
00055     CouNumber 
00056       coe = el -> second, term = 0.,
00057       lb  = el -> first -> lb (),
00058       ub  = el -> first -> ub ();
00059 
00060     if (((coe < 0.) && (sign < 0)) || 
00061         ((coe > 0.) && (sign > 0))) 
00062       {if    ((term=ub) >  COUENNE_INFINITY) return (sign < 0)? -COUENNE_INFINITY : COUENNE_INFINITY;}
00063     else {if ((term=lb) < -COUENNE_INFINITY) return (sign < 0)? -COUENNE_INFINITY : COUENNE_INFINITY;}
00064 
00065     bound += coe * term;
00066   }
00067 
00068 #ifdef DEBUG
00069   printf ("quadBound --- linear, %cb = %g\n", (sign < 0) ? 'l' : 'u', bound);
00070 #endif
00071 
00072   // derive quadratic part (obtain linear part)
00073   for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00074 
00075     int xind = row -> first -> Index ();
00076 
00077       CouNumber 
00078         lbi = row -> first -> lb (),
00079         ubi = row -> first -> ub ();
00080 
00081     for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00082 
00083       int yind = col -> first -> Index ();
00084 
00085       CouNumber coe = col -> second;
00086 
00087       if (xind == yind) { // term of the form q_ii x_i^2
00088 
00089         if (((coe > 0.) && (sign < 0)) ||
00090             ((coe < 0.) && (sign > 0))) 
00091           term = (ubi < 0) ? (ubi * ubi) : (lbi > 0) ? (lbi * lbi) : 0.; //min{xi^2: xi in [lbi,ubi]
00092         else 
00093           if ((term = CoinMax (lbi*lbi, ubi*ubi)) > COUENNE_INFINITY) 
00094             return (sign < 0) ? -COUENNE_INFINITY : COUENNE_INFINITY;
00095 
00096         term *= coe;
00097 
00098 #ifdef DEBUG
00099         printf ("Qii %d %g %g -> %g\n", xind, coe, term, bound + term);
00100 #endif
00101       } else {
00102 
00103         coe *= 2;
00104 
00105         CouNumber
00106           lbj = col -> first -> lb (),
00107           ubj = col -> first -> ub (),
00108           b1 = coe * lbi * lbj, 
00109           b2 = coe * lbi * ubj,
00110           b3 = coe * ubi * lbj, 
00111           b4 = coe * ubi * ubj;
00112 
00113         if (fabs (lbi) == 0) b1 = b2 = 0;
00114         if (fabs (lbj) == 0) b1 = b3 = 0;
00115         if (fabs (ubi) == 0) b3 = b4 = 0;
00116         if (fabs (ubj) == 0) b2 = b4 = 0;
00117 
00118         if (sign < 0) {
00119           if ((term = CoinMin (CoinMin (b1, b2), CoinMin (b3, b4))) < -COUENNE_INFINITY) 
00120             return -COUENNE_INFINITY; 
00121         } else
00122           if ((term = CoinMax (CoinMax (b1, b2), CoinMax (b3, b4))) >  COUENNE_INFINITY)
00123             return  COUENNE_INFINITY;
00124 
00125 #ifdef DEBUG
00126         printf ("Qij %d %d %g %g -> %g\n", xind, yind, coe, term, bound + term);
00127 #endif
00128       }
00129 
00130       //      if ((i!=j) || (lbi >= 0) || (ubi <= 0))
00131       bound += term;
00132     }
00133   }
00134 
00135   return bound;
00136 }

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