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

decompose.cpp

00001 // Copyright (C) 2003, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 #include "ClpSimplex.hpp"
00005 #include "CoinMpsIO.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("/home/forrest/data/ken-18.mps.gz",true);
00015     status=model.readMps("small.mps",true);
00016   } else {
00017     status=model.readMps(argv[1],true);
00018   }
00019   if (status)
00020     exit(10);
00021   /*
00022     This driver does a simple Dantzig Wolfe decomposition
00023   */
00024   // Get master rows in some mysterious way
00025   int numberRows = model.numberRows();
00026   int * rowBlock = new int[numberRows];
00027   int iRow;
00028   for (iRow=0;iRow<numberRows;iRow++)
00029     rowBlock[iRow]=-2;
00030   // these are master rows
00031   if (numberRows==105127) {
00032     // ken-18
00033     for (iRow=104976;iRow<numberRows;iRow++)
00034       rowBlock[iRow]=-1;
00035   } else if (numberRows==810) {
00036     for (iRow=81;iRow<84;iRow++)
00037       rowBlock[iRow]=-1;
00038   } else if (numberRows==5418) {
00039     for (iRow=564;iRow<603;iRow++)
00040       rowBlock[iRow]=-1;
00041   } else if (numberRows==1503) {
00042     // degen3
00043     for (iRow=0;iRow<561;iRow++)
00044       rowBlock[iRow]=-1;
00045   }
00046   CoinPackedMatrix * matrix = model.matrix();
00047   // get row copy
00048   CoinPackedMatrix rowCopy = *matrix;
00049   rowCopy.reverseOrdering();
00050   const int * row = matrix->getIndices();
00051   const int * columnLength = matrix->getVectorLengths();
00052   const CoinBigIndex * columnStart = matrix->getVectorStarts();
00053   //const double * elementByColumn = matrix->getElements();
00054   const int * column = rowCopy.getIndices();
00055   const int * rowLength = rowCopy.getVectorLengths();
00056   const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
00057   //const double * elementByRow = rowCopy.getElements();
00058   int numberBlocks = 0;
00059   int * stack = new int [numberRows];
00060   // to say if column looked at
00061   int numberColumns = model.numberColumns();
00062   int * columnBlock = new int[numberColumns];
00063   int iColumn;
00064   for (iColumn=0;iColumn<numberColumns;iColumn++)
00065     columnBlock[iColumn]=-2;
00066   for (iColumn=0;iColumn<numberColumns;iColumn++) {
00067     int kstart = columnStart[iColumn];
00068     int kend = columnStart[iColumn]+columnLength[iColumn];
00069     if (columnBlock[iColumn]==-2) {
00070       // column not allocated
00071       int j;
00072       int nstack=0;
00073       for (j=kstart;j<kend;j++) {
00074         int iRow= row[j];
00075         if (rowBlock[iRow]!=-1) {
00076           assert(rowBlock[iRow]==-2);
00077           rowBlock[iRow]=numberBlocks; // mark
00078           stack[nstack++] = iRow;
00079         }
00080       }
00081       if (nstack) {
00082         // new block - put all connected in
00083         numberBlocks++;
00084         columnBlock[iColumn]=numberBlocks-1;
00085         while (nstack) {
00086           int iRow = stack[--nstack];
00087           int k;
00088           for (k=rowStart[iRow];k<rowStart[iRow]+rowLength[iRow];k++) {
00089             int iColumn = column[k];
00090             int kkstart = columnStart[iColumn];
00091             int kkend = kkstart + columnLength[iColumn];
00092             if (columnBlock[iColumn]==-2) {
00093               columnBlock[iColumn]=numberBlocks-1; // mark
00094               // column not allocated
00095               int jj;
00096               for (jj=kkstart;jj<kkend;jj++) {
00097                 int jRow= row[jj];
00098                 if (rowBlock[jRow]==-2) {
00099                   rowBlock[jRow]=numberBlocks-1;
00100                   stack[nstack++]=jRow;
00101                 }
00102               }
00103             } else {
00104               assert (columnBlock[iColumn]==numberBlocks-1);
00105             }
00106           }
00107         }
00108       } else {
00109         // Only in master
00110         columnBlock[iColumn]=-1;
00111       }
00112     }
00113   }
00114   printf("%d blocks found\n",numberBlocks);
00115   delete [] stack;
00116   // make up problems
00117   CoinPackedMatrix * top = new CoinPackedMatrix [numberBlocks];
00118   ClpSimplex * sub = new ClpSimplex [numberBlocks];
00119   ClpSimplex master;
00120   // Create all sub problems
00121   // Could do much faster - but do that later
00122   int * whichRow = new int [numberRows];
00123   int * whichColumn = new int [numberColumns];
00124   // get top matrix
00125   CoinPackedMatrix topMatrix = *model.matrix();
00126   int numberRow2,numberColumn2;
00127   numberRow2=0;
00128   for (iRow=0;iRow<numberRows;iRow++)
00129     if (rowBlock[iRow]>=0)
00130       whichRow[numberRow2++]=iRow;
00131   topMatrix.deleteRows(numberRow2,whichRow);
00132   int iBlock;
00133   for (iBlock=0;iBlock<numberBlocks;iBlock++) {
00134     numberRow2=0;
00135     numberColumn2=0;
00136     for (iRow=0;iRow<numberRows;iRow++)
00137       if (iBlock==rowBlock[iRow])
00138         whichRow[numberRow2++]=iRow;
00139     for (iColumn=0;iColumn<numberColumns;iColumn++)
00140       if (iBlock==columnBlock[iColumn])
00141         whichColumn[numberColumn2++]=iColumn;
00142     sub[iBlock]=ClpSimplex(&model,numberRow2,whichRow,
00143                            numberColumn2,whichColumn);
00144 #if 1
00145     // temp
00146     double * upper = sub[iBlock].columnUpper();
00147     for (iColumn=0;iColumn<numberColumn2;iColumn++)
00148       upper[iColumn]=100.0;
00149 #endif
00150     // and top matrix
00151     CoinPackedMatrix matrix = topMatrix;
00152     // and delete bits
00153     numberColumn2=0;
00154     for (iColumn=0;iColumn<numberColumns;iColumn++)
00155       if (iBlock!=columnBlock[iColumn])
00156         whichColumn[numberColumn2++]=iColumn;
00157     matrix.deleteCols(numberColumn2,whichColumn);
00158     top[iBlock]=matrix;
00159   }
00160   // and master
00161   numberRow2=0;
00162   numberColumn2=0;
00163   for (iRow=0;iRow<numberRows;iRow++)
00164     if (rowBlock[iRow]==-1)
00165       whichRow[numberRow2++]=iRow;
00166   for (iColumn=0;iColumn<numberColumns;iColumn++)
00167     if (columnBlock[iColumn]==-1)
00168       whichColumn[numberColumn2++]=iColumn;
00169   ClpModel masterModel(&model,numberRow2,whichRow,
00170                     numberColumn2,whichColumn);
00171   master=ClpSimplex(masterModel);
00172   delete [] whichRow;
00173   delete [] whichColumn;
00174 
00175   // Overkill in terms of space
00176   int numberMasterRows = master.numberRows();
00177   int * columnAdd = new int[numberBlocks+1];
00178   int * rowAdd = new int[numberBlocks*(numberMasterRows+1)];
00179   double * elementAdd = new double[numberBlocks*(numberMasterRows+1)];
00180   double * objective = new double[numberBlocks];
00181   int maxPass=500;
00182   int iPass;
00183   double lastObjective=1.0e31;
00184   // Create convexity rows for proposals 
00185   int numberMasterColumns = master.numberColumns();
00186   master.resize(numberMasterRows+numberBlocks,numberMasterColumns);
00187   // Arrays to say which block and when created
00188   int maximumColumns = 2*numberMasterRows+10*numberBlocks;
00189   int * whichBlock = new int[maximumColumns];
00190   int * when = new int[maximumColumns];
00191   int numberColumnsGenerated=numberBlocks;
00192   // fill in rhs and add in artificials
00193   {
00194     double * rowLower = master.rowLower();
00195     double * rowUpper = master.rowUpper();
00196     int iBlock;
00197     columnAdd[0] = 0;
00198     for (iBlock=0;iBlock<numberBlocks;iBlock++) {
00199       int iRow = iBlock + numberMasterRows;;
00200       rowLower[iRow]=1.0;
00201       rowUpper[iRow]=1.0;
00202       rowAdd[iBlock] = iRow;
00203       elementAdd[iBlock] = 1.0;
00204       objective[iBlock] = 1.0e9;
00205       columnAdd[iBlock+1] = iBlock+1;
00206       when[iBlock]=-1;
00207       whichBlock[iBlock] = iBlock;
00208     }
00209     master.addColumns(numberBlocks,NULL,NULL,objective,
00210                       columnAdd, rowAdd, elementAdd);
00211   }
00212   // and resize matrix to double check clp will be happy
00213   //master.matrix()->setDimensions(numberMasterRows+numberBlocks,
00214   //                     numberMasterColumns+numberBlocks);
00215 
00216   for (iPass=0;iPass<maxPass;iPass++) {
00217     printf("Start of pass %d\n",iPass);
00218     // Solve master - may be infeasible
00219     master.scaling(false);
00220     if (0) {
00221       CoinMpsIO writer;
00222       writer.setMpsData(*master.matrix(), COIN_DBL_MAX,
00223                         master.getColLower(), master.getColUpper(),
00224                         master.getObjCoefficients(),
00225                         (const char*) 0 /*integrality*/,
00226                         master.getRowLower(), master.getRowUpper(),
00227                         NULL,NULL);
00228       writer.writeMps("yy.mps");
00229     }
00230 
00231     master.primal();
00232     if (master.numberIterations()==0&&iPass)
00233       break; // finished
00234     if (master.objectiveValue()>lastObjective-1.0e-7&&iPass>555)
00235       break; // finished
00236     lastObjective = master.objectiveValue();
00237     // mark basic ones and delete if necessary
00238     int iColumn;
00239     numberColumnsGenerated=master.numberColumns()-numberMasterColumns;
00240     for (iColumn=0;iColumn<numberColumnsGenerated;iColumn++) {
00241       if (master.getStatus(iColumn+numberMasterColumns)==ClpSimplex::basic)
00242         when[iColumn]=iPass;
00243     }
00244     if (numberColumnsGenerated+numberBlocks>maximumColumns) {
00245       // delete
00246       int numberKeep=0;
00247       int numberDelete=0;
00248       int * whichDelete = new int[numberColumns];
00249       for (iColumn=0;iColumn<numberColumnsGenerated;iColumn++) {
00250         if (when[iColumn]>iPass-7) {
00251           // keep
00252           when[numberKeep]=when[iColumn];
00253           whichBlock[numberKeep++]=whichBlock[iColumn];
00254         } else {
00255           // delete
00256           whichDelete[numberDelete++]=iColumn+numberMasterColumns;
00257         }
00258       }
00259       numberColumnsGenerated -= numberDelete;
00260       master.deleteColumns(numberDelete,whichDelete);
00261       delete [] whichDelete;
00262     }
00263     const double * dual=NULL;
00264     bool deleteDual=false;
00265     if (master.isProvenOptimal()) {
00266       dual = master.dualRowSolution();
00267     } else if (master.isProvenPrimalInfeasible()) {
00268       // could do composite objective
00269       dual = master.infeasibilityRay();
00270       deleteDual = true;
00271       printf("The sum of infeasibilities is %g\n",
00272              master.sumPrimalInfeasibilities());
00273     } else if (!master.numberColumns()) {
00274       assert(!iPass);
00275       dual = master.dualRowSolution();
00276       memset(master.dualRowSolution(),
00277              0,(numberMasterRows+numberBlocks)*sizeof(double));
00278     } else {
00279       abort();
00280     }
00281     // Create objective for sub problems and solve
00282     columnAdd[0]=0;
00283     int numberProposals=0;
00284     for (iBlock=0;iBlock<numberBlocks;iBlock++) {
00285       int numberColumns2 = sub[iBlock].numberColumns();
00286       double * saveObj = new double [numberColumns2];
00287       double * objective2 = sub[iBlock].objective();
00288       memcpy(saveObj,objective2,numberColumns2*sizeof(double));
00289       // new objective
00290       top[iBlock].transposeTimes(dual,objective2);
00291       int i;
00292       if (master.isProvenOptimal()) {
00293         for (i=0;i<numberColumns2;i++)
00294           objective2[i] = saveObj[i]-objective2[i];
00295       } else {
00296         for (i=0;i<numberColumns2;i++)
00297           objective2[i] = -objective2[i];
00298       }
00299       sub[iBlock].primal();
00300       memcpy(objective2,saveObj,numberColumns2*sizeof(double));
00301       // get proposal
00302       if (sub[iBlock].numberIterations()||!iPass) {
00303         double objValue =0.0;
00304         int start = columnAdd[numberProposals];
00305         // proposal
00306         if (sub[iBlock].isProvenOptimal()) {
00307           const double * solution = sub[iBlock].primalColumnSolution();
00308           top[iBlock].times(solution,elementAdd+start);
00309           for (i=0;i<numberColumns2;i++)
00310             objValue += solution[i]*saveObj[i];
00311           // See if good dj and pack down
00312           int number=start;
00313           double dj = objValue;
00314           if (!master.isProvenOptimal()) 
00315             dj=0.0;
00316           double smallest=1.0e100;
00317           double largest=0.0;
00318           for (i=0;i<numberMasterRows;i++) {
00319             double value = elementAdd[start+i];
00320             if (fabs(value)>1.0e-15) {
00321               dj -= dual[i]*value;
00322               smallest = min(smallest,fabs(value));
00323               largest = max(largest,fabs(value));
00324               rowAdd[number]=i;
00325               elementAdd[number++]=value;
00326             }
00327           }
00328           // and convexity
00329           dj -= dual[numberMasterRows+iBlock];
00330           rowAdd[number]=numberMasterRows+iBlock;
00331           elementAdd[number++]=1.0;
00332           // if elements large then scale?
00333           //if (largest>1.0e8||smallest<1.0e-8)
00334           printf("For subproblem %d smallest - %g, largest %g - dj %g\n",
00335                  iBlock,smallest,largest,dj);
00336           if (dj<-1.0e-6||!iPass) {
00337             // take
00338             objective[numberProposals]=objValue;
00339             columnAdd[++numberProposals]=number;
00340             when[numberColumnsGenerated]=iPass;
00341             whichBlock[numberColumnsGenerated++]=iBlock;
00342           }
00343         } else if (sub[iBlock].isProvenDualInfeasible()) {
00344           // use ray
00345           const double * solution = sub[iBlock].unboundedRay();
00346           top[iBlock].times(solution,elementAdd+start);
00347           for (i=0;i<numberColumns2;i++)
00348             objValue += solution[i]*saveObj[i];
00349           // See if good dj and pack down
00350           int number=start;
00351           double dj = objValue;
00352           double smallest=1.0e100;
00353           double largest=0.0;
00354           for (i=0;i<numberMasterRows;i++) {
00355             double value = elementAdd[start+i];
00356             if (fabs(value)>1.0e-15) {
00357               dj -= dual[i]*value;
00358               smallest = min(smallest,fabs(value));
00359               largest = max(largest,fabs(value));
00360               rowAdd[number]=i;
00361               elementAdd[number++]=value;
00362             }
00363           }
00364           // if elements large or small then scale?
00365           //if (largest>1.0e8||smallest<1.0e-8)
00366             printf("For subproblem ray %d smallest - %g, largest %g - dj %g\n",
00367                    iBlock,smallest,largest,dj);
00368           if (dj<-1.0e-6) {
00369             // take
00370             objective[numberProposals]=objValue;
00371             columnAdd[++numberProposals]=number;
00372             when[numberColumnsGenerated]=iPass;
00373             whichBlock[numberColumnsGenerated++]=iBlock;
00374           }
00375         } else {
00376           abort();
00377         }
00378       }
00379     }
00380     if (deleteDual)
00381       delete [] dual;
00382     if (numberProposals) 
00383       master.addColumns(numberProposals,NULL,NULL,objective,
00384                         columnAdd,rowAdd,elementAdd);
00385   }
00386   // now put back a good solution
00387   double * lower = new double[numberMasterRows+numberBlocks];
00388   double * upper = new double[numberMasterRows+numberBlocks];
00389   numberColumnsGenerated  += numberMasterColumns;
00390   double * sol = new double[numberColumnsGenerated];
00391   const double * solution = master.primalColumnSolution();
00392   const double * masterLower = master.rowLower();
00393   const double * masterUpper = master.rowUpper();
00394   double * fullSolution = model.primalColumnSolution();
00395   const double * fullLower = model.columnLower();
00396   const double * fullUpper = model.columnUpper();
00397   int kColumn=0;
00398   for (iRow=0;iRow<numberRows;iRow++)
00399     model.setRowStatus(iRow,ClpSimplex::superBasic);
00400   for (iColumn=0;iColumn<numberColumns;iColumn++) {
00401     if (columnBlock[iColumn]==-1) {
00402       model.setStatus(iColumn,master.getStatus(kColumn));
00403       fullSolution[iColumn]=solution[kColumn++];
00404     }
00405   }
00406   for (iBlock=0;iBlock<numberBlocks;iBlock++) {
00407     // convert top bit to by rows
00408     top[iBlock].reverseOrdering();
00409     // zero solution
00410     memset(sol,0,numberColumnsGenerated*sizeof(double));
00411     int i;
00412     for (i=numberMasterColumns;i<numberColumnsGenerated;i++)
00413       if (whichBlock[i-numberMasterColumns]==iBlock)
00414         sol[i] = solution[i];
00415     memset(lower,0,numberMasterRows*sizeof(double));
00416     master.times(1.0,sol,lower);
00417     for (iRow=0;iRow<numberMasterRows;iRow++) {
00418       double value = lower[iRow];
00419       if (masterUpper[iRow]<1.0e20) 
00420         upper[iRow] = value;
00421       else
00422         upper[iRow]=COIN_DBL_MAX;
00423       if (masterLower[iRow]>-1.0e20) 
00424         lower[iRow] = value;
00425       else
00426         lower[iRow]=-COIN_DBL_MAX;
00427     }
00428     sub[iBlock].addRows(numberMasterRows,lower,upper,
00429                         top[iBlock].getVectorStarts(),
00430                         top[iBlock].getVectorLengths(),
00431                         top[iBlock].getIndices(),
00432                         top[iBlock].getElements());
00433     sub[iBlock].primal();
00434     const double * subSolution = sub[iBlock].primalColumnSolution();
00435     // move solution
00436     kColumn=0;
00437     for (iColumn=0;iColumn<numberColumns;iColumn++) {
00438       if (columnBlock[iColumn]==iBlock) {
00439         model.setStatus(iColumn,sub[iBlock].getStatus(kColumn));
00440         fullSolution[iColumn]=subSolution[kColumn++];
00441       }
00442     }
00443     assert(kColumn==sub[iBlock].numberColumns());
00444   }
00445   for (iColumn=0;iColumn<numberColumns;iColumn++) {
00446     if (fullSolution[iColumn]<fullUpper[iColumn]-1.0e-8&&
00447         fullSolution[iColumn]>fullLower[iColumn]+1.0e-8) {
00448       model.setStatus(iColumn,ClpSimplex::basic);
00449     }
00450   }
00451   model.primal(1);
00452   delete [] sol;
00453   delete [] lower;
00454   delete [] upper;
00455   delete [] whichBlock;
00456   delete [] when;
00457   delete [] columnAdd;
00458   delete [] rowAdd;
00459   delete [] elementAdd;
00460   delete [] objective;
00461   delete [] top;
00462   delete [] sub;
00463   delete [] rowBlock;
00464   delete [] columnBlock;
00465   return 0;
00466 }    

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