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

CglGomory Class Reference

#include <CglGomory.hpp>

Inheritance diagram for CglGomory:

CglCutGenerator List of all members.

Public Member Functions

Generate Cuts
virtual void generateCuts (const OsiSolverInterface &si, OsiCuts &cs) const
int generateCuts (const OsiRowCutDebugger *debugger, OsiCuts &cs, const CoinPackedMatrix &columnCopy, const double *objective, const double *colsol, const double *colLower, const double *colUpper, const double *rowLower, const double *rowUpper, const char *intVar, const CoinWarmStartBasis *warm) const
Change limit on how many variables in cut (default 50)
void setLimit (int limit)
 Set.

int getLimit () const
 Get.

Change criterion on which variables to look at. All ones
more than "away" away from integrality will be investigated (default 0.05)

void setAway (double value)
 Set.

double getAway () const
 Get.

Constructors and destructors
 CglGomory ()
 Default constructor.

 CglGomory (const CglGomory &)
 Copy constructor.

CglGomoryoperator= (const CglGomory &rhs)
 Assignment operator.

virtual ~CglGomory ()
 Destructor.


Private Attributes

Private member data
double away_
 Only investigate if more than this away from integrality.

int limit_
 Limit - only generate if fewer than this in cut.


Friends

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

Detailed Description

Gomory Cut Generator Class

Definition at line 12 of file CglGomory.hpp.


Member Function Documentation

int CglGomory::generateCuts const OsiRowCutDebugger *  debugger,
OsiCuts &  cs,
const CoinPackedMatrix &  columnCopy,
const double *  objective,
const double *  colsol,
const double *  colLower,
const double *  colUpper,
const double *  rowLower,
const double *  rowUpper,
const char *  intVar,
const CoinWarmStartBasis warm
const
 

Generates cuts given matrix and solution etc, returns number of cuts generated

Definition at line 198 of file CglGomory.cpp.

References CoinIndexedVector::add(), away_, CoinIndexedVector::checkClear(), CoinIndexedVector::clear(), CoinIndexedVector::denseVector(), CoinWarmStartBasis::getArtifStatus(), CoinIndexedVector::getIndices(), CoinIndexedVector::getNumElements(), CoinWarmStartBasis::getStructStatus(), limit_, CoinIndexedVector::reserve(), CoinIndexedVector::setNumElements(), and CoinIndexedVector::setVector().

