00001
00002
00003
00004
00005
00006
00007
00008
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
00022
00043 bool exprQuad::alphaConvexify (const CouenneProblem *p) {
00044
00045
00046 if (matrix_.size () == 0)
00047 return false;
00048
00049
00050
00051
00052 int k=0,
00053 nDiag = bounds_.size (),
00054 *indexmap = new int [p -> nVars ()],
00055 *indices = new int [nDiag];
00056
00057
00058 CoinFillN (indexmap, p -> nVars (), -1);
00059
00060
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
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
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
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
00141
00142
00143
00144
00145 delete [] indexmap;
00146
00147
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,
00161 nDiag,
00162 matrix,
00163 nDiag,
00164 eigval,
00165 info);
00166
00167 if (info != 0) {
00168 printf ("exprQuad::alphaConvexify, warning: problem computing eigenvalue, info=%d\n", info);
00169 return false;
00170
00171 }
00172
00173
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 }