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

CglOddHole.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 <cfloat>
00011 #include <iostream>
00012 
00013 #include "CoinHelperFunctions.hpp"
00014 #include "CoinPackedVector.hpp"
00015 #include "CoinPackedMatrix.hpp"
00016 #include "OsiRowCutDebugger.hpp"
00017 #include "CglOddHole.hpp"
00018 //#define CGL_DEBUG
00019 // We may want to sort cut
00020 typedef struct {double dj;double element; int sequence;} 
00021 double_double_int_triple;
00022 class double_double_int_triple_compare {
00023 public:
00024   bool operator() (double_double_int_triple x , double_double_int_triple y) const
00025   {
00026     return ( x.dj < y.dj);
00027   }
00028 }; 
00029 //-------------------------------------------------------------------------------
00030 // Generate three cycle cuts
00031 //------------------------------------------------------------------- 
00032 void CglOddHole::generateCuts(const OsiSolverInterface & si, 
00033                                                 OsiCuts & cs ) const
00034 {
00035   // Get basic problem information
00036   int nRows=si.getNumRows(); 
00037   int nCols=si.getNumCols(); 
00038   
00039   const CoinPackedMatrix * rowCopy = si.getMatrixByRow();
00040 
00041   // Could do cliques and extra OSL cliques
00042   // For moment just easy ones
00043   
00044   // If no information exists then get a list of suitable rows
00045   // If it does then suitable rows are subset of information
00046   
00047   CglOddHole temp;
00048   int * checkRow = new int[nRows];
00049   int i;
00050   if (!suitableRows_) {
00051     for (i=0;i<nRows;i++) {
00052       checkRow[i]=1;
00053     }
00054   } else {
00055     // initialize and extend rows to current size
00056     memset(checkRow,0,nRows*sizeof(int));
00057     memcpy(checkRow,suitableRows_,CoinMin(nRows,numberRows_)*sizeof(int));
00058   }
00059   temp.createRowList(si,checkRow);
00060   // now cut down further by only allowing rows with fractional solution
00061   double * solution = new double[nCols];
00062   memcpy(solution,si.getColSolution(),nCols*sizeof(double));
00063   const int * column = rowCopy->getIndices();
00064   const int * rowStart = rowCopy->getVectorStarts();
00065   const int * rowLength = rowCopy->getVectorLengths(); 
00066   const double * collower = si.getColLower();
00067   const double * colupper = si.getColUpper();
00068   int * suitable = temp.suitableRows_;
00069 
00070   // At present I am using new and delete as easier to see arrays in debugger
00071   int * fixed = new int[nCols]; // mark fixed columns 
00072 
00073   for (i=0;i<nCols;i++) {
00074     if (si.isBinary(i) ) {
00075       fixed[i]=0;
00076       if (colupper[i]-collower[i]<epsilon_) {
00077         solution[i]=0.0;
00078         fixed[i]=2;
00079       } else if (solution[i]<epsilon_) {
00080         solution[i]=0.0;
00081         fixed[i]=-1;
00082       } else if (solution[i]>onetol_) {
00083         solution[i]=1.0;
00084         fixed[i]=+1;
00085       }
00086     } else {
00087       //mark as fixed even if not (can not intersect any interesting rows)
00088       solution[i]=0.0;
00089       fixed[i]=3;
00090     }
00091   }
00092   // first do packed
00093   const double * rowlower = si.getRowLower();
00094   const double * rowupper = si.getRowUpper();
00095   for (i=0;i<nRows;i++) {
00096     if (suitable[i]) {
00097       int k;
00098       double sum=0.0;
00099       if (rowupper[i]>1.001) suitable[i]=-1;
00100       for (k=rowStart[i]; k<rowStart[i]+rowLength[i];k++) {
00101         int icol=column[k];
00102         if (!fixed[icol]) sum += solution[icol];
00103       }
00104       if (sum<0.9) suitable[i]=-1; //say no good
00105     }
00106   }
00107 #ifdef CGL_DEBUG
00108   const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
00109   if (debugger&&!debugger->onOptimalPath(si))
00110     debugger = NULL;
00111 #else
00112   const OsiRowCutDebugger * debugger = NULL;
00113 #endif
00114   temp.generateCuts(debugger, *rowCopy,solution,
00115                     si.getReducedCost(),cs,suitable,fixed,true);
00116   // now cover
00117   //if no >= then skip
00118   bool doCover=false;
00119   int nsuitable=0;
00120   for (i=0;i<nRows;i++) {
00121     suitable[i]=abs(suitable[i]);
00122     if (suitable[i]) {
00123       int k;
00124       double sum=0.0;
00125       if (rowlower[i]<0.999) sum=2.0;
00126       if (rowupper[i]>1.001) doCover=true;
00127       for (k=rowStart[i]; k<rowStart[i]+rowLength[i];k++) {
00128         int icol=column[k];
00129         if (!fixed[icol]) sum += solution[icol];
00130         if (fixed[icol]==1) sum=2.0; //don't use if any at 1
00131       }
00132       if (sum>1.1) {
00133         suitable[i]=-1; //say no good
00134       } else {
00135         nsuitable++;
00136       }
00137     }
00138   }
00139   if (doCover&&nsuitable) 
00140     temp.generateCuts(debugger, *rowCopy,solution,si.getReducedCost(),
00141                       cs,suitable,fixed,false);
00142   delete [] checkRow;
00143   delete [] solution;
00144   delete [] fixed;
00145     
00146 }
00147 void CglOddHole::generateCuts(const OsiRowCutDebugger * debugger,
00148                               const CoinPackedMatrix & rowCopy, 
00149                                  const double * solution, 
00150                               const double * dj, OsiCuts & cs,
00151                                  const int * suitableRow,
00152                               const int * fixedColumn,
00153                               bool packed)
00154 {
00155   CoinPackedMatrix columnCopy = rowCopy;
00156   columnCopy.reverseOrdering();
00157 
00158   // Get basic problem information
00159   int nRows=columnCopy.getNumRows(); 
00160   int nCols=columnCopy.getNumCols(); 
00161   
00162   const int * column = rowCopy.getIndices();
00163   const int * rowStart = rowCopy.getVectorStarts();
00164   const int * rowLength = rowCopy.getVectorLengths(); 
00165   
00166   const int * row = columnCopy.getIndices();
00167   const int * columnStart = columnCopy.getVectorStarts();
00168   const int * columnLength = columnCopy.getVectorLengths(); 
00169 
00170   // we need only look at suitable rows and variables with unsatisfied 0-1
00171   // lookup from true row to compressed matrix
00172   int * mrow = new int[nRows];
00173   // lookup from true column to compressed
00174   int * lookup = new int[nCols];
00175   // number of columns in compressed matrix
00176   int nSmall=0;
00177   int i;
00178   //do lookup from true sequence to compressed
00179   int n=0;
00180   for (i=0;i<nRows;i++) {
00181     if (suitableRow[i]>0) {
00182       mrow[i]=n++;
00183     } else {
00184       mrow[i]=-1;
00185     }
00186   }
00187   for (i=0;i<nCols;i++) {
00188     if (!fixedColumn[i]) {
00189       lookup[i]=nSmall++;
00190     } else {
00191       lookup[i]=-1;
00192     }
00193   }
00194   int nSmall2=2*nSmall;
00195   // we don't know how big matrix will be
00196 #define MAXELS 50000
00197   int maxels=MAXELS;
00198   //How do I do reallocs in C++?
00199   // 1.0 - value x(i) - value x(j) for each node pair (or reverse if cover) 
00200   double * cost = (double *) malloc(maxels*sizeof(double));
00201   // arc i.e. j which can be reached from i
00202   int * to= (int *) malloc(maxels*sizeof(int));
00203   //original row for each arc
00204   int * rowfound=(int *) malloc(maxels*sizeof(int));
00205   // start of each column
00206   int * starts=new int[2*nSmall+1];
00207   starts[0]=0;
00208   // useful array for marking if already connected
00209   int * mark =new int[nSmall2];
00210   memset(mark,0,nSmall2*sizeof(int));
00211   n=0; //number of elements in matrix
00212   for (i=0;i<nCols;i++) {
00213     int icol=lookup[i];
00214     if (icol>=0) {
00215       // column in compressed matrix
00216       int k;
00217       double dd=1.0000001-solution[i];
00218       mark[icol]=1;
00219       // reallocate if matrix reached size limit
00220       if (n+nCols>maxels) {
00221         maxels*=2;
00222         cost=(double *) realloc(cost,maxels*sizeof(int));
00223         to=(int *) realloc(to,maxels*sizeof(int));
00224         rowfound=(int *) realloc(rowfound,maxels*sizeof(int));
00225       }
00226       // get all other connected variables
00227       for (k=columnStart[i];k<columnStart[i]+columnLength[i];k++) {
00228         int irow=row[k];
00229         int jrow=mrow[irow];
00230         // but only if row in compressed matrix
00231         if (jrow>=0) {
00232           int j;
00233           for (j=rowStart[irow];j<rowStart[irow]+rowLength[irow];j++) {
00234             int jcol=column[j];
00235             int kcol=lookup[jcol];
00236             if (kcol>=0&&!mark[kcol]) {
00237               cost[n]=dd-solution[jcol];
00238               to[n]=kcol;
00239               rowfound[n++]=irow;//original row
00240               mark[kcol]=1;
00241             }
00242           }
00243         }
00244       }
00245       starts[icol+1]=n;
00246       // zero out markers for next column
00247       mark[icol]=0;
00248       for (k=starts[icol];k<starts[icol+1];k++) {
00249         int ito=to[k];
00250         if (ito<0||ito>=nSmall) abort();
00251         mark[to[k]]=0;
00252       }
00253     }
00254   }
00255   //if cover then change sign - otherwise make sure positive
00256   if (packed) {
00257     for (i=0;i<n;i++) {
00258       if (cost[i]<1.0e-10) {
00259         cost[i]=1.0e-10;
00260       }
00261     }
00262   } else {
00263     for (i=0;i<n;i++) {
00264       cost[i]=-cost[i];
00265       if (cost[i]<1.0e-10) {
00266         cost[i]=1.0e-10;
00267       }
00268     }
00269   }
00270   // we are going to double size 
00271 
00272   if (2*n>maxels) {
00273     maxels=2*n;
00274     cost=(double *) realloc(cost,maxels*sizeof(int));
00275     to=(int *) realloc(to,maxels*sizeof(int));
00276     rowfound=(int *) realloc(rowfound,maxels*sizeof(int));
00277   }
00278   /* copy and make bipartite*/
00279 
00280   for (i=0;i<nSmall;i++) {
00281     int k,j=i+nSmall;
00282     for (k=starts[i];k<starts[i+1];k++) {
00283       int ito=to[k];
00284       to[n]=ito;
00285       to[k]=ito+nSmall;
00286       cost[n]=cost[k];
00287       rowfound[n++]=rowfound[k];;
00288     }
00289     starts[j+1]=n;
00290   }
00291   //random numbers to winnow out duplicate cuts
00292   double * check = new double[nCols];
00293   CoinSeedRandom(13579);
00294   for (i=0;i<nCols;i++) {
00295     check[i]=CoinDrand48();
00296   }
00297 
00298   // Shortest path algorithm from Dijkstra - is there a better one?
00299 
00300   typedef struct {
00301     double cost; //cost to starting node
00302     int back; //previous node
00303   } Path;
00304   typedef struct {
00305     double cost; //cost to starting node
00306     int node; //node
00307   } Item;
00308   Item * stack = new Item [nSmall2];
00309   Path * path = new Path [nSmall2];
00310   // arrays below are used only if looks promising
00311   // allocate here
00312   // we don't know how many cuts will be generated
00313   int ncuts=0;
00314   int maxcuts=1000;
00315   double * hash = (double *) malloc(maxcuts*sizeof(double));
00316   // to clean (should not be needed)
00317   int * clean = new int[nSmall2];
00318   int * candidate = new int[CoinMax(nSmall2,nCols)];
00319   double * element = new double[nCols];
00320   // in case we want to sort
00321   double_double_int_triple * sortit = 
00322     new double_double_int_triple [nCols];
00323   memset(mark,0,nSmall2*sizeof(int));
00324   int * countcol = new int[nCols];
00325   memset(countcol,0,nCols*sizeof(int));
00326   int bias = packed ? 0 : 1; //amount to add before halving
00327   // If nSmall large then should do a randomized subset
00328   // Improvement 1
00329   int icol;
00330   for (icol=0;icol<nSmall;icol++) {
00331     int j;
00332     int jcol=icol+nSmall;
00333     int istack=1;
00334     for (j=0;j<nSmall2;j++) {
00335       path[j].cost=1.0e70;
00336       path[j].back=nSmall2+1;
00337     }
00338     path[icol].cost=0.0;
00339     path[icol].back=-1;
00340     stack[0].cost=0.0;
00341     stack[0].node=icol;
00342     mark[icol]=1;
00343     while(istack) {
00344       Item thisItem=stack[--istack];
00345       double thisCost=thisItem.cost;
00346       int inode=thisItem.node;
00347       int k;
00348       mark[inode]=0; //say available for further work
00349       // See if sorting every so many would help (and which way)?
00350       // Improvement 2
00351       for (k=starts[inode];k<starts[inode+1];k++) {
00352         int jnode=to[k];
00353         if (!mark[jnode]&&thisCost+cost[k]<path[jnode].cost-1.0e-12) {
00354           path[jnode].cost=thisCost+cost[k];
00355           path[jnode].back=inode;
00356           // add to stack
00357           stack[istack].cost=path[jnode].cost;
00358           stack[istack++].node=jnode;
00359           mark[jnode]=1;
00360 #ifdef CGL_DEBUG
00361           assert (istack<=nSmall2);
00362 #endif
00363         }
00364       }
00365     }
00366     bool good=(path[jcol].cost<0.9999);
00367 
00368     if (good)  { /* try */
00369       int ii;
00370       int nrow2=0;
00371       int nclean=0;
00372       double sum=0;
00373 #ifdef CGL_DEBUG
00374       printf("** %d ",jcol-nSmall);
00375 #endif
00376       ii=1;
00377       candidate[0]=jcol;
00378       while(jcol!=icol) {
00379         int jjcol;
00380         jcol=path[jcol].back;
00381         if (jcol>=nSmall) {
00382           jjcol=jcol-nSmall;
00383         } else {
00384           jjcol=jcol;
00385         }
00386 #ifdef CGL_DEBUG
00387         printf(" %d",jjcol);
00388 #endif
00389         if (mark[jjcol]) {
00390           // good=false;
00391           // probably means this is from another cycle (will have been found)
00392           // one of cycles must be zero cost
00393           // printf("variable already on chain!\n");
00394         } else {
00395           mark[jjcol]=1;
00396           clean[nclean++]=jjcol;
00397           candidate[ii++]=jcol;
00398 #ifdef CGL_DEBUG
00399           assert (ii<=nSmall2);
00400 #endif
00401         }
00402       }
00403 #ifdef CGL_DEBUG
00404       printf("\n");
00405 #endif
00406       for (j=0;j<nclean;j++) {
00407         int k=clean[j];
00408         mark[k]=0;
00409       }
00410       if (good) {
00411         int k;
00412         for (k=ii-1;k>0;k--) {
00413           int jk,kk=candidate[k];
00414           int ix=0;
00415           for (jk=starts[kk];jk<starts[kk+1];jk++) {
00416             int ito=to[jk];
00417             if (ito==candidate[k-1]) {
00418               ix=1;
00419               // back to original row
00420               mrow[nrow2++]=rowfound[jk];
00421               break;
00422             }
00423           }
00424           if (!ix) {
00425             good=false;
00426           }
00427         }
00428         if ((nrow2&1)!=1) {
00429           good=false;
00430         }
00431         if (good) {
00432           int nincut=0;
00433           for (k=0;k<nrow2;k++) {
00434             int j,irow=mrow[k];
00435             for (j=rowStart[irow];j<rowStart[irow]+rowLength[irow];j++) {
00436               int icol=column[j];
00437               if (!countcol[icol]) candidate[nincut++]=icol;
00438               countcol[icol]++;
00439             }
00440           }
00441 #ifdef CGL_DEBUG
00442           printf("true constraint %d",nrow2);
00443 #endif
00444           nrow2=nrow2>>1;
00445           double rhs=nrow2; 
00446           if (!packed) rhs++; // +1 for cover
00447           ii=0;
00448           for (k=0;k<nincut;k++) {
00449             int jcol=candidate[k];
00450             if (countcol[jcol]) {
00451 #ifdef CGL_DEBUG
00452               printf(" %d %d",jcol,countcol[jcol]);
00453 #endif
00454               int ihalf=(countcol[jcol]+bias)>>1;
00455               if (ihalf) {
00456                 element[ii]=ihalf;
00457                 sum+=solution[jcol]*element[ii];
00458                 /*printf("%d %g %g\n",jcol,element[ii],sumall[jcol]);*/
00459                 candidate[ii++]=jcol;
00460               }
00461               countcol[jcol]=0;
00462             }
00463           }
00464 #ifdef CGL_DEBUG
00465           printf("\n");
00466 #endif
00467           OsiRowCut rc;
00468           double violation=0.0;
00469           if (packed) {
00470             violation = sum-rhs;
00471             rc.setLb(-DBL_MAX);
00472             rc.setUb(rhs);   
00473           } else {
00474             // other way for cover
00475             violation = rhs-sum;
00476             rc.setUb(DBL_MAX);
00477             rc.setLb(rhs);   
00478           }
00479           if (violation<minimumViolation_) {
00480 #ifdef CGL_DEBUG
00481             printf("why no cut\n");
00482 #endif
00483             good=false;
00484           } else {
00485             if (((double) ii) * minimumViolationPer_>violation||
00486                 ii>maximumEntries_) {
00487 #ifdef CGL_DEBUG
00488               printf("why no cut\n");
00489 #endif
00490               if (packed) {
00491                 // sort and see if we can get down to length
00492                 // relax by taking out ones with solution 0.0
00493                 nincut=ii;
00494                 for (k=0;k<nincut;k++) {
00495                   int jcol=candidate[k];
00496                   double value = fabs(dj[jcol]);
00497                   if (solution[jcol])
00498                   value = -solution[jcol];
00499                   sortit[k].dj=value;
00500                   sortit[k].element=element[k];
00501                   sortit[k].sequence=jcol;
00502                 }
00503                 // sort 
00504                 std::sort(sortit,sortit+nincut,double_double_int_triple_compare());
00505                 nincut = min(nincut,maximumEntries_);
00506                 sum=0.0;
00507                 for (k=0;k<nincut;k++) {
00508                   int jcol=sortit[k].sequence;
00509                   candidate[k]=jcol;
00510                   element[k]=sortit[k].element;
00511                   sum+=solution[jcol]*element[k];
00512                 }
00513                 violation = sum-rhs;
00514                 ii=nincut;
00515                 if (violation<minimumViolation_) {
00516                   good=false;
00517                 }
00518               } else { 
00519                 good=false;
00520               }
00521             }
00522           }
00523           if (good) {
00524             //this assumes not many cuts
00525             int j;
00526 #if 0
00527             double value=0.0;
00528             for (j=0;j<ii;j++) {
00529               int icol=candidate[j];
00530               value += check[icol]*element[j];
00531             }
00532 #else
00533             CoinPackedVector candidatePv(ii,candidate,element);
00534             candidatePv.sortIncrIndex();
00535             double value = candidatePv.dotProduct(check);
00536 #endif
00537 
00538             for (j=0;j<ncuts;j++) {
00539               if (value==hash[j]) {
00540                 //could check equality - quicker just to assume
00541                 break;
00542               }
00543             }
00544             if (j==ncuts) {
00545               //new
00546               if (ncuts==maxcuts) {
00547                 maxcuts *= 2;
00548                 hash = (double *) realloc(hash,maxcuts*sizeof(double));
00549               }
00550               hash[ncuts++]=value;
00551               rc.setRow(ii,candidate,element);
00552 #ifdef CGL_DEBUG
00553               printf("sum %g rhs %g %d\n",sum,rhs,ii);
00554               if (debugger) 
00555                 assert(!debugger->invalidCut(rc)); 
00556 #endif
00557               cs.insert(rc);
00558             }
00559           }
00560         }
00561         /* end of adding cut */
00562       }
00563     }
00564   }
00565   delete [] countcol;
00566   delete [] element;
00567   delete [] candidate;
00568   delete [] sortit;
00569   delete [] clean;
00570   delete [] path;
00571   delete [] stack;
00572   free(hash);
00573   delete [] check;
00574   delete [] mark;
00575   delete [] starts;
00576   delete [] lookup;
00577   delete [] mrow;
00578   free(rowfound);
00579   free(to);
00580   free(cost);
00581 }
00582 
00583 // Create a list of rows which might yield cuts
00584 // The possible parameter is a list to cut down search
00585 void CglOddHole::createRowList( const OsiSolverInterface & si,
00586                       const int * possible)
00587 {
00588   // Get basic problem information
00589   int nRows=si.getNumRows(); 
00590   
00591   const CoinPackedMatrix * rowCopy = si.getMatrixByRow();
00592 
00593   const int * column = rowCopy->getIndices();
00594   const int * rowStart = rowCopy->getVectorStarts();
00595   const int * rowLength = rowCopy->getVectorLengths(); 
00596   
00597   int rowIndex;
00598   delete [] suitableRows_;
00599   numberRows_=nRows;
00600 
00601   const double * rowElements = rowCopy->getElements();
00602   const double * rowupper = si.getRowUpper();
00603   const double * rowlower = si.getRowLower();
00604   const double * collower = si.getColLower();
00605   const double * colupper = si.getColUpper();
00606 
00607   suitableRows_=new int[nRows];
00608   if (possible) {
00609     memcpy(suitableRows_,possible,nRows*sizeof(int));
00610   } else {
00611     int i;
00612     for (i=0;i<nRows;i++) {
00613       suitableRows_[i]=1;
00614     }
00615   }
00616   for (rowIndex=0; rowIndex<nRows; rowIndex++){
00617     double rhs1=rowupper[rowIndex];
00618     double rhs2=rowlower[rowIndex];
00619     if (suitableRows_[rowIndex]) {
00620       int i;
00621       bool goodRow=true;
00622       for (i=rowStart[rowIndex];
00623            i<rowStart[rowIndex]+rowLength[rowIndex];i++) {
00624         int thisCol=column[i];
00625         if (colupper[thisCol]-collower[thisCol]>epsilon_) {
00626           // could allow general integer variables but unlikely
00627           if (!si.isBinary(thisCol) ) {
00628             goodRow=false;
00629             break;
00630           }
00631           if (fabs(rowElements[i]-1.0)>epsilon_) {
00632             goodRow=false;
00633             break;
00634           }
00635         } else {
00636           rhs1 -= collower[thisCol]*rowElements[i];
00637           rhs2 -= collower[thisCol]*rowElements[i];
00638         }
00639       }
00640       if (fabs(rhs1-1.0)>epsilon_&&fabs(rhs2-1.0)>epsilon_) {
00641         goodRow=false;
00642       }
00643       if (goodRow) {
00644         suitableRows_[rowIndex]=1;
00645       } else {
00646         suitableRows_[rowIndex]=0;
00647       }
00648     }
00649   }
00650 }
00652 void CglOddHole::createRowList(int numberRows, const int * whichRow)
00653 {
00654   suitableRows_=new int [numberRows];
00655   numberRows_=numberRows;
00656   memcpy(suitableRows_,whichRow,numberRows*sizeof(int));
00657 }
00658 
00659 // Create a list of extra row cliques which may not be in matrix
00660 // At present these are classical cliques
00661 void CglOddHole::createCliqueList(int numberCliques, const int * cliqueStart,
00662                      const int * cliqueMember)
00663 {
00664   numberCliques_=numberCliques;
00665   startClique_=new int[numberCliques_+1];
00666   memcpy(startClique_,cliqueStart,(numberCliques_+1)*sizeof(int));
00667   int length=startClique_[numberCliques_];
00668   member_=new int[length];
00669   memcpy(member_,cliqueMember,length*sizeof(int));
00670 }
00671 // Returns how many rows might give three cycle cuts
00672 int CglOddHole::numberPossible()
00673 {
00674   int i,n=0;
00675   for (i=0;i<numberRows_;i++) {
00676     if (suitableRows_[i]) n++;
00677   }
00678   return n;
00679 }
00680 
00681 
00682 //-------------------------------------------------------------------
00683 // Default Constructor 
00684 //-------------------------------------------------------------------
00685 CglOddHole::CglOddHole ()
00686 :
00687 CglCutGenerator(),
00688 epsilon_(1.0e-08),
00689 onetol_(1-epsilon_)
00690 {
00691   // null copy of suitable rows
00692   numberRows_=0;
00693   suitableRows_=NULL;
00694   startClique_=NULL;
00695   numberCliques_=0;
00696   member_=NULL;
00697   minimumViolation_=0.001;
00698   minimumViolationPer_=0.0003;
00699   maximumEntries_=100;
00700 }
00701 
00702 //-------------------------------------------------------------------
00703 // Copy constructor 
00704 //-------------------------------------------------------------------
00705 CglOddHole::CglOddHole (
00706                                                               const CglOddHole & source)
00707                                                               :
00708 CglCutGenerator(source),
00709 epsilon_(source.epsilon_),
00710 onetol_(source.onetol_)
00711 {  
00712   // copy list of suitable rows
00713   numberRows_=source.numberRows_;
00714   suitableRows_=new int[numberRows_];
00715   memcpy(suitableRows_,source.suitableRows_,numberRows_*sizeof(int));
00716   // copy list of cliques
00717   numberCliques_=source.numberCliques_;
00718   if (numberCliques_) {
00719     startClique_=new int[numberCliques_+1];
00720     memcpy(startClique_,source.startClique_,(numberCliques_+1)*sizeof(int));
00721     int length=startClique_[numberCliques_];
00722     member_=new int[length];
00723     memcpy(member_,source.member_,length*sizeof(int));
00724   } else {
00725     startClique_=NULL;
00726     member_=NULL;
00727   }
00728   minimumViolation_=source.minimumViolation_;
00729   minimumViolationPer_=source.minimumViolationPer_;
00730   maximumEntries_=source.maximumEntries_;
00731 }
00732 
00733 //-------------------------------------------------------------------
00734 // Destructor 
00735 //-------------------------------------------------------------------
00736 CglOddHole::~CglOddHole ()
00737 {
00738   // free memory
00739   delete [] suitableRows_;
00740   delete [] startClique_;
00741   delete [] member_;
00742 }
00743 
00744 //----------------------------------------------------------------
00745 // Assignment operator 
00746 //-------------------------------------------------------------------
00747 CglOddHole &
00748 CglOddHole::operator=(
00749                                          const CglOddHole& rhs)
00750 {
00751   if (this != &rhs) {
00752     CglCutGenerator::operator=(rhs);
00753     epsilon_=rhs.epsilon_;
00754     onetol_=rhs.onetol_;
00755     delete [] suitableRows_;
00756     // copy list of suitable rows
00757     numberRows_=rhs.numberRows_;
00758     suitableRows_=new int[numberRows_];
00759     memcpy(suitableRows_,rhs.suitableRows_,numberRows_*sizeof(int));
00760     delete [] startClique_;
00761     delete [] member_;
00762     // copy list of cliques
00763     numberCliques_=rhs.numberCliques_;
00764     if (numberCliques_) {
00765       startClique_=new int[numberCliques_+1];
00766       memcpy(startClique_,rhs.startClique_,(numberCliques_+1)*sizeof(int));
00767       int length=startClique_[numberCliques_];
00768       member_=new int[length];
00769       memcpy(member_,rhs.member_,length*sizeof(int));
00770     } else {
00771       startClique_=NULL;
00772       member_=NULL;
00773     }
00774     minimumViolation_=rhs.minimumViolation_;
00775     minimumViolationPer_=rhs.minimumViolationPer_;
00776     maximumEntries_=rhs.maximumEntries_;
00777   }
00778   return *this;
00779 }
00780 // Minimum violation
00781 double 
00782 CglOddHole::getMinimumViolation() const
00783 {
00784   return minimumViolation_;
00785 }
00786 void 
00787 CglOddHole::setMinimumViolation(double value)
00788 {
00789   if (value>1.0e-8&&value<=0.5)
00790     minimumViolation_=value;
00791 }
00792 // Minimum violation per entry
00793 double 
00794 CglOddHole::getMinimumViolationPer() const
00795 {
00796   return minimumViolationPer_;
00797 }
00798 void 
00799 CglOddHole::setMinimumViolationPer(double value)
00800 {
00801   if (value>1.0e-8&&value<=0.25)
00802     minimumViolationPer_=value;
00803 }
00804 // Maximum number of entries in a cut
00805 int 
00806 CglOddHole::getMaximumEntries() const
00807 {
00808   return maximumEntries_;
00809 }
00810 void 
00811 CglOddHole::setMaximumEntries(int value)
00812 {
00813   if (value>2)
00814     maximumEntries_=value;
00815 }
00816 
00817 // This can be used to refresh any inforamtion
00818 void 
00819 CglOddHole::refreshSolver(OsiSolverInterface * solver)
00820 {
00821 }

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