00206 {
00207   int numberRows=columnCopy.getNumRows();
00208   int numberColumns=columnCopy.getNumCols(); 
00209   
00210   // Start of code to create a factorization from warm start (A) ====
00211   // check factorization is okay
00212   CoinFactorization factorization;
00213   // We can either set increasing rows so ...IsBasic gives pivot row
00214   // or we can just increment iBasic one by one
00215   // for now let ...iBasic give pivot row
00216   factorization.increasingRows(2);
00217   int status=-100;
00218   // probably could use pivotVariables from OsiSimplexModel
00219   int * rowIsBasic = new int[numberRows];
00220   int * columnIsBasic = new int[numberColumns];
00221   int i;
00222   int numberBasic=0;
00223   for (i=0;i<numberRows;i++) {
00224     if (warm->getArtifStatus(i) == CoinWarmStartBasis::basic) {
00225       rowIsBasic[i]=1;
00226       numberBasic++;
00227     } else {
00228       rowIsBasic[i]=-1;
00229     }
00230   }
00231   for (i=0;i<numberColumns;i++) {
00232     if (warm->getStructStatus(i) == CoinWarmStartBasis::basic) {
00233       columnIsBasic[i]=1;
00234       numberBasic++;
00235     } else {
00236       columnIsBasic[i]=-1;
00237     }
00238   }
00239   //returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */
00240   while (status<-98) {
00241     status=factorization.factorize(columnCopy,
00242                                    rowIsBasic, columnIsBasic);
00243     if (status==-99) factorization.areaFactor(factorization.areaFactor() * 2.0);
00244   } 
00245   if (status) {
00246     std::cout<<"Bad factorization of basis - status "<<status<<std::endl;
00247     return -1;
00248   }
00249   // End of creation of factorization (A) ====
00250   
00251   double bounds[2]={-DBL_MAX,0.0};
00252   int iColumn,iRow;
00253 
00254   // get row copy of matrix
00255   CoinPackedMatrix rowCopy =  columnCopy;
00256   rowCopy.reverseOrdering();
00257   const int * column = rowCopy.getIndices();
00258   const int * rowStart = rowCopy.getVectorStarts();
00259   const int * rowLength = rowCopy.getVectorLengths(); 
00260   const double * rowElements = rowCopy.getElements();
00261   const int * row = columnCopy.getIndices();
00262   const int * columnStart = columnCopy.getVectorStarts();
00263   const int * columnLength = columnCopy.getVectorLengths(); 
00264   const double * columnElements = columnCopy.getElements();
00265 
00266   // we need to do book-keeping for variables at ub
00267   double tolerance = 1.0e-7;
00268   bool * swap= new bool [numberColumns];
00269   for (iColumn=0;iColumn<numberColumns;iColumn++) {
00270     if (columnIsBasic[iColumn]<0&&
00271         colUpper[iColumn]-colsol[iColumn]<=tolerance) {
00272       swap[iColumn]=true;
00273     } else {
00274       swap[iColumn]=false;
00275     }
00276   }
00277 
00278   // get row activities (could use solver but lets do here )
00279   double * rowActivity = new double [numberRows];
00280   CoinFillN(rowActivity,numberRows,0.0);
00281   for (iColumn=0;iColumn<numberColumns;iColumn++) {
00282     double value = colsol[iColumn];
00283     int k;
00284     for (k=columnStart[iColumn];k<columnStart[iColumn]+columnLength[iColumn];k++) {
00285       iRow = row[k];
00286       rowActivity[iRow] += columnElements[k]*value;
00287     }
00288   }
00289   /* we need to mark rows:
00290      0) equality
00291      1) slack at lb (activity at ub)
00292      2) slack at ub (activity at lb)
00293      and 4 bit is set if slack must be integer
00294 
00295   */
00296   int * rowType = new int[numberRows];
00297   for (iRow=0;iRow<numberRows;iRow++) {
00298     if (rowIsBasic[iRow]<0&&rowUpper[iRow]>rowLower[iRow]+1.0e-7) {
00299       int type=0;
00300       double rhs=0.0;
00301       if (rowActivity[iRow]>=rowUpper[iRow]-1.0e-7) {
00302         type=1;
00303         rhs=rowUpper[iRow];
00304       } else if (rowActivity[iRow]<=rowLower[iRow]+1.0e-7) {
00305         type=2;
00306         rhs=rowLower[iRow];
00307       } else {
00308         // wrong - but probably large rhs
00309         rowType[iRow]=type;
00310 #ifdef CGL_DEBUG
00311         assert (min(rowUpper[iRow]-rowActivity[iRow],
00312                     rowActivity[iRow]-rowUpper[iRow])<1.0e-7);
00313         abort();
00314 #else
00315         continue;
00316 #endif
00317       }
00318       if (above_integer(rhs)<1.0e-10) {
00319         // could be integer slack
00320         bool allInteger=true;
00321         int k;
00322         for (k=rowStart[iRow];
00323              k<rowStart[iRow]+rowLength[iRow];k++) {
00324           int iColumn=column[k];
00325           if (!intVar[iColumn]||above_integer(rowElements[k])>1.0e-10) {
00326             // not integer slacks
00327             allInteger=false;
00328             break;
00329           }
00330         }
00331         if (allInteger) {
00332           type |= 4;
00333         }
00334       }
00335       rowType[iRow]=type;
00336     } else {
00337       // row is equality or basic
00338       rowType[iRow]=0;
00339     }
00340   }
00341 
00342   // Start of code to create work arrays for factorization (B) ====
00343   // two vectors for updating (one is work)
00344   CoinIndexedVector work;
00345   CoinIndexedVector array;
00346   // make sure large enough
00347   work.reserve(numberRows);
00348   array.reserve(numberRows);
00349   int * arrayRows = array.getIndices();
00350   double * arrayElements = array.denseVector();
00351   // End of code to create work arrays (B) ====
00352 
00353   int numberAdded=0;
00354   // we also need somewhere to accumulate cut
00355   CoinIndexedVector cutVector;
00356   cutVector.reserve(numberColumns+1);
00357   int * cutIndex = cutVector.getIndices();
00358   double * cutElement = cutVector.denseVector(); 
00359   // and for packed form (as not necessarily in order)
00360   double * packed = new double[numberColumns+1];
00361 
00362   for (iColumn=0;iColumn<numberColumns;iColumn++) {
00363     double reducedValue=above_integer(colsol[iColumn]);;
00364     // This returns pivot row for columns or -1 if not basic (C) ====
00365     int iBasic=columnIsBasic[iColumn];
00366     double ratio=reducedValue/(1.0-reducedValue);
00367     if (iBasic>=0) {
00368   // Debug code below computes tableau column of basic ====
00369       int j;
00370 #ifdef CGL_DEBUG
00371       {
00372         // put column into array
00373         array.setVector(columnLength[iColumn],row+columnStart[iColumn],
00374                         columnElements+columnStart[iColumn]);
00375         // get column in tableau
00376         factorization.updateColumn ( &work, &array );
00377         int nn=0;
00378         int numberInArray=array.getNumElements();
00379         for (j=0;j<numberInArray;j++) {
00380           int indexValue=arrayRows[j];
00381           double value=arrayElements[indexValue];
00382           if (fabs(value)>1.0e-6) {
00383             assert (fabs(value-1.0)<1.0e-7);
00384             assert (indexValue==iBasic);
00385             nn++;
00386           }
00387         }
00388         assert (nn==1);
00389       }
00390 #endif
00391       if(intVar[iColumn]&&reducedValue<1.0-away_&&reducedValue>away_) {
00392 #ifdef CGL_DEBUG
00393         cutVector.checkClear();
00394 #endif
00395         // get row of tableau
00396         double one =1.0;
00397         array.setVector(1,&iBasic,&one);
00398         int numberNonInteger=0;
00399         //Code below computes tableau row ====
00400         // get pi
00401         factorization.updateColumnTranspose ( &work, &array );
00402         int numberInArray=array.getNumElements();
00403         // check pivot on iColumn
00404         {
00405           double value=0.0;
00406           int k;
00407           // add in row of tableau
00408           for (k=columnStart[iColumn];
00409                k<columnStart[iColumn]+columnLength[iColumn];k++) {
00410             iRow = row[k];
00411             value += columnElements[k]*arrayElements[iRow];
00412           }
00413           // should be 1
00414 #ifdef CGL_DEBUG
00415           assert (fabs(value-1.0) < 1.0e-7);
00416 #endif
00417         }
00418         //reducedValue=colsol[iColumn];
00419         // coding from pg 130 of Wolsey 
00420         // adjustment to rhs
00421         double rhs=0.0;
00422         int number=0;
00423         // columns
00424         for (j=0;j<numberColumns;j++) {
00425           double value=0.0;
00426           if (columnIsBasic[j]<0&&
00427               colUpper[j]>colLower[j]+1.0e-8) {
00428             int k;
00429             // add in row of tableau
00430             for (k=columnStart[j];k<columnStart[j]+columnLength[j];k++) {
00431               iRow = row[k];
00432               value += columnElements[k]*arrayElements[iRow];
00433             }
00434             // value is entry in tableau row end (C) ====
00435             if (fabs(value)<1.0e-16) {
00436               // small value
00437               continue;
00438             } else {
00439 #if CGL_DEBUG>1
00440               if (iColumn==314) printf("for basic %d, column %d has alpha %g, colsol %g\n",
00441                      iColumn,j,value,colsol[j]);
00442 #endif
00443               // deal with bounds
00444               if (swap[j]) {
00445                 //reducedValue -= value*colUpper[j];
00446                 // negate
00447                 value = - value;
00448               } else {
00449                 //reducedValue -= value*colLower[j];
00450               }
00451 #if CGL_DEBUG>1
00452               if (iColumn==348) printf("%d value %g reduced %g int %d rhs %g swap %d\n",
00453                      j,value,reducedValue,intVar[j],rhs,swap[j]);
00454 #endif
00455               double coefficient;
00456               if (intVar[j]) {
00457                 // integer
00458                 coefficient = above_integer(value);
00459                 if (coefficient > reducedValue) {
00460                   coefficient = ratio * (1.0-coefficient);
00461                 } 
00462               } else {
00463                 // continuous
00464                 numberNonInteger++;
00465                 if (value > 0.0) {
00466                   coefficient = value;
00467                 } else {
00468                   //??? sign wrong in book
00469                   coefficient = -ratio*value;
00470                 }
00471               }
00472               if (swap[j]) {
00473                 // negate
00474                 coefficient = - coefficient;
00475                 rhs += colUpper[j]*coefficient;
00476               } else {
00477                 rhs += colLower[j]*coefficient;
00478               }
00479               if (fabs(coefficient)>= COIN_INDEXED_TINY_ELEMENT) {
00480                  cutElement[j] = coefficient;
00481                  cutIndex[number++]=j;
00482                  // If too many - break from loop
00483                  if (number>limit_) 
00484                    break;
00485               }
00486             }
00487           } else {
00488             // basic
00489             continue;
00490           }
00491         }
00492         cutVector.setNumElements(number);
00493         // If too many - just clear vector and skip
00494         if (number>limit_) {
00495           cutVector.clear();
00496           continue;
00497         }
00498         //check will be cut
00499         //reducedValue=above_integer(reducedValue);
00500         rhs += reducedValue;
00501         double violation = reducedValue;
00502 #ifdef CGL_DEBUG
00503         std::cout<<"cut has violation of "<<violation
00504                  <<" value "<<colsol[iColumn]<<std::endl;
00505 #endif
00506         // now do slacks part
00507         for (j=0;j<numberInArray;j++) {
00508           iRow=arrayRows[j];
00509           double value = arrayElements[iRow];
00510           int type=rowType[iRow];
00511           if (type&&fabs(value)>=1.0e-16) {
00512             if ((type&1)==0) {
00513               // negate to get correct coefficient
00514               value = - value;
00515             }
00516             double coefficient;
00517             if ((type&4)!=0) {
00518               // integer
00519               coefficient = above_integer(value);
00520               if (coefficient > reducedValue) {
00521                 coefficient = ratio * (1.0-coefficient);
00522               } 
00523             } else {
00524               numberNonInteger++;
00525               // continuous
00526               if (value > 0.0) {
00527                 coefficient = value;
00528               } else {
00529                 coefficient = -ratio*value;
00530               }
00531             }
00532             if ((type&1)!=0) {
00533               // slack at ub - treat as +1.0
00534               rhs -= coefficient*rowUpper[iRow];
00535             } else {
00536               // negate yet again ?
00537               coefficient = - coefficient;
00538               rhs -= coefficient*rowLower[iRow];
00539             }
00540             int k;
00541             for (k=rowStart[iRow];
00542                  k<rowStart[iRow]+rowLength[iRow];k++) {
00543               int jColumn=column[k];
00544               double value=rowElements[k];
00545               cutVector.add(jColumn,-coefficient*value);
00546             }
00547           }
00548         }
00549         //check again and pack down
00550         // also change signs
00551         // also zero cutElement
00552         double sum=0.0;
00553         rhs = - rhs;
00554         int n = cutVector.getNumElements();
00555         number=0;
00556         for (j=0;j<n;j++) {
00557           int jColumn =cutIndex[j];
00558           double value=-cutElement[jColumn];
00559           cutElement[jColumn]=0.0;
00560           if (fabs(value)>1.0e-13) {
00561             sum+=value*colsol[jColumn];
00562             packed[number]=value;
00563             cutIndex[number++]=jColumn;
00564           }
00565         }
00566         // say zeroed out
00567         cutVector.setNumElements(0);
00568         if (sum >rhs+0.9*away_&&
00569             fabs((sum-rhs)-violation)<1.0e-6) {
00570           //#ifdef CGL_DEBUG
00571 #ifdef CGL_DEBUG
00572 #if CGL_DEBUG<=1
00573           if (number<=-10) {
00574 #endif
00575             for (j=0;j<number;j++) {
00576               std::cout<<" ["<<cutIndex[j]<<","<<packed[j]<<"]";
00577             }
00578             std::cout<<" <= "<<rhs<<std::endl;
00579 #if CGL_DEBUG<=1
00580           }
00581 #endif
00582 #endif
00583           if (!numberNonInteger&&number) {
00584 #ifdef CGL_DEBUG
00585             assert (sizeof(Rational)==sizeof(double));
00586 #endif
00587             Rational * cleaned = (Rational *) cutElement;
00588             int * xInt = (int *) cutElement;
00589             // cut should have an integer slack so try and simplify
00590             // add in rhs and put in cutElements (remember to zero later)
00591             cutIndex[number]=numberColumns+1;
00592             packed[number]=rhs;
00593             int numberNonSmall=0;
00594             int lcm = 1;
00595             
00596             for (j=0;j<number+1;j++) {
00597               double value=above_integer(fabs(packed[j]));
00598               if (fabs(value)<1.0e-4) {
00599                 // too small
00600                 continue;
00601               } else {
00602                 numberNonSmall++;
00603               }
00604               
00605               cleaned[j]=nearestRational(value,100000);
00606               if (cleaned[j].denominator<0) {
00607                 // bad rational
00608                 lcm=-1;
00609                 break;
00610               }
00611               int thisGcd = gcd(lcm,cleaned[j].denominator);
00612               // may need to check for overflow
00613               lcm /= thisGcd;
00614               lcm *= cleaned[j].denominator;
00615             }
00616             if (lcm>0&&numberNonSmall) {
00617               double multiplier = lcm;
00618               int nOverflow = 0; 
00619               for (j=0; j<number+1;j++) {
00620                 double value = fabs(packed[j]);
00621                 double dxInt = value*multiplier;
00622                 xInt[j]= (int) (dxInt+0.5); 
00623 #if CGL_DEBUG>1
00624                 printf("%g => %g   \n",value,dxInt);
00625 #endif
00626                 if (dxInt>1.0e9||fabs(dxInt-xInt[j])> 1.0e-8) {
00627                   nOverflow++;
00628                   break;
00629                 }
00630               }
00631               
00632               if (nOverflow){
00633 #ifdef CGL_DEBUG
00634                 printf("Gomory Scaling: Warning: Overflow detected \n");
00635 #endif
00636                 numberNonInteger=-1;
00637               } else {
00638                 
00639                 // find greatest common divisor of the elements
00640                 j=0;
00641                 while (!xInt[j])
00642                   j++; // skip zeros
00643                 int thisGcd = gcd(xInt[j],xInt[j+1]);
00644                 j++;
00645                 for (;j<number+1;j++) {
00646                   if (xInt[j])
00647                     thisGcd = gcd(thisGcd,xInt[j]);
00648                 }
00649 #if 0
00650                 // Check nothing too illegal - FIX this
00651                 for (j=0;j<number+1;j++) {
00652                   double old = lcm*packed[j];
00653                   int newOne;
00654                   if (old>0.0)
00655                     newOne=xInt[j]/thisGcd;
00656                   else
00657                     newOne=-xInt[j]/thisGcd;
00658                   if (fabs(((double) newOne)-old)>
00659                       1.0e-10*(fabs(newOne)+1.0)) {
00660                     // say no good - first see if happens
00661                     printf("Fix this test 456 - just skip\n");
00662                     abort();
00663                   }
00664                 } 
00665 #endif            
00666 #if CGL_DEBUG>1
00667                 printf("The gcd of xInt is %i\n",thisGcd);    
00668 #endif
00669                 
00670                 // construct new cut by dividing through by gcd and 
00671                 double minMultiplier=1.0e100;
00672                 double maxMultiplier=0.0;
00673                 for (j=0; j<number+1;j++) {
00674                   double old=packed[j];
00675                   if (old>0.0) {
00676                     packed[j]=xInt[j]/thisGcd;
00677                   } else {
00678                     packed[j]=-xInt[j]/thisGcd;
00679                   }
00680 #if CGL_DEBUG>1
00681                   printf("%g => %g   \n",old,packed[j]);
00682 #endif
00683                   if (packed[j]) {
00684                     if (fabs(packed[j])>maxMultiplier*fabs(old))
00685                       maxMultiplier = packed[j]/old;
00686                     if (fabs(packed[j])<minMultiplier*fabs(old))
00687                       minMultiplier = packed[j]/old;
00688                   }
00689                 }
00690                 rhs = packed[number];
00691                 double ratio=maxMultiplier/minMultiplier;
00692 #ifdef CGL_DEBUG
00693                 printf("min, max multipliers - %g, %g\n",
00694                        minMultiplier,maxMultiplier);
00695 #endif
00696                 assert(ratio>0.9999&&ratio<1.0001);
00697               }
00698             }
00699             // erase cutElement
00700             CoinFillN(cutElement,number+1,0.0);
00701           } else {
00702             // relax rhs a tiny bit
00703             rhs += 1.0e-8;
00704             // relax if lots of elements for mixed gomory
00705             if (number>=20) {
00706               rhs  += 1.0e-7*((double) (number/20));
00707             }
00708           }
00709           // Take off tiny elements
00710           // for first pass reject
00711 #define TINY_ELEMENT 1.0e-7
00712           {
00713             int i,number2=number;
00714             number=0;
00715             double largest=0.0;
00716             double smallest=1.0e30;
00717             for (i=0;i<number2;i++) {
00718               double value=fabs(packed[i]);
00719               if (value<TINY_ELEMENT) {
00720                 int iColumn = cutIndex[i];
00721                 if (colUpper[iColumn]-colLower[iColumn]<10.0) {
00722                   // weaken cut
00723                   if (packed[i]>0.0) 
00724                     rhs -= value*colLower[iColumn];
00725                   else
00726                     rhs += value*colUpper[iColumn];
00727                 } else {
00728                   // throw away
00729                   number=limit_+1;
00730                   numberNonInteger=1;
00731                   break;
00732                 }
00733               } else {
00734                 largest=max(largest,value);
00735                 smallest=min(smallest,value);
00736                 cutIndex[number]=cutIndex[i];
00737                 packed[number++]=packed[i];
00738               }
00739             }
00740             if (largest>1.0e9*smallest) {
00741               number=limit_+1; //reject
00742               numberNonInteger=1;
00743             }
00744           }
00745           if (number<limit_||!numberNonInteger) {
00746             bounds[1]=rhs;
00747             if (number>50&&numberNonInteger)
00748               bounds[1] += 1.0e-6; // weaken
00749             {
00750               OsiRowCut rc;
00751               rc.setRow(number,cutIndex,packed);
00752               rc.setLb(bounds[0]);
00753               rc.setUb(bounds[1]);   
00754               cs.insert(rc);
00755 #ifdef CGL_DEBUG
00756               if (!number)
00757                 std::cout<<"******* Empty cut - infeasible"<<std::endl;
00758               if (debugger) 
00759                 assert(!debugger->invalidCut(rc)); 
00760 #endif
00761             }
00762             numberAdded++;
00763           } else {
00764 #ifdef CGL_DEBUG
00765             std::cout<<"cut has "<<number<<" entries - skipped"
00766                      <<std::endl;
00767             if (!number)
00768               std::cout<<"******* Empty cut - infeasible"<<std::endl;
00769 #endif
00770           }
00771         } else {
00772           // why dropped?
00773 #ifdef CGL_DEBUG
00774           std::cout<<"first violation "<<violation<<" now "
00775                    <<sum-rhs<<" why?, rhs= "<<rhs<<std::endl;
00776           
00777           for (j=0;j<number;j++) {
00778             int jColumn =cutIndex[j];
00779             double value=packed[j];
00780             std::cout<<"("<<jColumn<<","<<value<<","<<colsol[jColumn]
00781                      <<") ";
00782           }
00783           std::cout<<std::endl;
00784           abort();
00785 #endif
00786         }
00787       }
00788     } else {
00789       // not basic
00790 #if CGL_DEBUG>1
00791       {
00792         // put column into array
00793         array.setVector(columnLength[iColumn],row+columnStart[iColumn],
00794                         columnElements+columnStart[iColumn]);
00795         // get column in tableau
00796         factorization.updateColumn ( &work, &array );
00797         int numberInArray=array.getNumElements();
00798         printf("non-basic %d\n",iColumn);
00799         for (j=0;j<numberInArray;j++) {
00800           int indexValue=arrayRows[j];
00801           double value=arrayElements[indexValue];
00802           if (fabs(value)>1.0e-6) {
00803             printf("%d %g\n",indexValue,value);
00804           }
00805         }
00806       }
00807 #endif
00808     }
00809   }
00810 
00811   delete [] rowActivity;
00812   delete [] swap;
00813   delete [] rowType;
00814   delete [] packed;
00815   delete [] rowIsBasic;
00816   delete [] columnIsBasic;
00817   return numberAdded;
00818 }

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

