00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <quadratic_cuts_check.hpp>
00011 #include <stdio.h>
00012 #include <dsyevx_wrapper.hpp>
00013 #include <tracer.hpp>
00014
00015 QuadraticCuts::QuadraticCuts(int n, const double *initial_sol, Tracer *tracer) {
00016 n_ = n;
00017 L = new double[n*n];
00018 tracer_ = tracer;
00019
00020 sol = new double[(n*(n+3))/2];
00021 previous_sol = new double[(n*(n+3))/2];
00022 for (int i=0;i<(n*(n+3))/2;i++) {
00023 sol[i] = 0.0;
00024 previous_sol[i] = 0.0;
00025 }
00026 eigenvectors = new double*[n];
00027 for (int i=0;i<n;i++)
00028 eigenvectors[i] = new double[n];
00029
00030 #ifdef RECOMPUTE_XTILDE_EV_FROM_SCRATCH
00031 Xtilde = new double[(n+1)*(n+1)];
00032 eigenvectors_Xtilde = new double*[n+1];
00033 for (int i=0;i<n+1;i++)
00034 eigenvectors_Xtilde[i] = new double[n+1];
00035 #endif
00036 updateSolution(initial_sol);
00037
00038 checkQuadraticDiagonalCutsOnCurrentSolution();
00039
00040 computeEigenvectorsFromCurrentSolution();
00041 }
00042
00043 QuadraticCuts::~QuadraticCuts() {
00044 delete [] L;
00045 delete [] sol;
00046 delete [] previous_sol;
00047 for (int i=0;i<n_;i++)
00048 delete [] eigenvectors[i];
00049 delete [] eigenvectors;
00050
00051 #ifdef RECOMPUTE_XTILDE_EV_FROM_SCRATCH
00052 delete [] Xtilde;
00053 for (int i=0;i<n_+1;i++)
00054 delete [] eigenvectors_Xtilde[i];
00055 delete [] eigenvectors_Xtilde;
00056 #endif
00057 }
00058
00059 void QuadraticCuts::refresh(const double *current_sol) {
00060 updateSolution(current_sol);
00061
00062 checkQuadraticDiagonalCutsOnCurrentSolution();
00063 checkPreviousQuadraticEVCutsOnCurrentSolution();
00064
00065 computeEigenvectorsFromCurrentSolution();
00066 }
00067
00068 void QuadraticCuts::updateSolution(const double *current_sol){
00069
00070
00071 double *X = new double[n_*n_];
00072 double *xxT = new double[n_*n_];
00073
00074 for (int i=0;i<(n_*(n_+3))/2;i++)
00075 previous_sol[i] = sol[i];
00076
00077 for (int i=0;i<(n_*(n_+3))/2;i++)
00078 sol[i] = current_sol[i];
00079
00080 for (int i=0;i<n_;i++) {
00081 for (int j=i;j<n_;j++) {
00082 X [i*n_ + j] = current_sol[indexQ(i,j,n_)];
00083 X [j*n_ + i] = current_sol[indexQ(i,j,n_)];
00084 xxT [i*n_ + j] = current_sol[i]*current_sol[j];
00085 xxT [j*n_ + i] = current_sol[i]*current_sol[j];
00086 }
00087 }
00088 for (int i=0;i<n_;i++) {
00089 for (int j=0;j<n_;j++) {
00090 L[i*n_ + j] = X[i*n_ + j] - xxT[i*n_ + j];
00091 }
00092 }
00093
00094 #ifdef QUADRATIC_CUTS_DEBUG
00095
00096
00097
00098
00099 printf("\n");
00100 printf("x :\t");
00101 for (int i=0;i<n_;i++)
00102 printf("%8.5f\t",current_sol[i]);
00103 printf("\n");
00104 printf("X :\t");
00105 for (int i=0;i<n_;i++) {
00106 for (int j=0;j<n_;j++)
00107 printf("%8.5f\t",X [i*n_ + j]);
00108 printf("\n\t");
00109 }
00110 printf("\n");
00111 printf("xxT :\t");
00112 for (int i=0;i<n_;i++) {
00113 for (int j=0;j<n_;j++)
00114 printf("%8.5f\t",xxT [i*n_ + j]);
00115 printf("\n\t");
00116 }
00117 printf("\n");
00118 printf("X-xxT :\t");
00119 for (int i=0;i<n_;i++) {
00120 for (int j=0;j<n_;j++)
00121 printf("%8.5f\t",L [i*n_ + j]);
00122 printf("\n\t");
00123 }
00124 printf("\n");
00125 #endif
00126
00127 delete [] X;
00128 delete [] xxT;
00129
00130 #ifdef RECOMPUTE_XTILDE_EV_FROM_SCRATCH
00131 int np=n_+1;
00132 for (int i=0;i<np*np;i++)
00133 Xtilde[i] = 0;
00134 Xtilde[0] = 1;
00135 for (int i=0;i<n_;i++) {
00136
00137 Xtilde[i+1] = current_sol[i];
00138 Xtilde[(i+1)*np] = current_sol[i];
00139 for (int j=i;j<n_;j++) {
00140 Xtilde[(i+1)*np+(j+1)] = current_sol[indexQ(i,j,n_)];
00141 Xtilde[(j+1)*np+(i+1)] = current_sol[indexQ(i,j,n_)];
00142 }
00143 }
00144 #ifdef QUADRATIC_CUTS_DEBUG
00145 printf("Xtilde=\n");
00146 for (int i=0;i<np;i++) {
00147 for (int j=0;j<np;j++)
00148 printf("%.5f ",Xtilde[i*np + j]);
00149 printf("\n");
00150 }
00151 #endif // QUADRATIC_CUTS_DEBUG
00152 #endif // RECOMPUTE_XTILDE_EV_FROM_SCRATCH
00153 }
00154
00155
00156
00157 void QuadraticCuts::computeEigenvectorsFromCurrentSolution() {
00158 double *z = new double[n_ * n_];
00159 double *w = new double[n_];
00160 int m;
00161
00162 dsyevx_wrapper_only_negative (n_, L, m, w, z,tracer_);
00163
00164 card_ev = 0;
00165 for (int i=0;i<m;i++) {
00166 if (w[i] < 0) {
00167 for (int j=0;j<n_;j++)
00168 eigenvectors[card_ev][j] = z[i*n_ + j];
00169 card_ev++;
00170 } else
00171 break;
00172 }
00173 #ifdef QUADRATIC_CUTS_DEBUG
00174 printf("eigenvectors of X - xx^T:\n");
00175 for (int i=0;i<card_ev;i++) {
00176 printf("[%d] ev=%.5f : ",i,w[i]);
00177 for (int j=0;j<n_;j++)
00178 printf("%.5f ",eigenvectors[i][j]);
00179 printf("\n");
00180 }
00181 printf("\n");
00182 #endif
00183 delete [] z;
00184 delete [] w;
00185
00186 #ifdef RECOMPUTE_XTILDE_EV_FROM_SCRATCH
00187 int np = n_+1;
00188 z = new double[np * np];
00189 w = new double[np];
00190
00191 dsyevx_full_wrapper (np, Xtilde, m, w, z, tracer_);
00192
00193 card_ev_Xtilde = 0;
00194 for (int i=0;i<m;i++) {
00195 if (w[i] < 0) {
00196 for (int j=0;j<np;j++)
00197 eigenvectors_Xtilde[card_ev_Xtilde][j] = z[i*np + j];
00198 card_ev_Xtilde++;
00199 } else
00200 break;
00201 }
00202
00203 #ifdef QUADRATIC_CUTS_DEBUG
00204 printf("eigenvectorsXtilde:\n");
00205 for (int i=0;i<card_ev_Xtilde;i++) {
00206 printf("[%d] ev=%.5f : ",i,w[i]);
00207 for (int j=0;j<np;j++)
00208 printf("%.5f ",eigenvectors_Xtilde[i][j]);
00209 printf("\n");
00210 }
00211 #endif
00212 delete [] z;
00213 delete [] w;
00214 #endif
00215 }
00216
00217 void QuadraticCuts::checkQuadraticDiagonalCutsOnCurrentSolution() {
00218 for (int i=0;i<n_;i++) {
00219 double value = sol[indexQ(i,i,n_)] - sol[i]*sol[i];
00220 if (value < - QUADRATIC_CUTS_CHECK_TOLERANCE)
00221 printf("quadratic cut X_%d,%d - (x_%d)^2 >= 0 violated (lhs=%.5f)\n",i,i,i,value);
00222 }
00223 }
00224
00225 void QuadraticCuts::checkPreviousQuadraticEVCutsOnCurrentSolution() {
00226 for(int i=0;i<card_ev;i++) {
00227 double vTx = 0.0;
00228 for (int j=0;j<n_;j++) {
00229 vTx += sol[j] * eigenvectors[i][j];
00230 }
00231 double XvvT = 0.0;
00232 for (int j=0;j<n_;j++) {
00233 for (int k=j+1;k<n_;k++)
00234 XvvT += 2*eigenvectors[i][j]*eigenvectors[i][k]*sol[indexQ(j,k,n_)];
00235 XvvT += eigenvectors[i][j]*eigenvectors[i][j]*sol[indexQ(j,j,n_)];
00236 }
00237 double lhs = vTx*vTx - XvvT;
00238
00239 #ifdef QUADRATIC_CUTS_DEBUG
00240 printf("ev[%d] v:\t",i);
00241 for (int k=0;k<n_;k++) {
00242 printf("%8.5f\t",eigenvectors[i][k]);
00243 }
00244 printf("\n");
00245 printf("ev[%d]vvT:\t",i);
00246 for (int k=0;k<n_;k++) {
00247 for (int j=0;j<n_;j++)
00248 printf("%8.5f\t",eigenvectors[i][k]*eigenvectors[i][j]);
00249 printf("\n\t\t");
00250 }
00251 printf("\n");
00252 printf("curr_ev_idx=%d vTx=%.5f vTx^2=%.5f XvvT=%.5f\n",i,vTx,vTx*vTx,XvvT);
00253 printf("\n");
00254 #endif
00255
00256 if (lhs > QUADRATIC_CUTS_CHECK_TOLERANCE) {
00257 printf("quadratic cut from %d-th prev ev (v^Tx)^2 - X.vv^T <=0)violated (lhs=%.5f)\n",i,lhs);
00258 }
00259 }
00260
00261
00262 #ifdef RECOMPUTE_XTILDE_EV_FROM_SCRATCH
00263 int np = n_+1;
00264 double **wwT = new double*[np];
00265 double **myXtilde = new double*[np];
00266 for (int i=0;i<np;i++) {
00267 wwT[i] = new double[np];
00268 myXtilde[i] = new double[np];
00269 }
00270
00271 myXtilde[0][0] = 1.0;
00272 for (int i=0;i<n_;i++) {
00273 myXtilde[0][i+1] = sol[i];
00274 myXtilde[i+1][0] = sol[i];
00275 for (int j=i;j<n_;j++) {
00276 myXtilde[i+1][j+1] = sol[indexQ(i,j,n_)];
00277 myXtilde[j+1][i+1] = sol[indexQ(i,j,n_)];
00278 }
00279 }
00280
00281 #ifdef QUADRATIC_CUTS_DEBUG
00282 printf("myXtilde:\n");
00283 for(int i=0;i<np;i++) {
00284 for (int j=0;j<np;j++)
00285 printf("%.2f ",myXtilde[i][j]);
00286 printf("\n");
00287 }
00288 #endif
00289
00290 for(int i=0;i<card_ev_Xtilde;i++) {
00291 for (int k=0;k<np;k++) {
00292 for (int j=0;j<np;j++) {
00293 wwT[k][j] = eigenvectors_Xtilde[i][k] * eigenvectors_Xtilde[i][j];
00294 }
00295 }
00296 double value = 0.0;
00297 for (int k=0;k<np;k++) {
00298 for (int j=0;j<np;j++) {
00299 value+=myXtilde[k][j]*wwT[k][j];
00300 }
00301 }
00302 if (value < -1e-8)
00303 printf("Original Xtilde ev[%d] cut violated (this should not happen!) = %.8f\n",i,value);
00304 }
00305
00306 for (int i=0;i<np;i++) {
00307 delete [] wwT[i];
00308 delete [] myXtilde[i];
00309 }
00310 delete [] wwT;
00311 #endif // RECOMPUTE_XTILDE_EV_FROM_SCRATCH
00312 }
00313
00314
00315
00316