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

sprint.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 <iomanip>
00007 
00008 int main (int argc, const char *argv[])
00009 {
00010   ClpSimplex  model;
00011   int status;
00012   // Keep names
00013   if (argc<2) {
00014     status=model.readMps("small.mps",true);
00015   } else {
00016     status=model.readMps(argv[1],true);
00017   }
00018   if (status)
00019     exit(10);
00020   /*
00021     This driver implements what I called Sprint.  Cplex calls it 
00022     "sifting" which is just as silly.  When I thought of this trivial idea
00023     it reminded me of an LP code of the 60's called sprint which after
00024     every factorization took a subset of the matrix into memory (all
00025     64K words!) and then iterated very fast on that subset.  On the
00026     problems of those days it did not work very well, but it worked very
00027     well on aircrew scheduling problems where there were very large numbers
00028     of columns all with the same flavor.
00029   */
00030 
00031   /* The idea works best if you can get feasible easily.  To make it
00032      more general we can add in costed slacks */
00033 
00034   int originalNumberColumns = model.numberColumns();
00035   int numberRows = model.numberRows();
00036 
00037   // We will need arrays to choose variables.  These are too big but ..
00038   double * weight = new double [numberRows+originalNumberColumns];
00039   int * sort = new int [numberRows+originalNumberColumns];
00040   int numberSort=0;
00041   // Say we are going to add slacks - if you can get a feasible
00042   // solution then do that at the comment - Add in your own coding here
00043   bool addSlacks = true;
00044 
00045   if (addSlacks) {
00046     // initial list will just be artificials
00047     // first we will set all variables as close to zero as possible
00048     int iColumn;
00049     const double * columnLower = model.columnLower();
00050     const double * columnUpper = model.columnUpper();
00051     double * columnSolution = model.primalColumnSolution();
00052 
00053     for (iColumn=0;iColumn<originalNumberColumns;iColumn++) {
00054       double value =0.0;
00055       if (columnLower[iColumn]>0.0)
00056         value = columnLower[iColumn];
00057       else if (columnUpper[iColumn]<0.0)
00058         value = columnUpper[iColumn];
00059       columnSolution[iColumn]=value;
00060     }
00061     // now see what that does to row solution
00062     double * rowSolution = model.primalRowSolution();
00063     memset (rowSolution,0,numberRows*sizeof(double));
00064     model.times(1.0,columnSolution,rowSolution);
00065 
00066     int * addStarts = new int [numberRows+1];
00067     int * addRow = new int[numberRows];
00068     double * addElement = new double[numberRows];
00069     const double * lower = model.rowLower();
00070     const double * upper = model.rowUpper();
00071     addStarts[0]=0;
00072     int numberArtificials=0;
00073     double * addCost = new double [numberRows];
00074     const double penalty=1.0e8;
00075     int iRow;
00076     for (iRow=0;iRow<numberRows;iRow++) {
00077       if (lower[iRow]>rowSolution[iRow]) {
00078         addRow[numberArtificials]=iRow;
00079         addElement[numberArtificials]=1.0;
00080         addCost[numberArtificials]=penalty;
00081         numberArtificials++;
00082         addStarts[numberArtificials]=numberArtificials;
00083       } else if (upper[iRow]<rowSolution[iRow]) {
00084         addRow[numberArtificials]=iRow;
00085         addElement[numberArtificials]=-1.0;
00086         addCost[numberArtificials]=penalty;
00087         numberArtificials++;
00088         addStarts[numberArtificials]=numberArtificials;
00089       }
00090     }
00091     model.addColumns(numberArtificials,NULL,NULL,addCost,
00092                       addStarts,addRow,addElement);
00093     delete [] addStarts;
00094     delete [] addRow;
00095     delete [] addElement;
00096     delete [] addCost;
00097     // Set up initial list
00098     numberSort=numberArtificials;
00099     int i;
00100     for (i=0;i<numberSort;i++)
00101       sort[i] = i+originalNumberColumns;
00102   } else {
00103     // Get initial list in some magical way
00104     // Add in your own coding here
00105     abort();
00106   }
00107 
00108   int numberColumns = model.numberColumns();
00109   const double * columnLower = model.columnLower();
00110   const double * columnUpper = model.columnUpper();
00111   double * fullSolution = model.primalColumnSolution();
00112 
00113   // Just do this number of passes
00114   int maxPass=100;
00115   int iPass;
00116   double lastObjective=1.0e31;
00117 
00118   // Just take this number of columns in small problem
00119   int smallNumberColumns = min(3*numberRows,numberColumns);
00120   smallNumberColumns = max(smallNumberColumns,3000);
00121   // We will be using all rows
00122   int * whichRows = new int [numberRows];
00123   for (int iRow=0;iRow<numberRows;iRow++)
00124     whichRows[iRow]=iRow;
00125   double originalOffset;
00126   model.getDblParam(ClpObjOffset,originalOffset);
00127 
00128   for (iPass=0;iPass<maxPass;iPass++) {
00129     printf("Start of pass %d\n",iPass);
00130     //printf("Bug until submodel new version\n");
00131     CoinSort_2(sort,sort+numberSort,weight);
00132     // Create small problem
00133     ClpSimplex small(&model,numberRows,whichRows,numberSort,sort);
00134     // now see what variables left out do to row solution
00135     double * rowSolution = model.primalRowSolution();
00136     memset (rowSolution,0,numberRows*sizeof(double));
00137     int iRow,iColumn;
00138     // zero out ones in small problem
00139     for (iColumn=0;iColumn<numberSort;iColumn++) {
00140       int kColumn = sort[iColumn];
00141       fullSolution[kColumn]=0.0;
00142     }
00143     // Get objective offset
00144     double offset=0.0;
00145     const double * objective = model.objective();
00146     for (iColumn=0;iColumn<originalNumberColumns;iColumn++) 
00147       offset += fullSolution[iColumn]*objective[iColumn];
00148     small.setDblParam(ClpObjOffset,originalOffset-offset);
00149     model.times(1.0,fullSolution,rowSolution);
00150 
00151     double * lower = small.rowLower();
00152     double * upper = small.rowUpper();
00153     for (iRow=0;iRow<numberRows;iRow++) {
00154       if (lower[iRow]>-1.0e50) 
00155         lower[iRow] -= rowSolution[iRow];
00156       if (upper[iRow]<1.0e50)
00157         upper[iRow] -= rowSolution[iRow];
00158     }
00159     /* For some problems a useful variant is to presolve problem.
00160        In this case you need to adjust smallNumberColumns to get
00161        right size problem.  Also you can dispense with creating
00162        small problem and fix variables in large problem and do presolve
00163        on that. */
00164     // Solve 
00165     small.primal();
00166     // move solution back
00167     const double * solution = small.primalColumnSolution();
00168     for (iColumn=0;iColumn<numberSort;iColumn++) {
00169       int kColumn = sort[iColumn];
00170       model.setColumnStatus(kColumn,small.getColumnStatus(iColumn));
00171       fullSolution[kColumn]=solution[iColumn];
00172     }
00173     for (iRow=0;iRow<numberRows;iRow++) 
00174       model.setRowStatus(iRow,small.getRowStatus(iRow));
00175     memcpy(model.primalRowSolution(),small.primalRowSolution(),
00176            numberRows*sizeof(double));
00177     if ((small.objectiveValue()>lastObjective-1.0e-7&&iPass>5)||
00178         !small.numberIterations()||
00179         iPass==maxPass-1) {
00180 
00181       break; // finished
00182     } else {
00183       lastObjective = small.objectiveValue();
00184       // get reduced cost for large problem
00185       // this assumes minimization
00186       memcpy(weight,model.objective(),numberColumns*sizeof(double));
00187       model.transposeTimes(-1.0,small.dualRowSolution(),weight);
00188       // now massage weight so all basic in plus good djs
00189       for (iColumn=0;iColumn<numberColumns;iColumn++) {
00190         double dj = weight[iColumn];
00191         double value = fullSolution[iColumn];
00192         if (model.getColumnStatus(iColumn)==ClpSimplex::basic)
00193           dj = -1.0e50;
00194         else if (dj<0.0&&value<columnUpper[iColumn])
00195           dj = dj;
00196         else if (dj>0.0&&value>columnLower[iColumn])
00197           dj = -dj;
00198         else if (columnUpper[iColumn]>columnLower[iColumn])
00199           dj = fabs(dj);
00200         else
00201           dj = 1.0e50;
00202         weight[iColumn] = dj;
00203         sort[iColumn] = iColumn;
00204       }
00205       // sort
00206       CoinSort_2(weight,weight+numberColumns,sort);
00207       numberSort = smallNumberColumns;
00208     }
00209   }
00210   if (addSlacks) {
00211     int i;
00212     int numberArtificials = numberColumns-originalNumberColumns;
00213     for (i=0;i<numberArtificials;i++)
00214       sort[i] = i + originalNumberColumns;
00215     model.deleteColumns(numberArtificials,sort);
00216   }
00217   delete [] weight;
00218   delete [] sort;
00219   delete [] whichRows;
00220   model.primal(1);
00221   return 0;
00222 }    

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