00001
00002
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
00013 if (argc<2) {
00014
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
00023
00024
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
00031 if (numberRows==105127) {
00032
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
00043 for (iRow=0;iRow<561;iRow++)
00044 rowBlock[iRow]=-1;
00045 }
00046 CoinPackedMatrix * matrix = model.matrix();
00047
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
00054 const int * column = rowCopy.getIndices();
00055 const int * rowLength = rowCopy.getVectorLengths();
00056 const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
00057
00058 int numberBlocks = 0;
00059 int * stack = new int [numberRows];
00060
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
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;
00078 stack[nstack++] = iRow;
00079 }
00080 }
00081 if (nstack) {
00082
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;
00094
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
00110 columnBlock[iColumn]=-1;
00111 }
00112 }
00113 }
00114 printf("%d blocks found\n",numberBlocks);
00115 delete [] stack;
00116
00117 CoinPackedMatrix * top = new CoinPackedMatrix [numberBlocks];
00118 ClpSimplex * sub = new ClpSimplex [numberBlocks];
00119 ClpSimplex master;
00120
00121
00122 int * whichRow = new int [numberRows];
00123 int * whichColumn = new int [numberColumns];
00124
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
00146 double * upper = sub[iBlock].columnUpper();
00147 for (iColumn=0;iColumn<numberColumn2;iColumn++)
00148 upper[iColumn]=100.0;
00149 #endif
00150
00151 CoinPackedMatrix matrix = topMatrix;
00152
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
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
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
00185 int numberMasterColumns = master.numberColumns();
00186 master.resize(numberMasterRows+numberBlocks,numberMasterColumns);
00187
00188 int maximumColumns = 2*numberMasterRows+10*numberBlocks;
00189 int * whichBlock = new int[maximumColumns];
00190 int * when = new int[maximumColumns];
00191 int numberColumnsGenerated=numberBlocks;
00192
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
00213
00214
00215
00216 for (iPass=0;iPass<maxPass;iPass++) {
00217 printf("Start of pass %d\n",iPass);
00218
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 ,
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;
00234 if (master.objectiveValue()>lastObjective-1.0e-7&&iPass>555)
00235 break;
00236 lastObjective = master.objectiveValue();
00237
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
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
00252 when[numberKeep]=when[iColumn];
00253 whichBlock[numberKeep++]=whichBlock[iColumn];
00254 } else {
00255
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
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
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
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
00302 if (sub[iBlock].numberIterations()||!iPass) {
00303 double objValue =0.0;
00304 int start = columnAdd[numberProposals];
00305
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
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
00329 dj -= dual[numberMasterRows+iBlock];
00330 rowAdd[number]=numberMasterRows+iBlock;
00331 elementAdd[number++]=1.0;
00332
00333
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
00338 objective[numberProposals]=objValue;
00339 columnAdd[++numberProposals]=number;
00340 when[numberColumnsGenerated]=iPass;
00341 whichBlock[numberColumnsGenerated++]=iBlock;
00342 }
00343 } else if (sub[iBlock].isProvenDualInfeasible()) {
00344
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
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
00365
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
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
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
00408 top[iBlock].reverseOrdering();
00409
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
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 }