Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

CglKnapsackCover.cpp

00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 #if defined(_MSC_VER)
00004 // Turn off compiler warning about long names
00005 #  pragma warning(disable:4786)
00006 #endif
00007 #include <cstdlib>
00008 #include <cstdio>
00009 #include <cmath>
00010 #include <cassert>
00011 #include <cfloat>
00012 #include <iostream>
00013 
00014 #include "CoinHelperFunctions.hpp"
00015 #include "CglKnapsackCover.hpp"
00016 #include "CoinPackedVector.hpp"
00017 #include "CoinSort.hpp"
00018 #include "CoinPackedMatrix.hpp"
00019 #include "OsiRowCutDebugger.hpp"
00020 //#define PRINT_DEBUG
00021 //#define CGL_DEBUG
00022 //-----------------------------------------------------------------------------
00023 // Generate knapsack cover cuts
00024 //------------------------------------------------------------------- 
00025 void CglKnapsackCover::generateCuts(const OsiSolverInterface & si, 
00026                                                 OsiCuts & cs ) const
00027 {
00028   // Get basic problem information
00029   int nRows=si.getNumRows(); 
00030   int nCols=si.getNumCols(); 
00031 
00032   // Create working space for "canonical" knapsack inequality
00033   // - krow will contain the coefficients and indices of the 
00034   // (potentially complemented) variables in the knapsack inequality.
00035   // - b is the rhs of knapsack inequality.
00036   // - complement[i] is 1 if the index i in krow refers to the complement
00037   // of the variable, and 0 otherwise. 
00038   CoinPackedVector krow; 
00039   double b=0.0;
00040   int * complement= new int[nCols];
00041     
00042   // Create a local copy of the column solution (colsol), call it xstar, and
00043   // inititalize it. 
00044   // Assumes the lp-relaxation has been solved, and the solver interface
00045   // has a meaningful colsol.
00046   double * xstar= new double[nCols]; 
00047 
00048   // To allow for vub knapsacks
00049   int * thisColumnIndex = new int [nCols];
00050   double * thisElement = new double[nCols];
00051   int * back = new int[nCols];
00052   
00053   const double *colsol = si.getColSolution(); 
00054   int k; 
00055   // For each row point to vub variable
00056   // -1 if no vub
00057   // -2 if can skip row for knapsacks
00058 
00059   int * vub = new int [nRows];
00060 
00061   // For each column point to vub row
00062   int * vubRow = new int [nCols];
00063   double * vubValue = new double [nRows];
00064 
00065   // Take out all fixed
00066   double * effectiveUpper = new double [nRows];
00067   double * effectiveLower = new double [nRows];
00068   const double * colUpper = si.getColUpper();
00069   const double * colLower = si.getColLower();
00070   for (k=0; k<nCols; k++){
00071     back[k]=-1;
00072     xstar[k]=colsol[k];
00073     complement[k]=0;
00074     vubRow[k]=-1;
00075     if (si.isBinary(k)) {
00076       if (si.isFreeBinary(k)) {
00077         vubRow[k]=-2;
00078       } else {
00079         vubRow[k]=-10;
00080       }
00081     } else if (colUpper[k]==colLower[k]) {
00082       vubRow[k]=-10; // fixed
00083     }
00084   }
00085 
00086   int rowIndex;
00087   int numberVub=0;
00088 
00089   const CoinPackedMatrix * matrixByRow = si.getMatrixByRow();
00090   const double * elementByRow = matrixByRow->getElements();
00091   const int * column = matrixByRow->getIndices();
00092   const int * rowStart = matrixByRow->getVectorStarts();
00093   const int * rowLength = matrixByRow->getVectorLengths();
00094   const double * rowUpper = si.getRowUpper();
00095   const double * rowLower = si.getRowLower();
00096 
00097   // Scan all rows looking for possibles
00098 
00099   for (rowIndex=0;rowIndex<nRows;rowIndex++) {
00100     int start = rowStart[rowIndex];
00101     int end = start + rowLength[rowIndex];
00102     double upRhs = rowUpper[rowIndex]; 
00103     double loRhs = rowLower[rowIndex]; 
00104     int numberContinuous=0;
00105     int numberBinary=0;
00106     int iCont=-1;
00107     double sum = 0.0;
00108     double valueContinuous=0.0;
00109     double valueBinary=0.0;
00110     int iBinary=-1;
00111     int j;
00112     for (j=start;j<end;j++) {
00113       int iColumn=column[j];
00114       if (colUpper[iColumn]>colLower[iColumn]) {
00115         sum += colsol[iColumn]*elementByRow[j];
00116         if (vubRow[iColumn]==-2) {
00117           // binary
00118           numberBinary++;
00119           valueBinary=elementByRow[j];
00120           iBinary=iColumn;
00121         } else if (vubRow[iColumn]==-1) {
00122           // only use if not at bound
00123           if (colsol[iColumn]<colUpper[iColumn]-1.0e-6&&
00124               colsol[iColumn]>colLower[iColumn]+1.0e-6) {
00125             // possible
00126             iCont=iColumn;
00127             numberContinuous++;
00128             valueContinuous=elementByRow[j];
00129           } else {
00130             // ** needs more thought
00131             numberContinuous ++;
00132             iCont=-1;
00133           }
00134         } else {
00135           // ** needs more thought
00136           numberContinuous ++;
00137           iCont=-1;
00138           if (colsol[iColumn]<colUpper[iColumn]-1.0e-6&&
00139               colsol[iColumn]>colLower[iColumn]+1.0e-6) {
00140             // already assigned
00141             numberContinuous ++;
00142             iCont=-1;
00143           }
00144         }
00145       } else {
00146         // fixed
00147         upRhs -= colLower[iColumn]*elementByRow[j];
00148         loRhs -= colLower[iColumn]*elementByRow[j];
00149       }
00150     }
00151     // see if binding
00152     effectiveUpper[rowIndex] = upRhs;
00153     effectiveLower[rowIndex] = loRhs;
00154     vubValue[rowIndex] = valueContinuous;
00155     bool possible = false;
00156     if (fabs(sum-upRhs)<1.0e-5) {
00157       possible=true;
00158     } else {
00159       effectiveUpper[rowIndex]=DBL_MAX;
00160     }
00161     if (fabs(sum-loRhs)<1.0e-5) {
00162       possible=true;
00163     } else {
00164       effectiveLower[rowIndex]=-DBL_MAX;
00165     }
00166     if (!numberBinary||numberBinary+numberContinuous>maxInKnapsack_)
00167       possible=false;
00168     if (possible) {
00169       // binding with binary
00170       if(numberContinuous==1&&iCont>=0) {
00171         // vub
00172         if (numberBinary==1)
00173 #ifdef PRINT_DEBUG
00174           printf("vub (by row %d) %g <= 0-1 %g * %d + %g * %d <= %g\n",
00175                  rowIndex,effectiveLower[rowIndex],valueBinary,iBinary,
00176                  valueContinuous,iCont,effectiveUpper[rowIndex]);
00177 #endif
00178         vubRow[iCont]=rowIndex;
00179         vub[rowIndex]=iCont;
00180         numberVub++;
00181       } else if (numberBinary>1) {
00182         // could be knapsack
00183         vub[rowIndex]=-1;
00184       } else {
00185         // no point looking at this row
00186         vub[rowIndex]=-2;
00187       }
00188     } else {
00189       // no point looking at this row
00190       vub[rowIndex]=-2;
00191     }
00192   }
00193   // Main loop
00194   int numCheck = 0;
00195   int* toCheck = 0;
00196   if (!rowsToCheck_) {
00197      toCheck = new int[nRows];
00198      CoinIotaN(toCheck, nRows, 0);
00199      numCheck = nRows;
00200   } else {
00201      numCheck = numRowsToCheck_;
00202      toCheck = rowsToCheck_;
00203   }
00204 
00205   // Set up number of tries for each row
00206   int ntry;
00207   if (numberVub) 
00208     ntry=4;
00209   else
00210     ntry=2;
00211   //ntry=2; // switch off
00212   for (int ii=0; ii < numCheck; ++ii){
00213      rowIndex = toCheck[ii];
00214      if (rowIndex < 0 || rowIndex >= nRows)
00215         continue;
00216      if (vub[rowIndex]==-2)
00217        continue;
00218 
00219 #ifdef PRINT_DEBUG
00220     std::cout << "CGL: Processing row " << rowIndex << std::endl;
00221 #endif
00222     
00223     // Get a tight row 
00224     // (want to be able to 
00225     //  experiment by turning this on and off)
00226     //
00227     // const double * pi=si.rowprice(); 
00228     // if (fabs(pi[row]) < epsilon_){
00229     //  continue;
00230     // }
00231     
00232     
00234     // Derive a "canonical"  knapsack                  //
00235     // inequality (in binary variables)                 //
00236     // from the model row in mixed integer variables    //
00238 #ifdef CGL_DEBUG
00239     assert(!krow.getNumElements());
00240 #endif
00241     double effectiveRhs[4];
00242     double rhs[4];
00243     double sign[]={0.0,0.0,-1.0,1.0};
00244     bool rowType[] = {false,true,false,true};
00245     effectiveRhs[0] = effectiveLower[rowIndex]; 
00246     rhs[0]=rowLower[rowIndex];
00247     effectiveRhs[2] = effectiveRhs[0];
00248     rhs[2]= effectiveRhs[0];
00249     effectiveRhs[1] = effectiveUpper[rowIndex]; 
00250     rhs[1]=rowUpper[rowIndex];
00251     effectiveRhs[3] = effectiveRhs[1];
00252     rhs[3]= effectiveRhs[1];
00253     int itry;
00254 #ifdef CGL_DEBUG
00255     int kcuts[4];
00256     memset(kcuts,0,4*sizeof(int));
00257 #endif
00258     for (itry=0;itry<ntry;itry++) {
00259 #ifdef CGL_DEBUG
00260       int nlast=cs.sizeRowCuts();
00261 #endif
00262       // see if to skip
00263       if (fabs(effectiveRhs[itry])>1.0e20)
00264         continue;
00265       int length = rowLength[rowIndex];
00266       memcpy(thisColumnIndex,column+rowStart[rowIndex],length*sizeof(int));
00267       memcpy(thisElement,elementByRow+rowStart[rowIndex],
00268              length*sizeof(double));
00269       b=rhs[itry];
00270       if (itry>1) {
00271         // see if we would be better off relaxing
00272         int i;
00273         // mark columns
00274         int length2=length; // for new length
00275         int numberReplaced=0;
00276         for (i=0;i<length;i++) {
00277           int iColumn = thisColumnIndex[i];
00278           back[thisColumnIndex[i]]=i;
00279           if (vubRow[iColumn]==-10) {
00280             // fixed - take out
00281             thisElement[i]=0.0;
00282           }
00283         }
00284         for (i=0;i<length;i++) {
00285           int iColumn = thisColumnIndex[i];
00286           int iRow = vubRow[iColumn];
00287           if (iRow>=0&&vub[iRow]==iColumn&&iRow!=rowIndex) {
00288             double useRhs=0.0;
00289             double vubCoefficient = vubValue[iRow];
00290             double thisCoefficient = thisElement[i];
00291             int replace = 0;
00292             // break it out - may be able to do better
00293             if (sign[itry]*thisCoefficient>0.0) {
00294               // we want valid lower bound on continuous
00295               if (effectiveLower[iRow]>-1.0e20&&vubCoefficient>0.0) 
00296                 replace=-1;
00297               else if (effectiveUpper[iRow]<1.0e20&&vubCoefficient<0.0) 
00298                 replace=1;
00299             } else {
00300               // we want valid upper bound on continuous
00301               if (effectiveLower[iRow]>-1.0e20&&vubCoefficient<0.0) 
00302                 replace=-1;
00303               else if (effectiveUpper[iRow]<1.0e20&&vubCoefficient>0.0) 
00304                 replace=1;
00305             }
00306             if (replace) {
00307               numberReplaced++;
00308               if (replace<0)
00309                 useRhs = effectiveLower[iRow];
00310               else
00311                 useRhs = effectiveUpper[iRow];
00312               // now replace (just using vubRow==-2)
00313               // delete continuous
00314               thisElement[i]=0.0;
00315               double scale = thisCoefficient/vubCoefficient;
00316               // modify rhs
00317               b -= scale*useRhs;
00318               int start = rowStart[iRow];
00319               int end = start+rowLength[iRow];
00320               int j;
00321               for (j=start;j<end;j++) {
00322                 int iColumn = column[j];
00323                 if (vubRow[iColumn]==-2) {
00324                   double change = scale*elementByRow[j];
00325                   int iBack = back[iColumn];
00326                   if (iBack<0) {
00327                     // element does not exist
00328                     back[iColumn]=length2;
00329                     thisElement[length2]=-change;
00330                     thisColumnIndex[length2++]=iColumn;
00331                   } else {
00332                     // element does exist
00333                     thisElement[iBack] -= change;
00334                   }
00335                 }
00336               }
00337             }
00338           }
00339         }
00340         if (numberReplaced) {
00341           length=0;
00342           for (i=0;i<length2;i++) {
00343             int iColumn = thisColumnIndex[i];
00344             back[iColumn]=-1; // un mark
00345             if (thisElement[i]) {
00346               thisElement[length]=thisElement[i];
00347               thisColumnIndex[length++]=iColumn;
00348             }
00349           }
00350           if (length>maxInKnapsack_)
00351             continue; // too long
00352         } else {
00353           for (i=0;i<length;i++) {
00354             int iColumn = thisColumnIndex[i];
00355             back[iColumn]=-1; // un mark
00356           }
00357           continue; // no good
00358         }
00359       }
00360       if (!deriveAKnapsack(si, cs, krow, rowType[itry], b, complement, 
00361                            xstar, rowIndex, 
00362                            length,thisColumnIndex,thisElement)) {
00363         
00364         // Reset local data and continue to the next iteration 
00365         // of the rowIndex-loop
00366         for(k=0; k<krow.getNumElements(); k++) {
00367           if (complement[krow.getIndices()[k]]){
00368             xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00369             complement[krow.getIndices()[k]]=0;        
00370           }
00371         }
00372         krow.setVector(0,NULL,NULL);
00373         continue;
00374       }
00375 #ifdef PRINT_DEBUG
00376       {
00377         // Get the sense of the row
00378         int i;
00379         printf("rhs sense %c rhs %g\n",si.getRowSense()[rowIndex],
00380                si.getRightHandSide()[rowIndex]);
00381         const int * indices = si.getMatrixByRow()->getVector(rowIndex).getIndices();
00382         const double * elements = si.getMatrixByRow()->getVector(rowIndex).getElements();
00383         // for every variable in the constraint
00384         for (i=0; i<si.getMatrixByRow()->getVector(rowIndex).getNumElements(); i++){
00385           printf("%d (s=%g) %g, ",indices[i],colsol[indices[i]],elements[i]);
00386         }
00387         printf("\n");
00388       }
00389 #endif
00390       
00392       // Look for a series of                             //
00393       // different types of minimal covers.               //
00394       // If a minimal cover is found,                     //
00395       // lift the associated minimal cover inequality,    //
00396       // uncomplement the vars                            //
00397       // and add it to the cut set.                       //
00398       // After the last type of cover is tried,           //
00399       // restore xstar values                             //
00401       
00403       // Try to generate a violated                       //
00404       // minimal cover greedily from fractional vars      //
00406       
00407       CoinPackedVector cover, remainder;  
00408       
00409       
00410       if (findGreedyCover(rowIndex, krow, b, xstar, cover, remainder) == 1){
00411         
00412         // Lift cover inequality and add to cut set 
00413         if (!liftAndUncomplementAndAdd(rowUpper[rowIndex], krow, b,
00414                                        complement, rowIndex, cover, 
00415                                        remainder, cs)) {
00416           // Reset local data and continue to the next iteration 
00417           // of the rowIndex-loop
00418           // I am not sure this is needed but I am just being careful
00419           for(k=0; k<krow.getNumElements(); k++) {
00420             if (complement[krow.getIndices()[k]]){
00421               xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00422               complement[krow.getIndices()[k]]=0;        
00423             }
00424           }
00425           krow.setVector(0,NULL,NULL);
00426           continue;
00427         }  
00428       }
00429       
00430       
00432       // Try to generate a violated                       //
00433       // minimal cover using pseudo John and Ellis logic  //
00435       
00436       // Reset the cover and remainder
00437       cover.setVector(0,NULL,NULL);
00438       remainder.setVector(0,NULL,NULL);
00439       
00440       if (findPseudoJohnAndEllisCover(rowIndex, krow, b,
00441                                       xstar, cover, remainder) == 1){
00442         
00443         // (Sequence Independent) Lift cover inequality and add to cut set 
00444         if (!liftAndUncomplementAndAdd(rowUpper[rowIndex], krow, b,
00445                                        complement, rowIndex, cover, 
00446                                        remainder, cs)) {
00447           // Reset local data and continue to the next iteration 
00448           // of the rowIndex-loop
00449           // I am not sure this is needed but I am just being careful
00450           for(k=0; k<krow.getNumElements(); k++) {
00451             if (complement[krow.getIndices()[k]]){
00452               xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00453               complement[krow.getIndices()[k]]=0;        
00454             }
00455           }
00456           krow.setVector(0,NULL,NULL);
00457           continue;
00458         }  
00459         
00460         // Skip experiment for now...
00461 #if 0
00462         // experimenting here...
00463         // (Sequence Dependent) Lift cover inequality and add to cut set
00464         seqLiftAndUncomplementAndAdd(nCols, xstar, complement, rowIndex,
00465                                      krow.getNumElements(), b, cover, remainder,
00466                                      cs);
00467 #endif 
00468       }  
00469       
00470       
00471       
00473       // Try to generate cuts using covers of unsat       //
00474       // vars on reduced krows with John and Ellis logic  //
00476       CoinPackedVector atOnes;
00477       CoinPackedVector fracCover; // different than cover
00478       
00479       // reset the remainder
00480       remainder.setVector(0,NULL,NULL);
00481       
00482       
00483       if (findJohnAndEllisCover(rowIndex, krow, b,
00484                                 xstar, fracCover, atOnes, remainder) == 1){
00485         
00486         // experimenting here...
00487         // Sequence Dependent Lifting up on remainders and lifting down on the
00488         // atOnes 
00489         liftUpDownAndUncomplementAndAdd(nCols, xstar, complement, rowIndex,
00490                                         krow.getNumElements(), b, fracCover,
00491                                         atOnes, remainder, cs);
00492       }
00493       
00494       
00496       // Try to generate a violated                       //
00497       // minimal cover by considering the                 //
00498       // most violated cover problem                      //
00500       
00501       
00502       // reset cover and remainder
00503       cover.setVector(0,NULL,NULL);
00504       remainder.setVector(0,NULL,NULL);
00505       
00506       // if the size of the krow is "small", 
00507       //    use an exact algorithm to find the most violated (minimal) cover, 
00508       // else, 
00509       //    use an lp-relaxation to find the most violated (minimal) cover.
00510       if(krow.getNumElements()<=15){
00511         if (findExactMostViolatedMinCover(nCols, rowIndex, krow, b,
00512                                           xstar, cover, remainder) == 1){
00513           
00514           // Lift cover inequality and add to cut set 
00515           if (!liftAndUncomplementAndAdd(rowUpper[rowIndex], krow, b,
00516                                          complement, rowIndex, cover, remainder, cs)) {
00517             // Reset local data and continue to the next iteration 
00518             // of the rowIndex-loop
00519             // I am not sure this is needed but I am just being careful
00520             for(k=0; k<krow.getNumElements(); k++) {
00521               if (complement[krow.getIndices()[k]]){
00522                 xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00523                 complement[krow.getIndices()[k]]=0;        
00524               }
00525             }
00526             krow.setVector(0,NULL,NULL);
00527             continue;
00528           }  
00529         }
00530       } 
00531       else {
00532         if (findLPMostViolatedMinCover(nCols, rowIndex, krow, b,
00533                                        xstar, cover, remainder) == 1){
00534           
00535           // Lift cover inequality and add to cut set 
00536           if (!liftAndUncomplementAndAdd(rowUpper[rowIndex], krow, b,
00537                                          complement, rowIndex, cover, remainder, cs)) {
00538             // Reset local data and continue to the next iteration 
00539             // of the rowIndex-loop
00540             // I am not sure this is needed but I am just being careful
00541             for(k=0; k<krow.getNumElements(); k++) {
00542               if (complement[krow.getIndices()[k]]){
00543                 xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00544                 complement[krow.getIndices()[k]]=0;        
00545               }
00546             }
00547             krow.setVector(0,NULL,NULL);
00548             continue;
00549           }  
00550         }
00551       } 
00552       
00553       
00554       
00555       // Reset xstar and complement to their initialized values for the next
00556       // go-around 
00557       int k;
00558       if (fabs(b-rowUpper[rowIndex]) > epsilon_) {
00559         for(k=0; k<krow.getNumElements(); k++) {
00560           if (complement[krow.getIndices()[k]]){
00561             xstar[krow.getIndices()[k]]= 1.0-xstar[krow.getIndices()[k]];
00562             complement[krow.getIndices()[k]]=0;
00563           }
00564         }
00565       }
00566       krow.setVector(0,NULL,NULL);
00567 #ifdef CGL_DEBUG
00568       int nnow = cs.sizeRowCuts();
00569       if (nnow>nlast) {
00570         const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
00571         if (debugger&&debugger->onOptimalPath(si)) {
00572           // check cuts okay
00573           int k;
00574           for (k=nlast;k<nnow;k++) {
00575             OsiRowCut rc=cs.rowCut(k);
00576             if(debugger->invalidCut(rc)) {
00577               printf("itry %d, rhs %g, length %d\n",itry,rhs[itry],length);
00578               int i;
00579               for (i=0;i<length;i++) {
00580                 int iColumn = thisColumnIndex[i];
00581                 printf("column %d, coefficient %g, value %g, bounds %g %g\n",iColumn,
00582                        thisElement[i],colsol[iColumn],colLower[iColumn],
00583                        colUpper[iColumn]);
00584               }
00585               if (itry>1) {
00586                 int length = rowLength[rowIndex];
00587                 memcpy(thisColumnIndex,column+rowStart[rowIndex],
00588                        length*sizeof(int));
00589                 memcpy(thisElement,elementByRow+rowStart[rowIndex],
00590                        length*sizeof(double));
00591                 printf("Original row had rhs %g and length %d\n",
00592                        (itry==2 ? rowLower[rowIndex] :rowUpper[rowIndex]),
00593                        length);
00594                 for (i=0;i<length;i++) {
00595                   int iColumn = thisColumnIndex[i];
00596                   printf("column %d, coefficient %g, value %g, bounds %g %g\n",iColumn,
00597                          thisElement[i],colsol[iColumn],colLower[iColumn],
00598                          colUpper[iColumn]);
00599                 }
00600               }
00601               assert(!debugger->invalidCut(rc));
00602             }
00603           }
00604         }
00605         if (itry>1&&nnow-nlast>kcuts[itry-2]) {
00606           printf("itry %d gave %d cuts as against %d for itry %d\n",
00607                  itry,nnow-nlast,kcuts[itry-2],itry-2);
00608         }
00609         kcuts[itry]=nnow-nlast;
00610         nlast=nnow;
00611       }
00612 #endif
00613     }
00614   }
00615   // Clean up: free allocated memory
00616   if (toCheck != rowsToCheck_)
00617      delete[] toCheck;
00618   delete[] xstar;
00619   delete[] complement;
00620   delete [] thisColumnIndex;
00621   delete [] thisElement;
00622   delete [] back;
00623   delete [] vub;
00624   delete [] vubRow;
00625   delete [] vubValue;
00626   delete [] effectiveLower;
00627   delete [] effectiveUpper;
00628 }
00629 
00630 void
00631 CglKnapsackCover::setTestedRowIndices(int num, const int* ind)
00632 {
00633    if (rowsToCheck_)
00634       delete[] rowsToCheck_;
00635    numRowsToCheck_ = num;
00636    if (num > 0) {
00637       rowsToCheck_ = new int[num];
00638       CoinCopyN(ind, num, rowsToCheck_);
00639    }
00640 }
00641 
00642 //------------------------------------------------------------- 
00643 // Lift and uncomplement cut. Add cut to the cutset
00644 //-------------------------------------------------------------------
00645 int 
00646 CglKnapsackCover::liftAndUncomplementAndAdd(
00647          double rowub,
00648          CoinPackedVector & krow,
00649          double & b,
00650          int * complement,
00651          int row,
00652          CoinPackedVector & cover,
00653          CoinPackedVector & remainder,
00654          OsiCuts & cs ) const
00655 {
00656   CoinPackedVector cut;
00657   double cutRhs = cover.getNumElements() - 1.0;
00658   int goodCut=1;
00659   
00660   if (remainder.getNumElements() > 0){
00661     // Construct lifted cover cut 
00662     if (!liftCoverCut( 
00663                       b, krow.getNumElements(), 
00664                       cover, remainder,
00665                       cut )) 
00666       goodCut= 0; // no cut
00667   }
00668   // The cover consists of every variable in the knapsack.
00669   // There is nothing to lift, so just add cut            
00670   else {
00671     cut.reserve(cover.getNumElements());
00672     cut.setConstant(cover.getNumElements(),cover.getIndices(),1.0);
00673   }
00674   
00675   // Uncomplement the complemented variables in the cut
00676   int k;
00677   if (fabs(b-rowub)> epsilon_) {
00678     double * elements = cut.getElements();
00679     int * indices = cut.getIndices();
00680     for (k=0; k<cut.getNumElements(); k++){
00681       if (complement[indices[k]]) {
00682         // Negate the k'th element in packedVector cut
00683         // and correspondingly adjust the rhs
00684         elements[k] *= -1;
00685         cutRhs += elements[k];
00686       }
00687     }
00688   }
00689   if (goodCut) {
00690     // Create row cut. Effectiveness defaults to 0.
00691     OsiRowCut rc;
00692     rc.setRow(cut);
00693 #ifdef CGL_DEBUG
00694     {
00695       double * elements = cut.getElements();
00696       int * indices = cut.getIndices();
00697       int n=cut.getNumElements();
00698       for (k=0; k<n; k++){
00699         assert(indices[k]>=0);
00700         assert(elements[k]);
00701       }
00702     }
00703 #endif
00704     rc.setLb(-DBL_MAX);
00705     rc.setUb(cutRhs);
00706     //  rc.setEffectiveness(0);
00707     // Todo: put in a more useful measure such as  the violation. 
00708     
00709     // Add row cut to the cut set  
00710 #ifdef PRINT_DEBUG
00711     {
00712       int k;
00713       printf("cutrhs %g %d elements\n",cutRhs,cut.getNumElements());
00714       double * elements = cut.getElements();
00715       int * indices = cut.getIndices();
00716       for (k=0; k<cut.getNumElements(); k++){
00717         printf("%d %g\n",indices[k],elements[k]);
00718       }
00719     }
00720 #endif
00721     cs.insert(rc);
00722     
00723     return 1;
00724   } else {
00725     return 0;
00726   }
00727 }
00728 
00729 //-------------------------------------------------------------------
00730 // deriveAKnapsack - returns 1 if the method is able to 
00731 //                  derive a canonical knapsack inequality
00732 //                  in binary variables of the form ax<=b 
00733 //                  from the rowIndex-th row of the constraint matrix.
00734 //                  returns 0, otherwise.
00735 //  Precondition: complement must be 0'd out!!!
00736 //-------------------------------------------------------------------
00737 int 
00738 CglKnapsackCover::deriveAKnapsack(
00739        const OsiSolverInterface & si, 
00740        OsiCuts & cs,
00741        CoinPackedVector & krow, 
00742        bool treatAsLRow,
00743        double & b,
00744        int *  complement,
00745        double *  xstar,
00746        int rowIndex,
00747        int numberElements,
00748        const int * index,
00749        const double * element) const
00750 {
00751   int i;
00752 
00753   krow.clear();
00754 
00755   // if the matrixRow represent a ge inequality, then
00756   //     leMatrixRow == -matrixRow  // otherwise
00757   //     leMatrixRow == matrixRow.
00758 
00759   CoinPackedVector leMatrixRow(numberElements,index,element); 
00760 
00761   double maxKrowElement = -DBL_MAX;
00762   double minKrowElement = DBL_MAX;
00763   
00764 
00765   if (treatAsLRow) {
00766     // treat as if L row
00767   } else {
00768     // treat as if G row
00769     b=-b;
00770     std::transform(leMatrixRow.getElements(),
00771                    leMatrixRow.getElements() + leMatrixRow.getNumElements(),
00772                    leMatrixRow.getElements(),
00773                    std::negate<double>());
00774   }
00775   
00776   // nBinUnsat is a counter for the number of unsatisfied
00777   // (i.e. fractional) binary vars  
00778   int nBinUnsat =0;
00779   const double * colupper = si.getColUpper();
00780   const double * collower = si.getColLower();
00781   
00782   // At this point, leMatrixRow and b represent a le inequality in general
00783   // variables. 
00784   // To derive a canonical knapsack inequality in free binary variable,
00785   // process out the continuous & non-binary integer & fixed binary variables.
00786   // If the non-free-binary variables can be appropriately bounded, 
00787   // net them out of the constraint, otherwise abandon this row and return 0.
00788 
00789   const int * indices = leMatrixRow.getIndices();
00790   const double * elements = leMatrixRow.getElements();
00791   // for every variable in the constraint
00792   for (i=0; i<leMatrixRow.getNumElements(); i++){
00793     // if the variable is not a free binary var
00794     if ( !si.isFreeBinary(indices[i]) ) {
00795       // and the coefficient is strictly negative
00796       if(elements[i]<-epsilon_){
00797         // and the variable has a finite upper bound
00798         if (colupper[indices[i]] < si.getInfinity()){
00799           // then replace the variable with its upper bound.
00800           b=b-elements[i]*colupper[indices[i]];
00801         } 
00802         else {
00803           return 0;
00804         }
00805       }
00806       // if the coefficient is strictly positive
00807       else if(elements[i]>epsilon_){
00808         // and the variable has a finite lower bound
00809         if (collower[indices[i]] > -si.getInfinity()){
00810           // then replace the variable with its lower bound.
00811           b=b-elements[i]*collower[indices[i]];
00812         }
00813         else {
00814           return 0;
00815         }
00816       }
00817       // note: if the coefficient is zero, the variable is not included in the 
00818       //       knapsack inequality.
00819     }
00820     // else the variable is a free binary var and is included in the knapsack
00821     // inequality. 
00822     // note: the variable is included regardless of its solution value to the
00823     // lp relaxation. 
00824     else{
00825       krow.insert(indices[i], elements[i]);
00826 
00827       // if the binary variable is unsatified (i.e. has fractional value),
00828       // increment the counter. 
00829       if(xstar[indices[i]] > epsilon_ && xstar[indices[i]] < onetol_)
00830         nBinUnsat++;
00831 
00832       // keep track of the largest and smallest elements in the knapsack
00833       // (the idea is if there is not a lot of variation in the knapsack
00834       // coefficients, it is unlikely we will find a violated minimal
00835       // cover from this knapsack so don't even bother trying) 
00836       if (fabs(elements[i]) > maxKrowElement) 
00837         maxKrowElement = fabs(elements[i]);
00838       if (fabs(elements[i]) < minKrowElement) 
00839         minKrowElement = fabs(elements[i]);
00840     }
00841   }
00842   
00843   // If there's little variation in the knapsack coefficients, return 0.
00844   // If there are no unsatisfied binary variables, return.
00845   // If there's only one binary, return.  
00846   // ToDo: but why return if 2 binary? ...there was some assumption in the
00847   // findVioMinCover..(?)   
00848   // Anyway probing will probably find something
00849   if (krow.getNumElements() < 3 ||
00850       nBinUnsat == 0 ||
00851       maxKrowElement-minKrowElement < 1.0e-3*maxKrowElement ) {
00852     return 0;
00853   }
00854 
00855   // However if we do decide to do when count is two - look carefully
00856   if (krow.getNumElements()==2) {
00857     const int * indices = krow.getIndices();
00858     double * elements = krow.getElements();
00859     double sum=0.0;
00860     for(i=0; i<2; i++){
00861       int iColumn = indices[i];
00862       sum += elements[i]*xstar[iColumn];
00863     }
00864     if (sum<b-1.0e-4) {
00865       return 0;
00866     } else {
00867       printf("*** Doubleton Row is ");
00868       for(i=0; i<2; i++){
00869         int iColumn = indices[i];
00870         sum += elements[i]*xstar[iColumn];
00871         printf("%d (coeff = %g, value = %g} ",indices[i],
00872                elements[i],xstar[iColumn]);
00873       }
00874       printf("<= %g - go for it\n",b);
00875     }
00876   }
00877 
00878 
00879   // At this point krow and b represent a le inequality in binary variables.  
00880   // To obtain an le inequality with all positive coefficients, complement
00881   // any variable with a negative coefficient by changing the sign of 
00882   // the coefficient, adjusting the rhs, and adjusting xstar, the column
00883   // solution vector.
00884   {
00885      const int s = krow.getNumElements();
00886      const int * indices = krow.getIndices();
00887      double * elements = krow.getElements();
00888      for(i=0; i<s; i++){
00889          if (elements[i] < -epsilon_) {
00890            complement[indices[i]]= 1;
00891            elements[i] *= -1;
00892            b+=elements[i]; 
00893            xstar[indices[i]]=1.0-xstar[indices[i]];
00894         }
00895      }
00896   }
00897 
00898   // Quick feasibility check.
00899   // If the problem is infeasible, add an infeasible col cut to cut set
00900   // e.g. one that has lb > ub.
00901   // TODO: test this scenario in BCP
00902   if (b < 0 ){ 
00903     OsiColCut cc;
00904     int index = krow.getIndices()[0]; 
00905     const double fakeLb = colupper[index] + 1.0;;  // yes, colupper.
00906     const double fakeUb = collower[index];
00907     assert( fakeUb < fakeLb );
00908     cc.setLbs( 1, &index, &fakeLb);
00909     cc.setUbs( 1, &index, &fakeLb);
00910     cc.setEffectiveness(DBL_MAX);
00911     cs.insert(cc);
00912 #ifdef PRINT_DEBUG
00913     printf("Cgl: Problem is infeasible\n");
00914 #endif
00915   }
00916   
00917   // At this point, krow and b represent a le inequality with postive
00918   // coefficients. 
00919   // If any coefficient a_j > b, then x_j = 0, return 0
00920   // If any complemented var has coef a_j > b, then x_j = 1, return 0 
00921   int fixed = 0;
00922   CoinPackedVector fixedBnd;  
00923   for(i=0; i<krow.getNumElements(); i++){
00924     if (krow.getElements()[i]> b){
00925       fixedBnd.insert(krow.getIndices()[i],complement[krow.getIndices()[i]]);
00926 #ifdef PRINT_DEBUG   
00927       printf("Variable %i being fixed to %i due to row %i.\n",
00928              krow.getIndices()[i],complement[krow.getIndices()[i]],rowIndex); 
00929 #endif
00930       fixed = 1;      
00931     }
00932   }
00933 
00934   // After all possible variables are fixed by adding a column cut with 
00935   // equivalent lower and upper bounds, return
00936   if (fixed) {
00937     OsiColCut cc;
00938     cc.setLbs(fixedBnd);
00939     cc.setUbs(fixedBnd);
00940     cc.setEffectiveness(DBL_MAX);
00941     return 0; 
00942   }  
00943 
00944   return 1;
00945 }
00946 
00947 
00948 //-------------------------------------------------------------------
00949 // deriveAKnapsack - returns 1 if the method is able to 
00950 //                  derive a cannonical knapsack inequality
00951 //                  in binary variables of the form ax<=b 
00952 //                  from the rowIndex-th row of the constraint matrix.
00953 //                  returns 0, otherwise.
00954 //  Precondition: complement must be 0'd out!!!
00955 //-------------------------------------------------------------------
00956 int 
00957 CglKnapsackCover::deriveAKnapsack(
00958        const OsiSolverInterface & si, 
00959        OsiCuts & cs,
00960        CoinPackedVector & krow, 
00961        double & b,
00962        int *  complement,
00963        double *  xstar,
00964        int rowIndex,
00965        const CoinPackedVectorBase & matrixRow ) const
00966 {
00967   // Get the sense of the row
00968   const char  rowsense = si.getRowSense()[rowIndex];
00969   
00970   // Skip equality and unbounded rows 
00971   if  (rowsense=='E' || rowsense=='N') {
00972     return 0; 
00973   }
00974   
00975   bool treatAsLRow =  (rowsense=='L');
00976   const int * indices = matrixRow.getIndices();
00977   const double * elements = matrixRow.getElements();
00978   int numberElements = matrixRow.getNumElements();
00979   return deriveAKnapsack( si, cs, krow, treatAsLRow, b, complement,
00980                           xstar, rowIndex, numberElements, indices,
00981                           elements);
00982 }
00983 
00984 //--------------------------------------------------
00985 // Find a violated minimal cover from 
00986 // a canonical form knapsack inequality by
00987 // solving the lp relaxation of the 
00988 // -most- violated cover problem.
00989 // Postprocess to ensure minimality.
00990 // -----------------------------------------
00991 int 
00992 CglKnapsackCover::findLPMostViolatedMinCover(
00993       int nCols,
00994       int row,
00995       CoinPackedVector & krow,
00996       double & b,
00997       double * xstar, 
00998       CoinPackedVector & cover,
00999       CoinPackedVector & remainder) const
01000 {
01001   
01002   // Assumes krow and b describe a knapsack inequality in canonical form
01003 
01004   // Given a knapsack inequality sum a_jx_j <= b, and optimal lp solution
01005   // xstart, a violated minimal cover inequality exists if the following 0-1
01006   // programming problem has an optimal objective function value (oofv) < 1
01007   //     oofv = min sum (1-xstar_j)z_j
01008   //            s.t. sum a_jz_j > b
01009   //            z binary
01010   
01011   // The vector z is an incidence vector, defining the cover R with the 
01012   // associated cover inequality:
01013   //    (sum j in R) x_j <= |R|-1
01014   
01015   // This problem is itself a (min version of the) knapsack problem
01016   // but with a unsightly strict inequalty.
01017   
01018   // To transform transform it into a max version, 
01019   // complement the z's, z_j=1-y_j.
01020   // To compensate for the strict inequality, subtract epsilon from the rhs.
01021   
01022   //     oofv = (sum (1-xstar_j))-  max sum (1-xstar)y_j
01023   //                        s.t. sum a_jy_j <= (sum over j)a_j - b (- EPSILON)
01024   //                             y binary
01025   
01026   // If oofv < 1, then a violated min cover inequality has
01027   // incidence vector z with elements z_j=1-y_j and rhs= num of nonzero's in 
01028   // z, i.e. the number of 0's in y.
01029 
01030   // If the size of the knapsack is "small", we solve the problem exactly. 
01031   // If the size of the knapsack is large, we solve the (simpler) lp relaxation
01032   // of the  knapsack problem and postprocess to ensure the construction of a 
01033   // minimimal cover.
01034   
01035   // We also assume that testing/probing/fixing based on the knapsack structure
01036   // is done elsewhere. Only convenient-to-do sanity checks are done here.
01037   // (We do not assume that data is integer.)
01038 
01039   double elementSum = krow.sum();
01040 
01041   // Redundant/useless adjusted rows should have been trapped in the 
01042   // transformation to the canonical form of knapsack inequality
01043   if (elementSum < b + epsilon_) {
01044     return -1; 
01045   }
01046   
01047   // Order krow in nonincreasing order of coefObj_j/a_j.  
01048   // (1-xstar_1)/a_1 >= (1-xstar_2)/a_2 >= ... >= (1-xstar_n)/a_n   
01049   // by defining this full-storage array "ratio" to be the external sort key.
01050   double * ratio= new double[nCols];
01051   memset(ratio, 0, (nCols*sizeof(double)));
01052 
01053   int i;
01054   for (i=0; i<krow.getNumElements(); i++){
01055     if (fabs(krow.getElements()[i])> epsilon_ ){
01056       ratio[krow.getIndices()[i]]=
01057          (1.0-xstar[krow.getIndices()[i]]) / (krow.getElements()[i]);
01058     }
01059     else {
01060       ratio[krow.getIndices()[i]] = 0.0;
01061     }
01062   }
01063 
01064   // ToDo: would be nice to have sortkey NOT be full-storage vector
01065   CoinDecrSolutionOrdered dso(ratio);
01066   krow.sort(dso);   
01067 
01068   // Find the "critical" element index "r" in the knapsack lp solution
01069   int r = 0;
01070   double sum = krow.getElements()[0];
01071   while ( sum <= (elementSum - b - epsilon_ ) ){
01072     r++;
01073     sum += krow.getElements()[r];
01074   }    
01075   
01076   // Note: It is possible the r=0, and you get a violated minimal cover 
01077   // if (r=0), then you've got a var with a really large coeff. compared
01078   //   to the rest of the row.
01079   // r=0 says trivially that the 
01080   //   sum of ALL the binary vars in the row <= (cardinality of all the set -1)
01081   // Note: The cover may not be minimal if there are alternate optimals to the 
01082   // maximization problem, so the cover must be post-processed to ensure 
01083   // minimality.
01084   
01085   // "r" is the critical element 
01086   // The lp relaxation column solution is:
01087   // y_j = 1 for  j=0,...,(r-1)
01088   // y_r = (elementSum - b - sum + krow.element()[r])/krow.element()[r] 
01089   // y_j = 0 for j=r+1,...,krow.getNumElements() 
01090   
01091   // The number of nonzeros in the lp column solution is r+1 
01092   
01093   // if oofv to the lp knap >= 1, then no violated min cover is possible 
01094   int nCover;
01095 
01096   double lpoofv=0.0;
01097   for (i=r+1; i<krow.getNumElements(); i++){
01098     lpoofv += (1-xstar[krow.getIndices()[i]]);
01099   }
01100   double ipofv = lpoofv + (1-xstar[krow.getIndices()[r]]);
01101 
01102   // Couldn't find an lp violated min cover inequality 
01103   if (ipofv > 1.0 - epsilon_){    
01104     delete [] ratio;
01105     return -1;
01106   }
01107   else {
01108     // Partition knapsack into cover and noncover (i.e. remainder)
01109     // pieces
01110     nCover = krow.getNumElements() - r;
01111     double coverSum =0.0;
01112     cover.reserve(nCover);
01113     remainder.reserve(r);
01114     
01115     for (i=r; i<krow.getNumElements(); i++){
01116       cover.insert(krow.getIndices()[i],krow.getElements()[i]);
01117       coverSum += krow.getElements()[i];
01118     }
01119     for (i=0; i<r; i++){
01120       remainder.insert(krow.getIndices()[i],krow.getElements()[i]);
01121     }
01122     
01123 #ifdef PRINT_DEBUG
01124     if (coverSum <= b){
01125       printf("The identified cover is NOT a cover\n");
01126       abort();
01127     }
01128 #endif
01129     
01130     // Sort cover in terms of knapsack row coefficients   
01131     cover.sortDecrElement();
01132     
01133     
01134     // We have a violated cover inequality.
01135     // Construct a -minimal- violated cover
01136     // by testing and potentially tossing smallest
01137     // elements 
01138     double oneLessCoverSum = coverSum - cover.getElements()[nCover-1];
01139     while (oneLessCoverSum > b){
01140       // move the excess cover member into the set of remainders
01141       remainder.insert(cover.getIndices()[nCover-1],
01142                        cover.getElements()[nCover-1]);
01143       cover.truncate(nCover-1);
01144       nCover--;
01145       oneLessCoverSum -= cover.getElements()[nCover-1];
01146     }
01147 
01148     if (nCover<2){
01149 #ifdef PRINT_DEBUG
01150       printf("nCover < 2...aborting\n");
01151 #endif
01152       abort();
01153     }
01154     
01155 #ifdef PRINT_DEBUG   /* debug */
01156     printf("\
01157 Lp relax of most violated minimal cover: row %i has cover of size %i.\n",
01158            row,nCover);
01159     //double sumCover = 0.0;
01160     for (i=0; i<cover.getNumElements(); i++){
01161       printf("index %i, element %g, xstar value % g \n",
01162              cover.getIndices()[i],cover.getElements()[i],
01163              xstar[cover.getIndices()[i]]);
01164       //sumCover += cover.getElements()[i];
01165     }
01166     printf("The b = %g, and the cover sum is %g\n\n", b, cover.sum());
01167 #endif
01168 
01169 #ifdef P0201
01170       double ppsum=0.0;
01171       for (i=0; i<nCover; i++){
01172         ppsum += p0201[krow.getIndices()[i]];
01173       }
01174         
01175       if (ppsum > nCover-1){
01176           printf("\
01177 \nBad cover from lp relax of most violated cover..aborting\n");
01178           abort();
01179       }
01180 #endif
01181     
01182     /* clean up */
01183     delete [] ratio;
01184     return  1;
01185   }
01186 }
01187 
01188 
01189 //--------------------------------------------------
01190 // Find a violated minimal cover from 
01191 // a canonical form knapsack inequality by
01192 // solving the -most- violated cover problem
01193 // and postprocess to ensure minimality
01194 // -----------------------------------------
01195 int 
01196 CglKnapsackCover::findExactMostViolatedMinCover(
01197         int nCols,
01198         int row,
01199         CoinPackedVector & krow,
01200         double b, 
01201         double *  xstar, 
01202         CoinPackedVector & cover,
01203         CoinPackedVector & remainder) const 
01204 {
01205   
01206   // assumes the row is in canonical knapsack form 
01207   
01208   // A violated min.cover inequality exists if the
01209   // opt obj func value (oofv) < 1: 
01210   //     oofv = min sum (1-xstar_j)z_j
01211   //            s.t. sum a_jz_j > b
01212   //            x binary
01213 
01214   //     The vector z is the incidence vector 
01215   //     defines the set R and the cover inequality.
01216   //      (sum j in R) x_j <= |R|-1
01217 
01218   //    This is the min version of the knapsack problem.
01219   //    (note that strict inequalty...bleck)
01220 
01221   //    To obtain the max version, complement the z's, z_j=1-y_j and 
01222   //    adjust the constraint.
01223 
01224   //    oofv = (sum (1-xstar_j))-  max sum (1-xstar)y_j
01225   //                       s.t. sum a_jy_j <= (sum over j)a_j - b (- EPSILON)]
01226   //                   y binary
01227 
01228   // If oofv < 1, violated min cover inequality has
01229   //    incidence vector z=1-y and rhs= num of nonzero's in z, i.e.
01230   //    the number 0 in y.
01231 
01232   //    We solve the  0-1 knapsack problem by explicit ennumeration
01233 
01234   double elementSum = krow.sum();
01235 
01236   // Redundant/useless adjusted rows should have been trapped in 
01237   // transformation to canonical form of knapsack inequality
01238   if (elementSum < b + epsilon_) {
01239 #ifdef PRINT_DEBUG
01240     printf("Redundant/useless adjusted row\n");
01241 #endif
01242     return -1; 
01243   }
01244 
01245   // Order krow in nonincreasing order of coefObj_j/a_j.  
01246   // (1-xstar_1)/a_1 >= (1-xstar_2)/a_2 >= ... >= (1-xstar_n)/a_n   
01247   // by defining this full-storage array "ratio" to be the external sort key.  
01248   double * ratio= new double[nCols];
01249   memset(ratio, 0, (nCols*sizeof(double)));
01250 
01251   int i;
01252   {
01253      const int * indices = krow.getIndices();
01254      const double * elements = krow.getElements();
01255      for (i=0; i<krow.getNumElements(); i++){
01256         if (fabs(elements[i])> epsilon_ ){
01257            ratio[indices[i]]= (1.0-xstar[indices[i]]) / elements[i];
01258         }
01259         else {
01260            ratio[indices[i]] = 0.0;
01261         }
01262      }
01263   }
01264 
01265   // ToDo: would be nice to have sortkey NOT be full-storage vector
01266   CoinDecrSolutionOrdered dso(ratio);
01267   krow.sort(dso);   
01268 
01269 #ifdef CGL_DEBUG
01270   // sanity check
01271   for ( i=1; i<krow.getNumElements(); i++ ) {
01272     double ratioim1 =  ratio[krow.getIndices()[i-1]];
01273     double ratioi= ratio[krow.getIndices()[i]];
01274     assert( ratioim1 >= ratioi );
01275   }  
01276 #endif  
01277   
01278   // Recall:
01279   // oofv = (sum (1-xstar_j))-  max sum (1-xstar)y_j
01280   //           s.t. sum a_jy_j <= (sum over j)a_j - b (- epsilon_)]
01281   //           y binary
01282 
01283   double objConst = 0.0;
01284   double exactOptVal = -1.0;
01285   int * exactOptSol = new int[krow.getNumElements()];
01286   double * p = new double[krow.getNumElements()];
01287   double * w = new double[krow.getNumElements()];
01288   int kk;
01289   for (kk=0; kk<krow.getNumElements(); kk++){
01290     p[kk]=1.0-xstar[krow.getIndices()[kk]];
01291     w[kk]=krow.getElements()[kk];
01292     objConst+=p[kk];
01293   }
01294   
01295   // vectors are indexed in ratioSortIndex order 
01296   exactSolveKnapsack(krow.getNumElements(), (elementSum-b-epsilon_), p, w,
01297                      exactOptVal, exactOptSol);
01298   
01299   if(objConst-exactOptVal < 1){
01300     cover.reserve(krow.getNumElements());
01301     remainder.reserve(krow.getNumElements());
01302 
01303     // Partition the krow into the cover and the remainder.
01304     // The cover is complement of solution.
01305     double coverElementSum = 0;
01306     for(kk=0;kk<krow.getNumElements();kk++){
01307       if(exactOptSol[kk]==0){
01308         cover.insert(krow.getIndices()[kk],krow.getElements()[kk]);
01309         coverElementSum += krow.getElements()[kk];
01310       }
01311       else {
01312         remainder.insert(krow.getIndices()[kk],krow.getElements()[kk]);
01313       }
01314     }
01315 
01316     cover.sortDecrElement();
01317 
01318     // We have a violated cover inequality.
01319     // Construct a -minimal- violated cover
01320     // by testing and potentially tossing smallest
01321     // elements 
01322     double oneLessCoverElementSum =
01323        coverElementSum - cover.getElements()[cover.getNumElements()-1];
01324     while (oneLessCoverElementSum > b){
01325       // move the excess cover member into the set of remainders
01326       remainder.insert(cover.getIndices()[cover.getNumElements()-1],
01327                        cover.getElements()[cover.getNumElements()-1]);
01328       cover.truncate(cover.getNumElements()-1);
01329       oneLessCoverElementSum -= cover.getElements()[cover.getNumElements()-1];
01330     }
01331 
01332 #ifdef PRINT_DEBUG
01333     printf("Exact Most Violated Cover: row %i has cover of size %i.\n",
01334            row,cover.getNumElements());
01335     //double sumCover = 0.0;
01336     for (i=0; i<cover.getNumElements(); i++){
01337       printf("index %i, element %g, xstar value % g \n",
01338              cover.getIndices()[i], cover.getElements()[i],
01339              xstar[cover.getIndices()[i]]);
01340       //sumCover += cover.getElements()[i];
01341     }
01342     printf("The b = %g, and the cover sum is %g\n\n", b, cover.sum() );
01343 #endif
01344    
01345     // local clean up 
01346     delete [] exactOptSol;
01347     delete [] p;
01348     delete [] w;
01349     delete [] ratio;
01350     
01351     return  1; // found an exact one
01352   }
01353 
01354   // local clean up 
01355   delete [] exactOptSol;
01356   delete [] p;
01357   delete [] w;
01358   delete [] ratio;
01359   
01360   return 0; // didn't find an exact one
01361 
01362 }  
01363 
01364 //-------------------------------------------------------------------
01365 // Find Pseudo John-and-Ellis Cover
01366 // 
01367 // only generates -violated- minimal covers
01368 //-------------------------------------------------------------------
01369 int
01370 CglKnapsackCover::findPseudoJohnAndEllisCover(
01371      int row,
01372      CoinPackedVector & krow,
01373      double & b,
01374      double * xstar, 
01375      CoinPackedVector & cover,  
01376      CoinPackedVector & remainder) const
01377 
01378 {
01379   // semi-mimic of John&Ellis's approach without taking advantage of SOS info
01380   // RLH: They find a minimal cover on unsatisfied variables, but it is 
01381   // not guaranteed to be violated by currently solution 
01382 
01383   // going for functional now, will make efficient when working 
01384   
01385   // look at unstatisfied binary vars with nonzero row coefficients only
01386   // get row in canonical form (here row is in canonical form)
01387   // if complement var, complement soln val too. (already done)
01388   // (*) sort in increasing value of soln val
01389   // track who is the biggest coef and it's index.
01390   // if biggest > adjRhs, skip row. Bad knapsack.
01391   // margin = adjRhs
01392   // idea: if (possibly compl) soln >= .5 round up, else round down
01393   // they do more, but that's the essence
01394   // go through the elements {
01395   // if round down, skip
01396   // if round up, add to element to cover. adjust margin 
01397   // if current element = biggest, then get next biggest
01398   // if biggest > marg, you've got a cover. stop looking               
01399   // else try next element in the loop
01400   // }       
01401   // (*)RLH: I'm going to sort in decreasing order of soln val
01402   // b/c var's whose soln < .5 in can. form get rounded down 
01403   // and skipped. If you can get a min cover of the vars
01404   // whose soln is >= .5, I believe this gives the same as J&E.
01405   // But if not, maybe I can get something more.
01406        
01407   // (**)By checking largest value left, they ensure a minimal cover
01408   // on the unsatisfied variables
01409      
01410   // if you have a cover
01411   // sort the elements to be lifted in order of their reduced costs.
01412   // lift in this order.
01413   // ...I don't understand their lifting, so for now use sequence-indep lifting
01414 
01415   // J&E employ lifting up and down. 
01416   // Here I'm including the vars at one in the cover.
01417   // Adding these vars back in may cause the minimality of the cover to lost.
01418   // So, post-processing to establish minimality is required.
01419   
01420   cover.reserve(krow.getNumElements());
01421   remainder.reserve(krow.getNumElements());
01422 
01423   double unsatRhs = b;
01424 
01425   // working info on unsatisfied vars
01426   CoinPackedVector unsat;
01427   unsat.reserve(krow.getNumElements());
01428 
01429   // working info on vars with value one
01430   CoinPackedVector atOne;
01431   atOne.reserve(krow.getNumElements());
01432 
01433   // partition the (binary) variables in the canonical knapsack
01434   // into those at zero, those at fractions, and those at one. 
01435   // Note: no consideration given to whether variables are free
01436   // or fixed at binary values.
01437   // Note: continuous and integer vars have already been netted out
01438   // to derive the canonical knapsack form
01439   int i;
01440   for (i=0; i<krow.getNumElements(); i++){
01441 
01442     if (xstar[krow.getIndices()[i]] > onetol_){
01443       atOne.insert(krow.getIndices()[i],krow.getElements()[i]); 
01444       unsatRhs -= krow.getElements()[i];
01445     }   
01446     else if (xstar[krow.getIndices()[i]] >= epsilon_){
01447       unsat.insert(krow.getIndices()[i],krow.getElements()[i]) ;
01448     }
01449     else { 
01450       remainder.insert(krow.getIndices()[i],krow.getElements()[i]);
01451     }
01452   }
01453 
01454   // sort the indices of the unsat var in order of decreasing solution value
01455   CoinDecrSolutionOrdered decrSol(xstar);
01456   unsat.sort(decrSol);
01457   
01458 #ifdef CGL_DEBUG
01459   // sanity check
01460   for (i=1; i<unsat.getNumElements(); i++){
01461     double xstarim1= xstar[unsat.getIndices()[i-1]];
01462     double xstari= xstar[unsat.getIndices()[i]];
01463     assert( xstarim1 >= xstari );
01464   }
01465 #endif
01466 
01467   // get the largest coefficient among the unsatisfied variables   
01468   double bigCoef= 0.0;
01469   // double temp;
01470   int bigIndex = 0;
01471   for (i=0; i<unsat.getNumElements(); i++){
01472     if (unsat.getElements()[i]>bigCoef){
01473       bigCoef = unsat.getElements()[i];
01474       bigIndex = i;
01475     }
01476   }
01477   
01478   // initialize 
01479   i=0;
01480   double margin = unsatRhs;
01481   int gotCover=0;
01482   int j;
01483   
01484   // look in order through the unsatisfied vars which along with the 
01485   // the max element defines a cover
01486   while (i<unsat.getNumElements() && !gotCover){
01487     margin -= unsat.getElements()[i];
01488     
01489     // get the biggest row coef downstream in the given order   
01490     if (i == bigIndex){
01491       bigCoef = 0.0;
01492       bigIndex = 0;
01493       for (j=i+1; j<unsat.getNumElements(); j++){
01494         double temp = unsat.getElements()[j];
01495         if (temp > bigCoef ){
01496           bigCoef = temp;
01497           bigIndex = j;
01498         }
01499       }
01500     }
01501     
01502     if (bigCoef > margin+epsilon2_) gotCover = 1;
01503     i++;          
01504   }
01505 
01506   // J&E approach; get first single one element that fills the margin   
01507   if(gotCover){
01508     j=i;
01509     if (j<unsat.getNumElements()){ // need this "if" incase nUnsat=1   
01510       while (unsat.getElements()[j]< margin) {
01511         j++;
01512       }
01513       // switch members so that first nUnsat define the cover
01514       unsat.swap(i,j);
01515       i++;
01516     }
01517     
01518     // check that detected cover is violated 
01519     // (would we want to save incase it's violated later?)
01520     int nCover = i;
01521     double coverElementSum = 0.0;
01522     double coverXstarSum = 0.0;
01523     int k;
01524     for (k=0; k<nCover; k++){
01525       coverElementSum += unsat.getElements()[k];
01526       coverXstarSum +=  xstar[unsat.getIndices()[k]];
01527     }
01528     
01529     // Split the unsatisfied elements into those in the cover and those
01530     // not in the cover. The elements not in the cover are considered
01531     // remainders. Variables atOne belong to the cover
01532 
01533     // Test if the detected cover is violated
01534     if (coverXstarSum > (nCover-1) && coverElementSum > unsatRhs+epsilon2_){
01535       for (i=nCover; i<unsat.getNumElements(); i++) {
01536         remainder.insert(unsat.getIndices()[i],unsat.getElements()[i]);
01537       }
01538       unsat.truncate(nCover);
01539       cover = unsat;
01540       cover.append(atOne);
01541 
01542       for (k=nCover; k<cover.getNumElements(); k++){
01543         coverElementSum+=cover.getElements()[k];
01544         coverXstarSum+=xstar[cover.getIndices()[k]];
01545       }
01546       
01547       // Sanity check
01548       int size = cover.getNumElements() + remainder.getNumElements(); 
01549       int krowsize = krow.getNumElements();
01550       assert( size == krowsize );
01551       
01552       // Sort cover in terms of knapsack row coefficients   
01553       cover.sortDecrElement();
01554 
01555     // New!
01556     // We have a violated cover inequality.
01557     // Construct a -minimal- violated cover
01558     // by testing and potentially tossing smallest
01559     // elements 
01560     double oneLessCoverElementSum =
01561        coverElementSum - cover.getElements()[cover.getNumElements()-1];
01562     while (oneLessCoverElementSum > b){
01563       // move the excess cover member into the set of remainders
01564       remainder.insert(cover.getIndices()[cover.getNumElements()-1],
01565                        cover.getElements()[cover.getNumElements()-1]);
01566       cover.truncate(cover.getNumElements()-1);
01567       oneLessCoverElementSum -= cover.getElements()[cover.getNumElements()-1];
01568     }
01569   
01570 #ifdef PRINT_DEBUG
01571     if (coverXstarSum > (nCover-1) && coverElementSum > b){
01572       printf("John and Ellis: row %i has cover of size %i.\n",
01573              row,cover.getNumElements());
01574       //double sumCover = 0.0;
01575       for (i=0; i<cover.getNumElements(); i++){
01576         printf("index %i, element %g, xstar value % g \n",
01577                cover.getIndices()[i], cover.getElements()[i],
01578                xstar[cover.getIndices()[i]]);
01579       }
01580       printf("The b = %g, and the cover element sum is %g\n\n",b,cover.sum());
01581     }
01582 #endif
01583 
01584     }
01585     // if minimal cover is not violated, turn gotCover off
01586     else {
01587 //    printf("heuristically found minimal cover is NOT violated by current lp solution");
01588       gotCover = 0;
01589     }          
01590   }
01591 
01592   // If no minimal cover was found, pack it in   
01593   if (!gotCover || cover.getNumElements() < 2) {
01594     return -1;
01595   }
01596   
01597   return  1;
01598 }
01599 
01600 
01601 
01602 
01603 
01604 //-------------------------------------------------------------------
01605 // Find a "approx" John-and-Ellis Cover
01606 // (i.e. that this approximates John & Ellis code)
01607 //  Test to see if we generate the same covers, and lifted cuts
01608 // 
01609 // generates minimal covers, not necessarily violated ones.
01610 //-------------------------------------------------------------------
01611 int
01612 CglKnapsackCover::findJohnAndEllisCover(
01613      int row,
01614      CoinPackedVector & krow,
01615      double & b,
01616      double * xstar, 
01617      CoinPackedVector & fracCover,  
01618      CoinPackedVector & atOne,
01619      CoinPackedVector & remainder) const
01620 
01621 {
01622   // John Forrest and Ellis Johnson's approach as I see it.
01623   // RLH: They find a minimal cover on unsatisfied variables, 
01624   // which may not be violated by the solution to the lp relaxation
01625 
01626   // "functional before efficient" is my creed.
01627   
01628   // look at unstatisfied binary vars with nonzero row coefficients only
01629   // get row in canonical form (here krow is in canonical form)
01630   // if complement var, complement soln val too. (already done)
01631   // (*) sort in increasing value of soln val
01632   // track who is the biggest coef and it's index.
01633   // if biggest > adjRhs, skip row. Bad knapsack.
01634   // margin = adjRhs
01635   // idea: if (possibly compl) soln >= .5 round up, else round down
01636   // they do more, but that's the essence
01637   // go through the elements {
01638   // if round down, skip
01639   // if round up, add to element to cover. adjust margin 
01640   // if current element = biggest, then get next biggest
01641   // if biggest > marg, you've got a cover. stop looking               
01642   // else try next element in the loop
01643   // }       
01644   // (*)RLH: I'm going to sort in decreasing order of soln val
01645   // b/c var's whose soln < .5 in can. form get rounded down 
01646   // and skipped. If you can get a min cover of the vars
01647   // whose soln is >= .5, I believe this gives the same as J&E.
01648   // But if not, maybe I can get something more.
01649        
01650   // (**)By checking largest value left, they ensure a minimal cover
01651   // on the unsatisfied variables
01652      
01653   // if you have a cover
01654   // sort the elements to be lifted in order of their reduced costs.
01655   // lift in this order.
01656   // They lift down on variables at one, in a sequence-dependent manner.
01657   // Partion the variables into three sets: those in the cover, those 
01658   // not in the cover at value one, and those remaining.
01659   
01660   fracCover.reserve(krow.getNumElements());
01661   remainder.reserve(krow.getNumElements());
01662   atOne.reserve(krow.getNumElements());
01663 
01664   double unsatRhs = b;
01665 
01666   // working info on unsatisfied vars
01667   CoinPackedVector unsat;
01668   unsat.reserve(krow.getNumElements());
01669 
01670   // partition the (binary) variables in the canonical knapsack
01671   // into those at zero, those at fractions, and those at one. 
01672   // 
01673   // essentially, temporarily fix to one the free vars with lp soln value of
01674   // one by calculating the "unsatRhs". Call the result the "reduced krow".
01675   //
01676   // Note: continuous and integer vars, and variables fixed at 
01677   // binary values have already been netted out
01678   // in deriving the canonical knapsack form
01679   int i;
01680   for (i=0; i<krow.getNumElements(); i++){
01681 
01682     if (xstar[krow.getIndices()[i]] > onetol_){
01683       atOne.insert(krow.getIndices()[i],krow.getElements()[i]); 
01684       unsatRhs -= krow.getElements()[i];
01685     }   
01686     else if (xstar[krow.getIndices()[i]] >= epsilon_){
01687       unsat.insert(krow.getIndices()[i],krow.getElements()[i]) ;
01688     }
01689     else { 
01690       remainder.insert(krow.getIndices()[i],krow.getElements()[i]);
01691     }
01692   }
01693 
01694   // sort the indices of the unsat var in order of decreasing solution value
01695   CoinDecrSolutionOrdered decrSol(xstar);
01696   unsat.sort(decrSol);
01697   
01698 #ifdef CGL_DEBUG
01699   // sanity check
01700   for (i=1; i<unsat.getNumElements(); i++){
01701     double xstarim1 = xstar[unsat.getIndices()[i-1]];
01702     double xstari=  xstar[unsat.getIndices()[i]];
01703     assert( xstarim1 >= xstari );
01704   }
01705 #endif
01706 
01707   // get the largest coefficient among the unsatisfied variables   
01708   double bigCoef= 0.0;
01709   // double temp;
01710   int bigIndex = 0;
01711   for (i=0; i<unsat.getNumElements(); i++){
01712     if (unsat.getElements()[i]>bigCoef){
01713       bigCoef = unsat.getElements()[i];
01714       bigIndex = i;
01715     }
01716   }
01717   
01718   // initialize 
01719   i=0;
01720   double margin = unsatRhs;
01721   int gotCover=0;
01722   int j;
01723   
01724   // look in order through the unsatisfied vars which along with the 
01725   // the max element defines a cover
01726   while (i<unsat.getNumElements() && !gotCover){
01727     margin -= unsat.getElements()[i];
01728     
01729     // get the biggest row coef downstream in the given order   
01730     if (i == bigIndex){
01731       bigCoef = 0.0;
01732       bigIndex = 0;
01733       for (j=i+1; j<unsat.getNumElements(); j++){
01734         double temp = unsat.getElements()[j];
01735         if (temp > bigCoef ){
01736           bigCoef = temp;
01737           bigIndex = j;
01738         }
01739       }
01740     }
01741     
01742     if (bigCoef > margin+epsilon2_) gotCover = 1;
01743     i++;          
01744   }
01745 
01746   // J&E approach; get first single one element that fills the margin   
01747   if(gotCover){ 
01748     j=i;
01749     if (j<unsat.getNumElements()){ // need this "if" incase nUnsat=1   
01750       while (unsat.getElements()[j]< margin) {
01751         j++;
01752       }
01753       // switch members so that first nUnsat define the cover
01754       unsat.swap(i,j);
01755       i++;
01756     }
01757     
01758     // DEBUG: verify we have a cover over the reduced krow
01759     // (may not be violated)
01760     int nCover = i;
01761     double coverElementSum = 0.0;
01762     int k;
01763     for (k=0; k<nCover; k++){
01764       coverElementSum += unsat.getElements()[k];
01765     }
01766     
01767     // Split the unsatisfied elements into those in the "reduced krow" cover
01768     // and those not in the cover. The elements not in the cover are
01769     // considered remainders. Variables atOne are reported as atOne.
01770 
01771 
01772     // Test if the detected cover is violated
01773     if (coverElementSum > unsatRhs+epsilon2_){
01774       for (i=nCover; i<unsat.getNumElements(); i++) {
01775         remainder.insert(unsat.getIndices()[i],unsat.getElements()[i]);
01776       }
01777       unsat.truncate(nCover);
01778       fracCover = unsat;
01779       // cover.append(atOne);
01780 
01781       // Sanity check
01782       int size = (fracCover.getNumElements() + remainder.getNumElements() +
01783                   atOne.getNumElements());
01784       int krowsize =  krow.getNumElements();
01785       assert( size == krowsize );
01786       
01787       // Sort cover in terms of knapsack row coefficients   
01788       fracCover.sortDecrElement();
01789 
01790     // We have a not-necessarily-violated "reduced krow" cover inequality.
01791     // Minimal on the "reduced krow" 
01792 
01793 #if 0
01794       
01795       double oneLessCoverElementSum =
01796          coverElementSum-fracCover.getElements()[fracCover.getNumElements()-1];
01797       while (oneLessCoverElementSum > b){
01798         // move the excess cover member into the set of remainders
01799         remainder.insert(fracCover.getIndices()[fracCover.getNumElements()-1],
01800                          fracCover.getElements()[fracCover.getNumElements()-1]);
01801         fracCover.truncate(fracCover.getNumElements()-1);
01802         oneLessCoverElementSum -=
01803            fracCover.getElements()[fracCover.getNumElements()-1];
01804       }
01805 #endif
01806   
01807 #ifdef PRINT_DEBUG
01808       printf("More Exactly John and Ellis:");
01809       printf(" row %i has -reduced--fractional- cover of size %i.\n",
01810              row,fracCover.getNumElements());
01811       double sumFracCover = 0.0;
01812       for (i=0; i<fracCover.getNumElements(); i++){
01813         printf("index %i, element %g, xstar value % g \n",
01814                fracCover.getIndices()[i],fracCover.getElements()[i],
01815                xstar[fracCover.getIndices()[i]]);
01816         sumFracCover += fracCover.getElements()[i];
01817       }
01818       double sumAtOne = 0.0;
01819       printf("There are %i variables at one:\n",atOne.getNumElements());
01820       for (i=0; i<atOne.getNumElements(); i++){
01821         printf("index %i, element %g, xstar value % g \n",
01822                atOne.getIndices()[i],atOne.getElements()[i],
01823                xstar[atOne.getIndices()[i]]);
01824         sumAtOne += atOne.getElements()[i];
01825       }
01826       printf("The b = %g, sumAtOne = %g, unsatRhs = b-sumAtOne = %g, ",
01827              b, sumAtOne, unsatRhs);
01828       printf("and the (fractional) cover element sum is %g\n\n", sumFracCover);
01829 #endif
01830 
01831     }
01832     // if minimal cover is not violated, turn gotCover off
01833     else {
01834 //    printf("heuristically found minimal cover is NOT violated by current lp solution");
01835       gotCover = 0;
01836     }          
01837   }
01838 
01839   // If no minimal cover was found, pack it in   
01840   //  if (!gotCover || cover.getNumElements() < 2) {
01841   if (!gotCover) {
01842     return -1;
01843   }
01844   
01845   return  1;
01846 }
01847 
01848 //-------------------------------------------------------------------
01849 // findGreedyCover: attempts to find a violated minimal
01850 //                  cover using a greedy approach
01851 //
01852 // If a cover is found, it the cover and the remainder are 
01853 // sorted in nonincreasing order of the coefficients.
01854 //-------------------------------------------------------------------
01855 int
01856 CglKnapsackCover::findGreedyCover(
01857      int row,
01858      CoinPackedVector & krow,
01859      double & b,
01860      double * xstar,
01861      CoinPackedVector & cover,
01862      CoinPackedVector & remainder
01863      ) const
01864   // the row argument is a hold over from debugging
01865   // ToDo: move the print cover statement out to the mainprogram 
01866   // and remove the row argument
01867 
01868 { 
01869   int i;
01870   int gotCover =0;
01871   
01872   cover.reserve(krow.getNumElements());
01873   remainder.reserve(krow.getNumElements());
01874   
01875   // sort knapsack in non-increasing size of row Coefficients 
01876   krow.sortDecrElement();  
01877   
01878   // greedily pack them in 
01879   // looking only at unsatisfied vars, i.e. 0<xstar[.]<1 
01880   double greedyElementSum = 0.0;
01881   double greedyXstarSum = 0.0;
01882   
01883   for (i=0;i<krow.getNumElements();i++){
01884     // if xstar fractional && no cover yet, consider it for the cover 
01885     if (xstar[krow.getIndices()[i]] >= epsilon_ &&
01886         xstar[krow.getIndices()[i]] <= onetol_ &&
01887         !gotCover){
01888       greedyElementSum += krow.getElements()[i];
01889       greedyXstarSum += xstar[krow.getIndices()[i]];
01890       cover.insert(krow.getIndices()[i],krow.getElements()[i]);
01891       if (greedyElementSum > b+epsilon2_){
01892         gotCover = 1;
01893       }
01894     }
01895     else{
01896       remainder.insert(krow.getIndices()[i],krow.getElements()[i]);
01897     }
01898   }
01899   
01900   // sanity check
01901   int size =  remainder.getNumElements()+cover.getNumElements();
01902   int krowsize = krow.getNumElements();
01903   assert( size==krowsize );
01904   
01905   // if no violated minimal cover was found, pack it in 
01906   if ( (greedyXstarSum<=(cover.getNumElements()-1)+epsilon2_) ||
01907        (!gotCover) ||
01908        (cover.getNumElements() < 2)){
01909     return -1;
01910   }
01911   
01912 #ifdef PRINT_DEBUG 
01913   printf("Greedy cover: row %i has cover of size %i\n",
01914          row,cover.getNumElements());
01915   for (i=0; i<cover.getNumElements(); i++){
01916     printf("index %i, element %g, xstar value % g \n", 
01917            cover.getIndices()[i], cover.getElements()[i],
01918            xstar[cover.getIndices()[i]]);
01919   }
01920   printf("The b = %g, and the cover sum is %g\n\n", b, greedyElementSum);
01921 #endif
01922 
01923   return  1;
01924 }
01925 
01926 //------------------------------------------------------------- 
01927 // Lift Up, Down, and Uncomplement. Add the resutling cut to the cutset
01928 //
01929 // In the solution to the lp relaxtion, 
01930 // the binary variable's solution value is either 0, 1 or fractional.
01931 //
01932 // Input:
01933 // The variables in fracCover form a cover, when the vars atOne take value one.
01934 // A cover for the krow would consist of the union of the fracCover and atOne vars
01935 // (which may not be violated, and may need to be processed to acheieve minimal-ness).
01936 //
01937 // Rather than take the "union" cover and lift up the remainder variables, 
01938 // we do something a little bit more interesting with the vars at one.
01939 //
01940 // The ip theory says that the lifted minimal cover cut can be strengthen by
01941 // "lifting down" the vars atOne.
01942 // -- this is what I believe John&Ellis were doing in OSL's knapsack cover cuts
01943 //    with a lifting heuristic.
01944 //
01945 //-------------------------------------------------------------------
01946 void 
01947 CglKnapsackCover::liftUpDownAndUncomplementAndAdd(
01948          int nCols,
01949          double * xstar, 
01950          int * complement,
01951          int row,
01952          int nRowElem,
01953          double & b,
01954 
01955          // the following 3 packed vectors partition the krow:
01956 
01957          // vars have frac soln values in lp relaxation
01958          // and form cover with the vars atOne
01959          CoinPackedVector & fracCover, 
01960          // vars have soln value of 1 in lp relaxation
01961          CoinPackedVector & atOne,
01962          // and together with fracCover form minimal (?) cover. 
01963          CoinPackedVector & remainder,
01964 
01965          OsiCuts & cs ) const
01966 {
01967   CoinPackedVector cut;
01968 
01969   // reserve storage for the cut
01970   cut.reserve(nRowElem);
01971   
01972   // the cut coefficent for the members of the cover is 1.0
01973   cut.setConstant(fracCover.getNumElements(),fracCover.getIndices(),1.0);
01974   
01975   // Preserve the cutRhs which is |C|-1, where |C| is the size of the
01976   // fracCover.
01977   double cutRhs=fracCover.getNumElements()-1;
01978 
01979   // local variables
01980   // unsatRhs is the rhs for the reduced krow
01981   double unsatRhs = 0, sumAtOne = 0;
01982   int i;
01983   for (i=0; i<atOne.getNumElements(); i++){
01984     sumAtOne += atOne.getElements()[i];
01985   }
01986   unsatRhs=b-sumAtOne;
01987   int firstFrac = fracCover.getIndices()[0];
01988   if (unsatRhs<=0.0&&fabs(xstar[firstFrac])>epsilon2_) {
01989     printf("At one %d\n",atOne.getNumElements());
01990     for (i=0; i<atOne.getNumElements(); i++){
01991       int iColumn = atOne.getIndices()[i];
01992       printf("%d %g %g\n",atOne.getIndices()[i],atOne.getElements()[i],
01993              xstar[iColumn]);
01994     }
01995     printf("frac %d\n",fracCover.getNumElements());
01996     for (i=0; i<fracCover.getNumElements(); i++){
01997       int iColumn = fracCover.getIndices()[i];
01998       printf("%d %g %g\n",fracCover.getIndices()[i],fracCover.getElements()[i],
01999              xstar[iColumn]);
02000     }
02001   }
02002   //assert ( unsatRhs > 0 );
02003 
02004   // If there is something to lift, then calculate the lifted coefficients
02005   if (unsatRhs>0.0&&(remainder.getNumElements()+atOne.getNumElements())> 0){
02006     
02007     // What order to lift?
02008     // Take the remainder vars in decreasing order of their
02009     // xstar solution value. Sort remainder in order of decreasing 
02010     // xstar value.
02011     // Lift them "up"
02012     // (The lift "down" the variables atOne.
02013     CoinDecrSolutionOrdered dso1(xstar);
02014     remainder.sort(dso1);   
02015     
02016     // a is the part of krow corresponding to vars which have been lifted
02017     // alpha are the lifted coefficients with explicit storage of lifted zero
02018     // coefficients the a.getIndices() and alpha.getIndices() are identical
02019     CoinPackedVector a(fracCover);
02020     CoinPackedVector alpha;
02021     int i;
02022     for (i=0; i<fracCover.getNumElements(); i++){
02023       alpha.insert(fracCover.getIndices()[i],1.0);
02024     }
02025     // needed as an argument for exactSolveKnapsack
02026     int * x = new int[nRowElem];
02027     double psi_j=0.0;
02028     
02029     // Order alpha and a in nonincreasing order of alpha_j/a_j.  
02030     // alpha_1/a_1 >= alpha_2/a_2 >= ... >= alpha_n/a_n   
02031     // by defining this full-storage array "ratio" to be the external sort key.
02032     // right now external sort key must be full-storage.
02033 
02034     double * ratio= new double[nCols];
02035     memset(ratio, 0, (nCols*sizeof(double)));
02036     double alphasize = alpha.getNumElements();
02037     double asize = a.getNumElements();
02038     assert( alphasize == asize );
02039     
02040     for (i=0; i<a.getNumElements(); i++){
02041       if (fabs(a.getElements()[i])> epsilon_ ){
02042         ratio[a.getIndices()[i]]=alpha.getElements()[i]/a.getElements()[i];
02043       }
02044       else {
02045         ratio[a.getIndices()[i]] = 0.0;
02046       }
02047     }
02048 
02049     CoinDecrSolutionOrdered dso2(ratio);
02050     a.sort(dso2);   
02051     alpha.sort(dso2);
02052     
02053 #ifdef CGL_DEBUG
02054     // sanity check
02055     for ( i=1; i<a.getNumElements(); i++ ) {
02056       int alphai=  alpha.getIndices()[i];
02057       int ai = a.getIndices()[i];
02058       assert( alphai == ai);
02059     }  
02060 #endif  
02061     
02062     // Loop through the remainder variables to be lifted "up", and lift.
02063     int j;
02064     for (j=0; j<remainder.getNumElements(); j++){
02065       // calculate the lifted coefficient of x_j = cutRhs-psi_j
02066       // where 
02067       // psi_j =  max of the current lefthand side of the cut
02068       //          s.t. the reduced knapsack corresponding to vars that have
02069       //          been lifted <= unsatRhs-a_j
02070       
02071       // Note: For exact solve, must be sorted in
02072       // alpha_1/a_1>=alpha_2/a_2>=...>=alpha_n/a_n order
02073       // check if lifted var can take value 1 
02074       if (unsatRhs - remainder.getElements()[j] < epsilon_){
02075         psi_j = cutRhs;
02076       }
02077       else {      
02078         exactSolveKnapsack(alpha.getNumElements(),
02079                  unsatRhs-remainder.getElements()[j],
02080                  alpha.getElements(),a.getElements(),psi_j,x);
02081       }
02082       
02083       // assert the new coefficient is nonegative?
02084       alpha.insert(remainder.getIndices()[j],cutRhs-psi_j);
02085       a.insert(remainder.getIndices()[j],remainder.getElements()[j]);
02086       
02087       // if the lifted coefficient is non-zero 
02088       // (i.e. psi_j != cutRhs), add it to the cut
02089       if (fabs(cutRhs-psi_j)>epsilon_)
02090          cut.insert(remainder.getIndices()[j],cutRhs-psi_j);
02091       
02092       ratio[remainder.getIndices()[j]]=
02093          (cutRhs-psi_j)/remainder.getElements()[j];
02094       CoinDecrSolutionOrdered dso(ratio);
02095       a.sort(dso);   
02096       alpha.sort(dso);    
02097     }
02098 
02099     // Loop throught the variables atOne and lift "down"
02100     for (j=0; j<atOne.getNumElements(); j++){
02101       // calculate the lifted coefficient of x_j = psi_j-cutRhs (now cutRhs
02102       // gets updated) where 
02103       // psi_j =  max of the current lefthand side of the cut
02104       //          s.t. the reduced knapsack corresponding to vars that have
02105       //          been lifted <= unsatRhs+a_j 
02106       
02107       // Note: For exact solve, must be sorted in
02108       // alpha_1/a_1>=alpha_2/a_2>=...>=alpha_n/a_n order 
02109       exactSolveKnapsack(alpha.getNumElements(),
02110                          unsatRhs+atOne.getElements()[j],
02111                          alpha.getElements(),a.getElements(),psi_j,x);
02112       alpha.insert(atOne.getIndices()[j],psi_j-cutRhs);
02113       a.insert(atOne.getIndices()[j],atOne.getElements()[j]);
02114       // if the lifted coefficient is non-zero (i.e. psi_j != cutRhs), add it
02115       // to the cut 
02116       if (fabs(psi_j-cutRhs)>epsilon_)
02117          cut.insert(atOne.getIndices()[j],psi_j-cutRhs);
02118 
02119 #ifdef CGL_DEBUG
02120       assert ( fabs(atOne.getElements()[j])> epsilon_ );
02121 #else
02122       if ( fabs(atOne.getElements()[j])<= epsilon_ ) {
02123         // exit gracefully
02124         cutRhs = DBL_MAX;
02125         break;
02126       }
02127 #endif
02128       ratio[atOne.getIndices()[j]]=(psi_j-cutRhs)/atOne.getElements()[j];
02129 
02130       // update cutRhs and unsatRhs
02131       cutRhs = psi_j ;      
02132       unsatRhs += atOne.getElements()[j];
02133 
02134       CoinDecrSolutionOrdered dso(ratio);
02135       a.sort(dso);   
02136       alpha.sort(dso);    
02137     }
02138     delete [] x;
02139     delete [] ratio;
02140   }
02141 
02142   // If the cut is violated, add it to the pool
02143   // if (sum over cut.getIndices())
02144   //    cut.element()*xstar > cover.getNumElements()-1, un-complement
02145   // and add it to the pool.
02146   double sum=0;
02147   for (i=0; i<cut.getNumElements(); i++){
02148     sum+= cut.getElements()[i]*xstar[cut.getIndices()[i]];
02149   }
02150   if (sum > cutRhs+epsilon2_){
02151 #ifdef PRINT_DEBUG
02152     printf("Sequentially lifted UpDown cover cut of ");
02153     printf("size %i derived from fracCover of size %i.\n",
02154            cut.getNumElements(), fracCover.getNumElements());
02155     for (i=0; i<cut.getNumElements(); i++){
02156       printf("index %i, element %g, xstar value % g \n",
02157              cut.getIndices()[i],cut.getElements()[i],
02158              xstar[cut.getIndices()[i]]);
02159     }
02160     printf("The cutRhs = %g, and the alpha_j*xstar_j sum is %g\n\n",
02161            cutRhs, sum);
02162 #endif
02163     
02164     // de-complement
02165     int k;
02166     const int s = cut.getNumElements();
02167     const int * indices = cut.getIndices();
02168     double * elements = cut.getElements();
02169     for (k=0; k<s; k++){
02170       if (complement[indices[k]]) {
02171         // Negate the k'th element in packedVector cut
02172         // and correspondingly adjust the rhs
02173         elements[k] *= -1;
02174         cutRhs += elements[k];
02175       }
02176     }
02177     
02178    
02179     // Create row cut
02180     OsiRowCut rc;
02181     rc.setRow(cut);
02182 #ifdef CGL_DEBUG
02183     {
02184       double * elements = cut.getElements();
02185       int * indices = cut.getIndices();
02186       int n=cut.getNumElements();
02187       for (k=0; k<n; k++){
02188         assert(indices[k]>=0);
02189         assert(elements[k]);
02190       }
02191     }
02192 #endif
02193     rc.setLb(-DBL_MAX);
02194     rc.setUb(cutRhs);
02195     // ToDo: what's the default effectiveness?
02196     //  rc.setEffectiveness(1.0);
02197     // Add row cut to the cut set  
02198 #ifdef PRINT_DEBUG
02199     {
02200       int k;
02201       printf("cutrhs %g %d elements\n",cutRhs,cut.getNumElements());
02202       double * elements = cut.getElements();
02203       int * indices = cut.getIndices();
02204       for (k=0; k<cut.getNumElements(); k++){
02205         printf("%d %g\n",indices[k],elements[k]);
02206       }
02207     }
02208 #endif
02209     cs.insert(rc);
02210   }
02211 }
02212 
02213 //-------------------------------------------------------------------
02214 // seqLiftCoverCut:  Given a canonical knapsack inequality and a
02215 //                cover, performs sequence-dependent lifting.
02216 //                Reference: Nemhauser & Wolsey
02217 //
02218 // NW suggest a lifting heuristic order that requires an argmax operation.
02219 // What's the strength vs performance tradeoff of using argmax over
02220 // a heuristic that depends soley on an a-prioi ordering based on
02221 // the optimal solution to the lp relaxation? ToDo:  Do both, and report.
02222 //
02223 //-------------------------------------------------------------------
02224 void
02225 CglKnapsackCover::seqLiftAndUncomplementAndAdd(
02226       int nCols,
02227       double * xstar, 
02228       int * complement,
02229       int row,                       // row index number: used for debugging 
02230                                      //     and to index into row bounds
02231       int nRowElem,                  // number of elements in the row, aka row
02232                                      //     size, row length. 
02233       double & b,                    // rhs of the canonical knapsack
02234                                      //     inequality derived from row 
02235       CoinPackedVector & cover,       // need not be violated
02236       CoinPackedVector & remainder,
02237       OsiCuts & cs) const
02238 {
02239   CoinPackedVector cut;
02240   
02241   // reserve storage for the cut
02242   cut.reserve(nRowElem);
02243   
02244   // the cut coefficent for the members of the cover is 1.0
02245   cut.setConstant(cover.getNumElements(),cover.getIndices(),1.0);
02246   
02247   // so preserve the cutRhs which is |C|-1, where |C| is the size of the cover.
02248   double cutRhs=cover.getNumElements()-1;
02249   
02250   // If there is something to lift, then calcualte the lifted coefficients
02251   if (remainder.getNumElements()> 0){
02252     
02253     // What order to lift?
02254     // Take the to-be-lifted vars in decreasing order of their
02255     // xstar solution value. Sort remainder in order of decreasing 
02256     // xstar value.
02257     CoinDecrSolutionOrdered dso1(xstar);
02258     remainder.sort(dso1);   
02259     
02260     // a is the part of krow corresponding to vars which have been lifted
02261     // alpha are the lifted coefficients with explicit storage of lifted zero
02262     // coefficients the a.getIndices() and alpha.getIndices() are identical
02263     CoinPackedVector a(cover);
02264     CoinPackedVector alpha;
02265     int i;
02266     for (i=0; i<cover.getNumElements(); i++){
02267       alpha.insert(cover.getIndices()[i],1.0);
02268     }
02269     // needed as an argument for exactSolveKnapsack
02270     int * x = new int[nRowElem]; 
02271     double psi_j=0.0;
02272     
02273     // Order alpha and a in nonincreasing order of alpha_j/a_j.  
02274     // alpha_1/a_1 >= alpha_2/a_2 >= ... >= alpha_n/a_n   
02275     // by defining this full-storage array "ratio" to be the external sort key.
02276     
02277     double * ratio= new double[nCols];
02278     memset(ratio, 0, (nCols*sizeof(double)));
02279     int alphasize =  alpha.getNumElements();
02280     int asize = a.getNumElements();
02281     assert( alphasize == asize );
02282     
02283     for (i=0; i<a.getNumElements(); i++){
02284       if (fabs(a.getElements()[i])> epsilon_ ){
02285         ratio[a.getIndices()[i]]=alpha.getElements()[i]/a.getElements()[i];
02286       }
02287       else {
02288         ratio[a.getIndices()[i]] = 0.0;
02289       }
02290     }
02291     
02292     // ToDo: would be nice to have sortkey NOT be full-storage vector
02293     CoinDecrSolutionOrdered dso2(ratio);
02294     // RLH:  JP, Is there a more efficient way?
02295     // The sort is identical for a and alpha, but I'm having to sort twice
02296     // here, and at every iteration in the loop below.
02297     a.sort(dso2);   
02298     alpha.sort(dso2);
02299     
02300 #ifdef CGL_DEBUG
02301     // sanity check
02302     for ( i=1; i<a.getNumElements(); i++ ) {
02303       int alphai= alpha.getIndices()[i];
02304       int ai = a.getIndices()[i];
02305       assert( alphai == ai);
02306     }  
02307 #endif  
02308     
02309     // Loop through the variables to be lifted, and lift.
02310     int j;
02311     for (j=0; j<remainder.getNumElements(); j++){
02312       // calculate the lifted coefficient of x_j = cutRhs-psi_j
02313       // where psi_j =  max of the current lefthand side of the cut
02314       // s.t. the knapsack corresponding to vars that have been lifted <= b-a_j
02315       
02316       // Note: For exact solve, must be sorted in
02317       // alpha_1/a_1>=alpha_2/a_2>=...>=alpha_n/a_n order
02318       exactSolveKnapsack(alpha.getNumElements(),
02319                          b-remainder.getElements()[j],
02320                          alpha.getElements(),a.getElements(),psi_j,x);
02321       alpha.insert(remainder.getIndices()[j],cutRhs-psi_j);
02322       a.insert(remainder.getIndices()[j],remainder.getElements()[j]);
02323       // if the lifted coefficient is non-zero (i.e. psi_j != cutRhs), add it
02324       // to the cut 
02325       if (fabs(cutRhs-psi_j)>epsilon_)
02326          cut.insert(remainder.getIndices()[j],cutRhs-psi_j);
02327       
02328       ratio[remainder.getIndices()[j]]=
02329          (cutRhs-psi_j)/remainder.getElements()[j];
02330       CoinDecrSolutionOrdered dso(ratio);
02331       a.sort(dso);   
02332       alpha.sort(dso);    
02333     }
02334     delete [] x;
02335     delete [] ratio;
02336   }
02337 
02338   // If the cut is violated, add it to the pool
02339   // if (sum over cut.getIndices())
02340   //    cut.element()*xstar > cover.getNumElements()-1, un-complement
02341   // and add it to the pool.
02342   double sum=0;
02343   int i;
02344   for (i=0; i<cut.getNumElements(); i++){
02345     sum+= cut.getElements()[i]*xstar[cut.getIndices()[i]];
02346   }
02347   if (sum > cutRhs+epsilon2_){
02348 #ifdef PRINT_DEBUG
02349     printf("Sequentially lifted cover cut of size %i derived from cover of size %i.\n",cut.getNumElements(), cover.getNumElements());
02350     for (i=0; i<cut.getNumElements(); i++){
02351       printf("index %i, element %g, xstar value % g \n", cut.getIndices()[i],cut.getElements()[i], xstar[cut.getIndices()[i]]);
02352     }
02353     printf("The cutRhs = %g, and the alpha_j*xstar_j sum is %g\n\n", cutRhs, sum);
02354 #endif
02355     
02356     int k;
02357     const int s = cut.getNumElements();
02358     const int * indices = cut.getIndices();
02359     double * elements = cut.getElements();
02360     for (k=0; k<s; k++){
02361       if (complement[indices[k]]) {
02362         // Negate the k'th element in packedVector cut
02363         // and correspondingly adjust the rhs
02364         elements[k] *= -1;
02365         cutRhs += elements[k];
02366       }
02367     }
02368     
02369     // Create a row cut and add it to the cut set
02370     OsiRowCut rc;
02371     rc.setRow(cut);
02372 #ifdef CGL_DEBUG
02373     {
02374       double * elements = cut.getElements();
02375       int * indices = cut.getIndices();
02376       int n=cut.getNumElements();
02377       for (k=0; k<n; k++){
02378         assert(indices[k]>=0);
02379         assert(elements[k]);
02380       }
02381     }
02382 #endif
02383     rc.setLb(-DBL_MAX);
02384     rc.setUb(cutRhs);
02385     // ToDo: what's a meaningful effectivity?
02386     //  rc.setEffectiveness(1.0);
02387 #ifdef PRINT_DEBUG
02388     {
02389       int k;
02390       printf("cutrhs %g\n",cutRhs);
02391       double * elements = cut.getElements();
02392       int * indices = cut.getIndices();
02393       for (k=0; k<cut.getNumElements(); k++){
02394         printf("%d %g\n",indices[k],elements[k]);
02395       }
02396     }
02397 #endif
02398     cs.insert(rc);
02399   }
02400 }
02401 
02402 //-------------------------------------------------------------------
02403 // liftCoverCut:  Given a canonical knapsack inequality and a
02404 //                cover, constructs a lift cover cut via
02405 //                sequence-independent lifting.
02406 //-------------------------------------------------------------------
02407 int
02408 CglKnapsackCover::liftCoverCut(
02409       double & b,
02410       int nRowElem,
02411       CoinPackedVector & cover,
02412       CoinPackedVector & remainder,
02413       CoinPackedVector & cut) const
02414 {
02415   int i;
02416   int  goodCut=1;
02417   // Given knapsack ax <=b, and a cover (e.g. cover corresponds to {0,...,nCover-1})
02418   // coverIndices are assumed in nondecr order of coverElements   
02419   // a_0>=a_1>=...>=a_(nCover-1)   
02420 
02421   // TODO: right now if the lifted coefficient is zero, 
02422   // then it's still in the cut. 
02423   // Should not carry explicit zero coefficients 
02424 
02425   // Calculate the sum of the knapsack coefficients of the cover variables 
02426   double sum = cover.sum();
02427 
02428   // Define lambda to be the "cover excess". 
02429   // By definition, lambda > 0. If this is not the case, something's screwy. Exit gracefully.
02430   double lambda = sum-b;
02431   if (lambda < epsilon_) {
02432 #ifdef PRINT_DEBUG
02433     printf("lambda < epsilon....aborting. \n");
02434     std::cout << "lambda " << lambda << " epsilon " << epsilon_ << std::endl;
02435     //abort();
02436     goodCut=0;
02437 #else
02438     //std::cout << "lambda " << lambda << " exiting" << std::endl;
02439     goodCut=0;
02440 #endif
02441   }
02442 
02443   // mu is vector of partial sums: 
02444   //   mu[i] = sum(j=0 to i) a_j where the cover is C={0,1,..,r}
02445   //   mu[0] = 0, mu[1]=a_0, mu[2]=a_0+a_1, etc.
02446   //   and C is assumed to be sorted in nondecreasing knapsack coefficient order.
02447   double * mu= new double[cover.getNumElements()+1];
02448   double * muMinusLambda= new double[cover.getNumElements()+1];
02449   memset(mu, 0, (cover.getNumElements()+1)*sizeof(double));
02450   memset(muMinusLambda, 0, (cover.getNumElements()+1)*sizeof(double));
02451   
02452   // mu[0] = 0, mu[1]= knapsack coef of cover element 0, etc.
02453   muMinusLambda[0]= -lambda;
02454   for(i=1; i<(cover.getNumElements()+1); i++){
02455     mu[i]=mu[i-1]+ cover.getElements()[i-1];
02456     muMinusLambda[i]=mu[i]-lambda;
02457   }
02458 
02459   cut.reserve(nRowElem);
02460 
02461   // the cut coefficent for the members of the cover is 1.0
02462   cut.setConstant(cover.getNumElements(),cover.getIndices(),1.0);
02463   
02464   // if f(z) is superadditive 
02465   int h;
02466   if (muMinusLambda[1] >= cover.getElements()[1]-epsilon_){
02467     for (h=0; h<remainder.getNumElements(); h++){
02468       if (remainder.getElements()[h] <= muMinusLambda[1]){
02469         // cutCoef[nCut] is 0, so don't bother storing 
02470       }    
02471       else{  
02472         // Todo: searching is inefficient. sort not in cover... 
02473         // change so that I sort remainder before the call to lift.
02474         int found=0;
02475         i=2;
02476         while (!found && i<(cover.getNumElements()+1)){
02477           if (remainder.getElements()[h] <= muMinusLambda[i]+epsilon_){
02478             bool e = cut.isExistingIndex(remainder.getIndices()[h]);
02479             assert( !e );
02480             cut.insert( remainder.getIndices()[h], i-1.0 );
02481             found=1;
02482           }
02483           i++;
02484         }
02485         if (!found) {
02486 #ifdef CGL_DEBUG
02487           printf("Error: Unable to fix lifted coefficient\n");
02488           abort();
02489 #else
02490           goodCut=0;
02491 #endif
02492         }
02493       } // end else 
02494     }// end for each j not in C 
02495   } // end if f superadditive 
02496 
02497   // else use superadditive function g 
02498   else {
02499     double * rho= new double[cover.getNumElements()];
02500     rho[0]=lambda;
02501     for (i=1; i<cover.getNumElements(); i++){
02502       rho[i]=CoinMax(0.0, cover.getElements()[i]- muMinusLambda[1]);
02503     }
02504     
02505     int h;
02506     for (h=0; h<remainder.getNumElements(); h++){
02507       
02508       int found=0; // Todo: searcing is inefficient: sort...
02509       i=0;
02510       while(!found && i<cover.getNumElements()){
02511         if (remainder.getElements()[h] <= muMinusLambda[i+1]+epsilon_){
02512           bool notE = !cut.isExistingIndex(remainder.getIndices()[h]);
02513           assert( notE );
02514           if (i)
02515             cut.insert( remainder.getIndices()[h], (double)i );
02516           found=1;
02517         }
02518         else if (remainder.getElements()[h] < muMinusLambda[i+1]+rho[i+1]){
02519           bool notE = !cut.isExistingIndex(remainder.getIndices()[h]); 
02520           assert( notE );
02521           double cutCoef = i+1 
02522               - (muMinusLambda[i+1]+rho[i+1]-remainder.getElements()[h])/rho[1];    
02523           if (fabs(cutCoef)>epsilon_)
02524             cut.insert( remainder.getIndices()[h], cutCoef );
02525           found=1;
02526         }
02527         i++;
02528       } // endwhile 
02529     } // end for j not in C
02530     delete [] rho;
02531   } // end else use g 
02532 
02533   delete [] muMinusLambda;
02534   delete [] mu;
02535 
02536   return goodCut;
02537 }
02538 
02539 //-------------------------------------------------------------------
02540 // A goto-less implementation of the Horowitz-Sahni exact solution 
02541 // procedure for solving knapsack problem.
02542 //
02543 // Reference: Martello and Toth, Knapsack Problems, Wiley, 1990, p30-31.
02544 //
02545 // ToDo: Implement a dynamic programming appraoch for case
02546 //       of knapsacks with integral coefficients
02547 //-------------------------------------------------------------------
02548 int
02549 CglKnapsackCover::exactSolveKnapsack(
02550        int n, 
02551        double c, 
02552        double const *pp, 
02553        double const *ww, 
02554        double & z, 
02555        int * x) const
02556 {
02557   // The knapsack problem is to find:
02558 
02559   // max {sum(j=1,n) p_j*x_j st. sum (j=1,n)w_j*x_j <= c, x binary}
02560 
02561   // Notation:
02562   //     xhat : current solution vector
02563   //     zhat : current solution value = sum (j=1,n) p_j*xhat_j
02564   //     chat : current residual capacity = c - sum (j=1,n) w_j*xhat_j
02565   //     x    : best solution so far, n-vector.
02566   //     z    : value of the best solution so far =  sum (j=1,n) p_j*x_j
02567      
02568 
02569   // Input: n, the number of variables; 
02570   //        c, the rhs;
02571   //        p, n-vector of objective func. coefficients;
02572   //        w, n-vector of the row coeff.
02573 
02574   // Output: z, the optimal objective function value;
02575   //         x, the optimal (binary) solution n-vector;
02576 
02577   // Assumes items are sorted  p_1/w_1 >= p_2/w_2 >= ... >= p_n/w_n
02578   
02579   memset(x, 0, (n)*sizeof(int));
02580   int * xhat = new int[n+1];
02581   memset(xhat, 0, (n+1)*sizeof(int));
02582   int j;
02583 
02584   // set up: adding the extra element and
02585   // accounting for the FORTRAN vs C difference in indexing arrays.
02586   double * p = new double[n+2];
02587   double * w = new double[n+2];
02588   int ii;
02589   for (ii=1; ii<n+1; ii++){
02590     p[ii]=pp[ii-1];
02591     w[ii]=ww[ii-1];
02592   }
02593 
02594   // 1. initialize 
02595   double zhat = 0.0;
02596   z = 0.0;
02597   double chat = c+epsilon2_;
02598   p[n+1] = 0.0;
02599   w[n+1]= DBL_MAX;
02600   j=1;
02601 
02602   while (1){
02603     // 2. compute upper bound u
02604     // "find r = min {i: sum k=j,i w_k>chat};"
02605     ii=j;
02606     double wSemiSum = w[j];
02607     double pSemiSum = p[j];
02608     while (wSemiSum <= chat && ii<n+2){
02609       ii++;
02610       wSemiSum+=w[ii];
02611       pSemiSum+=p[ii];
02612     }
02613     if (ii==n+2){
02614       printf("Exceeded iterator limit. Aborting...\n");
02615       abort();
02616     }
02617     // r = ii at this point 
02618     wSemiSum -= w[ii];
02619     pSemiSum -= p[ii];
02620     double u = pSemiSum + floor((chat - wSemiSum)*p[ii]/w[ii]);
02621     
02622     // "if (z >= zhat + u) goto 5: backtrack;"
02623     if (!(z >= zhat + u)) {
02624       do {
02625         // 3. perform a forward step 
02626         while (w[j] <= chat){
02627           chat = chat - w[j];
02628           zhat = zhat + p[j];
02629           xhat[j] = 1;
02630           j+=1;
02631         }
02632         if (j<=n) {
02633           xhat[j]= 0;
02634           j+=1;
02635         }
02636       } while(j==n); 
02637 
02638       // "if (j<n) goto 2: compute_ub;"
02639       if (j<n)
02640         continue;
02641       
02642       // 4. up date the best solution so far 
02643       if (zhat > z) {
02644         z=zhat;
02645         int k;
02646         for (k=0; k<n; k++){
02647           x[k]=xhat[k+1];
02648         }
02649       }
02650       j=n;
02651       if (xhat[n] == 1){
02652         chat = chat+ w[n];
02653         zhat = zhat-p[n];
02654         xhat[n]=0;
02655       }
02656     }
02657     // 5. backtrack 
02658     // "find i=max{k<j:xhat[k]=1};"
02659     int i=j-1; 
02660     while (!(xhat[i]==1) && i>0){
02661       i--;
02662     }
02663     
02664     // "if (no such i exists) return;"
02665     if (i==0){
02666       delete [] p;
02667       delete [] w;
02668       delete [] xhat;
02669       return 1;
02670     }
02671     
02672     chat = chat + w[i];
02673     zhat=zhat -p[i];
02674     xhat[i]=0;
02675     j=i+1;
02676     // "goto 2: compute_ub;"
02677   }
02678 }
02679 
02680 //-------------------------------------------------------------------
02681 // Default Constructor 
02682 //-------------------------------------------------------------------
02683 CglKnapsackCover::CglKnapsackCover ()
02684 :
02685 CglCutGenerator(),
02686 epsilon_(1.0e-08),
02687 epsilon2_(1.0e-5),
02688 onetol_(1-epsilon_),
02689 maxInKnapsack_(50),
02690 numRowsToCheck_(-1),
02691 rowsToCheck_(0)
02692 {
02693   // nothing to do here
02694 }
02695 
02696 //-------------------------------------------------------------------
02697 // Copy constructor 
02698 //-------------------------------------------------------------------
02699 CglKnapsackCover::CglKnapsackCover (const CglKnapsackCover & source) :
02700    CglCutGenerator(source),
02701    epsilon_(source.epsilon_),
02702    epsilon2_(source.epsilon2_),
02703    onetol_(source.onetol_),
02704    maxInKnapsack_(source.maxInKnapsack_),
02705    numRowsToCheck_(source.numRowsToCheck_),
02706    rowsToCheck_(0)
02707 {
02708    if (numRowsToCheck_ > 0) {
02709       rowsToCheck_ = new int[numRowsToCheck_];
02710       CoinCopyN(source.rowsToCheck_, numRowsToCheck_, rowsToCheck_);
02711    }
02712   // Nothing to do here
02713 }
02714 
02715 //-------------------------------------------------------------------
02716 // Destructor 
02717 //-------------------------------------------------------------------
02718 CglKnapsackCover::~CglKnapsackCover ()
02719 {
02720    delete[] rowsToCheck_;
02721   // Nothing to do here
02722 }
02723 
02724 //----------------------------------------------------------------
02725 // Assignment operator 
02726 //-------------------------------------------------------------------
02727 CglKnapsackCover &
02728 CglKnapsackCover::operator=(const CglKnapsackCover& rhs)
02729 {
02730    if (this != &rhs) {
02731       CglCutGenerator::operator=(rhs);
02732       epsilon_=rhs.epsilon_;
02733       epsilon2_=rhs.epsilon2_;
02734       onetol_=rhs.onetol_;
02735       maxInKnapsack_=rhs.maxInKnapsack_;
02736       delete[] rowsToCheck_;
02737       numRowsToCheck_ = rhs.numRowsToCheck_;
02738       if (numRowsToCheck_ > 0) {
02739          rowsToCheck_ = new int[numRowsToCheck_];
02740          CoinCopyN(rhs.rowsToCheck_, numRowsToCheck_, rowsToCheck_);
02741       } else {
02742          rowsToCheck_ = 0;
02743       }
02744    }
02745    return *this;
02746 }

Generated on Wed Dec 3 14:34:54 2003 for Cgl by doxygen 1.3.5