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

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

Generated on Thu Aug 5 03:02:56 2010 by  doxygen 1.4.7