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

ClpPresolve.cpp

00001 // Copyright (C) 2002, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 //#define       CHECK_CONSISTENCY       1
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 // Gets rid of presolve actions (e.g.when infeasible)
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 /* This version of presolve returns a pointer to a new presolved 
00075    model.  NULL if infeasible
00076 */
00077 ClpSimplex * 
00078 ClpPresolve::presolvedModel(ClpSimplex & si,
00079                          double feasibilityTolerance,
00080                          bool keepIntegers,
00081                          int numberPasses,
00082                          bool dropNames)
00083 {
00084   // Check matrix
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 /* This version of presolve updates
00092    model and saves original data to file.  Returns non-zero if infeasible
00093 */
00094 int
00095 ClpPresolve::presolvedModelToFile(ClpSimplex &si,std::string fileName,
00096                             double feasibilityTolerance,
00097                             bool keepIntegers,
00098                             int numberPasses)
00099 {
00100   // Check matrix
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 // Return pointer to presolved model
00116 ClpSimplex * 
00117 ClpPresolve::model() const
00118 {
00119   return presolvedModel_;
00120 }
00121 // Return pointer to original model
00122 ClpSimplex * 
00123 ClpPresolve::originalModel() const
00124 {
00125   return originalModel_;
00126 }
00127 void 
00128 ClpPresolve::postsolve(bool updateStatus)
00129 {
00130   // Messages
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   // this is the size of the original problem
00139   const int ncols0  = ncols_;
00140   const int nrows0  = nrows_;
00141   const CoinBigIndex nelems0 = nelems_;
00142   
00143   // this is the reduced problem
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     // reality check
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     // from file
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                        // end prepost
00184                        
00185                        sol, acts,
00186                        colstat, rowstat);
00187     
00188   postsolve(prob);
00189 
00190   if (saveFile_!="") {
00191     // From file
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   // put back duals
00204   memcpy(originalModel_->dualRowSolution(),prob.rowduals_,
00205          nrows_*sizeof(double));
00206   double maxmin = originalModel_->getObjSense();
00207   if (maxmin<0.0) {
00208     // swap signs
00209     int i;
00210     double * pi = originalModel_->dualRowSolution();
00211     for (i=0;i<nrows_;i++)
00212       pi[i] = -pi[i];
00213   }
00214   // Now check solution
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   // Messages
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   //originalModel_->objectiveValue_=objectiveValue_;
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 // return pointer to original columns
00254 const int * 
00255 ClpPresolve::originalColumns() const
00256 {
00257   return originalColumn_;
00258 }
00259 // return pointer to original rows
00260 const int * 
00261 ClpPresolve::originalRows() const
00262 {
00263   return originalRow_;
00264 }
00265 // Set pointer to original model
00266 void 
00267 ClpPresolve::setOriginalModel(ClpSimplex * model)
00268 {
00269   originalModel_=model;
00270 }
00271 #if 0
00272 // A lazy way to restrict which transformations are applied
00273 // during debugging.
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 //#define DEBUG_PRESOLVE 1
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 // This is the presolve loop.
00357 // It is a separate virtual function so that it can be easily
00358 // customized by subclassing CoinPresolve.
00359 const CoinPresolveAction *ClpPresolve::presolve(CoinPresolveMatrix *prob)
00360 {
00361   // Messages
00362   CoinMessages messages = CoinMessage(prob->messages().language());
00363   paction_ = 0;
00364 
00365   prob->status_=0; // say feasible
00366 
00367   paction_ = make_fixed(prob, paction_);
00368   // if integers then switch off dual stuff
00369   // later just do individually
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     //const bool forcing = ATOI("FORCING")!=0;
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     // normal
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     // some things are expensive so just do once (normally)
00413 
00414     int i;
00415     // say look at all
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       // some stuff must be left alone
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     // Check number rows dropped
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       // look for substitutions with no fill
00450       int fill_level=2;
00451       //fill_level=10;
00452       //printf("** fill_level == 10 !\n");
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           // this can also make E rows so do one bit here
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         // set up for next pass
00522         // later do faster if many changes i.e. memset and memcpy
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       // say look at all
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         // some stuff must be left alone
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       // now expensive things
00580       // this caused world.mps to run into numerical difficulties
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; // switches off substitution
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         //printf("%d rows dropped after pass %d\n",numberDropped,
00634         //     iLoop+1);
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     // get rid of data
00673     gutsOfDestroy();
00674   }
00675   return (paction_);
00676 }
00677 
00678 void check_djs(CoinPostsolveMatrix *prob);
00679 
00680 
00681 // We could have implemented this by having each postsolve routine
00682 // directly call the next one, but this may make it easier to add debugging checks.
00683 void ClpPresolve::postsolve(CoinPostsolveMatrix &prob)
00684 {
00685   {
00686     // Check activities
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   // debug check:  make sure we ended up with same original matrix
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   //return;
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 // Assumptions:
00912 // 1. nrows>=m.getNumRows()
00913 // 2. ncols>=m.getNumCols()
00914 //
00915 // In presolve, these values are equal.
00916 // In postsolve, they may be inequal, since the reduced problem
00917 // may be smaller, but we need room for the large problem.
00918 // ncols may be larger than si.getNumCols() in postsolve,
00919 // this at that point si will be the reduced problem,
00920 // but we need to reserve enough space for the original problem.
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 // I am not familiar enough with CoinPackedMatrix to be confident
00972 // that I will implement a row-ordered version of toColumnOrderedGapFree
00973 // properly.
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                                      // end prepost members
00999 
01000                                      ClpSimplex * si,
01001 
01002                                      // rowrep
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   // temporary init
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   // Set up change bits etc
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   // The coefficient matrix is a big hunk of stuff.
01045   // Do the copy here to try to avoid running out of memory.
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   // same thing for row rep
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   // Set up prohibited bits if needed
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     // allow for status and solution
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   // the original model's fields are now unneeded - free them
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   // this allows last col/row to expand up to bufsize-1 (22);
01138   // this must come after the calls to presolve_prefix
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                                        // end prepost members
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   // link, free_list, maxlink
01206   maxlink_(2*nelems0),
01207   link_(new int[/*maxlink*/ 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   // this is the *reduced* model, which is probably smaller
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   // This determines the size of the data structure that contains
01249   // the matrix being postsolved.  Links are taken from the free_list
01250   // to recreate matrix entries that were presolved away,
01251   // and links are added to the free_list when entries created during
01252   // presolve are discarded.  There is never a need to gc this list.
01253   // Naturally, it should contain
01254   // exactly nelems0 entries "in use" when postsolving is done,
01255   // but I don't know whether the matrix could temporarily get
01256   // larger during postsolving.  Substitution into more than two
01257   // rows could do that, in principle.  I am being very conservative
01258   // here by reserving much more than the amount of space I probably need.
01259   // If this guess is wrong, check_free_list may be called.
01260   //  int bufsize = 2*nelems0;
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     // change so will look as if minimize
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   //ClpDisjointCopyN(si->getRowUpper(), nrows1, rup_);
01281   //ClpDisjointCopyN(si->getRowLower(), nrows1, rlo_);
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 /* This is main part of Presolve */
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   // result is 0 - okay, 1 infeasible, -1 go round again
01322   int result = -1;
01323   
01324   // User may have deleted - its their responsibility
01325   presolvedModel_=NULL;
01326   // Messages
01327   CoinMessages messages = CoinMessage(originalModel->messages().language());
01328   while (result==-1) {
01329 
01330     // make new copy
01331     if (saveFile_=="") {
01332       delete presolvedModel_;
01333       presolvedModel_ = new ClpSimplex(*originalModel);
01334     } else {
01335       presolvedModel_=originalModel;
01336     }
01337     presolvedModel_->dropNames();
01338 
01339     // drop integer information if wanted
01340     if (!keepIntegers)
01341       presolvedModel_->deleteIntegerInformation();
01342 
01343     
01344     CoinPresolveMatrix prob(ncols_,
01345                         maxmin,
01346                         presolvedModel_,
01347                         nrows_, nelems_,true,nonLinearValue_);
01348     // make sure row solution correct
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     // move across feasibility tolerance
01378     prob.feasibilityTolerance_ = feasibilityTolerance;
01379 
01380     // Do presolve
01381 
01382     paction_ = presolve(&prob);
01383 
01384     result =0; 
01385 
01386     if (prob.status_==0&&paction_) {
01387       // Looks feasible but double check to see if anything slipped through
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             // infeasible
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             // infeasible
01412             prob.status_=1;
01413           } else {
01414             up[i]=lo[i];
01415           }
01416         }
01417       }
01418     }
01419     if (prob.status_==0&&paction_) {
01420       // feasible
01421     
01422       prob.update_model(presolvedModel_, nrows_, ncols_, nelems_);
01423       // copy status and solution
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         // Redo names
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       // now clean up integer variables.  This can modify original
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; // round again
01512           }
01513         }
01514       }
01515     } else {
01516       // infeasible
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 

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