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

CglGomory.cpp

00001 // Copyright (C) 2002, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 #if defined(_MSC_VER)
00004 // Turn off compiler warning about long names
00005 #  pragma warning(disable:4786)
00006 #endif
00007 #include <cstdlib>
00008 #include <cstdio>
00009 #include <cmath>
00010 #include <cfloat>
00011 #include <cassert>
00012 #include <iostream>
00013 //#define CGL_DEBUG
00014 #include "CoinHelperFunctions.hpp"
00015 #include "CoinPackedVector.hpp"
00016 #include "CoinPackedMatrix.hpp"
00017 #include "CoinIndexedVector.hpp"
00018 #include "OsiRowCutDebugger.hpp"
00019 #include "CoinFactorization.hpp"
00020 #include "CoinWarmStartBasis.hpp"
00021 #include "CglGomory.hpp"
00022 #include "CoinFinite.hpp"
00023 //-------------------------------------------------------------------
00024 // Generate Gomory cuts
00025 //------------------------------------------------------------------- 
00026 void CglGomory::generateCuts(const OsiSolverInterface & si, 
00027                                                 OsiCuts & cs ) const
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 }
00075 
00076 // Returns value - floor but allowing for small errors
00077 inline double above_integer(double value) 
00078 {
00079   double value2=floor(value);
00080   double value3=floor(value+0.5);
00081   if (fabs(value3-value)<1.0e-7*(fabs(value3)+1.0))
00082     return 0.0;
00083   return value-value2;
00084 }
00085 //-------------------------------------------------------------------
00086 // Returns the greatest common denominator of two 
00087 // positive integers, a and b, found using Euclid's algorithm 
00088 //-------------------------------------------------------------------
00089 static int gcd(int a, int b) 
00090 {
00091   int remainder = -1;
00092 #if CGL_DEBUG>1
00093   printf("gcd of %d and %d\n",a,b);
00094   int nLoop=0;
00095 #endif
00096   // make sure a<=b (will always remain so)
00097   if(a > b) {
00098     // Swap a and b
00099     int temp = a;
00100     a = b;
00101     b = temp;
00102   }
00103   // if zero then gcd is nonzero (zero may occur in rhs of packed)
00104   if (!a) {
00105     if (b) {
00106       return b;
00107     } else {
00108       printf("**** gcd given two zeros!!\n");
00109       abort();
00110     }
00111   }
00112   while (remainder) {
00113 
00114 #if CGL_DEBUG>1
00115     nLoop++;
00116     if (nLoop>50) {
00117       abort();
00118       return -1;
00119     }
00120 #endif
00121     remainder = b % a;
00122     b = a;
00123     a = remainder;
00124   }
00125 #if CGL_DEBUG>1
00126   printf("=> %d\n",b);
00127 #endif
00128   return b;
00129 }
00130 
00131 //-------------------------------------------------------------------
00132 // Returns the nearest rational with denominator < maxDenominator
00133 //-------------------------------------------------------------------
00134 typedef struct {
00135   int numerator;
00136   int denominator;
00137 } Rational;
00138 inline Rational nearestRational(double value, int maxDenominator) 
00139 {
00140   Rational tryThis;
00141   Rational tryA;
00142   Rational tryB;
00143   double integerPart;
00144 
00145 #if CGL_DEBUG>1
00146   printf("Rational of %g is ",value);
00147 #endif
00148   int nLoop=0;
00149 
00150   tryA.numerator=0;
00151   tryA.denominator=1;
00152   tryB.numerator=1;
00153   tryB.denominator=0;
00154 
00155   if (fabs(value)<1.0e-10)
00156     return tryA;
00157   integerPart = floor(value);
00158   value -= integerPart;
00159   tryThis.numerator = tryB.numerator* (int ) integerPart + tryA.numerator;
00160   tryThis.denominator = tryB.denominator* (int ) integerPart + tryA.denominator;
00161   tryA = tryB;
00162   tryB = tryThis;
00163 
00164   while (value>1.0e-10 && tryB.denominator <=maxDenominator) {
00165     nLoop++;
00166     if (nLoop>50) {
00167       Rational bad;
00168       bad.numerator=-1;
00169       bad.denominator=-1;
00170 #if CGL_DEBUG>1
00171       printf(" *** bad rational\n");
00172 #endif
00173       return bad;
00174     }
00175     value = 1.0/value;
00176     integerPart = floor(value+1.0e-10);
00177     value -= integerPart;
00178     tryThis.numerator = tryB.numerator* (int ) integerPart + tryA.numerator;
00179     tryThis.denominator = tryB.denominator* (int ) integerPart + tryA.denominator;
00180     tryA = tryB;
00181     tryB = tryThis;
00182   }
00183   if (tryB.denominator <= maxDenominator) {
00184 #if CGL_DEBUG>1
00185     printf("%d/%d\n",tryB.numerator,tryB.denominator);
00186 #endif
00187     return tryB;
00188   } else {
00189 #if CGL_DEBUG>1
00190     printf("%d/%d\n",tryA.numerator,tryA.denominator);
00191 #endif
00192     return tryA;
00193   }
00194 }
00195 
00196 // Does actual work - returns number of cuts
00197 int
00198 CglGomory::generateCuts( const OsiRowCutDebugger * debugger, 
00199                      OsiCuts & cs,
00200                      const CoinPackedMatrix & columnCopy,
00201                      const double * objective, const double * colsol,
00202                      const double * colLower, const double * colUpper,
00203                      const double * rowLower, const double * rowUpper,
00204                          const char * intVar,
00205                     const CoinWarmStartBasis* warm) const
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 }
00819 // Limit stuff
00820 void CglGomory::setLimit(int limit)
00821 {
00822   if (limit>0)
00823     limit_=limit;
00824 }
00825 int CglGomory::getLimit() const
00826 {
00827   return limit_;
00828 }
00829 
00830 // Away stuff
00831 void CglGomory::setAway(double value)
00832 {
00833   if (value>0.0&&value<=0.5)
00834     away_=value;
00835 }
00836 double CglGomory::getAway() const
00837 {
00838   return away_;
00839 }
00840 
00841 //-------------------------------------------------------------------
00842 // Default Constructor 
00843 //-------------------------------------------------------------------
00844 CglGomory::CglGomory ()
00845 :
00846 CglCutGenerator(),
00847 away_(0.05),
00848 limit_(50)
00849 {
00850 
00851 }
00852 
00853 //-------------------------------------------------------------------
00854 // Copy constructor 
00855 //-------------------------------------------------------------------
00856 CglGomory::CglGomory (const CglGomory & source) :
00857   CglCutGenerator(source),
00858   away_(source.away_),
00859   limit_(source.limit_)
00860 {  
00861 }
00862 
00863 //-------------------------------------------------------------------
00864 // Destructor 
00865 //-------------------------------------------------------------------
00866 CglGomory::~CglGomory ()
00867 {
00868 }
00869 
00870 //----------------------------------------------------------------
00871 // Assignment operator 
00872 //-------------------------------------------------------------------
00873 CglGomory &
00874 CglGomory::operator=(const CglGomory& rhs)
00875 {
00876   if (this != &rhs) {
00877     CglCutGenerator::operator=(rhs);
00878     away_=rhs.away_;
00879     limit_=rhs.limit_;
00880   }
00881   return *this;
00882 }

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