00001
00002
00003
00004
00005
00006 #include <stdio.h>
00007
00008 #include <assert.h>
00009 #include <iostream>
00010
00011 #include "CoinHelperFunctions.hpp"
00012
00013 #include "CoinPackedMatrix.hpp"
00014 #include "ClpSimplex.hpp"
00015
00016 #include "ClpPresolve.hpp"
00017 #include "CoinPresolveMatrix.hpp"
00018
00019 #include "CoinPresolveEmpty.hpp"
00020 #include "CoinPresolveFixed.hpp"
00021 #include "CoinPresolvePsdebug.hpp"
00022 #include "CoinPresolveSingleton.hpp"
00023 #include "CoinPresolveDoubleton.hpp"
00024 #include "CoinPresolveTripleton.hpp"
00025 #include "CoinPresolveZeros.hpp"
00026 #include "CoinPresolveSubst.hpp"
00027 #include "CoinPresolveForcing.hpp"
00028 #include "CoinPresolveDual.hpp"
00029 #include "CoinPresolveTighten.hpp"
00030 #include "CoinPresolveUseless.hpp"
00031 #include "CoinPresolveDupcol.hpp"
00032 #include "CoinPresolveImpliedFree.hpp"
00033 #include "CoinPresolveIsolated.hpp"
00034 #include "CoinMessage.hpp"
00035
00036
00037
00038 ClpPresolve::ClpPresolve() :
00039 originalModel_(NULL),
00040 presolvedModel_(NULL),
00041 nonLinearValue_(0.0),
00042 originalColumn_(NULL),
00043 originalRow_(NULL),
00044 paction_(0),
00045 ncols_(0),
00046 nrows_(0),
00047 nelems_(0),
00048 numberPasses_(5),
00049 saveFile_("")
00050 {
00051 }
00052
00053 ClpPresolve::~ClpPresolve()
00054 {
00055 gutsOfDestroy();
00056 }
00057
00058 void
00059 ClpPresolve::gutsOfDestroy()
00060 {
00061 const CoinPresolveAction *paction = paction_;
00062 while (paction) {
00063 const CoinPresolveAction *next = paction->next;
00064 delete paction;
00065 paction = next;
00066 }
00067 delete [] originalColumn_;
00068 delete [] originalRow_;
00069 paction_=NULL;
00070 originalColumn_=NULL;
00071 originalRow_=NULL;
00072 }
00073
00074
00075
00076
00077 ClpSimplex *
00078 ClpPresolve::presolvedModel(ClpSimplex & si,
00079 double feasibilityTolerance,
00080 bool keepIntegers,
00081 int numberPasses,
00082 bool dropNames)
00083 {
00084
00085 if (!si.clpMatrix()->allElementsInRange(&si,si.getSmallElementValue(),
00086 1.0e20))
00087 return NULL;
00088 else
00089 return gutsOfPresolvedModel(&si,feasibilityTolerance,keepIntegers,numberPasses,dropNames);
00090 }
00091
00092
00093
00094 int
00095 ClpPresolve::presolvedModelToFile(ClpSimplex &si,std::string fileName,
00096 double feasibilityTolerance,
00097 bool keepIntegers,
00098 int numberPasses)
00099 {
00100
00101 if (!si.clpMatrix()->allElementsInRange(&si,si.getSmallElementValue(),
00102 1.0e20))
00103 return 2;
00104 saveFile_=fileName;
00105 si.saveModel(saveFile_.c_str());
00106 ClpSimplex * model = gutsOfPresolvedModel(&si,feasibilityTolerance,keepIntegers,numberPasses,true);
00107 if (model==&si) {
00108 return 0;
00109 } else {
00110 si.restoreModel(saveFile_.c_str());
00111 return 1;
00112 }
00113 }
00114
00115
00116 ClpSimplex *
00117 ClpPresolve::model() const
00118 {
00119 return presolvedModel_;
00120 }
00121
00122 ClpSimplex *
00123 ClpPresolve::originalModel() const
00124 {
00125 return originalModel_;
00126 }
00127 void
00128 ClpPresolve::postsolve(bool updateStatus)
00129 {
00130
00131 CoinMessages messages = CoinMessage(presolvedModel_->messages().language());
00132 if (!presolvedModel_->isProvenOptimal()) {
00133 presolvedModel_->messageHandler()->message(COIN_PRESOLVE_NONOPTIMAL,
00134 messages)
00135 <<CoinMessageEol;
00136 }
00137
00138
00139 const int ncols0 = ncols_;
00140 const int nrows0 = nrows_;
00141 const CoinBigIndex nelems0 = nelems_;
00142
00143
00144 int ncols = presolvedModel_->getNumCols();
00145 int nrows = presolvedModel_->getNumRows();
00146
00147 double * acts=NULL;
00148 double * sol =NULL;
00149 unsigned char * rowstat=NULL;
00150 unsigned char * colstat = NULL;
00151 if (saveFile_=="") {
00152
00153 assert(ncols0==originalModel_->getNumCols());
00154 assert(nrows0==originalModel_->getNumRows());
00155 acts = originalModel_->primalRowSolution();
00156 sol = originalModel_->primalColumnSolution();
00157 if (updateStatus) {
00158 unsigned char *status = originalModel_->statusArray();
00159 rowstat = status + ncols0;
00160 colstat = status;
00161 memcpy(colstat, presolvedModel_->statusArray(), ncols);
00162 memcpy(rowstat, presolvedModel_->statusArray()+ncols, nrows);
00163 }
00164 } else {
00165
00166 acts = new double[nrows0];
00167 sol = new double[ncols0];
00168 if (updateStatus) {
00169 unsigned char *status = new unsigned char [nrows0+ncols0];
00170 rowstat = status + ncols0;
00171 colstat = status;
00172 memcpy(colstat, presolvedModel_->statusArray(), ncols);
00173 memcpy(rowstat, presolvedModel_->statusArray()+ncols, nrows);
00174 }
00175 }
00176
00177
00178 CoinPostsolveMatrix prob(presolvedModel_,
00179 ncols0,
00180 nrows0,
00181 nelems0,
00182 presolvedModel_->getObjSense(),
00183
00184
00185 sol, acts,
00186 colstat, rowstat);
00187
00188 postsolve(prob);
00189
00190 if (saveFile_!="") {
00191
00192 assert (originalModel_==presolvedModel_);
00193 originalModel_->restoreModel(saveFile_.c_str());
00194 memcpy(originalModel_->primalRowSolution(),acts,nrows0*sizeof(double));
00195 delete [] acts;
00196 memcpy(originalModel_->primalColumnSolution(),sol,ncols0*sizeof(double));
00197 delete [] sol;
00198 if (updateStatus) {
00199 memcpy(originalModel_->statusArray(),colstat,nrows0+ncols0);
00200 delete [] colstat;
00201 }
00202 }
00203
00204 memcpy(originalModel_->dualRowSolution(),prob.rowduals_,
00205 nrows_*sizeof(double));
00206 double maxmin = originalModel_->getObjSense();
00207 if (maxmin<0.0) {
00208
00209 int i;
00210 double * pi = originalModel_->dualRowSolution();
00211 for (i=0;i<nrows_;i++)
00212 pi[i] = -pi[i];
00213 }
00214
00215 memcpy(originalModel_->dualColumnSolution(),
00216 originalModel_->objective(),ncols_*sizeof(double));
00217 originalModel_->transposeTimes(-1.0,
00218 originalModel_->dualRowSolution(),
00219 originalModel_->dualColumnSolution());
00220 memset(originalModel_->primalRowSolution(),0,nrows_*sizeof(double));
00221 originalModel_->times(1.0,originalModel_->primalColumnSolution(),
00222 originalModel_->primalRowSolution());
00223 originalModel_->checkSolution();
00224
00225 presolvedModel_->messageHandler()->message(COIN_PRESOLVE_POSTSOLVE,
00226 messages)
00227 <<originalModel_->objectiveValue()
00228 <<originalModel_->sumDualInfeasibilities()
00229 <<originalModel_->numberDualInfeasibilities()
00230 <<originalModel_->sumPrimalInfeasibilities()
00231 <<originalModel_->numberPrimalInfeasibilities()
00232 <<CoinMessageEol;
00233
00234
00235 originalModel_->setNumberIterations(presolvedModel_->numberIterations());
00236 if (!presolvedModel_->status()) {
00237 if (!originalModel_->numberDualInfeasibilities()&&
00238 !originalModel_->numberPrimalInfeasibilities()) {
00239 originalModel_->setProblemStatus( 0);
00240 } else {
00241 originalModel_->setProblemStatus( -1);
00242 presolvedModel_->messageHandler()->message(COIN_PRESOLVE_NEEDS_CLEANING,
00243 messages)
00244 <<CoinMessageEol;
00245 }
00246 } else {
00247 originalModel_->setProblemStatus( presolvedModel_->status());
00248 }
00249 if (saveFile_!="")
00250 presolvedModel_=NULL;
00251 }
00252
00253
00254 const int *
00255 ClpPresolve::originalColumns() const
00256 {
00257 return originalColumn_;
00258 }
00259
00260 const int *
00261 ClpPresolve::originalRows() const
00262 {
00263 return originalRow_;
00264 }
00265
00266 void
00267 ClpPresolve::setOriginalModel(ClpSimplex * model)
00268 {
00269 originalModel_=model;
00270 }
00271 #if 0
00272
00273
00274 static int ATOI(const char *name)
00275 {
00276 return true;
00277 #if DEBUG_PRESOLVE || PRESOLVE_SUMMARY
00278 if (getenv(name)) {
00279 int val = atoi(getenv(name));
00280 printf("%s = %d\n", name, val);
00281 return (val);
00282 } else {
00283 if (strcmp(name,"off"))
00284 return (true);
00285 else
00286 return (false);
00287 }
00288 #else
00289 return (true);
00290 #endif
00291 }
00292 #endif
00293
00294 #if DEBUG_PRESOLVE
00295 void check_sol(CoinPresolveMatrix *prob,double tol)
00296 {
00297 double *colels = prob->colels_;
00298 int *hrow = prob->hrow_;
00299 int *mcstrt = prob->mcstrt_;
00300 int *hincol = prob->hincol_;
00301 int *hinrow = prob->hinrow_;
00302 int ncols = prob->ncols_;
00303
00304
00305 double * csol = prob->sol_;
00306 double * acts = prob->acts_;
00307 double * clo = prob->clo_;
00308 double * cup = prob->cup_;
00309 int nrows = prob->nrows_;
00310 double * rlo = prob->rlo_;
00311 double * rup = prob->rup_;
00312
00313 int colx;
00314
00315 double * rsol = new double[nrows];
00316 memset(rsol,0,nrows*sizeof(double));
00317
00318 for (colx = 0; colx < ncols; ++colx) {
00319 if (1) {
00320 CoinBigIndex k = mcstrt[colx];
00321 int nx = hincol[colx];
00322 double solutionValue = csol[colx];
00323 for (int i=0; i<nx; ++i) {
00324 int row = hrow[k];
00325 double coeff = colels[k];
00326 k++;
00327 rsol[row] += solutionValue*coeff;
00328 }
00329 if (csol[colx]<clo[colx]-tol) {
00330 printf("low CSOL: %d - %g %g %g\n",
00331 colx, clo[colx], csol[colx], cup[colx]);
00332 } else if (csol[colx]>cup[colx]+tol) {
00333 printf("high CSOL: %d - %g %g %g\n",
00334 colx, clo[colx], csol[colx], cup[colx]);
00335 }
00336 }
00337 }
00338 int rowx;
00339 for (rowx = 0; rowx < nrows; ++rowx) {
00340 if (hinrow[rowx]) {
00341 if (fabs(rsol[rowx]-acts[rowx])>tol)
00342 printf("inacc RSOL: %d - %g %g (acts_ %g) %g\n",
00343 rowx, rlo[rowx], rsol[rowx], acts[rowx], rup[rowx]);
00344 if (rsol[rowx]<rlo[rowx]-tol) {
00345 printf("low RSOL: %d - %g %g %g\n",
00346 rowx, rlo[rowx], rsol[rowx], rup[rowx]);
00347 } else if (rsol[rowx]>rup[rowx]+tol ) {
00348 printf("high RSOL: %d - %g %g %g\n",
00349 rowx, rlo[rowx], rsol[rowx], rup[rowx]);
00350 }
00351 }
00352 }
00353 delete [] rsol;
00354 }
00355 #endif
00356
00357
00358
00359 const CoinPresolveAction *ClpPresolve::presolve(CoinPresolveMatrix *prob)
00360 {
00361
00362 CoinMessages messages = CoinMessage(prob->messages().language());
00363 paction_ = 0;
00364
00365 prob->status_=0;
00366
00367 paction_ = make_fixed(prob, paction_);
00368
00369
00370 bool doDualStuff = (presolvedModel_->integerInformation()==NULL);
00371
00372 #if CHECK_CONSISTENCY
00373 presolve_links_ok(prob->rlink_, prob->mrstrt_, prob->hinrow_, prob->nrows_);
00374 #endif
00375
00376 if (!prob->status_) {
00377 #if 0
00378 const bool slackd = ATOI("SLACKD")!=0;
00379
00380 const bool doubleton = ATOI("DOUBLETON")!=0;
00381 const bool forcing = ATOI("off")!=0;
00382 const bool ifree = ATOI("off")!=0;
00383 const bool zerocost = ATOI("off")!=0;
00384 const bool dupcol = ATOI("off")!=0;
00385 const bool duprow = ATOI("off")!=0;
00386 const bool dual = ATOI("off")!=0;
00387 #else
00388
00389 #if 0
00390 const bool slackd = true;
00391 const bool doubleton = false;
00392 const bool tripleton = true;
00393 const bool forcing = false;
00394 const bool ifree = true;
00395 const bool zerocost = true;
00396 const bool dupcol = false;
00397 const bool duprow = false;
00398 const bool dual = doDualStuff;
00399 #else
00400 const bool slackd = true;
00401 const bool doubleton = true;
00402 const bool tripleton = true;
00403 const bool forcing = true;
00404 const bool ifree = true;
00405 const bool zerocost = true;
00406 const bool dupcol = true;
00407 const bool duprow = true;
00408 const bool dual = doDualStuff;
00409 #endif
00410 #endif
00411
00412
00413
00414 int i;
00415
00416 if (!prob->anyProhibited()) {
00417 for (i=0;i<nrows_;i++)
00418 prob->rowsToDo_[i]=i;
00419 prob->numberRowsToDo_=nrows_;
00420 for (i=0;i<ncols_;i++)
00421 prob->colsToDo_[i]=i;
00422 prob->numberColsToDo_=ncols_;
00423 } else {
00424
00425 prob->numberRowsToDo_=0;
00426 for (i=0;i<nrows_;i++)
00427 if (!prob->rowProhibited(i))
00428 prob->rowsToDo_[prob->numberRowsToDo_++]=i;
00429 prob->numberColsToDo_=0;
00430 for (i=0;i<ncols_;i++)
00431 if (!prob->colProhibited(i))
00432 prob->colsToDo_[prob->numberColsToDo_++]=i;
00433 }
00434
00435
00436 int iLoop;
00437 #if DEBUG_PRESOLVE
00438 check_sol(prob,1.0e0);
00439 #endif
00440
00441
00442 int lastDropped=0;
00443 prob->pass_=0;
00444 for (iLoop=0;iLoop<numberPasses_;iLoop++) {
00445 #ifdef PRESOLVE_SUMMARY
00446 printf("Starting major pass %d\n",iLoop+1);
00447 #endif
00448 const CoinPresolveAction * const paction0 = paction_;
00449
00450 int fill_level=2;
00451
00452
00453 int whichPass=0;
00454 while (1) {
00455 whichPass++;
00456 const CoinPresolveAction * const paction1 = paction_;
00457
00458 if (slackd) {
00459 bool notFinished = true;
00460 while (notFinished)
00461 paction_ = slack_doubleton_action::presolve(prob, paction_,
00462 notFinished);
00463 if (prob->status_)
00464 break;
00465 }
00466 if (dual&&whichPass==1) {
00467
00468 paction_ = remove_dual_action::presolve(prob, paction_);
00469 if (prob->status_)
00470 break;
00471 }
00472
00473 if (doubleton) {
00474 paction_ = doubleton_action::presolve(prob, paction_);
00475 if (prob->status_)
00476 break;
00477 }
00478
00479 if (tripleton) {
00480 paction_ = tripleton_action::presolve(prob, paction_);
00481 if (prob->status_)
00482 break;
00483 }
00484
00485 if (zerocost) {
00486 paction_ = do_tighten_action::presolve(prob, paction_);
00487 if (prob->status_)
00488 break;
00489 }
00490
00491 if (forcing) {
00492 paction_ = forcing_constraint_action::presolve(prob, paction_);
00493 if (prob->status_)
00494 break;
00495 }
00496
00497 if (ifree) {
00498 paction_ = implied_free_action::presolve(prob, paction_,fill_level);
00499 if (prob->status_)
00500 break;
00501 }
00502
00503 #if DEBUG_PRESOLVE
00504 check_sol(prob,1.0e0);
00505 #endif
00506
00507 #if CHECK_CONSISTENCY
00508 presolve_links_ok(prob->rlink_, prob->mrstrt_, prob->hinrow_,
00509 prob->nrows_);
00510 #endif
00511
00512 #if DEBUG_PRESOLVE
00513 presolve_no_zeros(prob->mcstrt_, prob->colels_, prob->hincol_,
00514 prob->ncols_);
00515 #endif
00516 #if CHECK_CONSISTENCY
00517 prob->consistent();
00518 #endif
00519
00520
00521
00522
00523 prob->numberRowsToDo_ = prob->numberNextRowsToDo_;
00524 int kcheck;
00525 bool found=false;
00526 kcheck=-1;
00527 for (i=0;i<prob->numberNextRowsToDo_;i++) {
00528 int index = prob->nextRowsToDo_[i];
00529 prob->unsetRowChanged(index);
00530 prob->rowsToDo_[i] = index;
00531 if (index==kcheck) {
00532 printf("row %d on list after pass %d\n",kcheck,
00533 whichPass);
00534 found=true;
00535 }
00536 }
00537 if (!found&&kcheck>=0)
00538 prob->rowsToDo_[prob->numberRowsToDo_++]=kcheck;
00539 prob->numberNextRowsToDo_=0;
00540 prob->numberColsToDo_ = prob->numberNextColsToDo_;
00541 kcheck=-1;
00542 found=false;
00543 for (i=0;i<prob->numberNextColsToDo_;i++) {
00544 int index = prob->nextColsToDo_[i];
00545 prob->unsetColChanged(index);
00546 prob->colsToDo_[i] = index;
00547 if (index==kcheck) {
00548 printf("col %d on list after pass %d\n",kcheck,
00549 whichPass);
00550 found=true;
00551 }
00552 }
00553 if (!found&&kcheck>=0)
00554 prob->colsToDo_[prob->numberColsToDo_++]=kcheck;
00555 prob->numberNextColsToDo_=0;
00556 if (paction_ == paction1&&fill_level>0)
00557 break;
00558 }
00559
00560 int i;
00561 if (!prob->anyProhibited()) {
00562 for (i=0;i<nrows_;i++)
00563 prob->rowsToDo_[i]=i;
00564 prob->numberRowsToDo_=nrows_;
00565 for (i=0;i<ncols_;i++)
00566 prob->colsToDo_[i]=i;
00567 prob->numberColsToDo_=ncols_;
00568 } else {
00569
00570 prob->numberRowsToDo_=0;
00571 for (i=0;i<nrows_;i++)
00572 if (!prob->rowProhibited(i))
00573 prob->rowsToDo_[prob->numberRowsToDo_++]=i;
00574 prob->numberColsToDo_=0;
00575 for (i=0;i<ncols_;i++)
00576 if (!prob->colProhibited(i))
00577 prob->colsToDo_[prob->numberColsToDo_++]=i;
00578 }
00579
00580
00581 #ifdef PRESOLVE_SUMMARY
00582 printf("Starting expensive\n");
00583 #endif
00584
00585 if (dual) {
00586 int itry;
00587 for (itry=0;itry<5;itry++) {
00588 const CoinPresolveAction * const paction2 = paction_;
00589 paction_ = remove_dual_action::presolve(prob, paction_);
00590 if (prob->status_)
00591 break;
00592 if (ifree) {
00593 int fill_level=0;
00594 paction_ = implied_free_action::presolve(prob, paction_,fill_level);
00595 if (prob->status_)
00596 break;
00597 }
00598 if (paction_ == paction2)
00599 break;
00600 }
00601 }
00602 #if DEBUG_PRESOLVE
00603 check_sol(prob,1.0e0);
00604 #endif
00605 if (dupcol) {
00606 paction_ = dupcol_action::presolve(prob, paction_);
00607 if (prob->status_)
00608 break;
00609 }
00610 #if DEBUG_PRESOLVE
00611 check_sol(prob,1.0e0);
00612 #endif
00613
00614 if (duprow) {
00615 paction_ = duprow_action::presolve(prob, paction_);
00616 if (prob->status_)
00617 break;
00618 }
00619 #if DEBUG_PRESOLVE
00620 check_sol(prob,1.0e0);
00621 #endif
00622 {
00623 int * hinrow = prob->hinrow_;
00624 int numberDropped=0;
00625 for (i=0;i<nrows_;i++)
00626 if (!hinrow[i])
00627 numberDropped++;
00628
00629 prob->messageHandler()->message(COIN_PRESOLVE_PASS,
00630 messages)
00631 <<numberDropped<<iLoop+1
00632 <<CoinMessageEol;
00633
00634
00635 if (numberDropped==lastDropped)
00636 break;
00637 else
00638 lastDropped = numberDropped;
00639 }
00640 if (paction_ == paction0)
00641 break;
00642
00643 }
00644 }
00645 if (!prob->status_) {
00646 paction_ = drop_zero_coefficients(prob, paction_);
00647 #if DEBUG_PRESOLVE
00648 check_sol(prob,1.0e0);
00649 #endif
00650
00651 paction_ = drop_empty_cols_action::presolve(prob, paction_);
00652 paction_ = drop_empty_rows_action::presolve(prob, paction_);
00653 #if DEBUG_PRESOLVE
00654 check_sol(prob,1.0e0);
00655 #endif
00656 }
00657
00658 if (prob->status_) {
00659 if (prob->status_==1)
00660 prob->messageHandler()->message(COIN_PRESOLVE_INFEAS,
00661 messages)
00662 <<prob->feasibilityTolerance_
00663 <<CoinMessageEol;
00664 else if (prob->status_==2)
00665 prob->messageHandler()->message(COIN_PRESOLVE_UNBOUND,
00666 messages)
00667 <<CoinMessageEol;
00668 else
00669 prob->messageHandler()->message(COIN_PRESOLVE_INFEASUNBOUND,
00670 messages)
00671 <<CoinMessageEol;
00672
00673 gutsOfDestroy();
00674 }
00675 return (paction_);
00676 }
00677
00678 void check_djs(CoinPostsolveMatrix *prob);
00679
00680
00681
00682
00683 void ClpPresolve::postsolve(CoinPostsolveMatrix &prob)
00684 {
00685 {
00686
00687 double *colels = prob.colels_;
00688 int *hrow = prob.hrow_;
00689 int *mcstrt = prob.mcstrt_;
00690 int *hincol = prob.hincol_;
00691 int *link = prob.link_;
00692 int ncols = prob.ncols_;
00693
00694 char *cdone = prob.cdone_;
00695
00696 double * csol = prob.sol_;
00697 int nrows = prob.nrows_;
00698
00699 int colx;
00700
00701 double * rsol = prob.acts_;
00702 memset(rsol,0,nrows*sizeof(double));
00703
00704 for (colx = 0; colx < ncols; ++colx) {
00705 if (cdone[colx]) {
00706 CoinBigIndex k = mcstrt[colx];
00707 int nx = hincol[colx];
00708 double solutionValue = csol[colx];
00709 for (int i=0; i<nx; ++i) {
00710 int row = hrow[k];
00711 double coeff = colels[k];
00712 k = link[k];
00713 rsol[row] += solutionValue*coeff;
00714 }
00715 }
00716 }
00717 }
00718 const CoinPresolveAction *paction = paction_;
00719
00720 if (prob.colstat_)
00721 prob.check_nbasic();
00722
00723 #if DEBUG_PRESOLVE
00724 check_djs(&prob);
00725 #endif
00726
00727
00728 while (paction) {
00729 #if DEBUG_PRESOLVE
00730 printf("POSTSOLVING %s\n", paction->name());
00731 #endif
00732
00733 paction->postsolve(&prob);
00734
00735 #if DEBUG_PRESOLVE
00736 if (prob.colstat_)
00737 prob.check_nbasic();
00738 #endif
00739 paction = paction->next;
00740 #if DEBUG_PRESOLVE
00741 check_djs(&prob);
00742 #endif
00743 }
00744
00745 #if 0 && DEBUG_PRESOLVE
00746 for (i=0; i<ncols0; i++) {
00747 if (!cdone[i]) {
00748 printf("!cdone[%d]\n", i);
00749 abort();
00750 }
00751 }
00752
00753 for (i=0; i<nrows0; i++) {
00754 if (!rdone[i]) {
00755 printf("!rdone[%d]\n", i);
00756 abort();
00757 }
00758 }
00759
00760
00761 for (i=0; i<ncols0; i++) {
00762 if (sol[i] < -1e10 || sol[i] > 1e10)
00763 printf("!!!%d %g\n", i, sol[i]);
00764
00765 }
00766
00767
00768 #endif
00769
00770 #if 0 && DEBUG_PRESOLVE
00771
00772 {
00773 int identical = 1;
00774
00775 for (int i=0; i<ncols0; i++) {
00776 PRESOLVEASSERT(hincol[i] == &prob->mcstrt0[i+1] - &prob->mcstrt0[i]);
00777 CoinBigIndex kcs0 = &prob->mcstrt0[i];
00778 CoinBigIndex kcs = mcstrt[i];
00779 int n = hincol[i];
00780 for (int k=0; k<n; k++) {
00781 CoinBigIndex k1 = presolve_find_row1(&prob->hrow0[kcs0+k], kcs, kcs+n, hrow);
00782
00783 if (k1 == kcs+n) {
00784 printf("ROW %d NOT IN COL %d\n", &prob->hrow0[kcs0+k], i);
00785 abort();
00786 }
00787
00788 if (colels[k1] != &prob->dels0[kcs0+k])
00789 printf("BAD COLEL[%d %d %d]: %g\n",
00790 k1, i, &prob->hrow0[kcs0+k], colels[k1] - &prob->dels0[kcs0+k]);
00791
00792 if (kcs0+k != k1)
00793 identical=0;
00794 }
00795 }
00796 printf("identical? %d\n", identical);
00797 }
00798 #endif
00799 }
00800
00801
00802
00803
00804
00805
00806
00807
00808 #if DEBUG_PRESOLVE
00809 void check_djs(CoinPostsolveMatrix *prob)
00810 {
00811
00812 double *colels = prob->colels_;
00813 int *hrow = prob->hrow_;
00814 int *mcstrt = prob->mcstrt_;
00815 int *hincol = prob->hincol_;
00816 int *link = prob->link_;
00817 int ncols = prob->ncols_;
00818
00819 double *dcost = prob->cost_;
00820
00821 double *rcosts = prob->rcosts_;
00822
00823 double *rowduals = prob->rowduals_;
00824
00825 const double maxmin = prob->maxmin_;
00826
00827 char *cdone = prob->cdone_;
00828
00829 double * csol = prob->sol_;
00830 double * clo = prob->clo_;
00831 double * cup = prob->cup_;
00832 int nrows = prob->nrows_;
00833 double * rlo = prob->rlo_;
00834 double * rup = prob->rup_;
00835 char *rdone = prob->rdone_;
00836
00837 int colx;
00838
00839 double * rsol = new double[nrows];
00840 memset(rsol,0,nrows*sizeof(double));
00841
00842 for (colx = 0; colx < ncols; ++colx) {
00843 if (cdone[colx]) {
00844 CoinBigIndex k = mcstrt[colx];
00845 int nx = hincol[colx];
00846 double dj = maxmin * dcost[colx];
00847 double solutionValue = csol[colx];
00848 for (int i=0; i<nx; ++i) {
00849 int row = hrow[k];
00850 double coeff = colels[k];
00851 k = link[k];
00852 dj -= rowduals[row] * coeff;
00853 rsol[row] += solutionValue*coeff;
00854 }
00855 if (! (fabs(rcosts[colx] - dj) < 1.0e-4))
00856 printf("BAD DJ: %d %g %g\n",
00857 colx, rcosts[colx], dj);
00858 if (cup[colx]-clo[colx]>1.0e-6) {
00859 if (csol[colx]<clo[colx]+1.0e-6) {
00860 if (dj <-1.0e-6)
00861 printf("neg DJ: %d %g - %g %g %g\n",
00862 colx, dj, clo[colx], csol[colx], cup[colx]);
00863 } else if (csol[colx]>cup[colx]-1.0e-6) {
00864 if (dj > 1.0e-6)
00865 printf("pos DJ: %d %g - %g %g %g\n",
00866 colx, dj, clo[colx], csol[colx], cup[colx]);
00867 } else {
00868 if (fabs(dj) >1.0e-6)
00869 printf("nonzero DJ: %d %g - %g %g %g\n",
00870 colx, dj, clo[colx], csol[colx], cup[colx]);
00871 }
00872 }
00873 }
00874 }
00875 int rowx;
00876 for (rowx = 0; rowx < nrows; ++rowx) {
00877 if (rdone[rowx]) {
00878 if (rup[rowx]-rlo[rowx]>1.0e-6) {
00879 double dj = rowduals[rowx];
00880 if (rsol[rowx]<rlo[rowx]+1.0e-6) {
00881 if (dj <-1.0e-5)
00882 printf("neg rDJ: %d %g - %g %g %g\n",
00883 rowx, dj, rlo[rowx], rsol[rowx], rup[rowx]);
00884 } else if (rsol[rowx]>rup[rowx]-1.0e-6) {
00885 if (dj > 1.0e-5)
00886 printf("pos rDJ: %d %g - %g %g %g\n",
00887 rowx, dj, rlo[rowx], rsol[rowx], rup[rowx]);
00888 } else {
00889 if (fabs(dj) >1.0e-5)
00890 printf("nonzero rDJ: %d %g - %g %g %g\n",
00891 rowx, dj, rlo[rowx], rsol[rowx], rup[rowx]);
00892 }
00893 }
00894 }
00895 }
00896 delete [] rsol;
00897 }
00898 #endif
00899
00900 static inline double getTolerance(const ClpSimplex *si, ClpDblParam key)
00901 {
00902 double tol;
00903 if (! si->getDblParam(key, tol)) {
00904 CoinPresolveAction::throwCoinError("getDblParam failed",
00905 "CoinPrePostsolveMatrix::CoinPrePostsolveMatrix");
00906 }
00907 return (tol);
00908 }
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921 CoinPrePostsolveMatrix::CoinPrePostsolveMatrix(const ClpSimplex * si,
00922 int ncols_in,
00923 int nrows_in,
00924 CoinBigIndex nelems_in) :
00925 ncols_(si->getNumCols()),
00926 ncols0_(ncols_in),
00927 nelems_(si->getNumElements()),
00928
00929 mcstrt_(new CoinBigIndex[ncols_in+1]),
00930 hincol_(new int[ncols_in+1]),
00931 hrow_ (new int [2*nelems_in]),
00932 colels_(new double[2*nelems_in]),
00933
00934 cost_(new double[ncols_in]),
00935 clo_(new double[ncols_in]),
00936 cup_(new double[ncols_in]),
00937 rlo_(new double[nrows_in]),
00938 rup_(new double[nrows_in]),
00939 originalColumn_(new int[ncols_in]),
00940 originalRow_(new int[nrows_in]),
00941
00942 ztolzb_(getTolerance(si, ClpPrimalTolerance)),
00943 ztoldj_(getTolerance(si, ClpDualTolerance)),
00944
00945 maxmin_(si->getObjSense())
00946
00947 {
00948 si->getDblParam(ClpObjOffset,originalOffset_);
00949 int ncols = si->getNumCols();
00950 int nrows = si->getNumRows();
00951
00952 ClpDisjointCopyN(si->getColLower(), ncols, clo_);
00953 ClpDisjointCopyN(si->getColUpper(), ncols, cup_);
00954 ClpDisjointCopyN(si->getObjCoefficients(), ncols, cost_);
00955 ClpDisjointCopyN(si->getRowLower(), nrows, rlo_);
00956 ClpDisjointCopyN(si->getRowUpper(), nrows, rup_);
00957 int i;
00958 for (i=0;i<ncols_in;i++)
00959 originalColumn_[i]=i;
00960 for (i=0;i<nrows_in;i++)
00961 originalRow_[i]=i;
00962 sol_=NULL;
00963 rowduals_=NULL;
00964 acts_=NULL;
00965
00966 rcosts_=NULL;
00967 colstat_=NULL;
00968 rowstat_=NULL;
00969 }
00970
00971
00972
00973
00974 static bool isGapFree(const CoinPackedMatrix& matrix)
00975 {
00976 const CoinBigIndex * start = matrix.getVectorStarts();
00977 const int * length = matrix.getVectorLengths();
00978 int i;
00979 for (i = matrix.getSizeVectorLengths() - 1; i >= 0; --i) {
00980 if (start[i+1] - start[i] != length[i])
00981 break;
00982 }
00983 return (! (i >= 0));
00984 }
00985 #if DEBUG_PRESOLVE
00986 static void matrix_bounds_ok(const double *lo, const double *up, int n)
00987 {
00988 int i;
00989 for (i=0; i<n; i++) {
00990 PRESOLVEASSERT(lo[i] <= up[i]);
00991 PRESOLVEASSERT(lo[i] < PRESOLVE_INF);
00992 PRESOLVEASSERT(-PRESOLVE_INF < up[i]);
00993 }
00994 }
00995 #endif
00996 CoinPresolveMatrix::CoinPresolveMatrix(int ncols0_in,
00997 double maxmin_,
00998
00999
01000 ClpSimplex * si,
01001
01002
01003 int nrows_in,
01004 CoinBigIndex nelems_in,
01005 bool doStatus,
01006 double nonLinearValue) :
01007
01008 CoinPrePostsolveMatrix(si,
01009 ncols0_in, nrows_in, nelems_in),
01010 clink_(new presolvehlink[ncols0_in+1]),
01011 rlink_(new presolvehlink[nrows_in+1]),
01012
01013 dobias_(0.0),
01014
01015 nrows_(si->getNumRows()),
01016
01017
01018 mrstrt_(new CoinBigIndex[nrows_in+1]),
01019 hinrow_(new int[nrows_in+1]),
01020 rowels_(new double[2*nelems_in]),
01021 hcol_(new int[2*nelems_in]),
01022 integerType_(new char[ncols0_in]),
01023 feasibilityTolerance_(0.0),
01024 status_(-1),
01025 rowsToDo_(new int [nrows_in]),
01026 numberRowsToDo_(0),
01027 nextRowsToDo_(new int[nrows_in]),
01028 numberNextRowsToDo_(0),
01029 colsToDo_(new int [ncols0_in]),
01030 numberColsToDo_(0),
01031 nextColsToDo_(new int[ncols0_in]),
01032 numberNextColsToDo_(0)
01033
01034 {
01035 const int bufsize = 2*nelems_in;
01036
01037
01038 rowChanged_ = new unsigned char[nrows_];
01039 memset(rowChanged_,0,nrows_);
01040 colChanged_ = new unsigned char[ncols_];
01041 memset(colChanged_,0,ncols_);
01042 CoinPackedMatrix * m = si->matrix();
01043
01044
01045
01046
01047 const CoinBigIndex * start = m->getVectorStarts();
01048 const int * length = m->getVectorLengths();
01049 const int * row = m->getIndices();
01050 const double * element = m->getElements();
01051 int icol,nel=0;
01052 mcstrt_[0]=0;
01053 for (icol=0;icol<ncols_;icol++) {
01054 int j;
01055 for (j=start[icol];j<start[icol]+length[icol];j++) {
01056 hrow_[nel]=row[j];
01057 colels_[nel++]=element[j];
01058 }
01059 mcstrt_[icol+1]=nel;
01060 }
01061 assert(mcstrt_[ncols_] == nelems_);
01062 ClpDisjointCopyN(m->getVectorLengths(),ncols_, hincol_);
01063
01064
01065 m = new CoinPackedMatrix();
01066 m->reverseOrderedCopyOf(*si->matrix());
01067 m->removeGaps();
01068
01069
01070 ClpDisjointCopyN(m->getVectorStarts(), nrows_, mrstrt_);
01071 mrstrt_[nrows_] = nelems_;
01072 ClpDisjointCopyN(m->getVectorLengths(), nrows_, hinrow_);
01073 ClpDisjointCopyN(m->getIndices(), nelems_, hcol_);
01074 ClpDisjointCopyN(m->getElements(), nelems_, rowels_);
01075
01076 delete m;
01077 if (si->integerInformation()) {
01078 memcpy(integerType_,si->integerInformation(),ncols_*sizeof(char));
01079 } else {
01080 ClpFillN<char>(integerType_, ncols_, 0);
01081 }
01082
01083
01084 if (nonLinearValue) {
01085 anyProhibited_ = true;
01086 for (icol=0;icol<ncols_;icol++) {
01087 int j;
01088 bool nonLinearColumn = false;
01089 if (cost_[icol]==nonLinearValue)
01090 nonLinearColumn=true;
01091 for (j=mcstrt_[icol];j<mcstrt_[icol+1];j++) {
01092 if (colels_[j]==nonLinearValue) {
01093 nonLinearColumn=true;
01094 setRowProhibited(hrow_[j]);
01095 }
01096 }
01097 if (nonLinearColumn)
01098 setColProhibited(icol);
01099 }
01100 } else {
01101 anyProhibited_ = false;
01102 }
01103
01104 if (doStatus) {
01105
01106 sol_ = new double[ncols_];
01107 memcpy(sol_,si->primalColumnSolution(),ncols_*sizeof(double));;
01108 acts_ = new double [nrows_];
01109 memcpy(acts_,si->primalRowSolution(),nrows_*sizeof(double));
01110 if (!si->statusArray())
01111 si->createStatus();
01112 colstat_ = new unsigned char [nrows_+ncols_];
01113 memcpy(colstat_,si->statusArray(),
01114 (nrows_+ncols_)*sizeof(unsigned char));
01115 rowstat_ = colstat_+ncols_;
01116 }
01117
01118
01119
01120 si->resize(0,0);
01121
01122 #if DEBUG_PRESOLVE
01123 matrix_bounds_ok(rlo_, rup_, nrows_);
01124 matrix_bounds_ok(clo_, cup_, ncols_);
01125 #endif
01126
01127 #if 0
01128 for (i=0; i<nrows; ++i)
01129 printf("NR: %6d\n", hinrow[i]);
01130 for (int i=0; i<ncols; ++i)
01131 printf("NC: %6d\n", hincol[i]);
01132 #endif
01133
01134 presolve_make_memlists(mcstrt_, hincol_, clink_, ncols_);
01135 presolve_make_memlists(mrstrt_, hinrow_, rlink_, nrows_);
01136
01137
01138
01139 mcstrt_[ncols_] = bufsize-1;
01140 mrstrt_[nrows_] = bufsize-1;
01141
01142 #if CHECK_CONSISTENCY
01143 consistent(false);
01144 #endif
01145 }
01146
01147 void CoinPresolveMatrix::update_model(ClpSimplex * si,
01148 int nrows0,
01149 int ncols0,
01150 CoinBigIndex nelems0)
01151 {
01152 si->loadProblem(ncols_, nrows_, mcstrt_, hrow_, colels_, hincol_,
01153 clo_, cup_, cost_, rlo_, rup_);
01154
01155 delete [] si->integerInformation();
01156 int numberIntegers=0;
01157 for (int i=0; i<ncols_; i++) {
01158 if (integerType_[i])
01159 numberIntegers++;
01160 }
01161 if (numberIntegers)
01162 si->copyInIntegerInformation(integerType_);
01163 else
01164 si->copyInIntegerInformation(NULL);
01165
01166 #if PRESOLVE_SUMMARY
01167 printf("NEW NCOL/NROW/NELS: %d(-%d) %d(-%d) %d(-%d)\n",
01168 ncols_, ncols0-ncols_,
01169 nrows_, nrows0-nrows_,
01170 si->getNumElements(), nelems0-si->getNumElements());
01171 #endif
01172 si->setDblParam(ClpObjOffset,originalOffset_-dobias_);
01173
01174 }
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01187
01188 CoinPostsolveMatrix::CoinPostsolveMatrix(ClpSimplex* si,
01189 int ncols0_in,
01190 int nrows0_in,
01191 CoinBigIndex nelems0,
01192
01193 double maxmin_,
01194
01195
01196 double *sol_in,
01197 double *acts_in,
01198
01199 unsigned char *colstat_in,
01200 unsigned char *rowstat_in) :
01201 CoinPrePostsolveMatrix(si,
01202 ncols0_in, nrows0_in, nelems0),
01203
01204 free_list_(0),
01205
01206 maxlink_(2*nelems0),
01207 link_(new int[ 2*nelems0]),
01208
01209 cdone_(new char[ncols0_]),
01210 rdone_(new char[nrows0_in]),
01211
01212 nrows_(si->getNumRows()),
01213 nrows0_(nrows0_in)
01214 {
01215
01216 sol_=sol_in;
01217 rowduals_=NULL;
01218 acts_=acts_in;
01219
01220 rcosts_=NULL;
01221 colstat_=colstat_in;
01222 rowstat_=rowstat_in;
01223
01224
01225 int ncols1 = si->getNumCols();
01226 int nrows1 = si->getNumRows();
01227
01228 const CoinPackedMatrix * m = si->matrix();
01229
01230 if (! isGapFree(*m)) {
01231 CoinPresolveAction::throwCoinError("Matrix not gap free",
01232 "CoinPostsolveMatrix");
01233 }
01234
01235 const CoinBigIndex nelemsr = m->getNumElements();
01236
01237 ClpDisjointCopyN(m->getVectorStarts(), ncols1, mcstrt_);
01238 mcstrt_[ncols_] = nelems0;
01239 ClpDisjointCopyN(m->getVectorLengths(),ncols1, hincol_);
01240 ClpDisjointCopyN(m->getIndices(), nelemsr, hrow_);
01241 ClpDisjointCopyN(m->getElements(), nelemsr, colels_);
01242
01243
01244 #if 0 && DEBUG_PRESOLVE
01245 presolve_check_costs(model, &colcopy);
01246 #endif
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262 memset(cdone_, -1, ncols0_);
01263 memset(rdone_, -1, nrows0_);
01264
01265 rowduals_ = new double[nrows0_];
01266 ClpDisjointCopyN(si->getRowPrice(), nrows1, rowduals_);
01267
01268 rcosts_ = new double[ncols0_];
01269 ClpDisjointCopyN(si->getReducedCost(), ncols1, rcosts_);
01270 if (maxmin_<0.0) {
01271
01272 int i;
01273 for (i=0;i<nrows1;i++)
01274 rowduals_[i] = - rowduals_[i];
01275 for (i=0;i<ncols1;i++) {
01276 rcosts_[i] = - rcosts_[i];
01277 }
01278 }
01279
01280
01281
01282
01283 ClpDisjointCopyN(si->getColSolution(), ncols1, sol_);
01284 si->setDblParam(ClpObjOffset,originalOffset_);
01285
01286 for (int j=0; j<ncols1; j++) {
01287 CoinBigIndex kcs = mcstrt_[j];
01288 CoinBigIndex kce = kcs + hincol_[j];
01289 for (CoinBigIndex k=kcs; k<kce; ++k) {
01290 link_[k] = k+1;
01291 }
01292 }
01293 {
01294 int ml = maxlink_;
01295 for (CoinBigIndex k=nelemsr; k<ml; ++k)
01296 link_[k] = k+1;
01297 link_[ml-1] = NO_LINK;
01298 }
01299 free_list_ = nelemsr;
01300 }
01301
01302 ClpSimplex *
01303 ClpPresolve::gutsOfPresolvedModel(ClpSimplex * originalModel,
01304 double feasibilityTolerance,
01305 bool keepIntegers,
01306 int numberPasses,
01307 bool dropNames)
01308 {
01309 ncols_ = originalModel->getNumCols();
01310 nrows_ = originalModel->getNumRows();
01311 nelems_ = originalModel->getNumElements();
01312 numberPasses_ = numberPasses;
01313
01314 double maxmin = originalModel->getObjSense();
01315 originalModel_ = originalModel;
01316 delete [] originalColumn_;
01317 originalColumn_ = new int[ncols_];
01318 delete [] originalRow_;
01319 originalRow_ = new int[nrows_];
01320
01321
01322 int result = -1;
01323
01324
01325 presolvedModel_=NULL;
01326
01327 CoinMessages messages = CoinMessage(originalModel->messages().language());
01328 while (result==-1) {
01329
01330
01331 if (saveFile_=="") {
01332 delete presolvedModel_;
01333 presolvedModel_ = new ClpSimplex(*originalModel);
01334 } else {
01335 presolvedModel_=originalModel;
01336 }
01337 presolvedModel_->dropNames();
01338
01339
01340 if (!keepIntegers)
01341 presolvedModel_->deleteIntegerInformation();
01342
01343
01344 CoinPresolveMatrix prob(ncols_,
01345 maxmin,
01346 presolvedModel_,
01347 nrows_, nelems_,true,nonLinearValue_);
01348
01349 {
01350 double *colels = prob.colels_;
01351 int *hrow = prob.hrow_;
01352 CoinBigIndex *mcstrt = prob.mcstrt_;
01353 int *hincol = prob.hincol_;
01354 int ncols = prob.ncols_;
01355
01356
01357 double * csol = prob.sol_;
01358 double * acts = prob.acts_;
01359 int nrows = prob.nrows_;
01360
01361 int colx;
01362
01363 memset(acts,0,nrows*sizeof(double));
01364
01365 for (colx = 0; colx < ncols; ++colx) {
01366 double solutionValue = csol[colx];
01367 for (int i=mcstrt[colx]; i<mcstrt[colx]+hincol[colx]; ++i) {
01368 int row = hrow[i];
01369 double coeff = colels[i];
01370 acts[row] += solutionValue*coeff;
01371 }
01372 }
01373 }
01374 prob.handler_ = presolvedModel_->messageHandler();
01375 prob.messages_ = CoinMessage(presolvedModel_->messages().language());
01376
01377
01378 prob.feasibilityTolerance_ = feasibilityTolerance;
01379
01380
01381
01382 paction_ = presolve(&prob);
01383
01384 result =0;
01385
01386 if (prob.status_==0&&paction_) {
01387
01388 int n = prob.ncols_;
01389 double * lo = prob.clo_;
01390 double * up = prob.cup_;
01391 int i;
01392
01393 for (i=0;i<n;i++) {
01394 if (up[i]<lo[i]) {
01395 if (up[i]<lo[i]-1.0e-8) {
01396
01397 prob.status_=1;
01398 } else {
01399 up[i]=lo[i];
01400 }
01401 }
01402 }
01403
01404 n = prob.nrows_;
01405 lo = prob.rlo_;
01406 up = prob.rup_;
01407
01408 for (i=0;i<n;i++) {
01409 if (up[i]<lo[i]) {
01410 if (up[i]<lo[i]-1.0e-8) {
01411
01412 prob.status_=1;
01413 } else {
01414 up[i]=lo[i];
01415 }
01416 }
01417 }
01418 }
01419 if (prob.status_==0&&paction_) {
01420
01421
01422 prob.update_model(presolvedModel_, nrows_, ncols_, nelems_);
01423
01424 memcpy(presolvedModel_->primalColumnSolution(),
01425 prob.sol_,prob.ncols_*sizeof(double));
01426 memcpy(presolvedModel_->primalRowSolution(),
01427 prob.acts_,prob.nrows_*sizeof(double));
01428 memcpy(presolvedModel_->statusArray(),
01429 prob.colstat_,prob.ncols_*sizeof(unsigned char));
01430 memcpy(presolvedModel_->statusArray()+prob.ncols_,
01431 prob.rowstat_,prob.nrows_*sizeof(unsigned char));
01432 delete [] prob.sol_;
01433 delete [] prob.acts_;
01434 delete [] prob.colstat_;
01435 prob.sol_=NULL;
01436 prob.acts_=NULL;
01437 prob.colstat_=NULL;
01438
01439 int ncolsNow = presolvedModel_->getNumCols();
01440 memcpy(originalColumn_,prob.originalColumn_,ncolsNow*sizeof(int));
01441 delete [] prob.originalColumn_;
01442 prob.originalColumn_=NULL;
01443 int nrowsNow = presolvedModel_->getNumRows();
01444 memcpy(originalRow_,prob.originalRow_,nrowsNow*sizeof(int));
01445 delete [] prob.originalRow_;
01446 prob.originalRow_=NULL;
01447 if (!dropNames&&originalModel->lengthNames()) {
01448
01449 int iRow;
01450 std::vector<std::string> rowNames;
01451 rowNames.reserve(nrowsNow);
01452 for (iRow=0;iRow<nrowsNow;iRow++) {
01453 int kRow = originalRow_[iRow];
01454 rowNames.push_back(originalModel->rowName(kRow));
01455 }
01456
01457 int iColumn;
01458 std::vector<std::string> columnNames;
01459 columnNames.reserve(ncolsNow);
01460 for (iColumn=0;iColumn<ncolsNow;iColumn++) {
01461 int kColumn = originalColumn_[iColumn];
01462 columnNames.push_back(originalModel->columnName(kColumn));
01463 }
01464 presolvedModel_->copyNames(rowNames,columnNames);
01465 }
01466
01467 int i;
01468 const char * information = presolvedModel_->integerInformation();
01469 if (information) {
01470 int numberChanges=0;
01471 double * lower0 = originalModel_->columnLower();
01472 double * upper0 = originalModel_->columnUpper();
01473 double * lower = presolvedModel_->columnLower();
01474 double * upper = presolvedModel_->columnUpper();
01475 for (i=0;i<ncolsNow;i++) {
01476 if (!information[i])
01477 continue;
01478 int iOriginal = originalColumn_[i];
01479 double lowerValue0 = lower0[iOriginal];
01480 double upperValue0 = upper0[iOriginal];
01481 double lowerValue = ceil(lower[i]-1.0e-5);
01482 double upperValue = floor(upper[i]+1.0e-5);
01483 lower[i]=lowerValue;
01484 upper[i]=upperValue;
01485 if (lowerValue>upperValue) {
01486 numberChanges++;
01487 presolvedModel_->messageHandler()->message(COIN_PRESOLVE_COLINFEAS,
01488 messages)
01489 <<iOriginal
01490 <<lowerValue
01491 <<upperValue
01492 <<CoinMessageEol;
01493 result=1;
01494 } else {
01495 if (lowerValue>lowerValue0+1.0e-8) {
01496 lower0[iOriginal] = lowerValue;
01497 numberChanges++;
01498 }
01499 if (upperValue<upperValue0-1.0e-8) {
01500 upper0[iOriginal] = upperValue;
01501 numberChanges++;
01502 }
01503 }
01504 }
01505 if (numberChanges) {
01506 presolvedModel_->messageHandler()->message(COIN_PRESOLVE_INTEGERMODS,
01507 messages)
01508 <<numberChanges
01509 <<CoinMessageEol;
01510 if (!result) {
01511 result = -1;
01512 }
01513 }
01514 }
01515 } else {
01516
01517 delete [] prob.sol_;
01518 delete [] prob.acts_;
01519 delete [] prob.colstat_;
01520 result=1;
01521 }
01522 }
01523 if (!result) {
01524 int nrowsAfter = presolvedModel_->getNumRows();
01525 int ncolsAfter = presolvedModel_->getNumCols();
01526 CoinBigIndex nelsAfter = presolvedModel_->getNumElements();
01527 presolvedModel_->messageHandler()->message(COIN_PRESOLVE_STATS,
01528 messages)
01529 <<nrowsAfter<< -(nrows_ - nrowsAfter)
01530 << ncolsAfter<< -(ncols_ - ncolsAfter)
01531 <<nelsAfter<< -(nelems_ - nelsAfter)
01532 <<CoinMessageEol;
01533 } else {
01534 gutsOfDestroy();
01535 delete presolvedModel_;
01536 presolvedModel_=NULL;
01537 }
01538 return presolvedModel_;
01539 }
01540
01541