/home/coin/SVN-release/OS-2.1.1/Couenne/src/disjunctive/disjCut.cpp

Go to the documentation of this file.
00001 /* $Id: disjCut.cpp 154 2009-06-16 18:52:53Z pbelotti $
00002  *
00003  * Name:    disjCut.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: generate one disjunctive cut based on a single disjunction
00006  *
00007  * (C) Carnegie-Mellon University, 2008. 
00008  * This file is licensed under the Common Public License (CPL)
00009  */
00010 
00011 #include "CoinTime.hpp"
00012 #include "OsiClpSolverInterface.hpp"
00013 #include "CouennePrecisions.hpp"
00014 #include "CouenneDisjCuts.hpp"
00015 
00016 #define COEFF_BOUNDS 1.e10
00017 
00018 #define MIN_NUM_COEFF 1.e-9
00019 #define MAX_NUM_COEFF 1.e+9
00020 #define MAX_NUM_RATIO 1.e+6
00021 
00022 
00023 // print content of sparse matrix
00024 void printMatrix (int nrows, int ncols, int nel, 
00025                   const int *start, const int *len, 
00026                   const int *ind, const double *el);
00027 
00028 // same with CoinPackedMatrix
00029 void printMatrix   (const CoinPackedMatrix *A);
00030 
00031 // same with si.GetMatrixByRow()
00032 void printLPMatrix (const OsiSolverInterface &si);
00033 
00034 // add columns specified by start/len/ind/el to matrix Astd
00035 void addSubMatr (int *start, int *len, int *ind, double *el, 
00036                  CoinPackedMatrix &Astd, CoinPackedVector &rstd, 
00037                  int &cur, int &curCol, int dispM, int dispVec, int nrows);
00038 
00039 
00041 int CouenneDisjCuts::generateDisjCuts (std::vector <std::pair <OsiCuts *, OsiCuts *> > &disjunctions, 
00042                                        OsiSolverInterface &si, 
00043                                        OsiCuts &cs, 
00044                                        const CglTreeInfo &info) const {
00045 
00046   // create CGLP with si+left and si+right, for each (left,right) in
00047   // the vector of disjunctions
00048   //
00049   // Here's the CGLP (row and column order as shown)
00050   //
00051   //        {n}          {1}    {m}    {m}   {mL} {mR}
00052   //
00053   // max    alpha xbar - beta                                        --- maximize so can copy xbar
00054   // s.t.  -alpha              + u A       + u'C           =  0      --- n rows
00055   //       -alpha                    + v A       + v'D     =  0      --- n
00056   //                    -beta  + u b       + u'c          <=  0      --- 1
00057   //                    -beta        + v b       + v'd    <=  0      --- 1
00058   //                           |(u,    v,    u',   v')|_1  =  1      --- normalized multipliers
00059   //
00060   //                             u,    v,    u',   v'     >=  0      --- non-negativity 
00061   //
00062   //
00063   //  And here are the submatrices (M' is M transposed)
00064   //
00065   //     First        Second  Third  Fourth Fifth Sixth   --- Columns
00066   //
00067   //       xbar          -1       0     0     0     0
00068   //      ---------------------------------------------
00069   //       -I_n           .       A'    .     C'    .     = 0
00070   //       -I_n           .       .     A'    .     D'    = 0
00071   //        .            -1       b'    .     c'    .    <= 0
00072   //        .            -1       .     b'    .     d'   <= 0
00073   //        .             .       e     e     e     e     = 1
00074   //
00075   //
00076   // build a different A such that
00077   // 
00078   // - only active rows (resp. columns) of A are included if active_rows_
00079   //   (resp. active_columns_) are set
00080   // - equality constraints are duplicated in a <= and a >= constraint
00081   // - >= constraints are inverted
00082   //
00083   // Also, add disjunctive cut to CGLP for use with next disjunction
00084 
00085   // put matrix from base problem in canonical form //////////////////////////////
00086   CoinPackedMatrix Astd;
00087   CoinPackedVector rstd;
00088   OsiSI2MatrVec (Astd,  rstd,  si); 
00089 
00090   int
00091     n   = si.   getNumCols (),      //mC   = 2*n + 3,
00092     m   = Astd. getMajorDim (),     nC   = 1 + n + 2 * m,
00093     nnz = Astd. getNumElements (),  nnzC = 2 * (n + 1 + nnz + 2*m);
00094 
00095   if (jnlst_ -> ProduceOutput (J_DETAILED, J_DISJCUTS))
00096     printf ("canonical form has %d cols, %d rows, %d nonzeros --> cglp has %d,%d,%d\n", 
00097             n, m, nnz, nC, 2*n + 3, nnzC);
00098 
00099   double 
00100     *elements = new double [nnzC];
00101 
00102   int 
00103     *indices = new int [nnzC],
00104     *start   = new int [nC + 1],
00105     *length  = new int [nC],
00106     cur      = 0,
00107     curCol   = 0;
00108 
00109   // first column: two identity matrices
00110   for (int i=0, i2 = n; i<n;) {
00111     start   [curCol]   = cur;
00112     length  [curCol++] = 2;
00113     indices [cur] =    i++; elements [cur++] = -1.;
00114     indices [cur] =   i2++; elements [cur++] = -1.;
00115   }
00116 
00117   // second column: two "-1" at position 2n and 2n+1
00118   start   [curCol]   = cur;
00119   length  [curCol++] = 2;
00120   indices [cur] = 2*n;   elements [cur++] = -1.;
00121   indices [cur] = 2*n+1; elements [cur++] = -1.;
00122 
00123   // third...
00124   addSubMatr (start + curCol, length + curCol, 
00125               indices + cur, elements + cur, 
00126               Astd, rstd,
00127               cur, curCol, 
00128               0, 2*n,   2*n+2);
00129 
00130   if (jnlst_ -> ProduceOutput (J_MATRIX, J_DISJCUTS)) {
00131     printf ("with third column\n");
00132     printMatrix (curCol, 2*n+3, cur, start, length, indices, elements);
00133   }
00134 
00135   // ... and fourth column: get single rows from Astd
00136   addSubMatr (start + curCol, length + curCol, 
00137               indices + cur, elements + cur, 
00138               Astd, rstd, 
00139               cur, curCol, 
00140               n, 2*n+1, 2*n+2);
00141 
00142   if (jnlst_ -> ProduceOutput (J_MATRIX, J_DISJCUTS)) {
00143     printf ("with 4th column\n");
00144     printMatrix (curCol, 2*n+3, cur, start, length, indices, elements);
00145   }
00146 
00147   CoinPackedMatrix *baseA = new CoinPackedMatrix;
00148 
00149   baseA -> assignMatrix (true,     // column ordered
00150                          2*n+3,    // minor dimension
00151                          curCol,   // major dimension
00152                          cur,      // number of elements
00153                          elements, // elements
00154                          indices,  // indices
00155                          start,    // starting positions
00156                          length);  // length
00157 
00158   //printf ("should be copy of above\n");
00159   //printMatrix (baseA);
00160 
00161   OsiClpSolverInterface cglp;
00162 
00163   cglp. messageHandler () -> setLogLevel (0);
00164 
00165   int 
00166     N = baseA -> getMajorDim (),        // # cols in base problem
00167     M = baseA -> getMinorDim ();        // # rows in base problem
00168 
00169   assert (M == 2 * n + 3);
00170 
00171   // vectors of the problem
00172   double
00173     *collb  = new double [N], // variable lower bounds
00174     *colub  = new double [N], // variable upper bounds
00175     *obj    = new double [N], // objective coefficients
00176     *rowrhs = new double [M], // right hand sides (all zero except the last, 1)
00177     *rowrng = new double [M]; // row range (empty)
00178 
00179   // bounds
00180   CoinFillN (collb,       n+1,       -COEFF_BOUNDS);
00181   CoinFillN (collb + n+1, N - (n+1),  0.);
00182   CoinFillN (colub,       n+1,        COEFF_BOUNDS);
00183   CoinFillN (colub + n+1, N - (n+1),  1.);
00184 
00185   // objective coefficients
00186   CoinCopyN (si.getColSolution (), n, obj);
00187   obj [n] = -1.;
00188   CoinFillN (obj + (n+1), N-(n+1),    0.);
00189 
00190   // rhs
00191   CoinFillN (rowrhs,      M-1,        0.);
00192   rowrhs [M-1] = 1.;
00193 
00194   // rhs range
00195   CoinFillN (rowrng,      M,          COIN_DBL_MAX);
00196 
00197   // signs of the inequalities
00198   char *rowsen = new char [M];
00199   CoinFillN (rowsen, M, 'E');
00200   rowsen [M-3] = rowsen [M-2] = 'L';
00201 
00202   cglp.assignProblem (baseA,   // matrix
00203                       collb,   // lower bounds 
00204                       colub,   // upper bounds
00205                       obj,     // obj coefficients
00206                       rowsen,  // row sense
00207                       rowrhs,  // right hand sides
00208                       rowrng); // no row range
00209 
00210   // this is a maximization problem
00211   cglp. setObjSense (-1);
00212 
00214 
00215   // generate and solve one CGLP for each disjunction
00216 
00217   bool first = true;
00218 
00219   for (std::vector <std::pair <OsiCuts *, OsiCuts *> >::iterator disjI = disjunctions.begin ();
00220        (disjI != disjunctions.end ()) && (CoinCpuTime () < cpuTime_); ++disjI) {
00221 
00222     OsiCuts
00223       *left  = disjI -> first,
00224       *right = disjI -> second;
00225 
00226     int 
00227       ncolLeft  = OsiCuts2MatrVec (&cglp,  left, 0, 2*n),
00228       ncolRight = OsiCuts2MatrVec (&cglp, right, n, 2*n+1);    
00229 
00230     /*char filename [30];
00231     static int iter = 0;
00232     sprintf (filename, "cglp-%04d-%04d-%04d", info.level, iter++, info.pass);
00233     cglp.writeLp (filename);*/
00234 
00235     if (jnlst_ -> ProduceOutput (J_MOREMATRIX, J_DISJCUTS)) {
00236       printf ("current CGLP:\n");
00237       printLPMatrix (cglp);
00238     }
00239 
00240     if (first) {cglp.initialSolve (); first = false;}
00241     else        cglp.resolve (); // segfault in ex1244
00242 
00243     if (cglp. isProvenOptimal () && (cglp.getObjValue () > COUENNE_EPS)) {
00244 
00245       const double *AlphaBeta = cglp. getColSolution ();
00246 
00247       int    *colInd = NULL, nnzCut = 0;
00248       double *colCoe = NULL;
00249 
00250       // count nonzero entries, compute ratio max/min coefficient
00251       double mincoeff = COIN_DBL_MAX, maxcoeff = 0.;
00252 
00253       for (register int i=n+1; i--;) {
00254         double value = fabs (AlphaBeta [i]);
00255         if (value == 0.) continue;
00256         if (value > maxcoeff) maxcoeff = value;
00257         if (value < mincoeff) mincoeff = value;
00258         if ((maxcoeff            > MAX_NUM_COEFF) ||
00259             (maxcoeff            < MIN_NUM_COEFF) ||
00260             (maxcoeff / mincoeff > MAX_NUM_RATIO)) 
00261           break;
00262         nnzCut++;
00263       }
00264 
00265       if (nnzCut &&
00266           (maxcoeff            < MAX_NUM_COEFF) &&
00267           (maxcoeff            > MIN_NUM_COEFF) &&
00268           (maxcoeff / mincoeff < MAX_NUM_RATIO)) {
00269 
00270         // cut data
00271         double *nzcoeff = new double [nnzCut];
00272         int    *indices = new int    [nnzCut];
00273 
00274         // fill in indices and coefficient
00275         for (int i = nnzCut = 0; i<n; i++)
00276           if (fabs (AlphaBeta [i]) > MIN_NUM_COEFF) {
00277             indices [nnzCut]   = i;
00278             nzcoeff [nnzCut++] = AlphaBeta [i];
00279           }
00280 
00281         OsiRowCut *cut = new OsiRowCut;
00282         cut -> setRow (nnzCut, indices, nzcoeff);
00283         cut -> setUb  (AlphaBeta [n]);
00284 
00285         /*if (1) {
00286 
00287           printf ("---- RESOLVING\n");
00288           si.applyRowCuts (1, cut);
00289           si.writeLp ("added");
00290           si.resolve ();
00291           printf ("---- RESOLVED\n");
00292 
00293           double *obj    = new double [N]; // objective coefficients
00294 
00295           // objective coefficients
00296           CoinCopyN (si.getColSolution (), n, obj);
00297           obj [n] = -1.;
00298           CoinFillN (obj + (n+1), N-(n+1),    0.);
00299 
00300           cglp.setObjective (obj);
00301           }*/
00302  
00303         // add it to CGLP
00304         if (addPreviousCut_) {
00305 
00306           colInd = new int    [2 * (nnzCut + 2)];
00307           colCoe = new double [2 * (nnzCut + 2)];
00308 
00309           // first column
00310           CoinCopyN    (nzcoeff, nnzCut, colCoe);
00311           CoinCopyN    (indices, nnzCut, colInd); 
00312           colInd [nnzCut]       = 2*n;   colCoe [nnzCut]   = AlphaBeta [n];
00313           colInd [nnzCut+1]     = 2*n+2; colCoe [nnzCut+1] = 1; // entry in norm constraint
00314 
00315           // second column
00316           CoinCopyN    (nzcoeff, nnzCut, colCoe + nnzCut + 2);
00317           CoinCopyDisp (indices, nnzCut, colInd + nnzCut + 2, n); 
00318           colInd [2*nnzCut + 2] = 2*n+1; colCoe [2*nnzCut+2] = AlphaBeta [n];
00319           colInd [2*nnzCut + 3] = 2*n+2; colCoe [2*nnzCut+3] = 1.; // entry in norm constraint
00320 
00321           // extra vectors
00322           double lb  [2] = {0., 0.};
00323           double ub  [2] = {1., 1.};
00324           double obj [2] = {0., 0.};
00325 
00326           int start [3];
00327           *start = 0;
00328           start [2] = 2 * (start [1] = nnzCut + 2);
00329 
00330           cglp. addCols (2,        // const int numcols, 
00331                          start,    // const int* columnStarts,
00332                          colInd,   // const int* rows, 
00333                          colCoe,   // const double* elements,
00334                          lb,       // const double* collb, 
00335                          ub,       // const double* colub,   
00336                          obj);     // const double* obj
00337 
00338           delete [] colCoe;
00339           delete [] colInd;
00340         }
00341 
00342         delete [] nzcoeff;
00343         delete [] indices;
00344 
00345         if (jnlst_ -> ProduceOutput (J_DETAILED, J_DISJCUTS)) {
00346           printf ("====== disjunctive cut: "); 
00347           cut -> print ();
00348         }
00349 
00350         // add cut to cs
00351         cs. insert (cut);
00352       }
00353     }
00354 
00355     // remove last ncolLeft + ncolRight columns from cglp
00356     int *delIndices = new int [ncolLeft + ncolRight];
00357     for (register int nc = ncolLeft + ncolRight, j = N + nc; nc--;)
00358       *delIndices++ = --j;
00359     delIndices -= (ncolLeft + ncolRight);
00360     cglp.deleteCols (ncolLeft + ncolRight, delIndices);
00361     delete [] delIndices;
00362   }
00363 
00364   return COUENNE_FEASIBLE;
00365 }

Generated on Mon May 3 03:05:19 2010 by  doxygen 1.4.7