/home/coin/SVN-release/OS-2.4.0/Couenne/src/convex/operators/alphaConvexify.cpp

Go to the documentation of this file.
00001 /* $Id: alphaConvexify.cpp 490 2011-01-14 16:07:12Z pbelotti $
00002  *
00003  * Name:    alphaConvexify.cpp
00004  * Author:  Stefan Vigerske
00005  * Purpose: create alpha-convexification of a quadratic expression
00006  *
00007  * (C) Carnegie-Mellon University, 2007-09.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 
00012 #include "CoinHelperFunctions.hpp"
00013 #include "OsiSolverInterface.hpp"
00014 #include "IpLapack.hpp"
00015 
00016 #include "CouenneExprQuad.hpp"
00017 #include "CouenneProblem.hpp"
00018 
00019 using namespace Couenne;
00020 
00021 //#define DEBUG
00022 
00043 bool exprQuad::alphaConvexify (const CouenneProblem *p) {
00044   //const OsiSolverInterface &si) {
00045 
00046   if (matrix_.size () == 0)
00047     return false;
00048 
00049   // inverse of dIndex_ mapping: for each variable tell me the index
00050   // that it will have in dIndex_, or -1 if not there
00051 
00052   int k=0,
00053      nDiag    = bounds_.size (),
00054     *indexmap = new int [p -> nVars ()],
00055     *indices  = new int [nDiag];
00056 
00057   //CoinFillN (indexmap, si.getNumCols (), -1);
00058   CoinFillN (indexmap, p -> nVars (), -1);
00059 
00060   // box diameter
00061   double *diam = new double [nDiag];
00062 
00063   bool changed_bounds = false;
00064 
00065   for (std::map <exprVar *, std::pair <CouNumber, CouNumber> >::iterator i = bounds_.begin ();
00066        i != bounds_.end (); ++i, k++) {
00067 
00068 #ifdef DEBUG
00069   printf ("b%04d. [%20g, %20g]\n", i->first->Index(), i->second.first, i->second.second);
00070 #endif
00071 
00072     int index = i -> first -> Index ();
00073     indexmap [index] = k;
00074     indices [k] = index;
00075 
00076     CouNumber
00077       lb = i -> first -> lb (),
00078       ub = i -> first -> ub ();
00079 
00080     // if one variable unbounded, bail out
00081     if ((lb < -COUENNE_INFINITY) ||
00082         (ub >  COUENNE_INFINITY)) {
00083 
00084       delete [] diam;
00085       delete [] indexmap;
00086       delete [] indices;
00087 
00088 #ifdef DEBUG
00089       printf ("unbounded, bailing out\n");
00090 #endif
00091 
00092       return false;
00093     }
00094 
00095     // if no variable has changed bounds, no need to convexify
00096     if (fabs (lb - i->second.first)  > COUENNE_EPS) {i -> second.first  = lb; changed_bounds = true;}
00097     if (fabs (ub - i->second.second) > COUENNE_EPS) {i -> second.second = ub; changed_bounds = true;}
00098 
00099     diam [k] = ub - lb;
00100 #ifdef DEBUG
00101     printf ("diam %4d - %4d = %g - %g = %g\n", index, k, ub, lb, diam [k]);
00102 #endif
00103   }
00104 
00105   if (!changed_bounds) {
00106 
00107     delete [] diam;
00108     delete [] indexmap;
00109     delete [] indices;
00110 
00111     return true;
00112   }
00113 
00114   // lower triangular of quadratic term matrix, scaled by box diameter
00115 
00116   double *matrix = new double [nDiag * nDiag];
00117 
00118   CoinFillN (matrix, nDiag * nDiag, 0.);
00119 
00120   for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00121 
00122     int 
00123       xind = row -> first -> Index (),
00124       irow = indexmap [xind];
00125 
00126     for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00127 
00128       int 
00129         yind = col -> first -> Index (),
00130         icol = indexmap [yind];
00131 
00132       double cell = col -> second * diam [irow] * diam [icol];
00133 
00134       matrix          [icol * nDiag + irow] = cell;
00135       if (irow != icol) 
00136         matrix        [irow * nDiag + icol] = cell;
00137     }
00138   }
00139 
00140   // compute value of matrix entry = q_ij * (u_i-l_i) * (u_j-l_j)
00141   // I (Stefan) do not understand the Lapack docu; it says it needs
00142   // only the lower triangular but it seem to need both parts to
00143   // work correct
00144 
00145   delete [] indexmap;
00146 
00147   // compute minimum and maximum eigenvalue of matrix
00148   double* eigval = new double [nDiag];
00149   int info;
00150 
00151 #ifdef DEBUG
00152   printf ("nDiag = %d\n", nDiag);
00153   for (int i=0; i<nDiag; i++) {
00154     for (int j=0; j<nDiag; j++)
00155       printf ("%6.2f ", matrix [i*nDiag + j]);
00156     printf ("\n");
00157   }
00158 #endif 
00159 
00160   Ipopt::IpLapackDsyev (true,   // compute eigenvector
00161                         nDiag,  // dimension
00162                         matrix, // matrix
00163                         nDiag,  // "leading dimension" (number of columns, I think)
00164                         eigval, // output vector to store eigenvalues
00165                         info);  // output status variable
00166 
00167   if (info != 0) {
00168     printf ("exprQuad::alphaConvexify, warning: problem computing eigenvalue, info=%d\n", info);
00169     return false;
00170     //TODO error handling
00171   }
00172 
00173   // clean eigenvector structure
00174   eigen_.erase (eigen_.begin (), eigen_.end ());
00175 
00176   for (int i=0; i<nDiag; i++) {
00177 
00178     std::pair <CouNumber, std::vector <std::pair <exprVar *, CouNumber> > > eigenCoord;
00179 
00180     eigenCoord. first = eigval [i];
00181 
00182     for (int j=0; j<nDiag; j++) {
00183 
00184       CouNumber elem = matrix [i * nDiag + j];
00185 
00186       if (fabs (elem) > COUENNE_EPS) 
00187         eigenCoord. second. push_back (std::pair <exprVar *, CouNumber> 
00188                                        (p -> Var (indices [j]), elem));
00189     }
00190 
00191     eigen_.push_back (eigenCoord);
00192   }
00193 
00194 #ifdef DEBUG
00195   for (std::vector <std::pair <CouNumber, 
00196          std::vector <std::pair <exprVar *, CouNumber> > > >::iterator i = eigen_.begin ();
00197        i != eigen_.end (); ++i) {
00198     printf (" [%g] -- ", i -> first);
00199     for (std::vector <std::pair <exprVar *, CouNumber> >::iterator j = i -> second. begin();
00200          j != i -> second. end (); ++j)
00201       printf ("(%d,%g) ", j -> first -> Index (), j -> second);
00202     printf ("\n");
00203   }
00204 #endif
00205 
00206   delete [] indices;
00207   delete [] matrix;
00208   delete [] diam;
00209   delete [] eigval;
00210 
00211   return true;
00212 }

Generated on Thu Sep 22 03:05:56 2011 by  doxygen 1.4.7