/home/coin/SVN-release/OS-2.4.2/Couenne/src/cut/sdpcuts/orthocut.cpp

Go to the documentation of this file.
00001 /* $Id: orthocut.cpp 508 2011-02-15 21:52:44Z pbelotti $
00002  *
00003  * Name:    orthocut.cpp
00004  * Author:  Andrea Qualizza
00005  * Purpose: 
00006  *
00007  * This file is licensed under the Eclipse Public License (EPL)
00008  */
00009 
00010 #include <orthocut.hpp>
00011 #include <CglCutGenerator.hpp>
00012 #include <OsiSolverInterface.hpp>
00013 #include <dsyevx_wrapper.hpp>
00014 #include <tracer.hpp>
00015 #include <misc_util.hpp>
00016 
00017 
00018 void orthoCutGen(const double *sol, int n, OsiCuts &cs, double *z, double *w, int m, Tracer *tracer) {
00019         // Y = / 1 x \
00020         //     \xT X /
00021         // D = diagonal matrix of eigenvalues \lambda_i of Y
00022         // P = orthogonal matrix where columns are eigenvectors v_i of Y
00023         // Y D = Y P by definition of eigenvalue/eigenvectors
00024         // so Y = P D P^{-1} = P D P^T since P is orthogonal
00025         // let
00026         // Pn = matrix where columns are eigenvectors of v_i of Y with \lambda_i < 0, other colums are 0
00027         // Pp = matrix where columns are eigenvectors of v_i of Y with \lambda_i >= 0, other colums are 0
00028         // Y = Pn D Pn^T + Pp D Pp^T
00029         // we want to find the projection of Y on the SDP cone, which is Pp D Pp^T = Y - Pn D Pn^T
00030 
00031         Timer orthocut_timer;
00032         orthocut_timer.start();
00033         int origcuts = cs.sizeCuts();
00034 
00035         int np = n+1;
00036         int sol_card = n*(n+3)/2;
00037         
00038         double **Pn = new double*[np];
00039         for(int i=0;i<np;i++)
00040                 Pn[i] = new double[np];
00041         double **PpDPpT = new double*[np];
00042         for(int i=0;i<np;i++)
00043                 PpDPpT[i] = new double[np];
00044         double **PnDPnT = new double*[np];
00045         for(int i=0;i<np;i++)
00046                 PnDPnT[i] = new double[np];
00047         double **Amat = new double*[np];
00048         for(int i=0;i<np;i++)
00049                 Amat[i] = new double[np];
00050         
00051         // populating Amat
00052         Amat[0][0]=1;
00053         for(int i=0;i<n;i++) {
00054                 Amat[0][i+1]            = sol[i];
00055                 Amat[i+1][0]            = sol[i];
00056                 Amat[i+1][i+1]          = sol[indexQ(i,i,n)];
00057                 for(int j=i+1;j<n;j++){
00058                         Amat[i+1][j+1]  = sol[indexQ(i,j,n)];
00059                         Amat[j+1][i+1]  = sol[indexQ(i,j,n)];
00060                 }
00061         }
00062 
00063         // computing Pn
00064         for(int i=0;i<np;i++)
00065                 for(int j=0;j<np;j++)
00066                         Pn[i][j] = 0.0;
00067         for(int i=0;i<np;i++) {
00068                 if ((i<m) && (w[i] < 0)) {
00069                         double *zbase = z + i * np;
00070                         for(int j=0;j<np;j++)
00071                                 Pn[j][i] = zbase[j];
00072                 } else
00073                         break;
00074         }
00075         
00076         // computing PpDPpT
00077         for (int i=0;i<np;i++) {
00078                 for (int j=0;j<np;j++) {
00079                         PpDPpT[i][j] = Amat[i][j];
00080                         PnDPnT[i][j] = 0.0;
00081                         for (int k=0;k<np;k++) {
00082                                 if ((k<m) && (w[k] < 0)) {
00083                                         PpDPpT[i][j] -= w[k] * Pn[i][k] * Pn[j][k];
00084                                         PnDPnT[i][j] += w[k] * Pn[i][k] * Pn[j][k];
00085                                 }
00086                         }
00087                 }
00088         }
00089 
00090         double *point_on_sdp_cone = new double[sol_card];
00091         for(int i=0;i<n;i++) {
00092                 point_on_sdp_cone[i] = PpDPpT[0][i+1];
00093                 for (int j=i;j<n;j++)
00094                         point_on_sdp_cone[indexQ(i,j,n)] = PpDPpT[i+1][j+1];
00095         }
00096         double point_on_sdp_cone00 = PpDPpT[0][0];
00097 
00098         double *PnDPnTvector = new double[sol_card];
00099         for (int i=0;i<n;i++) {
00100                 PnDPnTvector[i] = PnDPnT[0][i+1];
00101                 for (int j=i;j<n;j++)
00102                         PnDPnTvector[indexQ(i,j,n)] = PnDPnT[i+1][j+1];
00103         }
00104 
00105 
00106 
00107 
00108         double *tangent_line_coeff = new double[sol_card];
00109 
00110         for(int i=0;i<n;i++) {
00111                 tangent_line_coeff[i] = -2*PnDPnTvector[i];
00112                 tangent_line_coeff[indexQ(i,i,n)] = -PnDPnTvector[indexQ(i,i,n)];
00113                 for(int j=i+1;j<n;j++)
00114                         tangent_line_coeff[indexQ(i,j,n)] = -2*PnDPnTvector[indexQ(i,j,n)];
00115         }
00116 
00117         //I want that the line passes through point_on_sdp_cone
00118         double rhs = PnDPnT[0][0] * point_on_sdp_cone00;
00119         for(int i=0;i<sol_card;i++)
00120                 rhs += point_on_sdp_cone[i] * tangent_line_coeff[i];
00121         
00122         OsiRowCut *cut = new OsiRowCut;
00123         double *coeff = new double [sol_card];
00124         int *ind   = new int [sol_card];
00125         int nz = 0;
00126         for(int i=0;i<sol_card;i++) {
00127                 if (tangent_line_coeff[i]) {
00128                         coeff[nz] = tangent_line_coeff[i];
00129                         ind[nz] = i;
00130                         nz++;
00131                 }
00132         }
00133         cut -> setRow ( nz, ind, coeff );
00134         cut -> setLb (rhs);
00135 //cut->print();
00136 
00137 #ifdef TRACE_ORTHOCUT
00138         printf("orthocut violation-->%.5f\n",cut -> violated(sol));
00139 #endif
00140         cs.insert (cut);
00141 
00142         
00143 
00144         delete [] PnDPnTvector;
00145         for(int i=0;i<np;i++)
00146                 delete [] Pn[i];
00147         delete [] Pn;
00148         for(int i=0;i<np;i++)
00149                 delete [] PpDPpT[i];
00150         delete [] PpDPpT;
00151         for(int i=0;i<np;i++)
00152                 delete [] PnDPnT[i];
00153         delete [] PnDPnT;
00154         for(int i=0;i<np;i++)
00155                 delete [] Amat[i];
00156         delete [] Amat;
00157         delete [] point_on_sdp_cone;
00158         delete [] tangent_line_coeff;
00159         delete [] coeff;
00160         delete [] ind;
00161 
00162 
00163         tracer->setOrthocutTime(orthocut_timer.time());
00164         tracer->setOrthocutTotalCuts(cs.sizeCuts() - origcuts);
00165 }
00166 
00167 

Generated on Wed Nov 30 03:04:01 2011 by  doxygen 1.4.7