LTP GCOV extension - code coverage report
Current view: directory - tpl/coin-cbc/cbc/Cgl/src/CglDuplicateRow - CglDuplicateRow.cpp
Test: Acro
Date: 2008-08-19 Instrumented lines: 497
Code covered: 2.2 % Executed lines: 11

       1                 : // Copyright (C) 2004, International Business Machines
       2                 : // Corporation and others.  All Rights Reserved.
       3                 : #if defined(_MSC_VER)
       4                 : // Turn off compiler warning about long names
       5                 : #  pragma warning(disable:4786)
       6                 : #endif
       7                 : #include <cstdlib>
       8                 : #include <cstdio>
       9                 : #include <cmath>
      10                 : #include <cfloat>
      11                 : #include <cassert>
      12                 : #include <iostream>
      13                 : //#define PRINT_DEBUG
      14                 : //#define CGL_DEBUG
      15                 : #include "CoinHelperFunctions.hpp"
      16                 : #include "CoinPackedMatrix.hpp"
      17                 : #include "CoinFinite.hpp"
      18                 : #include "OsiRowCutDebugger.hpp"
      19                 : #include "CglDuplicateRow.hpp"
      20                 : #include "CglStored.hpp"
      21                 : //-------------------------------------------------------------------
      22                 : // Generate duplicate row column cuts
      23                 : //------------------------------------------------------------------- 
      24                 : void CglDuplicateRow::generateCuts(const OsiSolverInterface & si, OsiCuts & cs,
      25               0 :                               const CglTreeInfo info) const
      26                 : {
      27                 : #ifdef CGL_DEBUG
      28                 :   const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
      29                 :   if (debugger&&debugger->onOptimalPath(si)) {
      30                 :     printf("On optimal path\n");
      31                 :   }
      32                 : #endif
      33                 :   // Don't do in tree ?
      34               0 :   if (info.inTree) {
      35                 :     // but do any stored cuts
      36               0 :     if (storedCuts_)
      37               0 :       storedCuts_->generateCuts(si,cs,info);
      38               0 :     return;
      39                 :   }
      40               0 :   int numberColumns = matrix_.getNumCols();
      41               0 :   CoinPackedVector ubs;
      42                 :   
      43                 :   // Column copy
      44               0 :   const double * element = matrix_.getElements();
      45               0 :   const int * row = matrix_.getIndices();
      46               0 :   const CoinBigIndex * columnStart = matrix_.getVectorStarts();
      47               0 :   const int * columnLength = matrix_.getVectorLengths();
      48                 :   // Row copy
      49               0 :   const double * elementByRow = matrixByRow_.getElements();
      50               0 :   const int * column = matrixByRow_.getIndices();
      51               0 :   const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
      52               0 :   const int * rowLength = matrixByRow_.getVectorLengths();
      53               0 :   const double * columnLower = si.getColLower();
      54               0 :   const double * columnUpper = si.getColUpper();
      55               0 :   int nFree=0;
      56               0 :   int nOut=0;
      57               0 :   int nFixed=0;
      58                 :   int i;
      59               0 :   int numberRows=matrix_.getNumRows();
      60               0 :   const double * rowLower = si.getRowLower();
      61               0 :   const double * rowUpper = si.getRowUpper();
      62               0 :   int * effectiveRhs = CoinCopyOfArray(rhs_,numberRows);
      63               0 :   int * effectiveLower = CoinCopyOfArray(lower_,numberRows);
      64                 :   // mark bad rows - also used for domination
      65               0 :   for (i=0;i<numberRows;i++) {
      66               0 :     duplicate_[i]=-1;
      67                 :     int j;
      68               0 :     for (j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
      69               0 :       if (elementByRow[j]!=1.0) {
      70               0 :         duplicate_[i]=-3;
      71               0 :         rhs_[i]=-1000000;
      72               0 :         break;
      73                 :       }
      74                 :     }
      75                 :   }
      76               0 :   double * colUpper2 = CoinCopyOfArray(columnUpper,numberColumns);
      77               0 :   if (!info.pass&&(mode_&2)!=0) {
      78                 :     // First look at duplicate or dominated columns
      79               0 :     double * random = new double[numberRows];
      80               0 :     double * sort = new double[numberColumns+1];
      81               0 :     for (i=0;i<numberRows;i++) {
      82               0 :       if (rowLower[i]<-1.0e20||rowUpper[i]>1.0e20)
      83               0 :         random[i]=0.0;
      84                 :       else
      85               0 :         random[i] = CoinDrand48();
      86                 :     }
      87               0 :     int * which = new int[numberColumns];
      88               0 :     int nPossible=0;
      89               0 :     for ( i=0;i<numberColumns;i++) {
      90               0 :       if (si.isBinary(i)) {
      91               0 :         double value = 0.0;
      92               0 :         for (int jj=columnStart[i];jj<columnStart[i]+columnLength[i];jj++) {
      93               0 :           int iRow = row[jj];
      94               0 :           value += element[jj]*random[iRow];
      95                 :         }
      96               0 :         sort[nPossible]=value;
      97               0 :         which[nPossible++]=i;
      98                 :       }
      99                 :     }
     100               0 :     sort[nPossible]=COIN_DBL_MAX;
     101               0 :     CoinSort_2(sort,sort+nPossible,which);
     102               0 :     int last=maximumDominated_-1;
     103               0 :     double lastValue=-1.0;
     104               0 :     const double *objective = si.getObjCoefficients() ;
     105               0 :     double direction = si.getObjSense();
     106                 :     // arrays for checking
     107               0 :     double * elementEqualJ = new double [2*numberRows];
     108               0 :     CoinZeroN(elementEqualJ,numberRows); // for memory checkers
     109               0 :     double * elementGeJ = elementEqualJ + numberRows;
     110               0 :     CoinZeroN(elementGeJ,numberRows);
     111               0 :     int * rowEqualJ = new int[2*numberRows];
     112               0 :     CoinZeroN(rowEqualJ,numberRows); // for memory checkers
     113               0 :     int * rowGeJ = rowEqualJ + numberRows;
     114               0 :     char * mark = new char[numberRows];
     115               0 :     CoinZeroN(mark,numberRows);
     116               0 :     for (i=0;i<nPossible+1;i++) {
     117               0 :       if (sort[i]>lastValue) {
     118               0 :         if (i-last<=maximumDominated_) {
     119                 :           // look to see if dominated
     120               0 :           for (int j=last;j<i;j++) {
     121               0 :             int jColumn = which[j];
     122                 :             // skip if already fixed
     123               0 :             if (!colUpper2[jColumn])
     124               0 :               continue;
     125               0 :             int nGeJ=0;
     126               0 :             int nEqualJ=0;
     127                 :             int jj;
     128               0 :             for (jj=columnStart[jColumn];jj<columnStart[jColumn]+columnLength[jColumn];jj++) {
     129               0 :               int iRow = row[jj];
     130               0 :               if (random[iRow]) {
     131               0 :                 elementEqualJ[nEqualJ]=element[jj];
     132               0 :                 rowEqualJ[nEqualJ++]=iRow;
     133                 :               } else {
     134                 :                 // swap sign so all rows look like G
     135               0 :                 elementGeJ[iRow]=(rowUpper[iRow]>1.0e20) ? element[jj] : -element[jj];
     136               0 :                 rowGeJ[nGeJ++]=iRow;
     137                 :               }
     138                 :             }
     139               0 :             double objValueJ = objective[jColumn]*direction;
     140               0 :             for (int k=j+1;k<i;k++) {
     141               0 :               int kColumn = which[k];
     142                 :               // skip if already fixed
     143               0 :               if (!colUpper2[kColumn])
     144               0 :                 continue;
     145               0 :               int nEqualK=0;
     146                 :               // -2 no good, -1 J dominates K, 0 unknown or equal, 1 K dominates J
     147               0 :               int dominate=0;
     148                 :               // mark
     149                 :               int kk;
     150               0 :               for (kk=0;kk<nGeJ;kk++)
     151               0 :                 mark[rowGeJ[kk]]=1;
     152               0 :               for (kk=columnStart[kColumn];kk<columnStart[kColumn]+columnLength[kColumn];kk++) {
     153               0 :                 int iRow = row[kk];
     154               0 :                 if (random[iRow]) {
     155               0 :                   if (iRow!=rowEqualJ[nEqualK]||
     156                 :                       element[kk]!=elementEqualJ[nEqualK]) {
     157               0 :                     dominate=-2;
     158               0 :                     break;
     159                 :                   } else {
     160               0 :                     nEqualK++;
     161                 :                   }
     162                 :                 } else {
     163                 :                   // swap sign so all rows look like G
     164               0 :                   double valueK = (rowUpper[iRow]>1.0e20) ? element[kk] : -element[kk];
     165               0 :                   double valueJ = elementGeJ[iRow];
     166               0 :                   mark[iRow]=0;
     167               0 :                   if (valueJ==valueK) {
     168                 :                     // equal
     169               0 :                   } else if (valueJ>valueK) {
     170                 :                     // J would dominate K
     171               0 :                     if (dominate==1) {
     172                 :                       // no good
     173               0 :                       dominate=-2;
     174               0 :                       break;
     175                 :                     } else {
     176               0 :                       dominate=-1;
     177                 :                     }
     178                 :                   } else {
     179                 :                     // K would dominate J
     180               0 :                     if (dominate==-1) {
     181                 :                       // no good
     182               0 :                       dominate=-2;
     183               0 :                       break;
     184                 :                     } else {
     185               0 :                       dominate=1;
     186                 :                     }
     187                 :                   }
     188                 :                 }
     189                 :               }
     190               0 :               kk=0;
     191               0 :               if (dominate!=-2) {
     192                 :                 // unmark and check
     193               0 :                 for (;kk<nGeJ;kk++) {
     194               0 :                   int iRow = rowGeJ[kk];
     195               0 :                   if (mark[iRow]) {
     196               0 :                     double valueK = 0.0;
     197               0 :                     double valueJ = elementGeJ[iRow];
     198               0 :                     if (valueJ>valueK) {
     199                 :                       // J would dominate K
     200               0 :                       if (dominate==1) {
     201                 :                         // no good
     202               0 :                         dominate=-2;
     203               0 :                         break;
     204                 :                       } else {
     205               0 :                         dominate=-1;
     206                 :                       }
     207                 :                     } else {
     208                 :                       // K would dominate J
     209               0 :                       if (dominate==-1) {
     210                 :                         // no good
     211               0 :                         dominate=-2;
     212               0 :                         break;
     213                 :                       } else {
     214               0 :                         dominate=1;
     215                 :                       }
     216                 :                     }
     217                 :                   }
     218               0 :                   mark[iRow]=0;
     219                 :                 }
     220                 :               } 
     221                 :               // just unmark rest
     222               0 :               for (;kk<nGeJ;kk++)
     223               0 :                 mark[rowGeJ[kk]]=0;
     224               0 :               if (nEqualK==nEqualJ&&dominate!=-2) {
     225               0 :                 double objValueK = objective[kColumn]*direction;
     226               0 :                 if (objValueJ==objValueK) {
     227               0 :                   if (dominate<=0) {
     228                 :                     // say J dominates
     229               0 :                     assert (colUpper2[kColumn]);
     230               0 :                     dominate=-1;
     231                 :                   } else {
     232                 :                     // say K dominates
     233               0 :                     assert (colUpper2[jColumn]);
     234               0 :                     dominate=1;
     235                 :                   }
     236               0 :                 } else if (objValueJ<objValueK&&dominate<=0) {
     237                 :                   // say J dominates
     238               0 :                   assert (colUpper2[kColumn]);
     239               0 :                   dominate=-1;
     240               0 :                 } else if (objValueJ>objValueK&&dominate==1) {
     241                 :                   // say K dominates
     242               0 :                   assert (colUpper2[jColumn]);
     243               0 :                   dominate=1;
     244                 :                 } else {
     245               0 :                   dominate=0;
     246                 :                 }
     247               0 :                 if (dominate) {
     248                 :                   // see if both can be 1
     249               0 :                   bool canFix=false;
     250               0 :                   for (int jj=0;jj<nEqualJ;jj++) {
     251               0 :                     double value = 2.0*elementEqualJ[jj];
     252               0 :                     int iRow = rowEqualJ[jj];
     253               0 :                     if (duplicate_[iRow]==-1&&rowUpper[iRow]<1.999999) {
     254               0 :                       canFix=true;
     255                 :                     } else {
     256               0 :                       double minSum=0.0;
     257               0 :                       double maxSum=0.0;
     258               0 :                       for (int j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
     259               0 :                         int iColumn = column[j];
     260               0 :                         if (iColumn!=jColumn&&iColumn!=kColumn) {
     261               0 :                           double elValue = elementByRow[j];
     262               0 :                           double lo = columnLower[iColumn];
     263               0 :                           double up = colUpper2[iColumn];
     264               0 :                           if (elValue>0.0) {
     265               0 :                             minSum += lo*elValue;
     266               0 :                             maxSum += up*elValue;
     267                 :                           } else {
     268               0 :                             maxSum += lo*elValue;
     269               0 :                             minSum += up*elValue;
     270                 :                           }
     271                 :                         }
     272                 :                       }
     273               0 :                       if (minSum+value>rowUpper[iRow]+1.0e-5)
     274               0 :                         canFix=true;
     275               0 :                       else if (maxSum+value<rowLower[iRow]-1.0e-5)
     276               0 :                         canFix=true;
     277                 :                     }
     278               0 :                     if (canFix)
     279               0 :                       break;
     280                 :                   }
     281               0 :                   if (canFix) {
     282               0 :                     int iColumn = (dominate>0) ? jColumn : kColumn;
     283               0 :                     nFixed++;
     284               0 :                     assert (!columnLower[iColumn]);
     285               0 :                     colUpper2[iColumn]=0.0;
     286               0 :                     ubs.insert(iColumn,0.0);
     287               0 :                     if (iColumn==jColumn)
     288               0 :                       break; // no need to carry on on jColumn
     289                 :                   } else {
     290               0 :                     int iDominated = (dominate>0) ? jColumn : kColumn;
     291               0 :                     int iDominating = (dominate<0) ? jColumn : kColumn;
     292               0 :                     double els[]={1.0,-1.0};
     293                 :                     int inds[2];
     294               0 :                     inds[0]=iDominating;
     295               0 :                     inds[1]=iDominated;
     296               0 :                     if (!storedCuts_)
     297               0 :                       storedCuts_ = new CglStored();
     298               0 :                     storedCuts_->addCut(0.0,COIN_DBL_MAX,2,inds,els);
     299                 :                   }
     300                 :                 }
     301                 :               }
     302                 :             }
     303               0 :             for (jj=0;jj<nGeJ;jj++) {
     304               0 :               int iRow = rowGeJ[jj];
     305               0 :               elementGeJ[iRow]=0.0;
     306                 :             }
     307                 :           }
     308                 :         }
     309               0 :         last=i;
     310               0 :         lastValue = sort[i];
     311                 :       }
     312                 :     }
     313               0 :     delete [] mark;
     314               0 :     delete [] elementEqualJ;
     315               0 :     delete [] rowEqualJ;
     316               0 :     delete [] random;
     317               0 :     delete [] sort;
     318               0 :     delete [] which;
     319                 : #ifdef COIN_DEVELOP
     320                 :     int numberCuts = storedCuts_ ? storedCuts_->sizeRowCuts() : 0;
     321                 :     if (nFixed||numberCuts) 
     322                 :       printf("** %d fixed and %d cuts from domination\n",nFixed,numberCuts);
     323                 : #endif
     324                 :   }
     325               0 :   bool infeasible=false;
     326                 :   // if we were just doing columns - mark all as bad
     327               0 :   if ((mode_&1)==0) {
     328               0 :     for (i=0;i<numberRows;i++) {
     329               0 :       duplicate_[i]=-3;
     330               0 :       rhs_[i]=-1000000;
     331                 :     }
     332                 :   }
     333               0 :   for ( i=0;i<numberColumns;i++) {
     334               0 :     if (columnLower[i]) {
     335               0 :       double value = columnLower[i];
     336               0 :       for (int jj=columnStart[i];jj<columnStart[i]+columnLength[i];jj++) {
     337               0 :         int iRow = row[jj];
     338               0 :         nOut += (int) (element[jj]*value);
     339               0 :         effectiveRhs[iRow] -= (int) (element[jj]*value);
     340               0 :         effectiveLower[iRow] -= (int) (element[jj]*value);
     341                 :       }
     342                 :     }
     343                 :   }
     344               0 :   for ( i=0;i<numberColumns;i++) {
     345               0 :     if (columnLower[i]!=colUpper2[i]) {
     346               0 :       bool fixed=false;
     347               0 :       for (int jj=columnStart[i];jj<columnStart[i]+columnLength[i];jj++) {
     348               0 :         int iRow = row[jj];
     349               0 :         if (rhs_[iRow]>=0&&element[jj]>effectiveRhs[iRow]) 
     350               0 :           fixed=true;
     351                 :       }
     352               0 :       if (fixed) {
     353               0 :         nFixed++;
     354               0 :         colUpper2[i]=columnLower[i];
     355               0 :         ubs.insert(i,columnLower[i]);
     356                 :       } else {
     357               0 :         nFree++;
     358                 :       }
     359                 :     }
     360                 :   }
     361                 :   // See if anything odd
     362               0 :   char * check = new char[numberColumns];
     363               0 :   memset(check,0,numberColumns);
     364               0 :   int * which2 = new int[numberColumns];
     365               0 :   for (i=0;i<numberRows;i++) {
     366               0 :     if (duplicate_[i]==-1) {
     367               0 :       if (effectiveRhs[i]>0)
     368               0 :         duplicate_[i]=-1;
     369               0 :       else if (effectiveRhs[i]==0)
     370               0 :         duplicate_[i]=-2;
     371                 :       else
     372               0 :         duplicate_[i]=-3;
     373                 :     } else {
     374               0 :       effectiveRhs[i]=-1000;
     375                 :     }
     376                 :   }
     377               0 :   for (i=0;i<numberRows;i++) {
     378                 :     // initially just one
     379               0 :     if (effectiveRhs[i]==1&&duplicate_[i]==-1) {
     380               0 :       int nn=0;
     381                 :       int j,k;
     382               0 :       for (j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
     383               0 :         int iColumn = column[j];
     384               0 :         if (columnLower[iColumn]!=colUpper2[iColumn]) {
     385                 : #ifndef NDEBUG
     386               0 :           assert (elementByRow[j]==1.0);
     387                 : #endif
     388               0 :           check[iColumn]=1;
     389               0 :           which2[nn++]=iColumn;
     390                 :         }
     391                 :       }
     392               0 :       for ( k=i+1;k<numberRows;k++) {
     393               0 :         if (effectiveRhs[k]==1&&duplicate_[i]==-1) {
     394               0 :           int nn2=0;
     395               0 :           int nnsame=0;
     396               0 :           for ( j=rowStart[k];j<rowStart[k]+rowLength[k];j++) {
     397               0 :             int iColumn = column[j];
     398               0 :             if (columnLower[iColumn]!=colUpper2[iColumn]) {
     399                 : #ifndef NDEBUG
     400               0 :               assert (elementByRow[j]==1.0);
     401                 : #endif
     402               0 :               nn2++;
     403               0 :               if (check[iColumn]) 
     404               0 :                 nnsame++;
     405                 :             }
     406                 :           }
     407               0 :           if (nnsame==nn2) {
     408               0 :             if (nn2<nn&&effectiveLower[k]==rhs_[k]&&rhs_[i]==rhs_[k]) {
     409               0 :               if (logLevel_)
     410                 :                 printf("row %d strict subset of row %d, fix some in row %d\n",
     411               0 :                        k,i,i);
     412                 :               // treat i as duplicate
     413               0 :               duplicate_[i]=k;
     414                 :               // zero out check so we can see what is extra
     415               0 :               for ( j=rowStart[k];j<rowStart[k]+rowLength[k];j++) {
     416               0 :                 int iColumn = column[j];
     417               0 :                 check[iColumn]=0; 
     418                 :               }
     419                 :               // now redo and fix
     420               0 :               nn=0;
     421               0 :               for (j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
     422               0 :                 int iColumn = column[j];
     423               0 :                 if (columnLower[iColumn]!=colUpper2[iColumn]) {
     424               0 :                   if (check[iColumn]) {
     425                 :                     // fix
     426               0 :                     colUpper2[iColumn]=columnLower[iColumn];
     427               0 :                     nFixed++;
     428               0 :                     ubs.insert(iColumn,columnLower[iColumn]);
     429               0 :                     check[iColumn]=0;
     430                 :                   } else {
     431               0 :                     check[iColumn]=1;
     432               0 :                     which2[nn++]=iColumn;
     433                 :                   }
     434                 :                 }
     435                 :               }
     436               0 :             } else if (nn2==nn&&effectiveLower[i]==rhs_[i]&&effectiveLower[k]==rhs_[k]) {
     437               0 :               if (logLevel_)
     438                 :                 printf("row %d identical to row %d\n",
     439               0 :                        k,i);
     440               0 :               duplicate_[k]=i;
     441               0 :             } else if (nn2>=nn&&effectiveLower[i]==rhs_[i]&&effectiveLower[k]==rhs_[k]) {
     442               0 :               abort();
     443                 :             }
     444               0 :           } else if (nnsame==nn&&nn2>nn&&effectiveLower[i]==rhs_[i]&&rhs_[i]<=rhs_[k]) {
     445               0 :             if (logLevel_)
     446                 :               printf("row %d strict superset of row %d, fix some in row %d\n",
     447               0 :                      k,i,k);
     448                 :             // treat k as duplicate
     449               0 :             duplicate_[k]=i;
     450                 :             // set check for k
     451               0 :             for ( j=rowStart[k];j<rowStart[k]+rowLength[k];j++) {
     452               0 :               int iColumn = column[j];
     453               0 :               if (columnLower[iColumn]!=colUpper2[iColumn]) 
     454               0 :                 check[iColumn]=1; 
     455                 :             }
     456                 :             // zero out check so we can see what is extra
     457               0 :             for ( j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
     458               0 :               int iColumn = column[j];
     459               0 :               check[iColumn]=0; 
     460                 :             }
     461                 :             //  fix
     462               0 :             for (j=rowStart[k];j<rowStart[k]+rowLength[k];j++) {
     463               0 :               int iColumn = column[j];
     464               0 :               if (check[iColumn]) {
     465                 :                 // fix
     466               0 :                 colUpper2[iColumn]=columnLower[iColumn];
     467               0 :                 nFixed++;
     468               0 :                 ubs.insert(iColumn,columnLower[iColumn]);
     469               0 :                 check[iColumn]=0;
     470                 :               }
     471                 :             }
     472                 :             // redo
     473               0 :             nn=0;
     474               0 :             for (j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
     475               0 :               int iColumn = column[j];
     476               0 :               if (columnLower[iColumn]!=colUpper2[iColumn]) {
     477               0 :                 check[iColumn]=1;
     478               0 :                 which2[nn++]=iColumn;
     479                 :               }
     480                 :             }
     481                 :           } else {
     482                 :             // may be redundant
     483               0 :             if (nnsame==nn2) {
     484                 :               // k redundant ?
     485               0 :               if (nn2<nn&&effectiveLower[k]<=0&&rhs_[i]<=rhs_[k]) {
     486               0 :                 if (logLevel_)
     487                 :                   printf("row %d slack subset of row %d, drop row %d\n",
     488               0 :                          k,i,k);
     489                 :                 // treat k as duplicate
     490               0 :                 duplicate_[k]=i;
     491                 :               }
     492               0 :             } else if (nnsame==nn) {
     493                 :               // i redundant ?
     494               0 :               if (nn2>nn&&effectiveLower[i]<=0&&rhs_[k]<=rhs_[i]) {
     495               0 :                 if (logLevel_)
     496                 :                   printf("row %d slack subset of row %d, drop row %d\n",
     497               0 :                          i,k,i);
     498                 :                 // treat i as duplicate
     499               0 :                 duplicate_[i]=k;
     500                 :               }
     501                 :             }
     502                 :           }
     503                 :         }
     504                 :       }
     505               0 :       for (k=0;k<nn;k++) 
     506               0 :         check[which2[k]]=0;
     507                 :       
     508                 :     }
     509                 :   }
     510               0 :   delete [] check;
     511               0 :   delete [] which2;
     512               0 :   delete [] colUpper2;
     513               0 :   int nRow=0;
     514               0 :   sizeDynamic_=1;
     515               0 :   for (i=0;i<numberRows;i++) {
     516               0 :     if (duplicate_[i]!=-3) {
     517               0 :       if (duplicate_[i]==-1) {
     518               0 :         nRow++;
     519               0 :         int k=effectiveRhs[i];
     520               0 :         while (k) {
     521               0 :           if (sizeDynamic_<1000000000)
     522               0 :             sizeDynamic_ = sizeDynamic_<<1;
     523               0 :           k = k >>1;
     524                 :         }
     525                 :       }
     526                 :     } else {
     527               0 :       duplicate_[i]=-1;
     528                 :     }
     529                 :   } 
     530               0 :   delete [] effectiveRhs;
     531               0 :   delete [] effectiveLower;
     532               0 :   if (logLevel_)
     533                 :     printf("%d free (but %d fixed this time), %d out of rhs, DP size %d, %d rows\n",
     534               0 :            nFree,nFixed,nOut,sizeDynamic_,nRow);
     535               0 :   if (nFixed) {
     536               0 :     OsiColCut cc;
     537               0 :     cc.setUbs(ubs);
     538               0 :     cc.setEffectiveness(100.0);
     539               0 :     cs.insert(cc);
     540                 :   }
     541               0 :   if (infeasible) {
     542                 :     // generate infeasible cut and return
     543               0 :     OsiRowCut rc;
     544               0 :     rc.setLb(DBL_MAX);
     545               0 :     rc.setUb(0.0);   
     546               0 :     cs.insert(rc);
     547               0 :   }
     548                 : }
     549                 : //-------------------------------------------------------------------
     550                 : // Default Constructor 
     551                 : //-------------------------------------------------------------------
     552              12 : CglDuplicateRow::CglDuplicateRow ()
     553                 : :
     554                 :   CglCutGenerator(),
     555                 :   rhs_(NULL),
     556                 :   duplicate_(NULL),
     557                 :   lower_(NULL),
     558                 :   storedCuts_(NULL),
     559                 :   maximumDominated_(1000),
     560                 :   maximumRhs_(1),
     561                 :   sizeDynamic_(COIN_INT_MAX),
     562                 :   mode_(3),
     563              12 :   logLevel_(0)
     564                 : {
     565              12 : }
     566                 : // Useful constructor
     567               0 : CglDuplicateRow::CglDuplicateRow(OsiSolverInterface * solver)
     568                 :   : CglCutGenerator(),
     569                 :     rhs_(NULL),
     570                 :     duplicate_(NULL),
     571                 :     lower_(NULL),
     572                 :     storedCuts_(NULL),
     573                 :     maximumDominated_(1000),
     574                 :     maximumRhs_(1),
     575                 :     sizeDynamic_(COIN_INT_MAX),
     576                 :     mode_(3),
     577               0 :     logLevel_(0)
     578                 : {
     579               0 :   refreshSolver(solver);
     580               0 : }
     581                 : 
     582                 : //-------------------------------------------------------------------
     583                 : // Copy constructor 
     584                 : //-------------------------------------------------------------------
     585               0 : CglDuplicateRow::CglDuplicateRow (  const CglDuplicateRow & rhs)
     586                 :                                                               :
     587                 :   CglCutGenerator(rhs),
     588                 :   matrix_(rhs.matrix_),
     589                 :   matrixByRow_(rhs.matrixByRow_),
     590                 :   storedCuts_(NULL),
     591                 :   maximumDominated_(rhs.maximumDominated_),
     592                 :   maximumRhs_(rhs.maximumRhs_),
     593                 :   sizeDynamic_(rhs.sizeDynamic_),
     594                 :   mode_(rhs.mode_),
     595               0 :   logLevel_(rhs.logLevel_)
     596                 : {  
     597               0 :   int numberRows=matrix_.getNumRows();
     598               0 :   rhs_ = CoinCopyOfArray(rhs.rhs_,numberRows);
     599               0 :   duplicate_ = CoinCopyOfArray(rhs.duplicate_,numberRows);
     600               0 :   lower_ = CoinCopyOfArray(rhs.lower_,numberRows);
     601               0 :   if (rhs.storedCuts_)
     602               0 :     storedCuts_ = new CglStored(*rhs.storedCuts_);
     603               0 : }
     604                 : 
     605                 : //-------------------------------------------------------------------
     606                 : // Clone
     607                 : //-------------------------------------------------------------------
     608                 : CglCutGenerator *
     609               0 : CglDuplicateRow::clone() const
     610                 : {
     611               0 :   return new CglDuplicateRow(*this);
     612                 : }
     613                 : 
     614                 : //-------------------------------------------------------------------
     615                 : // Destructor 
     616                 : //-------------------------------------------------------------------
     617              12 : CglDuplicateRow::~CglDuplicateRow ()
     618                 : {
     619                 :   // free memory
     620              12 :   delete [] rhs_;
     621              12 :   delete [] duplicate_;
     622              12 :   delete [] lower_;
     623              12 :   delete storedCuts_;
     624              12 : }
     625                 : 
     626                 : //----------------------------------------------------------------
     627                 : // Assignment operator 
     628                 : //-------------------------------------------------------------------
     629                 : CglDuplicateRow &
     630                 : CglDuplicateRow::operator=(
     631               0 :                                          const CglDuplicateRow& rhs)
     632                 : {
     633               0 :   if (this != &rhs) {
     634               0 :     CglCutGenerator::operator=(rhs);
     635               0 :     delete [] rhs_;
     636               0 :     delete [] duplicate_;
     637               0 :     delete [] lower_;
     638               0 :     delete storedCuts_;
     639               0 :     storedCuts_ = NULL;
     640               0 :     matrix_=rhs.matrix_;
     641               0 :     matrixByRow_=rhs.matrixByRow_;
     642               0 :     maximumDominated_ = rhs.maximumDominated_;
     643               0 :     maximumRhs_=rhs.maximumRhs_;
     644               0 :     sizeDynamic_ = rhs.sizeDynamic_;
     645               0 :     mode_ = rhs.mode_;
     646               0 :     logLevel_ = rhs.logLevel_;
     647               0 :     int numberRows=matrix_.getNumRows();
     648               0 :     rhs_ = CoinCopyOfArray(rhs.rhs_,numberRows);
     649               0 :     duplicate_ = CoinCopyOfArray(rhs.duplicate_,numberRows);
     650               0 :     lower_ = CoinCopyOfArray(rhs.lower_,numberRows);
     651               0 :   if (rhs.storedCuts_)
     652               0 :     storedCuts_ = new CglStored(*rhs.storedCuts_);
     653                 :   }
     654               0 :   return *this;
     655                 : }
     656                 : 
     657                 : /// This can be used to refresh any inforamtion
     658                 : void 
     659               0 : CglDuplicateRow::refreshSolver(OsiSolverInterface * solver)
     660                 : {
     661               0 :   delete [] rhs_;
     662               0 :   delete [] duplicate_;
     663               0 :   delete [] lower_;
     664               0 :   matrix_ = *solver->getMatrixByCol();
     665               0 :   matrix_.removeGaps();
     666               0 :   matrix_.orderMatrix();
     667               0 :   matrixByRow_ = *solver->getMatrixByRow();
     668               0 :   int numberRows=matrix_.getNumRows();
     669               0 :   rhs_ = new int[numberRows];
     670               0 :   duplicate_ = new int[numberRows];
     671               0 :   lower_ = new int[numberRows];
     672               0 :   const double * rowLower = solver->getRowLower();
     673               0 :   const double * rowUpper = solver->getRowUpper();
     674                 :   // Row copy
     675               0 :   const double * elementByRow = matrixByRow_.getElements();
     676               0 :   const int * column = matrixByRow_.getIndices();
     677               0 :   const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
     678               0 :   const int * rowLength = matrixByRow_.getVectorLengths();
     679                 :   int iRow;
     680               0 :   int numberGood=0;
     681               0 :   int markBad = -(solver->getNumCols()+1);
     682               0 :   for (iRow=0;iRow<numberRows;iRow++) {
     683               0 :     rhs_[iRow]=markBad;
     684               0 :     lower_[iRow]=markBad;
     685               0 :     duplicate_[iRow]=-1;
     686               0 :     if (rowUpper[iRow]<100) {
     687               0 :       int iRhs= (int) floor(rowUpper[iRow]);
     688                 :       // check elements
     689               0 :       bool good=true;
     690               0 :       for (int j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
     691               0 :         int iColumn = column[j];
     692               0 :         if (!solver->isInteger(iColumn))
     693               0 :           good=false;
     694               0 :         double value = elementByRow[j];
     695               0 :         if (floor(value)!=value||value<1.0) {
     696               0 :           good=false;
     697                 :         }
     698                 :       }
     699               0 :       if (good) {
     700               0 :         lower_[iRow] = (int) CoinMax(0.0,ceil(rowLower[iRow]));
     701               0 :         if (iRhs>=lower_[iRow]) {
     702               0 :           rhs_[iRow]=iRhs;
     703               0 :           numberGood++;
     704                 :         } else {
     705                 :           // infeasible ?
     706               0 :           lower_[iRow]=markBad;
     707               0 :           rhs_[iRow]=markBad;
     708                 :         }
     709                 :       } else {
     710               0 :         lower_[iRow]=markBad;
     711               0 :         rhs_[iRow]=markBad;
     712                 :       }
     713                 :     }
     714                 :   }
     715               0 : }
     716                 :   /** Fix variables and find duplicate/dominated rows for the model of the 
     717                 :       solver interface, si.
     718                 : 
     719                 :       This is a very simple minded idea but I (JJF) am using it in a project so thought
     720                 :       I might as well add it.  It should really be called before first solve and I may
     721                 :       modify CBC to allow for that.
     722                 : 
     723                 :       This is designed for problems with few rows and many integer variables where the rhs
     724                 :       are <= or == and all coefficients and rhs are small integers.
     725                 : 
     726                 :       If effective rhs is K then we can fix all variables with coefficients > K to their lower bounds
     727                 :       (effective rhs just means original with variables with nonzero lower bounds subtracted out).
     728                 : 
     729                 :       If one row is a subset of another and the effective rhs are same we can fix some variables
     730                 :       and then the two rows are identical.
     731                 : 
     732                 :       This version does deletions and fixings and may return stored cuts for
     733                 :       dominated columns 
     734                 :   */
     735                 : CglStored * 
     736               0 : CglDuplicateRow::outDuplicates( OsiSolverInterface * solver)
     737                 : {
     738                 :   
     739               0 :   CglTreeInfo info;
     740               0 :   info.level = 0;
     741               0 :   info.pass = 0;
     742               0 :   int numberRows = solver->getNumRows();
     743               0 :   info.formulation_rows = numberRows;
     744               0 :   info.inTree = false;
     745               0 :   info.strengthenRow= NULL;
     746               0 :   info.pass = 0;
     747               0 :   OsiCuts cs;
     748               0 :   generateCuts(*solver,cs,info);
     749                 :   // Get rid of duplicate rows
     750               0 :   int * which = new int[numberRows]; 
     751               0 :   int numberDrop=0;
     752               0 :   for (int iRow=0;iRow<numberRows;iRow++) {
     753               0 :     if (duplicate_[iRow]==-2||duplicate_[iRow]>=0) 
     754               0 :       which[numberDrop++]=iRow;
     755                 :   }
     756               0 :   if (numberDrop) {
     757               0 :     solver->deleteRows(numberDrop,which);
     758                 :   }
     759               0 :   delete [] which;
     760                 :   // see if we have any column cuts
     761               0 :   int numberColumnCuts = cs.sizeColCuts() ;
     762               0 :   const double * columnLower = solver->getColLower();
     763               0 :   const double * columnUpper = solver->getColUpper();
     764               0 :   for (int k = 0;k<numberColumnCuts;k++) {
     765               0 :     OsiColCut * thisCut = cs.colCutPtr(k) ;
     766               0 :     const CoinPackedVector & lbs = thisCut->lbs() ;
     767               0 :     const CoinPackedVector & ubs = thisCut->ubs() ;
     768                 :     int j ;
     769                 :     int n ;
     770                 :     const int * which ;
     771                 :     const double * values ;
     772               0 :     n = lbs.getNumElements() ;
     773               0 :     which = lbs.getIndices() ;
     774               0 :     values = lbs.getElements() ;
     775               0 :     for (j = 0;j<n;j++) {
     776               0 :       int iColumn = which[j] ;
     777               0 :       if (values[j]>columnLower[iColumn]) 
     778               0 :         solver->setColLower(iColumn,values[j]) ;
     779                 :     }
     780               0 :     n = ubs.getNumElements() ;
     781               0 :     which = ubs.getIndices() ;
     782               0 :     values = ubs.getElements() ;
     783               0 :     for (j = 0;j<n;j++) {
     784               0 :       int iColumn = which[j] ;
     785               0 :       if (values[j]<columnUpper[iColumn]) 
     786               0 :         solver->setColUpper(iColumn,values[j]) ;
     787                 :     }
     788                 :   }
     789               0 :   return storedCuts_;
     790                 : }
     791                 : // Create C++ lines to get to current state
     792                 : std::string
     793               0 : CglDuplicateRow::generateCpp( FILE * fp) 
     794                 : {
     795               0 :   CglDuplicateRow other;
     796               0 :   fprintf(fp,"0#include \"CglDuplicateRow.hpp\"\n");
     797               0 :   fprintf(fp,"3  CglDuplicateRow duplicateRow;\n");
     798               0 :   if (logLevel_!=other.logLevel_)
     799               0 :     fprintf(fp,"3  duplicateRow.setLogLevel(%d);\n",logLevel_);
     800                 :   else
     801               0 :     fprintf(fp,"4  duplicateRow.setLogLevel(%d);\n",logLevel_);
     802               0 :   if (maximumRhs_!=other.maximumRhs_)
     803               0 :     fprintf(fp,"3  duplicateRow.setMaximumRhs(%d);\n",maximumRhs_);
     804                 :   else
     805               0 :     fprintf(fp,"4  duplicateRow.setMaximumRhs(%d);\n",maximumRhs_);
     806               0 :   if (maximumDominated_!=other.maximumDominated_)
     807               0 :     fprintf(fp,"3  duplicateRow.setMaximumDominated(%d);\n",maximumDominated_);
     808                 :   else
     809               0 :     fprintf(fp,"4  duplicateRow.setMaximumDominated(%d);\n",maximumDominated_);
     810               0 :   if (mode_!=other.mode_)
     811               0 :     fprintf(fp,"3  duplicateRow.setMode(%d);\n",mode_);
     812                 :   else
     813               0 :     fprintf(fp,"4  duplicateRow.setMode(%d);\n",mode_);
     814               0 :   if (getAggressiveness()!=other.getAggressiveness())
     815               0 :     fprintf(fp,"3  duplicateRow.setAggressiveness(%d);\n",getAggressiveness());
     816                 :   else
     817               0 :     fprintf(fp,"4  duplicateRow.setAggressiveness(%d);\n",getAggressiveness());
     818               0 :   return "duplicateRow";
     819              88 : }

Generated by: LTP GCOV extension version 1.4