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

CglOddHole Class Reference

#include <CglOddHole.hpp>

Inheritance diagram for CglOddHole:

CglCutGenerator List of all members.

Public Member Functions

Generate Cuts
virtual void generateCuts (const OsiSolverInterface &si, OsiCuts &cs) const
Create Row List
void createRowList (const OsiSolverInterface &si, const int *possible=NULL)
void createRowList (int numberRows, const int *whichRow)
 This version passes in a list - 1 marks possible.

Create Clique List
void createCliqueList (int numberCliques, const int *cliqueStart, const int *cliqueMember)
Number Possibilities
int numberPossible ()
 Returns how many rows might give odd hole cuts.

Gets and Sets
double getMinimumViolation () const
 Minimum violation.

void setMinimumViolation (double value)
double getMinimumViolationPer () const
 Minimum violation per entry.

void setMinimumViolationPer (double value)
int getMaximumEntries () const
 Maximum number of entries in a cut.

void setMaximumEntries (int value)
Constructors and destructors
 CglOddHole ()
 Default constructor.

 CglOddHole (const CglOddHole &)
 Copy constructor.

CglOddHoleoperator= (const CglOddHole &rhs)
 Assignment operator.

virtual ~CglOddHole ()
 Destructor.

virtual void refreshSolver (OsiSolverInterface *solver)
 This can be used to refresh any inforamtion.


Private Member Functions

Private methods
void generateCuts (const OsiRowCutDebugger *debugger, const CoinPackedMatrix &rowCopy, const double *solution, const double *dj, OsiCuts &cs, const int *suitableRow, const int *fixedColumn, bool packed)

Private Attributes

Private member data
int * suitableRows_
 list of suitableRows

int * startClique_
 start of each clique

int * member_
 clique members

double epsilon_
 epsilon

double onetol_
 1-epsilon

double minimumViolation_
 Minimum violation.

double minimumViolationPer_
 Minimum violation per entry.

int maximumEntries_
 Maximum number of entries in a cut.

int numberRows_
 number of rows when suitability tested

int numberCliques_
 number of cliques


Friends

void CglOddHoleUnitTest (const OsiSolverInterface *siP, const std::string mpdDir)

Detailed Description

Odd Hole Cut Generator Class

Definition at line 11 of file CglOddHole.hpp.


Member Function Documentation

void CglOddHole::createCliqueList int  numberCliques,
const int *  cliqueStart,
const int *  cliqueMember
 

Create a list of extra row cliques which may not be in matrix At present these are classical cliques

Definition at line 661 of file CglOddHole.cpp.

References member_, numberCliques_, and startClique_.

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 }

void CglOddHole::createRowList const OsiSolverInterface &  si,
const int *  possible = NULL
 

Create a list of rows which might yield cuts this is to speed up process The possible parameter is a list to cut down search

Definition at line 585 of file CglOddHole.cpp.

References epsilon_, numberRows_, and suitableRows_.

Referenced by generateCuts().

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 }

void CglOddHole::generateCuts const OsiRowCutDebugger *  debugger,
const CoinPackedMatrix &  rowCopy,
const double *  solution,
const double *  dj,
OsiCuts &  cs,
const int *  suitableRow,
const int *  fixedColumn,
bool  packed
[private]
 

Generate cuts from matrix copy and solution If packed true then <=1 rows, otherwise >=1 rows.

Definition at line 147 of file CglOddHole.cpp.

References CoinPackedVectorBase::dotProduct(), maximumEntries_, minimumViolation_, minimumViolationPer_, and CoinPackedVector::sortIncrIndex().

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 }

void CglOddHole::generateCuts const OsiSolverInterface &  si,
OsiCuts &  cs
const [virtual]
 

Generate odd hole cuts for the model of the solver interface, si. This looks at all rows of type sum x(i) <= 1 (or == 1) (x 0-1) and sees if there is an odd cycle cut. See Grotschel, Lovasz and Schrijver (1988) for method. This is then lifted by using the corresponding Chvatal cut i.e. Take all rows in cycle and add them together. RHS will be odd so weaken all odd coefficients so 1.0 goes to 0.0 etc - then constraint is sum even(j)*x(j) <= odd which can be replaced by sum (even(j)/2)*x(j) <= (odd-1.0)/2. A similar cut can be generated for sum x(i) >= 1.

Insert the generated cuts into OsiCut, cs.

