00001
00002
00003
00004 #include "CoinPragma.hpp"
00005 #include "ClpFactorization.hpp"
00006 #include "ClpQuadraticObjective.hpp"
00007 #include "CoinHelperFunctions.hpp"
00008 #include "CoinIndexedVector.hpp"
00009 #include "ClpSimplex.hpp"
00010 #include "ClpMatrixBase.hpp"
00011 #include "ClpNetworkBasis.hpp"
00012 #include "ClpNetworkMatrix.hpp"
00013
00014 #ifdef CHECK_NETWORK
00015 const static bool doCheck=true;
00016 #else
00017 const static bool doCheck=false;
00018 #endif
00019
00020
00021
00022
00023
00024
00025
00026
00027 ClpFactorization::ClpFactorization () :
00028 CoinFactorization()
00029 {
00030 networkBasis_ = NULL;
00031 }
00032
00033
00034
00035
00036 ClpFactorization::ClpFactorization (const ClpFactorization & rhs) :
00037 CoinFactorization(rhs)
00038 {
00039 if (rhs.networkBasis_)
00040 networkBasis_ = new ClpNetworkBasis(*(rhs.networkBasis_));
00041 else
00042 networkBasis_=NULL;
00043 }
00044
00045 ClpFactorization::ClpFactorization (const CoinFactorization & rhs) :
00046 CoinFactorization(rhs)
00047 {
00048 networkBasis_=NULL;
00049 }
00050
00051
00052
00053
00054 ClpFactorization::~ClpFactorization ()
00055 {
00056 delete networkBasis_;
00057 }
00058
00059
00060
00061
00062 ClpFactorization &
00063 ClpFactorization::operator=(const ClpFactorization& rhs)
00064 {
00065 if (this != &rhs) {
00066 CoinFactorization::operator=(rhs);
00067 delete networkBasis_;
00068 if (rhs.networkBasis_)
00069 networkBasis_ = new ClpNetworkBasis(*(rhs.networkBasis_));
00070 else
00071 networkBasis_=NULL;
00072 }
00073 return *this;
00074 }
00075 int
00076 ClpFactorization::factorize ( ClpSimplex * model,
00077 int solveType, bool valuesPass)
00078 {
00079 const ClpMatrixBase * matrix = model->clpMatrix();
00080 int numberRows = model->numberRows();
00081 int numberColumns = model->numberColumns();
00082
00083 if (numberPivots_>1&&numberCompressions_*10 > numberPivots_+10) {
00084 areaFactor_ *= 1.1;
00085 }
00086 if (!networkBasis_||doCheck) {
00087 status_=-99;
00088 int * pivotVariable = model->pivotVariable();
00089
00090 while (status_<-98) {
00091
00092 int i;
00093 int numberBasic=0;
00094 int numberRowBasic;
00095 for (i=0;i<numberRows;i++) {
00096 if (model->getRowStatus(i) == ClpSimplex::basic)
00097 pivotVariable[numberBasic++]=i;
00098 }
00099 numberRowBasic=numberBasic;
00100 for (i=0;i<numberColumns;i++) {
00101 if (model->getColumnStatus(i) == ClpSimplex::basic)
00102 pivotVariable[numberBasic++]=i;
00103 }
00104 assert (numberBasic<=numberRows);
00105
00106 ClpNetworkMatrix* networkMatrix =
00107 dynamic_cast< ClpNetworkMatrix*>(model->clpMatrix());
00108
00109 int saveMaximumPivots = maximumPivots();
00110 delete networkBasis_;
00111 networkBasis_ = NULL;
00112 if (networkMatrix&&!doCheck)
00113 maximumPivots(1);
00114 while (status_==-99) {
00115
00116 gutsOfDestructor();
00117 gutsOfInitialize(2);
00118 CoinBigIndex numberElements=numberRowBasic;
00119
00120
00121
00122 int i;
00123
00124 numberElements +=matrix->fillBasis(model,
00125 pivotVariable+numberRowBasic,
00126 numberRowBasic,
00127 numberBasic-numberRowBasic,
00128 NULL,NULL,NULL);
00129
00130 numberElements = 3 * numberBasic + 3 * numberElements + 10000;
00131 getAreas ( numberRows, numberBasic, numberElements,
00132 2 * numberElements );
00133
00134
00135 numberElements=numberRowBasic;
00136 for (i=0;i<numberRowBasic;i++) {
00137 int iRow = pivotVariable[i];
00138 indexRowU_[i]=iRow;
00139 indexColumnU_[i]=i;
00140 elementU_[i]=slackValue_;
00141 }
00142 numberElements +=matrix->fillBasis(model,
00143 pivotVariable+numberRowBasic,
00144 numberRowBasic,
00145 numberBasic-numberRowBasic,
00146 indexRowU_+numberElements,
00147 indexColumnU_+numberElements,
00148 elementU_+numberElements);
00149 lengthU_ = numberElements;
00150
00151 preProcess ( 0 );
00152 factor ( );
00153 if (status_==-99) {
00154
00155 areaFactor(2.0*areaFactor());
00156 }
00157 }
00158
00159 if (status_ == 0) {
00160 int * permuteBack = permuteBack_;
00161 int * back = pivotColumnBack_;
00162 int * pivotTemp = pivotColumn_;
00163 ClpDisjointCopyN ( pivotVariable, numberRows_ , pivotTemp );
00164
00165 for (i=0;i<numberRowBasic;i++) {
00166 int k = pivotTemp[i];
00167
00168 pivotVariable[permuteBack[back[i]]]=k+numberColumns;
00169 }
00170 for (;i<numberRows;i++) {
00171 int k = pivotTemp[i];
00172
00173 pivotVariable[permuteBack[back[i]]]=k;
00174 }
00175
00176
00177
00178 ClpDisjointCopyN ( permute_, numberRows_ , pivotColumn_ );
00179 ClpDisjointCopyN ( permuteBack_, numberRows_ , pivotColumnBack_ );
00180 if (networkMatrix) {
00181 maximumPivots(saveMaximumPivots);
00182
00183 if (doCheck)
00184 delete networkBasis_;
00185 networkBasis_ = new ClpNetworkBasis(model,numberRows_,
00186 pivotRegion_,
00187 permuteBack_,
00188 startColumnU_,
00189 numberInColumn_,
00190 indexRowU_,
00191 elementU_);
00192
00193 if (!doCheck) {
00194 gutsOfDestructor();
00195 #if 0
00196
00197 int numberRows = model->numberRows();
00198 pivotColumnBack_ = new int [numberRows];
00199 permute_ = new int [numberRows];
00200 int i;
00201 for (i=0;i<numberRows;i++) {
00202 pivotColumnBack_[i]=i;
00203 permute_[i]=i;
00204 }
00205 #endif
00206 }
00207 } else {
00208
00209 if (numberFtranCounts_>100) {
00210 ftranAverageAfterL_ = max(ftranCountAfterL_/ftranCountInput_,1.0);
00211 ftranAverageAfterR_ = max(ftranCountAfterR_/ftranCountAfterL_,1.0);
00212 ftranAverageAfterU_ = max(ftranCountAfterU_/ftranCountAfterR_,1.0);
00213 assert (ftranCountInput_&&ftranCountAfterL_&&ftranCountAfterR_);
00214 if (btranCountInput_&&btranCountAfterU_&&btranCountAfterR_) {
00215 btranAverageAfterU_ = max(btranCountAfterU_/btranCountInput_,1.0);
00216 btranAverageAfterR_ = max(btranCountAfterR_/btranCountAfterU_,1.0);
00217 btranAverageAfterL_ = max(btranCountAfterL_/btranCountAfterR_,1.0);
00218 } else {
00219
00220 btranAverageAfterU_ = 1.0;
00221 btranAverageAfterR_ = 1.0;
00222 btranAverageAfterL_ = 1.0;
00223 }
00224 }
00225
00226
00227 ftranCountInput_ *= 0.8;
00228 ftranCountAfterL_ *= 0.8;
00229 ftranCountAfterR_ *= 0.8;
00230 ftranCountAfterU_ *= 0.8;
00231 btranCountInput_ *= 0.8;
00232 btranCountAfterU_ *= 0.8;
00233 btranCountAfterR_ *= 0.8;
00234 btranCountAfterL_ *= 0.8;
00235 }
00236 } else if (status_ == -1&&(solveType==0||solveType==2)) {
00237
00238 int numberTotal = numberRows+numberColumns;
00239 int * isBasic = new int [numberTotal];
00240 int * rowIsBasic = isBasic+numberColumns;
00241 int * columnIsBasic = isBasic;
00242 for (i=0;i<numberTotal;i++)
00243 isBasic[i]=-1;
00244 for (i=0;i<numberRowBasic;i++) {
00245 int iRow = pivotVariable[i];
00246 rowIsBasic[iRow]=1;
00247 }
00248 for (;i<numberBasic;i++) {
00249 int iColumn = pivotVariable[i];
00250 columnIsBasic[iColumn]=1;
00251 }
00252 numberBasic=0;
00253 for (i=0;i<numberRows;i++)
00254 pivotVariable[i]=-1;
00255
00256 for (i=0;i<numberRows;i++) {
00257 if (rowIsBasic[i]>=0) {
00258 if (pivotColumn_[numberBasic]>=0)
00259 rowIsBasic[i]=pivotColumn_[numberBasic];
00260 else
00261 rowIsBasic[i]=-1;
00262 numberBasic++;
00263 }
00264 }
00265 for (i=0;i<numberColumns;i++) {
00266 if (columnIsBasic[i]>=0) {
00267 if (pivotColumn_[numberBasic]>=0)
00268 columnIsBasic[i]=pivotColumn_[numberBasic];
00269 else
00270 columnIsBasic[i]=-1;
00271 numberBasic++;
00272 }
00273 }
00274
00275 int * pivotVariable = model->pivotVariable();
00276 for (i=0;i<numberRows;i++) {
00277 pivotVariable[i]=-1;
00278 }
00279 for (i=0;i<numberRows;i++) {
00280 if (model->getRowStatus(i) == ClpSimplex::basic) {
00281 int iPivot = rowIsBasic[i];
00282 if (iPivot>=0)
00283 pivotVariable[iPivot]=i+numberColumns;
00284 }
00285 }
00286 for (i=0;i<numberColumns;i++) {
00287 if (model->getColumnStatus(i) == ClpSimplex::basic) {
00288 int iPivot = columnIsBasic[i];
00289 if (iPivot>=0)
00290 pivotVariable[iPivot]=i;
00291 }
00292 }
00293 delete [] isBasic;
00294 double * columnLower = model->lowerRegion();
00295 double * columnUpper = model->upperRegion();
00296 double * columnActivity = model->solutionRegion();
00297 double * rowLower = model->lowerRegion(0);
00298 double * rowUpper = model->upperRegion(0);
00299 double * rowActivity = model->solutionRegion(0);
00300
00301 int iColumn;
00302 double largeValue = model->largeValue();
00303 for (iColumn=0;iColumn<numberColumns;iColumn++) {
00304 if (model->getColumnStatus(iColumn)==ClpSimplex::basic) {
00305
00306 if (!valuesPass) {
00307 double lower=columnLower[iColumn];
00308 double upper=columnUpper[iColumn];
00309 double value=columnActivity[iColumn];
00310 if (lower>-largeValue||upper<largeValue) {
00311 if (fabs(value-lower)<fabs(value-upper)) {
00312 model->setColumnStatus(iColumn,ClpSimplex::atLowerBound);
00313 columnActivity[iColumn]=lower;
00314 } else {
00315 model->setColumnStatus(iColumn,ClpSimplex::atUpperBound);
00316 columnActivity[iColumn]=upper;
00317 }
00318 } else {
00319 model->setColumnStatus(iColumn,ClpSimplex::isFree);
00320 }
00321 } else {
00322 model->setColumnStatus(iColumn,ClpSimplex::superBasic);
00323 }
00324 }
00325 }
00326 int iRow;
00327 for (iRow=0;iRow<numberRows;iRow++) {
00328 int iSequence=pivotVariable[iRow];
00329 if (iSequence>=0) {
00330
00331 if (iSequence>=numberColumns) {
00332
00333
00334 } else {
00335
00336 model->setColumnStatus(iSequence,ClpSimplex::basic);
00337 }
00338 } else {
00339
00340 model->setRowStatus(iRow,ClpSimplex::basic);
00341 }
00342 }
00343
00344 status_=-99;
00345
00346 for (iRow=0;iRow<numberRows;iRow++) {
00347 if (model->getRowStatus(iRow)!=ClpSimplex::basic ) {
00348 if (rowLower[iRow]==rowUpper[iRow]) {
00349 rowActivity[iRow]=rowLower[iRow];
00350 model->setRowStatus(iRow,ClpSimplex::isFixed);
00351 }
00352 }
00353 }
00354 for (iColumn=0;iColumn<numberColumns;iColumn++) {
00355 if (model->getColumnStatus(iColumn)!=ClpSimplex::basic ) {
00356 if (columnLower[iColumn]==columnUpper[iColumn]) {
00357 columnActivity[iColumn]=columnLower[iColumn];
00358 model->setColumnStatus(iColumn,ClpSimplex::isFixed);
00359 }
00360 }
00361 }
00362 }
00363 }
00364 } else {
00365
00366 status_=0;
00367 }
00368
00369 if (!status_) {
00370
00371 if (model->algorithm()==2) {
00372 ClpObjective * obj = model->objectiveAsObject();
00373 ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(obj));
00374 assert (quadraticObj);
00375 CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective();
00376 int numberXColumns = quadratic->getNumCols();
00377 assert (numberXColumns<numberColumns);
00378 int base = numberColumns-numberXColumns;
00379 int * which = new int [numberXColumns];
00380 int * pivotVariable = model->pivotVariable();
00381 int * permute = pivotColumn();
00382 int i;
00383 int n=0;
00384 for (i=0;i<numberRows;i++) {
00385 int iSj = pivotVariable[i]-base;
00386 if (iSj>=0&&iSj<numberXColumns)
00387 which[n++]=permute[i];
00388 }
00389 if (n)
00390 emptyRows(n,which);
00391 delete [] which;
00392 }
00393 }
00394 return status_;
00395 }
00396
00397
00398
00399
00400
00401
00402
00403 int
00404 ClpFactorization::replaceColumn ( CoinIndexedVector * regionSparse,
00405 int pivotRow,
00406 double pivotCheck ,
00407 bool checkBeforeModifying)
00408 {
00409 if (!networkBasis_) {
00410 return CoinFactorization::replaceColumn(regionSparse,
00411 pivotRow,
00412 pivotCheck,
00413 checkBeforeModifying);
00414 } else {
00415 if (doCheck) {
00416 int returnCode = CoinFactorization::replaceColumn(regionSparse,
00417 pivotRow,
00418 pivotCheck,
00419 checkBeforeModifying);
00420 networkBasis_->replaceColumn(regionSparse,
00421 pivotRow);
00422 return returnCode;
00423 } else {
00424
00425 numberPivots_++;
00426 return networkBasis_->replaceColumn(regionSparse,
00427 pivotRow);
00428 }
00429 }
00430 }
00431
00432
00433
00434
00435 int
00436 ClpFactorization::updateColumnFT ( CoinIndexedVector * regionSparse,
00437 CoinIndexedVector * regionSparse2)
00438 {
00439 #ifdef CLP_DEBUG
00440 regionSparse->checkClear();
00441 #endif
00442 if (!networkBasis_) {
00443 collectStatistics_ = true;
00444 int returnValue= CoinFactorization::updateColumnFT(regionSparse,
00445 regionSparse2);
00446 collectStatistics_ = false;
00447 return returnValue;
00448 } else {
00449 #ifdef CHECK_NETWORK
00450 CoinIndexedVector * save = new CoinIndexedVector(*regionSparse2);
00451 int returnCode = CoinFactorization::updateColumnFT(regionSparse,
00452 regionSparse2);
00453 networkBasis_->updateColumn(regionSparse,save);
00454 int i;
00455 double * array = regionSparse2->denseVector();
00456 double * array2 = save->denseVector();
00457 for (i=0;i<numberRows_;i++) {
00458 double value1 = array[i];
00459 double value2 = array2[i];
00460 assert (value1==value2);
00461 }
00462 delete save;
00463 return returnCode;
00464 #else
00465 networkBasis_->updateColumn(regionSparse,regionSparse2,-1);
00466 return 1;
00467 #endif
00468 }
00469 }
00470
00471
00472
00473 int
00474 ClpFactorization::updateColumn ( CoinIndexedVector * regionSparse,
00475 CoinIndexedVector * regionSparse2,
00476 bool noPermute) const
00477 {
00478 #ifdef CLP_DEBUG
00479 if (!noPermute)
00480 regionSparse->checkClear();
00481 #endif
00482 if (!networkBasis_) {
00483 collectStatistics_ = true;
00484 int returnValue= CoinFactorization::updateColumn(regionSparse,
00485 regionSparse2,
00486 noPermute);
00487 collectStatistics_ = false;
00488 return returnValue;
00489 } else {
00490 #ifdef CHECK_NETWORK
00491 CoinIndexedVector * save = new CoinIndexedVector(*regionSparse2);
00492 int returnCode = CoinFactorization::updateColumn(regionSparse,
00493 regionSparse2,
00494 noPermute);
00495 networkBasis_->updateColumn(regionSparse,save);
00496 int i;
00497 double * array = regionSparse2->denseVector();
00498 double * array2 = save->denseVector();
00499 for (i=0;i<numberRows_;i++) {
00500 double value1 = array[i];
00501 double value2 = array2[i];
00502 assert (value1==value2);
00503 }
00504 delete save;
00505 return returnCode;
00506 #else
00507 networkBasis_->updateColumn(regionSparse,regionSparse2,-1);
00508 return 1;
00509 #endif
00510 }
00511 }
00512
00513
00514 int
00515 ClpFactorization::updateColumnTranspose ( CoinIndexedVector * regionSparse,
00516 CoinIndexedVector * regionSparse2) const
00517 {
00518 if (!networkBasis_) {
00519 collectStatistics_ = true;
00520 return CoinFactorization::updateColumnTranspose(regionSparse,
00521 regionSparse2);
00522 collectStatistics_ = false;
00523 } else {
00524 #ifdef CHECK_NETWORK
00525 CoinIndexedVector * save = new CoinIndexedVector(*regionSparse2);
00526 int returnCode = CoinFactorization::updateColumnTranspose(regionSparse,
00527 regionSparse2);
00528 networkBasis_->updateColumnTranspose(regionSparse,save);
00529 int i;
00530 double * array = regionSparse2->denseVector();
00531 double * array2 = save->denseVector();
00532 for (i=0;i<numberRows_;i++) {
00533 double value1 = array[i];
00534 double value2 = array2[i];
00535 assert (value1==value2);
00536 }
00537 delete save;
00538 return returnCode;
00539 #else
00540 return networkBasis_->updateColumnTranspose(regionSparse,regionSparse2);
00541 #endif
00542 }
00543 }
00544
00545 void
00546 ClpFactorization::goSparse()
00547 {
00548 if (!networkBasis_)
00549 CoinFactorization::goSparse();
00550 }
00551
00552 void
00553 ClpFactorization::cleanUp()
00554 {
00555 delete networkBasis_;
00556 networkBasis_=NULL;
00557 resetStatistics();
00558 }
00560 bool
00561 ClpFactorization::needToReorder() const
00562 {
00563 #ifdef CHECK_NETWORK
00564 return true;
00565 #endif
00566 if (!networkBasis_)
00567 return true;
00568 else
00569 return false;
00570 }