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 coefficie