Generate Mixed Integer Gomory cuts for the model of the solver interface, si.

Insert the generated cuts into OsiCut, cs.

There is a limit option, which will only generate cuts with less than this number of entries.

We can also only look at 0-1 variables a certain distance from integer.

Implements CglCutGenerator.

Definition at line 26 of file CglGomory.cpp.

00028 {
00029   // Get basic problem information
00030   int numberColumns=si.getNumCols(); 
00031 
00032   // get integer variables and basis
00033   char * intVar = new char[numberColumns];
00034   int i;
00035   CoinWarmStart * warmstart = si.getWarmStart();
00036   const CoinWarmStartBasis* warm =
00037     dynamic_cast<const CoinWarmStartBasis*>(warmstart);
00038   const double * colUpper = si.getColUpper();
00039   const double * colLower = si.getColLower();
00040   for (i=0;i<numberColumns;i++) {
00041     if (si.isInteger(i)) {
00042       if (colUpper[i]>colLower[i]+0.5) {
00043         if (fabs(colUpper[i]-1.0)<1.0e-12&&fabs(colLower[i])<1.0e-12) {
00044           intVar[i]=1; //0-1
00045         } else  if (colLower[i]>=0.0) {
00046           intVar[i] = 2; // other
00047         } else {
00048           // negative bounds - I am not sure works
00049           intVar[i] = 0;
00050         }
00051       } else {
00052         intVar[i] = 0;
00053       }
00054     } else {
00055       intVar[i]=0;
00056     }
00057   }
00058 #ifdef CGL_DEBUG
00059   const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
00060   if (debugger&&!debugger->onOptimalPath(si))
00061     debugger = NULL;
00062 #else
00063   const OsiRowCutDebugger * debugger = NULL;
00064 #endif
00065 
00066   generateCuts(debugger, cs, *si.getMatrixByCol(),
00067            si.getObjCoefficients(), si.getColSolution(),
00068            si.getColLower(), si.getColUpper(), 
00069            si.getRowLower(), si.getRowUpper(),
00070            intVar,warm);
00071 
00072   delete warmstart;
00073   delete [] intVar;
00074 }


Friends And Related Function Documentation

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

A function that tests the methods in the CglGomory 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 25 of file CglGomoryTest.cpp.

