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

dualCuts.cpp

00001 // Copyright (C) 2003, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 #include "ClpSimplex.hpp"
00005 #include "CoinSort.hpp"
00006 #include "CoinHelperFunctions.hpp"
00007 #include "CoinTime.hpp"
00008 #include "CoinMpsIO.hpp"
00009 #include <iomanip>
00010 
00011 int main (int argc, const char *argv[])
00012 {
00013   ClpSimplex  model;
00014   int status;
00015   // Keep names
00016   if (argc<2) {
00017     status=model.readMps("small.mps",true);
00018   } else {
00019     status=model.readMps(argv[1],true);
00020   }
00021   if (status)
00022     exit(10);
00023   /*
00024     This driver implements a method of treating a problem as all cuts.
00025     So it adds in all E rows, solves and then adds in violated rows.
00026   */
00027 
00028   double time1 = CoinCpuTime();
00029   
00030   
00031   int numberColumns = model.numberColumns();
00032   int originalNumberRows = model.numberRows();
00033   
00034   // We will need arrays to choose rows to add
00035   double * weight = new double [originalNumberRows];
00036   int * sort = new int [originalNumberRows];
00037   int numberSort=0;
00038   
00039   const double * rowLower = model.rowLower();
00040   const double * rowUpper = model.rowUpper();
00041   int iRow,iColumn;
00042   // Set up initial list
00043   numberSort=0;
00044   for (iRow=0;iRow<originalNumberRows;iRow++) {
00045     weight[iRow]=1.123e50;
00046     if (rowLower[iRow]==rowUpper[iRow]) {
00047       sort[numberSort++] = iRow;
00048       weight[iRow]=0.0;
00049     }
00050   }
00051   // Just add this number of rows each time in small problem
00052   int smallNumberRows = 2*numberColumns;
00053   smallNumberRows=min(smallNumberRows,originalNumberRows/20);
00054   // and pad out with random rows
00055   double ratio = ((double)(smallNumberRows-numberSort))/((double) originalNumberRows);
00056   for (iRow=0;iRow<originalNumberRows;iRow++) {
00057     if (weight[iRow]==1.123e50&&CoinDrand48()<ratio)
00058       sort[numberSort++] = iRow;
00059   }
00060   /* This is optional.
00061      The best thing to do is to miss out random rows and do a set which makes dual feasible.
00062      If that is not possible then make sure variables have bounds.
00063 
00064      One way that normally works is to automatically tighten bounds.
00065   */
00066 #if 0
00067   model.tightenPrimalBounds();
00068   // However for some we need to do anyway
00069   double * columnLower = model.columnLower();
00070   double * columnUpper = model.columnUpper();
00071   for (iColumn=0;iColumn<numberColumns;iColumn++) {
00072     columnLower[iColumn]=max(-1.0e6,columnLower[iColumn]);
00073     columnUpper[iColumn]=min(1.0e6,columnUpper[iColumn]);
00074   }
00075 #endif
00076   printf("%d rows in initial problem\n",numberSort);
00077   double * fullSolution = model.primalRowSolution();
00078   
00079   // Just do this number of passes
00080   int maxPass=100;
00081   // And take out slack rows until this pass
00082   int takeOutPass=20;
00083   int iPass;
00084   
00085   // We will be using all columns
00086   int * whichColumns = new int [numberColumns];
00087   for (int iColumn=0;iColumn<numberColumns;iColumn++)
00088     whichColumns[iColumn]=iColumn;
00089   
00090   for (iPass=0;iPass<maxPass;iPass++) {
00091     printf("Start of pass %d\n",iPass);
00092     // Cleaner this way
00093     std::sort(sort,sort+numberSort);
00094     // Create small problem
00095     ClpSimplex small(&model,numberSort,sort,numberColumns,whichColumns);
00096     small.setFactorizationFrequency(100+numberSort/100);
00097     //small.setPerturbation(50);
00098     //small.setLogLevel(63);
00099     // A variation is to just do N iterations
00100     // Solve 
00101     small.dual();
00102     // move solution back
00103     memcpy(model.primalColumnSolution(),small.primalColumnSolution(),numberColumns*sizeof(double));
00104     for (iColumn=0;iColumn<numberColumns;iColumn++) 
00105       model.setColumnStatus(iColumn,small.getColumnStatus(iColumn));
00106     
00107     for (iRow=0;iRow<numberSort;iRow++) {
00108       int kRow = sort[iRow];
00109       model.setRowStatus(kRow,small.getRowStatus(iRow));
00110     }
00111     // compute full solution
00112     memset(fullSolution,0,originalNumberRows*sizeof(double));
00113     model.times(1.0,model.primalColumnSolution(),fullSolution);
00114     if (iPass!=maxPass-1) {
00115       // Mark row as not looked at
00116       for (iRow=0;iRow<originalNumberRows;iRow++)
00117         weight[iRow]=1.123e50;
00118       // Look at rows already in small problem
00119       int iSort;
00120       int numberDropped=0;
00121       int numberKept=0;
00122       for (iSort=0;iSort<numberSort;iSort++) {
00123         iRow=sort[iSort];
00124         //printf("%d %g %g\n",iRow,fullSolution[iRow],small.primalRowSolution()[iSort]);
00125         if (model.getRowStatus(iRow)==ClpSimplex::basic) {
00126           // Basic - we can get rid of if early on
00127           if (iPass<takeOutPass) {
00128             weight[iRow]=1.0;
00129             numberDropped++;
00130           } else {
00131             // keep
00132             weight[iRow]=-1.0e40;
00133             numberKept++;
00134           }
00135         } else {
00136           // keep
00137           weight[iRow]=-1.0e50;
00138           numberKept++;
00139         }
00140       }
00141       int numberInfeasibilities=0;
00142       double sumInfeasibilities=0.0;
00143       // Now rest
00144       for (iRow=0;iRow<originalNumberRows;iRow++) {
00145         sort[iRow]=iRow;
00146         if (weight[iRow]==1.123e50) {
00147           // not looked at yet
00148           double infeasibility = max(fullSolution[iRow]-rowUpper[iRow],
00149                                      rowLower[iRow]-fullSolution[iRow]);
00150           weight[iRow]=-infeasibility;
00151           if (infeasibility>1.0e-8) {
00152             numberInfeasibilities++;
00153             sumInfeasibilities += infeasibility;
00154           }
00155         }
00156       }
00157       // sort
00158       CoinSort_2(weight,weight+originalNumberRows,sort);
00159       numberSort = min(originalNumberRows,smallNumberRows+numberKept);
00160       printf("%d rows kept, %d rows dropped - new size %d rows\n",
00161              numberKept,numberDropped,numberSort);
00162       printf("%d rows are infeasible - sum is %g\n",numberInfeasibilities,
00163                sumInfeasibilities);
00164       if (!numberInfeasibilities) {
00165         printf("Exiting as looks optimal\n");
00166         break;
00167       }
00168       numberInfeasibilities=0;
00169       sumInfeasibilities=0.0;
00170       for (iSort=0;iSort<numberSort;iSort++) {
00171         if (weight[iSort]>-1.0e30&&weight[iSort]<-1.0e-8) {
00172           numberInfeasibilities++;
00173           sumInfeasibilities += -weight[iSort];
00174         }
00175       }
00176       printf("in small model %d rows are infeasible - sum is %g\n",numberInfeasibilities,
00177                sumInfeasibilities);
00178     }
00179   }
00180   delete [] weight;
00181   delete [] sort;
00182   delete [] whichColumns;
00183   // If problem is big you may wish to skip this
00184   model.dual();
00185   printf("Solve took %g seconds\n",CoinCpuTime()-time1);
00186   return 0;
00187 }    

Generated on Wed Dec 3 14:37:36 2003 for CLP by doxygen 1.3.5