This is only done for rows with unsatisfied 0-1 variables. If there are many of these it will be slow. Improvements would do a randomized subset and also speed up shortest path algorithm used.

Implements CglCutGenerator.

Definition at line 32 of file CglOddHole.cpp.

References createRowList(), epsilon_, numberRows_, onetol_, and suitableRows_.

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 }


Friends And Related Function Documentation

void CglOddHoleUnitTest const OsiSolverInterface *  siP,
const std::string  mpdDir
[friend]
 

A function that tests the methods in the CglOddHole class. The only reason for it not to be a member method is that this way it doesn't have to be compiled into the library. And that's a gain, because the library should be compiled with optimization on, but this method should be compiled with debugging.

Definition at line 23 of file CglOddHoleTest.cpp.

00026 {
00027   CoinRelFltEq eq(0.000001);
00028 
00029   // Test default constructor
00030   {
00031     CglOddHole aGenerator;
00032   }
00033   
00034   // Test copy & assignment
00035   {
00036     CglOddHole rhs;
00037     {
00038       CglOddHole bGenerator;
00039       CglOddHole cGenerator(bGenerator);
00040       rhs=bGenerator;
00041     }
00042   }
00043 
00044 
00045   // test on simple case
00046   {  
00047     const int nRows=3;
00048     const int nCols=3;
00049     const int nEls=6;
00050     const double elem[]={1.0,1.0,1.0,1.0,1.0,1.0};
00051     const int row[]={0,1,0,2,1,2};
00052     const int start[]={0,2,4};
00053     const int len[]={2,2,2};
00054     CoinPackedMatrix matrix(true,nRows,nCols,nEls,elem,row,start,len);
00055     const double sol[]={0.5,0.5,0.5};
00056     const double dj[]={0,0,0};
00057     const int which[]={1,1,1};
00058     const int fixed[]={0,0,0};
00059     OsiCuts cs;
00060     CglOddHole test1;
00061     test1.generateCuts(NULL,matrix,sol,dj,cs,which,fixed,true);
00062     CoinPackedVector check;
00063     int index[] = {0,1,2};
00064     double el[] = {1,1,1};
00065     check.setVector(3,index,el);
00066     //assert (cs.sizeRowCuts()==2);
00067     assert (cs.sizeRowCuts()==1);
00068     // sort Elements in increasing order
00069     CoinPackedVector rpv=cs.rowCut(0).row();
00070     rpv.sortIncrIndex();
00071     assert (check==rpv);
00072   }
00073   
00074   // Testcase /u/rlh/osl2/mps/scOneInt.mps
00075   // Model has 3 continous, 2 binary, and 1 general
00076   // integer variable.
00077   {
00078     OsiSolverInterface  * siP = baseSiP->clone();
00079     
00080     std::string fn = mpsDir+"scOneInt";
00081     siP->readMps(fn.c_str(),"mps");
00082 #if 0
00083     CglOddHole cg;
00084     int nCols=siP->getNumCols();
00085     
00086     // Test the siP methods for detecting
00087     // variable type
00088     int numCont=0, numBinary=0, numIntNonBinary=0, numInt=0;
00089     for (int thisCol=0; thisCol<nCols; thisCol++) {
00090       if ( siP->isContinuous(thisCol) ) numCont++;
00091       if ( siP->isBinary(thisCol) ) numBinary++;
00092       if ( siP->isIntegerNonBinary(thisCol) ) numIntNonBinary++;
00093       if ( siP->isInteger(thisCol) ) numInt++;
00094     }
00095     assert(numCont==3);
00096     assert(numBinary==2);
00097     assert(numIntNonBinary==1);
00098     assert(numInt==3);
00099     
00100     
00101     // Test initializeCutGenerator
00102     siP->initialSolve();
00103     assert(xstar !=NULL);
00104     for (i=0; i<nCols; i++){
00105       assert(complement[i]==0);
00106     }
00107     int nRows=siP->getNumRows();
00108     for (i=0; i<nRows; i++){
00109     int vectorsize = siP->getMatrixByRow()->getVectorSize(i);
00110     assert(vectorsize==2);
00111     }
00112     
00113     kccg.cleanUpCutGenerator(complement,xstar);
00114 #endif  
00115     delete siP;
00116   }
00117 
00118 }


The documentation for this class was generated from the following files:
Generated on Wed Dec 3 14:34:58 2003 for Cgl by doxygen 1.3.5