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

Go to the documentation of this file.
00001 /* $Id: compQuadFinBounds.cpp 490 2011-01-14 16:07:12Z pbelotti $ */
00002 /*
00003  * Name:    compQuadFinBounds.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: compute bounds on quadratic form without the contribution of a single variable
00006  *
00007  * (C) Carnegie-Mellon University, 2006. 
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CouenneExprQuad.hpp"
00012 #include "CoinHelperFunctions.hpp"
00013 
00014 using namespace Couenne;
00015 
00016 void updateInf (CouNumber coe, CouNumber lb, CouNumber ub, int &indInf1, int &indInf2, int i) {
00017 
00018   if (coe > 0) {
00019     if (lb < 0) indInf1 = (indInf1 == -1) ? i : -2;
00020     if (ub > 0) indInf2 = (indInf2 == -1) ? i : -2;
00021   } else {
00022     if (lb < 0) indInf2 = (indInf2 == -1) ? i : -2;
00023     if (ub > 0) indInf1 = (indInf1 == -1) ? i : -2;
00024   }
00025 }
00026 
00027 // compute bound of a quadratic expression neglecting the infinite
00028 // bounds of single variables
00029 
00030 void exprQuad::computeQuadFiniteBound (CouNumber &qMin, 
00031                                        CouNumber &qMax, 
00032                                        CouNumber *l, 
00033                                        CouNumber *u,
00034                                        int &indInfLo, 
00035                                        int &indInfUp) {
00036 
00037   // linear terms ///////////////////////////////////////////////////
00038 
00039   for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el) {
00040 
00041     int ind = el -> first -> Index ();
00042 
00043     CouNumber 
00044       coe = el -> second,
00045       li  = l [ind], 
00046       ui  = u [ind];
00047 
00048     if (coe < 0) { // negative coefficient
00049 
00050       if (indInfLo > -2) {
00051         if (ui >  COUENNE_INFINITY) indInfLo = (indInfLo == -1) ? ind : -2;
00052         else qMin += coe * ui;
00053       }
00054 
00055       if (indInfUp > -2) {
00056         if (li < -COUENNE_INFINITY) indInfUp = (indInfUp == -1) ? ind : -2;
00057         else qMax += coe * li;
00058       }
00059     } else { // positive coefficient
00060 
00061       if (indInfLo > -2) {
00062         if (li < -COUENNE_INFINITY) indInfLo = (indInfLo == -1) ? ind : -2;
00063         else qMin += coe * li;
00064       }
00065 
00066       if (indInfUp > -2) {
00067         if (ui >  COUENNE_INFINITY) indInfUp = (indInfUp == -1) ? ind : -2;
00068         else qMax += coe * ui;
00069       }
00070     }
00071   }
00072 
00073   // quadratic terms ///////////////////////////////////////////////////
00074 
00075   for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00076 
00077     int i = row -> first -> Index ();
00078 
00079     for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00080 
00081       int j = col -> first -> Index ();
00082 
00083       CouNumber 
00084         coe = col -> second,
00085         lbi = l [i],
00086         ubi = u [i];
00087 
00088       if (i==j) { // term of the form q_{ii} x_i^2
00089 
00090         CouNumber
00091           tmin = (ubi <= 0) ? (ubi * ubi) : (lbi >= 0) ? (lbi * lbi) : 0,
00092           tmax = CoinMax (lbi*lbi, ubi*ubi);
00093 
00094         if (coe < 0) { // negative coefficient, q_{ii} < 0
00095           qMax += coe * tmin;
00096           if (indInfLo > -2) {
00097             if (tmax > COUENNE_INFINITY) indInfLo = (indInfLo == -1) ? i : -2;
00098             else qMin += coe * tmax;
00099           }
00100         } else { // positive coefficient
00101           qMin += coe * tmin;
00102           if (indInfUp > -2) {
00103             if (tmax > COUENNE_INFINITY) indInfUp = (indInfUp == -1) ? i : -2;
00104             else qMax += coe * tmax;
00105           }
00106         }
00107       } else { // term of the form q_{ij} x_i x_j, j\neq i
00108 
00109         CouNumber
00110           lbj = l [j],
00111           ubj = u [j];
00112 
00113         coe *= 2;
00114 
00115         // check if index i wrings unbounded value in both directions
00116 
00117         if (lbi < -COUENNE_INFINITY) updateInf (coe, lbj, ubj, indInfUp, indInfLo, i);
00118         if (lbj < -COUENNE_INFINITY) updateInf (coe, lbi, ubi, indInfUp, indInfLo, j);
00119 
00120         if (ubi >  COUENNE_INFINITY) updateInf (coe, lbj, ubj, indInfLo, indInfUp, i);
00121         if (ubj >  COUENNE_INFINITY) updateInf (coe, lbi, ubi, indInfLo, indInfUp, j);
00122 
00123         CouNumber term, 
00124           b1 = coe * lbi * lbj,
00125           b2 = coe * lbi * ubj,
00126           b3 = coe * ubi * lbj,
00127           b4 = coe * ubi * ubj;
00128 
00129         if ((term = CoinMin (CoinMin (b1, b2), CoinMin (b3, b4))) > -COUENNE_INFINITY) qMin += term;
00130         if ((term = CoinMax (CoinMax (b1, b2), CoinMax (b3, b4))) <  COUENNE_INFINITY) qMax += term;
00131       }
00132     }
00133   }
00134 }

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