00028 {
00029   CoinRelFltEq eq(0.000001);
00030 
00031   // Test default constructor
00032   {
00033     CglGomory aGenerator;
00034     assert (aGenerator.getLimit()==50);
00035     assert (aGenerator.getAway()==0.05);
00036   }
00037   
00038   // Test copy & assignment etc
00039   {
00040     CglGomory rhs;
00041     {
00042       CglGomory bGenerator;
00043       bGenerator.setLimit(99);
00044       bGenerator.setAway(0.2);
00045       CglGomory cGenerator(bGenerator);
00046       rhs=bGenerator;
00047       assert (rhs.getLimit()==99);
00048       assert (rhs.getAway()==0.2);
00049     }
00050   }
00051 
00052   // Test explicit form - all integer (pg 125 Wolsey)
00053   if (1) {
00054     OsiCuts osicuts;
00055     CglGomory test1;
00056     int i;
00057     int nOldCuts=0,nRowCuts;
00058  
00059     // matrix data
00060     //deliberate hiccup of 2 between 0 and 1
00061     int start[5]={0,4,7,8,9};
00062     int length[5]={2,3,1,1,1};
00063     int rows[11]={0,2,-1,-1,0,1,2,0,1,2};
00064     double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,1,1};
00065     CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length);
00066     
00067     // rim data (objective not used just yet)
00068     double objective[7]={-4.0,1.0,0.0,0.0,0.0,0.0,0.0};
00069     double rowLower[5]={14.0,3.0,3.0,1.0e10,1.0e10};
00070     double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10};
00071     double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0};
00072     double colUpper[7]={100.0,100.0,100.0,100.0,100.0,100.0,100.0};
00073   
00074     // integer
00075     char intVar[7]={2,2,2,2,2,2,2};
00076 
00077     // basis 1
00078     int rowBasis1[3]={-1,-1,-1};
00079     int colBasis1[5]={1,1,-1,-1,1};
00080     CoinWarmStartBasis warm;
00081     warm.setSize(5,3);
00082     for (i=0;i<3;i++) {
00083       if (rowBasis1[i]<0) {
00084         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00085       } else {
00086         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00087       }
00088     }
00089     for (i=0;i<5;i++) {
00090       if (colBasis1[i]<0) {
00091         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00092       } else {
00093         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00094       }
00095     }
00096 
00097     // solution 1
00098     double colsol1[5]={20.0/7.0,3.0,0.0,0.0,23.0/7.0};
00099     test1.generateCuts(NULL, osicuts, matrix,
00100                  objective, colsol1,
00101                  colLower, colUpper,
00102                  rowLower, rowUpper, intVar, &warm);
00103     nRowCuts = osicuts.sizeRowCuts();
00104     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00105     assert (nRowCuts==2);
00106     // cuts always <=
00107     int testCut=0; // test first cut as stronger
00108     double rhs=-6.0;
00109     double testCut1[5]={0.0,0.0,-1.0,-2.0,0.0};
00110     double * cut = testCut1;
00111     double * colsol = colsol1;
00112     for (i=nOldCuts; i<nRowCuts; i++){
00113       OsiRowCut rcut;
00114       CoinPackedVector rpv;
00115       rcut = osicuts.rowCut(i);
00116       rpv = rcut.row();
00117       const int n = rpv.getNumElements();
00118       const int * indices = rpv.getIndices();
00119       double* elements = rpv.getElements();
00120       double sum2=0.0;
00121       int k=0;
00122       double lb=rcut.lb();
00123       double ub=rcut.ub();
00124       for (k=0; k<n; k++){
00125         int column=indices[k];
00126         sum2 += colsol[column]*elements[k];
00127       }
00128       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
00129         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
00130         for (k=0; k<n; k++){
00131           int column=indices[k];
00132           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
00133             colsol[column]<<") ";
00134         }
00135         std::cout <<std::endl;
00136       }
00137       if (i-nOldCuts==testCut) {
00138         assert( eq(rhs,ub));
00139         assert(n==2);
00140         for (k=0; k<n; k++){
00141           int column=indices[k];
00142           assert (eq(cut[column],elements[k]));
00143         }
00144         // add cut
00145         // explicit slack
00146         matrix.setDimensions(-1,6);
00147         rpv.insert(5,1.0*7.0); // to get cut in book
00148         rowLower[3]=ub;
00149         rowUpper[3]=ub;
00150         matrix.appendRow(rpv);
00151       }
00152     }
00153     nOldCuts=nRowCuts;
00154     // basis 2
00155     int rowBasis2[4]={-1,-1,-1,-1};
00156     int colBasis2[6]={1,1,1,1,-1,-1};
00157     warm.setSize(6,4);
00158     for (i=0;i<4;i++) {
00159       if (rowBasis2[i]<0) {
00160         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00161       } else {
00162         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00163       }
00164     }
00165     for (i=0;i<6;i++) {
00166       if (colBasis2[i]<0) {
00167         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00168       } else {
00169         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00170       }
00171     }
00172 
00173     // solution 2
00174     double colsol2[6]={2.0,0.5,1.0,2.5,0.0,0.0};
00175     test1.generateCuts(NULL, osicuts, matrix,
00176                  objective, colsol2,
00177                  colLower, colUpper,
00178                  rowLower, rowUpper, intVar, &warm);
00179     nRowCuts = osicuts.sizeRowCuts();
00180     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00181     assert (nRowCuts-nOldCuts==2);
00182     // cuts always <=
00183     testCut=0; // test first cut as stronger
00184     rhs=-1.0;
00185     double testCut2[6]={0.0,0.0,0.0,0.0,-1.0,0.0};
00186     cut = testCut2;
00187     colsol = colsol2;
00188     for (i=nOldCuts; i<nRowCuts; i++){
00189       OsiRowCut rcut;
00190       CoinPackedVector rpv;
00191       rcut = osicuts.rowCut(i);
00192       rpv = rcut.row();
00193       const int n = rpv.getNumElements();
00194       const int * indices = rpv.getIndices();
00195       double* elements = rpv.getElements();
00196       double sum2=0.0;
00197       int k=0;
00198       double lb=rcut.lb();
00199       double ub=rcut.ub();
00200       for (k=0; k<n; k++){
00201         int column=indices[k];
00202         sum2 += colsol[column]*elements[k];
00203       }
00204       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
00205         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
00206         for (k=0; k<n; k++){
00207           int column=indices[k];
00208           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
00209             colsol[column]<<") ";
00210         }
00211         std::cout <<std::endl;
00212       }
00213       if (i-nOldCuts==testCut) {
00214         assert( eq(rhs,ub));
00215         assert(n==1);
00216         for (k=0; k<n; k++){
00217           int column=indices[k];
00218           assert (eq(cut[column],elements[k]));
00219         }
00220         // add cut
00221         // explicit slack
00222         matrix.setDimensions(-1,7);
00223         rpv.insert(6,1.0);
00224         rowLower[4]=ub;
00225         rowUpper[4]=ub;
00226         matrix.appendRow(rpv);
00227       }
00228     }
00229     nOldCuts=nRowCuts;
00230     // basis 3
00231     int rowBasis3[5]={-1,-1,-1,-1,-1};
00232     int colBasis3[7]={1,1,1,1,1,-1,-1};
00233     warm.setSize(7,5);
00234     for (i=0;i<5;i++) {
00235       if (rowBasis3[i]<0) {
00236         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00237       } else {
00238         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00239       }
00240     }
00241     for (i=0;i<7;i++) {
00242       if (colBasis3[i]<0) {
00243         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00244       } else {
00245         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00246       }
00247     }
00248 
00249     // solution 3
00250     double colsol3[7]={2.0,1.0,2.0,2.0,1.0,0.0,0.0};
00251     test1.generateCuts(NULL, osicuts, matrix,
00252                  objective, colsol3,
00253                  colLower, colUpper,
00254                  rowLower, rowUpper, intVar, &warm);
00255     nRowCuts = osicuts.sizeRowCuts();
00256     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00257     assert (nRowCuts==nOldCuts);
00258     
00259   }
00260   // Test explicit form - this time with x4 flipped
00261   if (1) {
00262     OsiCuts osicuts;
00263     CglGomory test1;
00264     int i;
00265     int nOldCuts=0,nRowCuts;
00266  
00267     // matrix data
00268     //deliberate hiccup of 2 between 0 and 1
00269     int start[5]={0,4,7,8,9};
00270     int length[5]={2,3,1,1,1};
00271     int rows[11]={0,2,-1,-1,0,1,2,0,1,2};
00272     double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,-1,1};
00273     CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length);
00274     
00275     // rim data (objective not used just yet)
00276     double objective[7]={-4.0,1.0,0.0,0.0,0.0,0.0,0.0};
00277     double rowLower[5]={14.0,-5.0,3.0,1.0e10,1.0e10};
00278     double rowUpper[5]={14.0,-5.0,3.0,-1.0e10,-1.0e10};
00279     double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0};
00280     double colUpper[7]={100.0,100.0,100.0,8.0,100.0,100.0,100.0};
00281   
00282     // integer
00283     char intVar[7]={2,2,2,2,2,2,2};
00284 
00285     // basis 1
00286     int rowBasis1[3]={-1,-1,-1};
00287     int colBasis1[5]={1,1,-1,-1,1};
00288     CoinWarmStartBasis warm;
00289     warm.setSize(5,3);
00290     for (i=0;i<3;i++) {
00291       if (rowBasis1[i]<0) {
00292         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00293       } else {
00294         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00295       }
00296     }
00297     for (i=0;i<5;i++) {
00298       if (colBasis1[i]<0) {
00299         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00300       } else {
00301         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00302       }
00303     }
00304 
00305     // solution 1
00306     double colsol1[5]={20.0/7.0,3.0,0.0,8.0,23.0/7.0};
00307     test1.generateCuts(NULL, osicuts, matrix,
00308                  objective, colsol1,
00309                  colLower, colUpper,
00310                  rowLower, rowUpper, intVar, &warm);
00311     nRowCuts = osicuts.sizeRowCuts();
00312     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00313     assert (nRowCuts==2);
00314     // cuts always <=
00315     int testCut=0; // test first cut as stronger
00316     double rhs=10.0;
00317     double testCut1[5]={0.0,0.0,-1.0,2.0,0.0};
00318     double * cut = testCut1;
00319     double * colsol = colsol1;
00320     for (i=nOldCuts; i<nRowCuts; i++){
00321       OsiRowCut rcut;
00322       CoinPackedVector rpv;
00323       rcut = osicuts.rowCut(i);
00324       rpv = rcut.row();
00325       const int n = rpv.getNumElements();
00326       const int * indices = rpv.getIndices();
00327       double* elements = rpv.getElements();
00328       double sum2=0.0;
00329       int k=0;
00330       double lb=rcut.lb();
00331       double ub=rcut.ub();
00332       for (k=0; k<n; k++){
00333         int column=indices[k];
00334         sum2 += colsol[column]*elements[k];
00335       }
00336       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
00337         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
00338         for (k=0; k<n; k++){
00339           int column=indices[k];
00340           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
00341             colsol[column]<<") ";
00342         }
00343         std::cout <<std::endl;
00344       }
00345       if (i-nOldCuts==testCut) {
00346         assert( eq(rhs,ub));
00347         assert(n==2);
00348         for (k=0; k<n; k++){
00349           int column=indices[k];
00350           assert (eq(cut[column],elements[k]));
00351         }
00352         // add cut
00353         // explicit slack
00354         matrix.setDimensions(-1,6);
00355         rpv.insert(5,1.0*7.0); // to get cut in book
00356         rowLower[3]=ub;
00357         rowUpper[3]=ub;
00358         matrix.appendRow(rpv);
00359       }
00360     }
00361     nOldCuts=nRowCuts;
00362     // basis 2
00363     int rowBasis2[4]={-1,-1,-1,-1};
00364     int colBasis2[6]={1,1,1,1,-1,-1};
00365     warm.setSize(6,4);
00366     for (i=0;i<4;i++) {
00367       if (rowBasis2[i]<0) {
00368         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00369       } else {
00370         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00371       }
00372     }
00373     for (i=0;i<6;i++) {
00374       if (colBasis2[i]<0) {
00375         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00376       } else {
00377         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00378       }
00379     }
00380 
00381     // solution 2
00382     double colsol2[6]={2.0,0.5,1.0,5.5,0.0,0.0};
00383     test1.generateCuts(NULL, osicuts, matrix,
00384                  objective, colsol2,
00385                  colLower, colUpper,
00386                  rowLower, rowUpper, intVar, &warm);
00387     nRowCuts = osicuts.sizeRowCuts();
00388     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00389     assert (nRowCuts-nOldCuts==2);
00390     // cuts always <=
00391     testCut=0; // test first cut as stronger
00392     rhs=-1.0;
00393     double testCut2[6]={0.0,0.0,0.0,0.0,-1.0,0.0};
00394     cut = testCut2;
00395     colsol = colsol2;
00396     for (i=nOldCuts; i<nRowCuts; i++){
00397       OsiRowCut rcut;
00398       CoinPackedVector rpv;
00399       rcut = osicuts.rowCut(i);
00400       rpv = rcut.row();
00401       const int n = rpv.getNumElements();
00402       const int * indices = rpv.getIndices();
00403       double* elements = rpv.getElements();
00404       double sum2=0.0;
00405       int k=0;
00406       double lb=rcut.lb();
00407       double ub=rcut.ub();
00408       for (k=0; k<n; k++){
00409         int column=indices[k];
00410         sum2 += colsol[column]*elements[k];
00411       }
00412       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
00413         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
00414         for (k=0; k<n; k++){
00415           int column=indices[k];
00416           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
00417             colsol[column]<<") ";
00418         }
00419         std::cout <<std::endl;
00420       }
00421       if (i-nOldCuts==testCut) {
00422         assert( eq(rhs,ub));
00423         assert(n==1);
00424         for (k=0; k<n; k++){
00425           int column=indices[k];
00426           assert (eq(cut[column],elements[k]));
00427         }
00428         // add cut
00429         // explicit slack
00430         matrix.setDimensions(-1,7);
00431         rpv.insert(6,1.0);
00432         rowLower[4]=ub;
00433         rowUpper[4]=ub;
00434         matrix.appendRow(rpv);
00435       }
00436     }
00437     nOldCuts=nRowCuts;
00438     // basis 3
00439     int rowBasis3[5]={-1,-1,-1,-1,-1};
00440     int colBasis3[7]={1,1,1,1,1,-1,-1};
00441     warm.setSize(7,5);
00442     for (i=0;i<5;i++) {
00443       if (rowBasis3[i]<0) {
00444         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00445       } else {
00446         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00447       }
00448     }
00449     for (i=0;i<7;i++) {
00450       if (colBasis3[i]<0) {
00451         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00452       } else {
00453         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00454       }
00455     }
00456 
00457     // solution 3
00458     double colsol3[7]={2.0,1.0,2.0,6.0,1.0,0.0,0.0};
00459     test1.generateCuts(NULL, osicuts, matrix,
00460                  objective, colsol3,
00461                  colLower, colUpper,
00462                  rowLower, rowUpper, intVar, &warm);
00463     nRowCuts = osicuts.sizeRowCuts();
00464     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00465     assert (nRowCuts==nOldCuts);
00466     
00467   }
00468   // Test with slacks 
00469   if (1) {
00470     OsiCuts osicuts;
00471     CglGomory test1;
00472     int i;
00473     int nOldCuts=0,nRowCuts;
00474  
00475     // matrix data
00476     //deliberate hiccup of 2 between 0 and 1
00477     int start[5]={0,4};
00478     int length[5]={2,3};
00479     int rows[11]={0,2,-1,-1,0,1,2};
00480     double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0};
00481     CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length);
00482     
00483     // rim data (objective not used just yet)
00484     double objective[2]={-4.0,1.0};
00485     double rowLower[5]={-1.0e10,-1.0e10,-1.0e10,1.0e10,1.0e10};
00486     double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10};
00487     double colLower[2]={0.0,0.0};
00488     double colUpper[2]={100.0,100.0};
00489   
00490     // integer
00491     char intVar[2]={2,2};
00492 
00493     // basis 1
00494     int rowBasis1[3]={-1,-1,1};
00495     int colBasis1[2]={1,1};
00496     CoinWarmStartBasis warm;
00497     warm.setSize(2,3);
00498     for (i=0;i<3;i++) {
00499       if (rowBasis1[i]<0) {
00500         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00501       } else {
00502         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00503       }
00504     }
00505     for (i=0;i<2;i++) {
00506       if (colBasis1[i]<0) {
00507         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00508       } else {
00509         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00510       }
00511     }
00512 
00513     // solution 1
00514     double colsol1[2]={20.0/7.0,3.0};
00515     test1.generateCuts(NULL, osicuts, matrix,
00516                  objective, colsol1,
00517                  colLower, colUpper,
00518                  rowLower, rowUpper, intVar, &warm);
00519     nRowCuts = osicuts.sizeRowCuts();
00520     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00521     assert (nRowCuts==1);
00522     // cuts always <=
00523     int testCut=0; // test first cut as stronger
00524     double rhs=2.0;
00525     double testCut1[2]={1.0,0.0};
00526     double * cut = testCut1;
00527     double * colsol = colsol1;
00528     for (i=nOldCuts; i<nRowCuts; i++){
00529       OsiRowCut rcut;
00530       CoinPackedVector rpv;
00531       rcut = osicuts.rowCut(i);
00532       rpv = rcut.row();
00533       const int n = rpv.getNumElements();
00534       const int * indices = rpv.getIndices();
00535       double* elements = rpv.getElements();
00536       double sum2=0.0;
00537       int k=0;
00538       double lb=rcut.lb();
00539       double ub=rcut.ub();
00540       for (k=0; k<n; k++){
00541         int column=indices[k];
00542         sum2 += colsol[column]*elements[k];
00543       }
00544       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
00545         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
00546         for (k=0; k<n; k++){
00547           int column=indices[k];
00548           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
00549             colsol[column]<<") ";
00550         }
00551         std::cout <<std::endl;
00552       }
00553       if (i-nOldCuts==testCut) {
00554         assert( eq(rhs,ub));
00555         assert(n==1);
00556         for (k=0; k<n; k++){
00557           int column=indices[k];
00558           assert (eq(cut[column],elements[k]));
00559         }
00560         // add cut
00561         rowLower[3]=-1.0e100;
00562         rowUpper[3]=ub;
00563         matrix.appendRow(rpv);
00564       }
00565     }
00566     nOldCuts=nRowCuts;
00567     // basis 2
00568     int rowBasis2[4]={1,1,-1,-1};
00569     int colBasis2[2]={1,1};
00570     warm.setSize(2,4);
00571     for (i=0;i<4;i++) {
00572       if (rowBasis2[i]<0) {
00573         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00574       } else {
00575         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00576       }
00577     }
00578     for (i=0;i<2;i++) {
00579       if (colBasis2[i]<0) {
00580         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00581       } else {
00582         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00583       }
00584     }
00585 
00586     // solution 2
00587     double colsol2[2]={2.0,0.5};
00588     test1.generateCuts(NULL, osicuts, matrix,
00589                  objective, colsol2,
00590                  colLower, colUpper,
00591                  rowLower, rowUpper, intVar, &warm);
00592     nRowCuts = osicuts.sizeRowCuts();
00593     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00594     assert (nRowCuts-nOldCuts==1);
00595     // cuts always <=
00596     testCut=0; // test first cut as stronger
00597     rhs=1.0;
00598     double testCut2[2]={1.0,-1.0};
00599     cut = testCut2;
00600     colsol = colsol2;
00601     for (i=nOldCuts; i<nRowCuts; i++){
00602       OsiRowCut rcut;
00603       CoinPackedVector rpv;
00604       rcut = osicuts.rowCut(i);
00605       rpv = rcut.row();
00606       const int n = rpv.getNumElements();
00607       const int * indices = rpv.getIndices();
00608       double* elements = rpv.getElements();
00609       double sum2=0.0;
00610       int k=0;
00611       double lb=rcut.lb();
00612       double ub=rcut.ub();
00613       for (k=0; k<n; k++){
00614         int column=indices[k];
00615         sum2 += colsol[column]*elements[k];
00616       }
00617       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
00618         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
00619         for (k=0; k<n; k++){
00620           int column=indices[k];
00621           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
00622             colsol[column]<<") ";
00623         }
00624         std::cout <<std::endl;
00625       }
00626       if (i-nOldCuts==testCut) {
00627         assert( eq(rhs,ub));
00628         assert(n==2);
00629         for (k=0; k<n; k++){
00630           int column=indices[k];
00631           assert (eq(cut[column],elements[k]));
00632         }
00633         // add cut
00634         rowLower[4]=-1.0e100;
00635         rowUpper[4]=ub;
00636         matrix.appendRow(rpv);
00637       }
00638     }
00639     nOldCuts=nRowCuts;
00640     // basis 3
00641     int rowBasis3[5]={1,1,1,-1,-1};
00642     int colBasis3[2]={1,1};
00643     warm.setSize(2,5);
00644     for (i=0;i<5;i++) {
00645       if (rowBasis3[i]<0) {
00646         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00647       } else {
00648         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00649       }
00650     }
00651     for (i=0;i<2;i++) {
00652       if (colBasis3[i]<0) {
00653         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00654       } else {
00655         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00656       }
00657     }
00658 
00659     // solution 3
00660     double colsol3[2]={2.0,1.0};
00661     test1.generateCuts(NULL, osicuts, matrix,
00662                  objective, colsol3,
00663                  colLower, colUpper,
00664                  rowLower, rowUpper, intVar, &warm);
00665     nRowCuts = osicuts.sizeRowCuts();
00666     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00667     assert (nRowCuts==nOldCuts);
00668     
00669   }
00670   // swap some rows to G
00671   if (1) {
00672     OsiCuts osicuts;
00673     CglGomory test1;
00674     int i;
00675     int nOldCuts=0,nRowCuts;
00676  
00677     // matrix data
00678     //deliberate hiccup of 2 between 0 and 1
00679     int start[5]={0,4};
00680     int length[5]={2,3};
00681     int rows[11]={0,2,-1,-1,0,1,2};
00682     double elements[11]={-7.0,-2.0,1.0e10,1.0e10,+2.0,1.0,+2.0};
00683     CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length);
00684     
00685     // rim data (objective not used just yet)
00686     double objective[2]={-4.0,1.0};
00687     double rowUpper[5]={1.0e10,3.0,1.0e10,-1.0e10,-1.0e10};
00688     double rowLower[5]={-14.0,-1.0e10,-3.0,1.0e10,1.0e10};
00689     double colLower[2]={0.0,0.0};
00690     double colUpper[2]={100.0,100.0};
00691   
00692     // integer
00693     char intVar[2]={2,2};
00694 
00695     // basis 1
00696     int rowBasis1[3]={-1,-1,1};
00697     int colBasis1[2]={1,1};
00698     CoinWarmStartBasis warm;
00699     warm.setSize(2,3);
00700     for (i=0;i<3;i++) {
00701       if (rowBasis1[i]<0) {
00702         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00703       } else {
00704         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00705       }
00706     }
00707     for (i=0;i<2;i++) {
00708       if (colBasis1[i]<0) {
00709         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00710       } else {
00711         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00712       }
00713     }
00714 
00715     // solution 1
00716     double colsol1[2]={20.0/7.0,3.0};
00717     test1.generateCuts(NULL, osicuts, matrix,
00718                  objective, colsol1,
00719                  colLower, colUpper,
00720                  rowLower, rowUpper, intVar, &warm);
00721     nRowCuts = osicuts.sizeRowCuts();
00722     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00723     assert (nRowCuts==1);
00724     // cuts always <=
00725     int testCut=0; // test first cut as stronger
00726     double rhs=2.0;
00727     double testCut1[2]={1.0,0.0};
00728     double * cut = testCut1;
00729     double * colsol = colsol1;
00730     for (i=nOldCuts; i<nRowCuts; i++){
00731       OsiRowCut rcut;
00732       CoinPackedVector rpv;
00733       rcut = osicuts.rowCut(i);
00734       rpv = rcut.row();
00735       const int n = rpv.getNumElements();
00736       const int * indices = rpv.getIndices();
00737       double* elements = rpv.getElements();
00738       double sum2=0.0;
00739       int k=0;
00740       double lb=rcut.lb();
00741       double ub=rcut.ub();
00742       for (k=0; k<n; k++){
00743         int column=indices[k];
00744         sum2 += colsol[column]*elements[k];
00745       }
00746       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
00747         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
00748         for (k=0; k<n; k++){
00749           int column=indices[k];
00750           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
00751             colsol[column]<<") ";
00752         }
00753         std::cout <<std::endl;
00754       }
00755       if (i-nOldCuts==testCut) {
00756         assert( eq(rhs,ub));
00757         assert(n==1);
00758         for (k=0; k<n; k++){
00759           int column=indices[k];
00760           assert (eq(cut[column],elements[k]));
00761         }
00762         // add cut
00763         rowLower[3]=-1.0e100;
00764         rowUpper[3]=ub;
00765         matrix.appendRow(rpv);
00766       }
00767     }
00768     nOldCuts=nRowCuts;
00769     // basis 2
00770     int rowBasis2[4]={1,1,-1,-1};
00771     int colBasis2[2]={1,1};
00772     warm.setSize(2,4);
00773     for (i=0;i<4;i++) {
00774       if (rowBasis2[i]<0) {
00775         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00776       } else {
00777         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00778       }
00779     }
00780     for (i=0;i<2;i++) {
00781       if (colBasis2[i]<0) {
00782         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00783       } else {
00784         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00785       }
00786     }
00787 
00788     // solution 2
00789     double colsol2[2]={2.0,0.5};
00790     test1.generateCuts(NULL, osicuts, matrix,
00791                  objective, colsol2,
00792                  colLower, colUpper,
00793                  rowLower, rowUpper, intVar, &warm);
00794     nRowCuts = osicuts.sizeRowCuts();
00795     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00796     assert (nRowCuts-nOldCuts==1);
00797     // cuts always <=
00798     testCut=0; // test first cut as stronger
00799     rhs=1.0;
00800     double testCut2[2]={1.0,-1.0};
00801     cut = testCut2;
00802     colsol = colsol2;
00803     for (i=nOldCuts; i<nRowCuts; i++){
00804       OsiRowCut rcut;
00805       CoinPackedVector rpv;
00806       rcut = osicuts.rowCut(i);
00807       rpv = rcut.row();
00808       const int n = rpv.getNumElements();
00809       const int * indices = rpv.getIndices();
00810       double* elements = rpv.getElements();
00811       double sum2=0.0;
00812       int k=0;
00813       double lb=rcut.lb();
00814       double ub=rcut.ub();
00815       for (k=0; k<n; k++){
00816         int column=indices[k];
00817         sum2 += colsol[column]*elements[k];
00818       }
00819       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
00820         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
00821         for (k=0; k<n; k++){
00822           int column=indices[k];
00823           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
00824             colsol[column]<<") ";
00825         }
00826         std::cout <<std::endl;
00827       }
00828       if (i-nOldCuts==testCut) {
00829         assert( eq(rhs,ub));
00830         assert(n==2);
00831         for (k=0; k<n; k++){
00832           int column=indices[k];
00833           assert (eq(cut[column],elements[k]));
00834         }
00835         // add cut
00836         rowLower[4]=-1.0e100;
00837         rowUpper[4]=ub;
00838         matrix.appendRow(rpv);
00839       }
00840     }
00841     nOldCuts=nRowCuts;
00842     // basis 3
00843     int rowBasis3[5]={1,1,1,-1,-1};
00844     int colBasis3[2]={1,1};
00845     warm.setSize(2,5);
00846     for (i=0;i<5;i++) {
00847       if (rowBasis3[i]<0) {
00848         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00849       } else {
00850         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00851       }
00852     }
00853     for (i=0;i<2;i++) {
00854       if (colBasis3[i]<0) {
00855         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00856       } else {
00857         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00858       }
00859     }
00860 
00861     // solution 3
00862     double colsol3[2]={2.0,1.0};
00863     test1.generateCuts(NULL, osicuts, matrix,
00864                  objective, colsol3,
00865                  colLower, colUpper,
00866                  rowLower, rowUpper, intVar, &warm);
00867     nRowCuts = osicuts.sizeRowCuts();
00868     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00869     assert (nRowCuts==nOldCuts);
00870     
00871   }
00872 
00873 
00874   // NOW mixed integer gomory cuts
00875 
00876   // Test explicit form - (pg 130 Wolsey)
00877   // Some arrays left same size as previously although not used in full
00878   if (1) {
00879     OsiCuts osicuts;
00880     CglGomory test1;
00881     int i;
00882     int nOldCuts=0,nRowCuts;
00883  
00884     // matrix data
00885     //deliberate hiccup of 2 between 0 and 1
00886     int start[5]={0,4,7,8,9};
00887     int length[5]={2,3,1,1,1};
00888     int rows[11]={0,2,-1,-1,0,1,2,0,1,2};
00889     double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,1,1};
00890     CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length);
00891     
00892     // rim data (objective not used just yet)
00893     double objective[7]={-4.0,1.0,0.0,0.0,0.0,0.0,0.0};
00894     double rowLower[5]={14.0,3.0,3.0,1.0e10,1.0e10};
00895     double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10};
00896     double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0};
00897     double colUpper[7]={100.0,100.0,100.0,100.0,100.0,100.0,100.0};
00898   
00899     // integer
00900     char intVar[7]={2,0,0,0,0,0,0};
00901 
00902     // basis 1
00903     int rowBasis1[3]={-1,-1,-1};
00904     int colBasis1[5]={1,1,-1,-1,1};
00905     CoinWarmStartBasis warm;
00906     warm.setSize(5,3);
00907     for (i=0;i<3;i++) {
00908       if (rowBasis1[i]<0) {
00909         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00910       } else {
00911         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00912       }
00913     }
00914     for (i=0;i<5;i++) {
00915       if (colBasis1[i]<0) {
00916         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00917       } else {
00918         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00919       }
00920     }
00921 
00922     // solution 1
00923     double colsol1[5]={20.0/7.0,3.0,0.0,0.0,23.0/7.0};
00924     test1.generateCuts(NULL, osicuts, matrix,
00925                  objective, colsol1,
00926                  colLower, colUpper,
00927                  rowLower, rowUpper, intVar, &warm);
00928     nRowCuts = osicuts.sizeRowCuts();
00929     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
00930     assert (nRowCuts==1);
00931     // cuts always <=
00932     int testCut=0; // test first cut as stronger
00933     double rhs=-6.0/7.0;
00934     double testCut1[5]={0.0,0.0,-1.0/7.0,-2.0/7.0,0.0};
00935     double * cut = testCut1;
00936     double * colsol = colsol1;
00937     for (i=nOldCuts; i<nRowCuts; i++){
00938       OsiRowCut rcut;
00939       CoinPackedVector rpv;
00940       rcut = osicuts.rowCut(i);
00941       rpv = rcut.row();
00942       const int n = rpv.getNumElements();
00943       const int * indices = rpv.getIndices();
00944       double* elements = rpv.getElements();
00945       double sum2=0.0;
00946       int k=0;
00947       double lb=rcut.lb();
00948       double ub=rcut.ub();
00949       for (k=0; k<n; k++){
00950         int column=indices[k];
00951         sum2 += colsol[column]*elements[k];
00952       }
00953       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
00954         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
00955         for (k=0; k<n; k++){
00956           int column=indices[k];
00957           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
00958             colsol[column]<<") ";
00959         }
00960         std::cout <<std::endl;
00961       }
00962       if (i-nOldCuts==testCut) {
00963         assert( eq(rhs,ub));
00964         assert(n==2);
00965         for (k=0; k<n; k++){
00966           int column=indices[k];
00967           assert (eq(cut[column],elements[k]));
00968         }
00969         // add cut
00970         // explicit slack
00971         matrix.setDimensions(-1,6);
00972         rpv.insert(5,1.0); // to get cut in book
00973         rowLower[3]=ub;
00974         rowUpper[3]=ub;
00975         matrix.appendRow(rpv);
00976       }
00977     }
00978     nOldCuts=nRowCuts;
00979     // basis 2
00980     int rowBasis2[4]={-1,-1,-1,-1};
00981     int colBasis2[6]={1,1,1,1,-1,-1};
00982     warm.setSize(6,4);
00983     for (i=0;i<4;i++) {
00984       if (rowBasis2[i]<0) {
00985         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
00986       } else {
00987         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
00988       }
00989     }
00990     for (i=0;i<6;i++) {
00991       if (colBasis2[i]<0) {
00992         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
00993       } else {
00994         warm.setStructStatus(i,CoinWarmStartBasis::basic);
00995       }
00996     }
00997 
00998     // solution 2
00999     double colsol2[6]={2.0,0.5,1.0,2.5,0.0,0.0};
01000     test1.generateCuts(NULL, osicuts, matrix,
01001                  objective, colsol2,
01002                  colLower, colUpper,
01003                  rowLower, rowUpper, intVar, &warm);
01004     nRowCuts = osicuts.sizeRowCuts();
01005     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
01006     assert (nRowCuts==nOldCuts);
01007     
01008   }
01009   // Test explicit form - this time with x4 flipped 
01010   if (1) {
01011     OsiCuts osicuts;
01012     CglGomory test1;
01013     int i;
01014     int nOldCuts=0,nRowCuts;
01015  
01016     // matrix data
01017     //deliberate hiccup of 2 between 0 and 1
01018     int start[5]={0,4,7,8,9};
01019     int length[5]={2,3,1,1,1};
01020     int rows[11]={0,2,-1,-1,0,1,2,0,1,2};
01021     double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0,1,-1,1};
01022     CoinPackedMatrix matrix(true,3,5,8,elements,rows,start,length);
01023     
01024     // rim data (objective not used just yet)
01025     double objective[7]={-4.0,1.0,0.0,0.0,0.0,0.0,0.0};
01026     double rowLower[5]={14.0,-5.0,3.0,1.0e10,1.0e10};
01027     double rowUpper[5]={14.0,-5.0,3.0,-1.0e10,-1.0e10};
01028     double colLower[7]={0.0,0.0,0.0,0.0,0.0,0.0,0.0};
01029     double colUpper[7]={100.0,100.0,100.0,8.0,100.0,100.0,100.0};
01030   
01031     // integer
01032     char intVar[7]={2,0,0,0,0,0,0};
01033 
01034     // basis 1
01035     int rowBasis1[3]={-1,-1,-1};
01036     int colBasis1[5]={1,1,-1,-1,1};
01037     CoinWarmStartBasis warm;
01038     warm.setSize(5,3);
01039     for (i=0;i<3;i++) {
01040       if (rowBasis1[i]<0) {
01041         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
01042       } else {
01043         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
01044       }
01045     }
01046     for (i=0;i<5;i++) {
01047       if (colBasis1[i]<0) {
01048         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
01049       } else {
01050         warm.setStructStatus(i,CoinWarmStartBasis::basic);
01051       }
01052     }
01053 
01054     // solution 1
01055     double colsol1[5]={20.0/7.0,3.0,0.0,8.0,23.0/7.0};
01056     test1.generateCuts(NULL, osicuts, matrix,
01057                  objective, colsol1,
01058                  colLower, colUpper,
01059                  rowLower, rowUpper, intVar, &warm);
01060     nRowCuts = osicuts.sizeRowCuts();
01061     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
01062     assert (nRowCuts==1);
01063     // cuts always <=
01064     int testCut=0; 
01065     double rhs=10.0/7.0;
01066     double testCut1[5]={0.0,0.0,-1.0/7.0,2.0/7.0,0.0};
01067     double * cut = testCut1;
01068     double * colsol = colsol1;
01069     for (i=nOldCuts; i<nRowCuts; i++){
01070       OsiRowCut rcut;
01071       CoinPackedVector rpv;
01072       rcut = osicuts.rowCut(i);
01073       rpv = rcut.row();
01074       const int n = rpv.getNumElements();
01075       const int * indices = rpv.getIndices();
01076       double* elements = rpv.getElements();
01077       double sum2=0.0;
01078       int k=0;
01079       double lb=rcut.lb();
01080       double ub=rcut.ub();
01081       for (k=0; k<n; k++){
01082         int column=indices[k];
01083         sum2 += colsol[column]*elements[k];
01084       }
01085       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
01086         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
01087         for (k=0; k<n; k++){
01088           int column=indices[k];
01089           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
01090             colsol[column]<<") ";
01091         }
01092         std::cout <<std::endl;
01093       }
01094       if (i-nOldCuts==testCut) {
01095         assert( eq(rhs,ub));
01096         assert(n==2);
01097         for (k=0; k<n; k++){
01098           int column=indices[k];
01099           assert (eq(cut[column],elements[k]));
01100         }
01101         // add cut
01102         // explicit slack
01103         matrix.setDimensions(-1,6);
01104         rpv.insert(5,1.0); // to get cut in book
01105         rowLower[3]=ub;
01106         rowUpper[3]=ub;
01107         matrix.appendRow(rpv);
01108       }
01109     }
01110     nOldCuts=nRowCuts;
01111     // basis 2
01112     int rowBasis2[4]={-1,-1,-1,-1};
01113     int colBasis2[6]={1,1,1,1,-1,-1};
01114     warm.setSize(6,4);
01115     for (i=0;i<4;i++) {
01116       if (rowBasis2[i]<0) {
01117         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
01118       } else {
01119         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
01120       }
01121     }
01122     for (i=0;i<6;i++) {
01123       if (colBasis2[i]<0) {
01124         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
01125       } else {
01126         warm.setStructStatus(i,CoinWarmStartBasis::basic);
01127       }
01128     }
01129 
01130     // solution 2
01131     double colsol2[6]={2.0,0.5,1.0,5.5,0.0,0.0};
01132     test1.generateCuts(NULL, osicuts, matrix,
01133                  objective, colsol2,
01134                  colLower, colUpper,
01135                  rowLower, rowUpper, intVar, &warm);
01136     nRowCuts = osicuts.sizeRowCuts();
01137     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
01138     assert (nRowCuts==nOldCuts);
01139     
01140   }
01141   // Test with slacks 
01142   if (1) {
01143     OsiCuts osicuts;
01144     CglGomory test1;
01145     int i;
01146     int nOldCuts=0,nRowCuts;
01147  
01148     // matrix data
01149     //deliberate hiccup of 2 between 0 and 1
01150     int start[5]={0,4};
01151     int length[5]={2,3};
01152     int rows[11]={0,2,-1,-1,0,1,2};
01153     double elements[11]={7.0,2.0,1.0e10,1.0e10,-2.0,1.0,-2.0};
01154     CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length);
01155     
01156     // rim data (objective not used just yet)
01157     double objective[2]={-4.0,1.0};
01158     double rowLower[5]={-1.0e10,-1.0e10,-1.0e10,1.0e10,1.0e10};
01159     double rowUpper[5]={14.0,3.0,3.0,-1.0e10,-1.0e10};
01160     double colLower[2]={0.0,0.0};
01161     double colUpper[2]={100.0,100.0};
01162   
01163     // integer
01164     char intVar[2]={2,0};
01165 
01166     // basis 1
01167     int rowBasis1[3]={-1,-1,1};
01168     int colBasis1[2]={1,1};
01169     CoinWarmStartBasis warm;
01170     warm.setSize(2,3);
01171     for (i=0;i<3;i++) {
01172       if (rowBasis1[i]<0) {
01173         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
01174       } else {
01175         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
01176       }
01177     }
01178     for (i=0;i<2;i++) {
01179       if (colBasis1[i]<0) {
01180         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
01181       } else {
01182         warm.setStructStatus(i,CoinWarmStartBasis::basic);
01183       }
01184     }
01185 
01186     // solution 1
01187     double colsol1[2]={20.0/7.0,3.0};
01188     test1.generateCuts(NULL, osicuts, matrix,
01189                  objective, colsol1,
01190                  colLower, colUpper,
01191                  rowLower, rowUpper, intVar, &warm);
01192     nRowCuts = osicuts.sizeRowCuts();
01193     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
01194     assert (nRowCuts==1);
01195     // cuts always <=
01196     int testCut=0; // test first cut as stronger
01197     double rhs=2.0;
01198     double testCut1[2]={1.0,0.0};
01199     double * cut = testCut1;
01200     double * colsol = colsol1;
01201     for (i=nOldCuts; i<nRowCuts; i++){
01202       OsiRowCut rcut;
01203       CoinPackedVector rpv;
01204       rcut = osicuts.rowCut(i);
01205       rpv = rcut.row();
01206       const int n = rpv.getNumElements();
01207       const int * indices = rpv.getIndices();
01208       double* elements = rpv.getElements();
01209       double sum2=0.0;
01210       int k=0;
01211       double lb=rcut.lb();
01212       double ub=rcut.ub();
01213       for (k=0; k<n; k++){
01214         int column=indices[k];
01215         sum2 += colsol[column]*elements[k];
01216       }
01217       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
01218         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
01219         for (k=0; k<n; k++){
01220           int column=indices[k];
01221           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
01222             colsol[column]<<") ";
01223         }
01224         std::cout <<std::endl;
01225       }
01226       if (i-nOldCuts==testCut) {
01227         assert( eq(rhs,ub));
01228         assert(n==1);
01229         for (k=0; k<n; k++){
01230           int column=indices[k];
01231           assert (eq(cut[column],elements[k]));
01232         }
01233         // add cut
01234         rowLower[3]=-1.0e100;
01235         rowUpper[3]=ub;
01236         matrix.appendRow(rpv);
01237       }
01238     }
01239     nOldCuts=nRowCuts;
01240     // basis 2
01241     int rowBasis2[4]={1,1,-1,-1};
01242     int colBasis2[2]={1,1};
01243     warm.setSize(2,4);
01244     for (i=0;i<4;i++) {
01245       if (rowBasis2[i]<0) {
01246         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
01247       } else {
01248         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
01249       }
01250     }
01251     for (i=0;i<2;i++) {
01252       if (colBasis2[i]<0) {
01253         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
01254       } else {
01255         warm.setStructStatus(i,CoinWarmStartBasis::basic);
01256       }
01257     }
01258 
01259     // solution 2
01260     double colsol2[2]={2.0,0.5};
01261     test1.generateCuts(NULL, osicuts, matrix,
01262                  objective, colsol2,
01263                  colLower, colUpper,
01264                  rowLower, rowUpper, intVar, &warm);
01265     nRowCuts = osicuts.sizeRowCuts();
01266     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
01267     assert (nRowCuts==nOldCuts);
01268     
01269   }
01270   // swap some rows to G
01271   if (1) {
01272     OsiCuts osicuts;
01273     CglGomory test1;
01274     int i;
01275     int nOldCuts=0,nRowCuts;
01276  
01277     // matrix data
01278     //deliberate hiccup of 2 between 0 and 1
01279     int start[5]={0,4};
01280     int length[5]={2,3};
01281     int rows[11]={0,2,-1,-1,0,1,2};
01282     double elements[11]={-7.0,-2.0,1.0e10,1.0e10,+2.0,1.0,+2.0};
01283     CoinPackedMatrix matrix(true,3,2,5,elements,rows,start,length);
01284     
01285     // rim data (objective not used just yet)
01286     double objective[2]={-4.0,1.0};
01287     double rowUpper[5]={1.0e10,3.0,1.0e10,-1.0e10,-1.0e10};
01288     double rowLower[5]={-14.0,-1.0e10,-3.0,1.0e10,1.0e10};
01289     double colLower[2]={0.0,0.0};
01290     double colUpper[2]={100.0,100.0};
01291   
01292     // integer
01293     char intVar[2]={2,0};
01294 
01295     // basis 1
01296     int rowBasis1[3]={-1,-1,1};
01297     int colBasis1[2]={1,1};
01298     CoinWarmStartBasis warm;
01299     warm.setSize(2,3);
01300     for (i=0;i<3;i++) {
01301       if (rowBasis1[i]<0) {
01302         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
01303       } else {
01304         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
01305       }
01306     }
01307     for (i=0;i<2;i++) {
01308       if (colBasis1[i]<0) {
01309         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
01310       } else {
01311         warm.setStructStatus(i,CoinWarmStartBasis::basic);
01312       }
01313     }
01314 
01315     // solution 1
01316     double colsol1[2]={20.0/7.0,3.0};
01317     test1.generateCuts(NULL, osicuts, matrix,
01318                  objective, colsol1,
01319                  colLower, colUpper,
01320                  rowLower, rowUpper, intVar, &warm);
01321     nRowCuts = osicuts.sizeRowCuts();
01322     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
01323     assert (nRowCuts==1);
01324     // cuts always <=
01325     int testCut=0; // test first cut as stronger
01326     double rhs=2.0;
01327     double testCut1[2]={1.0,0.0};
01328     double * cut = testCut1;
01329     double * colsol = colsol1;
01330     for (i=nOldCuts; i<nRowCuts; i++){
01331       OsiRowCut rcut;
01332       CoinPackedVector rpv;
01333       rcut = osicuts.rowCut(i);
01334       rpv = rcut.row();
01335       const int n = rpv.getNumElements();
01336       const int * indices = rpv.getIndices();
01337       double* elements = rpv.getElements();
01338       double sum2=0.0;
01339       int k=0;
01340       double lb=rcut.lb();
01341       double ub=rcut.ub();
01342       for (k=0; k<n; k++){
01343         int column=indices[k];
01344         sum2 += colsol[column]*elements[k];
01345       }
01346       if (sum2 >ub + 1.0e-7 ||sum2 < lb - 1.0e-7) {
01347         std::cout<<"Cut "<<i<<" lb "<<lb<<" solution "<<sum2<<" ub "<<ub<<std::endl;
01348         for (k=0; k<n; k++){
01349           int column=indices[k];
01350           std::cout<<"(col="<<column<<",el="<<elements[k]<<",sol="<<
01351             colsol[column]<<") ";
01352         }
01353         std::cout <<std::endl;
01354       }
01355       if (i-nOldCuts==testCut) {
01356         assert( eq(rhs,ub));
01357         assert(n==1);
01358         for (k=0; k<n; k++){
01359           int column=indices[k];
01360           assert (eq(cut[column],elements[k]));
01361         }
01362         // add cut
01363         rowLower[3]=-1.0e100;
01364         rowUpper[3]=ub;
01365         matrix.appendRow(rpv);
01366       }
01367     }
01368     nOldCuts=nRowCuts;
01369     // basis 2
01370     int rowBasis2[4]={1,1,-1,-1};
01371     int colBasis2[2]={1,1};
01372     warm.setSize(2,4);
01373     for (i=0;i<4;i++) {
01374       if (rowBasis2[i]<0) {
01375         warm.setArtifStatus(i,CoinWarmStartBasis::atLowerBound);
01376       } else {
01377         warm.setArtifStatus(i,CoinWarmStartBasis::basic);
01378       }
01379     }
01380     for (i=0;i<2;i++) {
01381       if (colBasis2[i]<0) {
01382         warm.setStructStatus(i,CoinWarmStartBasis::atLowerBound);
01383       } else {
01384         warm.setStructStatus(i,CoinWarmStartBasis::basic);
01385       }
01386     }
01387 
01388     // solution 2
01389     double colsol2[2]={2.0,0.5};
01390     test1.generateCuts(NULL, osicuts, matrix,
01391                  objective, colsol2,
01392                  colLower, colUpper,
01393                  rowLower, rowUpper, intVar, &warm);
01394     nRowCuts = osicuts.sizeRowCuts();
01395     std::cout<<"There are "<<nRowCuts<<" gomory cuts"<<std::endl;
01396     assert (nRowCuts==nOldCuts);
01397     
01398   }
01399 
01400   // Miplib3 problem p0033
01401   if (1) {
01402     // Setup
01403     OsiSolverInterface  * siP = baseSiP->clone();
01404     std::string fn(mpsDir+"p0033");
01405     siP->readMps(fn.c_str(),"mps");
01406     siP->activateRowCutDebugger("p0033");
01407     CglGomory test;
01408 
01409     // Solve the LP relaxation of the model and
01410     // print out ofv for sake of comparison 
01411     siP->initialSolve();
01412     double lpRelaxBefore=siP->getObjValue();
01413     assert( eq(lpRelaxBefore, 2520.5717391304347) );
01414     double mycs[] = {0, 1, 0, 0, -2.0837010502455788e-19, 1, 0, 0, 1,
01415                        0.021739130434782594, 0.35652173913043478, 
01416                        -6.7220534694101275e-18, 5.3125906451789717e-18, 
01417                        1, 0, 1.9298798670241979e-17, 0, 0, 0,
01418                        7.8875708048320448e-18, 0.5, 0, 
01419                        0.85999999999999999, 1, 1, 0.57999999999999996,
01420                        1, 0, 1, 0, 0.25, 0, 0.67500000000000004};
01421     siP->setColSolution(mycs);
01422 #ifdef CGL_DEBUG
01423     printf("\n\nOrig LP min=%f\n",lpRelaxBefore);
01424 #endif
01425     
01426     OsiCuts cuts;    
01427     
01428     // Test generateCuts method
01429     test.generateCuts(*siP,cuts);
01430     OsiSolverInterface::ApplyCutsReturnCode rc = siP->applyCuts(cuts);
01431     
01432     siP->resolve();
01433     double lpRelaxAfter=siP->getObjValue(); 
01434     //assert( eq(lpRelaxAfter, 2592.1908295194507) );
01435     assert( eq(lpRelaxAfter, 2582.6167554453768) );
01436 #ifdef CGL_DEBUG
01437     printf("\n\nOrig LP min=%f\n",lpRelaxBefore);
01438     printf("\n\nFinal LP min=%f\n",lpRelaxAfter);
01439 #endif
01440     assert( lpRelaxBefore < lpRelaxAfter );
01441     
01442     delete siP;
01443   } 
01444   //exit(0);
01445     
01446 }


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